From 266222ebf44337034e36711bee8c146e0f0874da Mon Sep 17 00:00:00 2001 From: Shadi Date: Fri, 29 Sep 2023 11:10:00 -0500 Subject: [PATCH] chore: use BiomeJS to format our code (#3496) * chore: add biomejs and config to monorepo * chore: vscode settings for biomejs * chore: update ci and package.json scripts * chore: update internal docs * chore: format everything with biome * chore: remove unused tools script * chore: fix usage of reserved word * chore: fix import order with biomejs * chore: adjust formatter to use double quotes in JS * chore: format code with double quotes * chore: prettier should use double quotes too * chore: fix biome.json * chore: remove faiss_index files --- .changeset/config.json | 2 +- .../changesets-that-need-core-check.spec.ts | 76 +- .../missing-changesets-check.spec.ts | 146 +- .../missing-upgrade-guide-check.spec.ts | 32 +- .danger/__tests__/package-json-check.spec.ts | 52 +- .danger/__tests__/pin-external-deps.spec.ts | 54 +- .danger/__tests__/utils.spec.ts | 354 +- .../__tests__/website-page-vrt-check.spec.ts | 20 +- .danger/changesets-that-need-core-check.ts | 22 +- .danger/missing-changesets-check.ts | 22 +- .danger/missing-upgrade-guide-check.ts | 12 +- .danger/package-json-check.ts | 10 +- .danger/pin-external-deps.ts | 24 +- .danger/utils.ts | 36 +- .danger/website-page-vrt-check.ts | 2 +- .eslint/resolver.js | 18 +- .eslintrc.core.js | 4 +- .eslintrc.js | 250 +- .eslintrc.repo.js | 26 +- .github/workflows/on_pull_request.yml | 13 +- .jest/globals/TestTheme.js | 1284 +- .jest/setupFilesAfterEnv.js | 4 +- .prettierignore | 11 + .prettierrc.js | 10 +- .storybook/RenderPerformanceProfiler.tsx | 20 +- .../addons/google-analytics/register.js | 16 +- .storybook/main.ts | 52 +- .storybook/next.tsx | 4 +- .storybook/preview.tsx | 128 +- .storybook/test-runner.js | 14 +- .vscode/extensions.json | 1 + .vscode/settings.json | 18 + apps/vs-code-intellisense/src/extension.ts | 34 +- apps/vs-code-intellisense/src/test/runTest.ts | 12 +- .../src/test/suite/extension.test.ts | 122 +- .../src/test/suite/index.ts | 12 +- .../test/suite/utils/get-theme-tokens.test.ts | 22 +- .../suite/utils/is-color-category.test.ts | 32 +- .../src/test/suite/utils/rem-to-px.test.ts | 26 +- .../src/tokens/dark-theme-tokens.ts | 2 +- .../src/tokens/default-theme-tokens.ts | 2 +- .../src/tokens/evergreen-theme-tokens.ts | 2 +- apps/vs-code-intellisense/src/tokens/index.ts | 14 +- .../src/tokens/paste-token-attributes.ts | 80 +- .../src/tokens/sendgrid-theme-tokens.ts | 2 +- .../src/tokens/twilio-dark-theme-tokens.ts | 2 +- .../src/tokens/twilio-theme-tokens.ts | 2 +- apps/vs-code-intellisense/src/types/index.ts | 10 +- .../src/types/paste-token.ts | 4 +- apps/vs-code-intellisense/src/types/themes.ts | 2 +- .../src/types/token-category.ts | 30 +- .../src/types/token-map.ts | 2 +- .../src/types/token-type.ts | 2 +- .../src/utils/get-color-preview.ts | 6 +- .../src/utils/get-theme-setting.ts | 6 +- .../src/utils/get-theme-tokens.ts | 16 +- apps/vs-code-intellisense/src/utils/index.ts | 10 +- .../src/utils/is-color-category.ts | 4 +- .../src/utils/rem-to-px.ts | 4 +- babel.config.js | 22 +- biome.json | 70 + commitlint.config.js | 2 +- cypress.config.ts | 22 +- cypress/fixtures/example.json | 2 +- .../e2e/components/alert-dialog.spec.ts | 8 +- .../e2e/components/overview-page.spec.ts | 8 +- .../e2e/patterns/button-vs-anchor.spec.ts | 8 +- .../e2e/patterns/overview-page.spec.ts | 8 +- .../integration/e2e/primitives/box.spec.ts | 8 +- .../e2e/primitives/overview-page.spec.ts | 8 +- cypress/integration/e2e/roadmap-page.spec.ts | 38 +- .../filter-group-examples/index.spec.ts | 226 +- .../integration/landing-page/index.spec.ts | 8 +- .../integration/link-checker/index.spec.ts | 20 +- cypress/integration/opengraph/index.spec.ts | 14 +- .../sidebar-navigation/index.spec.ts | 58 +- cypress/integration/site-search/index.spec.ts | 22 +- .../integration/sitemap-vrt/batch2.spec.ts | 6 +- .../integration/sitemap-vrt/batch3.spec.ts | 6 +- .../integration/sitemap-vrt/batch4.spec.ts | 6 +- .../integration/sitemap-vrt/batch5.spec.ts | 6 +- cypress/integration/sitemap-vrt/constants.ts | 352 +- cypress/integration/sitemap-vrt/index.spec.ts | 6 +- cypress/integration/token-list/index.spec.ts | 64 +- cypress/integration/word-list/index.spec.ts | 28 +- cypress/support/commands/index.ts | 2 +- cypress/support/commands/parent-commands.ts | 115 +- cypress/support/e2e.ts | 6 +- cypress/support/utils/vrt.ts | 4 +- dangerfile.ts | 16 +- internal-docs/engineering/ci.md | 9 +- internal-docs/engineering/technologies.md | 2 +- internal-docs/engineering/testing.md | 8 +- jest.config.js | 58 +- package.json | 21 +- .../tools/__tests__/tools.spec.ts | 56 +- .../tools/create-package-mappings.ts | 12 +- .../tools/generatePackageExportsMap.ts | 8 +- .../__tests__/barreled-to-unbarreled.spec.tsx | 4 +- .../transforms/barreled-to-unbarreled.js | 6 +- .../colorContrastPairingUtils.spec.ts | 218 +- .../__tests__/themeContrast.spec.ts | 116 +- packages/paste-color-contrast-utils/build.js | 4 +- .../paste-color-contrast-utils/src/index.ts | 2 +- .../paste-color-contrast-utils/src/utils.ts | 36 +- .../__tests__/AccountSwitcher.spec.tsx | 84 +- .../components/account-switcher/build.js | 4 +- .../account-switcher/src/AccountSwitcher.tsx | 14 +- .../src/AccountSwitcherBadge.tsx | 16 +- .../src/AccountSwitcherGroup.tsx | 14 +- .../src/AccountSwitcherItem.tsx | 14 +- .../src/AccountSwitcherItemRadio.tsx | 14 +- .../src/AccountSwitcherSeparator.tsx | 14 +- .../components/account-switcher/src/index.tsx | 14 +- .../src/useAccountSwitcher.ts | 2 +- .../AccountSwitcher.customization.stories.tsx | 70 +- .../stories/AccountSwitcher.stories.tsx | 24 +- .../__tests__/customization.spec.tsx | 92 +- .../alert-dialog/__tests__/index.spec.tsx | 72 +- .../components/alert-dialog/build.js | 4 +- .../alert-dialog/src/AlertDialogBody.tsx | 16 +- .../alert-dialog/src/AlertDialogContent.tsx | 14 +- .../alert-dialog/src/AlertDialogFooter.tsx | 24 +- .../alert-dialog/src/AlertDialogHeader.tsx | 18 +- .../components/alert-dialog/src/index.tsx | 42 +- .../alert-dialog/stories/index.stories.tsx | 100 +- .../components/alert/__tests__/index.spec.tsx | 184 +- packages/paste-core/components/alert/build.js | 4 +- .../paste-core/components/alert/src/index.tsx | 70 +- .../alert/stories/index.stories.tsx | 70 +- .../anchor/__tests__/anchor.test.tsx | 200 +- .../paste-core/components/anchor/build.js | 4 +- .../components/anchor/src/Anchor.tsx | 36 +- .../components/anchor/src/DefaultAnchor.tsx | 24 +- .../components/anchor/src/InverseAnchor.tsx | 24 +- .../components/anchor/src/index.tsx | 4 +- .../paste-core/components/anchor/src/types.ts | 14 +- .../anchor/stories/index.stories.tsx | 60 +- .../avatar/__tests__/avatar.test.tsx | 279 +- .../paste-core/components/avatar/build.js | 4 +- .../components/avatar/src/Avatar.tsx | 75 +- .../components/avatar/src/AvatarGroup.tsx | 18 +- .../components/avatar/src/index.tsx | 6 +- .../paste-core/components/avatar/src/types.ts | 20 +- .../paste-core/components/avatar/src/utils.ts | 168 +- .../avatar/stories/index.stories.tsx | 40 +- .../badge/__tests__/customization.spec.tsx | 48 +- .../components/badge/__tests__/index.spec.tsx | 202 +- packages/paste-core/components/badge/build.js | 4 +- .../paste-core/components/badge/src/Badge.tsx | 36 +- .../components/badge/src/constants.ts | 28 +- .../paste-core/components/badge/src/hooks.tsx | 12 +- .../paste-core/components/badge/src/index.tsx | 10 +- .../paste-core/components/badge/src/styles.ts | 172 +- .../paste-core/components/badge/src/types.ts | 24 +- .../badge/stories/customization.stories.tsx | 82 +- .../badge/stories/index.stories.tsx | 36 +- .../__tests__/base-radio-checkbox.test.tsx | 92 +- .../components/base-radio-checkbox/build.js | 4 +- .../src/BaseRadioCheckbox.tsx | 124 +- .../base-radio-checkbox/src/index.tsx | 2 +- .../breadcrumb/__tests__/breadcrumb.spec.tsx | 236 +- .../paste-core/components/breadcrumb/build.js | 4 +- .../components/breadcrumb/src/index.tsx | 52 +- .../breadcrumb/stories/index.stories.tsx | 68 +- .../button-group/__tests__/index.spec.tsx | 64 +- .../components/button-group/build.js | 4 +- .../button-group/src/ButtonGroup.tsx | 48 +- .../components/button-group/src/index.tsx | 2 +- .../button-group/stories/index.stories.tsx | 32 +- .../button/__tests__/button.test.tsx | 444 +- .../button/__tests__/customization.test.tsx | 100 +- .../paste-core/components/button/build.js | 4 +- .../components/button/src/Button.tsx | 152 +- .../button/src/DestructiveButton.tsx | 56 +- .../button/src/DestructiveIconButton.tsx | 34 +- .../button/src/DestructiveLinkButton.tsx | 54 +- .../button/src/DestructiveSecondaryButton.tsx | 56 +- .../components/button/src/InverseButton.tsx | 56 +- .../button/src/InverseLinkButton.tsx | 44 +- .../components/button/src/LinkButton.tsx | 42 +- .../components/button/src/PrimaryButton.tsx | 56 +- .../button/src/PrimaryIconButton.tsx | 34 +- .../components/button/src/ResetButton.tsx | 32 +- .../components/button/src/SecondaryButton.tsx | 68 +- .../button/src/SecondaryIconButton.tsx | 42 +- .../components/button/src/index.tsx | 6 +- .../components/button/src/styles.ts | 270 +- .../paste-core/components/button/src/types.ts | 56 +- .../button/stories/customization.stories.tsx | 76 +- .../button/stories/index.stories.tsx | 98 +- .../callout/__tests__/customization.spec.tsx | 182 +- .../callout/__tests__/index.spec.tsx | 140 +- .../paste-core/components/callout/build.js | 4 +- .../components/callout/src/Callout.tsx | 72 +- .../components/callout/src/CalloutHeading.tsx | 18 +- .../components/callout/src/CalloutList.tsx | 30 +- .../components/callout/src/CalloutText.tsx | 16 +- .../components/callout/src/index.tsx | 8 +- .../callout/stories/customization.stories.tsx | 46 +- .../callout/stories/index.stories.tsx | 12 +- .../components/card/__test__/card.test.tsx | 80 +- packages/paste-core/components/card/build.js | 4 +- .../paste-core/components/card/src/index.tsx | 31 +- .../components/card/stories/index.stories.tsx | 36 +- .../__tests__/customization.spec.tsx | 70 +- .../chat-composer/__tests__/index.spec.tsx | 68 +- .../components/chat-composer/build.js | 4 +- .../chat-composer/src/AutoLinkPlugin.tsx | 6 +- .../chat-composer/src/ChatComposer.tsx | 72 +- .../chat-composer/src/PlaceholderWrapper.tsx | 16 +- .../components/chat-composer/src/helpers.ts | 4 +- .../components/chat-composer/src/index.tsx | 2 +- .../components/chat-composer/src/styles.ts | 2 +- .../stories/ConversationsUIKit/helpers.tsx | 34 +- .../ConversationsUIKit/index.stories.tsx | 68 +- .../stories/customization.stories.tsx | 28 +- .../chat-composer/stories/index.stories.tsx | 46 +- .../__tests__/ChatAttachment.spec.tsx | 196 +- .../chat-log/__tests__/ChatBookend.spec.tsx | 84 +- .../chat-log/__tests__/ChatBubble.spec.tsx | 90 +- .../chat-log/__tests__/ChatEvent.spec.tsx | 64 +- .../chat-log/__tests__/ChatLogger.spec.tsx | 26 +- .../chat-log/__tests__/ChatMessage.spec.tsx | 88 +- .../__tests__/ChatMessageMeta.spec.tsx | 162 +- .../chat-log/__tests__/chatLog.spec.tsx | 60 +- .../chat-log/__tests__/useChatLogger.spec.tsx | 42 +- .../paste-core/components/chat-log/build.js | 4 +- .../chat-log/src/ChatAttachment.tsx | 24 +- .../src/ChatAttachmentDescription.tsx | 20 +- .../chat-log/src/ChatAttachmentLink.tsx | 24 +- .../components/chat-log/src/ChatBookend.tsx | 16 +- .../chat-log/src/ChatBookendItem.tsx | 16 +- .../components/chat-log/src/ChatBubble.tsx | 28 +- .../components/chat-log/src/ChatEvent.tsx | 16 +- .../components/chat-log/src/ChatLog.tsx | 14 +- .../components/chat-log/src/ChatLogger.tsx | 32 +- .../components/chat-log/src/ChatMessage.tsx | 26 +- .../chat-log/src/ChatMessageMeta.tsx | 22 +- .../chat-log/src/ChatMessageMetaItem.tsx | 14 +- .../chat-log/src/ComposerAttachmentCard.tsx | 38 +- .../chat-log/src/MessageVariantContext.tsx | 6 +- .../components/chat-log/src/index.tsx | 30 +- .../components/chat-log/src/useChatLogger.ts | 12 +- .../components/ChatAttachment.stories.tsx | 24 +- .../components/ChatBookend.stories.tsx | 8 +- .../stories/components/ChatBubble.stories.tsx | 8 +- .../stories/components/ChatEvent.stories.tsx | 8 +- .../components/ChatMessageMeta.stories.tsx | 10 +- .../components/UseChatLogger.stories.tsx | 48 +- .../stories/customization.stories.tsx | 90 +- .../chat-log/stories/index.stories.tsx | 40 +- .../checkbox/__tests__/checkbox.test.tsx | 348 +- .../__tests__/checkboxdisclaimer.test.tsx | 92 +- .../paste-core/components/checkbox/build.js | 4 +- .../components/checkbox/src/Checkbox.tsx | 94 +- .../checkbox/src/CheckboxContext.tsx | 4 +- .../checkbox/src/CheckboxDisclaimer.tsx | 20 +- .../components/checkbox/src/CheckboxGroup.tsx | 28 +- .../components/checkbox/src/index.tsx | 6 +- .../checkbox/stories/checkbox.stories.tsx | 74 +- .../stories/customization.stories.tsx | 58 +- .../__tests__/customization.spec.tsx | 213 +- .../code-block/__tests__/index.spec.tsx | 123 +- .../paste-core/components/code-block/build.js | 4 +- .../components/code-block/src/CodeBlock.tsx | 54 +- .../code-block/src/CodeBlockHeader.tsx | 18 +- .../code-block/src/CodeBlockTab.tsx | 16 +- .../code-block/src/CodeBlockTabList.tsx | 20 +- .../code-block/src/CodeBlockTabPanel.tsx | 16 +- .../code-block/src/CodeBlockTheme.ts | 226 +- .../code-block/src/CodeBlockWrapper.tsx | 18 +- .../components/code-block/src/CopyButton.tsx | 28 +- .../code-block/src/ExternalLinkButton.tsx | 20 +- .../components/code-block/src/index.tsx | 12 +- .../stories/customization.stories.tsx | 81 +- .../code-block/stories/index.stories.tsx | 21 +- .../combobox/__tests__/Combobox.spec.tsx | 310 +- .../combobox/__tests__/GrowingInput.spec.tsx | 24 +- .../__tests__/MultiselectCombobox.spec.tsx | 226 +- .../__tests__/combobox-customization.spec.tsx | 194 +- ...ultiselect-combobox-customization.spec.tsx | 218 +- .../__tests__/virtualization.spec.tsx | 154 +- .../paste-core/components/combobox/build.js | 4 +- .../components/combobox/src/ComboboxItems.tsx | 48 +- .../combobox/src/ListboxPositioner.tsx | 20 +- .../components/combobox/src/helpers.tsx | 46 +- .../components/combobox/src/index.tsx | 18 +- .../combobox/src/multiselect/GrowingInput.tsx | 38 +- .../src/multiselect/MultiselectCombobox.tsx | 94 +- .../src/multiselect/extractPropsFromState.tsx | 14 +- .../combobox/src/singleselect/Combobox.tsx | 82 +- .../singleselect/extractPropsFromState.tsx | 56 +- .../src/styles/ComboboxInputSelect.tsx | 16 +- .../src/styles/ComboboxInputWrapper.tsx | 12 +- .../combobox/src/styles/ComboboxListbox.tsx | 16 +- .../src/styles/ComboboxListboxGroup.tsx | 22 +- .../src/styles/ComboboxListboxOption.tsx | 66 +- .../components/combobox/src/types.ts | 70 +- .../Combobox-customization.stories.tsx | 108 +- .../combobox/stories/Combobox.stories.tsx | 312 +- .../combobox/stories/GrowingInput.stories.tsx | 18 +- ...tiselectCombobox-customization.stories.tsx | 120 +- .../stories/MultiselectCombobox.stories.tsx | 210 +- .../__tests__/cell-management.spec.ts | 44 +- .../__tests__/customization.spec.tsx | 126 +- .../data-grid/__tests__/index.spec.tsx | 248 +- .../__tests__/reakit-hasFocus.spec.tsx | 30 +- .../paste-core/components/data-grid/build.js | 4 +- .../components/data-grid/src/DataGrid.tsx | 36 +- .../components/data-grid/src/DataGridBody.tsx | 12 +- .../components/data-grid/src/DataGridCell.tsx | 38 +- .../data-grid/src/DataGridContext.tsx | 4 +- .../components/data-grid/src/DataGridFoot.tsx | 12 +- .../components/data-grid/src/DataGridHead.tsx | 12 +- .../data-grid/src/DataGridHeader.tsx | 10 +- .../data-grid/src/DataGridHeaderSort.tsx | 36 +- .../components/data-grid/src/DataGridRow.tsx | 18 +- .../components/data-grid/src/index.tsx | 16 +- .../components/data-grid/src/table/Td.tsx | 20 +- .../components/data-grid/src/table/Th.tsx | 20 +- .../components/data-grid/src/table/Tr.tsx | 28 +- .../data-grid/src/utils/cell-management.ts | 4 +- .../components/data-grid/src/utils/index.ts | 4 +- .../data-grid/src/utils/reakit/index.ts | 6 +- .../src/utils/reakit/reakit-ensureFocus.ts | 8 +- .../reakit/reakit-getActiveElement-modded.ts | 4 +- .../src/utils/reakit/reakit-hasFocus.ts | 4 +- .../src/utils/reakit/reakit-matches.ts | 4 +- .../utils/reakit/reakit-tabbable-modded.ts | 6 +- .../stories/components/ColumnSpanDataGrid.tsx | 18 +- .../components/ComposableCellsDataGrid.tsx | 18 +- .../components/CustomizableDataGrid.tsx | 46 +- .../stories/components/DataGridLayouts.tsx | 28 +- .../stories/components/I18nDataGrid.tsx | 30 +- .../components/KitchenSinkDataGrid.tsx | 54 +- .../stories/components/LoadingDataGrid.tsx | 16 +- .../stories/components/PaginatedDataGrid.tsx | 28 +- .../stories/components/PlainDataGrid.tsx | 32 +- .../components/SelectableRowsDataGrid.tsx | 18 +- .../components/SortableColumnsDataGrid.tsx | 30 +- .../components/StickyHeaderDataGrid.tsx | 18 +- .../data-grid/stories/components/constants.ts | 258 +- .../stories/customization.stories.tsx | 4 +- .../data-grid/stories/index.stories.tsx | 24 +- .../date-picker/__tests__/index.spec.tsx | 176 +- .../components/date-picker/build.js | 4 +- .../components/date-picker/src/DatePicker.tsx | 14 +- .../components/date-picker/src/index.tsx | 4 +- .../components/date-picker/src/utils.ts | 6 +- .../date-picker/stories/index.stories.tsx | 118 +- .../description-list/__tests__/index.spec.tsx | 128 +- .../components/description-list/build.js | 4 +- .../description-list/src/DescriptionList.tsx | 18 +- .../src/DescriptionListDetails.tsx | 18 +- .../src/DescriptionListSet.tsx | 38 +- .../src/DescriptionListTerm.tsx | 18 +- .../components/description-list/src/index.tsx | 8 +- .../stories/index.stories.tsx | 26 +- .../detail-text/__tests__/index.spec.tsx | 46 +- .../components/detail-text/build.js | 4 +- .../components/detail-text/src/index.tsx | 20 +- .../detail-text/stories/index.stories.tsx | 18 +- .../disclosure/__tests__/disclosure.test.tsx | 172 +- .../paste-core/components/disclosure/build.js | 4 +- .../components/disclosure/src/Disclosure.tsx | 28 +- .../disclosure/src/DisclosureContent.tsx | 46 +- .../disclosure/src/DisclosureContext.tsx | 8 +- .../disclosure/src/DisclosureHeading.tsx | 104 +- .../components/disclosure/src/constants.ts | 12 +- .../components/disclosure/src/index.tsx | 8 +- .../components/disclosure/src/types.ts | 9 +- .../disclosure/stories/index.stories.tsx | 95 +- .../display-heading/__tests__/index.spec.tsx | 68 +- .../components/display-heading/build.js | 4 +- .../components/display-heading/src/index.tsx | 58 +- .../display-heading/stories/index.stories.tsx | 12 +- .../__tests__/index.spec.tsx | 116 +- .../components/display-pill-group/build.js | 4 +- .../display-pill-group/src/DisplayPill.tsx | 32 +- .../src/DisplayPillGroup.tsx | 16 +- .../display-pill-group/src/index.tsx | 4 +- .../stories/customization.stories.tsx | 30 +- .../stories/index.stories.tsx | 22 +- .../components/editable-code-block/build.js | 4 +- .../src/EditableCodeBlock.tsx | 76 +- .../src/EditableCodeBlockHeader.tsx | 16 +- .../src/EditableCodeBlockWrapper.tsx | 24 +- .../editable-code-block/src/index.tsx | 6 +- .../stories/index.stories.tsx | 28 +- .../file-picker/__tests__/index.spec.tsx | 88 +- .../components/file-picker/build.js | 4 +- .../components/file-picker/src/FilePicker.tsx | 54 +- .../file-picker/src/FilePickerButton.tsx | 16 +- .../components/file-picker/src/index.tsx | 4 +- .../file-picker/stories/index.stories.tsx | 34 +- .../__tests__/customization.spec.tsx | 260 +- .../file-uploader/__tests__/index.spec.tsx | 116 +- .../components/file-uploader/build.js | 4 +- .../file-uploader/src/FileUploader.tsx | 22 +- .../file-uploader/src/FileUploaderContext.tsx | 2 +- .../src/FileUploaderDropzone.tsx | 68 +- .../src/FileUploaderDropzoneText.tsx | 20 +- .../src/FileUploaderErrorText.tsx | 24 +- .../src/FileUploaderHelpText.tsx | 24 +- .../file-uploader/src/FileUploaderItem.tsx | 74 +- .../src/FileUploaderItemContext.tsx | 6 +- .../src/FileUploaderItemDescription.tsx | 32 +- .../src/FileUploaderItemTitle.tsx | 16 +- .../src/FileUploaderItemsList.tsx | 16 +- .../file-uploader/src/FileUploaderLabel.tsx | 22 +- .../components/file-uploader/src/index.tsx | 20 +- .../components/file-uploader/src/utils.ts | 6 +- .../file-uploader/stories/index.stories.tsx | 114 +- .../form-pill-group/__tests__/index.spec.tsx | 160 +- .../components/form-pill-group/build.js | 4 +- .../form-pill-group/src/FormPill.styles.ts | 158 +- .../form-pill-group/src/FormPill.tsx | 38 +- .../form-pill-group/src/FormPillButton.tsx | 34 +- .../form-pill-group/src/FormPillGroup.tsx | 37 +- .../form-pill-group/src/PillCloseIcon.tsx | 22 +- .../components/form-pill-group/src/index.tsx | 6 +- .../components/form-pill-group/src/types.ts | 4 +- .../form-pill-group/src/useFormPillState.tsx | 10 +- .../stories/customization.stories.tsx | 28 +- .../form-pill-group/stories/index.stories.tsx | 36 +- .../components/form/__tests__/index.spec.tsx | 138 +- packages/paste-core/components/form/build.js | 4 +- .../paste-core/components/form/src/Form.tsx | 18 +- .../components/form/src/FormActions.tsx | 16 +- .../components/form/src/FormControl.tsx | 16 +- .../form/src/FormControlTwoColumn.tsx | 16 +- .../components/form/src/FormSection.tsx | 26 +- .../form/src/FormSectionContext.tsx | 2 +- .../form/src/FormSectionDescription.tsx | 20 +- .../form/src/FormSectionHeading.tsx | 22 +- .../paste-core/components/form/src/index.tsx | 14 +- .../components/form/stories/index.stories.tsx | 288 +- .../heading/__tests__/heading.test.tsx | 202 +- .../paste-core/components/heading/build.js | 4 +- .../components/heading/src/index.tsx | 92 +- .../components/heading/src/types.ts | 12 +- .../heading/stories/index.stories.tsx | 68 +- .../help-text/__tests__/helptext.test.tsx | 64 +- .../paste-core/components/help-text/build.js | 4 +- .../components/help-text/src/HelpText.tsx | 56 +- .../components/help-text/src/index.tsx | 2 +- .../help-text/stories/input.stories.tsx | 46 +- .../__tests__/index.spec.tsx | 120 +- .../components/in-page-navigation/build.js | 4 +- .../src/InPageNavigation.tsx | 36 +- .../src/InPageNavigationContext.tsx | 8 +- .../src/InPageNavigationItem.tsx | 104 +- .../in-page-navigation/src/index.tsx | 4 +- .../in-page-navigation/src/types.ts | 2 +- .../stories/index.stories.tsx | 24 +- .../inline-code/__tests__/index.spec.tsx | 52 +- .../components/inline-code/build.js | 4 +- .../components/inline-code/src/index.tsx | 20 +- .../inline-code/stories/index.stories.tsx | 34 +- .../__tests__/inlineControlGroup.test.tsx | 132 +- .../components/inline-control-group/build.js | 4 +- .../src/InlineControlGroup.tsx | 48 +- .../inline-control-group/src/index.tsx | 2 +- .../stories/inline-control-group.stories.tsx | 52 +- .../input-box/__tests__/input-box.test.tsx | 64 +- .../__tests__/input-chevron-wrapper.test.tsx | 68 +- .../input-box/__tests__/prefix.test.tsx | 64 +- .../input-box/__tests__/suffix.test.tsx | 64 +- .../paste-core/components/input-box/build.js | 4 +- .../src/FauxInput/DefaultFauxInput.tsx | 52 +- .../src/FauxInput/InverseFauxInput.tsx | 48 +- .../input-box/src/FauxInput/index.tsx | 16 +- .../components/input-box/src/InputBox.tsx | 30 +- .../input-box/src/InputBoxContext.tsx | 6 +- .../input-box/src/InputChevronWrapper.tsx | 60 +- .../components/input-box/src/Prefix.tsx | 40 +- .../components/input-box/src/Suffix.tsx | 40 +- .../components/input-box/src/index.tsx | 10 +- .../components/input-box/src/types.ts | 26 +- .../input-box/stories/inputbox.stories.tsx | 32 +- .../components/input/__tests__/input.test.tsx | 380 +- packages/paste-core/components/input/build.js | 4 +- .../components/input/src/DecrementButton.tsx | 22 +- .../components/input/src/IncrementButton.tsx | 22 +- .../paste-core/components/input/src/Input.tsx | 92 +- .../paste-core/components/input/src/index.tsx | 2 +- .../paste-core/components/input/src/utils.ts | 4 +- .../input/stories/input.stories.tsx | 480 +- .../components/label/__tests__/label.test.tsx | 88 +- packages/paste-core/components/label/build.js | 4 +- .../paste-core/components/label/src/Label.tsx | 68 +- .../components/label/src/RequiredDot.tsx | 16 +- .../paste-core/components/label/src/index.tsx | 4 +- .../label/stories/label.stories.tsx | 38 +- .../components/list/__tests__/index.spec.tsx | 232 +- packages/paste-core/components/list/build.js | 4 +- .../paste-core/components/list/src/List.tsx | 14 +- .../components/list/src/ListItem.tsx | 48 +- .../components/list/src/OrderedList.tsx | 16 +- .../components/list/src/UnorderedList.tsx | 16 +- .../paste-core/components/list/src/index.tsx | 10 +- .../paste-core/components/list/src/types.ts | 16 +- .../components/list/stories/index.stories.tsx | 70 +- .../menu/__tests__/customization.spec.tsx | 292 +- .../components/menu/__tests__/index.spec.tsx | 188 +- .../menu-badge-customization.spec.tsx | 52 +- packages/paste-core/components/menu/build.js | 4 +- .../paste-core/components/menu/src/Menu.tsx | 22 +- .../components/menu/src/MenuBadge.tsx | 40 +- .../components/menu/src/MenuButton.tsx | 30 +- .../components/menu/src/MenuGroup.tsx | 24 +- .../components/menu/src/MenuItem.styles.tsx | 70 +- .../components/menu/src/MenuItem.tsx | 20 +- .../components/menu/src/MenuItemCheckbox.tsx | 20 +- .../components/menu/src/MenuItemRadio.tsx | 20 +- .../components/menu/src/MenuSeparator.tsx | 20 +- .../components/menu/src/SubMenuButton.tsx | 24 +- .../components/menu/src/constants.ts | 8 +- .../paste-core/components/menu/src/index.tsx | 24 +- .../paste-core/components/menu/src/types.ts | 22 +- .../components/menu/src/useMenuState.ts | 4 +- .../menu/stories/customization.stories.tsx | 182 +- .../components/menu/stories/index.stories.tsx | 54 +- .../menu-badge-customization.stories.tsx | 82 +- .../menu/stories/menu-badge.stories.tsx | 18 +- .../stories/menu-checkable-items.stories.tsx | 62 +- .../components/meter/__tests__/index.spec.tsx | 96 +- packages/paste-core/components/meter/build.js | 4 +- .../paste-core/components/meter/src/Meter.tsx | 40 +- .../components/meter/src/MeterLabel.tsx | 22 +- .../components/meter/src/constants.ts | 2 +- .../paste-core/components/meter/src/index.tsx | 4 +- .../meter/stories/index.stories.tsx | 68 +- .../__tests__/customization.spec.tsx | 192 +- .../__tests__/index.spec.tsx | 54 +- .../components/minimizable-dialog/build.js | 4 +- .../src/MinimizableDialog.tsx | 40 +- .../src/MinimizableDialogButton.tsx | 20 +- .../src/MinimizableDialogContainer.tsx | 22 +- .../src/MinimizableDialogContent.tsx | 26 +- .../src/MinimizableDialogContext.tsx | 6 +- .../src/MinimizableDialogHeader.tsx | 40 +- .../src/StyledMinimizableDialog.tsx | 10 +- .../minimizable-dialog/src/index.tsx | 10 +- .../stories/customization.stories.tsx | 50 +- .../stories/index.stories.tsx | 42 +- .../modal/__tests__/customization.spec.tsx | 136 +- .../components/modal/__tests__/index.spec.tsx | 90 +- packages/paste-core/components/modal/build.js | 4 +- .../paste-core/components/modal/src/Modal.tsx | 98 +- .../components/modal/src/ModalBody.tsx | 20 +- .../components/modal/src/ModalContext.tsx | 4 +- .../components/modal/src/ModalFooter.tsx | 20 +- .../modal/src/ModalFooterActions.tsx | 24 +- .../components/modal/src/ModalHeader.tsx | 32 +- .../components/modal/src/ModalHeading.tsx | 22 +- .../paste-core/components/modal/src/index.tsx | 16 +- .../components/modal/src/styles.tsx | 28 +- .../modal/stories/customization.stories.tsx | 114 +- .../modal/stories/index.stories.tsx | 130 +- .../__tests__/customization.spec.tsx | 232 +- .../pagination/__tests__/index.spec.tsx | 148 +- .../paste-core/components/pagination/build.js | 4 +- .../components/pagination/src/Pagination.tsx | 14 +- .../PaginationArrow/PaginationArrowButton.tsx | 38 +- .../PaginationArrowIconWrapper.tsx | 14 +- .../PaginationArrow/PaginationBackArrow.tsx | 26 +- .../PaginationForwardArrow.tsx | 26 +- .../pagination/src/PaginationArrow/index.tsx | 44 +- .../pagination/src/PaginationEllipsis.tsx | 14 +- .../pagination/src/PaginationItems.tsx | 22 +- .../pagination/src/PaginationLabel.tsx | 14 +- .../pagination/src/PaginationNumber.tsx | 48 +- .../pagination/src/PaginationNumbers.tsx | 24 +- .../components/pagination/src/index.tsx | 16 +- .../components/pagination/src/styles.ts | 14 +- .../components/pagination/src/types.ts | 24 +- .../components/pagination/src/utils.ts | 12 +- .../stories/customization.stories.tsx | 82 +- .../pagination/stories/index.stories.tsx | 56 +- .../paragraph/__tests__/paragraph.test.tsx | 60 +- .../paste-core/components/paragraph/build.js | 4 +- .../components/paragraph/src/index.tsx | 22 +- .../paragraph/stories/index.stories.tsx | 28 +- .../popover/__tests__/index.spec.tsx | 188 +- .../paste-core/components/popover/build.js | 4 +- .../components/popover/src/Popover.tsx | 42 +- .../components/popover/src/PopoverArrow.tsx | 12 +- .../popover/src/PopoverBadgeButton.tsx | 24 +- .../components/popover/src/PopoverButton.tsx | 18 +- .../popover/src/PopoverContainer.tsx | 20 +- .../components/popover/src/PopoverContext.tsx | 6 +- .../components/popover/src/index.tsx | 10 +- .../components/popover/src/types.ts | 16 +- .../popover/stories/index.stories.tsx | 54 +- .../__tests__/ProductSwitcher.spec.tsx | 72 +- .../components/product-switcher/build.js | 4 +- .../product-switcher/src/ProductSwitcher.tsx | 14 +- .../src/ProductSwitcherButton.tsx | 20 +- .../src/ProductSwitcherItem.tsx | 20 +- .../components/product-switcher/src/index.tsx | 8 +- .../src/useProductSwitcher.ts | 2 +- .../ProductSwitcher.customization.stories.tsx | 78 +- .../stories/ProductSwitcher.stories.tsx | 40 +- .../progress-bar/__tests__/index.spec.tsx | 76 +- .../components/progress-bar/build.js | 4 +- .../progress-bar/src/ProgressBar.tsx | 44 +- .../progress-bar/src/ProgressBarLabel.tsx | 20 +- .../components/progress-bar/src/constants.ts | 2 +- .../components/progress-bar/src/index.tsx | 4 +- .../stories/customization.stories.tsx | 40 +- .../progress-bar/stories/index.stories.tsx | 22 +- .../progress-steps/__tests__/index.spec.tsx | 148 +- .../components/progress-steps/build.js | 4 +- .../src/ProgressStepComplete.tsx | 24 +- .../src/ProgressStepCurrent.tsx | 24 +- .../progress-steps/src/ProgressStepError.tsx | 24 +- .../src/ProgressStepIncomplete.tsx | 34 +- .../src/ProgressStepSeparator.tsx | 42 +- .../progress-steps/src/ProgressSteps.tsx | 36 +- .../src/ProgressStepsContext.tsx | 4 +- .../src/icons/ProgressCurrentIcon.tsx | 18 +- .../src/icons/ProgressErrorIcon.tsx | 18 +- .../src/icons/ProgressIncompleteIcon.tsx | 18 +- .../components/progress-steps/src/index.tsx | 14 +- .../components/progress-steps/src/types.ts | 36 +- .../stories/customization.stories.tsx | 78 +- .../stories/horizontal.stories.tsx | 8 +- .../stories/vertical.stories.tsx | 8 +- .../__tests__/index.spec.tsx | 250 +- .../components/radio-button-group/build.js | 4 +- .../radio-button-group/src/HiddenRadio.tsx | 10 +- .../radio-button-group/src/RadioButton.tsx | 44 +- .../src/RadioButtonContext.tsx | 8 +- .../src/RadioButtonGroup.tsx | 30 +- .../src/StyledRadioButtonGroupWrapper.tsx | 34 +- .../src/StyledRadioButtonLabel.tsx | 26 +- .../radio-button-group/src/index.tsx | 4 +- .../stories/index.stories.tsx | 46 +- .../radio-group/__tests__/radio.test.tsx | 376 +- .../components/radio-group/build.js | 4 +- .../components/radio-group/src/Radio.tsx | 46 +- .../radio-group/src/RadioContext.tsx | 8 +- .../components/radio-group/src/RadioGroup.tsx | 24 +- .../components/radio-group/src/index.tsx | 4 +- .../stories/customization.stories.tsx | 58 +- .../stories/radio-controlled.stories.tsx | 48 +- .../stories/radio-uncontrolled.stories.tsx | 24 +- .../stories/radiogroup-controlled.stories.tsx | 46 +- .../radiogroup-uncontrolled.stories.tsx | 36 +- .../stories/radiogroup-vrt.stories.tsx | 58 +- .../components/screen-reader-only/build.js | 4 +- .../screen-reader-only/src/index.tsx | 16 +- .../stories/index.stories.tsx | 8 +- .../select/__tests__/option.test.tsx | 120 +- .../select/__tests__/optiongroup.test.tsx | 104 +- .../select/__tests__/select.test.tsx | 314 +- .../paste-core/components/select/build.js | 4 +- .../components/select/src/Option.tsx | 16 +- .../components/select/src/OptionGroup.tsx | 18 +- .../components/select/src/Select.tsx | 38 +- .../components/select/src/index.tsx | 6 +- .../paste-core/components/select/src/types.ts | 6 +- .../select/stories/select.stories.tsx | 244 +- .../components/select/test-utils/index.ts | 10 +- .../separator/__tests__/index.spec.tsx | 136 +- .../paste-core/components/separator/build.js | 4 +- .../components/separator/src/index.tsx | 30 +- .../separator/stories/index.stories.tsx | 56 +- .../__tests__/customization.spec.tsx | 218 +- .../side-modal/__tests__/index.spec.tsx | 54 +- .../paste-core/components/side-modal/build.js | 4 +- .../components/side-modal/src/SideModal.tsx | 34 +- .../side-modal/src/SideModalBody.tsx | 20 +- .../side-modal/src/SideModalButton.tsx | 20 +- .../side-modal/src/SideModalContainer.tsx | 20 +- .../side-modal/src/SideModalContext.tsx | 6 +- .../side-modal/src/SideModalFooter.tsx | 20 +- .../side-modal/src/SideModalFooterActions.tsx | 22 +- .../side-modal/src/SideModalHeader.tsx | 30 +- .../side-modal/src/SideModalHeading.tsx | 22 +- .../components/side-modal/src/index.tsx | 18 +- .../stories/customization.stories.tsx | 58 +- .../side-modal/stories/index.stories.tsx | 34 +- .../sidebar/__tests__/index.spec.tsx | 224 +- .../__tests__/sidebarNavigation.spec.tsx | 164 +- .../sidebar/__tests__/skipLinks.spec.tsx | 54 +- .../paste-core/components/sidebar/build.js | 4 +- .../components/sidebar/src/Sidebar.tsx | 46 +- .../sidebar/src/SidebarBetaBadge.tsx | 42 +- .../components/sidebar/src/SidebarBody.tsx | 18 +- .../components/sidebar/src/SidebarContext.tsx | 4 +- .../sidebar/src/SidebarSkipLinks.tsx | 22 +- .../SidebarOverlayContentWrapper.tsx | 26 +- .../SidebarPushContentWrapper.tsx | 34 +- .../src/footer/SidebarCollapseButton.tsx | 28 +- .../sidebar/src/footer/SidebarFooter.tsx | 12 +- .../sidebar/src/header/SidebarHeader.tsx | 18 +- .../src/header/SidebarHeaderIconButton.tsx | 24 +- .../sidebar/src/header/SidebarHeaderLabel.tsx | 24 +- .../components/sidebar/src/index.tsx | 36 +- .../src/navigation/SidebarNavigation.tsx | 58 +- .../navigation/SidebarNavigationContext.tsx | 2 +- .../SidebarNavigationDisclosure.tsx | 38 +- .../SidebarNavigationDisclosureContent.tsx | 24 +- .../SidebarNavigationDisclosureContext.tsx | 6 +- .../SidebarNavigationDisclosureHeading.tsx | 54 +- ...ebarNavigationDisclosureHeadingWrapper.tsx | 14 +- .../src/navigation/SidebarNavigationItem.tsx | 62 +- .../navigation/SidebarNavigationSeparator.tsx | 24 +- .../sidebar/src/navigation/styles.tsx | 80 +- .../sidebar/src/navigation/types.ts | 5 +- .../components/sidebar/src/types.ts | 2 +- .../sidebar/stories/BetaBadge.stories.tsx | 8 +- .../sidebar/stories/SidebarHeader.stories.tsx | 12 +- .../sidebar/stories/customization.stories.tsx | 78 +- .../components/AccountMenu.tsx | 6 +- .../components/AccountSwitcher.tsx | 18 +- .../components/AppSwitcher.tsx | 34 +- .../components/BillingMenu.tsx | 6 +- .../full-composition/components/Console.tsx | 58 +- .../components/DebuggerAction.tsx | 6 +- .../full-composition/components/Flex.tsx | 48 +- .../components/NotificationsDialog.tsx | 6 +- .../full-composition/components/SearchBox.tsx | 8 +- .../full-composition/components/Segment.tsx | 60 +- .../components/StatusMenu.tsx | 48 +- .../components/SupportMenu.tsx | 6 +- .../components/TrialBadge.tsx | 6 +- .../components/UpgradeBadge.tsx | 4 +- .../components/UserDialogConsole.tsx | 18 +- .../components/UserDialogFlex.tsx | 16 +- .../components/UserDialogSegment.tsx | 14 +- .../components/WorkspaceSwitcher.tsx | 18 +- .../full-composition/console.stories.tsx | 8 +- .../stories/full-composition/docs.stories.tsx | 50 +- .../stories/full-composition/flex.stories.tsx | 8 +- .../full-composition/segment.stories.tsx | 8 +- .../sidebar/stories/navigation.stories.tsx | 74 +- .../sidebar/stories/overlay.stories.tsx | 26 +- .../sidebar/stories/push.stories.tsx | 26 +- .../skeleton-loader/__tests__/index.spec.tsx | 92 +- .../components/skeleton-loader/build.js | 4 +- .../components/skeleton-loader/src/index.tsx | 38 +- .../skeleton-loader/src/keyframes.tsx | 2 +- .../skeleton-loader/stories/index.stories.tsx | 40 +- .../slider/__tests__/index.spec.tsx | 80 +- .../paste-core/components/slider/build.js | 4 +- .../components/slider/src/Slider.tsx | 46 +- .../components/slider/src/SliderThumb.tsx | 18 +- .../components/slider/src/SliderTrack.tsx | 16 +- .../components/slider/src/helpers.ts | 18 +- .../components/slider/src/index.tsx | 2 +- .../slider/stories/index.stories.tsx | 58 +- .../spinner/__tests__/index.test.tsx | 80 +- .../paste-core/components/spinner/build.js | 4 +- .../components/spinner/src/constants.ts | 2 +- .../components/spinner/src/index.tsx | 30 +- .../components/spinner/src/keyframes.tsx | 4 +- .../components/spinner/src/styled.tsx | 18 +- .../spinner/stories/index.stories.tsx | 44 +- .../StatusBadgeCustomization.spec.tsx | 48 +- .../StatusMenuCustomization.spec.tsx | 132 +- .../paste-core/components/status/build.js | 4 +- .../components/status/src/StatusBadge.tsx | 28 +- .../components/status/src/StatusMenu.tsx | 10 +- .../components/status/src/StatusMenuBadge.tsx | 22 +- .../components/status/src/StatusMenuItem.tsx | 10 +- .../status/src/StatusMenuItemCheckbox.tsx | 10 +- .../status/src/StatusMenuItemChild.tsx | 24 +- .../status/src/StatusMenuItemRadio.tsx | 10 +- .../components/status/src/constants.tsx | 76 +- .../components/status/src/index.tsx | 20 +- .../paste-core/components/status/src/types.ts | 28 +- .../status/stories/StatusBadge.stories.tsx | 34 +- .../StatusBadgeCustomization.stories.tsx | 82 +- .../status/stories/StatusMenu.stories.tsx | 110 +- .../StatusMenuCustomization.stories.tsx | 100 +- .../switch/__tests__/index.spec.tsx | 330 +- .../paste-core/components/switch/build.js | 4 +- .../components/switch/src/Switch.tsx | 68 +- .../components/switch/src/SwitchContext.tsx | 4 +- .../components/switch/src/SwitchGroup.tsx | 24 +- .../components/switch/src/SwitchKnob.tsx | 48 +- .../components/switch/src/constants.ts | 6 +- .../components/switch/src/index.tsx | 4 +- .../switch/stories/index.stories.tsx | 56 +- .../components/table/__tests__/index.spec.tsx | 344 +- packages/paste-core/components/table/build.js | 4 +- .../paste-core/components/table/src/TBody.tsx | 44 +- .../paste-core/components/table/src/TFoot.tsx | 30 +- .../paste-core/components/table/src/THead.tsx | 32 +- .../paste-core/components/table/src/Table.tsx | 32 +- .../components/table/src/TableContext.tsx | 6 +- .../paste-core/components/table/src/Td.tsx | 12 +- .../paste-core/components/table/src/Th.tsx | 14 +- .../paste-core/components/table/src/Tr.tsx | 22 +- .../components/table/src/constants.ts | 20 +- .../paste-core/components/table/src/index.tsx | 16 +- .../paste-core/components/table/src/types.ts | 38 +- .../table/stories/index.stories.tsx | 90 +- .../components/tabs/__tests__/tabs.test.tsx | 356 +- packages/paste-core/components/tabs/build.js | 4 +- .../paste-core/components/tabs/src/Tab.tsx | 158 +- .../components/tabs/src/TabList.tsx | 45 +- .../components/tabs/src/TabPanel.tsx | 30 +- .../components/tabs/src/TabPanels.tsx | 22 +- .../paste-core/components/tabs/src/Tabs.tsx | 42 +- .../components/tabs/src/TabsContext.tsx | 12 +- .../paste-core/components/tabs/src/index.tsx | 10 +- .../paste-core/components/tabs/src/types.ts | 4 +- .../paste-core/components/tabs/src/utils.ts | 4 +- .../components/tabs/stories/index.stories.tsx | 160 +- .../textarea/__tests__/textarea.test.tsx | 174 +- .../paste-core/components/textarea/build.js | 4 +- .../components/textarea/src/TextArea.tsx | 90 +- .../components/textarea/src/index.tsx | 2 +- .../textarea/stories/textarea.stories.tsx | 376 +- .../time-picker/__tests__/index.spec.tsx | 184 +- .../components/time-picker/build.js | 4 +- .../components/time-picker/src/TimePicker.tsx | 16 +- .../components/time-picker/src/index.tsx | 4 +- .../components/time-picker/src/utils.ts | 6 +- .../time-picker/stories/index.stories.tsx | 118 +- .../toast/__tests__/customization.spec.tsx | 68 +- .../components/toast/__tests__/index.spec.tsx | 126 +- .../toast/__tests__/toaster.spec.tsx | 104 +- .../toast/__tests__/useToaster.spec.tsx | 108 +- packages/paste-core/components/toast/build.js | 4 +- .../components/toast/src/ErrorToast.tsx | 14 +- .../components/toast/src/NeutralToast.tsx | 14 +- .../components/toast/src/SuccessToast.tsx | 14 +- .../paste-core/components/toast/src/Toast.tsx | 56 +- .../components/toast/src/ToastContainer.tsx | 14 +- .../components/toast/src/ToastPortal.tsx | 16 +- .../components/toast/src/Toaster.tsx | 44 +- .../components/toast/src/WarningToast.tsx | 14 +- .../components/toast/src/constants.ts | 8 +- .../paste-core/components/toast/src/index.tsx | 10 +- .../paste-core/components/toast/src/types.ts | 22 +- .../components/toast/src/useToaster.ts | 14 +- .../toast/stories/customization.stories.tsx | 60 +- .../toast/stories/index.stories.tsx | 84 +- .../tooltip/__test__/index.spec.tsx | 138 +- .../paste-core/components/tooltip/build.js | 4 +- .../components/tooltip/src/TooltipArrow.tsx | 12 +- .../components/tooltip/src/index.tsx | 40 +- .../tooltip/stories/index.stories.tsx | 60 +- .../topbar/__tests__/index.spec.tsx | 44 +- .../paste-core/components/topbar/build.js | 4 +- .../components/topbar/src/Topbar.tsx | 18 +- .../components/topbar/src/TopbarActions.tsx | 26 +- .../components/topbar/src/index.tsx | 4 +- .../topbar/stories/customization.stories.tsx | 18 +- .../topbar/stories/topbar.stories.tsx | 40 +- .../paste-core/components/truncate/build.js | 4 +- .../components/truncate/src/index.tsx | 16 +- .../truncate/stories/index.stories.tsx | 12 +- .../user-dialog/__tests__/index.spec.tsx | 142 +- .../components/user-dialog/build.js | 4 +- .../components/user-dialog/src/UserDialog.tsx | 38 +- .../user-dialog/src/UserDialogContainer.tsx | 22 +- .../user-dialog/src/UserDialogList.tsx | 22 +- .../user-dialog/src/UserDialogListItem.tsx | 46 +- .../user-dialog/src/UserDialogSeparator.tsx | 12 +- .../user-dialog/src/UserDialogUserEmail.tsx | 12 +- .../user-dialog/src/UserDialogUserInfo.tsx | 22 +- .../user-dialog/src/UserDialogUserName.tsx | 12 +- .../components/user-dialog/src/index.tsx | 16 +- .../components/user-dialog/src/types.ts | 68 +- .../user-dialog/stories/index.stories.tsx | 106 +- .../visual-picker/__tests__/checkbox.spec.tsx | 220 +- .../visual-picker/__tests__/radio.spec.tsx | 224 +- .../components/visual-picker/build.js | 4 +- .../src/VisualPickerCheckbox.tsx | 51 +- .../src/VisualPickerCheckboxGroup.tsx | 24 +- .../visual-picker/src/VisualPickerContext.tsx | 14 +- .../visual-picker/src/VisualPickerRadio.tsx | 56 +- .../src/VisualPickerRadioGroup.tsx | 28 +- .../components/visual-picker/src/index.tsx | 8 +- .../components/visual-picker/src/types.ts | 16 +- .../stories/checkbox.stories.tsx | 22 +- .../stories/customization.stories.tsx | 90 +- .../visual-picker/stories/radio.stories.tsx | 36 +- .../paste-core/core-bundle/babel.config.js | 2 +- .../core-bundle/src/account-switcher.tsx | 2 +- .../core-bundle/src/alert-dialog.tsx | 2 +- packages/paste-core/core-bundle/src/alert.tsx | 2 +- .../paste-core/core-bundle/src/anchor.tsx | 2 +- .../core-bundle/src/animation-library.tsx | 2 +- .../core-bundle/src/aspect-ratio.tsx | 2 +- .../paste-core/core-bundle/src/avatar.tsx | 2 +- packages/paste-core/core-bundle/src/badge.tsx | 2 +- .../core-bundle/src/base-radio-checkbox.tsx | 2 +- packages/paste-core/core-bundle/src/box.tsx | 2 +- .../paste-core/core-bundle/src/breadcrumb.tsx | 2 +- .../core-bundle/src/button-group.tsx | 2 +- .../paste-core/core-bundle/src/button.tsx | 2 +- .../paste-core/core-bundle/src/callout.tsx | 2 +- packages/paste-core/core-bundle/src/card.tsx | 2 +- .../core-bundle/src/chat-composer.tsx | 2 +- .../paste-core/core-bundle/src/chat-log.tsx | 2 +- .../paste-core/core-bundle/src/checkbox.tsx | 2 +- .../src/clipboard-copy-library.tsx | 2 +- .../paste-core/core-bundle/src/code-block.tsx | 2 +- .../core-bundle/src/code-editor-library.tsx | 2 +- .../core-bundle/src/color-contrast-utils.tsx | 2 +- .../core-bundle/src/combobox-primitive.tsx | 2 +- .../paste-core/core-bundle/src/combobox.tsx | 2 +- .../core-bundle/src/customization.tsx | 2 +- .../paste-core/core-bundle/src/data-grid.tsx | 2 +- .../src/data-visualization-library.tsx | 2 +- .../core-bundle/src/date-picker.tsx | 2 +- .../core-bundle/src/description-list.tsx | 2 +- .../core-bundle/src/design-tokens.tsx | 2 +- .../core-bundle/src/detail-text.tsx | 2 +- .../core-bundle/src/disclosure-primitive.tsx | 2 +- .../paste-core/core-bundle/src/disclosure.tsx | 2 +- .../core-bundle/src/display-heading.tsx | 2 +- .../core-bundle/src/display-pill-group.tsx | 2 +- .../core-bundle/src/dropdown-library.tsx | 2 +- .../core-bundle/src/editable-code-block.tsx | 2 +- .../core-bundle/src/file-picker.tsx | 2 +- .../core-bundle/src/file-uploader.tsx | 2 +- packages/paste-core/core-bundle/src/flex.tsx | 2 +- .../core-bundle/src/form-pill-group.tsx | 2 +- packages/paste-core/core-bundle/src/form.tsx | 2 +- packages/paste-core/core-bundle/src/grid.tsx | 2 +- .../paste-core/core-bundle/src/heading.tsx | 2 +- .../paste-core/core-bundle/src/help-text.tsx | 2 +- .../core-bundle/src/in-page-navigation.tsx | 2 +- packages/paste-core/core-bundle/src/index.tsx | 172 +- .../core-bundle/src/inline-code.tsx | 2 +- .../core-bundle/src/inline-control-group.tsx | 2 +- .../paste-core/core-bundle/src/input-box.tsx | 2 +- packages/paste-core/core-bundle/src/input.tsx | 2 +- packages/paste-core/core-bundle/src/label.tsx | 2 +- .../core-bundle/src/lexical-library.tsx | 2 +- packages/paste-core/core-bundle/src/list.tsx | 2 +- .../core-bundle/src/listbox-primitive.tsx | 2 +- .../core-bundle/src/media-object.tsx | 2 +- .../core-bundle/src/menu-primitive.tsx | 2 +- packages/paste-core/core-bundle/src/menu.tsx | 2 +- packages/paste-core/core-bundle/src/meter.tsx | 2 +- .../core-bundle/src/minimizable-dialog.tsx | 2 +- .../src/modal-dialog-primitive.tsx | 2 +- packages/paste-core/core-bundle/src/modal.tsx | 2 +- .../src/non-modal-dialog-primitive.tsx | 2 +- .../paste-core/core-bundle/src/pagination.tsx | 2 +- .../paste-core/core-bundle/src/paragraph.tsx | 2 +- .../paste-core/core-bundle/src/popover.tsx | 2 +- .../core-bundle/src/product-switcher.tsx | 2 +- .../core-bundle/src/progress-bar.tsx | 2 +- .../core-bundle/src/progress-steps.tsx | 2 +- .../core-bundle/src/radio-button-group.tsx | 2 +- .../core-bundle/src/radio-group.tsx | 2 +- .../src/react-spectrum-library.tsx | 2 +- .../src/react-textarea-autosize-library.tsx | 2 +- .../core-bundle/src/reakit-library.tsx | 2 +- .../core-bundle/src/screen-reader-only.tsx | 2 +- .../paste-core/core-bundle/src/select.tsx | 2 +- .../paste-core/core-bundle/src/separator.tsx | 2 +- .../core-bundle/src/sibling-box.tsx | 2 +- .../paste-core/core-bundle/src/side-modal.tsx | 2 +- .../paste-core/core-bundle/src/sidebar.tsx | 2 +- .../core-bundle/src/skeleton-loader.tsx | 2 +- .../paste-core/core-bundle/src/slider.tsx | 2 +- .../paste-core/core-bundle/src/spinner.tsx | 2 +- packages/paste-core/core-bundle/src/stack.tsx | 2 +- .../paste-core/core-bundle/src/status.tsx | 2 +- .../core-bundle/src/style-props.tsx | 2 +- .../core-bundle/src/styling-library.tsx | 2 +- .../paste-core/core-bundle/src/switch.tsx | 2 +- .../src/syntax-highlighter-library.tsx | 2 +- .../core-bundle/src/syntax-highlighter.tsx | 2 +- packages/paste-core/core-bundle/src/table.tsx | 2 +- .../core-bundle/src/tabs-primitive.tsx | 2 +- packages/paste-core/core-bundle/src/tabs.tsx | 2 +- packages/paste-core/core-bundle/src/text.tsx | 2 +- .../paste-core/core-bundle/src/textarea.tsx | 2 +- packages/paste-core/core-bundle/src/theme.tsx | 2 +- .../core-bundle/src/time-picker.tsx | 2 +- packages/paste-core/core-bundle/src/toast.tsx | 2 +- .../core-bundle/src/tooltip-primitive.tsx | 2 +- .../paste-core/core-bundle/src/tooltip.tsx | 2 +- .../paste-core/core-bundle/src/topbar.tsx | 2 +- .../paste-core/core-bundle/src/truncate.tsx | 2 +- packages/paste-core/core-bundle/src/types.tsx | 2 +- .../core-bundle/src/uid-library.tsx | 2 +- .../core-bundle/src/user-dialog.tsx | 2 +- packages/paste-core/core-bundle/src/utils.tsx | 2 +- .../core-bundle/src/visual-picker.tsx | 2 +- .../paste-core/core-bundle/tools/constants.ts | 28 +- .../paste-core/core-bundle/tools/generate.ts | 20 +- .../paste-core/core-bundle/tools/minify.ts | 12 +- .../paste-core/core-bundle/tools/utils.ts | 48 +- .../__tests__/aspectRatio.spec.tsx | 42 +- .../paste-core/layout/aspect-ratio/build.js | 4 +- .../layout/aspect-ratio/src/AspectRatio.tsx | 18 +- .../layout/aspect-ratio/src/index.tsx | 4 +- .../aspect-ratio/stories/index.stories.tsx | 8 +- .../layout/flex/__tests__/flex.test.tsx | 458 +- packages/paste-core/layout/flex/build.js | 4 +- packages/paste-core/layout/flex/src/Flex.tsx | 40 +- .../paste-core/layout/flex/src/helpers.tsx | 70 +- packages/paste-core/layout/flex/src/index.tsx | 4 +- packages/paste-core/layout/flex/src/types.tsx | 16 +- .../layout/flex/stories/index.stories.tsx | 28 +- .../layout/grid/__tests__/grid.test.tsx | 506 +- packages/paste-core/layout/grid/build.js | 4 +- .../paste-core/layout/grid/src/Column.tsx | 35 +- packages/paste-core/layout/grid/src/Grid.tsx | 46 +- packages/paste-core/layout/grid/src/index.tsx | 6 +- packages/paste-core/layout/grid/src/types.ts | 22 +- packages/paste-core/layout/grid/src/utils.tsx | 62 +- .../layout/grid/stories/index.stories.tsx | 118 +- .../media-object/__tests__/index.spec.tsx | 162 +- .../paste-core/layout/media-object/build.js | 4 +- .../layout/media-object/src/MediaBody.tsx | 20 +- .../layout/media-object/src/MediaFigure.tsx | 28 +- .../layout/media-object/src/MediaObject.tsx | 26 +- .../layout/media-object/src/index.tsx | 12 +- .../media-object/stories/index.stories.tsx | 80 +- .../layout/stack/__tests__/stack.test.tsx | 138 +- packages/paste-core/layout/stack/build.js | 4 +- .../paste-core/layout/stack/src/Stack.tsx | 68 +- .../paste-core/layout/stack/src/index.tsx | 4 +- .../layout/stack/stories/index.stories.tsx | 58 +- .../box/__tests__/SafelySpreadProps.test.ts | 22 +- .../box/__tests__/StyleFunctions.test.tsx | 136 +- .../primitives/box/__tests__/box.test.tsx | 670 +- packages/paste-core/primitives/box/build.js | 4 +- .../primitives/box/src/CustomStyleProps.ts | 38 +- .../primitives/box/src/PseudoPropStyles.ts | 82 +- .../primitives/box/src/SafelySpreadProps.ts | 18 +- .../primitives/box/src/StyleFunctions.ts | 24 +- .../paste-core/primitives/box/src/index.tsx | 52 +- .../paste-core/primitives/box/src/types.ts | 10 +- .../primitives/box/stories/index.stories.tsx | 134 +- .../useMultiSelectPrimitive.test.tsx | 789 +- .../paste-core/primitives/combobox/build.js | 4 +- .../primitives/combobox/src/index.tsx | 8 +- .../combobox/stories/index.stories.tsx | 70 +- .../paste-core/primitives/disclosure/build.js | 4 +- .../primitives/disclosure/src/index.tsx | 4 +- .../disclosure/stories/index.stories.tsx | 22 +- .../listbox/__tests__/index.spec.tsx | 100 +- .../paste-core/primitives/listbox/build.js | 4 +- .../listbox/src/ListboxPrimitive.tsx | 18 +- .../listbox/src/ListboxPrimitiveItem.tsx | 16 +- .../primitives/listbox/src/index.tsx | 10 +- .../primitives/listbox/src/types.ts | 2 +- .../listbox/src/useListboxPrimitiveState.tsx | 12 +- .../listbox/stories/index.stories.tsx | 52 +- .../primitives/menu/__tests__/index.spec.tsx | 126 +- packages/paste-core/primitives/menu/build.js | 4 +- .../paste-core/primitives/menu/src/index.tsx | 4 +- .../primitives/menu/stories/index.stories.tsx | 16 +- .../primitives/modal-dialog/build.js | 4 +- .../primitives/modal-dialog/src/index.tsx | 4 +- .../modal-dialog/stories/index.stories.tsx | 40 +- .../primitives/non-modal-dialog/build.js | 4 +- .../primitives/non-modal-dialog/src/index.tsx | 4 +- .../stories/index.stories.tsx | 38 +- .../sibling-box/__tests__/siblingBox.test.tsx | 126 +- .../primitives/sibling-box/build.js | 4 +- .../primitives/sibling-box/src/index.tsx | 34 +- packages/paste-core/primitives/tabs/build.js | 4 +- .../paste-core/primitives/tabs/src/index.tsx | 4 +- .../primitives/tabs/stories/index.stories.tsx | 26 +- .../text/__tests__/SafelySpreadProps.spec.ts | 22 +- .../text/__tests__/StyleFunctions.spec.tsx | 142 +- .../primitives/text/__tests__/text.spec.tsx | 488 +- packages/paste-core/primitives/text/build.js | 4 +- .../primitives/text/src/CustomStyleProps.ts | 4 +- .../primitives/text/src/PseudoPropStyles.ts | 50 +- .../primitives/text/src/SafelySpreadProps.ts | 14 +- .../primitives/text/src/StyleFunctions.ts | 24 +- .../paste-core/primitives/text/src/index.tsx | 42 +- .../paste-core/primitives/text/src/types.ts | 18 +- .../primitives/text/stories/index.stories.tsx | 144 +- .../paste-core/primitives/tooltip/build.js | 4 +- .../primitives/tooltip/src/index.tsx | 4 +- .../tooltip/stories/index.stories.tsx | 20 +- .../__tests__/CustomizationProvider.test.tsx | 64 +- .../__tests__/utils.test.ts | 106 +- packages/paste-customization/build.js | 4 +- .../src/CustomizationConsumer.tsx | 10 +- .../src/CustomizationProvider.tsx | 24 +- packages/paste-customization/src/index.tsx | 6 +- .../src/types/CreateCustomTheme.ts | 6 +- .../src/types/CustomTheme.ts | 4 +- .../src/types/CustomizationProvider.ts | 12 +- .../paste-customization/src/types/PasteCSS.ts | 14 +- .../paste-customization/src/types/index.ts | 8 +- packages/paste-customization/src/utils.ts | 6 +- .../stories/customization.stories.tsx | 286 +- packages/paste-design-tokens/.babelrc | 4 +- .../__tests__/index.test.tsx | 48 +- .../formatters/__tests__/common.ts.spec.ts | 20 +- .../formatters/__tests__/d.ts.spec.ts | 20 +- .../formatters/__tests__/es6.spec.ts | 20 +- .../formatters/__tests__/generic.d.ts.spec.ts | 20 +- .../formatters/__tests__/generic.js.spec.ts | 20 +- .../__tests__/sketchpalette.spec.ts | 20 +- .../paste-design-tokens/formatters/common.ts | 18 +- .../paste-design-tokens/formatters/d.ts.ts | 22 +- .../paste-design-tokens/formatters/es6.ts | 20 +- .../formatters/generic.d.ts.ts | 18 +- .../paste-design-tokens/formatters/generic.ts | 38 +- .../formatters/sketchpalette.ts | 24 +- packages/paste-design-tokens/gulpfile.ts | 300 +- .../tokens/global/data-visualization.yml | 20 +- .../types/GenericTokensShape.ts | 44 +- .../paste-design-tokens/types/index.ds.ts | 2 +- .../utils/__tests__/rgbToHex.test.tsx | 40 +- .../formatGroupTokensWithTemplate/index.ts | 24 +- .../formatSingleTokensWithTemplate/index.ts | 12 +- .../utils/getTokenCategories/index.ts | 6 +- .../utils/pluralCategoryMap.ts | 62 +- packages/paste-design-tokens/utils/remToPx.ts | 8 +- .../paste-design-tokens/utils/rgbToHex.ts | 10 +- .../__tests__/no-invalid-module-paths.test.js | 58 +- .../__tests__/svg-needs-viewBox.test.js | 12 +- .../eslint-plugin-paste-internal/src/index.js | 16 +- .../src/rules/no-invalid-module-paths.js | 18 +- .../src/rules/svg-needs-viewBox.js | 10 +- packages/paste-icons/.prettierrc.js | 8 +- packages/paste-icons/__test__/icons.spec.tsx | 154 +- packages/paste-icons/build.js | 20 +- packages/paste-icons/src/AcceptIcon.tsx | 18 +- packages/paste-icons/src/AddListIcon.tsx | 18 +- packages/paste-icons/src/AddSeriesIcon.tsx | 18 +- packages/paste-icons/src/AgentIcon.tsx | 18 +- packages/paste-icons/src/AlignLeftIcon.tsx | 18 +- packages/paste-icons/src/AlignRightIcon.tsx | 18 +- .../src/AlignVerticalCenterIcon.tsx | 18 +- packages/paste-icons/src/ArchiveIcon.tsx | 18 +- packages/paste-icons/src/ArrowBackIcon.tsx | 18 +- packages/paste-icons/src/ArrowDownIcon.tsx | 18 +- packages/paste-icons/src/ArrowForwardIcon.tsx | 18 +- packages/paste-icons/src/ArrowUpIcon.tsx | 18 +- packages/paste-icons/src/AttachIcon.tsx | 18 +- packages/paste-icons/src/AttachmentIcon.tsx | 18 +- .../paste-icons/src/AutomaticUpdatesIcon.tsx | 18 +- packages/paste-icons/src/BoldIcon.tsx | 18 +- packages/paste-icons/src/BuildIcon.tsx | 18 +- packages/paste-icons/src/BuiltInIcon.tsx | 18 +- packages/paste-icons/src/BusinessIcon.tsx | 18 +- packages/paste-icons/src/ButtonIcon.tsx | 18 +- packages/paste-icons/src/CalendarIcon.tsx | 18 +- packages/paste-icons/src/CallActiveIcon.tsx | 18 +- packages/paste-icons/src/CallAddIcon.tsx | 18 +- packages/paste-icons/src/CallFailedIcon.tsx | 18 +- packages/paste-icons/src/CallHoldIcon.tsx | 18 +- packages/paste-icons/src/CallIcon.tsx | 18 +- packages/paste-icons/src/CallIncomingIcon.tsx | 18 +- packages/paste-icons/src/CallOutgoingIcon.tsx | 18 +- packages/paste-icons/src/CallTransferIcon.tsx | 18 +- packages/paste-icons/src/ChatIcon.tsx | 18 +- .../paste-icons/src/CheckboxCheckIcon.tsx | 18 +- packages/paste-icons/src/CheckboxLineIcon.tsx | 18 +- .../paste-icons/src/CheckmarkCircleIcon.tsx | 18 +- .../src/ChevronDisclosureCollapsedIcon.tsx | 18 +- .../src/ChevronDisclosureExpandedIcon.tsx | 18 +- .../paste-icons/src/ChevronDisclosureIcon.tsx | 18 +- .../paste-icons/src/ChevronDoubleLeftIcon.tsx | 18 +- .../src/ChevronDoubleRightIcon.tsx | 18 +- packages/paste-icons/src/ChevronDownIcon.tsx | 18 +- .../paste-icons/src/ChevronExpandIcon.tsx | 18 +- packages/paste-icons/src/ChevronLeftIcon.tsx | 18 +- packages/paste-icons/src/ChevronRightIcon.tsx | 18 +- packages/paste-icons/src/ChevronUpIcon.tsx | 18 +- packages/paste-icons/src/ClearIcon.tsx | 18 +- packages/paste-icons/src/CloseCircleIcon.tsx | 18 +- packages/paste-icons/src/CloseIcon.tsx | 18 +- packages/paste-icons/src/CloudIcon.tsx | 18 +- packages/paste-icons/src/CodeIcon.tsx | 18 +- packages/paste-icons/src/CollapseIcon.tsx | 18 +- packages/paste-icons/src/ColorPickerIcon.tsx | 18 +- packages/paste-icons/src/ColumnIcon.tsx | 18 +- packages/paste-icons/src/CommunityIcon.tsx | 18 +- .../src/ConnectivityAvailableIcon.tsx | 18 +- .../paste-icons/src/ConnectivityBusyIcon.tsx | 18 +- .../src/ConnectivityNeutralIcon.tsx | 18 +- .../src/ConnectivityOfflineIcon.tsx | 18 +- .../src/ConnectivityUnavailableIcon.tsx | 18 +- packages/paste-icons/src/CopyIcon.tsx | 18 +- packages/paste-icons/src/CreditCardIcon.tsx | 18 +- packages/paste-icons/src/CustomIcon.tsx | 18 +- packages/paste-icons/src/DarkModeIcon.tsx | 18 +- packages/paste-icons/src/DataBarChartIcon.tsx | 18 +- .../paste-icons/src/DataLineChartIcon.tsx | 18 +- packages/paste-icons/src/DataPieChartIcon.tsx | 18 +- packages/paste-icons/src/DataTableIcon.tsx | 18 +- packages/paste-icons/src/DatabaseIcon.tsx | 18 +- packages/paste-icons/src/DeleteIcon.tsx | 18 +- packages/paste-icons/src/DeliveredIcon.tsx | 18 +- packages/paste-icons/src/DialpadIcon.tsx | 18 +- packages/paste-icons/src/DirectoryIcon.tsx | 18 +- packages/paste-icons/src/DisableIcon.tsx | 18 +- packages/paste-icons/src/DividerIcon.tsx | 18 +- packages/paste-icons/src/DoNotIcon.tsx | 18 +- .../paste-icons/src/DocumentationIcon.tsx | 18 +- packages/paste-icons/src/DownloadIcon.tsx | 18 +- .../paste-icons/src/DragHorizontalIcon.tsx | 18 +- packages/paste-icons/src/DragIcon.tsx | 18 +- packages/paste-icons/src/DragVerticalIcon.tsx | 18 +- packages/paste-icons/src/EditIcon.tsx | 18 +- .../src/ElasticSIPTrunkingCapableIcon.tsx | 18 +- packages/paste-icons/src/EmailIcon.tsx | 18 +- packages/paste-icons/src/EmojiIcon.tsx | 18 +- packages/paste-icons/src/ErrorIcon.tsx | 18 +- packages/paste-icons/src/ExpandIcon.tsx | 18 +- packages/paste-icons/src/ExportIcon.tsx | 18 +- packages/paste-icons/src/FaxCapableIcon.tsx | 18 +- packages/paste-icons/src/FeedIcon.tsx | 18 +- packages/paste-icons/src/FileAudioIcon.tsx | 18 +- packages/paste-icons/src/FileIcon.tsx | 18 +- packages/paste-icons/src/FileImageIcon.tsx | 18 +- packages/paste-icons/src/FileVideoIcon.tsx | 18 +- packages/paste-icons/src/FileZipIcon.tsx | 18 +- packages/paste-icons/src/FilterIcon.tsx | 18 +- packages/paste-icons/src/FlagIcon.tsx | 18 +- packages/paste-icons/src/GitIcon.tsx | 18 +- packages/paste-icons/src/HeatmapIcon.tsx | 18 +- packages/paste-icons/src/HideIcon.tsx | 18 +- packages/paste-icons/src/HistoryIcon.tsx | 18 +- packages/paste-icons/src/ImageTextIcon.tsx | 18 +- packages/paste-icons/src/InboxIcon.tsx | 18 +- .../paste-icons/src/IndentDecreaseIcon.tsx | 18 +- .../paste-icons/src/IndentIncreaseIcon.tsx | 18 +- packages/paste-icons/src/InformationIcon.tsx | 18 +- packages/paste-icons/src/ItalicIcon.tsx | 18 +- packages/paste-icons/src/LightModeIcon.tsx | 18 +- packages/paste-icons/src/LinkExternalIcon.tsx | 18 +- packages/paste-icons/src/LinkIcon.tsx | 18 +- packages/paste-icons/src/LoadingIcon.tsx | 18 +- packages/paste-icons/src/LockIcon.tsx | 18 +- packages/paste-icons/src/LogInIcon.tsx | 18 +- packages/paste-icons/src/LogOutIcon.tsx | 18 +- packages/paste-icons/src/LogoTwilioIcon.tsx | 18 +- packages/paste-icons/src/LowerHandIcon.tsx | 18 +- packages/paste-icons/src/MMSCapableIcon.tsx | 18 +- packages/paste-icons/src/MenuIcon.tsx | 18 +- .../paste-icons/src/MicrophoneOffIcon.tsx | 18 +- packages/paste-icons/src/MicrophoneOnIcon.tsx | 18 +- packages/paste-icons/src/MinusIcon.tsx | 18 +- packages/paste-icons/src/MobileIcon.tsx | 18 +- packages/paste-icons/src/MoreIcon.tsx | 18 +- packages/paste-icons/src/NeutralIcon.tsx | 18 +- packages/paste-icons/src/NewIcon.tsx | 18 +- packages/paste-icons/src/NotesIcon.tsx | 18 +- packages/paste-icons/src/NotificationIcon.tsx | 18 +- packages/paste-icons/src/OrderedListIcon.tsx | 18 +- packages/paste-icons/src/OutOfDateIcon.tsx | 18 +- packages/paste-icons/src/PauseIcon.tsx | 18 +- packages/paste-icons/src/PinIcon.tsx | 18 +- packages/paste-icons/src/PlayIcon.tsx | 18 +- packages/paste-icons/src/PlusIcon.tsx | 18 +- .../paste-icons/src/ProcessDisabledIcon.tsx | 18 +- packages/paste-icons/src/ProcessDraftIcon.tsx | 18 +- packages/paste-icons/src/ProcessErrorIcon.tsx | 18 +- .../paste-icons/src/ProcessInProgressIcon.tsx | 18 +- .../paste-icons/src/ProcessNeutralIcon.tsx | 18 +- .../paste-icons/src/ProcessSuccessIcon.tsx | 18 +- .../paste-icons/src/ProcessWarningIcon.tsx | 18 +- .../src/ProductAPIExplorerIcon.tsx | 18 +- .../paste-icons/src/ProductAddOnsIcon.tsx | 18 +- .../src/ProductAdminAccessControlIcon.tsx | 18 +- .../src/ProductAdminAccountsIcon.tsx | 18 +- .../src/ProductAdminDomainsIcon.tsx | 18 +- .../src/ProductAdminResoldCustomersIcon.tsx | 18 +- .../paste-icons/src/ProductAdminSSOIcon.tsx | 18 +- .../paste-icons/src/ProductAdminUsersIcon.tsx | 18 +- .../paste-icons/src/ProductAlarmsIcon.tsx | 18 +- .../paste-icons/src/ProductAssetsIcon.tsx | 18 +- .../paste-icons/src/ProductAudiencesIcon.tsx | 18 +- packages/paste-icons/src/ProductAuthyIcon.tsx | 18 +- .../paste-icons/src/ProductAutopilotIcon.tsx | 18 +- .../paste-icons/src/ProductBillingIcon.tsx | 18 +- packages/paste-icons/src/ProductCLIIcon.tsx | 18 +- .../paste-icons/src/ProductChannelsIcon.tsx | 18 +- packages/paste-icons/src/ProductChatIcon.tsx | 18 +- .../src/ProductCodeExchangeCommunityIcon.tsx | 18 +- .../src/ProductCodeExchangePartnerIcon.tsx | 18 +- packages/paste-icons/src/ProductCommsIcon.tsx | 18 +- .../src/ProductConnectedDevicesIcon.tsx | 18 +- .../src/ProductConnectionsIcon.tsx | 18 +- .../src/ProductContactCenterAdminIcon.tsx | 18 +- .../ProductContactCenterAssessmentsIcon.tsx | 18 +- .../src/ProductContactCenterQueuesIcon.tsx | 18 +- .../src/ProductContactCenterTasksIcon.tsx | 18 +- .../src/ProductContactCenterTeamsIcon.tsx | 18 +- .../src/ProductConversationsIcon.tsx | 18 +- .../paste-icons/src/ProductDebuggerIcon.tsx | 18 +- .../src/ProductDestinationsIcon.tsx | 18 +- .../src/ProductElasticSIPTrunkingIcon.tsx | 18 +- .../paste-icons/src/ProductEmailAPIIcon.tsx | 18 +- .../paste-icons/src/ProductEngageIcon.tsx | 18 +- ...ductEngagementIntelligencePlatformIcon.tsx | 16 +- .../src/ProductEventLibraryIcon.tsx | 18 +- .../src/ProductEventStreamIcon.tsx | 18 +- .../src/ProductEventStreamsIcon.tsx | 18 +- packages/paste-icons/src/ProductFaxIcon.tsx | 18 +- packages/paste-icons/src/ProductFlexIcon.tsx | 18 +- packages/paste-icons/src/ProductFlowIcon.tsx | 18 +- .../paste-icons/src/ProductFrontlineIcon.tsx | 18 +- .../paste-icons/src/ProductFunctionsIcon.tsx | 18 +- packages/paste-icons/src/ProductHomeIcon.tsx | 18 +- .../paste-icons/src/ProductInsightsIcon.tsx | 18 +- .../src/ProductInterconnectIcon.tsx | 18 +- ...ProductInternetOfThingsEmbeddedSIMIcon.tsx | 16 +- .../src/ProductInternetOfThingsIcon.tsx | 18 +- .../ProductInternetOfThingsNarrowbandIcon.tsx | 18 +- ...etOfThingsProgrammableAssetTrackerIcon.tsx | 16 +- .../ProductInternetOfThingsSuperSIMIcon.tsx | 18 +- ...roductInternetOfThingsTrustOnboardIcon.tsx | 16 +- .../ProductInternetOfThingsWirelessIcon.tsx | 18 +- .../paste-icons/src/ProductJourneysIcon.tsx | 18 +- packages/paste-icons/src/ProductKeysIcon.tsx | 18 +- packages/paste-icons/src/ProductLiveIcon.tsx | 18 +- packages/paste-icons/src/ProductLogsIcon.tsx | 18 +- .../paste-icons/src/ProductLookupIcon.tsx | 18 +- .../paste-icons/src/ProductMappingIcon.tsx | 18 +- .../src/ProductMarketingCampaignsIcon.tsx | 18 +- .../paste-icons/src/ProductMessagingIcon.tsx | 18 +- .../paste-icons/src/ProductMicrovisorIcon.tsx | 18 +- .../paste-icons/src/ProductNotifyIcon.tsx | 18 +- .../paste-icons/src/ProductOneAdminIcon.tsx | 18 +- .../src/ProductPayConnectorIcon.tsx | 18 +- .../paste-icons/src/ProductPersonasIcon.tsx | 18 +- .../src/ProductPhoneNumbersIcon.tsx | 18 +- .../paste-icons/src/ProductPrivacyIcon.tsx | 18 +- .../paste-icons/src/ProductProtocolsIcon.tsx | 18 +- packages/paste-icons/src/ProductProxyIcon.tsx | 18 +- .../paste-icons/src/ProductRegionalIcon.tsx | 18 +- .../paste-icons/src/ProductReverseETLIcon.tsx | 18 +- packages/paste-icons/src/ProductSDKIcon.tsx | 18 +- .../paste-icons/src/ProductSegmentIcon.tsx | 18 +- .../paste-icons/src/ProductSettingsIcon.tsx | 18 +- .../src/ProductSourceSchemaIcon.tsx | 18 +- .../paste-icons/src/ProductSourcesIcon.tsx | 18 +- .../paste-icons/src/ProductStudioIcon.tsx | 18 +- .../paste-icons/src/ProductSupportIcon.tsx | 18 +- .../paste-icons/src/ProductSwitcherIcon.tsx | 18 +- packages/paste-icons/src/ProductSyncIcon.tsx | 18 +- .../paste-icons/src/ProductTaskRouterIcon.tsx | 18 +- .../paste-icons/src/ProductTraitsIcon.tsx | 18 +- .../paste-icons/src/ProductTrustHubIcon.tsx | 18 +- .../paste-icons/src/ProductTwiMLBinsIcon.tsx | 18 +- .../paste-icons/src/ProductTwilioOrgIcon.tsx | 18 +- packages/paste-icons/src/ProductUSSDIcon.tsx | 18 +- packages/paste-icons/src/ProductUnifyIcon.tsx | 18 +- packages/paste-icons/src/ProductUsageIcon.tsx | 18 +- .../paste-icons/src/ProductVerifyIcon.tsx | 18 +- packages/paste-icons/src/ProductVideoIcon.tsx | 18 +- packages/paste-icons/src/ProductVoiceIcon.tsx | 18 +- .../src/ProductVoiceIntelligenceIcon.tsx | 18 +- packages/paste-icons/src/RaiseHandIcon.tsx | 18 +- packages/paste-icons/src/RecordIcon.tsx | 18 +- packages/paste-icons/src/RedoIcon.tsx | 18 +- packages/paste-icons/src/RefreshIcon.tsx | 18 +- packages/paste-icons/src/RepeatIcon.tsx | 18 +- packages/paste-icons/src/ResetIcon.tsx | 18 +- packages/paste-icons/src/SMSCapableIcon.tsx | 18 +- packages/paste-icons/src/SMSIcon.tsx | 18 +- packages/paste-icons/src/ScreenShareIcon.tsx | 18 +- packages/paste-icons/src/SearchIcon.tsx | 18 +- packages/paste-icons/src/SelectIcon.tsx | 18 +- packages/paste-icons/src/SelectedIcon.tsx | 18 +- packages/paste-icons/src/SendIcon.tsx | 18 +- packages/paste-icons/src/SentIcon.tsx | 18 +- packages/paste-icons/src/ShareIcon.tsx | 18 +- packages/paste-icons/src/ShowIcon.tsx | 18 +- packages/paste-icons/src/ShrinkIcon.tsx | 18 +- packages/paste-icons/src/SkipBackIcon.tsx | 18 +- packages/paste-icons/src/SkipForwardIcon.tsx | 18 +- packages/paste-icons/src/SocialIcon.tsx | 18 +- .../paste-icons/src/SortAlphabeticalIcon.tsx | 18 +- .../paste-icons/src/SpacerVerticalIcon.tsx | 18 +- packages/paste-icons/src/StarIcon.tsx | 18 +- packages/paste-icons/src/StopIcon.tsx | 18 +- .../paste-icons/src/StopScreenShareIcon.tsx | 18 +- packages/paste-icons/src/StoreIcon.tsx | 18 +- .../paste-icons/src/StrikethroughIcon.tsx | 18 +- packages/paste-icons/src/SubscriptIcon.tsx | 18 +- packages/paste-icons/src/SuccessIcon.tsx | 18 +- packages/paste-icons/src/SuperscriptIcon.tsx | 18 +- packages/paste-icons/src/SupportIcon.tsx | 18 +- packages/paste-icons/src/SystemStatusIcon.tsx | 18 +- packages/paste-icons/src/TaskIcon.tsx | 18 +- .../paste-icons/src/TextAlignCenterIcon.tsx | 18 +- .../paste-icons/src/TextAlignJustifyIcon.tsx | 18 +- .../paste-icons/src/TextAlignLeftIcon.tsx | 18 +- .../paste-icons/src/TextAlignRightIcon.tsx | 18 +- .../paste-icons/src/TextFormatClearIcon.tsx | 18 +- packages/paste-icons/src/TextFormatIcon.tsx | 18 +- .../paste-icons/src/TextHighlightIcon.tsx | 18 +- packages/paste-icons/src/ThemeIcon.tsx | 18 +- packages/paste-icons/src/ThumbsDownIcon.tsx | 18 +- packages/paste-icons/src/ThumbsUpIcon.tsx | 18 +- packages/paste-icons/src/TimeIcon.tsx | 18 +- packages/paste-icons/src/TipIcon.tsx | 18 +- packages/paste-icons/src/TokenIcon.tsx | 18 +- packages/paste-icons/src/TourIcon.tsx | 18 +- packages/paste-icons/src/TranslationIcon.tsx | 18 +- packages/paste-icons/src/TrendDownIcon.tsx | 18 +- packages/paste-icons/src/TrendUpIcon.tsx | 18 +- packages/paste-icons/src/UnarchiveIcon.tsx | 18 +- packages/paste-icons/src/UnderlineIcon.tsx | 18 +- packages/paste-icons/src/UndoIcon.tsx | 18 +- packages/paste-icons/src/UnlockIcon.tsx | 18 +- .../paste-icons/src/UnorderedListIcon.tsx | 18 +- packages/paste-icons/src/UnpinIcon.tsx | 18 +- packages/paste-icons/src/UnsortedIcon.tsx | 18 +- packages/paste-icons/src/UnsubscribeIcon.tsx | 18 +- packages/paste-icons/src/UploadIcon.tsx | 18 +- .../paste-icons/src/UploadToCloudIcon.tsx | 18 +- packages/paste-icons/src/UserIcon.tsx | 18 +- packages/paste-icons/src/UsersIcon.tsx | 18 +- packages/paste-icons/src/VideoOffIcon.tsx | 18 +- packages/paste-icons/src/VideoOnIcon.tsx | 18 +- packages/paste-icons/src/VoiceCapableIcon.tsx | 18 +- packages/paste-icons/src/VoicemailIcon.tsx | 18 +- packages/paste-icons/src/VolumeOffIcon.tsx | 18 +- packages/paste-icons/src/VolumeOnIcon.tsx | 18 +- packages/paste-icons/src/WarningIcon.tsx | 18 +- packages/paste-icons/src/WebCapableIcon.tsx | 18 +- packages/paste-icons/src/ZoomInIcon.tsx | 18 +- .../paste-icons/src/helpers/IconWrapper.tsx | 21 +- packages/paste-icons/src/types/index.ts | 2 +- .../paste-icons/stories/index.stories.tsx | 38 +- .../tools/actions/convertAllAction.ts | 12 +- .../tools/actions/convertNewAction.ts | 26 +- .../tools/actions/listIconsAction.ts | 18 +- packages/paste-icons/tools/cli.ts | 16 +- packages/paste-icons/tools/constants.ts | 20 +- .../tools/templates/buildListTemplate.ts | 2 +- .../tools/templates/jsonTemplate.ts | 2 +- .../tools/templates/reactIconTemplate.ts | 2 +- packages/paste-icons/tools/utils.ts | 22 +- packages/paste-libraries/animation/build.js | 4 +- .../paste-libraries/animation/src/index.tsx | 14 +- .../animation/src/useReducedMotion.tsx | 8 +- .../paste-libraries/clipboard-copy/build.js | 4 +- .../clipboard-copy/src/index.tsx | 4 +- .../clipboard-copy/stories/index.stories.tsx | 26 +- packages/paste-libraries/code-editor/build.js | 4 +- .../code-editor/src/PasteTheme.ts | 730 +- .../paste-libraries/code-editor/src/index.tsx | 6 +- .../stories/diffEditor.stories.tsx | 10 +- .../code-editor/stories/editor.stories.tsx | 12 +- .../__test__/index.spec.tsx | 34 +- .../data-visualization/build.js | 4 +- .../data-visualization/src/index.tsx | 2 +- .../src/usePasteHighchartsTheme.tsx | 20 +- .../stories/index.stories.tsx | 28 +- .../stories/options/basicAreaChartOptions.ts | 22 +- .../stories/options/columnChartOptions.ts | 20 +- .../stories/options/lineChartOptions.ts | 16 +- .../lineChartWithAnnotationsOptions.ts | 80 +- .../stories/options/pieChartOptions.ts | 36 +- .../stories/options/timeSeriesOptions.ts | 25 +- packages/paste-libraries/dropdown/build.js | 4 +- .../paste-libraries/dropdown/src/index.tsx | 6 +- .../dropdown/stories/combobox.stories.tsx | 36 +- .../dropdown/stories/multiselect.stories.tsx | 94 +- packages/paste-libraries/lexical/build.js | 4 +- .../paste-libraries/lexical/src/index.tsx | 46 +- .../lexical/stories/index.stories.tsx | 24 +- .../paste-libraries/react-spectrum/build.js | 4 +- .../react-spectrum/src/index.tsx | 4 +- .../react-spectrum/src/react-aria.tsx | 2 +- .../react-spectrum/src/react-stately.tsx | 2 +- .../stories/useSlider.stories.tsx | 26 +- .../__tests__/index.test.tsx | 146 +- .../react-textarea-autosize/build.js | 4 +- .../src/calculateNodeHeight.ts | 18 +- .../src/forceHiddenStyles.ts | 20 +- .../react-textarea-autosize/src/getHeight.ts | 4 +- .../src/getSizingData.ts | 50 +- .../react-textarea-autosize/src/index.tsx | 44 +- .../src/useHiddenTextarea.tsx | 10 +- .../src/useWindowResizeListener.tsx | 8 +- packages/paste-libraries/reakit/build.js | 4 +- .../reakit/src/Popover/PopoverArrow.tsx | 54 +- .../reakit/src/Popover/__keys.ts | 50 +- .../reakit/src/Tooltip/TooltipArrow.tsx | 18 +- .../reakit/src/Tooltip/__keys.ts | 50 +- packages/paste-libraries/reakit/src/index.tsx | 20 +- .../reakit/stories/composite.stories.tsx | 14 +- packages/paste-libraries/styling/build.js | 4 +- .../src/css-function/__tests__/css.test.ts | 334 +- .../styling/src/css-function/css.ts | 304 +- .../styling/src/css-function/index.ts | 2 +- .../paste-libraries/styling/src/index.tsx | 24 +- .../syntax-highlighter/build.js | 4 +- .../syntax-highlighter/src/index.tsx | 84 +- packages/paste-libraries/uid/build.js | 4 +- packages/paste-libraries/uid/src/index.tsx | 8 +- .../uid/stories/index.stories.tsx | 40 +- packages/paste-style-props/build.js | 4 +- packages/paste-style-props/src/background.ts | 14 +- packages/paste-style-props/src/border.ts | 54 +- packages/paste-style-props/src/constants.ts | 4 +- packages/paste-style-props/src/flexbox.ts | 26 +- packages/paste-style-props/src/grid.ts | 18 +- packages/paste-style-props/src/index.ts | 20 +- packages/paste-style-props/src/layout.ts | 20 +- packages/paste-style-props/src/position.ts | 2 +- packages/paste-style-props/src/shadow.ts | 2 +- packages/paste-style-props/src/space.ts | 58 +- .../paste-style-props/src/types/background.ts | 22 +- .../paste-style-props/src/types/border.ts | 28 +- .../paste-style-props/src/types/css-props.ts | 48 +- .../paste-style-props/src/types/flexbox.ts | 68 +- packages/paste-style-props/src/types/grid.ts | 22 +- .../paste-style-props/src/types/helpers.ts | 2 +- packages/paste-style-props/src/types/index.ts | 20 +- .../paste-style-props/src/types/layout.ts | 78 +- .../paste-style-props/src/types/position.ts | 20 +- .../paste-style-props/src/types/shadow.ts | 8 +- packages/paste-style-props/src/types/space.ts | 8 +- .../paste-style-props/src/types/typography.ts | 44 +- packages/paste-style-props/src/typography.ts | 30 +- .../layout/editor-wrapper/ExportModal.tsx | 30 +- .../layout/editor-wrapper/ImportModal.tsx | 32 +- .../layout/editor-wrapper/TokenSelector.tsx | 18 +- .../layout/editor-wrapper/index.tsx | 20 +- .../components/preview/AlertPreview.tsx | 10 +- .../components/preview/AnchorPreview.tsx | 8 +- .../components/preview/AvatarPreview.tsx | 8 +- .../components/preview/BreadcrumbPreview.tsx | 6 +- .../components/preview/ButtonPreview.tsx | 8 +- .../components/preview/CardPreview.tsx | 22 +- .../components/preview/FormPreview.tsx | 50 +- .../components/preview/MenuPreview.tsx | 8 +- .../components/preview/ModalPreview.tsx | 18 +- .../components/preview/PopoverPreview.tsx | 8 +- .../components/preview/TabbedContent.tsx | 38 +- .../components/preview/TablePreview.tsx | 6 +- .../components/preview/ToastPreview.tsx | 20 +- .../components/preview/TooltipPreview.tsx | 8 +- .../components/preview/TypographyPreview.tsx | 10 +- .../components/preview/index.tsx | 22 +- .../token-option/ColorTokenInput.tsx | 48 +- .../token-option/FontTokenInput.tsx | 20 +- .../token-option/TextTokenInput.tsx | 20 +- .../token-option/UnitTokenInput.tsx | 38 +- .../components/token-option/index.tsx | 48 +- .../components/topbar/BetaBadge.tsx | 18 +- .../components/topbar/BetaModal.tsx | 34 +- .../components/topbar/PasteIconInverse.tsx | 12 +- .../components/topbar/SiteHeaderLogo.tsx | 26 +- .../components/topbar/index.tsx | 8 +- .../paste-theme-designer/constants/Routes.ts | 2 +- .../context/TokenContext.ts | 6 +- packages/paste-theme-designer/pages/_app.tsx | 34 +- .../pages/background-color/index.tsx | 10 +- .../pages/border-color/index.tsx | 10 +- .../pages/border-width/index.tsx | 10 +- .../pages/box-shadow/index.tsx | 10 +- .../pages/font-size/index.tsx | 10 +- .../pages/font-weight/index.tsx | 10 +- .../paste-theme-designer/pages/font/index.tsx | 10 +- packages/paste-theme-designer/pages/index.tsx | 4 +- .../pages/line-height/index.tsx | 10 +- .../pages/radii/index.tsx | 10 +- .../pages/sizing/index.tsx | 10 +- .../pages/spacing/index.tsx | 10 +- .../pages/text-color/index.tsx | 10 +- .../pages/z-index/index.tsx | 10 +- .../utils/SimpleStorage.ts | 2 +- .../__tests__/generateThemeFromTokens.spec.ts | 134 +- .../paste-theme/__tests__/remToPx.spec.ts | 24 +- .../__tests__/themeConsumer.spec.tsx | 26 +- .../__tests__/themeProvider.spec.tsx | 54 +- packages/paste-theme/__tests__/themes.spec.ts | 10 +- .../paste-theme/__tests__/useTheme.spec.tsx | 24 +- .../__tests__/useThemeContrastCheck.spec.tsx | 44 +- .../paste-theme/__tests__/withTheme.spec.tsx | 28 +- packages/paste-theme/build.js | 4 +- packages/paste-theme/src/constants.ts | 14 +- .../src/generateThemeFromTokens.ts | 50 +- .../src/generateTokensFromTheme.ts | 34 +- packages/paste-theme/src/index.tsx | 38 +- packages/paste-theme/src/styles/base.ts | 16 +- packages/paste-theme/src/styles/fonts.ts | 2 +- packages/paste-theme/src/styles/global.ts | 52 +- packages/paste-theme/src/themeConsumer.tsx | 20 +- packages/paste-theme/src/themeProvider.tsx | 36 +- packages/paste-theme/src/themes/dark/index.ts | 16 +- .../paste-theme/src/themes/default/index.ts | 16 +- .../paste-theme/src/themes/evergreen/index.ts | 16 +- packages/paste-theme/src/themes/index.ts | 14 +- .../paste-theme/src/themes/sendgrid/index.ts | 16 +- .../src/themes/twilio-dark/index.ts | 16 +- .../paste-theme/src/themes/twilio/index.ts | 16 +- .../src/types/GenericThemeShape.ts | 14 +- packages/paste-theme/src/types/themes.ts | 12 +- packages/paste-theme/src/useTheme.tsx | 10 +- .../paste-theme/src/useThemeContrastCheck.ts | 8 +- .../paste-theme/src/utils/getThemeFromHash.ts | 4 +- packages/paste-theme/src/utils/remToPx.ts | 8 +- packages/paste-theme/src/withTheme.ts | 4 +- .../stories/cacheProvider.stories.tsx | 24 +- .../stories/evergreenTheme.stories.tsx | 66 +- .../stories/themeProvider.stories.tsx | 22 +- .../.eslintrc.json | 2 +- .../paste-token-contrast-checker/src/App.tsx | 16 +- .../src/components/Form.tsx | 54 +- .../src/components/KitchenSink.tsx | 52 +- .../src/components/Menu.tsx | 6 +- .../src/components/SideBar.tsx | 30 +- .../src/components/ThemeSelector.tsx | 16 +- .../src/components/TokenPairRating.tsx | 38 +- .../src/index.tsx | 14 +- .../src/pages/IndexPage.tsx | 8 +- .../src/reportWebVitals.ts | 8 +- packages/paste-types/build.js | 4 +- packages/paste-types/src/DomTypes.ts | 4 +- packages/paste-types/src/index.ts | 4 +- .../__tests__/useWindowSize.test.tsx | 28 +- packages/paste-utils/build.js | 4 +- .../paste-utils/src/hooks/useMergeRefs.ts | 4 +- .../src/hooks/useMutationObservable.ts | 12 +- .../paste-utils/src/hooks/useWindowSize.ts | 18 +- packages/paste-utils/src/index.ts | 6 +- .../indexes/faiss_index/index.faiss | Bin 11182125 -> 0 bytes .../indexes/faiss_index/index.pkl | Bin 2001684 -> 0 bytes packages/paste-website/next.config.mjs | 20 +- .../plugins/remark-headings-plugin.mjs | 6 +- packages/paste-website/scripts/fetch-data.mjs | 92 +- .../src/__tests__/colorGradient.test.tsx | 54 +- .../src/__tests__/filterGroup.test.tsx | 92 +- .../src/__tests__/genericHeader.test.tsx | 44 +- .../__tests__/packageStatusLegend.test.tsx | 70 +- .../__tests__/tokenAccessiblePairs.test.tsx | 104 +- .../src/__tests__/tokenCard.test.tsx | 80 +- .../src/__tests__/tokensList.test.tsx | 176 +- packages/paste-website/src/assets/Logo.tsx | 10 +- .../animations/homepage-hero-animation.json | 10608 +++++++++++++++- .../src/assets/illustrations/DoodleArrow.tsx | 10 +- .../src/assets/illustrations/DoodleBurst.tsx | 10 +- .../src/assets/illustrations/DoodleCloud.tsx | 10 +- .../src/assets/illustrations/DoodleCurve.tsx | 10 +- .../assets/illustrations/DoodleLoopArrow.tsx | 10 +- .../illustrations/DoodleLoopArrowLarge.tsx | 10 +- .../assets/illustrations/DoodleLoopLarge.tsx | 10 +- .../assets/illustrations/DoodleLoopMedium.tsx | 10 +- .../assets/illustrations/DoodleLoopSmall.tsx | 10 +- .../assets/illustrations/DoodleLoopTiny.tsx | 10 +- .../src/assets/illustrations/DoodleZigzag.tsx | 10 +- .../ChatComposerExamples.tsx | 34 +- .../ColorsFoundationExamples.tsx | 136 +- .../ComboboxPrimitiveExamples.ts | 3 +- .../ConversationsUIKitAnnouncement.tsx | 8 +- .../component-examples/DataGridExamples.ts | 30 +- .../DataVisualizationExamples.tsx | 44 +- .../ModalDialogPrimitiveExample.tsx | 34 +- .../component-examples/StatusMenuExamples.ts | 48 +- .../StatusPatternExamples.tsx | 16 +- .../src/component-examples/ToastExamples.tsx | 26 +- .../filter-group/Examples.tsx | 10 +- .../components/CustomDateFilterGroup.tsx | 88 +- .../components/DateTimePopover.tsx | 46 +- .../components/DefaultFilterGroup.tsx | 48 +- .../filter-group/components/EmptyState.tsx | 14 +- .../components/SampleDataGrid.tsx | 19 +- .../filter-group/constants.ts | 162 +- .../filter-group/helpers.ts | 26 +- .../component-examples/filter-group/types.ts | 18 +- .../paste-website/src/components/Article.tsx | 30 +- .../src/components/ArticleAuthor.tsx | 16 +- .../src/components/ArticleList.tsx | 16 +- .../src/components/Blockquote.tsx | 14 +- .../src/components/BrowserSupport.tsx | 4 +- .../src/components/ContactUsMenu.tsx | 20 +- .../src/components/CookieConsent.tsx | 10 +- .../src/components/CopyButton.tsx | 16 +- .../paste-website/src/components/DoDont.tsx | 24 +- .../components/FormPillVsDisplayPillTable.tsx | 10 +- .../paste-website/src/components/Heading.tsx | 38 +- .../src/components/ImageCaption.tsx | 8 +- .../src/components/PageContentWrapper.tsx | 15 +- .../src/components/PropsTables.tsx | 52 +- .../src/components/ResponsiveImage.tsx | 12 +- .../src/components/Roadmap/Roadmap.tsx | 40 +- .../src/components/Roadmap/RoadmapAside.tsx | 24 +- .../src/components/Roadmap/constants.ts | 8 +- .../src/components/Roadmap/index.ts | 8 +- .../src/components/Roadmap/types.ts | 10 +- .../paste-website/src/components/SiteLink.tsx | 20 +- .../components/SlantedBackgroundGradient.tsx | 24 +- .../src/components/ThemeObjectDisplay.tsx | 12 +- .../src/components/Typography.tsx | 14 +- .../src/components/breadcrumb/index.tsx | 24 +- .../src/components/codeblock/index.tsx | 10 +- .../components/color-swatch/ColorGradient.tsx | 50 +- .../components/color-swatch/ColorSwatch.tsx | 26 +- .../component-overview-table/index.tsx | 32 +- .../component-status/AssetStatus.tsx | 16 +- .../component-status/PeerReviewStatus.tsx | 17 +- .../ComingSoonCard.tsx | 12 +- .../customization-landing-page/FlexCard.tsx | 8 +- .../LandingPageDesigner/ColorTokenInput.tsx | 48 +- .../LandingPageDesigner/DesignerContext.tsx | 6 +- .../LandingPageDesigner/DesignerControls.tsx | 30 +- .../LandingPageDesigner/DesignerPreview.tsx | 40 +- .../LandingPageDesigner/TextToken.tsx | 20 +- .../LandingPageDesigner/UnitTokenInput.tsx | 40 +- .../LandingPageDesigner/index.tsx | 20 +- .../LandingPageHero.tsx | 46 +- .../LandingPageLayoutUtils.tsx | 18 +- .../customization-landing-page/LikeTwilio.tsx | 38 +- .../ProjectCard.tsx | 16 +- .../customization-landing-page/ReactCard.tsx | 8 +- .../ReadyToGetStarted.tsx | 28 +- .../ReasonBlock.tsx | 14 +- .../customization-landing-page/WhyPaste.tsx | 58 +- .../WorksGreatWith.tsx | 42 +- .../image-slider/ImageSlider.tsx | 86 +- .../image-slider/SVGThumb.tsx | 20 +- .../image-slider/index.tsx | 2 +- .../image-slider/useSvgResize.ts | 12 +- .../image-slider/utils.ts | 2 +- .../src/components/empty-state/Error404.tsx | 24 +- .../components/empty-state/InDevelopment.tsx | 30 +- .../src/components/empty-state/NotFound.tsx | 14 +- .../src/components/grid/index.tsx | 4 +- .../src/components/homepage/Experiment.tsx | 64 +- .../homepage/ExperimentMobileButton.tsx | 10 +- .../src/components/homepage/GetStarted.tsx | 26 +- .../components/homepage/GetStartedCard.tsx | 18 +- .../homepage/GetStartedCardIllustration.tsx | 6 +- .../homepage/GetStartedCardLink.tsx | 10 +- .../homepage/GetStartedCardLinks.tsx | 12 +- .../homepage/GetStartedInclusive.tsx | 38 +- .../components/homepage/GetStartedRunning.tsx | 48 +- .../src/components/homepage/GetStartedWhy.tsx | 32 +- .../src/components/homepage/HomeHero.tsx | 64 +- .../homepage/HomeHeroIllustration.tsx | 28 +- .../homepage/NewComponentBanner.tsx | 8 +- .../homepage/NewComponentBannerLink.tsx | 18 +- .../homepage/NewComponentBannerText.tsx | 12 +- .../src/components/homepage/Popular.tsx | 22 +- .../homepage/PopularComponentCard.tsx | 30 +- .../components/homepage/PopularComponents.tsx | 42 +- .../components/homepage/PopularPatterns.tsx | 42 +- .../homepage/PopularSectionHeader.tsx | 22 +- .../src/components/icons-list/IconCard.tsx | 26 +- .../components/icons-list/IconListItem.tsx | 20 +- .../src/components/icons-list/IconTile.tsx | 30 +- .../src/components/icons-list/IconsList.tsx | 72 +- .../src/components/icons-list/index.tsx | 2 +- .../src/components/icons-list/types.ts | 2 +- .../src/components/icons/A11yIcon.tsx | 16 +- .../src/components/icons/Brush.tsx | 10 +- .../src/components/icons/ComponentsIcon.tsx | 10 +- .../src/components/icons/CustomizableIcon.tsx | 16 +- .../src/components/icons/FigmaIcon.tsx | 18 +- .../src/components/icons/GithubIcon.tsx | 34 +- .../src/components/icons/HeartDoodleIcon.tsx | 10 +- .../src/components/icons/PasteIcon.tsx | 20 +- .../src/components/icons/PasteIconPride.tsx | 14 +- .../src/components/icons/PatternsIcon.tsx | 10 +- .../src/components/icons/ReactLogoIcon.tsx | 16 +- .../src/components/icons/StorybookIcon.tsx | 10 +- .../src/components/icons/Terminal.tsx | 10 +- .../src/components/icons/ThemableIcon.tsx | 16 +- .../src/components/icons/TwilioIcon.tsx | 12 +- .../src/components/icons/TwilioLogo.tsx | 41 +- .../src/components/icons/WindowLayout.tsx | 12 +- .../components/images/DatePickerImages.tsx | 46 +- .../components/images/TimePickerImages.tsx | 46 +- .../components/ingredients/Ingredients.tsx | 14 +- .../ingredients/ObjectDetailsIngredients.tsx | 16 +- .../ingredients/ObjectsListIngredients.tsx | 18 +- .../ingredients/SettingsIngredients.tsx | 30 +- .../open-graph-card/AssetStatus.tsx | 16 +- .../open-graph-card/ComponentStatus.tsx | 20 +- .../open-graph-card/GraphImageDetails.tsx | 12 +- .../open-graph-card/GraphImageHero.tsx | 18 +- .../open-graph-card/GraphImageWrapper.tsx | 8 +- .../open-graph-card/PeerReviewStatus.tsx | 12 +- .../src/components/open-graph-card/types.ts | 4 +- .../AccessibilityCallout.tsx | 10 +- .../CustomThemeKeyList.tsx | 4 +- .../customization-provider/FontCallout.tsx | 2 +- .../components/paste-mdx-provider/index.tsx | 90 +- .../components/shortcodes/ArticleHeader.tsx | 24 +- .../components/shortcodes/ArticleLayouts.tsx | 10 +- .../shortcodes/ChangelogRevealer.tsx | 10 +- .../src/components/shortcodes/PageAside.tsx | 24 +- .../components/shortcodes/StoryPreview.tsx | 24 +- .../shortcodes/feedback-popover/index.tsx | 64 +- .../shortcodes/generic-header/index.tsx | 44 +- .../live-preview/CodeBlockOverlayShadow.tsx | 6 +- .../shortcodes/live-preview/ThemeSwitcher.tsx | 24 +- .../shortcodes/live-preview/index.tsx | 46 +- .../shortcodes/live-preview/theme.ts | 78 +- .../normalized-component-header/index.tsx | 12 +- .../normalized-pattern-header/index.tsx | 30 +- .../package-status-legend/index.tsx | 28 +- .../TableOfContentsAnchor.tsx | 16 +- .../table-of-contents/TableOfContentsList.tsx | 8 +- .../TableOfContentsListItem.tsx | 36 +- .../shortcodes/table-of-contents/index.tsx | 54 +- .../shortcodes/table-of-contents/types.ts | 2 +- .../src/components/site-wrapper/SiteBody.tsx | 50 +- .../src/components/site-wrapper/SiteMain.tsx | 8 +- .../src/components/site-wrapper/index.tsx | 12 +- .../site-wrapper/sidebar/SidebarAnchor.tsx | 12 +- .../sidebar/SidebarNavigation.tsx | 150 +- .../site-footer/SiteFooterHeader.tsx | 24 +- .../site-footer/SiteFooterIllustration.tsx | 12 +- .../site-footer/SiteFooterNav.tsx | 100 +- .../site-footer/SiteFooterTopAngle.tsx | 6 +- .../site-wrapper/site-footer/index.tsx | 22 +- .../site-header/DarkModeToggle.tsx | 30 +- .../site-wrapper/site-header/FigmaButton.tsx | 20 +- .../site-header/HamburgerToggle.tsx | 38 +- .../site-header/SiteHeaderLogo.tsx | 40 +- .../site-header/SiteHeaderSearch.tsx | 22 +- .../site-wrapper/site-header/index.tsx | 34 +- .../components/tokens-list/NoTokensFound.tsx | 24 +- .../tokens-list/ScrollToTopLink.tsx | 10 +- .../tokens-list/TokensListFilter.tsx | 38 +- .../src/components/tokens-list/helpers.tsx | 40 +- .../src/components/tokens-list/index.tsx | 102 +- .../components/tokens-list/sectionIntros.tsx | 34 +- .../token-card/AccessiblePairing.tsx | 22 +- .../tokens-list/token-card/index.tsx | 90 +- .../token-example/BorderExample.tsx | 10 +- .../token-card/token-example/BoxExample.tsx | 16 +- .../token-example/IconSizeExample.tsx | 10 +- .../token-example/LineHeightExample.tsx | 14 +- .../token-example/SpacingExample.tsx | 18 +- .../token-example/TextColorExample.tsx | 28 +- .../token-card/token-example/TextExample.tsx | 24 +- .../token-card/token-example/index.tsx | 104 +- .../src/components/tokens-list/types.ts | 28 +- .../src/components/word-list/EmptyState.tsx | 26 +- .../src/components/word-list/WordFilter.tsx | 20 +- .../word-list/__tests__/utils.spec.ts | 44 +- .../src/components/word-list/index.tsx | 24 +- .../src/components/word-list/types.ts | 2 +- .../src/components/word-list/utils.tsx | 2 +- packages/paste-website/src/constants.ts | 94 +- .../src/context/DarkModeContext.tsx | 6 +- .../src/context/NavigationContext.tsx | 6 +- .../src/context/PreviewThemeContext.tsx | 4 +- .../src/functions-utils/logger.ts | 4 +- .../paste-website/src/hooks/useDarkMode.tsx | 16 +- .../paste-website/src/hooks/useWindowSize.tsx | 20 +- .../src/layouts/ComponentPageLayout.tsx | 36 +- .../src/layouts/DefaultLayout.tsx | 18 +- packages/paste-website/src/lib/gtag.ts | 12 +- packages/paste-website/src/pages/_app.tsx | 76 +- .../paste-website/src/pages/_document.tsx | 4 +- packages/paste-website/src/pages/api/ai.ts | 72 +- .../paste-website/src/pages/api/opengraph.ts | 58 +- .../src/pages/customization/index.tsx | 24 +- packages/paste-website/src/pages/index.tsx | 28 +- .../src/pages/opengraph/index.tsx | 72 +- .../paste-website/src/pages/sitemap.xml.tsx | 18 +- .../paste-website/src/styles/docSearch.ts | 188 +- packages/paste-website/src/types/index.ts | 2 +- packages/paste-website/src/utils/DataUtils.ts | 30 +- .../paste-website/src/utils/RouteUtils.ts | 48 +- .../paste-website/src/utils/SimpleStorage.ts | 2 +- .../src/utils/__tests__/DataUtils.spec.ts | 174 +- .../utils/__tests__/componentApiUtils.spec.ts | 70 +- .../src/utils/__tests__/contrastScore.spec.ts | 18 +- packages/paste-website/src/utils/airtable.mjs | 14 +- packages/paste-website/src/utils/api.ts | 82 +- .../utils/color-combos/__test__/index.spec.ts | 198 +- .../src/utils/color-combos/index.ts | 26 +- .../color-rating/__tests__/index.spec.ts | 36 +- .../src/utils/color-rating/index.ts | 12 +- .../src/utils/componentApiUtils.ts | 8 +- .../paste-website/src/utils/contrastScore.ts | 16 +- packages/paste-website/src/utils/inCypress.ts | 2 +- .../stories/AnchoredHeading.stories.tsx | 8 +- .../stories/ColorSwatch.stories.tsx | 14 +- .../stories/FeedbackPopover.stories.tsx | 6 +- .../stories/FigmaButton.stories.tsx | 8 +- .../stories/FilterGroup.stories.tsx | 10 +- .../stories/GenericHeader.stories.tsx | 6 +- .../stories/HamburgerToggle.stories.tsx | 8 +- .../stories/InlineCode.stories.tsx | 14 +- .../stories/LivePreview.stories.tsx | 24 +- .../stories/PackageStatusLegend.stories.tsx | 24 +- .../stories/PropsTable.stories.tsx | 22 +- .../stories/TableOfContents.stories.tsx | 20 +- .../stories/TokenCard.stories.tsx | 134 +- .../stories/TokensListFilter.stories.tsx | 10 +- .../stories/opengraph.stories.tsx | 58 +- .../stories/tokenSectionIntros.stories.tsx | 20 +- performance-benchmarks/alert.stories.tsx | 10 +- performance-benchmarks/box.stories.tsx | 12 +- performance-benchmarks/button.stories.tsx | 10 +- plopfile.js | 104 +- .../paste-nextjs-template/pages/_app.tsx | 6 +- .../paste-nextjs-template/pages/_document.tsx | 2 +- .../paste-nextjs-template/pages/index.tsx | 18 +- tools/build/__tests__/compiledImports.test.ts | 50 +- .../__tests__/generate-type-docs.test.ts | 76 +- tools/build/clean-repo.ts | 2 +- tools/build/esbuild.js | 40 +- tools/build/generate-type-docs/index.ts | 52 +- tools/build/generate-type-docs/utils.ts | 32 +- tools/build/plugins/EsmExternals.js | 24 +- tools/build/plugins/PasteCJSResolver.js | 12 +- tools/build/pre-build.ts | 10 +- tools/build/pre-test.ts | 2 +- tools/build/token-usage-detector.ts | 24 +- tools/build/version.ts | 2 +- tools/test/act-user-event.ts | 4 +- tools/test/react-dom-create-root.ts | 10 +- tools/test/react-testing-library.ts | 8 +- tools/utils/__tests__/runCmd.spec.ts | 28 +- .../utils/calibratePackagePeerDepsVersions.ts | 26 +- tools/utils/getPackageInfo.ts | 4 +- tools/utils/getRepoPackages.ts | 8 +- tools/utils/mkdir.ts | 8 +- tools/utils/removeNodeModules.ts | 8 +- tools/utils/removeTsconfigBuildFiles.ts | 8 +- tools/utils/removeYarnLockfile.ts | 10 +- tools/utils/runCmd.ts | 10 +- .../convertFilePathsToPackageNames.test.ts | 12 +- .../__tests__/getMinimalPackageList.test.ts | 896 +- .../__tests__/getUnusedTokenList.test.ts | 14 +- .../convertFilePathsToPackageNames.ts | 4 +- .../token-usage/getMinimalPackageList.ts | 8 +- .../token-usage/getTokenPackageMapping.ts | 18 +- tools/utils/token-usage/getUnusedTokenList.ts | 2 +- tools/utils/token-usage/types.ts | 4 +- tools/utils/updatePackageCache.ts | 10 +- tools/utils/updatePackageReferences.ts | 135 - tools/utils/writeToFile.ts | 8 +- vite.config.ts | 6 +- yarn.lock | 72 + 1945 files changed, 46195 insertions(+), 35386 deletions(-) create mode 100644 biome.json delete mode 100644 packages/paste-website/indexes/faiss_index/index.faiss delete mode 100644 packages/paste-website/indexes/faiss_index/index.pkl delete mode 100644 tools/utils/updatePackageReferences.ts diff --git a/.changeset/config.json b/.changeset/config.json index 85b288b134..5069042829 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -1,6 +1,6 @@ { "$schema": "https://unpkg.com/@changesets/config@1.4.0/schema.json", - "changelog": ["@changesets/changelog-github", {"repo": "twilio-labs/paste"}], + "changelog": ["@changesets/changelog-github", { "repo": "twilio-labs/paste" }], "commit": false, "linked": [], "access": "public", diff --git a/.danger/__tests__/changesets-that-need-core-check.spec.ts b/.danger/__tests__/changesets-that-need-core-check.spec.ts index 95f4f1ba59..fe6260540c 100644 --- a/.danger/__tests__/changesets-that-need-core-check.spec.ts +++ b/.danger/__tests__/changesets-that-need-core-check.spec.ts @@ -1,42 +1,42 @@ import changesetsThatNeedCoreCheck, { - shouldFlagChangeset, getChangesetsNotTaggingCore, -} from '../changesets-that-need-core-check'; + shouldFlagChangeset, +} from "../changesets-that-need-core-check"; declare const global: any; -describe('shouldFlagChangeset', () => { - it('should not flag icon changesets', () => { - expect(shouldFlagChangeset('./.danger/__fixtures__/changeset/heavy-peaches-repeat.md')).toEqual(false); +describe("shouldFlagChangeset", () => { + it("should not flag icon changesets", () => { + expect(shouldFlagChangeset("./.danger/__fixtures__/changeset/heavy-peaches-repeat.md")).toEqual(false); }); - it('should not flag changesets with core in', () => { - expect(shouldFlagChangeset('./.danger/__fixtures__/changeset/pink-masks-walk.md')).toEqual(false); + it("should not flag changesets with core in", () => { + expect(shouldFlagChangeset("./.danger/__fixtures__/changeset/pink-masks-walk.md")).toEqual(false); }); - it('should flag changesets without core in', () => { - expect(shouldFlagChangeset('./.danger/__fixtures__/changeset/popular-cheetahs-punch.md')).toEqual(true); - expect(shouldFlagChangeset('./.danger/__fixtures__/changeset/pretty-cameras-burn.md')).toEqual(true); + it("should flag changesets without core in", () => { + expect(shouldFlagChangeset("./.danger/__fixtures__/changeset/popular-cheetahs-punch.md")).toEqual(true); + expect(shouldFlagChangeset("./.danger/__fixtures__/changeset/pretty-cameras-burn.md")).toEqual(true); }); }); -describe('getChangesetsNotTaggingCore', () => { - it('should return an array of changesets that do not tag core', () => { +describe("getChangesetsNotTaggingCore", () => { + it("should return an array of changesets that do not tag core", () => { expect( getChangesetsNotTaggingCore([ - './.danger/__fixtures__/changeset/heavy-peaches-repeat.md', - './.danger/__fixtures__/changeset/pink-masks-walk.md', - './.danger/__fixtures__/changeset/popular-cheetahs-punch.md', - './.danger/__fixtures__/changeset/pretty-cameras-burn.md', - ]) + "./.danger/__fixtures__/changeset/heavy-peaches-repeat.md", + "./.danger/__fixtures__/changeset/pink-masks-walk.md", + "./.danger/__fixtures__/changeset/popular-cheetahs-punch.md", + "./.danger/__fixtures__/changeset/pretty-cameras-burn.md", + ]), ).toEqual([ - './.danger/__fixtures__/changeset/popular-cheetahs-punch.md', - './.danger/__fixtures__/changeset/pretty-cameras-burn.md', + "./.danger/__fixtures__/changeset/popular-cheetahs-punch.md", + "./.danger/__fixtures__/changeset/pretty-cameras-burn.md", ]); }); }); -describe('changesetsThatNeedCoreCheck()', () => { +describe("changesetsThatNeedCoreCheck()", () => { beforeEach(() => { global.warn = jest.fn(); global.message = jest.fn(); @@ -52,14 +52,14 @@ describe('changesetsThatNeedCoreCheck()', () => { global.danger = undefined; }); - it('should fail for each modified changeset that does not tag core', () => { + it("should fail for each modified changeset that does not tag core", () => { global.danger = { git: { modified_files: [ - './.danger/__fixtures__/changeset/heavy-peaches-repeat.md', - './.danger/__fixtures__/changeset/pink-masks-walk.md', - './.danger/__fixtures__/changeset/popular-cheetahs-punch.md', - './.danger/__fixtures__/changeset/pretty-cameras-burn.md', + "./.danger/__fixtures__/changeset/heavy-peaches-repeat.md", + "./.danger/__fixtures__/changeset/pink-masks-walk.md", + "./.danger/__fixtures__/changeset/popular-cheetahs-punch.md", + "./.danger/__fixtures__/changeset/pretty-cameras-burn.md", ], created_files: [], }, @@ -68,13 +68,13 @@ describe('changesetsThatNeedCoreCheck()', () => { expect(global.fail).toHaveBeenCalledTimes(2); }); - it('should fail for each created changeset that does not tag core', () => { + it("should fail for each created changeset that does not tag core", () => { global.danger = { git: { modified_files: [], created_files: [ - './.danger/__fixtures__/changeset/pink-masks-walk.md', - './.danger/__fixtures__/changeset/pretty-cameras-burn.md', + "./.danger/__fixtures__/changeset/pink-masks-walk.md", + "./.danger/__fixtures__/changeset/pretty-cameras-burn.md", ], }, }; @@ -82,34 +82,34 @@ describe('changesetsThatNeedCoreCheck()', () => { expect(global.fail).toHaveBeenCalledTimes(1); }); - it('should fail for each modified and created changeset that does not tag core', () => { + it("should fail for each modified and created changeset that does not tag core", () => { global.danger = { git: { modified_files: [ - './.danger/__fixtures__/changeset/heavy-peaches-repeat.md', - './.danger/__fixtures__/changeset/pink-masks-walk.md', - './.danger/__fixtures__/changeset/pretty-cameras-burn.md', + "./.danger/__fixtures__/changeset/heavy-peaches-repeat.md", + "./.danger/__fixtures__/changeset/pink-masks-walk.md", + "./.danger/__fixtures__/changeset/pretty-cameras-burn.md", ], - created_files: ['./.danger/__fixtures__/changeset/popular-cheetahs-punch.md'], + created_files: ["./.danger/__fixtures__/changeset/popular-cheetahs-punch.md"], }, }; changesetsThatNeedCoreCheck(); expect(global.fail).toHaveBeenCalledTimes(2); }); - it('should name the failing changeset that does not tag core', () => { + it("should name the failing changeset that does not tag core", () => { global.danger = { git: { modified_files: [ - './.danger/__fixtures__/changeset/heavy-peaches-repeat.md', - './.danger/__fixtures__/changeset/pink-masks-walk.md', + "./.danger/__fixtures__/changeset/heavy-peaches-repeat.md", + "./.danger/__fixtures__/changeset/pink-masks-walk.md", ], - created_files: ['./.danger/__fixtures__/changeset/popular-cheetahs-punch.md'], + created_files: ["./.danger/__fixtures__/changeset/popular-cheetahs-punch.md"], }, }; changesetsThatNeedCoreCheck(); expect(global.fail).toHaveBeenCalledWith( - 'Changeset ./.danger/__fixtures__/changeset/popular-cheetahs-punch.md does not mention a change to Paste Core. Please include core with this changeset.' + "Changeset ./.danger/__fixtures__/changeset/popular-cheetahs-punch.md does not mention a change to Paste Core. Please include core with this changeset.", ); }); }); diff --git a/.danger/__tests__/missing-changesets-check.spec.ts b/.danger/__tests__/missing-changesets-check.spec.ts index b03c97bd7f..86d6d45716 100644 --- a/.danger/__tests__/missing-changesets-check.spec.ts +++ b/.danger/__tests__/missing-changesets-check.spec.ts @@ -1,85 +1,85 @@ -import missingChangesetCheck, {getMissingPackagesFromChangesets} from '../missing-changesets-check'; +import missingChangesetCheck, { getMissingPackagesFromChangesets } from "../missing-changesets-check"; declare const global: any; const mockPackList = [ { - name: '@twilio-paste/avatar', - version: '0.0.0', + name: "@twilio-paste/avatar", + version: "0.0.0", private: false, - location: '/Users/simon/dev/twilio/design-systems/paste/packages/paste-core/components/avatar', + location: "/Users/simon/dev/twilio/design-systems/paste/packages/paste-core/components/avatar", }, { - name: '@twilio-paste/icons', - version: '0.0.0', + name: "@twilio-paste/icons", + version: "0.0.0", private: false, - location: '/Users/simon/dev/twilio/design-systems/paste/packages/paste-icons', + location: "/Users/simon/dev/twilio/design-systems/paste/packages/paste-icons", }, { - name: '@twilio-paste/core', - version: '0.0.0', + name: "@twilio-paste/core", + version: "0.0.0", private: false, - location: '/Users/simon/dev/twilio/design-systems/paste/packages/paste-core/core-bundle', + location: "/Users/simon/dev/twilio/design-systems/paste/packages/paste-core/core-bundle", }, { - name: '@twilio-paste/box', - version: '0.0.0', + name: "@twilio-paste/box", + version: "0.0.0", private: true, - location: '/Users/simon/dev/twilio/design-systems/paste/packages/paste-core/primitives/box', + location: "/Users/simon/dev/twilio/design-systems/paste/packages/paste-core/primitives/box", }, { - name: '@twilio-paste/design-tokens', - version: '0.0.0', + name: "@twilio-paste/design-tokens", + version: "0.0.0", private: false, - location: '/Users/simon/dev/twilio/design-systems/paste/packages/paste-design-tokens', + location: "/Users/simon/dev/twilio/design-systems/paste/packages/paste-design-tokens", }, ]; -describe('getMissingPackagesFromChangesets()', () => { - it('should not return the names of packages if none are missing from changesets', () => { +describe("getMissingPackagesFromChangesets()", () => { + it("should not return the names of packages if none are missing from changesets", () => { expect( getMissingPackagesFromChangesets( [ - './.danger/__fixtures__/changeset/heavy-peaches-repeat.md', - './.danger/__fixtures__/changeset/pink-masks-walk.md', - './.danger/__fixtures__/changeset/popular-cheetahs-punch.md', - './.danger/__fixtures__/changeset/pretty-cameras-burn.md', + "./.danger/__fixtures__/changeset/heavy-peaches-repeat.md", + "./.danger/__fixtures__/changeset/pink-masks-walk.md", + "./.danger/__fixtures__/changeset/popular-cheetahs-punch.md", + "./.danger/__fixtures__/changeset/pretty-cameras-burn.md", ], - ['@twilio-paste/avatar', '@twilio-paste/box', '@twilio-paste/icons', '@twilio-paste/core'] - ) + ["@twilio-paste/avatar", "@twilio-paste/box", "@twilio-paste/icons", "@twilio-paste/core"], + ), ).toEqual([]); }); - it('should return the names of packages that are missing from changesets', () => { + it("should return the names of packages that are missing from changesets", () => { expect( getMissingPackagesFromChangesets( [ - './.danger/__fixtures__/changeset/heavy-peaches-repeat.md', - './.danger/__fixtures__/changeset/popular-cheetahs-punch.md', - './.danger/__fixtures__/changeset/pretty-cameras-burn.md', + "./.danger/__fixtures__/changeset/heavy-peaches-repeat.md", + "./.danger/__fixtures__/changeset/popular-cheetahs-punch.md", + "./.danger/__fixtures__/changeset/pretty-cameras-burn.md", ], [ - '@twilio-paste/avatar', - '@twilio-paste/box', - '@twilio-paste/icons', - '@twilio-paste/core', - '@twilio-paste/design-tokens', - ] - ) - ).toEqual(['@twilio-paste/core', '@twilio-paste/design-tokens']); + "@twilio-paste/avatar", + "@twilio-paste/box", + "@twilio-paste/icons", + "@twilio-paste/core", + "@twilio-paste/design-tokens", + ], + ), + ).toEqual(["@twilio-paste/core", "@twilio-paste/design-tokens"]); expect( getMissingPackagesFromChangesets( - ['./.danger/__fixtures__/changeset/pretty-cameras-burn.md'], - ['@twilio-paste/avatar', '@twilio-paste/box', '@twilio-paste/icons', '@twilio-paste/core'] - ) - ).toEqual(['@twilio-paste/box', '@twilio-paste/icons', '@twilio-paste/core']); + ["./.danger/__fixtures__/changeset/pretty-cameras-burn.md"], + ["@twilio-paste/avatar", "@twilio-paste/box", "@twilio-paste/icons", "@twilio-paste/core"], + ), + ).toEqual(["@twilio-paste/box", "@twilio-paste/icons", "@twilio-paste/core"]); }); }); -describe('missingChangesetCheck()', () => { +describe("missingChangesetCheck()", () => { beforeEach(() => { global.warn = jest.fn(); global.message = jest.fn(); @@ -95,18 +95,18 @@ describe('missingChangesetCheck()', () => { global.danger = undefined; }); - it('should fail once for a single package that is not in a changeset', () => { + it("should fail once for a single package that is not in a changeset", () => { global.danger = { git: { modified_files: [ - 'package.json', - 'packages/paste-codemods/package.json', - 'packages/paste-icons/src/index.tsx', - 'packages/paste-core/components/avatar/src/index.tsx', - 'packages/paste-core/primitives/box/src/index.tsx', - 'packages/paste-design-tokens/tokens/themes/evergreen/global/background-color.yml', - 'yarn.lock', - './.danger/__fixtures__/changeset/pretty-cameras-burn.md', + "package.json", + "packages/paste-codemods/package.json", + "packages/paste-icons/src/index.tsx", + "packages/paste-core/components/avatar/src/index.tsx", + "packages/paste-core/primitives/box/src/index.tsx", + "packages/paste-design-tokens/tokens/themes/evergreen/global/background-color.yml", + "yarn.lock", + "./.danger/__fixtures__/changeset/pretty-cameras-burn.md", ], created_files: [], }, @@ -115,16 +115,16 @@ describe('missingChangesetCheck()', () => { expect(global.fail).toHaveBeenCalledTimes(2); }); - it('should fail twice for two packages that are not in a changeset', () => { + it("should fail twice for two packages that are not in a changeset", () => { global.danger = { git: { modified_files: [ - 'package.json', - 'packages/paste-codemods/package.json', - 'packages/paste-icons/src/index.tsx', - 'packages/paste-core/components/avatar/src/index.tsx', - 'packages/paste-core/primitives/box/src/index.tsx', - 'yarn.lock', + "package.json", + "packages/paste-codemods/package.json", + "packages/paste-icons/src/index.tsx", + "packages/paste-core/components/avatar/src/index.tsx", + "packages/paste-core/primitives/box/src/index.tsx", + "yarn.lock", ], created_files: [], }, @@ -133,20 +133,20 @@ describe('missingChangesetCheck()', () => { expect(global.fail).toHaveBeenCalledTimes(2); }); - it('should not fail if all packages are covered', () => { + it("should not fail if all packages are covered", () => { global.danger = { git: { modified_files: [ - 'package.json', - 'packages/paste-codemods/package.json', - 'packages/paste-icons/src/index.tsx', - 'packages/paste-core/components/avatar/src/index.tsx', - 'packages/paste-core/primitives/box/src/index.tsx', - 'yarn.lock', - './.danger/__fixtures__/changeset/heavy-peaches-repeat.md', - './.danger/__fixtures__/changeset/pink-masks-walk.md', - './.danger/__fixtures__/changeset/popular-cheetahs-punch.md', - './.danger/__fixtures__/changeset/pretty-cameras-burn.md', + "package.json", + "packages/paste-codemods/package.json", + "packages/paste-icons/src/index.tsx", + "packages/paste-core/components/avatar/src/index.tsx", + "packages/paste-core/primitives/box/src/index.tsx", + "yarn.lock", + "./.danger/__fixtures__/changeset/heavy-peaches-repeat.md", + "./.danger/__fixtures__/changeset/pink-masks-walk.md", + "./.danger/__fixtures__/changeset/popular-cheetahs-punch.md", + "./.danger/__fixtures__/changeset/pretty-cameras-burn.md", ], created_files: [], }, @@ -155,20 +155,20 @@ describe('missingChangesetCheck()', () => { expect(global.fail).toHaveBeenCalledTimes(0); }); - it('should be called with an fail message that lists the missing package that is not in a changeset', () => { + it("should be called with an fail message that lists the missing package that is not in a changeset", () => { global.danger = { git: { modified_files: [ - 'packages/paste-icons/src/index.tsx', - 'packages/paste-core/components/avatar/src/index.tsx', - './.danger/__fixtures__/changeset/pretty-cameras-burn.md', + "packages/paste-icons/src/index.tsx", + "packages/paste-core/components/avatar/src/index.tsx", + "./.danger/__fixtures__/changeset/pretty-cameras-burn.md", ], created_files: [], }, }; missingChangesetCheck(mockPackList); expect(global.fail).toHaveBeenCalledWith( - 'Looks like @twilio-paste/icons was not included in a changeset - *edit an existing changeset or run `yarn changeset` to create one*' + "Looks like @twilio-paste/icons was not included in a changeset - *edit an existing changeset or run `yarn changeset` to create one*", ); }); }); diff --git a/.danger/__tests__/missing-upgrade-guide-check.spec.ts b/.danger/__tests__/missing-upgrade-guide-check.spec.ts index 7690e72efa..e158ffa0f1 100644 --- a/.danger/__tests__/missing-upgrade-guide-check.spec.ts +++ b/.danger/__tests__/missing-upgrade-guide-check.spec.ts @@ -1,7 +1,7 @@ -import missingUpgradeGuideCheck, {UPGRADE_GUIDE_PAGE_FILE, FAIL_MESSAGE} from '../missing-upgrade-guide-check'; +import missingUpgradeGuideCheck, { FAIL_MESSAGE, UPGRADE_GUIDE_PAGE_FILE } from "../missing-upgrade-guide-check"; declare const global: any; -describe('missingUpgradeGuideCheck()', () => { +describe("missingUpgradeGuideCheck()", () => { const expectFail = (): void => { expect(global.fail).toHaveBeenCalledTimes(1); expect(global.fail).toHaveBeenCalledWith(FAIL_MESSAGE); @@ -22,10 +22,10 @@ describe('missingUpgradeGuideCheck()', () => { global.danger = undefined; }); - it('should fail for a modified changeset that sets an update version if the upgrade guide is not also modified', () => { + it("should fail for a modified changeset that sets an update version if the upgrade guide is not also modified", () => { global.danger = { git: { - modified_files: ['./.danger/__fixtures__/changeset/tiny-robot-hands.md'], + modified_files: ["./.danger/__fixtures__/changeset/tiny-robot-hands.md"], created_files: [], }, }; @@ -33,58 +33,58 @@ describe('missingUpgradeGuideCheck()', () => { expectFail(); }); - it('should fail for a created changeset that that sets a major version if the upgrade guide is not also modified', () => { + it("should fail for a created changeset that that sets a major version if the upgrade guide is not also modified", () => { global.danger = { git: { modified_files: [], - created_files: ['./.danger/__fixtures__/changeset/tiny-robot-hands.md'], + created_files: ["./.danger/__fixtures__/changeset/tiny-robot-hands.md"], }, }; missingUpgradeGuideCheck(); expectFail(); }); - it('should fail for a created changeset that that sets a non-core major version if the upgrade guide is not also modified', () => { + it("should fail for a created changeset that that sets a non-core major version if the upgrade guide is not also modified", () => { global.danger = { git: { modified_files: [], - created_files: ['./.danger/__fixtures__/changeset/pretty-cameras-burn.md'], + created_files: ["./.danger/__fixtures__/changeset/pretty-cameras-burn.md"], }, }; missingUpgradeGuideCheck(); expectFail(); }); - it('should not fail for any changeset that bumps a non-core major version and bumps core minor/patch', () => { + it("should not fail for any changeset that bumps a non-core major version and bumps core minor/patch", () => { global.danger = { git: { modified_files: [], - created_files: ['./.danger/__fixtures__/changeset/lost-cradle-unlimited.md'], + created_files: ["./.danger/__fixtures__/changeset/lost-cradle-unlimited.md"], }, }; missingUpgradeGuideCheck(); expect(global.fail).not.toHaveBeenCalled(); }); - it('should not fail for any changeset that sets a major version but DOES include a change to the upgrade guide', () => { + it("should not fail for any changeset that sets a major version but DOES include a change to the upgrade guide", () => { global.danger = { git: { modified_files: [UPGRADE_GUIDE_PAGE_FILE], - created_files: ['./.danger/__fixtures__/changeset/tiny-robot-hands.md'], + created_files: ["./.danger/__fixtures__/changeset/tiny-robot-hands.md"], }, }; missingUpgradeGuideCheck(); expect(global.fail).not.toHaveBeenCalled(); }); - it('should not fail for any changeset that does not set a major version', () => { + it("should not fail for any changeset that does not set a major version", () => { global.danger = { git: { modified_files: [ - './.danger/__fixtures__/changeset/heavy-peaches-repeat.md', - './.danger/__fixtures__/changeset/pink-masks-walk.md', + "./.danger/__fixtures__/changeset/heavy-peaches-repeat.md", + "./.danger/__fixtures__/changeset/pink-masks-walk.md", ], - created_files: ['./.danger/__fixtures__/changeset/popular-cheetahs-punch.md'], + created_files: ["./.danger/__fixtures__/changeset/popular-cheetahs-punch.md"], }, }; missingUpgradeGuideCheck(); diff --git a/.danger/__tests__/package-json-check.spec.ts b/.danger/__tests__/package-json-check.spec.ts index 051a8d3521..0d463d3c52 100644 --- a/.danger/__tests__/package-json-check.spec.ts +++ b/.danger/__tests__/package-json-check.spec.ts @@ -1,8 +1,8 @@ -import packageJsonCheck from '../package-json-check'; +import packageJsonCheck from "../package-json-check"; declare const global: any; -describe('packageJsonCheck()', () => { +describe("packageJsonCheck()", () => { beforeEach(() => { global.warn = jest.fn(); global.message = jest.fn(); @@ -17,20 +17,20 @@ describe('packageJsonCheck()', () => { global.markdown = undefined; }); - describe('checking for missing lockfile updates', () => { + describe("checking for missing lockfile updates", () => { afterEach(() => { global.danger = undefined; }); - it('should not warn when the lockfile is modified', () => { + it("should not warn when the lockfile is modified", () => { global.danger = { git: { modified_files: [ - 'package.json', - 'packages/paste-codemods/package.json', - 'packages/paste-core/components/alert-dialog/stories/index.stories.tsx', - 'yarn.lock', - '.changeset/pretty-cameras-burn.md', + "package.json", + "packages/paste-codemods/package.json", + "packages/paste-core/components/alert-dialog/stories/index.stories.tsx", + "yarn.lock", + ".changeset/pretty-cameras-burn.md", ], created_files: [], }, @@ -38,13 +38,13 @@ describe('packageJsonCheck()', () => { packageJsonCheck(); expect(global.warn).not.toHaveBeenCalled(); }); - it('should not warn when the root package.json is modified', () => { + it("should not warn when the root package.json is modified", () => { global.danger = { git: { modified_files: [ - 'package.json', - 'packages/paste-core/components/alert-dialog/stories/index.stories.tsx', - '.changeset/pretty-cameras-burn.md', + "package.json", + "packages/paste-core/components/alert-dialog/stories/index.stories.tsx", + ".changeset/pretty-cameras-burn.md", ], created_files: [], }, @@ -52,13 +52,13 @@ describe('packageJsonCheck()', () => { packageJsonCheck(); expect(global.warn).not.toHaveBeenCalled(); }); - it('should warn when a package package.json is modified', () => { + it("should warn when a package package.json is modified", () => { global.danger = { git: { modified_files: [ - 'packages/paste-codemods/package.json', - 'packages/paste-core/components/alert-dialog/stories/index.stories.tsx', - '.changeset/pretty-cameras-burn.md', + "packages/paste-codemods/package.json", + "packages/paste-core/components/alert-dialog/stories/index.stories.tsx", + ".changeset/pretty-cameras-burn.md", ], created_files: [], }, @@ -66,28 +66,28 @@ describe('packageJsonCheck()', () => { packageJsonCheck(); expect(global.warn).toHaveBeenCalled(); }); - it('should warn when a new package package.json is created', () => { + it("should warn when a new package package.json is created", () => { global.danger = { git: { modified_files: [ - 'packages/paste-core/components/alert-dialog/stories/index.stories.tsx', - '.changeset/pretty-cameras-burn.md', + "packages/paste-core/components/alert-dialog/stories/index.stories.tsx", + ".changeset/pretty-cameras-burn.md", ], - created_files: ['packages/paste-codemods/package.json'], + created_files: ["packages/paste-codemods/package.json"], }, }; packageJsonCheck(); expect(global.warn).toHaveBeenCalled(); }); - it('should not warn when a new package package.json is created but lockfile is updated', () => { + it("should not warn when a new package package.json is created but lockfile is updated", () => { global.danger = { git: { modified_files: [ - 'packages/paste-core/components/alert-dialog/stories/index.stories.tsx', - '.changeset/pretty-cameras-burn.md', - 'yarn.lock', + "packages/paste-core/components/alert-dialog/stories/index.stories.tsx", + ".changeset/pretty-cameras-burn.md", + "yarn.lock", ], - created_files: ['packages/paste-codemods/package.json'], + created_files: ["packages/paste-codemods/package.json"], }, }; packageJsonCheck(); diff --git a/.danger/__tests__/pin-external-deps.spec.ts b/.danger/__tests__/pin-external-deps.spec.ts index 6cb93a0848..a225521a97 100644 --- a/.danger/__tests__/pin-external-deps.spec.ts +++ b/.danger/__tests__/pin-external-deps.spec.ts @@ -1,51 +1,51 @@ import pinExternalDeps, { getUnPinnedExternalDepsFromPackageJSONFiles, getUnpinnedExternalDeps, -} from '../pin-external-deps'; +} from "../pin-external-deps"; declare const global: any; -describe('pin external dependencies check', () => { - describe('getUnpinnedExternalDeps()', () => { - it('should return the names of external deps that are not pinned', () => { - expect(getUnpinnedExternalDeps({lodash: '^4.17.21'})).toEqual(['lodash']); - expect(getUnpinnedExternalDeps({csstype: '3.0.11', lodash: '^4.17.21'})).toEqual(['lodash']); - expect(getUnpinnedExternalDeps({csstype: '^3.0.11', lodash: '^4.17.21'})).toEqual(['csstype', 'lodash']); - expect(getUnpinnedExternalDeps({csstype: '3.0.11'})).toEqual([]); +describe("pin external dependencies check", () => { + describe("getUnpinnedExternalDeps()", () => { + it("should return the names of external deps that are not pinned", () => { + expect(getUnpinnedExternalDeps({ lodash: "^4.17.21" })).toEqual(["lodash"]); + expect(getUnpinnedExternalDeps({ csstype: "3.0.11", lodash: "^4.17.21" })).toEqual(["lodash"]); + expect(getUnpinnedExternalDeps({ csstype: "^3.0.11", lodash: "^4.17.21" })).toEqual(["csstype", "lodash"]); + expect(getUnpinnedExternalDeps({ csstype: "3.0.11" })).toEqual([]); }); }); - describe('getUnPinnedExternalDepsFromPackageJSONFiles()', () => { - it('should return an array of all the unpinned external deps across every provided package.json file', () => { + describe("getUnPinnedExternalDepsFromPackageJSONFiles()", () => { + it("should return an array of all the unpinned external deps across every provided package.json file", () => { expect( - getUnPinnedExternalDepsFromPackageJSONFiles(['./.danger/__fixtures__/mock_package/package.json']) + getUnPinnedExternalDepsFromPackageJSONFiles(["./.danger/__fixtures__/mock_package/package.json"]), ).toMatchSnapshot(); expect( - getUnPinnedExternalDepsFromPackageJSONFiles(['./.danger/__fixtures__/mock_package_2/package.json']) + getUnPinnedExternalDepsFromPackageJSONFiles(["./.danger/__fixtures__/mock_package_2/package.json"]), ).toMatchSnapshot(); expect( - getUnPinnedExternalDepsFromPackageJSONFiles(['./.danger/__fixtures__/mock_package_3/package.json']) + getUnPinnedExternalDepsFromPackageJSONFiles(["./.danger/__fixtures__/mock_package_3/package.json"]), ).toMatchSnapshot(); expect( getUnPinnedExternalDepsFromPackageJSONFiles([ - './.danger/__fixtures__/mock_package/package.json', - './.danger/__fixtures__/mock_package_3/package.json', - ]) + "./.danger/__fixtures__/mock_package/package.json", + "./.danger/__fixtures__/mock_package_3/package.json", + ]), ).toMatchSnapshot(); expect( getUnPinnedExternalDepsFromPackageJSONFiles([ - './.danger/__fixtures__/mock_package/package.json', - './.danger/__fixtures__/mock_package_2/package.json', - './.danger/__fixtures__/mock_package_3/package.json', - ]) + "./.danger/__fixtures__/mock_package/package.json", + "./.danger/__fixtures__/mock_package_2/package.json", + "./.danger/__fixtures__/mock_package_3/package.json", + ]), ).toMatchSnapshot(); }); }); - describe('pinExternalDeps()', () => { + describe("pinExternalDeps()", () => { beforeEach(() => { global.warn = jest.fn(); global.message = jest.fn(); @@ -61,10 +61,10 @@ describe('pin external dependencies check', () => { global.danger = undefined; }); - it('should not fail when there are not unpinned external deps', () => { + it("should not fail when there are not unpinned external deps", () => { global.danger = { git: { - modified_files: ['./.danger/__fixtures__/mock_package_3/package.json'], + modified_files: ["./.danger/__fixtures__/mock_package_3/package.json"], created_files: [], }, }; @@ -72,10 +72,10 @@ describe('pin external dependencies check', () => { expect(global.fail).not.toHaveBeenCalled(); }); - it('should fail when there are unpinned external deps', () => { + it("should fail when there are unpinned external deps", () => { global.danger = { git: { - modified_files: ['./.danger/__fixtures__/mock_package_2/package.json'], + modified_files: ["./.danger/__fixtures__/mock_package_2/package.json"], created_files: [], }, }; @@ -83,10 +83,10 @@ describe('pin external dependencies check', () => { expect(global.fail).toHaveBeenCalled(); }); - it('should fail even when there are mixed pinned and unpinned external deps', () => { + it("should fail even when there are mixed pinned and unpinned external deps", () => { global.danger = { git: { - modified_files: ['./.danger/__fixtures__/mock_package/package.json'], + modified_files: ["./.danger/__fixtures__/mock_package/package.json"], created_files: [], }, }; diff --git a/.danger/__tests__/utils.spec.ts b/.danger/__tests__/utils.spec.ts index d618b5c48f..1a0de79d3e 100644 --- a/.danger/__tests__/utils.spec.ts +++ b/.danger/__tests__/utils.spec.ts @@ -1,332 +1,332 @@ import { - getPublicPackages, - getRepoPackagePath, - getPackagePaths, - getPublicPackageFilesFromFiles, getChangesetsFromFiles, getPackJsonsFromFiles, getPackageNameFromPath, + getPackagePaths, + getPublicPackageFilesFromFiles, + getPublicPackages, + getRepoPackagePath, getUnpublishedPackageNames, -} from '../utils'; +} from "../utils"; -describe('danger utils', () => { - describe('getPublicPackages', () => { - it('should only return public packages', () => { +describe("danger utils", () => { + describe("getPublicPackages", () => { + it("should only return public packages", () => { expect( getPublicPackages([ { - name: '@twilio-paste/style-props', - version: '3.1.0', + name: "@twilio-paste/style-props", + version: "3.1.0", private: false, - location: '/Users/simon/dev/twilio/design-systems/paste/packages/paste-style-props', + location: "/Users/simon/dev/twilio/design-systems/paste/packages/paste-style-props", }, - ]) + ]), ).toEqual([ { - name: '@twilio-paste/style-props', - version: '3.1.0', + name: "@twilio-paste/style-props", + version: "3.1.0", private: false, - location: '/Users/simon/dev/twilio/design-systems/paste/packages/paste-style-props', + location: "/Users/simon/dev/twilio/design-systems/paste/packages/paste-style-props", }, ]); expect( getPublicPackages([ { - name: '@twilio-paste/private', - version: '3.1.0', + name: "@twilio-paste/private", + version: "3.1.0", private: true, - location: '/Users/simon/dev/twilio/design-systems/paste/packages/paste-style-props', + location: "/Users/simon/dev/twilio/design-systems/paste/packages/paste-style-props", }, { - name: '@twilio-paste/public', - version: '3.1.0', + name: "@twilio-paste/public", + version: "3.1.0", private: false, - location: '/Users/simon/dev/twilio/design-systems/paste/packages/paste-style-props', + location: "/Users/simon/dev/twilio/design-systems/paste/packages/paste-style-props", }, - ]) + ]), ).toEqual([ { - name: '@twilio-paste/public', - version: '3.1.0', + name: "@twilio-paste/public", + version: "3.1.0", private: false, - location: '/Users/simon/dev/twilio/design-systems/paste/packages/paste-style-props', + location: "/Users/simon/dev/twilio/design-systems/paste/packages/paste-style-props", }, ]); expect( getPublicPackages([ { - name: '@twilio-paste/private', - version: '3.1.0', + name: "@twilio-paste/private", + version: "3.1.0", private: true, - location: '/Users/simon/dev/twilio/design-systems/paste/packages/paste-style-props', + location: "/Users/simon/dev/twilio/design-systems/paste/packages/paste-style-props", }, - ]) + ]), ).toEqual([]); }); }); - describe('getRepoPackagePath', () => { - it('should return a file path after and including the packages/', () => { - expect(getRepoPackagePath('/Users/simon/dev/twilio/design-systems/paste/packages/paste-style-props')).toEqual( - 'packages/paste-style-props' + describe("getRepoPackagePath", () => { + it("should return a file path after and including the packages/", () => { + expect(getRepoPackagePath("/Users/simon/dev/twilio/design-systems/paste/packages/paste-style-props")).toEqual( + "packages/paste-style-props", ); - expect(getRepoPackagePath('/dev/twilio/design-systems/paste/packages/paste-style-props')).toEqual( - 'packages/paste-style-props' + expect(getRepoPackagePath("/dev/twilio/design-systems/paste/packages/paste-style-props")).toEqual( + "packages/paste-style-props", ); - expect(getRepoPackagePath('paste/packages/paste-style-props')).toEqual('packages/paste-style-props'); - expect(getRepoPackagePath('/design-systems/paste/packages/paste-style-props/foo/bar')).toEqual( - 'packages/paste-style-props/foo/bar' + expect(getRepoPackagePath("paste/packages/paste-style-props")).toEqual("packages/paste-style-props"); + expect(getRepoPackagePath("/design-systems/paste/packages/paste-style-props/foo/bar")).toEqual( + "packages/paste-style-props/foo/bar", ); - expect(getRepoPackagePath('packages/paste-style-props/foo/')).toEqual('packages/paste-style-props/foo/'); + expect(getRepoPackagePath("packages/paste-style-props/foo/")).toEqual("packages/paste-style-props/foo/"); }); }); - describe('getPackagePaths', () => { - it('should return a string array of files paths relative to the root of the repo', () => { + describe("getPackagePaths", () => { + it("should return a string array of files paths relative to the root of the repo", () => { expect( getPackagePaths([ { - name: '@twilio-paste/private', - version: '3.1.0', + name: "@twilio-paste/private", + version: "3.1.0", private: true, - location: '/Users/simon/dev/twilio/design-systems/paste/packages/box', + location: "/Users/simon/dev/twilio/design-systems/paste/packages/box", }, { - name: '@twilio-paste/public', - version: '3.1.0', + name: "@twilio-paste/public", + version: "3.1.0", private: false, - location: '/Users/simon/dev/twilio/design-systems/paste/packages/paste-style-props', + location: "/Users/simon/dev/twilio/design-systems/paste/packages/paste-style-props", }, - ]) - ).toEqual(['packages/box', 'packages/paste-style-props']); + ]), + ).toEqual(["packages/box", "packages/paste-style-props"]); }); }); - describe('getPublicPackageFilesFromFiles', () => { - it('should only return files that are in public package folders', () => { + describe("getPublicPackageFilesFromFiles", () => { + it("should only return files that are in public package folders", () => { expect( getPublicPackageFilesFromFiles( [ - 'package.json', - 'packages/box/package.json', - 'packages/paste-core/components/alert-dialog/stories/index.stories.tsx', - 'yarn.lock', - '.changeset/pretty-cameras-burn.md', + "package.json", + "packages/box/package.json", + "packages/paste-core/components/alert-dialog/stories/index.stories.tsx", + "yarn.lock", + ".changeset/pretty-cameras-burn.md", ], - ['packages/box', 'packages/paste-core/components/alert-dialog'] - ) - ).toEqual(['packages/box/package.json', 'packages/paste-core/components/alert-dialog/stories/index.stories.tsx']); + ["packages/box", "packages/paste-core/components/alert-dialog"], + ), + ).toEqual(["packages/box/package.json", "packages/paste-core/components/alert-dialog/stories/index.stories.tsx"]); expect( getPublicPackageFilesFromFiles( - ['package.json', 'yarn.lock', '.changeset/pretty-cameras-burn.md'], - ['packages/box', 'packages/paste-core/components/alert-dialog'] - ) + ["package.json", "yarn.lock", ".changeset/pretty-cameras-burn.md"], + ["packages/box", "packages/paste-core/components/alert-dialog"], + ), ).toEqual([]); }); }); - describe('getPackageNameFromPath', () => { - it('should return the name of a package a file belongs to', () => { + describe("getPackageNameFromPath", () => { + it("should return the name of a package a file belongs to", () => { expect( - getPackageNameFromPath('packages/box/package.json', [ + getPackageNameFromPath("packages/box/package.json", [ { - name: '@twilio-paste/private', - version: '3.1.0', + name: "@twilio-paste/private", + version: "3.1.0", private: true, - location: '/Users/simon/dev/twilio/design-systems/paste/packages/box', + location: "/Users/simon/dev/twilio/design-systems/paste/packages/box", }, { - name: '@twilio-paste/public', - version: '3.1.0', + name: "@twilio-paste/public", + version: "3.1.0", private: false, - location: '/Users/simon/dev/twilio/design-systems/paste/packages/paste-style-props', + location: "/Users/simon/dev/twilio/design-systems/paste/packages/paste-style-props", }, - ]) - ).toEqual('@twilio-paste/private'); + ]), + ).toEqual("@twilio-paste/private"); }); }); - describe('getUnpublishedPackageNames', () => { - it('should return an empty list if no files are in src', () => { + describe("getUnpublishedPackageNames", () => { + it("should return an empty list if no files are in src", () => { expect( getUnpublishedPackageNames( [ - 'package.json', - 'packages/box/package.json', - 'packages/paste-core/components/alert-dialog/stories/index.stories.tsx', - 'yarn.lock', - '.changeset/pretty-cameras-burn.md', + "package.json", + "packages/box/package.json", + "packages/paste-core/components/alert-dialog/stories/index.stories.tsx", + "yarn.lock", + ".changeset/pretty-cameras-burn.md", ], [ { - name: '@twilio-paste/alert-dialog', - version: '3.1.0', + name: "@twilio-paste/alert-dialog", + version: "3.1.0", private: false, - location: '/Users/simon/dev/twilio/design-systems/paste/packages/paste-core/components/alert-dialog', + location: "/Users/simon/dev/twilio/design-systems/paste/packages/paste-core/components/alert-dialog", }, { - name: '@twilio-paste/style-props', - version: '3.1.0', + name: "@twilio-paste/style-props", + version: "3.1.0", private: false, - location: '/Users/simon/dev/twilio/design-systems/paste/packages/paste-style-props', + location: "/Users/simon/dev/twilio/design-systems/paste/packages/paste-style-props", }, - ] - ) + ], + ), ).toEqual([]); }); - it('should return the names of packages with src files updated', () => { + it("should return the names of packages with src files updated", () => { expect( getUnpublishedPackageNames( [ - 'package.json', - 'packages/paste-style-props/src/index.ts', - 'packages/paste-core/components/alert-dialog/stories/index.stories.tsx', - 'yarn.lock', - '.changeset/pretty-cameras-burn.md', + "package.json", + "packages/paste-style-props/src/index.ts", + "packages/paste-core/components/alert-dialog/stories/index.stories.tsx", + "yarn.lock", + ".changeset/pretty-cameras-burn.md", ], [ { - name: '@twilio-paste/alert-dialog', - version: '3.1.0', + name: "@twilio-paste/alert-dialog", + version: "3.1.0", private: false, - location: '/Users/simon/dev/twilio/design-systems/paste/packages/paste-core/components/alert-dialog', + location: "/Users/simon/dev/twilio/design-systems/paste/packages/paste-core/components/alert-dialog", }, { - name: '@twilio-paste/style-props', - version: '3.1.0', + name: "@twilio-paste/style-props", + version: "3.1.0", private: false, - location: '/Users/simon/dev/twilio/design-systems/paste/packages/paste-style-props', + location: "/Users/simon/dev/twilio/design-systems/paste/packages/paste-style-props", }, - ] - ) - ).toEqual(['@twilio-paste/style-props']); + ], + ), + ).toEqual(["@twilio-paste/style-props"]); expect( getUnpublishedPackageNames( [ - 'package.json', - 'packages/paste-style-props/src/index.ts', - 'packages/paste-core/components/alert-dialog/stories/index.stories.tsx', - 'packages/paste-core/components/alert-dialog/src/index.tsx', - 'yarn.lock', - '.changeset/pretty-cameras-burn.md', + "package.json", + "packages/paste-style-props/src/index.ts", + "packages/paste-core/components/alert-dialog/stories/index.stories.tsx", + "packages/paste-core/components/alert-dialog/src/index.tsx", + "yarn.lock", + ".changeset/pretty-cameras-burn.md", ], [ { - name: '@twilio-paste/alert-dialog', - version: '3.1.0', + name: "@twilio-paste/alert-dialog", + version: "3.1.0", private: false, - location: '/Users/simon/dev/twilio/design-systems/paste/packages/paste-core/components/alert-dialog', + location: "/Users/simon/dev/twilio/design-systems/paste/packages/paste-core/components/alert-dialog", }, { - name: '@twilio-paste/style-props', - version: '3.1.0', + name: "@twilio-paste/style-props", + version: "3.1.0", private: false, - location: '/Users/simon/dev/twilio/design-systems/paste/packages/paste-style-props', + location: "/Users/simon/dev/twilio/design-systems/paste/packages/paste-style-props", }, - ] - ) - ).toEqual(['@twilio-paste/style-props', '@twilio-paste/alert-dialog']); + ], + ), + ).toEqual(["@twilio-paste/style-props", "@twilio-paste/alert-dialog"]); }); - it('should return the design-tokens and codemods package with even though no src files are updated', () => { + it("should return the design-tokens and codemods package with even though no src files are updated", () => { expect( getUnpublishedPackageNames( [ - 'package.json', - 'packages/paste-style-props/src/index.ts', - 'packages/paste-core/components/alert-dialog/stories/index.stories.tsx', - 'packages/paste-design-tokens/tokens/themes/evergreen/global/background-color.yml', - 'packages/paste-codemods/tools/.cache/mappings.json', - 'yarn.lock', - '.changeset/pretty-cameras-burn.md', + "package.json", + "packages/paste-style-props/src/index.ts", + "packages/paste-core/components/alert-dialog/stories/index.stories.tsx", + "packages/paste-design-tokens/tokens/themes/evergreen/global/background-color.yml", + "packages/paste-codemods/tools/.cache/mappings.json", + "yarn.lock", + ".changeset/pretty-cameras-burn.md", ], [ { - name: '@twilio-paste/alert-dialog', - version: '3.1.0', + name: "@twilio-paste/alert-dialog", + version: "3.1.0", private: false, - location: '/Users/simon/dev/twilio/design-systems/paste/packages/paste-core/components/alert-dialog', + location: "/Users/simon/dev/twilio/design-systems/paste/packages/paste-core/components/alert-dialog", }, { - name: '@twilio-paste/style-props', - version: '3.1.0', + name: "@twilio-paste/style-props", + version: "3.1.0", private: false, - location: '/Users/simon/dev/twilio/design-systems/paste/packages/paste-style-props', + location: "/Users/simon/dev/twilio/design-systems/paste/packages/paste-style-props", }, { - name: '@twilio-paste/design-tokens', - version: '3.1.0', + name: "@twilio-paste/design-tokens", + version: "3.1.0", private: false, - location: '/Users/simon/dev/twilio/design-systems/paste/packages/paste-design-tokens', + location: "/Users/simon/dev/twilio/design-systems/paste/packages/paste-design-tokens", }, { - name: '@twilio-paste/codemods', - version: '3.1.0', + name: "@twilio-paste/codemods", + version: "3.1.0", private: false, - location: '/Users/simon/dev/twilio/design-systems/paste/packages/paste-codemods', + location: "/Users/simon/dev/twilio/design-systems/paste/packages/paste-codemods", }, - ] - ) - ).toEqual(['@twilio-paste/style-props', '@twilio-paste/design-tokens', '@twilio-paste/codemods']); + ], + ), + ).toEqual(["@twilio-paste/style-props", "@twilio-paste/design-tokens", "@twilio-paste/codemods"]); }); }); - describe('getChangesetsFromFiles', () => { - it('should return the changesets from a change list', () => { + describe("getChangesetsFromFiles", () => { + it("should return the changesets from a change list", () => { expect( getChangesetsFromFiles([ - 'package.json', - 'packages/box/package.json', - 'packages/paste-core/components/alert-dialog/stories/index.stories.tsx', - 'yarn.lock', - '.changeset/pretty-cameras-burn.md', - ]) - ).toEqual(['.changeset/pretty-cameras-burn.md']); + "package.json", + "packages/box/package.json", + "packages/paste-core/components/alert-dialog/stories/index.stories.tsx", + "yarn.lock", + ".changeset/pretty-cameras-burn.md", + ]), + ).toEqual([".changeset/pretty-cameras-burn.md"]); }); - it('should return a list of more than one changesets from a change list', () => { + it("should return a list of more than one changesets from a change list", () => { expect( getChangesetsFromFiles([ - 'package.json', - 'packages/box/package.json', - 'packages/paste-core/components/alert-dialog/stories/index.stories.tsx', - 'yarn.lock', - '.changeset/pretty-cameras-burn.md', - '.changeset/pretty-silly-sheep.md', - ]) - ).toEqual(['.changeset/pretty-cameras-burn.md', '.changeset/pretty-silly-sheep.md']); + "package.json", + "packages/box/package.json", + "packages/paste-core/components/alert-dialog/stories/index.stories.tsx", + "yarn.lock", + ".changeset/pretty-cameras-burn.md", + ".changeset/pretty-silly-sheep.md", + ]), + ).toEqual([".changeset/pretty-cameras-burn.md", ".changeset/pretty-silly-sheep.md"]); }); }); - describe('getPackJsonsFromFiles', () => { - it('should return package json files from a changelist', () => { + describe("getPackJsonsFromFiles", () => { + it("should return package json files from a changelist", () => { expect( getPackJsonsFromFiles([ - 'package.json', - 'packages/paste-core/components/alert-dialog/package.json', - 'packages/paste-core/components/alert-dialog/stories/index.stories.tsx', - 'yarn.lock', - '.changeset/pretty-cameras-burn.md', - ]) - ).toEqual(['packages/paste-core/components/alert-dialog/package.json']); + "package.json", + "packages/paste-core/components/alert-dialog/package.json", + "packages/paste-core/components/alert-dialog/stories/index.stories.tsx", + "yarn.lock", + ".changeset/pretty-cameras-burn.md", + ]), + ).toEqual(["packages/paste-core/components/alert-dialog/package.json"]); }); - it('should return more than one package json file from a changelist', () => { + it("should return more than one package json file from a changelist", () => { expect( getPackJsonsFromFiles([ - 'package.json', - 'packages/paste-core/components/alert-dialog/package.json', - 'packages/box/package.json', - 'packages/paste-core/components/alert-dialog/stories/index.stories.tsx', - 'yarn.lock', - '.changeset/pretty-cameras-burn.md', - ]) - ).toEqual(['packages/paste-core/components/alert-dialog/package.json', 'packages/box/package.json']); + "package.json", + "packages/paste-core/components/alert-dialog/package.json", + "packages/box/package.json", + "packages/paste-core/components/alert-dialog/stories/index.stories.tsx", + "yarn.lock", + ".changeset/pretty-cameras-burn.md", + ]), + ).toEqual(["packages/paste-core/components/alert-dialog/package.json", "packages/box/package.json"]); }); }); }); diff --git a/.danger/__tests__/website-page-vrt-check.spec.ts b/.danger/__tests__/website-page-vrt-check.spec.ts index dd542faa9e..541ee915d0 100644 --- a/.danger/__tests__/website-page-vrt-check.spec.ts +++ b/.danger/__tests__/website-page-vrt-check.spec.ts @@ -1,8 +1,8 @@ -import websitePageVrtCheck, {FAIL_MESSAGE} from '../website-page-vrt-check'; +import websitePageVrtCheck, { FAIL_MESSAGE } from "../website-page-vrt-check"; declare const global: any; -describe('websitePageVrtCheck()', () => { +describe("websitePageVrtCheck()", () => { beforeEach(() => { global.warn = jest.fn(); global.message = jest.fn(); @@ -17,26 +17,26 @@ describe('websitePageVrtCheck()', () => { global.markdown = undefined; }); - describe('checking for missing vrt updates', () => { + describe("checking for missing vrt updates", () => { afterEach(() => { global.danger = undefined; }); - it('should fail when new website pages are created without a sitemap vrt modification', () => { + it("should fail when new website pages are created without a sitemap vrt modification", () => { global.danger = { git: { modified_files: [], - created_files: ['packages/paste-website/src/pages/index.tsx'], + created_files: ["packages/paste-website/src/pages/index.tsx"], }, }; websitePageVrtCheck(); expect(global.fail).toHaveBeenCalledWith(FAIL_MESSAGE); }); - it('should not fail when no new website pages are created', () => { + it("should not fail when no new website pages are created", () => { global.danger = { git: { - modified_files: ['cypress/integration/sitemap-vrt/constants.ts'], + modified_files: ["cypress/integration/sitemap-vrt/constants.ts"], created_files: [], }, }; @@ -44,11 +44,11 @@ describe('websitePageVrtCheck()', () => { expect(global.fail).not.toHaveBeenCalled(); }); - it('should not fail when new website pages are created with a sitemap vrt modification', () => { + it("should not fail when new website pages are created with a sitemap vrt modification", () => { global.danger = { git: { - modified_files: ['cypress/integration/sitemap-vrt/constants.ts'], - created_files: ['packages/paste-website/src/pages/index.tsx'], + modified_files: ["cypress/integration/sitemap-vrt/constants.ts"], + created_files: ["packages/paste-website/src/pages/index.tsx"], }, }; websitePageVrtCheck(); diff --git a/.danger/changesets-that-need-core-check.ts b/.danger/changesets-that-need-core-check.ts index 5f5d4f9ab0..26f544593f 100644 --- a/.danger/changesets-that-need-core-check.ts +++ b/.danger/changesets-that-need-core-check.ts @@ -1,20 +1,20 @@ -import * as fs from 'fs'; -import {getChangesetsFromFiles} from './utils'; +import * as fs from "fs"; // you kind of have to treat Danger plugins as global? // https://danger.systems/js/usage/extending-danger.html#writing-your-plugin -import {DangerDSLType} from 'danger/distribution/dsl/DangerDSL'; +import { DangerDSLType } from "danger/distribution/dsl/DangerDSL"; +import { getChangesetsFromFiles } from "./utils"; declare const danger: DangerDSLType; export declare function fail(message: string): void; const IGNORE_LIST = [ - '@twilio-paste/core', - '@twilio-paste/icons', - '@twilio-paste/website', - '@twilio-paste/codemods', - '@twilio-paste/nextjs-template', - '@twilio-paste/theme-designer', - '@twilio-paste/color-contrast-utils', - '@twilio-paste/token-contrast-checker', + "@twilio-paste/core", + "@twilio-paste/icons", + "@twilio-paste/website", + "@twilio-paste/codemods", + "@twilio-paste/nextjs-template", + "@twilio-paste/theme-designer", + "@twilio-paste/color-contrast-utils", + "@twilio-paste/token-contrast-checker", ]; /** diff --git a/.danger/missing-changesets-check.ts b/.danger/missing-changesets-check.ts index 4529d57fbf..49f8245e14 100644 --- a/.danger/missing-changesets-check.ts +++ b/.danger/missing-changesets-check.ts @@ -1,19 +1,19 @@ -import * as fs from 'fs'; +import * as fs from "fs"; +// you kind of have to treat Danger plugins as global? +// https://danger.systems/js/usage/extending-danger.html#writing-your-plugin +import { DangerDSLType } from "danger/distribution/dsl/DangerDSL"; +import type { PackageShape } from "../tools/utils/getRepoPackages"; import { getChangesetsFromFiles, - getPublicPackageFilesFromFiles, getPackagePaths, + getPublicPackageFilesFromFiles, getPublicPackages, getUnpublishedPackageNames, -} from './utils'; -import type {PackageShape} from '../tools/utils/getRepoPackages'; -// you kind of have to treat Danger plugins as global? -// https://danger.systems/js/usage/extending-danger.html#writing-your-plugin -import {DangerDSLType} from 'danger/distribution/dsl/DangerDSL'; +} from "./utils"; declare const danger: DangerDSLType; export declare function fail(message: string): void; -const difference = require('lodash/difference'); +const difference = require("lodash/difference"); /** * Utility to return the difference between the packages we know were changed in the PR based on files, and the packages @@ -51,7 +51,7 @@ export default (packageList: PackageShape[]) => { /** List of public packages that have changes in src files, that will need to be published */ const publicPackagesWithUnpublishedSourceChanges = getUnpublishedPackageNames( modifiedPublicPackageFiles, - publicPackages + publicPackages, ); /** Modified Changeset files */ @@ -63,9 +63,9 @@ export default (packageList: PackageShape[]) => { if (modifiedPublicPackageFiles.length > 0) { const missingPackages = getMissingPackagesFromChangesets( modifiedChangeSetFiles, - publicPackagesWithUnpublishedSourceChanges + publicPackagesWithUnpublishedSourceChanges, ); - const idea = 'edit an existing changeset or run `yarn changeset` to create one'; + const idea = "edit an existing changeset or run `yarn changeset` to create one"; if (missingPackages.length > 0) { missingPackages.forEach((packageName: string) => { fail(`Looks like ${packageName} was not included in a changeset - *${idea}*`); diff --git a/.danger/missing-upgrade-guide-check.ts b/.danger/missing-upgrade-guide-check.ts index b5d500fd93..db672fd40c 100644 --- a/.danger/missing-upgrade-guide-check.ts +++ b/.danger/missing-upgrade-guide-check.ts @@ -1,13 +1,13 @@ -import * as fs from 'fs'; -import {getChangesetsFromFiles} from './utils'; +import * as fs from "fs"; // you kind of have to treat Danger plugins as global? // https://danger.systems/js/usage/extending-danger.html#writing-your-plugin -import {DangerDSLType} from 'danger/distribution/dsl/DangerDSL'; +import { DangerDSLType } from "danger/distribution/dsl/DangerDSL"; +import { getChangesetsFromFiles } from "./utils"; declare const danger: DangerDSLType; export declare function fail(message: string): void; /** location in the repo where the upgrade guide lives */ -export const UPGRADE_GUIDE_PAGE_FILE = 'packages/paste-website/src/pages/core/upgrade-guide.mdx'; +export const UPGRADE_GUIDE_PAGE_FILE = "packages/paste-website/src/pages/core/upgrade-guide.mdx"; export const FAIL_MESSAGE = `You have marked a Paste package as a MAJOR update via changeset, but have not provided a corresponding [upgrade guide](https://paste.twilio.design/core/upgrade-guide) entry. Please update the guide to inform our users what to do in response to this major update to Paste.`; @@ -22,9 +22,9 @@ export const qualifyingMajorUpdate = (fileContent: string) => { const matches = Array.from(fileContent.matchAll(/'\@twilio-paste\/(\S+)': major/g), (m) => m[1]); // check if core has a major bump - if (matches.includes('core')) return true; + if (matches.includes("core")) return true; // check if other packages have major bump alongside a patch/minor core bump - if (matches.length && fileContent.includes('@twilio-paste/core')) return false; + if (matches.length && fileContent.includes("@twilio-paste/core")) return false; // check if other packages have a major bump without any core bump if (matches.length) return true; diff --git a/.danger/package-json-check.ts b/.danger/package-json-check.ts index 8b1dff5b08..3997baddeb 100644 --- a/.danger/package-json-check.ts +++ b/.danger/package-json-check.ts @@ -1,7 +1,7 @@ -import {getPackJsonsFromFiles} from './utils'; // you kind of have to treat Danger plugins as global? // https://danger.systems/js/usage/extending-danger.html#writing-your-plugin -import {DangerDSLType} from 'danger/distribution/dsl/DangerDSL'; +import { DangerDSLType } from "danger/distribution/dsl/DangerDSL"; +import { getPackJsonsFromFiles } from "./utils"; declare const danger: DangerDSLType; export declare function warn(message: string): void; @@ -12,14 +12,14 @@ export declare function warn(message: string): void; export default () => { // package.json related files const packageJSONsChanged = getPackJsonsFromFiles([...danger.git.modified_files, ...danger.git.created_files]); - const lockfileChanged = danger.git.modified_files.includes('yarn.lock'); + const lockfileChanged = danger.git.modified_files.includes("yarn.lock"); /** * Warn when user potentially forgets to update lockfile */ if (packageJSONsChanged.length > 0 && !lockfileChanged) { - const message = 'Changes were made to package.json, but not to yarn.lock'; - const idea = 'Perhaps you need to run `yarn install`?'; + const message = "Changes were made to package.json, but not to yarn.lock"; + const idea = "Perhaps you need to run `yarn install`?"; warn(`${message} - ${idea}`); } }; diff --git a/.danger/pin-external-deps.ts b/.danger/pin-external-deps.ts index 72717eb239..fa258097fd 100644 --- a/.danger/pin-external-deps.ts +++ b/.danger/pin-external-deps.ts @@ -1,6 +1,6 @@ -import {DangerDSLType} from 'danger/distribution/dsl/DangerDSL'; -import fs from 'fs'; -import {getPackJsonsFromFiles} from './utils'; +import fs from "fs"; +import { DangerDSLType } from "danger/distribution/dsl/DangerDSL"; +import { getPackJsonsFromFiles } from "./utils"; // you kind of have to treat Danger plugins as global? // https://danger.systems/js/usage/extending-danger.html#writing-your-plugin @@ -18,9 +18,9 @@ export const getUnpinnedExternalDeps = (deps: Record): string[] return ( Object.keys(deps) // we don't want internal packages - .filter((dep) => !dep.includes('@twilio-paste')) + .filter((dep) => !dep.includes("@twilio-paste")) // we want anything that has a ^ - .filter((dep) => deps[dep].startsWith('^')) + .filter((dep) => deps[dep].startsWith("^")) ); } else { return []; @@ -34,13 +34,13 @@ export const getUnpinnedExternalDeps = (deps: Record): string[] * @return {*} {string[]} */ export const getUnPinnedExternalDepsFromPackageJSONFiles = ( - pkgJSONFiles: string[] -): Array<{dep: string; name: string}> => { - const unPinnedExternalDeps: Array<{dep: string; name: string}> = []; + pkgJSONFiles: string[], +): Array<{ dep: string; name: string }> => { + const unPinnedExternalDeps: Array<{ dep: string; name: string }> = []; pkgJSONFiles.forEach((pkgJSON) => { const fileContent = fs.readFileSync(pkgJSON).toString(); - const {name, dependencies} = JSON.parse(fileContent); - getUnpinnedExternalDeps(dependencies).forEach((dep) => unPinnedExternalDeps.push({dep, name})); + const { name, dependencies } = JSON.parse(fileContent); + getUnpinnedExternalDeps(dependencies).forEach((dep) => unPinnedExternalDeps.push({ dep, name })); }); return unPinnedExternalDeps; }; @@ -60,11 +60,11 @@ export default () => { if (unpinnedExternalDeps.length > 0) { let locationString = ``; - unpinnedExternalDeps.forEach(({dep, name}) => { + unpinnedExternalDeps.forEach(({ dep, name }) => { locationString += `* ${name} - ${dep}\n`; }); fail( - `There are some package.json files in this PR that contain unpinned external package libraries. Please pin your external package libraries by removing the ^ from the beginning of the version number. See:\n\n${locationString}` + `There are some package.json files in this PR that contain unpinned external package libraries. Please pin your external package libraries by removing the ^ from the beginning of the version number. See:\n\n${locationString}`, ); } } diff --git a/.danger/utils.ts b/.danger/utils.ts index 41a31acf7e..64b30835d0 100644 --- a/.danger/utils.ts +++ b/.danger/utils.ts @@ -1,4 +1,4 @@ -import type {PackageShape} from '../tools/utils/getRepoPackages'; +import type { PackageShape } from "../tools/utils/getRepoPackages"; /** * Returns a list of public packages by filtering out the private ones @@ -15,7 +15,7 @@ export const getPublicPackages = (packageList: PackageShape[]) => packageList.fi * @return {*} {string} */ export const getRepoPackagePath = (location: string): string => - location.slice(location.indexOf('packages'), location.length); + location.slice(location.indexOf("packages"), location.length); /** * Returns file paths relative to the root of the project from a list of packages @@ -24,7 +24,7 @@ export const getRepoPackagePath = (location: string): string => * @return {*} {string[]} */ export const getPackagePaths = (packages: PackageShape[]): string[] => - packages.map(({location}) => getRepoPackagePath(location)); + packages.map(({ location }) => getRepoPackagePath(location)); /** * From a list of files, return only the files that are located in @@ -71,13 +71,13 @@ export const getUnpublishedPackageNames = (touchedFiles: string[], publicPackage // all packages are uniform, except for design tokens. Source files are in the src directory. // any changes to tokens, formatters or types in design tokens also need to be released if ( - filePath.includes('/src/') || - filePath.includes('/paste-design-tokens/tokens/') || - filePath.includes('/paste-design-tokens/formatters/') || - filePath.includes('/paste-design-tokens/types/') || - filePath.includes('/paste-codemods/bin/') || - filePath.includes('/paste-codemods/transforms/') || - filePath.includes('/paste-codemods/tools/.cache/') + filePath.includes("/src/") || + filePath.includes("/paste-design-tokens/tokens/") || + filePath.includes("/paste-design-tokens/formatters/") || + filePath.includes("/paste-design-tokens/types/") || + filePath.includes("/paste-codemods/bin/") || + filePath.includes("/paste-codemods/transforms/") || + filePath.includes("/paste-codemods/tools/.cache/") ) { uniquePackages.add(packageName); } @@ -91,14 +91,14 @@ export const getUnpublishedPackageNames = (touchedFiles: string[], publicPackage * @param {string[]} fileList */ export const getChangesetsFromFiles = (fileList: string[]) => - fileList.filter((filePath) => filePath.includes('changeset') && filePath.includes('.md')); + fileList.filter((filePath) => filePath.includes("changeset") && filePath.includes(".md")); export const IGNORE_LIST = [ - 'paste-website', - 'paste-nextjs-template', - 'paste-theme-designer', - 'paste-color-contrast-utils', - 'paste-token-contrast-checker', + "paste-website", + "paste-nextjs-template", + "paste-theme-designer", + "paste-color-contrast-utils", + "paste-token-contrast-checker", ]; /** @@ -109,8 +109,8 @@ export const IGNORE_LIST = [ export const getPackJsonsFromFiles = (fileList: string[]) => fileList.filter((filePath) => { return ( - filePath !== 'package.json' && // Ignore root package.json - filePath.includes('package.json') && // Only include package.json files + filePath !== "package.json" && // Ignore root package.json + filePath.includes("package.json") && // Only include package.json files !IGNORE_LIST.some((ignorePath) => filePath.includes(ignorePath)) // Unless they are in the ignore list ); }); diff --git a/.danger/website-page-vrt-check.ts b/.danger/website-page-vrt-check.ts index 305e67a474..71c779fbb1 100644 --- a/.danger/website-page-vrt-check.ts +++ b/.danger/website-page-vrt-check.ts @@ -1,6 +1,6 @@ // you kind of have to treat Danger plugins as global? // https://danger.systems/js/usage/extending-danger.html#writing-your-plugin -import {DangerDSLType} from 'danger/distribution/dsl/DangerDSL'; +import { DangerDSLType } from "danger/distribution/dsl/DangerDSL"; declare const danger: DangerDSLType; export declare function fail(message: string): void; diff --git a/.eslint/resolver.js b/.eslint/resolver.js index bb0af9ceae..fd3fad12b4 100644 --- a/.eslint/resolver.js +++ b/.eslint/resolver.js @@ -1,5 +1,5 @@ -const resolve = require('resolve'); -const cachedPackages = require('../tools/.cache/packages.json'); +const resolve = require("resolve"); +const cachedPackages = require("../tools/.cache/packages.json"); exports.interfaceVersion = 2; @@ -24,10 +24,10 @@ const keyedPackages = cachedPackages.reduce((acc, currentPackage) => { // If there's no main entrypoint, don't update the location path. // Note: the icons package doesn't have a main entrypoint - if (packageJson['main:dev'] == null && packageJson.main == null) { + if (packageJson["main:dev"] == null && packageJson.main == null) { acc[currentPackage.name] = currentPackage; } else { - const mainEntrypoint = packageJson['main:dev'] || packageJson.main; + const mainEntrypoint = packageJson["main:dev"] || packageJson.main; // Make sure to set the location to the dist/main entrypoint. acc[currentPackage.name] = { ...currentPackage, @@ -46,17 +46,17 @@ const keyedPackages = cachedPackages.reduce((acc, currentPackage) => { * https://github.com/benmosher/eslint-plugin-import/blob/master/resolvers/README.md */ exports.resolve = function customResolver(source, file, config) { - if (source.includes('@twilio-paste/') && keyedPackages[source] != null) { - return {found: true, path: keyedPackages[source].location}; + if (source.includes("@twilio-paste/") && keyedPackages[source] != null) { + return { found: true, path: keyedPackages[source].location }; } if (resolve.isCore(source)) { - return {found: true, path: null}; + return { found: true, path: null }; } try { - return {found: true, path: resolve.sync(source, opts(file, config))}; + return { found: true, path: resolve.sync(source, opts(file, config)) }; } catch (err) { - return {found: false}; + return { found: false }; } }; diff --git a/.eslintrc.core.js b/.eslintrc.core.js index b6e01b3d32..13ef6e1865 100644 --- a/.eslintrc.core.js +++ b/.eslintrc.core.js @@ -1,9 +1,9 @@ module.exports = { - extends: ['./.eslintrc.js'], + extends: ["./.eslintrc.js"], root: true, rules: { // when linting a package we want eslint to look at the package json file to // correctly detect a missing dependency - 'import/no-extraneous-dependencies': ['error'], + "import/no-extraneous-dependencies": ["error"], }, }; diff --git a/.eslintrc.js b/.eslintrc.js index 5740925d76..84ef154df0 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,21 +1,21 @@ // Based on https://github.com/iamturns/create-exposed-app/blob/master/.eslintrc.js module.exports = { root: true, - parser: '@typescript-eslint/parser', + parser: "@typescript-eslint/parser", parserOptions: { - project: './tsconfig.json', + project: "./tsconfig.json", }, - plugins: ['eslint-comments', 'jest', 'unicorn', 'promise', '@emotion/eslint-plugin', 'paste-internal'], + plugins: ["eslint-comments", "jest", "unicorn", "promise", "@emotion/eslint-plugin", "paste-internal"], extends: [ - 'twilio-react', - 'twilio-ts', - 'plugin:jest/recommended', - 'plugin:eslint-comments/recommended', - 'plugin:cypress/recommended', - 'plugin:promise/recommended', - 'plugin:unicorn/recommended', - 'plugin:paste-internal/all', - 'plugin:storybook/recommended', + "twilio-react", + "twilio-ts", + "plugin:jest/recommended", + "plugin:eslint-comments/recommended", + "plugin:cypress/recommended", + "plugin:promise/recommended", + "plugin:unicorn/recommended", + "plugin:paste-internal/all", + "plugin:storybook/recommended", ], env: { node: true, @@ -24,16 +24,16 @@ module.exports = { }, rules: { // Makes no sense to allow type inference for expression parameters, but require typing the response - '@typescript-eslint/explicit-function-return-type': [ - 'error', + "@typescript-eslint/explicit-function-return-type": [ + "error", { allowExpressions: true, allowTypedFunctionExpressions: true, }, ], - eqeqeq: ['error', 'smart'], + eqeqeq: ["error", "smart"], // Doesnt really work in our use-cases: https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/require-default-props.m - 'react/require-default-props': 'off', + "react/require-default-props": "off", /** * Disbled this rule because the current failures are stories, test files, and index files. * - story files need to export stories even tho no other module uses them for storybook to render @@ -41,69 +41,69 @@ module.exports = { * - for some reason, index files that just say "export * from '../blah'" fail saying they don't export anything, even tho they do * This rule is designed for a product, not a series of libraries. */ - 'import/no-unused-modules': [0], + "import/no-unused-modules": [0], // There are times when we have to use require, so maybe this should stay a warning - '@typescript-eslint/no-require-imports': 'warn', + "@typescript-eslint/no-require-imports": "warn", // There are times when we have to use var requires, so maybe this should stay a warning (example: importing token files on the website) - '@typescript-eslint/no-var-requires': 'warn', + "@typescript-eslint/no-var-requires": "warn", // We spread props a lot, for example for combobox hooks - 'react/jsx-props-no-spreading': 'off', + "react/jsx-props-no-spreading": "off", // This rule doesn't work with typescript, disabled in favor of the typescript version - 'no-duplicate-imports': 'off', - '@typescript-eslint/no-duplicate-imports': 'error', + "no-duplicate-imports": "off", + "@typescript-eslint/no-duplicate-imports": "error", // We have our own prettier config that runs in its own CI check, so we don't need ESLint to do it too - 'prettier/prettier': 'off', + "prettier/prettier": "off", // This extends twilio-style's camelcase rule and adds an allow list camelcase: [ - 'error', + "error", { - properties: 'always', + properties: "always", ignoreDestructuring: true, allow: [ // Box pseudoselectors are allowed - '_focus_hover', - '_focus_placeholder', - '_checked_hover', - '_disabled_focus', - '_selected_hover', - '_selected_focus', - '_selected_focusVisible', - '_pressed_focus', - '_pressed_hover', - '_pressed_disabled', - '_pressed_active', - '__moz_focus_inner', - '__webkit_datetime_edit', - '__webkit_calendar_picker_indicator_hover', - '__webkit_inner_spin_button', - '__webkit_outer_spin_button', + "_focus_hover", + "_focus_placeholder", + "_checked_hover", + "_disabled_focus", + "_selected_hover", + "_selected_focus", + "_selected_focusVisible", + "_pressed_focus", + "_pressed_hover", + "_pressed_disabled", + "_pressed_active", + "__moz_focus_inner", + "__webkit_datetime_edit", + "__webkit_calendar_picker_indicator_hover", + "__webkit_inner_spin_button", + "__webkit_outer_spin_button", // these are variant names we use as keys in style objects - 'destructive_link', - 'destructive_secondary', - 'circle_small', - 'rounded_small', - 'icon_small', - 'error_counter', - 'neutral_counter', + "destructive_link", + "destructive_secondary", + "circle_small", + "rounded_small", + "icon_small", + "error_counter", + "neutral_counter", // unstable props are allowed - '^unstable_', + "^unstable_", // this is a temporary prop, if the console patch is removed from components this can be removed too - '__console_patch', + "__console_patch", // token types relating to color contrast aren't camelcase, but they should probably be refactored - 'text_contrast_pairing', - 'uicontrol_contrast_pairing', - 'data_visualization_contrast_pairing', + "text_contrast_pairing", + "uicontrol_contrast_pairing", + "data_visualization_contrast_pairing", // These are from the website and are keys returned from airtable, they should be refactored - 'Design_committee_review', - 'Engineer_committee_review', - 'external_link', - 'Product_suitability', - 'Public_Description__from_System_', - 'Release_Description', - 'Release_feature_name', - 'page_path', - 'event_category', - 'event_label', + "Design_committee_review", + "Engineer_committee_review", + "external_link", + "Product_suitability", + "Public_Description__from_System_", + "Release_Description", + "Release_feature_name", + "page_path", + "event_category", + "event_label", ], }, ], @@ -111,16 +111,16 @@ module.exports = { * TEMPORARY TWILIO STYLE OVERRIDES * There are PRs open to update these rules in twilio-style */ - 'react/no-multi-comp': [ - 'error', + "react/no-multi-comp": [ + "error", { ignoreStateless: true, }, ], - 'jsx-a11y/label-has-associated-control': [ + "jsx-a11y/label-has-associated-control": [ 2, { - assert: 'either', + assert: "either", depth: 3, }, ], @@ -128,98 +128,98 @@ module.exports = { * FIXES FOR ANOTHER TICKET * these take a little more work to fix (there are 535 errors) */ - '@typescript-eslint/no-floating-promises': 'off', - 'react-hooks/rules-of-hooks': 'off', - 'react/jsx-no-bind': 'off', - 'react/no-unused-prop-types': 'off', - 'no-negated-condition': 'off', - 'no-eq-null': 'off', - 'no-unneeded-ternary': 'off', - 'no-nested-ternary': 'off', - 'no-process-exit': 'off', - 'no-new': 'off', - 'default-case': 'off', - 'guard-for-in': 'off', - 'callback-return': 'off', - 'sonarjs/cognitive-complexity': 'off', - 'sonarjs/no-nested-template-literals': 'off', - 'sonarjs/no-identical-functions': 'off', - complexity: 'off', + "@typescript-eslint/no-floating-promises": "off", + "react-hooks/rules-of-hooks": "off", + "react/jsx-no-bind": "off", + "react/no-unused-prop-types": "off", + "no-negated-condition": "off", + "no-eq-null": "off", + "no-unneeded-ternary": "off", + "no-nested-ternary": "off", + "no-process-exit": "off", + "no-new": "off", + "default-case": "off", + "guard-for-in": "off", + "callback-return": "off", + "sonarjs/cognitive-complexity": "off", + "sonarjs/no-nested-template-literals": "off", + "sonarjs/no-identical-functions": "off", + complexity: "off", // this rule should be kept warning once it is fixed - 'sonarjs/no-duplicate-string': 'warn', + "sonarjs/no-duplicate-string": "warn", /** MISC OVERRIDES */ // Too restrictive, writing ugly code to defend against a very unlikely scenario: https://eslint.org/docs/rules/no-prototype-builtins - 'no-prototype-builtins': 'off', - '@typescript-eslint/comma-dangle': ['error', 'only-multiline'], - '@typescript-eslint/no-shadow': [ - 'error', + "no-prototype-builtins": "off", + "@typescript-eslint/comma-dangle": ["error", "only-multiline"], + "@typescript-eslint/no-shadow": [ + "error", { ignoreFunctionTypeParameterNameValueShadow: true, }, ], // This rule tells people to do something (import foo = require('foo')) which doesn't work // with babel compiled typescript. - '@typescript-eslint/no-var-requires': 'off', + "@typescript-eslint/no-var-requires": "off", // Warn about incorrect type imports // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/consistent-type-imports.md - '@typescript-eslint/consistent-type-imports': 'warn', + "@typescript-eslint/consistent-type-imports": "warn", // Common abbreviations are known and readable - 'unicorn/prevent-abbreviations': 'off', + "unicorn/prevent-abbreviations": "off", // We don't really have a style yet. To be discussed // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/filename-case.md - 'unicorn/filename-case': 'off', - 'unicorn/no-null': 'off', - 'unicorn/no-reduce': 'off', - 'unicorn/no-fn-reference-in-iterator': 'off', + "unicorn/filename-case": "off", + "unicorn/no-null": "off", + "unicorn/no-reduce": "off", + "unicorn/no-fn-reference-in-iterator": "off", // weirdly specific - 'unicorn/import-style': 'off', - 'unicorn/prefer-ternary': 'off', + "unicorn/import-style": "off", + "unicorn/prefer-ternary": "off", // Too big of a change - 'unicorn/numeric-separators-style': 'off', + "unicorn/numeric-separators-style": "off", // Mixed ts and node code base - 'unicorn/prefer-module': 'warn', + "unicorn/prefer-module": "warn", // This conflicts with consistent-return - 'unicorn/no-useless-undefined': 'off', + "unicorn/no-useless-undefined": "off", // New rules - 'unicorn/no-array-reduce': 'off', - 'unicorn/no-array-for-each': 'off', - 'unicorn/prefer-dom-node-dataset': 'off', - 'unicorn/no-lonely-if': 'off', - 'unicorn/prefer-export-from': 'off', - 'unicorn/no-array-callback-reference': 'off', - 'unicorn/consistent-destructuring': 'off', - 'unicorn/prefer-number-properties': 'off', - 'unicorn/prefer-node-protocol': 'off', - 'unicorn/prefer-spread': 'off', - 'unicorn/prefer-regexp-test': 'off', - 'unicorn/no-new-array': 'off', - 'unicorn/prefer-object-from-entries': 'off', + "unicorn/no-array-reduce": "off", + "unicorn/no-array-for-each": "off", + "unicorn/prefer-dom-node-dataset": "off", + "unicorn/no-lonely-if": "off", + "unicorn/prefer-export-from": "off", + "unicorn/no-array-callback-reference": "off", + "unicorn/consistent-destructuring": "off", + "unicorn/prefer-number-properties": "off", + "unicorn/prefer-node-protocol": "off", + "unicorn/prefer-spread": "off", + "unicorn/prefer-regexp-test": "off", + "unicorn/no-new-array": "off", + "unicorn/prefer-object-from-entries": "off", // We don't use jasmine and this clashes with danger js - 'jest/no-jasmine-globals': 'off', - 'jest/no-conditional-expect': 'off', + "jest/no-jasmine-globals": "off", + "jest/no-conditional-expect": "off", }, overrides: [ { files: [ - '**/stories/**/*.tsx', - '**/__tests__/*.spec.{ts,tsx}', - '**/__tests__/*.test.{ts,tsx}', - '**/__fixtures__/*.tsx', - '**/__test__/*.spec.{ts,tsx}', - 'performance-benchmarks/**/*.tsx', + "**/stories/**/*.tsx", + "**/__tests__/*.spec.{ts,tsx}", + "**/__tests__/*.test.{ts,tsx}", + "**/__fixtures__/*.tsx", + "**/__test__/*.spec.{ts,tsx}", + "performance-benchmarks/**/*.tsx", ], rules: { // stories and tests aren't public, they don't need display names - 'react/display-name': 'off', + "react/display-name": "off", // we use empty functions in stories and tests to mock components - '@typescript-eslint/no-empty-function': 'off', + "@typescript-eslint/no-empty-function": "off", }, }, ], settings: { react: { - version: 'detect', + version: "detect", }, }, }; diff --git a/.eslintrc.repo.js b/.eslintrc.repo.js index 0e9aec27ff..7442974556 100644 --- a/.eslintrc.repo.js +++ b/.eslintrc.repo.js @@ -1,8 +1,8 @@ -const path = require('path'); -const cachedPackages = require('./tools/.cache/packages.json'); +const path = require("path"); +const cachedPackages = require("./tools/.cache/packages.json"); module.exports = { - extends: ['./.eslintrc.js'], + extends: ["./.eslintrc.js"], root: true, // lint everything but: // - src files in packages as they need to be linted with the context of their local package.json file to make no-extraneous-dependencies work @@ -10,21 +10,21 @@ module.exports = { // - vs-code extensions // - cypress ignorePatterns: [ - 'packages/**/src', - 'packages/paste-theme-designer', - 'packages/paste-token-contrast-checker', - 'packages/paste-website', - 'templates/paste-nextjs-template', - 'apps/vs-code-intellisense', - 'cypress', + "packages/**/src", + "packages/paste-theme-designer", + "packages/paste-token-contrast-checker", + "packages/paste-website", + "templates/paste-nextjs-template", + "apps/vs-code-intellisense", + "cypress", ], rules: { - 'import/no-extraneous-dependencies': [ - 'error', + "import/no-extraneous-dependencies": [ + "error", { // when linting the repo globally, local packages are not installed, so we need to // manually tell eslint where to look for them - packageDir: [path.join(__dirname, './'), ...cachedPackages.map((package) => package.location)], + packageDir: [path.join(__dirname, "./"), ...cachedPackages.map((pkg) => pkg.location)], }, ], }, diff --git a/.github/workflows/on_pull_request.yml b/.github/workflows/on_pull_request.yml index 52073f5ac7..62797f0faf 100644 --- a/.github/workflows/on_pull_request.yml +++ b/.github/workflows/on_pull_request.yml @@ -258,8 +258,8 @@ jobs: - name: Run tests run: yarn test - prettier: - name: Prettier checks + format: + name: Code format checks runs-on: ubuntu-latest steps: - name: Checkout Repo @@ -300,13 +300,8 @@ jobs: if: steps.yarn_cache_id.outputs.cache-hit != 'true' || steps.node_modules_cache_id.outputs.cache-hit != 'true' run: yarn install --immutable - - name: Build packages - run: yarn build - env: - NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} - - - name: Run prettier - run: yarn prettier + - name: Run BiomeJS + Prettier format for their respective files + run: yarn format:ci chromatic: name: Component Visual regression tests diff --git a/.jest/globals/TestTheme.js b/.jest/globals/TestTheme.js index 074ccc52aa..5dbeb0251d 100644 --- a/.jest/globals/TestTheme.js +++ b/.jest/globals/TestTheme.js @@ -1,238 +1,238 @@ module.exports = { shadows: { - shadow: '0 4px 16px 0 rgba(18, 28, 45, 0.2)', - shadowBorder: '0 0 0 1px #8891aa', - shadowBorderDestructive: '0 0 0 1px #d61f1f', - shadowBorderDestructiveDarker: '0 0 0 1px #4a0b0b', - shadowBorderDestructiveLight: '0 0 0 1px #f6b1b1', - shadowBorderDestructiveLighter: '0 0 0 1px #fccfcf', - shadowBorderDestructiveStrong: '0 0 0 1px #750c0c', - shadowBorderDestructiveStronger: '0 0 0 1px #4a0b0b', - shadowBorderDestructiveStrongest: '0 0 0 1px #310c0c', - shadowBorderDestructiveWeak: '0 0 0 1px #f6b1b1', - shadowBorderDestructiveWeaker: '0 0 0 1px #fccfcf', - shadowBorderError: '0 0 0 1px #d61f1f', - shadowBorderErrorDark: '0 0 0 1px #750c0c', - shadowBorderErrorLight: '0 0 0 1px #eb5656', - shadowBorderErrorStrong: '0 0 0 1px #750c0c', - shadowBorderErrorWeak: '0 0 0 1px #eb5656', - shadowBorderInverse: '0 0 0 1px rgba(255, 255, 255, 0.5)', - shadowBorderInverseDarker: '0 0 0 1px rgba(255, 255, 255, 0.2)', - shadowBorderInverseLight: '0 0 0 1px rgba(255, 255, 255, 0.9)', - shadowBorderInverseLightest: '0 0 0 1px #ffffff', - shadowBorderInverseStrong: '0 0 0 1px rgba(255, 255, 255, 0.7)', - shadowBorderInverseStronger: '0 0 0 1px rgba(255, 255, 255, 0.9)', - shadowBorderInverseStrongest: '0 0 0 1px #ffffff', - shadowBorderInverseWeaker: '0 0 0 1px rgba(255, 255, 255, 0.2)', - shadowBorderLight: '0 0 0 1px #cacdd8', - shadowBorderLighter: '0 0 0 1px #e1e3ea', - shadowBorderPrimary: '0 0 0 1px #0263e0', - shadowBorderPrimaryDark: '0 0 0 1px #001489', - shadowBorderPrimaryDarker: '0 0 0 1px #030b5d', - shadowBorderPrimaryLight: '0 0 0 1px #99cdff', - shadowBorderPrimaryLighter: '0 0 0 1px #cce4ff', - shadowBorderPrimaryStrong: '0 0 0 1px #001489', - shadowBorderPrimaryStronger: '0 0 0 1px #030b5d', - shadowBorderPrimaryStrongest: '0 0 0 1px #06033a', - shadowBorderPrimaryWeak: '0 0 0 1px #99cdff', - shadowBorderPrimaryWeaker: '0 0 0 1px #cce4ff', - shadowBorderStrong: '0 0 0 1px #606b85', - shadowBorderWeak: '0 0 0 1px #cacdd8', - shadowBorderWeaker: '0 0 0 1px #e1e3ea', - shadowCard: '0 2px 8px 0 rgba(18, 28, 45, 0.1)', - shadowFocus: '0 0 0 4px rgba(2, 99, 224, 0.7)', - shadowFocusInverse: '0 0 0 4px rgba(255, 255, 255, 0.4)', - shadowHigh: '0 16px 24px 0 rgba(18, 28, 45, 0.2)', - shadowLow: '0 2px 8px 0 rgba(18, 28, 45, 0.1)', + shadow: "0 4px 16px 0 rgba(18, 28, 45, 0.2)", + shadowBorder: "0 0 0 1px #8891aa", + shadowBorderDestructive: "0 0 0 1px #d61f1f", + shadowBorderDestructiveDarker: "0 0 0 1px #4a0b0b", + shadowBorderDestructiveLight: "0 0 0 1px #f6b1b1", + shadowBorderDestructiveLighter: "0 0 0 1px #fccfcf", + shadowBorderDestructiveStrong: "0 0 0 1px #750c0c", + shadowBorderDestructiveStronger: "0 0 0 1px #4a0b0b", + shadowBorderDestructiveStrongest: "0 0 0 1px #310c0c", + shadowBorderDestructiveWeak: "0 0 0 1px #f6b1b1", + shadowBorderDestructiveWeaker: "0 0 0 1px #fccfcf", + shadowBorderError: "0 0 0 1px #d61f1f", + shadowBorderErrorDark: "0 0 0 1px #750c0c", + shadowBorderErrorLight: "0 0 0 1px #eb5656", + shadowBorderErrorStrong: "0 0 0 1px #750c0c", + shadowBorderErrorWeak: "0 0 0 1px #eb5656", + shadowBorderInverse: "0 0 0 1px rgba(255, 255, 255, 0.5)", + shadowBorderInverseDarker: "0 0 0 1px rgba(255, 255, 255, 0.2)", + shadowBorderInverseLight: "0 0 0 1px rgba(255, 255, 255, 0.9)", + shadowBorderInverseLightest: "0 0 0 1px #ffffff", + shadowBorderInverseStrong: "0 0 0 1px rgba(255, 255, 255, 0.7)", + shadowBorderInverseStronger: "0 0 0 1px rgba(255, 255, 255, 0.9)", + shadowBorderInverseStrongest: "0 0 0 1px #ffffff", + shadowBorderInverseWeaker: "0 0 0 1px rgba(255, 255, 255, 0.2)", + shadowBorderLight: "0 0 0 1px #cacdd8", + shadowBorderLighter: "0 0 0 1px #e1e3ea", + shadowBorderPrimary: "0 0 0 1px #0263e0", + shadowBorderPrimaryDark: "0 0 0 1px #001489", + shadowBorderPrimaryDarker: "0 0 0 1px #030b5d", + shadowBorderPrimaryLight: "0 0 0 1px #99cdff", + shadowBorderPrimaryLighter: "0 0 0 1px #cce4ff", + shadowBorderPrimaryStrong: "0 0 0 1px #001489", + shadowBorderPrimaryStronger: "0 0 0 1px #030b5d", + shadowBorderPrimaryStrongest: "0 0 0 1px #06033a", + shadowBorderPrimaryWeak: "0 0 0 1px #99cdff", + shadowBorderPrimaryWeaker: "0 0 0 1px #cce4ff", + shadowBorderStrong: "0 0 0 1px #606b85", + shadowBorderWeak: "0 0 0 1px #cacdd8", + shadowBorderWeaker: "0 0 0 1px #e1e3ea", + shadowCard: "0 2px 8px 0 rgba(18, 28, 45, 0.1)", + shadowFocus: "0 0 0 4px rgba(2, 99, 224, 0.7)", + shadowFocusInverse: "0 0 0 4px rgba(255, 255, 255, 0.4)", + shadowHigh: "0 16px 24px 0 rgba(18, 28, 45, 0.2)", + shadowLow: "0 2px 8px 0 rgba(18, 28, 45, 0.1)", }, borderWidths: { - borderWidth0: '0', - borderWidth10: '1px', - borderWidth20: '2px', - borderWidth30: '4px', - borderWidth40: '8px', + borderWidth0: "0", + borderWidth10: "1px", + borderWidth20: "2px", + borderWidth30: "4px", + borderWidth40: "8px", }, radii: { - borderRadius0: '0', - borderRadius10: '2px', - borderRadius20: '4px', - borderRadius30: '8px', - borderRadiusCircle: '50%', + borderRadius0: "0", + borderRadius10: "2px", + borderRadius20: "4px", + borderRadius30: "8px", + borderRadiusCircle: "50%", }, - breakpoints: ['400px', '1024px', '1232px'], + breakpoints: ["400px", "1024px", "1232px"], textColors: { - colorText: 'rgb(18, 28, 45)', - colorTextBrandHighlight: 'rgb(242, 47, 70)', - colorTextBrandInverse: 'rgb(255, 255, 255)', - colorTextError: 'rgb(214, 31, 31)', - colorTextErrorDark: 'rgb(173, 17, 17)', - colorTextErrorLight: 'rgb(235, 86, 86)', - colorTextErrorStrong: 'rgb(173, 17, 17)', - colorTextErrorWeak: 'rgb(235, 86, 86)', - colorTextIcon: 'rgb(96, 107, 133)', - colorTextIconBrandHighlight: 'rgb(242, 47, 70)', - colorTextIconBrandInverse: 'rgb(255, 255, 255)', - colorTextIconError: 'rgb(214, 31, 31)', - colorTextIconInverse: 'rgb(136, 145, 170)', - colorTextIconNeutral: 'rgb(0, 20, 137)', - colorTextIconSuccess: 'rgb(14, 124, 58)', - colorTextIconWarning: 'rgb(227, 106, 25)', - colorTextInverse: 'rgb(255, 255, 255)', - colorTextInverseWeak: 'rgb(174, 178, 193)', - colorTextInverseWeaker: 'rgb(96, 107, 133)', - colorTextLink: 'rgb(2, 99, 224)', - colorTextLinkDark: 'rgb(0, 20, 137)', - colorTextLinkDarker: 'rgb(3, 11, 93)', - colorTextLinkDestructive: 'rgb(214, 31, 31)', - colorTextLinkDestructiveDark: 'rgb(173, 17, 17)', - colorTextLinkDestructiveDarker: 'rgb(74, 11, 11)', - colorTextLinkDestructiveLight: 'rgb(246, 177, 177)', - colorTextLinkDestructiveStrong: 'rgb(173, 17, 17)', - colorTextLinkDestructiveStronger: 'rgb(74, 11, 11)', - colorTextLinkDestructiveWeak: 'rgb(246, 177, 177)', - colorTextLinkLight: 'rgb(153, 205, 255)', - colorTextLinkStrong: 'rgb(0, 20, 137)', - colorTextLinkStronger: 'rgb(3, 11, 93)', - colorTextLinkWeak: 'rgb(153, 205, 255)', - colorTextNeutral: 'rgb(0, 20, 137)', - colorTextNew: 'rgb(109, 46, 209)', - colorTextSuccess: 'rgb(14, 124, 58)', - colorTextWarning: 'rgb(141, 49, 24)', - colorTextWarningDark: 'rgb(195, 83, 35)', - colorTextWarningStrong: 'rgb(141, 49, 24)', - colorTextWeak: 'rgb(96, 107, 133)', - colorTextWeaker: 'rgb(174, 178, 193)', - colorTextWeakest: 'rgb(255, 255, 255)', + colorText: "rgb(18, 28, 45)", + colorTextBrandHighlight: "rgb(242, 47, 70)", + colorTextBrandInverse: "rgb(255, 255, 255)", + colorTextError: "rgb(214, 31, 31)", + colorTextErrorDark: "rgb(173, 17, 17)", + colorTextErrorLight: "rgb(235, 86, 86)", + colorTextErrorStrong: "rgb(173, 17, 17)", + colorTextErrorWeak: "rgb(235, 86, 86)", + colorTextIcon: "rgb(96, 107, 133)", + colorTextIconBrandHighlight: "rgb(242, 47, 70)", + colorTextIconBrandInverse: "rgb(255, 255, 255)", + colorTextIconError: "rgb(214, 31, 31)", + colorTextIconInverse: "rgb(136, 145, 170)", + colorTextIconNeutral: "rgb(0, 20, 137)", + colorTextIconSuccess: "rgb(14, 124, 58)", + colorTextIconWarning: "rgb(227, 106, 25)", + colorTextInverse: "rgb(255, 255, 255)", + colorTextInverseWeak: "rgb(174, 178, 193)", + colorTextInverseWeaker: "rgb(96, 107, 133)", + colorTextLink: "rgb(2, 99, 224)", + colorTextLinkDark: "rgb(0, 20, 137)", + colorTextLinkDarker: "rgb(3, 11, 93)", + colorTextLinkDestructive: "rgb(214, 31, 31)", + colorTextLinkDestructiveDark: "rgb(173, 17, 17)", + colorTextLinkDestructiveDarker: "rgb(74, 11, 11)", + colorTextLinkDestructiveLight: "rgb(246, 177, 177)", + colorTextLinkDestructiveStrong: "rgb(173, 17, 17)", + colorTextLinkDestructiveStronger: "rgb(74, 11, 11)", + colorTextLinkDestructiveWeak: "rgb(246, 177, 177)", + colorTextLinkLight: "rgb(153, 205, 255)", + colorTextLinkStrong: "rgb(0, 20, 137)", + colorTextLinkStronger: "rgb(3, 11, 93)", + colorTextLinkWeak: "rgb(153, 205, 255)", + colorTextNeutral: "rgb(0, 20, 137)", + colorTextNew: "rgb(109, 46, 209)", + colorTextSuccess: "rgb(14, 124, 58)", + colorTextWarning: "rgb(141, 49, 24)", + colorTextWarningDark: "rgb(195, 83, 35)", + colorTextWarningStrong: "rgb(141, 49, 24)", + colorTextWeak: "rgb(96, 107, 133)", + colorTextWeaker: "rgb(174, 178, 193)", + colorTextWeakest: "rgb(255, 255, 255)", }, borderColors: { - colorBorder: 'rgb(136, 145, 170)', - colorBorderDark: 'rgb(96, 107, 133)', - colorBorderDestructive: 'rgb(214, 31, 31)', - colorBorderDestructiveDark: 'rgb(117, 12, 12)', - colorBorderDestructiveDarker: 'rgb(74, 11, 11)', - colorBorderDestructiveDarkest: 'rgb(49, 12, 12)', - colorBorderDestructiveLight: 'rgb(245, 138, 138)', - colorBorderDestructiveLighter: 'rgb(252, 207, 207)', - colorBorderDestructiveStrong: 'rgb(117, 12, 12)', - colorBorderDestructiveStronger: 'rgb(74, 11, 11)', - colorBorderDestructiveStrongest: 'rgb(49, 12, 12)', - colorBorderDestructiveWeak: 'rgb(245, 138, 138)', - colorBorderDestructiveWeaker: 'rgb(252, 207, 207)', - colorBorderDestructiveWeakest: 'rgb(254, 236, 236)', - colorBorderError: 'rgb(214, 31, 31)', - colorBorderErrorDark: 'rgb(117, 12, 12)', - colorBorderErrorLight: 'rgb(245, 138, 138)', - colorBorderErrorLightest: 'rgb(254, 236, 236)', - colorBorderErrorStrong: 'rgb(117, 12, 12)', - colorBorderErrorWeak: 'rgb(245, 138, 138)', - colorBorderErrorWeakest: 'rgb(254, 236, 236)', - colorBorderInverse: 'rgba(255, 255, 255, 0.5)', - colorBorderInverseDarker: 'rgba(255, 255, 255, 0.2)', - colorBorderInverseLighter: 'rgba(255, 255, 255, 0.9)', - colorBorderInverseLightest: 'rgb(255, 255, 255)', - colorBorderInverseStrong: 'rgba(255, 255, 255, 0.7)', - colorBorderInverseStronger: 'rgba(255, 255, 255, 0.9)', - colorBorderInverseStrongest: 'rgb(255, 255, 255)', - colorBorderInverseWeaker: 'rgba(255, 255, 255, 0.2)', - colorBorderLight: 'rgb(202, 205, 216)', - colorBorderLighter: 'rgb(225, 227, 234)', - colorBorderNeutral: 'rgb(2, 99, 224)', - colorBorderNeutralLight: 'rgb(136, 145, 170)', - colorBorderNeutralWeak: 'rgb(136, 145, 170)', - colorBorderPrimary: 'rgb(2, 99, 224)', - colorBorderPrimaryDark: 'rgb(0, 20, 137)', - colorBorderPrimaryDarker: 'rgb(3, 11, 93)', - colorBorderPrimaryDarkest: 'rgb(6, 3, 58)', - colorBorderPrimaryLight: 'rgb(102, 179, 255)', - colorBorderPrimaryLighter: 'rgb(204, 228, 255)', - colorBorderPrimaryStrong: 'rgb(0, 20, 137)', - colorBorderPrimaryStronger: 'rgb(3, 11, 93)', - colorBorderPrimaryStrongest: 'rgb(6, 3, 58)', - colorBorderPrimaryWeak: 'rgb(102, 179, 255)', - colorBorderPrimaryWeaker: 'rgb(204, 228, 255)', - colorBorderPrimaryWeakest: 'rgb(235, 244, 255)', - colorBorderStrong: 'rgb(96, 107, 133)', - colorBorderSuccess: 'rgb(20, 176, 83)', - colorBorderSuccessLight: 'rgb(54, 213, 118)', - colorBorderSuccessLightest: 'rgb(237, 253, 243)', - colorBorderSuccessWeak: 'rgb(54, 213, 118)', - colorBorderSuccessWeakest: 'rgb(237, 253, 243)', - colorBorderWarning: 'rgb(244, 124, 34)', - colorBorderWarningLight: 'rgb(255, 179, 122)', - colorBorderWarningLightest: 'rgb(254, 245, 238)', - colorBorderWarningWeak: 'rgb(255, 179, 122)', - colorBorderWarningWeakest: 'rgb(254, 245, 238)', - colorBorderWeak: 'rgb(202, 205, 216)', - colorBorderWeaker: 'rgb(225, 227, 234)', + colorBorder: "rgb(136, 145, 170)", + colorBorderDark: "rgb(96, 107, 133)", + colorBorderDestructive: "rgb(214, 31, 31)", + colorBorderDestructiveDark: "rgb(117, 12, 12)", + colorBorderDestructiveDarker: "rgb(74, 11, 11)", + colorBorderDestructiveDarkest: "rgb(49, 12, 12)", + colorBorderDestructiveLight: "rgb(245, 138, 138)", + colorBorderDestructiveLighter: "rgb(252, 207, 207)", + colorBorderDestructiveStrong: "rgb(117, 12, 12)", + colorBorderDestructiveStronger: "rgb(74, 11, 11)", + colorBorderDestructiveStrongest: "rgb(49, 12, 12)", + colorBorderDestructiveWeak: "rgb(245, 138, 138)", + colorBorderDestructiveWeaker: "rgb(252, 207, 207)", + colorBorderDestructiveWeakest: "rgb(254, 236, 236)", + colorBorderError: "rgb(214, 31, 31)", + colorBorderErrorDark: "rgb(117, 12, 12)", + colorBorderErrorLight: "rgb(245, 138, 138)", + colorBorderErrorLightest: "rgb(254, 236, 236)", + colorBorderErrorStrong: "rgb(117, 12, 12)", + colorBorderErrorWeak: "rgb(245, 138, 138)", + colorBorderErrorWeakest: "rgb(254, 236, 236)", + colorBorderInverse: "rgba(255, 255, 255, 0.5)", + colorBorderInverseDarker: "rgba(255, 255, 255, 0.2)", + colorBorderInverseLighter: "rgba(255, 255, 255, 0.9)", + colorBorderInverseLightest: "rgb(255, 255, 255)", + colorBorderInverseStrong: "rgba(255, 255, 255, 0.7)", + colorBorderInverseStronger: "rgba(255, 255, 255, 0.9)", + colorBorderInverseStrongest: "rgb(255, 255, 255)", + colorBorderInverseWeaker: "rgba(255, 255, 255, 0.2)", + colorBorderLight: "rgb(202, 205, 216)", + colorBorderLighter: "rgb(225, 227, 234)", + colorBorderNeutral: "rgb(2, 99, 224)", + colorBorderNeutralLight: "rgb(136, 145, 170)", + colorBorderNeutralWeak: "rgb(136, 145, 170)", + colorBorderPrimary: "rgb(2, 99, 224)", + colorBorderPrimaryDark: "rgb(0, 20, 137)", + colorBorderPrimaryDarker: "rgb(3, 11, 93)", + colorBorderPrimaryDarkest: "rgb(6, 3, 58)", + colorBorderPrimaryLight: "rgb(102, 179, 255)", + colorBorderPrimaryLighter: "rgb(204, 228, 255)", + colorBorderPrimaryStrong: "rgb(0, 20, 137)", + colorBorderPrimaryStronger: "rgb(3, 11, 93)", + colorBorderPrimaryStrongest: "rgb(6, 3, 58)", + colorBorderPrimaryWeak: "rgb(102, 179, 255)", + colorBorderPrimaryWeaker: "rgb(204, 228, 255)", + colorBorderPrimaryWeakest: "rgb(235, 244, 255)", + colorBorderStrong: "rgb(96, 107, 133)", + colorBorderSuccess: "rgb(20, 176, 83)", + colorBorderSuccessLight: "rgb(54, 213, 118)", + colorBorderSuccessLightest: "rgb(237, 253, 243)", + colorBorderSuccessWeak: "rgb(54, 213, 118)", + colorBorderSuccessWeakest: "rgb(237, 253, 243)", + colorBorderWarning: "rgb(244, 124, 34)", + colorBorderWarningLight: "rgb(255, 179, 122)", + colorBorderWarningLightest: "rgb(254, 245, 238)", + colorBorderWarningWeak: "rgb(255, 179, 122)", + colorBorderWarningWeakest: "rgb(254, 245, 238)", + colorBorderWeak: "rgb(202, 205, 216)", + colorBorderWeaker: "rgb(225, 227, 234)", }, backgroundColors: { - colorBackground: 'rgb(244, 244, 246)', - colorBackgroundAvailable: 'rgb(20, 176, 83)', - colorBackgroundBody: 'rgb(255, 255, 255)', - colorBackgroundBodyInverse: 'rgb(18, 28, 45)', - colorBackgroundBrand: 'rgb(0, 20, 137)', - colorBackgroundBrandHighlight: 'rgb(242, 47, 70)', - colorBackgroundBrandHighlightWeakest: 'rgba(242, 47, 70, 0.1)', - colorBackgroundBrandStrong: 'rgb(3, 11, 93)', - colorBackgroundBrandStronger: 'rgb(6, 3, 58)', - colorBackgroundBusy: 'rgb(244, 124, 34)', - colorBackgroundDark: 'rgb(225, 227, 234)', - colorBackgroundDarker: 'rgb(136, 145, 170)', - colorBackgroundDarkest: 'rgb(75, 86, 113)', - colorBackgroundDestructive: 'rgb(214, 31, 31)', - colorBackgroundDestructiveDark: 'rgb(117, 12, 12)', - colorBackgroundDestructiveDarker: 'rgb(74, 11, 11)', - colorBackgroundDestructiveDarkest: 'rgb(49, 12, 12)', - colorBackgroundDestructiveLight: 'rgb(246, 177, 177)', - colorBackgroundDestructiveLighter: 'rgb(252, 207, 207)', - colorBackgroundDestructiveLightest: 'rgb(254, 236, 236)', - colorBackgroundDestructiveStrong: 'rgb(117, 12, 12)', - colorBackgroundDestructiveStronger: 'rgb(74, 11, 11)', - colorBackgroundDestructiveStrongest: 'rgb(49, 12, 12)', - colorBackgroundDestructiveWeak: 'rgb(246, 177, 177)', - colorBackgroundDestructiveWeaker: 'rgb(252, 207, 207)', - colorBackgroundDestructiveWeakest: 'rgb(254, 236, 236)', - colorBackgroundError: 'rgb(214, 31, 31)', - colorBackgroundErrorDark: 'rgb(117, 12, 12)', - colorBackgroundErrorLightest: 'rgb(254, 236, 236)', - colorBackgroundErrorStrong: 'rgb(117, 12, 12)', - colorBackgroundErrorWeakest: 'rgb(254, 236, 236)', - colorBackgroundInverse: 'rgba(255, 255, 255, 0.1)', - colorBackgroundInverseLight: 'rgba(255, 255, 255, 0.2)', - colorBackgroundInverseStrong: 'rgba(255, 255, 255, 0.2)', - colorBackgroundNeutralLightest: 'rgb(235, 244, 255)', - colorBackgroundNeutralWeakest: 'rgb(235, 244, 255)', - colorBackgroundNew: 'rgb(231, 220, 250)', - colorBackgroundOffline: 'rgb(174, 178, 193)', - colorBackgroundOverlay: 'rgba(6, 3, 58, 0.4)', - colorBackgroundPrimary: 'rgb(2, 99, 224)', - colorBackgroundPrimaryDark: 'rgb(0, 20, 137)', - colorBackgroundPrimaryDarker: 'rgb(3, 11, 93)', - colorBackgroundPrimaryDarkest: 'rgb(6, 3, 58)', - colorBackgroundPrimaryLight: 'rgb(153, 205, 255)', - colorBackgroundPrimaryLighter: 'rgb(204, 228, 255)', - colorBackgroundPrimaryLightest: 'rgb(235, 244, 255)', - colorBackgroundPrimaryStrong: 'rgb(0, 20, 137)', - colorBackgroundPrimaryStronger: 'rgb(3, 11, 93)', - colorBackgroundPrimaryStrongest: 'rgb(6, 3, 58)', - colorBackgroundPrimaryWeak: 'rgb(153, 205, 255)', - colorBackgroundPrimaryWeaker: 'rgb(204, 228, 255)', - colorBackgroundPrimaryWeakest: 'rgb(235, 244, 255)', - colorBackgroundRequired: 'rgb(235, 86, 86)', - colorBackgroundRowStriped: 'rgb(244, 244, 246)', - colorBackgroundStrong: 'rgb(225, 227, 234)', - colorBackgroundStronger: 'rgb(136, 145, 170)', - colorBackgroundStrongest: 'rgb(75, 86, 113)', - colorBackgroundSubaccount: 'rgb(255, 241, 179)', - colorBackgroundSuccess: 'rgb(20, 176, 83)', - colorBackgroundSuccessLightest: 'rgb(237, 253, 243)', - colorBackgroundSuccessWeakest: 'rgb(237, 253, 243)', - colorBackgroundTrial: 'rgb(209, 250, 224)', - colorBackgroundUnavailable: 'rgb(214, 31, 31)', - colorBackgroundUser: 'rgb(200, 175, 240)', - colorBackgroundWarning: 'rgb(244, 124, 34)', - colorBackgroundWarningLightest: 'rgb(254, 245, 238)', - colorBackgroundWarningWeakest: 'rgb(254, 245, 238)', + colorBackground: "rgb(244, 244, 246)", + colorBackgroundAvailable: "rgb(20, 176, 83)", + colorBackgroundBody: "rgb(255, 255, 255)", + colorBackgroundBodyInverse: "rgb(18, 28, 45)", + colorBackgroundBrand: "rgb(0, 20, 137)", + colorBackgroundBrandHighlight: "rgb(242, 47, 70)", + colorBackgroundBrandHighlightWeakest: "rgba(242, 47, 70, 0.1)", + colorBackgroundBrandStrong: "rgb(3, 11, 93)", + colorBackgroundBrandStronger: "rgb(6, 3, 58)", + colorBackgroundBusy: "rgb(244, 124, 34)", + colorBackgroundDark: "rgb(225, 227, 234)", + colorBackgroundDarker: "rgb(136, 145, 170)", + colorBackgroundDarkest: "rgb(75, 86, 113)", + colorBackgroundDestructive: "rgb(214, 31, 31)", + colorBackgroundDestructiveDark: "rgb(117, 12, 12)", + colorBackgroundDestructiveDarker: "rgb(74, 11, 11)", + colorBackgroundDestructiveDarkest: "rgb(49, 12, 12)", + colorBackgroundDestructiveLight: "rgb(246, 177, 177)", + colorBackgroundDestructiveLighter: "rgb(252, 207, 207)", + colorBackgroundDestructiveLightest: "rgb(254, 236, 236)", + colorBackgroundDestructiveStrong: "rgb(117, 12, 12)", + colorBackgroundDestructiveStronger: "rgb(74, 11, 11)", + colorBackgroundDestructiveStrongest: "rgb(49, 12, 12)", + colorBackgroundDestructiveWeak: "rgb(246, 177, 177)", + colorBackgroundDestructiveWeaker: "rgb(252, 207, 207)", + colorBackgroundDestructiveWeakest: "rgb(254, 236, 236)", + colorBackgroundError: "rgb(214, 31, 31)", + colorBackgroundErrorDark: "rgb(117, 12, 12)", + colorBackgroundErrorLightest: "rgb(254, 236, 236)", + colorBackgroundErrorStrong: "rgb(117, 12, 12)", + colorBackgroundErrorWeakest: "rgb(254, 236, 236)", + colorBackgroundInverse: "rgba(255, 255, 255, 0.1)", + colorBackgroundInverseLight: "rgba(255, 255, 255, 0.2)", + colorBackgroundInverseStrong: "rgba(255, 255, 255, 0.2)", + colorBackgroundNeutralLightest: "rgb(235, 244, 255)", + colorBackgroundNeutralWeakest: "rgb(235, 244, 255)", + colorBackgroundNew: "rgb(231, 220, 250)", + colorBackgroundOffline: "rgb(174, 178, 193)", + colorBackgroundOverlay: "rgba(6, 3, 58, 0.4)", + colorBackgroundPrimary: "rgb(2, 99, 224)", + colorBackgroundPrimaryDark: "rgb(0, 20, 137)", + colorBackgroundPrimaryDarker: "rgb(3, 11, 93)", + colorBackgroundPrimaryDarkest: "rgb(6, 3, 58)", + colorBackgroundPrimaryLight: "rgb(153, 205, 255)", + colorBackgroundPrimaryLighter: "rgb(204, 228, 255)", + colorBackgroundPrimaryLightest: "rgb(235, 244, 255)", + colorBackgroundPrimaryStrong: "rgb(0, 20, 137)", + colorBackgroundPrimaryStronger: "rgb(3, 11, 93)", + colorBackgroundPrimaryStrongest: "rgb(6, 3, 58)", + colorBackgroundPrimaryWeak: "rgb(153, 205, 255)", + colorBackgroundPrimaryWeaker: "rgb(204, 228, 255)", + colorBackgroundPrimaryWeakest: "rgb(235, 244, 255)", + colorBackgroundRequired: "rgb(235, 86, 86)", + colorBackgroundRowStriped: "rgb(244, 244, 246)", + colorBackgroundStrong: "rgb(225, 227, 234)", + colorBackgroundStronger: "rgb(136, 145, 170)", + colorBackgroundStrongest: "rgb(75, 86, 113)", + colorBackgroundSubaccount: "rgb(255, 241, 179)", + colorBackgroundSuccess: "rgb(20, 176, 83)", + colorBackgroundSuccessLightest: "rgb(237, 253, 243)", + colorBackgroundSuccessWeakest: "rgb(237, 253, 243)", + colorBackgroundTrial: "rgb(209, 250, 224)", + colorBackgroundUnavailable: "rgb(214, 31, 31)", + colorBackgroundUser: "rgb(200, 175, 240)", + colorBackgroundWarning: "rgb(244, 124, 34)", + colorBackgroundWarningLightest: "rgb(254, 245, 238)", + colorBackgroundWarningWeakest: "rgb(254, 245, 238)", }, fonts: { fontFamilyCode: "'TwilioSansMono', Courier, monospace", @@ -240,448 +240,448 @@ module.exports = { "'Inter var experimental', 'Inter var', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif", }, fontSizes: { - fontSize10: '0.625rem', - fontSize100: '2.5rem', - fontSize110: '3rem', - fontSize20: '0.75rem', - fontSize30: '0.875rem', - fontSize40: '1rem', - fontSize50: '1.125rem', - fontSize60: '1.25rem', - fontSize70: '1.5rem', - fontSize80: '1.75rem', - fontSize90: '2rem', + fontSize10: "0.625rem", + fontSize100: "2.5rem", + fontSize110: "3rem", + fontSize20: "0.75rem", + fontSize30: "0.875rem", + fontSize40: "1rem", + fontSize50: "1.125rem", + fontSize60: "1.25rem", + fontSize70: "1.5rem", + fontSize80: "1.75rem", + fontSize90: "2rem", }, fontWeights: { - fontWeightBold: '700', - fontWeightLight: '400', - fontWeightMedium: '500', - fontWeightNormal: '400', - fontWeightSemibold: '600', + fontWeightBold: "700", + fontWeightLight: "400", + fontWeightMedium: "500", + fontWeightNormal: "400", + fontWeightSemibold: "600", }, lineHeights: { - lineHeight0: '0', - lineHeight10: '1rem', - lineHeight100: '3.25rem', - lineHeight110: '4rem', - lineHeight20: '1.25rem', - lineHeight30: '1.25rem', - lineHeight40: '1.5rem', - lineHeight50: '1.75rem', - lineHeight60: '1.75rem', - lineHeight70: '2rem', - lineHeight80: '2.5rem', - lineHeight90: '2.75rem', + lineHeight0: "0", + lineHeight10: "1rem", + lineHeight100: "3.25rem", + lineHeight110: "4rem", + lineHeight20: "1.25rem", + lineHeight30: "1.25rem", + lineHeight40: "1.5rem", + lineHeight50: "1.75rem", + lineHeight60: "1.75rem", + lineHeight70: "2rem", + lineHeight80: "2.5rem", + lineHeight90: "2.75rem", }, widths: { - size0: '0', - size10: '5.5rem', - size100: '64rem', - size110: '70.5rem', - size120: '77rem', - size20: '12rem', - size30: '18.5rem', - size40: '25rem', - size50: '31.5rem', - size60: '38rem', - size70: '44.5rem', - size80: '51rem', - size90: '57.5rem', - sizeIcon10: '1rem', - sizeIcon100: '3.25rem', - sizeIcon110: '4rem', - sizeIcon20: '1.25rem', - sizeIcon30: '1.25rem', - sizeIcon40: '1.5rem', - sizeIcon50: '1.75rem', - sizeIcon60: '1.75rem', - sizeIcon70: '2rem', - sizeIcon80: '2.5rem', - sizeIcon90: '2.75rem', - sizeSidebar: '13.75rem', - sizeSquare0: '0', - sizeSquare10: '0.125rem', - sizeSquare100: '2.25rem', - sizeSquare110: '2.5rem', - sizeSquare120: '2.75rem', - sizeSquare130: '3rem', - sizeSquare140: '3.25rem', - sizeSquare150: '3.5rem', - sizeSquare160: '3.75rem', - sizeSquare170: '4rem', - sizeSquare180: '4.25rem', - sizeSquare190: '4.5rem', - sizeSquare20: '0.25rem', - sizeSquare200: '4.75rem', - sizeSquare25: '0.375rem', - sizeSquare30: '0.5rem', - sizeSquare40: '0.75rem', - sizeSquare50: '1rem', - sizeSquare60: '1.25rem', - sizeSquare70: '1.5rem', - sizeSquare80: '1.75rem', - sizeSquare90: '2rem', + size0: "0", + size10: "5.5rem", + size100: "64rem", + size110: "70.5rem", + size120: "77rem", + size20: "12rem", + size30: "18.5rem", + size40: "25rem", + size50: "31.5rem", + size60: "38rem", + size70: "44.5rem", + size80: "51rem", + size90: "57.5rem", + sizeIcon10: "1rem", + sizeIcon100: "3.25rem", + sizeIcon110: "4rem", + sizeIcon20: "1.25rem", + sizeIcon30: "1.25rem", + sizeIcon40: "1.5rem", + sizeIcon50: "1.75rem", + sizeIcon60: "1.75rem", + sizeIcon70: "2rem", + sizeIcon80: "2.5rem", + sizeIcon90: "2.75rem", + sizeSidebar: "13.75rem", + sizeSquare0: "0", + sizeSquare10: "0.125rem", + sizeSquare100: "2.25rem", + sizeSquare110: "2.5rem", + sizeSquare120: "2.75rem", + sizeSquare130: "3rem", + sizeSquare140: "3.25rem", + sizeSquare150: "3.5rem", + sizeSquare160: "3.75rem", + sizeSquare170: "4rem", + sizeSquare180: "4.25rem", + sizeSquare190: "4.5rem", + sizeSquare20: "0.25rem", + sizeSquare200: "4.75rem", + sizeSquare25: "0.375rem", + sizeSquare30: "0.5rem", + sizeSquare40: "0.75rem", + sizeSquare50: "1rem", + sizeSquare60: "1.25rem", + sizeSquare70: "1.5rem", + sizeSquare80: "1.75rem", + sizeSquare90: "2rem", }, maxWidths: { - size0: '0', - size10: '5.5rem', - size100: '64rem', - size110: '70.5rem', - size120: '77rem', - size20: '12rem', - size30: '18.5rem', - size40: '25rem', - size50: '31.5rem', - size60: '38rem', - size70: '44.5rem', - size80: '51rem', - size90: '57.5rem', - sizeIcon10: '1rem', - sizeIcon100: '3.25rem', - sizeIcon110: '4rem', - sizeIcon20: '1.25rem', - sizeIcon30: '1.25rem', - sizeIcon40: '1.5rem', - sizeIcon50: '1.75rem', - sizeIcon60: '1.75rem', - sizeIcon70: '2rem', - sizeIcon80: '2.5rem', - sizeIcon90: '2.75rem', - sizeSidebar: '13.75rem', - sizeSquare0: '0', - sizeSquare10: '0.125rem', - sizeSquare100: '2.25rem', - sizeSquare110: '2.5rem', - sizeSquare120: '2.75rem', - sizeSquare130: '3rem', - sizeSquare140: '3.25rem', - sizeSquare150: '3.5rem', - sizeSquare160: '3.75rem', - sizeSquare170: '4rem', - sizeSquare180: '4.25rem', - sizeSquare190: '4.5rem', - sizeSquare20: '0.25rem', - sizeSquare200: '4.75rem', - sizeSquare25: '0.375rem', - sizeSquare30: '0.5rem', - sizeSquare40: '0.75rem', - sizeSquare50: '1rem', - sizeSquare60: '1.25rem', - sizeSquare70: '1.5rem', - sizeSquare80: '1.75rem', - sizeSquare90: '2rem', + size0: "0", + size10: "5.5rem", + size100: "64rem", + size110: "70.5rem", + size120: "77rem", + size20: "12rem", + size30: "18.5rem", + size40: "25rem", + size50: "31.5rem", + size60: "38rem", + size70: "44.5rem", + size80: "51rem", + size90: "57.5rem", + sizeIcon10: "1rem", + sizeIcon100: "3.25rem", + sizeIcon110: "4rem", + sizeIcon20: "1.25rem", + sizeIcon30: "1.25rem", + sizeIcon40: "1.5rem", + sizeIcon50: "1.75rem", + sizeIcon60: "1.75rem", + sizeIcon70: "2rem", + sizeIcon80: "2.5rem", + sizeIcon90: "2.75rem", + sizeSidebar: "13.75rem", + sizeSquare0: "0", + sizeSquare10: "0.125rem", + sizeSquare100: "2.25rem", + sizeSquare110: "2.5rem", + sizeSquare120: "2.75rem", + sizeSquare130: "3rem", + sizeSquare140: "3.25rem", + sizeSquare150: "3.5rem", + sizeSquare160: "3.75rem", + sizeSquare170: "4rem", + sizeSquare180: "4.25rem", + sizeSquare190: "4.5rem", + sizeSquare20: "0.25rem", + sizeSquare200: "4.75rem", + sizeSquare25: "0.375rem", + sizeSquare30: "0.5rem", + sizeSquare40: "0.75rem", + sizeSquare50: "1rem", + sizeSquare60: "1.25rem", + sizeSquare70: "1.5rem", + sizeSquare80: "1.75rem", + sizeSquare90: "2rem", }, minWidths: { - size0: '0', - size10: '5.5rem', - size100: '64rem', - size110: '70.5rem', - size120: '77rem', - size20: '12rem', - size30: '18.5rem', - size40: '25rem', - size50: '31.5rem', - size60: '38rem', - size70: '44.5rem', - size80: '51rem', - size90: '57.5rem', - sizeIcon10: '1rem', - sizeIcon100: '3.25rem', - sizeIcon110: '4rem', - sizeIcon20: '1.25rem', - sizeIcon30: '1.25rem', - sizeIcon40: '1.5rem', - sizeIcon50: '1.75rem', - sizeIcon60: '1.75rem', - sizeIcon70: '2rem', - sizeIcon80: '2.5rem', - sizeIcon90: '2.75rem', - sizeSidebar: '13.75rem', - sizeSquare0: '0', - sizeSquare10: '0.125rem', - sizeSquare100: '2.25rem', - sizeSquare110: '2.5rem', - sizeSquare120: '2.75rem', - sizeSquare130: '3rem', - sizeSquare140: '3.25rem', - sizeSquare150: '3.5rem', - sizeSquare160: '3.75rem', - sizeSquare170: '4rem', - sizeSquare180: '4.25rem', - sizeSquare190: '4.5rem', - sizeSquare20: '0.25rem', - sizeSquare200: '4.75rem', - sizeSquare25: '0.375rem', - sizeSquare30: '0.5rem', - sizeSquare40: '0.75rem', - sizeSquare50: '1rem', - sizeSquare60: '1.25rem', - sizeSquare70: '1.5rem', - sizeSquare80: '1.75rem', - sizeSquare90: '2rem', + size0: "0", + size10: "5.5rem", + size100: "64rem", + size110: "70.5rem", + size120: "77rem", + size20: "12rem", + size30: "18.5rem", + size40: "25rem", + size50: "31.5rem", + size60: "38rem", + size70: "44.5rem", + size80: "51rem", + size90: "57.5rem", + sizeIcon10: "1rem", + sizeIcon100: "3.25rem", + sizeIcon110: "4rem", + sizeIcon20: "1.25rem", + sizeIcon30: "1.25rem", + sizeIcon40: "1.5rem", + sizeIcon50: "1.75rem", + sizeIcon60: "1.75rem", + sizeIcon70: "2rem", + sizeIcon80: "2.5rem", + sizeIcon90: "2.75rem", + sizeSidebar: "13.75rem", + sizeSquare0: "0", + sizeSquare10: "0.125rem", + sizeSquare100: "2.25rem", + sizeSquare110: "2.5rem", + sizeSquare120: "2.75rem", + sizeSquare130: "3rem", + sizeSquare140: "3.25rem", + sizeSquare150: "3.5rem", + sizeSquare160: "3.75rem", + sizeSquare170: "4rem", + sizeSquare180: "4.25rem", + sizeSquare190: "4.5rem", + sizeSquare20: "0.25rem", + sizeSquare200: "4.75rem", + sizeSquare25: "0.375rem", + sizeSquare30: "0.5rem", + sizeSquare40: "0.75rem", + sizeSquare50: "1rem", + sizeSquare60: "1.25rem", + sizeSquare70: "1.5rem", + sizeSquare80: "1.75rem", + sizeSquare90: "2rem", }, heights: { - size0: '0', - size10: '5.5rem', - size100: '64rem', - size110: '70.5rem', - size120: '77rem', - size20: '12rem', - size30: '18.5rem', - size40: '25rem', - size50: '31.5rem', - size60: '38rem', - size70: '44.5rem', - size80: '51rem', - size90: '57.5rem', - sizeIcon10: '1rem', - sizeIcon100: '3.25rem', - sizeIcon110: '4rem', - sizeIcon20: '1.25rem', - sizeIcon30: '1.25rem', - sizeIcon40: '1.5rem', - sizeIcon50: '1.75rem', - sizeIcon60: '1.75rem', - sizeIcon70: '2rem', - sizeIcon80: '2.5rem', - sizeIcon90: '2.75rem', - sizeSidebar: '13.75rem', - sizeSquare0: '0', - sizeSquare10: '0.125rem', - sizeSquare100: '2.25rem', - sizeSquare110: '2.5rem', - sizeSquare120: '2.75rem', - sizeSquare130: '3rem', - sizeSquare140: '3.25rem', - sizeSquare150: '3.5rem', - sizeSquare160: '3.75rem', - sizeSquare170: '4rem', - sizeSquare180: '4.25rem', - sizeSquare190: '4.5rem', - sizeSquare20: '0.25rem', - sizeSquare200: '4.75rem', - sizeSquare25: '0.375rem', - sizeSquare30: '0.5rem', - sizeSquare40: '0.75rem', - sizeSquare50: '1rem', - sizeSquare60: '1.25rem', - sizeSquare70: '1.5rem', - sizeSquare80: '1.75rem', - sizeSquare90: '2rem', + size0: "0", + size10: "5.5rem", + size100: "64rem", + size110: "70.5rem", + size120: "77rem", + size20: "12rem", + size30: "18.5rem", + size40: "25rem", + size50: "31.5rem", + size60: "38rem", + size70: "44.5rem", + size80: "51rem", + size90: "57.5rem", + sizeIcon10: "1rem", + sizeIcon100: "3.25rem", + sizeIcon110: "4rem", + sizeIcon20: "1.25rem", + sizeIcon30: "1.25rem", + sizeIcon40: "1.5rem", + sizeIcon50: "1.75rem", + sizeIcon60: "1.75rem", + sizeIcon70: "2rem", + sizeIcon80: "2.5rem", + sizeIcon90: "2.75rem", + sizeSidebar: "13.75rem", + sizeSquare0: "0", + sizeSquare10: "0.125rem", + sizeSquare100: "2.25rem", + sizeSquare110: "2.5rem", + sizeSquare120: "2.75rem", + sizeSquare130: "3rem", + sizeSquare140: "3.25rem", + sizeSquare150: "3.5rem", + sizeSquare160: "3.75rem", + sizeSquare170: "4rem", + sizeSquare180: "4.25rem", + sizeSquare190: "4.5rem", + sizeSquare20: "0.25rem", + sizeSquare200: "4.75rem", + sizeSquare25: "0.375rem", + sizeSquare30: "0.5rem", + sizeSquare40: "0.75rem", + sizeSquare50: "1rem", + sizeSquare60: "1.25rem", + sizeSquare70: "1.5rem", + sizeSquare80: "1.75rem", + sizeSquare90: "2rem", }, maxHeights: { - size0: '0', - size10: '5.5rem', - size100: '64rem', - size110: '70.5rem', - size120: '77rem', - size20: '12rem', - size30: '18.5rem', - size40: '25rem', - size50: '31.5rem', - size60: '38rem', - size70: '44.5rem', - size80: '51rem', - size90: '57.5rem', - sizeIcon10: '1rem', - sizeIcon100: '3.25rem', - sizeIcon110: '4rem', - sizeIcon20: '1.25rem', - sizeIcon30: '1.25rem', - sizeIcon40: '1.5rem', - sizeIcon50: '1.75rem', - sizeIcon60: '1.75rem', - sizeIcon70: '2rem', - sizeIcon80: '2.5rem', - sizeIcon90: '2.75rem', - sizeSidebar: '13.75rem', - sizeSquare0: '0', - sizeSquare10: '0.125rem', - sizeSquare100: '2.25rem', - sizeSquare110: '2.5rem', - sizeSquare120: '2.75rem', - sizeSquare130: '3rem', - sizeSquare140: '3.25rem', - sizeSquare150: '3.5rem', - sizeSquare160: '3.75rem', - sizeSquare170: '4rem', - sizeSquare180: '4.25rem', - sizeSquare190: '4.5rem', - sizeSquare20: '0.25rem', - sizeSquare200: '4.75rem', - sizeSquare25: '0.375rem', - sizeSquare30: '0.5rem', - sizeSquare40: '0.75rem', - sizeSquare50: '1rem', - sizeSquare60: '1.25rem', - sizeSquare70: '1.5rem', - sizeSquare80: '1.75rem', - sizeSquare90: '2rem', + size0: "0", + size10: "5.5rem", + size100: "64rem", + size110: "70.5rem", + size120: "77rem", + size20: "12rem", + size30: "18.5rem", + size40: "25rem", + size50: "31.5rem", + size60: "38rem", + size70: "44.5rem", + size80: "51rem", + size90: "57.5rem", + sizeIcon10: "1rem", + sizeIcon100: "3.25rem", + sizeIcon110: "4rem", + sizeIcon20: "1.25rem", + sizeIcon30: "1.25rem", + sizeIcon40: "1.5rem", + sizeIcon50: "1.75rem", + sizeIcon60: "1.75rem", + sizeIcon70: "2rem", + sizeIcon80: "2.5rem", + sizeIcon90: "2.75rem", + sizeSidebar: "13.75rem", + sizeSquare0: "0", + sizeSquare10: "0.125rem", + sizeSquare100: "2.25rem", + sizeSquare110: "2.5rem", + sizeSquare120: "2.75rem", + sizeSquare130: "3rem", + sizeSquare140: "3.25rem", + sizeSquare150: "3.5rem", + sizeSquare160: "3.75rem", + sizeSquare170: "4rem", + sizeSquare180: "4.25rem", + sizeSquare190: "4.5rem", + sizeSquare20: "0.25rem", + sizeSquare200: "4.75rem", + sizeSquare25: "0.375rem", + sizeSquare30: "0.5rem", + sizeSquare40: "0.75rem", + sizeSquare50: "1rem", + sizeSquare60: "1.25rem", + sizeSquare70: "1.5rem", + sizeSquare80: "1.75rem", + sizeSquare90: "2rem", }, minHeights: { - size0: '0', - size10: '5.5rem', - size100: '64rem', - size110: '70.5rem', - size120: '77rem', - size20: '12rem', - size30: '18.5rem', - size40: '25rem', - size50: '31.5rem', - size60: '38rem', - size70: '44.5rem', - size80: '51rem', - size90: '57.5rem', - sizeIcon10: '1rem', - sizeIcon100: '3.25rem', - sizeIcon110: '4rem', - sizeIcon20: '1.25rem', - sizeIcon30: '1.25rem', - sizeIcon40: '1.5rem', - sizeIcon50: '1.75rem', - sizeIcon60: '1.75rem', - sizeIcon70: '2rem', - sizeIcon80: '2.5rem', - sizeIcon90: '2.75rem', - sizeSidebar: '13.75rem', - sizeSquare0: '0', - sizeSquare10: '0.125rem', - sizeSquare100: '2.25rem', - sizeSquare110: '2.5rem', - sizeSquare120: '2.75rem', - sizeSquare130: '3rem', - sizeSquare140: '3.25rem', - sizeSquare150: '3.5rem', - sizeSquare160: '3.75rem', - sizeSquare170: '4rem', - sizeSquare180: '4.25rem', - sizeSquare190: '4.5rem', - sizeSquare20: '0.25rem', - sizeSquare200: '4.75rem', - sizeSquare25: '0.375rem', - sizeSquare30: '0.5rem', - sizeSquare40: '0.75rem', - sizeSquare50: '1rem', - sizeSquare60: '1.25rem', - sizeSquare70: '1.5rem', - sizeSquare80: '1.75rem', - sizeSquare90: '2rem', + size0: "0", + size10: "5.5rem", + size100: "64rem", + size110: "70.5rem", + size120: "77rem", + size20: "12rem", + size30: "18.5rem", + size40: "25rem", + size50: "31.5rem", + size60: "38rem", + size70: "44.5rem", + size80: "51rem", + size90: "57.5rem", + sizeIcon10: "1rem", + sizeIcon100: "3.25rem", + sizeIcon110: "4rem", + sizeIcon20: "1.25rem", + sizeIcon30: "1.25rem", + sizeIcon40: "1.5rem", + sizeIcon50: "1.75rem", + sizeIcon60: "1.75rem", + sizeIcon70: "2rem", + sizeIcon80: "2.5rem", + sizeIcon90: "2.75rem", + sizeSidebar: "13.75rem", + sizeSquare0: "0", + sizeSquare10: "0.125rem", + sizeSquare100: "2.25rem", + sizeSquare110: "2.5rem", + sizeSquare120: "2.75rem", + sizeSquare130: "3rem", + sizeSquare140: "3.25rem", + sizeSquare150: "3.5rem", + sizeSquare160: "3.75rem", + sizeSquare170: "4rem", + sizeSquare180: "4.25rem", + sizeSquare190: "4.5rem", + sizeSquare20: "0.25rem", + sizeSquare200: "4.75rem", + sizeSquare25: "0.375rem", + sizeSquare30: "0.5rem", + sizeSquare40: "0.75rem", + sizeSquare50: "1rem", + sizeSquare60: "1.25rem", + sizeSquare70: "1.5rem", + sizeSquare80: "1.75rem", + sizeSquare90: "2rem", }, sizes: { - size0: '0', - size10: '5.5rem', - size100: '64rem', - size110: '70.5rem', - size120: '77rem', - size20: '12rem', - size30: '18.5rem', - size40: '25rem', - size50: '31.5rem', - size60: '38rem', - size70: '44.5rem', - size80: '51rem', - size90: '57.5rem', - sizeIcon10: '1rem', - sizeIcon100: '3.25rem', - sizeIcon110: '4rem', - sizeIcon20: '1.25rem', - sizeIcon30: '1.25rem', - sizeIcon40: '1.5rem', - sizeIcon50: '1.75rem', - sizeIcon60: '1.75rem', - sizeIcon70: '2rem', - sizeIcon80: '2.5rem', - sizeIcon90: '2.75rem', - sizeSidebar: '13.75rem', - sizeSquare0: '0', - sizeSquare10: '0.125rem', - sizeSquare100: '2.25rem', - sizeSquare110: '2.5rem', - sizeSquare120: '2.75rem', - sizeSquare130: '3rem', - sizeSquare140: '3.25rem', - sizeSquare150: '3.5rem', - sizeSquare160: '3.75rem', - sizeSquare170: '4rem', - sizeSquare180: '4.25rem', - sizeSquare190: '4.5rem', - sizeSquare20: '0.25rem', - sizeSquare200: '4.75rem', - sizeSquare25: '0.375rem', - sizeSquare30: '0.5rem', - sizeSquare40: '0.75rem', - sizeSquare50: '1rem', - sizeSquare60: '1.25rem', - sizeSquare70: '1.5rem', - sizeSquare80: '1.75rem', - sizeSquare90: '2rem', + size0: "0", + size10: "5.5rem", + size100: "64rem", + size110: "70.5rem", + size120: "77rem", + size20: "12rem", + size30: "18.5rem", + size40: "25rem", + size50: "31.5rem", + size60: "38rem", + size70: "44.5rem", + size80: "51rem", + size90: "57.5rem", + sizeIcon10: "1rem", + sizeIcon100: "3.25rem", + sizeIcon110: "4rem", + sizeIcon20: "1.25rem", + sizeIcon30: "1.25rem", + sizeIcon40: "1.5rem", + sizeIcon50: "1.75rem", + sizeIcon60: "1.75rem", + sizeIcon70: "2rem", + sizeIcon80: "2.5rem", + sizeIcon90: "2.75rem", + sizeSidebar: "13.75rem", + sizeSquare0: "0", + sizeSquare10: "0.125rem", + sizeSquare100: "2.25rem", + sizeSquare110: "2.5rem", + sizeSquare120: "2.75rem", + sizeSquare130: "3rem", + sizeSquare140: "3.25rem", + sizeSquare150: "3.5rem", + sizeSquare160: "3.75rem", + sizeSquare170: "4rem", + sizeSquare180: "4.25rem", + sizeSquare190: "4.5rem", + sizeSquare20: "0.25rem", + sizeSquare200: "4.75rem", + sizeSquare25: "0.375rem", + sizeSquare30: "0.5rem", + sizeSquare40: "0.75rem", + sizeSquare50: "1rem", + sizeSquare60: "1.25rem", + sizeSquare70: "1.5rem", + sizeSquare80: "1.75rem", + sizeSquare90: "2rem", }, iconSizes: { - sizeIcon10: '1rem', - sizeIcon20: '1.25rem', - sizeIcon30: '1.25rem', - sizeIcon40: '1.5rem', - sizeIcon50: '1.75rem', - sizeIcon60: '1.75rem', - sizeIcon70: '2rem', - sizeIcon80: '2.5rem', - sizeIcon90: '2.75rem', - sizeIcon100: '3.25rem', - sizeIcon110: '4rem', + sizeIcon10: "1rem", + sizeIcon20: "1.25rem", + sizeIcon30: "1.25rem", + sizeIcon40: "1.5rem", + sizeIcon50: "1.75rem", + sizeIcon60: "1.75rem", + sizeIcon70: "2rem", + sizeIcon80: "2.5rem", + sizeIcon90: "2.75rem", + sizeIcon100: "3.25rem", + sizeIcon110: "4rem", }, space: { - space0: '0', - space10: '0.125rem', - space100: '2.25rem', - space110: '2.5rem', - space120: '2.75rem', - space130: '3rem', - space140: '3.25rem', - space150: '3.5rem', - space160: '3.75rem', - space170: '4rem', - space180: '4.25rem', - space190: '4.5rem', - space20: '0.25rem', - space200: '4.75rem', - space30: '0.5rem', - space40: '0.75rem', - space50: '1rem', - space60: '1.25rem', - space70: '1.5rem', - space80: '1.75rem', - space90: '2rem', - spaceNegative10: '-0.125rem', - spaceNegative100: '-2.25rem', - spaceNegative110: '-2.5rem', - spaceNegative120: '-2.75rem', - spaceNegative130: '-3rem', - spaceNegative140: '-3.25rem', - spaceNegative150: '-3.5rem', - spaceNegative160: '-3.75rem', - spaceNegative170: '-4rem', - spaceNegative180: '-4.25rem', - spaceNegative190: '-4.5rem', - spaceNegative20: '-0.25rem', - spaceNegative200: '-4.75rem', - spaceNegative30: '-0.5rem', - spaceNegative40: '-0.75rem', - spaceNegative50: '-1rem', - spaceNegative60: '-1.25rem', - spaceNegative70: '-1.5rem', - spaceNegative80: '-1.75rem', - spaceNegative90: '-2rem', + space0: "0", + space10: "0.125rem", + space100: "2.25rem", + space110: "2.5rem", + space120: "2.75rem", + space130: "3rem", + space140: "3.25rem", + space150: "3.5rem", + space160: "3.75rem", + space170: "4rem", + space180: "4.25rem", + space190: "4.5rem", + space20: "0.25rem", + space200: "4.75rem", + space30: "0.5rem", + space40: "0.75rem", + space50: "1rem", + space60: "1.25rem", + space70: "1.5rem", + space80: "1.75rem", + space90: "2rem", + spaceNegative10: "-0.125rem", + spaceNegative100: "-2.25rem", + spaceNegative110: "-2.5rem", + spaceNegative120: "-2.75rem", + spaceNegative130: "-3rem", + spaceNegative140: "-3.25rem", + spaceNegative150: "-3.5rem", + spaceNegative160: "-3.75rem", + spaceNegative170: "-4rem", + spaceNegative180: "-4.25rem", + spaceNegative190: "-4.5rem", + spaceNegative20: "-0.25rem", + spaceNegative200: "-4.75rem", + spaceNegative30: "-0.5rem", + spaceNegative40: "-0.75rem", + spaceNegative50: "-1rem", + spaceNegative60: "-1.25rem", + spaceNegative70: "-1.5rem", + spaceNegative80: "-1.75rem", + spaceNegative90: "-2rem", }, zIndices: { - zIndex0: '0', - zIndex10: '10', - zIndex20: '20', - zIndex30: '30', - zIndex40: '40', - zIndex50: '50', - zIndex60: '60', - zIndex70: '70', - zIndex80: '80', - zIndex90: '90', + zIndex0: "0", + zIndex10: "10", + zIndex20: "20", + zIndex30: "30", + zIndex40: "40", + zIndex50: "50", + zIndex60: "60", + zIndex70: "70", + zIndex80: "80", + zIndex90: "90", }, }; diff --git a/.jest/setupFilesAfterEnv.js b/.jest/setupFilesAfterEnv.js index e8ca6a24ae..c851b340c5 100644 --- a/.jest/setupFilesAfterEnv.js +++ b/.jest/setupFilesAfterEnv.js @@ -1,3 +1,3 @@ -const {matchers: jestEmotionMatchers} = require('@emotion/jest'); -require('@testing-library/jest-dom'); +const { matchers: jestEmotionMatchers } = require("@emotion/jest"); +require("@testing-library/jest-dom"); expect.extend(jestEmotionMatchers); diff --git a/.prettierignore b/.prettierignore index 65b2df9986..42935c3dde 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,9 +1,20 @@ +**/*.ts +**/*.tsx +**/*.js +**/*.jsx +**/*.json +**/*.jsonc +**/*.css +**/*.md +**/*.mdx + node_modules bower_components dist bin __testfixtures__ +packages/paste-design-tokens/docs packages/paste-icons/cjs packages/paste-icons/esm packages/paste-icons/json diff --git a/.prettierrc.js b/.prettierrc.js index 0a31b363d4..9a719f06e0 100644 --- a/.prettierrc.js +++ b/.prettierrc.js @@ -1,14 +1,14 @@ module.exports = { printWidth: 120, - trailingComma: 'es5', - bracketSpacing: false, - singleQuote: true, + trailingComma: "es5", + bracketSpacing: true, + singleQuote: false, tabWidth: 2, overrides: [ { - files: '*.yml', + files: "*.yml", options: { - parser: 'yaml', + parser: "yaml", singleQuote: false, }, }, diff --git a/.storybook/RenderPerformanceProfiler.tsx b/.storybook/RenderPerformanceProfiler.tsx index f9c0c95268..1dc37e7f4e 100644 --- a/.storybook/RenderPerformanceProfiler.tsx +++ b/.storybook/RenderPerformanceProfiler.tsx @@ -1,23 +1,23 @@ +import isChromatic from "chromatic"; /// -import React from 'react'; -import isChromatic from 'chromatic'; -import {version} from '../packages/paste-core/core-bundle/package.json'; +import React from "react"; +import { version } from "../packages/paste-core/core-bundle/package.json"; const trackRenderPerformance = (data) => { - const commitSha = import.meta.env.STORYBOOK_GITHUB_SHA ? import.meta.env.STORYBOOK_GITHUB_SHA : 'localdev'; + const commitSha = import.meta.env.STORYBOOK_GITHUB_SHA ? import.meta.env.STORYBOOK_GITHUB_SHA : "localdev"; - fetch('https://paste-data.netlify.app/.netlify/functions/create-component-perf-metric', { - method: 'POST', + fetch("https://paste-data.netlify.app/.netlify/functions/create-component-perf-metric", { + method: "POST", keepalive: true, - mode: 'cors', + mode: "cors", // mix in the current git commit SHA, along with core bundle version number to profiler data. SHA is set via github actions when run in a PR - body: JSON.stringify({...data, commitSha, coreVersionNumber: version}), + body: JSON.stringify({ ...data, commitSha, coreVersionNumber: version }), }); }; -const IdentityComponent = ({children}) => <>{children}; +const IdentityComponent = ({ children }) => <>{children}; -const Profiler = ({id, kind, view, children}) => { +const Profiler = ({ id, kind, view, children }) => { return ( { +addons.register("paste-google-analytics", (api) => { if (!isChromatic()) { - ReactGA.initialize('G-1DZ9RS3QNT'); + ReactGA.initialize("G-1DZ9RS3QNT"); api.on(STORY_RENDERED, () => { - const {path} = api.getUrlState(); + const { path } = api.getUrlState(); ReactGA.pageview(path); }); - api.on(STORY_ERRORED, ({description}) => { + api.on(STORY_ERRORED, ({ description }) => { ReactGA.exception({ description, fatal: true, diff --git a/.storybook/main.ts b/.storybook/main.ts index 3c6ff84a1a..c85c0cfe1b 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -1,34 +1,34 @@ -import type {StorybookConfig} from '@storybook/react-vite'; -import {mergeConfig} from 'vite'; -import turbosnap from 'vite-plugin-turbosnap'; -import path from 'path'; +import path from "path"; +import type { StorybookConfig } from "@storybook/react-vite"; +import { mergeConfig } from "vite"; +import turbosnap from "vite-plugin-turbosnap"; const config: StorybookConfig = { stories: [ - '../packages/**/*.stories.@(js|jsx|ts|tsx|mdx)', - '../performance-benchmarks/**/*.stories.@(js|jsx|ts|tsx|mdx)', + "../packages/**/*.stories.@(js|jsx|ts|tsx|mdx)", + "../performance-benchmarks/**/*.stories.@(js|jsx|ts|tsx|mdx)", ], addons: [ - '@storybook/addon-links', - '@storybook/addon-essentials', - '@storybook/addon-a11y', - '@storybook/addon-interactions', - './addons/google-analytics/register', - '@storybook/addon-mdx-gfm', + "@storybook/addon-links", + "@storybook/addon-essentials", + "@storybook/addon-a11y", + "@storybook/addon-interactions", + "./addons/google-analytics/register", + "@storybook/addon-mdx-gfm", ], - framework: '@storybook/react-vite', + framework: "@storybook/react-vite", features: { interactionsDebugger: true, }, - staticDirs: ['./static'], + staticDirs: ["./static"], typescript: { // enable type checking check: true, }, - async viteFinal(config, {configType}) { - const isTest = process.env.NODE_ENV === 'test'; + async viteFinal(config, { configType }) { + const isTest = process.env.NODE_ENV === "test"; return mergeConfig(config, { plugins: - configType === 'PRODUCTION' + configType === "PRODUCTION" ? [ turbosnap({ rootDir: config.root ?? process.cwd(), @@ -37,24 +37,24 @@ const config: StorybookConfig = { : [], resolve: { alias: { - 'next/link': path.resolve(__dirname, './next'), - 'react-dom/client': path.resolve(__dirname, '../node_modules/react-dom/client'), - 'react-dom': path.resolve(__dirname, '../node_modules/react-dom/profiling'), - 'scheduler/tracing': path.resolve(__dirname, '../node_modules/scheduler/tracing-profiling'), + "next/link": path.resolve(__dirname, "./next"), + "react-dom/client": path.resolve(__dirname, "../node_modules/react-dom/client"), + "react-dom": path.resolve(__dirname, "../node_modules/react-dom/profiling"), + "scheduler/tracing": path.resolve(__dirname, "../node_modules/scheduler/tracing-profiling"), // Avoid initial render issues for code blocks in prod build - 'react-syntax-highlighter/dist/esm': path.resolve( + "react-syntax-highlighter/dist/esm": path.resolve( __dirname, - '../node_modules/react-syntax-highlighter/dist/cjs' + "../node_modules/react-syntax-highlighter/dist/cjs", ), - 'react-syntax-highlighter': path.resolve(__dirname, '../node_modules/react-syntax-highlighter/dist/cjs'), + "react-syntax-highlighter": path.resolve(__dirname, "../node_modules/react-syntax-highlighter/dist/cjs"), }, // Use source files for HMR and TurboSnap dependency map ...(!isTest && { - mainFields: ['main:dev', 'browser', 'module', 'main'], + mainFields: ["main:dev", "browser", "module", "main"], }), }, optimizeDeps: { - include: ['@storybook/addon-viewport', 'chromatic', '@emotion/react/jsx-dev-runtime'], + include: ["@storybook/addon-viewport", "chromatic", "@emotion/react/jsx-dev-runtime"], }, }); }, diff --git a/.storybook/next.tsx b/.storybook/next.tsx index 018202745d..b9a3c0c3d9 100644 --- a/.storybook/next.tsx +++ b/.storybook/next.tsx @@ -1,5 +1,5 @@ -import * as React from 'react'; +import * as React from "react"; -const Link: React.FC = ({children, ...props}) => {children}; +const Link: React.FC = ({ children, ...props }) => {children}; export default Link; diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index 207f9c2eca..f2207216c9 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -1,64 +1,64 @@ -import React from 'react'; -import {INITIAL_VIEWPORTS} from '@storybook/addon-viewport'; -import isChromatic from 'chromatic'; -import {StylingGlobals} from '@twilio-paste/styling-library'; -import {Theme} from '@twilio-paste/theme'; -import {Box} from '@twilio-paste/box'; -import {Stack} from '@twilio-paste/stack'; -import {Grid, Column} from '@twilio-paste/grid'; -import {RenderPerformanceProfiler} from './RenderPerformanceProfiler'; -import {SITE_BREAKPOINTS} from '../packages/paste-website/src/constants'; +import { INITIAL_VIEWPORTS } from "@storybook/addon-viewport"; +import { Box } from "@twilio-paste/box"; +import { Column, Grid } from "@twilio-paste/grid"; +import { Stack } from "@twilio-paste/stack"; +import { StylingGlobals } from "@twilio-paste/styling-library"; +import { Theme } from "@twilio-paste/theme"; +import isChromatic from "chromatic"; +import React from "react"; +import { SITE_BREAKPOINTS } from "../packages/paste-website/src/constants"; +import { RenderPerformanceProfiler } from "./RenderPerformanceProfiler"; // disable animations in test environments -const isTestEnvironment = isChromatic() || process.env.NODE_ENV === 'test'; +const isTestEnvironment = isChromatic() || process.env.NODE_ENV === "test"; export const globalTypes = { theme: { - name: 'Paste Theme', - description: 'Global theme for components', - defaultValue: 'twilio', + name: "Paste Theme", + description: "Global theme for components", + defaultValue: "twilio", toolbar: { // All available icons // https://github.com/storybookjs/storybook/blob/master/lib/components/src/icon/icons.tsx - icon: 'paintbrush', + icon: "paintbrush", // array of plain string values or MenuItem shape (see below) - items: ['default', 'dark', 'sendgrid', 'evergreen', 'twilio', 'twilio-dark'], + items: ["default", "dark", "sendgrid", "evergreen", "twilio", "twilio-dark"], }, }, theme_layout: { - name: 'Theme layout', - description: 'Choose how you wish to view the story themes', - defaultValue: isTestEnvironment ? 'stacked' : 'default', + name: "Theme layout", + description: "Choose how you wish to view the story themes", + defaultValue: isTestEnvironment ? "stacked" : "default", toolbar: { - icon: 'component', + icon: "component", items: [ - {value: 'default', title: 'default'}, - {value: 'side-by-side', title: 'side by side'}, - {value: 'stacked', title: 'stacked'}, + { value: "default", title: "default" }, + { value: "side-by-side", title: "side by side" }, + { value: "stacked", title: "stacked" }, ], }, }, locale: { - name: 'Locale', - description: 'Internationalization locale', - defaultValue: 'en', + name: "Locale", + description: "Internationalization locale", + defaultValue: "en", toolbar: { - icon: 'globe', + icon: "globe", items: [ - {value: 'en', right: 'LTR', title: 'English'}, - {value: 'rtl', right: 'RTL', title: 'English (RTL)'}, + { value: "en", right: "LTR", title: "English" }, + { value: "rtl", right: "RTL", title: "English (RTL)" }, ], }, }, breakpoints: { - name: 'Breakpoints', - description: 'Responsive breakpoint settings for ThemeProvider', + name: "Breakpoints", + description: "Responsive breakpoint settings for ThemeProvider", defaultValue: null, toolbar: { - icon: 'mobile', + icon: "mobile", items: [ - {value: null, title: 'Default Breakpoints'}, - {value: SITE_BREAKPOINTS, title: 'Docs Site Breakpoints'}, + { value: null, title: "Default Breakpoints" }, + { value: SITE_BREAKPOINTS, title: "Docs Site Breakpoints" }, ], }, }, @@ -68,7 +68,7 @@ const GlobalStyles = () => ( @@ -77,28 +77,28 @@ const GlobalStyles = () => ( // This collection of story ids will always be tested in VRT and our a11y test suites using // the default layout, rather than the stacked layout which renders the story across multiple // themes. This is important for stories that focus on an individual theme for example. -const FORCE_DEFAULT_LAYOUT_STORY_IDS = 'theme-themes--evergreen'.split(' '); +const FORCE_DEFAULT_LAYOUT_STORY_IDS = "theme-themes--evergreen".split(" "); export const decorators = [ (Story, context) => { const theme = context.globals.theme; - const layout = FORCE_DEFAULT_LAYOUT_STORY_IDS.includes(context.id) ? 'default' : context.globals.theme_layout; + const layout = FORCE_DEFAULT_LAYOUT_STORY_IDS.includes(context.id) ? "default" : context.globals.theme_layout; const lang = context.globals.locale; const breakpoints = context.globals.breakpoints; switch (lang) { - case 'rtl': - document.body.setAttribute('dir', 'rtl'); + case "rtl": + document.body.setAttribute("dir", "rtl"); break; default: - document.body.setAttribute('dir', 'ltr'); + document.body.setAttribute("dir", "ltr"); break; } switch (layout) { default: - case 'default': + case "default": return ( @@ -106,14 +106,14 @@ export const decorators = [ ); - case 'side-by-side': + case "side-by-side": return ( @@ -123,7 +123,7 @@ export const decorators = [ @@ -138,7 +138,7 @@ export const decorators = [ @@ -147,7 +147,7 @@ export const decorators = [ ); - case 'stacked': + case "stacked": return ( @@ -156,7 +156,7 @@ export const decorators = [ @@ -165,11 +165,11 @@ export const decorators = [ @@ -180,7 +180,7 @@ export const decorators = [ @@ -189,11 +189,11 @@ export const decorators = [ @@ -204,7 +204,7 @@ export const decorators = [ @@ -213,11 +213,11 @@ export const decorators = [ @@ -228,7 +228,7 @@ export const decorators = [ @@ -237,11 +237,11 @@ export const decorators = [ @@ -257,10 +257,10 @@ export const decorators = [ export const parameters = { isTestEnvironment, - actions: {argTypesRegex: '^on[A-Z].*'}, + actions: { argTypesRegex: "^on[A-Z].*" }, viewport: { viewports: INITIAL_VIEWPORTS, }, // Notifies Chromatic to pause the animations when they finish for all stories. - chromatic: {pauseAnimationAtEnd: true}, + chromatic: { pauseAnimationAtEnd: true }, }; diff --git a/.storybook/test-runner.js b/.storybook/test-runner.js index 9c958ad1dc..a2e69a19f8 100644 --- a/.storybook/test-runner.js +++ b/.storybook/test-runner.js @@ -1,5 +1,5 @@ -const {getStoryContext} = require('@storybook/test-runner'); -const {injectAxe, configureAxe, checkA11y} = require('axe-playwright'); +const { getStoryContext } = require("@storybook/test-runner"); +const { injectAxe, configureAxe, checkA11y } = require("axe-playwright"); const a11yConfig = { async preRender(page, context) { @@ -18,27 +18,27 @@ const a11yConfig = { rules: [ { // Page level test that states one main element is present. Not applicable for isolated components. - id: 'landmark-unique', + id: "landmark-unique", enabled: false, }, { // Page level test that states one main element is present. Not applicable for isolated components. - id: 'landmark-one-main', + id: "landmark-one-main", enabled: false, }, { // Page level test that states one h1 element is present. Not applicable for isolated components. - id: 'page-has-heading-one', + id: "page-has-heading-one", enabled: false, }, { // Page level test that states all page content must be contained by landmarks. Not applicable for isolated components. - id: 'region', + id: "region", enabled: false, }, { // Rule that dictates that long scrolling content should have a focusable element. Not applicable when we don't control the component children. - id: 'scrollable-region-focusable', + id: "scrollable-region-focusable", enabled: false, }, // allow individual stories to configure axe-playwright rules by setting story parameters. diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 4b73c55736..324310b6cb 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -2,6 +2,7 @@ "recommendations": [ "dbaeumer.vscode-eslint", "esbenp.prettier-vscode", + "biomejs.biome", "unifiedjs.vscode-mdx", "styled-components.vscode-styled-components", "eamodio.gitlens", diff --git a/.vscode/settings.json b/.vscode/settings.json index 5c92698921..0b70e07a67 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,24 @@ { "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.organizeImports.biome": true + }, "editor.defaultFormatter": "esbenp.prettier-vscode", + "[javascript]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[typescript]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[json]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[css]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[jsonc]": { + "editor.defaultFormatter": "biomejs.biome" + }, "search.exclude": { "**/dist": true, "**/docs": true diff --git a/apps/vs-code-intellisense/src/extension.ts b/apps/vs-code-intellisense/src/extension.ts index b8aa5d72af..f845f4c059 100644 --- a/apps/vs-code-intellisense/src/extension.ts +++ b/apps/vs-code-intellisense/src/extension.ts @@ -1,12 +1,12 @@ +import camelCase from "lodash.camelcase"; +import kebabCase from "lodash.kebabcase"; // The module 'vscode' contains the VS Code extensibility API // Import the module and reference it with the alias vscode in your code below -import * as vscode from 'vscode'; -import camelCase from 'lodash.camelcase'; -import kebabCase from 'lodash.kebabcase'; +import * as vscode from "vscode"; -import {pasteTokenAttributes} from './tokens'; -import {PasteToken} from './types'; -import {getColorPreview, getThemeSetting, getThemeTokens, remToPx, isColorCategory} from './utils'; +import { pasteTokenAttributes } from "./tokens"; +import { PasteToken } from "./types"; +import { getColorPreview, getThemeSetting, getThemeTokens, isColorCategory, remToPx } from "./utils"; const DIVIDER = `___\n`; @@ -22,12 +22,12 @@ export function findPasteToken(word?: string): PasteToken | undefined { } export function getAttributeName(linePrefix: string) { - let attributeName = ''; + let attributeName = ""; for (let endIdx = linePrefix.length - 2; endIdx >= 0; endIdx -= 1) { - if (linePrefix[endIdx] === ' ') { + if (linePrefix[endIdx] === " ") { break; } - if (linePrefix[endIdx] === '=') { + if (linePrefix[endIdx] === "=") { continue; } attributeName = linePrefix[endIdx] + attributeName; @@ -37,9 +37,9 @@ export function getAttributeName(linePrefix: string) { } export function getCompletionItem(token: PasteToken) { - const {name, value, type} = token; + const { name, value, type } = token; const label = camelCase(name); - if (type === 'color') { + if (type === "color") { return { label, documentation: value, @@ -69,7 +69,7 @@ export function activate(context: vscode.ExtensionContext) { console.log('Congratulations, your extension "vs-code-intellisense" is now active!'); const hoverProvider = vscode.languages.registerHoverProvider( - ['javascript', 'typescript', 'javascriptreact', 'typescriptreact'], + ["javascript", "typescript", "javascriptreact", "typescriptreact"], { provideHover(document, position) { const word = document.getText(document.getWordRangeAtPosition(position)); @@ -80,7 +80,7 @@ export function activate(context: vscode.ExtensionContext) { const hoverMessage = new vscode.MarkdownString(); - const {name, value, comment, category} = foundPasteToken; + const { name, value, comment, category } = foundPasteToken; // Run any formatters/converters on value before appending const formattedValue = remToPx(value); @@ -100,11 +100,11 @@ export function activate(context: vscode.ExtensionContext) { return new vscode.Hover(hoverMessage); }, - } + }, ); const completionProvider = vscode.languages.registerCompletionItemProvider( - ['javascript', 'typescript', 'javascriptreact', 'typescriptreact'], + ["javascript", "typescript", "javascriptreact", "typescriptreact"], { provideCompletionItems(document: vscode.TextDocument, position: vscode.Position) { const linePrefix = document.lineAt(position).text.slice(0, position.character); @@ -113,10 +113,10 @@ export function activate(context: vscode.ExtensionContext) { const items = getAttributeTokens(attributeName); - return {isIncomplete: false, items}; + return { isIncomplete: false, items }; }, }, - '"' // triggered when we type '"' + '"', // triggered when we type '"' ); context.subscriptions.push(hoverProvider); diff --git a/apps/vs-code-intellisense/src/test/runTest.ts b/apps/vs-code-intellisense/src/test/runTest.ts index 78330f7c30..2a42bb56aa 100644 --- a/apps/vs-code-intellisense/src/test/runTest.ts +++ b/apps/vs-code-intellisense/src/test/runTest.ts @@ -1,20 +1,20 @@ -import * as path from 'path'; -import {runTests} from '@vscode/test-electron'; +import * as path from "path"; +import { runTests } from "@vscode/test-electron"; async function main() { try { // The folder containing the Extension Manifest package.json // Passed to `--extensionDevelopmentPath` - const extensionDevelopmentPath = path.resolve(__dirname, '../../'); + const extensionDevelopmentPath = path.resolve(__dirname, "../../"); // The path to test runner // Passed to --extensionTestsPath - const extensionTestsPath = path.resolve(__dirname, './suite/index'); + const extensionTestsPath = path.resolve(__dirname, "./suite/index"); // Download VS Code, unzip it and run the integration test - await runTests({extensionDevelopmentPath, extensionTestsPath}); + await runTests({ extensionDevelopmentPath, extensionTestsPath }); } catch (err) { - console.error('Failed to run tests', err); + console.error("Failed to run tests", err); process.exit(1); } } diff --git a/apps/vs-code-intellisense/src/test/suite/extension.test.ts b/apps/vs-code-intellisense/src/test/suite/extension.test.ts index 5cc36cff32..a28347df30 100644 --- a/apps/vs-code-intellisense/src/test/suite/extension.test.ts +++ b/apps/vs-code-intellisense/src/test/suite/extension.test.ts @@ -1,147 +1,147 @@ -import assert from 'assert'; -import vscode from 'vscode'; +import assert from "assert"; +import vscode from "vscode"; -import * as myExtension from '../../extension'; +import * as myExtension from "../../extension"; -suite('Extension Test Suite', () => { - vscode.window.showInformationMessage('Start all tests.'); +suite("Extension Test Suite", () => { + vscode.window.showInformationMessage("Start all tests."); - suite('findPasteToken', () => { - test('when we find twilio paste token', () => { - const colorBackgroundWord = 'colorBackground'; + suite("findPasteToken", () => { + test("when we find twilio paste token", () => { + const colorBackgroundWord = "colorBackground"; const colorBackgroundToken = myExtension.findPasteToken(colorBackgroundWord); - assert.strictEqual(colorBackgroundToken?.name, 'color-background'); - assert.strictEqual(colorBackgroundToken?.value, '#f4f4f6'); - assert.strictEqual(colorBackgroundToken?.comment, 'Default background color for any container.'); + assert.strictEqual(colorBackgroundToken?.name, "color-background"); + assert.strictEqual(colorBackgroundToken?.value, "#f4f4f6"); + assert.strictEqual(colorBackgroundToken?.comment, "Default background color for any container."); - const fontSize10Word = 'fontSize10'; + const fontSize10Word = "fontSize10"; const fontSize10Token = myExtension.findPasteToken(fontSize10Word); - assert.strictEqual(fontSize10Token?.name, 'font-size-10'); - assert.strictEqual(fontSize10Token?.value, '0.625rem'); - assert.strictEqual(fontSize10Token?.comment, 'Constant typography token for font size 10'); + assert.strictEqual(fontSize10Token?.name, "font-size-10"); + assert.strictEqual(fontSize10Token?.value, "0.625rem"); + assert.strictEqual(fontSize10Token?.comment, "Constant typography token for font size 10"); - const colorTextWord = 'colorText'; + const colorTextWord = "colorText"; const colorTextToken = myExtension.findPasteToken(colorTextWord); - assert.strictEqual(colorTextToken?.name, 'color-text'); - assert.strictEqual(colorTextToken?.value, '#121c2d'); - assert.strictEqual(colorTextToken?.comment, 'Body text color'); + assert.strictEqual(colorTextToken?.name, "color-text"); + assert.strictEqual(colorTextToken?.value, "#121c2d"); + assert.strictEqual(colorTextToken?.comment, "Body text color"); }); - test('when we don`t find twilio paste token', () => { - const borderWidth0Word = 'borderWidth0'; + test("when we don`t find twilio paste token", () => { + const borderWidth0Word = "borderWidth0"; const borderWidth0Token = myExtension.findPasteToken(borderWidth0Word); - assert.strictEqual(borderWidth0Token?.name, 'border-width-0'); - assert.strictEqual(borderWidth0Token?.value, '0'); + assert.strictEqual(borderWidth0Token?.name, "border-width-0"); + assert.strictEqual(borderWidth0Token?.value, "0"); - const notFoundWord = 'notFoundWord'; + const notFoundWord = "notFoundWord"; const notFoundToken = myExtension.findPasteToken(notFoundWord); assert.strictEqual(notFoundToken, undefined); }); - test('when word is undefined', () => { + test("when word is undefined", () => { const result = myExtension.findPasteToken(undefined); assert.strictEqual(result, undefined); }); }); - suite('getAttributeName', () => { - test('when attribute name is correct', () => { + suite("getAttributeName", () => { + test("when attribute name is correct", () => { const marginLeftPrefix = '
{ + test("when attribute name is not correct", () => { const marginLeftPrefix = '
{ - test('paste token items by attribute name', () => { - const borderRadiusToken = myExtension.getAttributeTokens('borderRadius'); + suite("getAttributeTokens", () => { + test("paste token items by attribute name", () => { + const borderRadiusToken = myExtension.getAttributeTokens("borderRadius"); assert.strictEqual(borderRadiusToken.length, 6); - const zIndexToken = myExtension.getAttributeTokens('zIndex'); + const zIndexToken = myExtension.getAttributeTokens("zIndex"); assert.strictEqual(zIndexToken.length, 10); }); - test('when attribute name is not correct and empty', () => { - const borderRadiusToken = myExtension.getAttributeTokens('borderRadi'); + test("when attribute name is not correct and empty", () => { + const borderRadiusToken = myExtension.getAttributeTokens("borderRadi"); assert.strictEqual(borderRadiusToken.length, 0); - const zIndexToken = myExtension.getAttributeTokens(''); + const zIndexToken = myExtension.getAttributeTokens(""); assert.strictEqual(zIndexToken.length, 0); }); }); - suite('getCompletionItem', () => { - test('returns completion color item when type is color', () => { + suite("getCompletionItem", () => { + test("returns completion color item when type is color", () => { const result = myExtension.getCompletionItem({ - type: 'color', - category: 'background-color', - value: '#1f304c', - comment: 'Strong default background color.', - name: 'color-background-strong', + type: "color", + category: "background-color", + value: "#1f304c", + comment: "Strong default background color.", + name: "color-background-strong", }); const expected = { - label: 'colorBackgroundStrong', - documentation: '#1f304c', + label: "colorBackgroundStrong", + documentation: "#1f304c", kind: vscode.CompletionItemKind.Color, - detail: '#1f304c', + detail: "#1f304c", }; assert.deepStrictEqual(result, expected); }); - test('returns basic completion when type is not color', () => { + test("returns basic completion when type is not color", () => { const result = myExtension.getCompletionItem({ - type: 'size', - category: 'radius', - value: '0', - comment: 'Border radius reset', - name: 'border-radius-0', + type: "size", + category: "radius", + value: "0", + comment: "Border radius reset", + name: "border-radius-0", }); const expected = new vscode.CompletionItem( { - description: '0', - label: 'borderRadius0', + description: "0", + label: "borderRadius0", }, - vscode.CompletionItemKind.Constant + vscode.CompletionItemKind.Constant, ); assert.deepStrictEqual(result, expected); }); diff --git a/apps/vs-code-intellisense/src/test/suite/index.ts b/apps/vs-code-intellisense/src/test/suite/index.ts index 6fce3bc95b..43f5dd0020 100644 --- a/apps/vs-code-intellisense/src/test/suite/index.ts +++ b/apps/vs-code-intellisense/src/test/suite/index.ts @@ -1,18 +1,18 @@ -import * as path from 'path'; -import Mocha from 'mocha'; -import glob from 'glob'; +import * as path from "path"; +import glob from "glob"; +import Mocha from "mocha"; export function run(): Promise { // Create the mocha test const mocha = new Mocha({ - ui: 'tdd', + ui: "tdd", color: true, }); - const testsRoot = path.resolve(__dirname, '..'); + const testsRoot = path.resolve(__dirname, ".."); return new Promise((c, e) => { - glob('**/**.test.js', {cwd: testsRoot}, (err: any, files: string[]) => { + glob("**/**.test.js", { cwd: testsRoot }, (err: any, files: string[]) => { if (err) { return e(err); } diff --git a/apps/vs-code-intellisense/src/test/suite/utils/get-theme-tokens.test.ts b/apps/vs-code-intellisense/src/test/suite/utils/get-theme-tokens.test.ts index 78607f0b06..23487a2592 100644 --- a/apps/vs-code-intellisense/src/test/suite/utils/get-theme-tokens.test.ts +++ b/apps/vs-code-intellisense/src/test/suite/utils/get-theme-tokens.test.ts @@ -1,6 +1,5 @@ -import assert from 'assert'; +import assert from "assert"; -import {getThemeTokens} from '../../../utils'; import { darkThemeTokens, defaultThemeTokens, @@ -8,11 +7,12 @@ import { sendGridThemeTokens, twilioDarkThemeTokens, twilioThemeTokens, -} from '../../../tokens'; -import {Theme} from '../../../types'; +} from "../../../tokens"; +import { Theme } from "../../../types"; +import { getThemeTokens } from "../../../utils"; -suite('getThemeTokens', () => { - ['Default', 'default', undefined, null, 'foo'].forEach((theme) => { +suite("getThemeTokens", () => { + ["Default", "default", undefined, null, "foo"].forEach((theme) => { test(`when theme is '${theme}', returns defaultThemeTokens`, () => { const result = getThemeTokens(theme as Theme | undefined); @@ -21,31 +21,31 @@ suite('getThemeTokens', () => { }); test(`when theme is 'Dark', returns darkThemeTokens`, () => { - const result = getThemeTokens('Dark'); + const result = getThemeTokens("Dark"); assert.strictEqual(result, darkThemeTokens); }); test(`when theme is 'Evergreen', returns evergreenThemeTokens`, () => { - const result = getThemeTokens('Evergreen'); + const result = getThemeTokens("Evergreen"); assert.strictEqual(result, evergreenThemeTokens); }); test(`when theme is 'SendGrid', returns sendGridThemeTokens`, () => { - const result = getThemeTokens('SendGrid'); + const result = getThemeTokens("SendGrid"); assert.strictEqual(result, sendGridThemeTokens); }); test(`when theme is 'Twilio', returns twilioThemeTokens`, () => { - const result = getThemeTokens('Twilio'); + const result = getThemeTokens("Twilio"); assert.strictEqual(result, twilioThemeTokens); }); test(`when theme is 'Twilio Dark', returns twilioDarkThemeTokens`, () => { - const result = getThemeTokens('Twilio Dark'); + const result = getThemeTokens("Twilio Dark"); assert.strictEqual(result, twilioDarkThemeTokens); }); diff --git a/apps/vs-code-intellisense/src/test/suite/utils/is-color-category.test.ts b/apps/vs-code-intellisense/src/test/suite/utils/is-color-category.test.ts index 74bd805264..8946d025a0 100644 --- a/apps/vs-code-intellisense/src/test/suite/utils/is-color-category.test.ts +++ b/apps/vs-code-intellisense/src/test/suite/utils/is-color-category.test.ts @@ -1,25 +1,25 @@ -import assert from 'assert'; +import assert from "assert"; -import {isColorCategory} from '../../../utils/is-color-category'; -import {TokenCategory} from '../../../types'; +import { TokenCategory } from "../../../types"; +import { isColorCategory } from "../../../utils/is-color-category"; -const COLOR_CATEGORIES: TokenCategory[] = ['border-color', 'background-color', 'color', 'text-color']; +const COLOR_CATEGORIES: TokenCategory[] = ["border-color", "background-color", "color", "text-color"]; const NON_COLOR_CATEGORIES: TokenCategory[] = [ - 'radius', - 'border-width', - 'box-shadow', - 'data-visualization', - 'font', - 'font-size', - 'font-weight', - 'line-height', - 'sizing', - 'spacing', - 'z-index', + "radius", + "border-width", + "box-shadow", + "data-visualization", + "font", + "font-size", + "font-weight", + "line-height", + "sizing", + "spacing", + "z-index", ]; -suite('isColorCategory', () => { +suite("isColorCategory", () => { COLOR_CATEGORIES.forEach((category) => { test(`should return true for ${category}`, () => { assert.strictEqual(true, isColorCategory(category)); diff --git a/apps/vs-code-intellisense/src/test/suite/utils/rem-to-px.test.ts b/apps/vs-code-intellisense/src/test/suite/utils/rem-to-px.test.ts index f84b7bb568..60d8dc24fa 100644 --- a/apps/vs-code-intellisense/src/test/suite/utils/rem-to-px.test.ts +++ b/apps/vs-code-intellisense/src/test/suite/utils/rem-to-px.test.ts @@ -1,37 +1,37 @@ -import assert from 'assert'; +import assert from "assert"; -import {remToPx} from '../../../utils/rem-to-px'; +import { remToPx } from "../../../utils/rem-to-px"; -suite('remToPx', () => { +suite("remToPx", () => { test("when 'rem' is not found in value, returns unmodified string", () => { - const value = '0'; + const value = "0"; const result = remToPx(value); assert.strictEqual(result, value); }); - test('converts 0.5rem to 8px', () => { - const value = '0.5rem'; + test("converts 0.5rem to 8px", () => { + const value = "0.5rem"; const result = remToPx(value); - assert.strictEqual(result, '0.5rem (8px)'); + assert.strictEqual(result, "0.5rem (8px)"); }); - test('converts 1rem to 16px', () => { - const value = '1rem'; + test("converts 1rem to 16px", () => { + const value = "1rem"; const result = remToPx(value); - assert.strictEqual(result, '1rem (16px)'); + assert.strictEqual(result, "1rem (16px)"); }); - test('gracefully handles extra whitespace on either side of rem value', () => { - const value = ' 1 rem'; + test("gracefully handles extra whitespace on either side of rem value", () => { + const value = " 1 rem"; const result = remToPx(value); - assert.strictEqual(result, '1rem (16px)'); + assert.strictEqual(result, "1rem (16px)"); }); }); diff --git a/apps/vs-code-intellisense/src/tokens/dark-theme-tokens.ts b/apps/vs-code-intellisense/src/tokens/dark-theme-tokens.ts index 2e15c7392c..efa9d0263f 100644 --- a/apps/vs-code-intellisense/src/tokens/dark-theme-tokens.ts +++ b/apps/vs-code-intellisense/src/tokens/dark-theme-tokens.ts @@ -1 +1 @@ -export {props as darkThemeTokens} from '@twilio-paste/design-tokens/dist/themes/dark/tokens.raw.json'; +export { props as darkThemeTokens } from "@twilio-paste/design-tokens/dist/themes/dark/tokens.raw.json"; diff --git a/apps/vs-code-intellisense/src/tokens/default-theme-tokens.ts b/apps/vs-code-intellisense/src/tokens/default-theme-tokens.ts index 3353e12539..5c9e10899f 100644 --- a/apps/vs-code-intellisense/src/tokens/default-theme-tokens.ts +++ b/apps/vs-code-intellisense/src/tokens/default-theme-tokens.ts @@ -1 +1 @@ -export {props as defaultThemeTokens} from '@twilio-paste/design-tokens/dist/tokens.raw.json'; +export { props as defaultThemeTokens } from "@twilio-paste/design-tokens/dist/tokens.raw.json"; diff --git a/apps/vs-code-intellisense/src/tokens/evergreen-theme-tokens.ts b/apps/vs-code-intellisense/src/tokens/evergreen-theme-tokens.ts index cc3d944b13..34a66f8e45 100644 --- a/apps/vs-code-intellisense/src/tokens/evergreen-theme-tokens.ts +++ b/apps/vs-code-intellisense/src/tokens/evergreen-theme-tokens.ts @@ -1 +1 @@ -export {props as evergreenThemeTokens} from '@twilio-paste/design-tokens/dist/themes/evergreen/tokens.raw.json'; +export { props as evergreenThemeTokens } from "@twilio-paste/design-tokens/dist/themes/evergreen/tokens.raw.json"; diff --git a/apps/vs-code-intellisense/src/tokens/index.ts b/apps/vs-code-intellisense/src/tokens/index.ts index a3701027e0..bbedf4533d 100644 --- a/apps/vs-code-intellisense/src/tokens/index.ts +++ b/apps/vs-code-intellisense/src/tokens/index.ts @@ -1,7 +1,7 @@ -export * from './dark-theme-tokens'; -export * from './default-theme-tokens'; -export * from './evergreen-theme-tokens'; -export * from './paste-token-attributes'; -export * from './sendgrid-theme-tokens'; -export * from './twilio-theme-tokens'; -export * from './twilio-dark-theme-tokens'; +export * from "./dark-theme-tokens"; +export * from "./default-theme-tokens"; +export * from "./evergreen-theme-tokens"; +export * from "./paste-token-attributes"; +export * from "./sendgrid-theme-tokens"; +export * from "./twilio-theme-tokens"; +export * from "./twilio-dark-theme-tokens"; diff --git a/apps/vs-code-intellisense/src/tokens/paste-token-attributes.ts b/apps/vs-code-intellisense/src/tokens/paste-token-attributes.ts index 7bcaf3ec59..e9dacf417b 100644 --- a/apps/vs-code-intellisense/src/tokens/paste-token-attributes.ts +++ b/apps/vs-code-intellisense/src/tokens/paste-token-attributes.ts @@ -1,43 +1,43 @@ -import {TokenCategory} from '../types'; +import { TokenCategory } from "../types"; export const pasteTokenAttributes: Record = { - margin: 'spacing', - marginTop: 'spacing', - marginRight: 'spacing', - marginBottom: 'spacing', - marginLeft: 'spacing', - marginX: 'spacing', - marginY: 'spacing', - padding: 'spacing', - paddingTop: 'spacing', - paddingRight: 'spacing', - paddingBottom: 'spacing', - paddingLeft: 'spacing', - paddingX: 'spacing', - paddingY: 'spacing', - borderRadius: 'radius', - borderTopLeftRadius: 'radius', - borderTopRightRadius: 'radius', - borderBottomRightRadius: 'radius', - borderBottomLeftRadius: 'radius', - borderWidth: 'border-width', - borderTopWidth: 'border-width', - borderRightWidth: 'border-width', - borderBottomWidth: 'border-width', - borderLeftWidth: 'border-width', - borderColor: 'border-color', - borderTopColor: 'border-color', - borderRightColor: 'border-color', - borderBottomColor: 'border-color', - borderLeftColor: 'border-color', - zIndex: 'z-index', - backgroundColor: 'background-color', - columnGap: 'spacing', - rowGap: 'spacing', - boxShadow: 'box-shadow', - fontSize: 'font-size', - fontWeight: 'font-weight', - lineHeight: 'line-height', - color: 'text-color', - size: 'sizing', + margin: "spacing", + marginTop: "spacing", + marginRight: "spacing", + marginBottom: "spacing", + marginLeft: "spacing", + marginX: "spacing", + marginY: "spacing", + padding: "spacing", + paddingTop: "spacing", + paddingRight: "spacing", + paddingBottom: "spacing", + paddingLeft: "spacing", + paddingX: "spacing", + paddingY: "spacing", + borderRadius: "radius", + borderTopLeftRadius: "radius", + borderTopRightRadius: "radius", + borderBottomRightRadius: "radius", + borderBottomLeftRadius: "radius", + borderWidth: "border-width", + borderTopWidth: "border-width", + borderRightWidth: "border-width", + borderBottomWidth: "border-width", + borderLeftWidth: "border-width", + borderColor: "border-color", + borderTopColor: "border-color", + borderRightColor: "border-color", + borderBottomColor: "border-color", + borderLeftColor: "border-color", + zIndex: "z-index", + backgroundColor: "background-color", + columnGap: "spacing", + rowGap: "spacing", + boxShadow: "box-shadow", + fontSize: "font-size", + fontWeight: "font-weight", + lineHeight: "line-height", + color: "text-color", + size: "sizing", }; diff --git a/apps/vs-code-intellisense/src/tokens/sendgrid-theme-tokens.ts b/apps/vs-code-intellisense/src/tokens/sendgrid-theme-tokens.ts index c2bcee8f9c..135ed5e56a 100644 --- a/apps/vs-code-intellisense/src/tokens/sendgrid-theme-tokens.ts +++ b/apps/vs-code-intellisense/src/tokens/sendgrid-theme-tokens.ts @@ -1 +1 @@ -export {props as sendGridThemeTokens} from '@twilio-paste/design-tokens/dist/themes/sendgrid/tokens.raw.json'; +export { props as sendGridThemeTokens } from "@twilio-paste/design-tokens/dist/themes/sendgrid/tokens.raw.json"; diff --git a/apps/vs-code-intellisense/src/tokens/twilio-dark-theme-tokens.ts b/apps/vs-code-intellisense/src/tokens/twilio-dark-theme-tokens.ts index 9a1d90ca39..62243985d0 100644 --- a/apps/vs-code-intellisense/src/tokens/twilio-dark-theme-tokens.ts +++ b/apps/vs-code-intellisense/src/tokens/twilio-dark-theme-tokens.ts @@ -1 +1 @@ -export {props as twilioDarkThemeTokens} from '@twilio-paste/design-tokens/dist/themes/twilio-dark/tokens.raw.json'; +export { props as twilioDarkThemeTokens } from "@twilio-paste/design-tokens/dist/themes/twilio-dark/tokens.raw.json"; diff --git a/apps/vs-code-intellisense/src/tokens/twilio-theme-tokens.ts b/apps/vs-code-intellisense/src/tokens/twilio-theme-tokens.ts index bf49d2231a..5d9d0dc89f 100644 --- a/apps/vs-code-intellisense/src/tokens/twilio-theme-tokens.ts +++ b/apps/vs-code-intellisense/src/tokens/twilio-theme-tokens.ts @@ -1 +1 @@ -export {props as twilioThemeTokens} from '@twilio-paste/design-tokens/dist/themes/twilio/tokens.raw.json'; +export { props as twilioThemeTokens } from "@twilio-paste/design-tokens/dist/themes/twilio/tokens.raw.json"; diff --git a/apps/vs-code-intellisense/src/types/index.ts b/apps/vs-code-intellisense/src/types/index.ts index 9f96fae9cf..91815f311d 100644 --- a/apps/vs-code-intellisense/src/types/index.ts +++ b/apps/vs-code-intellisense/src/types/index.ts @@ -1,5 +1,5 @@ -export * from './paste-token'; -export * from './themes'; -export * from './token-category'; -export * from './token-map'; -export * from './token-type'; +export * from "./paste-token"; +export * from "./themes"; +export * from "./token-category"; +export * from "./token-map"; +export * from "./token-type"; diff --git a/apps/vs-code-intellisense/src/types/paste-token.ts b/apps/vs-code-intellisense/src/types/paste-token.ts index f22cdb745a..21d920ce16 100644 --- a/apps/vs-code-intellisense/src/types/paste-token.ts +++ b/apps/vs-code-intellisense/src/types/paste-token.ts @@ -1,5 +1,5 @@ -import {TokenCategory} from './token-category'; -import {TokenType} from './token-type'; +import { TokenCategory } from "./token-category"; +import { TokenType } from "./token-type"; export interface PasteToken { name: string; diff --git a/apps/vs-code-intellisense/src/types/themes.ts b/apps/vs-code-intellisense/src/types/themes.ts index 59874c58ae..548c00022a 100644 --- a/apps/vs-code-intellisense/src/types/themes.ts +++ b/apps/vs-code-intellisense/src/types/themes.ts @@ -1 +1 @@ -export type Theme = 'Default' | 'Dark' | 'SendGrid' | 'Twilio' | 'Twilio Dark' | 'Evergreen'; +export type Theme = "Default" | "Dark" | "SendGrid" | "Twilio" | "Twilio Dark" | "Evergreen"; diff --git a/apps/vs-code-intellisense/src/types/token-category.ts b/apps/vs-code-intellisense/src/types/token-category.ts index 17c9c3a44f..158dd93576 100644 --- a/apps/vs-code-intellisense/src/types/token-category.ts +++ b/apps/vs-code-intellisense/src/types/token-category.ts @@ -1,16 +1,16 @@ export type TokenCategory = - | 'background-color' - | 'border-color' - | 'radius' - | 'border-width' - | 'box-shadow' - | 'data-visualization' - | 'font' - | 'font-size' - | 'font-weight' - | 'line-height' - | 'color' - | 'sizing' - | 'spacing' - | 'text-color' - | 'z-index'; + | "background-color" + | "border-color" + | "radius" + | "border-width" + | "box-shadow" + | "data-visualization" + | "font" + | "font-size" + | "font-weight" + | "line-height" + | "color" + | "sizing" + | "spacing" + | "text-color" + | "z-index"; diff --git a/apps/vs-code-intellisense/src/types/token-map.ts b/apps/vs-code-intellisense/src/types/token-map.ts index c174604502..e70030246e 100644 --- a/apps/vs-code-intellisense/src/types/token-map.ts +++ b/apps/vs-code-intellisense/src/types/token-map.ts @@ -1,3 +1,3 @@ -import {PasteToken} from './paste-token'; +import { PasteToken } from "./paste-token"; export type TokenMap = Record; diff --git a/apps/vs-code-intellisense/src/types/token-type.ts b/apps/vs-code-intellisense/src/types/token-type.ts index deda187cd2..a0fc542b9e 100644 --- a/apps/vs-code-intellisense/src/types/token-type.ts +++ b/apps/vs-code-intellisense/src/types/token-type.ts @@ -1 +1 @@ -export type TokenType = 'color' | 'size' | 'shadow' | 'font' | 'font-size' | 'font-weight' | 'number' | 'z-index'; +export type TokenType = "color" | "size" | "shadow" | "font" | "font-size" | "font-weight" | "number" | "z-index"; diff --git a/apps/vs-code-intellisense/src/utils/get-color-preview.ts b/apps/vs-code-intellisense/src/utils/get-color-preview.ts index 3cf17e1741..f0235c7b19 100644 --- a/apps/vs-code-intellisense/src/utils/get-color-preview.ts +++ b/apps/vs-code-intellisense/src/utils/get-color-preview.ts @@ -1,8 +1,8 @@ -import * as base64 from 'base-64'; -import * as utf8 from 'utf8'; +import * as base64 from "base-64"; +import * as utf8 from "utf8"; const HEIGHT = 50; -const WIDTH = '100%'; +const WIDTH = "100%"; /** * Generates markdown to render an svg of the provided color diff --git a/apps/vs-code-intellisense/src/utils/get-theme-setting.ts b/apps/vs-code-intellisense/src/utils/get-theme-setting.ts index ef919ed11f..afa2326562 100644 --- a/apps/vs-code-intellisense/src/utils/get-theme-setting.ts +++ b/apps/vs-code-intellisense/src/utils/get-theme-setting.ts @@ -1,6 +1,6 @@ -import * as vscode from 'vscode'; +import * as vscode from "vscode"; -import {Theme} from '../types'; +import { Theme } from "../types"; export const getThemeSetting = (): Theme => - (vscode.workspace.getConfiguration('vs-code-intellisense').get('theme') as Theme) ?? 'Default'; + (vscode.workspace.getConfiguration("vs-code-intellisense").get("theme") as Theme) ?? "Default"; diff --git a/apps/vs-code-intellisense/src/utils/get-theme-tokens.ts b/apps/vs-code-intellisense/src/utils/get-theme-tokens.ts index ac24dd4a9f..e3a124280e 100644 --- a/apps/vs-code-intellisense/src/utils/get-theme-tokens.ts +++ b/apps/vs-code-intellisense/src/utils/get-theme-tokens.ts @@ -5,22 +5,22 @@ import { sendGridThemeTokens, twilioDarkThemeTokens, twilioThemeTokens, -} from '../tokens'; -import {Theme, TokenMap} from '../types'; +} from "../tokens"; +import { Theme, TokenMap } from "../types"; export const getThemeTokens = (theme?: Theme): TokenMap => { switch (theme) { - case 'Dark': + case "Dark": return darkThemeTokens as TokenMap; - case 'Evergreen': + case "Evergreen": return evergreenThemeTokens as TokenMap; - case 'SendGrid': + case "SendGrid": return sendGridThemeTokens as TokenMap; - case 'Twilio': + case "Twilio": return twilioThemeTokens as TokenMap; - case 'Twilio Dark': + case "Twilio Dark": return twilioDarkThemeTokens as TokenMap; - case 'Default': + case "Default": default: return defaultThemeTokens as TokenMap; } diff --git a/apps/vs-code-intellisense/src/utils/index.ts b/apps/vs-code-intellisense/src/utils/index.ts index a2d9ca2fa6..4192ae89ff 100644 --- a/apps/vs-code-intellisense/src/utils/index.ts +++ b/apps/vs-code-intellisense/src/utils/index.ts @@ -1,5 +1,5 @@ -export * from './get-color-preview'; -export * from './get-theme-setting'; -export * from './get-theme-tokens'; -export * from './is-color-category'; -export * from './rem-to-px'; +export * from "./get-color-preview"; +export * from "./get-theme-setting"; +export * from "./get-theme-tokens"; +export * from "./is-color-category"; +export * from "./rem-to-px"; diff --git a/apps/vs-code-intellisense/src/utils/is-color-category.ts b/apps/vs-code-intellisense/src/utils/is-color-category.ts index 317749d8cb..f560dfc0e9 100644 --- a/apps/vs-code-intellisense/src/utils/is-color-category.ts +++ b/apps/vs-code-intellisense/src/utils/is-color-category.ts @@ -1,4 +1,4 @@ -import {TokenCategory} from '../types'; +import { TokenCategory } from "../types"; export const isColorCategory = (category: TokenCategory): boolean => - category === 'background-color' || category === 'border-color' || category === 'color' || category === 'text-color'; + category === "background-color" || category === "border-color" || category === "color" || category === "text-color"; diff --git a/apps/vs-code-intellisense/src/utils/rem-to-px.ts b/apps/vs-code-intellisense/src/utils/rem-to-px.ts index 26cf603364..829b328cb3 100644 --- a/apps/vs-code-intellisense/src/utils/rem-to-px.ts +++ b/apps/vs-code-intellisense/src/utils/rem-to-px.ts @@ -3,11 +3,11 @@ * If the value is not a rem unit, it returns the original value. */ export const remToPx = (value: string): string => { - if (!value.includes('rem')) { + if (!value.includes("rem")) { return value; } - const remValue = Number(value.replace('rem', '').trim()); + const remValue = Number(value.replace("rem", "").trim()); if (isNaN(remValue)) { return value; } diff --git a/babel.config.js b/babel.config.js index db42e523a8..54ba9fb1a8 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,7 +1,7 @@ const getPresets = (isDev) => [ - '@babel/preset-env', - '@babel/preset-react', - '@babel/preset-typescript', + "@babel/preset-env", + "@babel/preset-react", + "@babel/preset-typescript", [ /** [@emotion/babel-preset-css-prop] * This preset is used to automatically enable Emotion’s css prop when using the classic JSX runtime. @@ -14,22 +14,22 @@ const getPresets = (isDev) => [ * 1. remove this preset * 2. add the `@emotion/babel` plugin to our plugin section. */ - '@emotion/babel-preset-css-prop', + "@emotion/babel-preset-css-prop", { sourceMap: isDev, - autoLabel: 'dev-only', - labelFormat: '[local]', + autoLabel: "dev-only", + labelFormat: "[local]", cssPropOptimization: !isDev, }, ], ]; const BASE_PLUGINS = [ - 'macros', - ['@babel/proposal-class-properties', {loose: true}], - '@babel/proposal-object-rest-spread', - ['@babel/proposal-private-property-in-object', {loose: true}], - '@babel/plugin-proposal-optional-chaining', + "macros", + ["@babel/proposal-class-properties", { loose: true }], + "@babel/proposal-object-rest-spread", + ["@babel/proposal-private-property-in-object", { loose: true }], + "@babel/plugin-proposal-optional-chaining", ]; module.exports = { diff --git a/biome.json b/biome.json new file mode 100644 index 0000000000..05d86c9b6c --- /dev/null +++ b/biome.json @@ -0,0 +1,70 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.2.2/schema.json", + "files": { + "maxSize": 5242880, + "ignore": [ + "node_modules", + "bower_components", + "dist", + "bin", + "__testfixtures__", + "__fixtures__", + "packages/paste-icons/cjs", + "packages/paste-icons/esm", + "packages/paste-icons/json", + "packages/paste-theme-designer/public", + "packages/paste-theme-designer/out", + "packages/paste-token-contrast-checker/public", + "packages/paste-website/data", + ".cache", + ".next", + ".netlify", + ".yarn", + "packages/**/dist/*", + "tsconfig.build.tsbuildinfo", + "**/*.d.ts", + ".codesandbox/ci.json", + "build.icon-list.js", + "**/*.hbs" + ] + }, + "organizeImports": { + "enabled": true + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true, + "a11y": { + "noSvgWithoutTitle": "off" + }, + "suspicious": { + "noExplicitAny": "off" + }, + "complexity": { + "noUselessSwitchCase": "off", + "noMultipleSpacesInRegularExpressionLiterals": "off" + } + } + }, + "formatter": { + "enabled": true, + "indentStyle": "space", + "indentSize": 2, + "lineWidth": 120 + }, + "javascript": { + "formatter": { + "indentStyle": "space", + "indentSize": 2, + "lineWidth": 120 + } + }, + "json": { + "formatter": { + "indentStyle": "space", + "indentSize": 2, + "lineWidth": 120 + } + } +} diff --git a/commitlint.config.js b/commitlint.config.js index 84dcb122af..69b4242cc7 100644 --- a/commitlint.config.js +++ b/commitlint.config.js @@ -1,3 +1,3 @@ module.exports = { - extends: ['@commitlint/config-conventional'], + extends: ["@commitlint/config-conventional"], }; diff --git a/cypress.config.ts b/cypress.config.ts index 97f56103c7..b50cec7423 100644 --- a/cypress.config.ts +++ b/cypress.config.ts @@ -1,31 +1,31 @@ -import {defineConfig} from 'cypress'; +import { defineConfig } from "cypress"; // eslint-disable-next-line import/no-default-export export default defineConfig({ e2e: { - baseUrl: 'http://localhost:3000', + baseUrl: "http://localhost:3000", env: { USE_CYPRESS_VRT: process.env.USE_CYPRESS_VRT, CYPRESS_BASE_URL: process.env.CYPRESS_BASE_URL, }, viewportWidth: 1440, viewportHeight: 1440, - projectId: 'pe4h41', + projectId: "pe4h41", retries: { runMode: 2, openMode: 2, }, video: false, blockHosts: [ - '*.google-analytics.com', - '*.codesandbox.io', - 'codesandbox.io', - '*.loom.com', - '*.youtube.com', - '*.github.com', - '*.googletagmanager.com', + "*.google-analytics.com", + "*.codesandbox.io", + "codesandbox.io", + "*.loom.com", + "*.youtube.com", + "*.github.com", + "*.googletagmanager.com", ], - specPattern: ['cypress/**/*.spec.ts'], + specPattern: ["cypress/**/*.spec.ts"], defaultCommandTimeout: 6000, }, }); diff --git a/cypress/fixtures/example.json b/cypress/fixtures/example.json index da18d9352a..02e4254378 100644 --- a/cypress/fixtures/example.json +++ b/cypress/fixtures/example.json @@ -2,4 +2,4 @@ "name": "Using fixtures to represent data", "email": "hello@cypress.io", "body": "Fixtures are a great way to mock data for responses to routes" -} \ No newline at end of file +} diff --git a/cypress/integration/e2e/components/alert-dialog.spec.ts b/cypress/integration/e2e/components/alert-dialog.spec.ts index a2d59ff455..45f6344e55 100644 --- a/cypress/integration/e2e/components/alert-dialog.spec.ts +++ b/cypress/integration/e2e/components/alert-dialog.spec.ts @@ -1,11 +1,11 @@ -describe('Alert-dialog component documentation page', function () { +describe("Alert-dialog component documentation page", function () { beforeEach(() => { - cy.visit('/components/alert-dialog'); + cy.visit("/components/alert-dialog"); }); - it('should render the alert-dialog component page correctly', () => { + it("should render the alert-dialog component page correctly", () => { cy.pageHeaderShouldBeVisible({ - headerText: 'Alert Dialog', + headerText: "Alert Dialog", shouldHaveGithubLink: true, shouldHaveStorybook: true, shouldHaveOpenGraph: true, diff --git a/cypress/integration/e2e/components/overview-page.spec.ts b/cypress/integration/e2e/components/overview-page.spec.ts index 80a3a8c521..16b04b2220 100644 --- a/cypress/integration/e2e/components/overview-page.spec.ts +++ b/cypress/integration/e2e/components/overview-page.spec.ts @@ -1,11 +1,11 @@ -describe('Overview page', () => { +describe("Overview page", () => { beforeEach(() => { - cy.visit('/components'); + cy.visit("/components"); }); - it('should render the components overview page correctly', () => { + it("should render the components overview page correctly", () => { cy.pageHeaderShouldBeVisible({ - headerText: 'Components', + headerText: "Components", }); cy.overviewTableRendersCorrectly(); diff --git a/cypress/integration/e2e/patterns/button-vs-anchor.spec.ts b/cypress/integration/e2e/patterns/button-vs-anchor.spec.ts index e357314a3e..479348a0fa 100644 --- a/cypress/integration/e2e/patterns/button-vs-anchor.spec.ts +++ b/cypress/integration/e2e/patterns/button-vs-anchor.spec.ts @@ -1,11 +1,11 @@ -describe('Button-vs-anchor patterns documentation page', () => { +describe("Button-vs-anchor patterns documentation page", () => { beforeEach(() => { - cy.visit('/patterns/button-vs-anchor'); + cy.visit("/patterns/button-vs-anchor"); }); - it('should render the button-vs-anchor patterns page correctly', () => { + it("should render the button-vs-anchor patterns page correctly", () => { cy.pageHeaderShouldBeVisible({ - headerText: 'Button vs. Anchor', + headerText: "Button vs. Anchor", }); cy.checkInPageNavigationLinks(); diff --git a/cypress/integration/e2e/patterns/overview-page.spec.ts b/cypress/integration/e2e/patterns/overview-page.spec.ts index a6d306ec26..cf6c50e417 100644 --- a/cypress/integration/e2e/patterns/overview-page.spec.ts +++ b/cypress/integration/e2e/patterns/overview-page.spec.ts @@ -1,11 +1,11 @@ -describe('Overview page', () => { +describe("Overview page", () => { beforeEach(() => { - cy.visit('/patterns'); + cy.visit("/patterns"); }); - it('should render the patterns overview page correctly', () => { + it("should render the patterns overview page correctly", () => { cy.pageHeaderShouldBeVisible({ - headerText: 'Patterns', + headerText: "Patterns", }); cy.overviewTableRendersCorrectly(); diff --git a/cypress/integration/e2e/primitives/box.spec.ts b/cypress/integration/e2e/primitives/box.spec.ts index c98d0518b3..817199c356 100644 --- a/cypress/integration/e2e/primitives/box.spec.ts +++ b/cypress/integration/e2e/primitives/box.spec.ts @@ -1,11 +1,11 @@ -describe('Box primitives documentation page', () => { +describe("Box primitives documentation page", () => { beforeEach(() => { - cy.visit('/primitives/box'); + cy.visit("/primitives/box"); }); - it('should render the box primitives page correctly', () => { + it("should render the box primitives page correctly", () => { cy.pageHeaderShouldBeVisible({ - headerText: 'Box', + headerText: "Box", shouldHaveGithubLink: true, shouldHaveStorybook: true, shouldHaveOpenGraph: true, diff --git a/cypress/integration/e2e/primitives/overview-page.spec.ts b/cypress/integration/e2e/primitives/overview-page.spec.ts index 33ec59e7b7..49683211f4 100644 --- a/cypress/integration/e2e/primitives/overview-page.spec.ts +++ b/cypress/integration/e2e/primitives/overview-page.spec.ts @@ -1,11 +1,11 @@ -describe('Overview page', () => { +describe("Overview page", () => { beforeEach(() => { - cy.visit('/primitives'); + cy.visit("/primitives"); }); - it('should render the primitives overview page correctly', () => { + it("should render the primitives overview page correctly", () => { cy.pageHeaderShouldBeVisible({ - headerText: 'Primitives', + headerText: "Primitives", }); cy.overviewTableRendersCorrectly(); diff --git a/cypress/integration/e2e/roadmap-page.spec.ts b/cypress/integration/e2e/roadmap-page.spec.ts index 8f5e6b6183..5d0620203f 100644 --- a/cypress/integration/e2e/roadmap-page.spec.ts +++ b/cypress/integration/e2e/roadmap-page.spec.ts @@ -1,34 +1,34 @@ -describe('Roadmap Page', () => { +describe("Roadmap Page", () => { beforeEach(() => { - cy.visit('/roadmap'); + cy.visit("/roadmap"); }); - it('should render the future and current release table(s)', () => { - cy.get('[data-cy^="release-container"]').its('length').should('be.greaterThan', 0); + it("should render the future and current release table(s)", () => { + cy.get('[data-cy^="release-container"]').its("length").should("be.greaterThan", 0); }); - it('should load the roadmap correctly', () => { - cy.get('[data-cy^="release-container"]').as('release-containers'); + it("should load the roadmap correctly", () => { + cy.get('[data-cy^="release-container"]').as("release-containers"); - cy.get('@release-containers').each((container) => { - cy.wrap(container).find('h2').should('exist'); - cy.wrap(container).find('table').should('exist'); + cy.get("@release-containers").each((container) => { + cy.wrap(container).find("h2").should("exist"); + cy.wrap(container).find("table").should("exist"); cy.wrap(container) - .find('table') - .find('thead') - .find('tr') - .find('th') - .as('table-headers') - .its('length') - .should('eql', 3); - const expectedHeaders = ['Feature', 'Description', 'Status']; - cy.get('@table-headers').each((headerEl, idx) => { + .find("table") + .find("thead") + .find("tr") + .find("th") + .as("table-headers") + .its("length") + .should("eql", 3); + const expectedHeaders = ["Feature", "Description", "Status"]; + cy.get("@table-headers").each((headerEl, idx) => { expect(headerEl.text()).to.eql(expectedHeaders[idx]); }); }); }); - it('should render in page navigation correctly', () => { + it("should render in page navigation correctly", () => { cy.checkInPageNavigationLinks(); }); }); diff --git a/cypress/integration/filter-group-examples/index.spec.ts b/cypress/integration/filter-group-examples/index.spec.ts index c484634dc0..263215d1e0 100644 --- a/cypress/integration/filter-group-examples/index.spec.ts +++ b/cypress/integration/filter-group-examples/index.spec.ts @@ -1,160 +1,160 @@ -describe('Filter group pattern examples', () => { +describe("Filter group pattern examples", () => { beforeEach(() => { - cy.visit('/patterns/filter-group'); - cy.get('[data-cy="filter-group-default-example"]').first().as('filterGroupWrapper'); - cy.get('@filterGroupWrapper').find('select[name="type"]').as('roomTypeSelect'); - cy.get('@filterGroupWrapper').find('select[name="range"]').as('dateRangeSelect'); - cy.get('@filterGroupWrapper').find('input[name="search"]').as('searchInput'); + cy.visit("/patterns/filter-group"); + cy.get('[data-cy="filter-group-default-example"]').first().as("filterGroupWrapper"); + cy.get("@filterGroupWrapper").find('select[name="type"]').as("roomTypeSelect"); + cy.get("@filterGroupWrapper").find('select[name="range"]').as("dateRangeSelect"); + cy.get("@filterGroupWrapper").find('input[name="search"]').as("searchInput"); }); - it('filters the table with the search bar', () => { - cy.get('@filterGroupWrapper').find('tr').should('have.length', 8); - cy.get('@searchInput').type('test').should('have.value', 'test'); - cy.get('@filterGroupWrapper').find('[data-cy="filter-group-search-button"]').click(); - cy.get('@filterGroupWrapper').find('tr').should('have.length', 3); + it("filters the table with the search bar", () => { + cy.get("@filterGroupWrapper").find("tr").should("have.length", 8); + cy.get("@searchInput").type("test").should("have.value", "test"); + cy.get("@filterGroupWrapper").find('[data-cy="filter-group-search-button"]').click(); + cy.get("@filterGroupWrapper").find("tr").should("have.length", 3); }); - it('filters the table with the selects', () => { - cy.get('@filterGroupWrapper').find('tr').should('have.length', 8); - cy.get('@roomTypeSelect').select('Group').should('have.value', 'Group'); - cy.get('@dateRangeSelect').select('day').should('have.value', 'day'); - cy.get('@filterGroupWrapper').find('[data-cy="filter-group-apply-button"]').click(); - cy.get('@filterGroupWrapper').find('tr').should('have.length', 2); + it("filters the table with the selects", () => { + cy.get("@filterGroupWrapper").find("tr").should("have.length", 8); + cy.get("@roomTypeSelect").select("Group").should("have.value", "Group"); + cy.get("@dateRangeSelect").select("day").should("have.value", "day"); + cy.get("@filterGroupWrapper").find('[data-cy="filter-group-apply-button"]').click(); + cy.get("@filterGroupWrapper").find("tr").should("have.length", 2); }); - describe('Empty state', () => { - it('shows the empty state when search returns no results', () => { - cy.get('@filterGroupWrapper').find('tr').should('have.length', 8); - cy.get('@searchInput').type('asdfasdf'); - cy.get('@filterGroupWrapper').find('[data-cy="filter-group-search-button"]').click(); - cy.get('@filterGroupWrapper').find('table').should('have.length', 0); - cy.get('@filterGroupWrapper').find('[data-cy="filter-group-empty-state-clear-button"]').should('be.visible'); + describe("Empty state", () => { + it("shows the empty state when search returns no results", () => { + cy.get("@filterGroupWrapper").find("tr").should("have.length", 8); + cy.get("@searchInput").type("asdfasdf"); + cy.get("@filterGroupWrapper").find('[data-cy="filter-group-search-button"]').click(); + cy.get("@filterGroupWrapper").find("table").should("have.length", 0); + cy.get("@filterGroupWrapper").find('[data-cy="filter-group-empty-state-clear-button"]').should("be.visible"); }); - it('shows the empty state when selects returns no results', () => { - cy.get('@filterGroupWrapper').find('tr').should('have.length', 8); - cy.get('@roomTypeSelect').select('Peer to Peer'); - cy.get('@dateRangeSelect').select('day'); - cy.get('@filterGroupWrapper').find('[data-cy="filter-group-apply-button"]').click(); - cy.get('@filterGroupWrapper').find('table').should('have.length', 0); - cy.get('@filterGroupWrapper').find('[data-cy="filter-group-empty-state-clear-button"]').should('be.visible'); + it("shows the empty state when selects returns no results", () => { + cy.get("@filterGroupWrapper").find("tr").should("have.length", 8); + cy.get("@roomTypeSelect").select("Peer to Peer"); + cy.get("@dateRangeSelect").select("day"); + cy.get("@filterGroupWrapper").find('[data-cy="filter-group-apply-button"]').click(); + cy.get("@filterGroupWrapper").find("table").should("have.length", 0); + cy.get("@filterGroupWrapper").find('[data-cy="filter-group-empty-state-clear-button"]').should("be.visible"); }); }); - describe('Clear buttons', () => { + describe("Clear buttons", () => { beforeEach(() => { - cy.get('@roomTypeSelect').select('Group'); - cy.get('@dateRangeSelect').select('day'); - cy.get('@searchInput').type('sfasdf'); - cy.get('@filterGroupWrapper').find('[data-cy="filter-group-apply-button"]').click(); + cy.get("@roomTypeSelect").select("Group"); + cy.get("@dateRangeSelect").select("day"); + cy.get("@searchInput").type("sfasdf"); + cy.get("@filterGroupWrapper").find('[data-cy="filter-group-apply-button"]').click(); }); - it('clears the filters when press clear button', () => { - cy.get('@filterGroupWrapper').find('tr').should('have.length', 0); - cy.get('@filterGroupWrapper').find('[data-cy="filter-group-clear-button"]').click(); - cy.get('@filterGroupWrapper').find('tr').should('have.length', 8); - cy.get('@roomTypeSelect').should('have.value', 'All'); - cy.get('@dateRangeSelect').should('have.value', 'all'); - cy.get('@searchInput').should('have.value', ''); + it("clears the filters when press clear button", () => { + cy.get("@filterGroupWrapper").find("tr").should("have.length", 0); + cy.get("@filterGroupWrapper").find('[data-cy="filter-group-clear-button"]').click(); + cy.get("@filterGroupWrapper").find("tr").should("have.length", 8); + cy.get("@roomTypeSelect").should("have.value", "All"); + cy.get("@dateRangeSelect").should("have.value", "all"); + cy.get("@searchInput").should("have.value", ""); }); - it('clears the filters when press empty state clear button', () => { - cy.get('@filterGroupWrapper').find('tr').should('have.length', 0); - cy.get('@filterGroupWrapper').find('[data-cy="filter-group-empty-state-clear-button"]').click(); - cy.get('@filterGroupWrapper').find('tr').should('have.length', 8); - cy.get('@roomTypeSelect').should('have.value', 'All'); - cy.get('@dateRangeSelect').should('have.value', 'all'); - cy.get('@searchInput').should('have.value', ''); + it("clears the filters when press empty state clear button", () => { + cy.get("@filterGroupWrapper").find("tr").should("have.length", 0); + cy.get("@filterGroupWrapper").find('[data-cy="filter-group-empty-state-clear-button"]').click(); + cy.get("@filterGroupWrapper").find("tr").should("have.length", 8); + cy.get("@roomTypeSelect").should("have.value", "All"); + cy.get("@dateRangeSelect").should("have.value", "all"); + cy.get("@searchInput").should("have.value", ""); }); }); }); -describe('Custom date/time pattern example', () => { +describe("Custom date/time pattern example", () => { beforeEach(() => { - cy.visit('/patterns/filter-group'); - cy.get('[data-cy="custom-filter-group-example"]').first().as('filterGroupWrapper'); - cy.get('@filterGroupWrapper').find('select[name="type"]').as('roomTypeSelect'); - cy.get('@filterGroupWrapper').find('select[name="range"]').as('dateRangeSelect'); - cy.get('@filterGroupWrapper').find('input[name="search"]').as('searchInput'); - cy.get('@filterGroupWrapper').find('[data-cy="custom-filter-group-popover-button"]').as('dateTimePopoverButton'); + cy.visit("/patterns/filter-group"); + cy.get('[data-cy="custom-filter-group-example"]').first().as("filterGroupWrapper"); + cy.get("@filterGroupWrapper").find('select[name="type"]').as("roomTypeSelect"); + cy.get("@filterGroupWrapper").find('select[name="range"]').as("dateRangeSelect"); + cy.get("@filterGroupWrapper").find('input[name="search"]').as("searchInput"); + cy.get("@filterGroupWrapper").find('[data-cy="custom-filter-group-popover-button"]').as("dateTimePopoverButton"); }); - it('filters the table with the search bar', () => { - cy.get('@filterGroupWrapper').find('tr').should('have.length', 8); - cy.get('@searchInput').type('test').should('have.value', 'test'); - cy.get('@filterGroupWrapper').find('[data-cy="custom-filter-group-search-button"]').click(); - cy.get('@filterGroupWrapper').find('tr').should('have.length', 3); + it("filters the table with the search bar", () => { + cy.get("@filterGroupWrapper").find("tr").should("have.length", 8); + cy.get("@searchInput").type("test").should("have.value", "test"); + cy.get("@filterGroupWrapper").find('[data-cy="custom-filter-group-search-button"]').click(); + cy.get("@filterGroupWrapper").find("tr").should("have.length", 3); }); - it('filters the table with the selects', () => { - cy.get('@filterGroupWrapper').find('tr').should('have.length', 8); - cy.get('@roomTypeSelect').select('WebRTC Go').should('have.value', 'WebRTC Go'); - cy.get('@dateRangeSelect').select('day').should('have.value', 'day'); - cy.get('@filterGroupWrapper').find('[data-cy="custom-filter-group-apply-button"]').click(); - cy.get('@filterGroupWrapper').find('tr').should('have.length', 3); + it("filters the table with the selects", () => { + cy.get("@filterGroupWrapper").find("tr").should("have.length", 8); + cy.get("@roomTypeSelect").select("WebRTC Go").should("have.value", "WebRTC Go"); + cy.get("@dateRangeSelect").select("day").should("have.value", "day"); + cy.get("@filterGroupWrapper").find('[data-cy="custom-filter-group-apply-button"]').click(); + cy.get("@filterGroupWrapper").find("tr").should("have.length", 3); }); - describe('Empty state', () => { - it('shows the empty state when search returns no results', () => { - cy.get('@filterGroupWrapper').find('tr').should('have.length', 8); - cy.get('@searchInput').type('asdfasdf'); - cy.get('@filterGroupWrapper').find('[data-cy="custom-filter-group-search-button"]').click(); - cy.get('@filterGroupWrapper').find('table').should('have.length', 0); - cy.get('@filterGroupWrapper').find('[data-cy="filter-group-empty-state-clear-button"]').should('be.visible'); + describe("Empty state", () => { + it("shows the empty state when search returns no results", () => { + cy.get("@filterGroupWrapper").find("tr").should("have.length", 8); + cy.get("@searchInput").type("asdfasdf"); + cy.get("@filterGroupWrapper").find('[data-cy="custom-filter-group-search-button"]').click(); + cy.get("@filterGroupWrapper").find("table").should("have.length", 0); + cy.get("@filterGroupWrapper").find('[data-cy="filter-group-empty-state-clear-button"]').should("be.visible"); }); - it('shows the empty state when selects returns no results', () => { - cy.get('@filterGroupWrapper').find('tr').should('have.length', 8); - cy.get('@roomTypeSelect').select('Peer to Peer'); - cy.get('@dateRangeSelect').select('12hours'); - cy.get('@filterGroupWrapper').find('[data-cy="custom-filter-group-apply-button"]').click(); - cy.get('@filterGroupWrapper').find('table').should('have.length', 0); - cy.get('@filterGroupWrapper').find('[data-cy="filter-group-empty-state-clear-button"]').should('be.visible'); + it("shows the empty state when selects returns no results", () => { + cy.get("@filterGroupWrapper").find("tr").should("have.length", 8); + cy.get("@roomTypeSelect").select("Peer to Peer"); + cy.get("@dateRangeSelect").select("12hours"); + cy.get("@filterGroupWrapper").find('[data-cy="custom-filter-group-apply-button"]').click(); + cy.get("@filterGroupWrapper").find("table").should("have.length", 0); + cy.get("@filterGroupWrapper").find('[data-cy="filter-group-empty-state-clear-button"]').should("be.visible"); }); }); - it('clears the filters when press empty state clear button', () => { - cy.get('@roomTypeSelect').select('Peer to Peer'); - cy.get('@dateRangeSelect').select('12hours'); - cy.get('@searchInput').type('sfasdf'); - cy.get('@filterGroupWrapper').find('[data-cy="custom-filter-group-apply-button"]').click(); - - cy.get('@filterGroupWrapper').find('tr').should('have.length', 0); - cy.get('@filterGroupWrapper').find('[data-cy="filter-group-empty-state-clear-button"]').click(); - cy.get('@filterGroupWrapper').find('tr').should('have.length', 8); - cy.get('@roomTypeSelect').should('have.value', 'All'); - cy.get('@dateRangeSelect').should('have.value', 'all'); - cy.get('@searchInput').should('have.value', ''); + it("clears the filters when press empty state clear button", () => { + cy.get("@roomTypeSelect").select("Peer to Peer"); + cy.get("@dateRangeSelect").select("12hours"); + cy.get("@searchInput").type("sfasdf"); + cy.get("@filterGroupWrapper").find('[data-cy="custom-filter-group-apply-button"]').click(); + + cy.get("@filterGroupWrapper").find("tr").should("have.length", 0); + cy.get("@filterGroupWrapper").find('[data-cy="filter-group-empty-state-clear-button"]').click(); + cy.get("@filterGroupWrapper").find("tr").should("have.length", 8); + cy.get("@roomTypeSelect").should("have.value", "All"); + cy.get("@dateRangeSelect").should("have.value", "all"); + cy.get("@searchInput").should("have.value", ""); }); - describe('Custom date/time popover', () => { + describe("Custom date/time popover", () => { beforeEach(() => { - cy.get('@dateTimePopoverButton').click(); + cy.get("@dateTimePopoverButton").click(); - cy.get('input[name="customDate.startDate"]').as('startDateInput'); - cy.get('input[name="customDate.startTime"]').as('startTimeInput'); - cy.get('input[name="customDate.endDate"]').as('endDateInput'); - cy.get('input[name="customDate.endTime"]').as('endTimeInput'); - cy.get('[data-cy="custom-filter-group-popover-apply-button"]').as('popoverApplyButton'); + cy.get('input[name="customDate.startDate"]').as("startDateInput"); + cy.get('input[name="customDate.startTime"]').as("startTimeInput"); + cy.get('input[name="customDate.endDate"]').as("endDateInput"); + cy.get('input[name="customDate.endTime"]').as("endTimeInput"); + cy.get('[data-cy="custom-filter-group-popover-apply-button"]').as("popoverApplyButton"); }); - it('clears the date/time values if change the range select', () => { + it("clears the date/time values if change the range select", () => { const TODAY = new Date(); - cy.get('@startDateInput').type('2022-05-01'); - cy.get('@startTimeInput').type('10:30'); - cy.get('@endDateInput').type('2022-05-01'); - cy.get('@endTimeInput').type('20:30'); + cy.get("@startDateInput").type("2022-05-01"); + cy.get("@startTimeInput").type("10:30"); + cy.get("@endDateInput").type("2022-05-01"); + cy.get("@endTimeInput").type("20:30"); - cy.get('@popoverApplyButton').click(); + cy.get("@popoverApplyButton").click(); - cy.get('@dateRangeSelect').select('12hours'); - cy.get('@filterGroupWrapper').find('[data-cy="custom-filter-group-apply-button"]').click(); + cy.get("@dateRangeSelect").select("12hours"); + cy.get("@filterGroupWrapper").find('[data-cy="custom-filter-group-apply-button"]').click(); - cy.get('@startDateInput').should('have.value', TODAY.toISOString().slice(0, 10)); - cy.get('@startTimeInput').should('have.value', '00:00'); - cy.get('@endDateInput').should('have.value', TODAY.toISOString().slice(0, 10)); - cy.get('@endTimeInput').should('have.value', '23:59'); + cy.get("@startDateInput").should("have.value", TODAY.toISOString().slice(0, 10)); + cy.get("@startTimeInput").should("have.value", "00:00"); + cy.get("@endDateInput").should("have.value", TODAY.toISOString().slice(0, 10)); + cy.get("@endTimeInput").should("have.value", "23:59"); }); }); }); diff --git a/cypress/integration/landing-page/index.spec.ts b/cypress/integration/landing-page/index.spec.ts index ee6ed3a6ef..bac3ddefc9 100644 --- a/cypress/integration/landing-page/index.spec.ts +++ b/cypress/integration/landing-page/index.spec.ts @@ -1,11 +1,11 @@ // ℹ️ If we use anon functions instead of arrow functions, we can leverage Mocha's context and pull the test name directly from this -describe('Landing Page', function () { +describe("Landing Page", function () { // ℹ️ We are able to reference `this.title` because we have bound this describe block to the Cypress context. const testSuiteName = this.title; - describe('Visual regression tests', () => { - it('Basic VRT', () => { - cy.visualRegressionTestUrl({url: '/', testName: `${testSuiteName}-landing-page-check`}); + describe("Visual regression tests", () => { + it("Basic VRT", () => { + cy.visualRegressionTestUrl({ url: "/", testName: `${testSuiteName}-landing-page-check` }); }); }); }); diff --git a/cypress/integration/link-checker/index.spec.ts b/cypress/integration/link-checker/index.spec.ts index ab2b5069fc..08768c2dac 100644 --- a/cypress/integration/link-checker/index.spec.ts +++ b/cypress/integration/link-checker/index.spec.ts @@ -17,19 +17,19 @@ const IGNORE_LIST = []; */ const shouldVisitLink = (link, baseUrl) => { // We should never have a `//` in a url other than the one in `http://` - const passesDoubleSlashTest = link.split('//')[2] == null; - const passesIrrelevantTest = !link.includes('page-data') && !link.includes('socket.io'); + const passesDoubleSlashTest = link.split("//")[2] == null; + const passesIrrelevantTest = !link.includes("page-data") && !link.includes("socket.io"); // does it include the baseUrl the site is running on, or a production link url including Storybook - const passesHostTest = link.includes(baseUrl) || link.includes('paste-storybook.twilio.design'); + const passesHostTest = link.includes(baseUrl) || link.includes("paste-storybook.twilio.design"); const passesIgnoreTest = !IGNORE_LIST.some((ignoreItem) => link.includes(ignoreItem)); return passesDoubleSlashTest && passesIrrelevantTest && passesHostTest && passesIgnoreTest; }; -describe('Broken link checker', () => { - it('recursively check all website links for any broken links', () => { +describe("Broken link checker", () => { + it("recursively check all website links for any broken links", () => { const VISITED_LINKS = new Set(); - const baseUrl = Cypress.env('CYPRESS_BASE_URL'); + const baseUrl = Cypress.env("CYPRESS_BASE_URL"); cy.log(`[LINK CHECKER]: Link checking starting on ${baseUrl}`); @@ -45,8 +45,8 @@ describe('Broken link checker', () => { // so it omits the need to wait for the JS to execute. // This makes this crawler much more performant, but it only // works because we SSR our website. - cy.request({url: pagePath}) - .its('body') + cy.request({ url: pagePath }) + .its("body") .then((html) => { // Cyprus has a jQuery like syntax (called Cheerio) to traverse // the html content: https://cheerio.js.org @@ -58,10 +58,10 @@ describe('Broken link checker', () => { // until every link has been crawled. #recursion $anchors.each((index: number) => { // Gatsby or Cypress does some weird "/__/" routing. This removes that oddity. - const href = $anchors[index].href.replace('/__/', '/'); + const href = $anchors[index].href.replace("/__/", "/"); // Remove the hash to prevent checking the same actual link multiple times - const link = href.split('#')[0]; + const link = href.split("#")[0]; if (shouldVisitLink(link, baseUrl)) { crawlPageLinks(link); diff --git a/cypress/integration/opengraph/index.spec.ts b/cypress/integration/opengraph/index.spec.ts index b2e7a4e375..beaeff28e2 100644 --- a/cypress/integration/opengraph/index.spec.ts +++ b/cypress/integration/opengraph/index.spec.ts @@ -1,17 +1,17 @@ -describe('OpenGraph Cards', () => { - it('renders opengraph cards correctly', () => { - cy.visit('/opengraph/?path=components/alert'); +describe("OpenGraph Cards", () => { + it("renders opengraph cards correctly", () => { + cy.visit("/opengraph/?path=components/alert"); // Check the title - cy.get('h1').should('have.text', 'Alert'); + cy.get("h1").should("have.text", "Alert"); // Check the logo - cy.get('svg').should('be.visible'); + cy.get("svg").should("be.visible"); // Check the aria-label - cy.get('[aria-label="Open Graph Template"]').should('be.visible'); + cy.get('[aria-label="Open Graph Template"]').should("be.visible"); // Check the fonts - cy.document().its('fonts.status').should('equal', 'loaded'); + cy.document().its("fonts.status").should("equal", "loaded"); }); }); diff --git a/cypress/integration/sidebar-navigation/index.spec.ts b/cypress/integration/sidebar-navigation/index.spec.ts index e2f90e2618..f8540cd864 100644 --- a/cypress/integration/sidebar-navigation/index.spec.ts +++ b/cypress/integration/sidebar-navigation/index.spec.ts @@ -1,27 +1,27 @@ const sidebarNavigationDisclosures = [ - 'introduction', - 'for-designers', - 'for-engineers', - 'contributing', - 'foundations', - 'content', - 'patterns', - 'components', - 'combobox', - 'icon', - 'primitives', - 'tokens', - 'core', - 'libraries', - 'customization', - 'theme', + "introduction", + "for-designers", + "for-engineers", + "contributing", + "foundations", + "content", + "patterns", + "components", + "combobox", + "icon", + "primitives", + "tokens", + "core", + "libraries", + "customization", + "theme", ]; -const BASE = 'sidebar-disclosure'; +const BASE = "sidebar-disclosure"; -describe('Sidebar navigation', () => { +describe("Sidebar navigation", () => { before(() => { - cy.visit('/'); + cy.visit("/"); cy.wait(1000); }); @@ -30,11 +30,11 @@ describe('Sidebar navigation', () => { const contentSelector = `${BASE}-content-${disclosureName}`; it(`should open the the "${disclosureName}" sidebar disclosure`, () => { - cy.get(`[data-cy="${buttonSelector}"]`).click().should('have.attr', 'aria-expanded', 'true'); + cy.get(`[data-cy="${buttonSelector}"]`).click().should("have.attr", "aria-expanded", "true"); // creates an alias for the content - cy.get(`[data-cy="${contentSelector}"]`).as('currentContent'); + cy.get(`[data-cy="${contentSelector}"]`).as("currentContent"); - cy.get('@currentContent').scrollIntoView().should('be.visible'); + cy.get("@currentContent").scrollIntoView().should("be.visible"); }); }); @@ -42,20 +42,20 @@ describe('Sidebar navigation', () => { const buttonSelector = `${BASE}-button-${disclosureName}`; it(`should close the the "${disclosureName}" sidebar disclosure`, () => { - cy.get(`[data-cy="${buttonSelector}"]`).click().should('have.attr', 'aria-expanded', 'false'); + cy.get(`[data-cy="${buttonSelector}"]`).click().should("have.attr", "aria-expanded", "false"); }); }); }); -describe('Sidebar opens correct section on first load', () => { - it('opens the sidebar category and selects the page correctly on first load', () => { - cy.visit('/components/alert-dialog/'); +describe("Sidebar opens correct section on first load", () => { + it("opens the sidebar category and selects the page correctly on first load", () => { + cy.visit("/components/alert-dialog/"); const componentsCategoryButton = cy.get(`[data-cy="sidebar-disclosure-button-components"]`); - componentsCategoryButton.should('have.attr', 'aria-expanded', 'true'); + componentsCategoryButton.should("have.attr", "aria-expanded", "true"); const componentsCategoryList = cy.get(`[data-cy="sidebar-disclosure-content-components"]`); - const alertDialogLink = componentsCategoryList.contains('Alert Dialog'); - alertDialogLink.should('have.attr', 'aria-current', 'page'); + const alertDialogLink = componentsCategoryList.contains("Alert Dialog"); + alertDialogLink.should("have.attr", "aria-current", "page"); }); }); diff --git a/cypress/integration/site-search/index.spec.ts b/cypress/integration/site-search/index.spec.ts index 200178ea57..9107fa017c 100644 --- a/cypress/integration/site-search/index.spec.ts +++ b/cypress/integration/site-search/index.spec.ts @@ -1,23 +1,23 @@ -describe('Docs website search', () => { +describe("Docs website search", () => { before(() => { - cy.visit('/roadmap'); + cy.visit("/roadmap"); cy.wait(1000); }); beforeEach(() => { - cy.intercept({url: 'https://**.algolia.net/**', method: 'POST'}).as('searchRequest'); + cy.intercept({ url: "https://**.algolia.net/**", method: "POST" }).as("searchRequest"); }); beforeEach(() => { - cy.get('[data-cy="paste-docsearch-container"] button:visible').as('searchButtonEl'); + cy.get('[data-cy="paste-docsearch-container"] button:visible').as("searchButtonEl"); }); - it('should handle a search string', () => { - cy.get('@searchButtonEl').scrollIntoView().should('be.visible').click({force: true}); - cy.get('.DocSearch-Input').should('be.visible').should('be.focused').type('checkbox'); - cy.wait('@searchRequest'); - cy.get('.DocSearch-Hits').should('have.length.above', 0); - cy.get('.DocSearch-Hits [role="listbox"]').should('have.length.above', 0); - cy.get('.DocSearch-Hits [role="option"]').should('have.length.above', 0); + it("should handle a search string", () => { + cy.get("@searchButtonEl").scrollIntoView().should("be.visible").click({ force: true }); + cy.get(".DocSearch-Input").should("be.visible").should("be.focused").type("checkbox"); + cy.wait("@searchRequest"); + cy.get(".DocSearch-Hits").should("have.length.above", 0); + cy.get('.DocSearch-Hits [role="listbox"]').should("have.length.above", 0); + cy.get('.DocSearch-Hits [role="option"]').should("have.length.above", 0); }); }); diff --git a/cypress/integration/sitemap-vrt/batch2.spec.ts b/cypress/integration/sitemap-vrt/batch2.spec.ts index 0cdff81cbe..8b144185ba 100644 --- a/cypress/integration/sitemap-vrt/batch2.spec.ts +++ b/cypress/integration/sitemap-vrt/batch2.spec.ts @@ -1,9 +1,9 @@ -import {SITEMAP_CHUNKS} from './constants'; +import { SITEMAP_CHUNKS } from "./constants"; -describe('Full Site VRT Batch 2', function () { +describe("Full Site VRT Batch 2", function () { SITEMAP_CHUNKS[1].forEach((url) => { it(`should vrt ${url}`, () => { - cy.visualRegressionTestUrl({url, testName: url}); + cy.visualRegressionTestUrl({ url, testName: url }); }); }); }); diff --git a/cypress/integration/sitemap-vrt/batch3.spec.ts b/cypress/integration/sitemap-vrt/batch3.spec.ts index 607164f874..aff51ca608 100644 --- a/cypress/integration/sitemap-vrt/batch3.spec.ts +++ b/cypress/integration/sitemap-vrt/batch3.spec.ts @@ -1,9 +1,9 @@ -import {SITEMAP_CHUNKS} from './constants'; +import { SITEMAP_CHUNKS } from "./constants"; -describe('Full Site VRT Batch 3', function () { +describe("Full Site VRT Batch 3", function () { SITEMAP_CHUNKS[2].forEach((url) => { it(`should vrt ${url}`, () => { - cy.visualRegressionTestUrl({url, testName: url}); + cy.visualRegressionTestUrl({ url, testName: url }); }); }); }); diff --git a/cypress/integration/sitemap-vrt/batch4.spec.ts b/cypress/integration/sitemap-vrt/batch4.spec.ts index 320acc2d44..f3c98affb4 100644 --- a/cypress/integration/sitemap-vrt/batch4.spec.ts +++ b/cypress/integration/sitemap-vrt/batch4.spec.ts @@ -1,9 +1,9 @@ -import {SITEMAP_CHUNKS} from './constants'; +import { SITEMAP_CHUNKS } from "./constants"; -describe('Full Site VRT Batch 4', function () { +describe("Full Site VRT Batch 4", function () { SITEMAP_CHUNKS[3].forEach((url) => { it(`should vrt ${url}`, () => { - cy.visualRegressionTestUrl({url, testName: url}); + cy.visualRegressionTestUrl({ url, testName: url }); }); }); }); diff --git a/cypress/integration/sitemap-vrt/batch5.spec.ts b/cypress/integration/sitemap-vrt/batch5.spec.ts index 9896651ca7..a4282a059a 100644 --- a/cypress/integration/sitemap-vrt/batch5.spec.ts +++ b/cypress/integration/sitemap-vrt/batch5.spec.ts @@ -1,9 +1,9 @@ -import {SITEMAP_CHUNKS} from './constants'; +import { SITEMAP_CHUNKS } from "./constants"; -describe('Full Site VRT Batch 5', function () { +describe("Full Site VRT Batch 5", function () { SITEMAP_CHUNKS[4].forEach((url) => { it(`should vrt ${url}`, () => { - cy.visualRegressionTestUrl({url, testName: url}); + cy.visualRegressionTestUrl({ url, testName: url }); }); }); }); diff --git a/cypress/integration/sitemap-vrt/constants.ts b/cypress/integration/sitemap-vrt/constants.ts index 6b2d90d032..16cc79e1ea 100644 --- a/cypress/integration/sitemap-vrt/constants.ts +++ b/cypress/integration/sitemap-vrt/constants.ts @@ -1,179 +1,179 @@ export const SITEMAP = [ - '/customization/', - '/', - '/blog/', - '/blog/2020-11-26-growing-pains-and-how-we-scaled-our-design-system-support/', - '/blog/2021-04-29-insights-and-metrics-that-inform-the-paste-design-system/', - '/blog/2021-07-26-pastes-path-to-a-transparent-package-categorization-system/', - '/blog/2022-04-06-paste-newsletter/', - '/blog/2022-05-17-bringing-cohesion-to-the-twilio-product-suite-part-i/', - '/blog/2022-06-28-paste-newsletter/', - '/blog/2022-07-26-paste-newsletter/', - '/blog/2022-09-23-paste-newsletter/', - '/blog/2022-10-31-paste-newsletter/', - '/blog/2022-12-06-announcing-the-conversations-ui-kit/', - '/blog/2022-12-09-paste-newsletter/', - '/blog/2023-01-27-paste-newsletter/', - '/blog/2023-04-13-paste-newsletter/', - '/blog/2023-06-12-paste-newsletter/', - '/blog/2023-08-01-bringing-cohesion-to-the-twilio-product-suite-part-ii/', - '/blog/2023-08-02-paste-newsletter/', - '/components/account-switcher/', - '/components/aspect-ratio/', - '/components/aspect-ratio/api', - '/components/aspect-ratio/changelog', - '/components/anchor/', - '/components/anchor/api', - '/components/anchor/changelog', - '/components/alert-dialog/', - '/components/avatar/', - '/components/breadcrumb/', - '/components/badge/', - '/components/callout/', - '/components/code-block/', - '/components/card/', - '/components/chat-composer/', - '/components/chat-log/', - '/components/checkbox/', - '/components/data-grid/', - '/components/detail-text', - '/components/description-list/', - '/components/display-heading/', - '/components/display-pill-group/', - '/components/disclosure/', - '/components/button/', - '/components/button/api', - '/components/button/changelog', - '/components/button-group/', - '/components/flex/', - '/components/flex/api', - '/components/flex/changelog', - '/components/file-picker/', - '/components/file-uploader/', - '/components/form/', - '/components/combobox/', - '/components/date-picker/', - '/components/grid/', - '/components/grid/api', - '/components/grid/changelog', - '/components/heading/', - '/components/form-pill-group/', - '/components/alert/', - '/components/help-text/', - '/components/icon/', - '/components/icon/usage-guidelines/', - '/components/', - '/components/in-page-navigation', - '/components/inline-code/', - '/components/input/', - '/components/label/', - '/components/list/', - '/components/minimizable-dialog/', - '/components/media-object/', - '/components/media-object/api', - '/components/media-object/changelog', - '/components/meter', - '/components/pagination/', - '/components/modal/', - '/components/menu/', - '/components/paragraph/', - '/components/popover/', - '/components/product-switcher/', - '/components/progress-steps/', - '/components/radio-group/', - '/components/radio-button-group/', - '/components/screen-reader-only/', - '/components/select/', - '/components/separator/', - '/components/sidebar/', - '/components/sidebar-navigation/', - '/components/stack/', - '/components/stack/api', - '/components/stack/changelog', - '/components/status-badge/', - '/components/status-menu/', - '/components/spinner/', - '/components/skeleton-loader/', - '/components/slider/', - '/components/switch/', - '/components/tabs/', - '/components/toast/', - '/components/time-picker/', - '/components/truncate/', - '/components/tooltip/', - '/components/topbar', - '/components/user-dialog/', - '/components/textarea/', - '/components/table/', - '/components/table/api', - '/components/table/changelog', - '/components/visual-picker/', - '/core/', - '/core/changelog/', - '/core/libraries/', - '/core/libraries/code-editor/', - '/core/libraries/codemods/', - '/core/libraries/data-visualization/', - '/core/libraries/uid-library/', - '/core/libraries/vs-code-plugin/', - '/core/upgrade-guide/', - '/customization/composing-custom-components-with-design-tokens/', - '/customization/creating-a-custom-theme/', - '/customization/customization-provider/', - '/customization/customizing-component-elements/', - '/foundations/colors/', - '/foundations/content/content-checklist/', - '/foundations/content/voice-and-tone/', - '/foundations/content/word-list/', - '/foundations/illustrations/', - '/foundations/data-visualization/', - '/foundations/spacing-and-layout/', - '/foundations/typography/', - '/inclusive-design/', - '/foundations/content/product-style-guide/', - '/introduction/about-paste/', - '/introduction/contributing/components/', - '/foundations/content/', - '/introduction/contributing/icons/', - '/introduction/contributing/patterns/', - '/introduction/for-designers/design-guidelines/', - '/introduction/for-engineers/manual-installation/', - '/introduction/for-engineers/quickstart/', - '/introduction/working-with-us/', - '/page-templates/', - '/page-templates/object-details/', - '/page-templates/objects-list/', - '/page-templates/settings/', - '/patterns/button-vs-anchor/', - '/patterns/confirmation/', - '/patterns/delete/', - '/patterns/data-export/', - '/patterns/filter-group/', - '/patterns/', - '/patterns/empty-state/', - '/patterns/error-state/', - '/patterns/navigation/', - '/patterns/notifications-and-feedback/', - '/patterns/privacy/', - '/patterns/status/', - '/primitives/combobox-primitive/', - '/patterns/create/', - '/primitives/', - '/primitives/menu-primitive/', - '/primitives/disclosure-primitive/', - '/primitives/modal-dialog-primitive/', - '/primitives/non-modal-dialog-primitive/', - '/primitives/tabs-primitive/', - '/primitives/text/', - '/primitives/tooltip-primitive/', - '/primitives/listbox-primitive/', - '/roadmap/', - '/theme/', - '/theme/changing-theme/', - '/theme/dark-theme/', - '/tokens/design-tokens-package/', - '/tokens/', - '/primitives/box/', + "/customization/", + "/", + "/blog/", + "/blog/2020-11-26-growing-pains-and-how-we-scaled-our-design-system-support/", + "/blog/2021-04-29-insights-and-metrics-that-inform-the-paste-design-system/", + "/blog/2021-07-26-pastes-path-to-a-transparent-package-categorization-system/", + "/blog/2022-04-06-paste-newsletter/", + "/blog/2022-05-17-bringing-cohesion-to-the-twilio-product-suite-part-i/", + "/blog/2022-06-28-paste-newsletter/", + "/blog/2022-07-26-paste-newsletter/", + "/blog/2022-09-23-paste-newsletter/", + "/blog/2022-10-31-paste-newsletter/", + "/blog/2022-12-06-announcing-the-conversations-ui-kit/", + "/blog/2022-12-09-paste-newsletter/", + "/blog/2023-01-27-paste-newsletter/", + "/blog/2023-04-13-paste-newsletter/", + "/blog/2023-06-12-paste-newsletter/", + "/blog/2023-08-01-bringing-cohesion-to-the-twilio-product-suite-part-ii/", + "/blog/2023-08-02-paste-newsletter/", + "/components/account-switcher/", + "/components/aspect-ratio/", + "/components/aspect-ratio/api", + "/components/aspect-ratio/changelog", + "/components/anchor/", + "/components/anchor/api", + "/components/anchor/changelog", + "/components/alert-dialog/", + "/components/avatar/", + "/components/breadcrumb/", + "/components/badge/", + "/components/callout/", + "/components/code-block/", + "/components/card/", + "/components/chat-composer/", + "/components/chat-log/", + "/components/checkbox/", + "/components/data-grid/", + "/components/detail-text", + "/components/description-list/", + "/components/display-heading/", + "/components/display-pill-group/", + "/components/disclosure/", + "/components/button/", + "/components/button/api", + "/components/button/changelog", + "/components/button-group/", + "/components/flex/", + "/components/flex/api", + "/components/flex/changelog", + "/components/file-picker/", + "/components/file-uploader/", + "/components/form/", + "/components/combobox/", + "/components/date-picker/", + "/components/grid/", + "/components/grid/api", + "/components/grid/changelog", + "/components/heading/", + "/components/form-pill-group/", + "/components/alert/", + "/components/help-text/", + "/components/icon/", + "/components/icon/usage-guidelines/", + "/components/", + "/components/in-page-navigation", + "/components/inline-code/", + "/components/input/", + "/components/label/", + "/components/list/", + "/components/minimizable-dialog/", + "/components/media-object/", + "/components/media-object/api", + "/components/media-object/changelog", + "/components/meter", + "/components/pagination/", + "/components/modal/", + "/components/menu/", + "/components/paragraph/", + "/components/popover/", + "/components/product-switcher/", + "/components/progress-steps/", + "/components/radio-group/", + "/components/radio-button-group/", + "/components/screen-reader-only/", + "/components/select/", + "/components/separator/", + "/components/sidebar/", + "/components/sidebar-navigation/", + "/components/stack/", + "/components/stack/api", + "/components/stack/changelog", + "/components/status-badge/", + "/components/status-menu/", + "/components/spinner/", + "/components/skeleton-loader/", + "/components/slider/", + "/components/switch/", + "/components/tabs/", + "/components/toast/", + "/components/time-picker/", + "/components/truncate/", + "/components/tooltip/", + "/components/topbar", + "/components/user-dialog/", + "/components/textarea/", + "/components/table/", + "/components/table/api", + "/components/table/changelog", + "/components/visual-picker/", + "/core/", + "/core/changelog/", + "/core/libraries/", + "/core/libraries/code-editor/", + "/core/libraries/codemods/", + "/core/libraries/data-visualization/", + "/core/libraries/uid-library/", + "/core/libraries/vs-code-plugin/", + "/core/upgrade-guide/", + "/customization/composing-custom-components-with-design-tokens/", + "/customization/creating-a-custom-theme/", + "/customization/customization-provider/", + "/customization/customizing-component-elements/", + "/foundations/colors/", + "/foundations/content/content-checklist/", + "/foundations/content/voice-and-tone/", + "/foundations/content/word-list/", + "/foundations/illustrations/", + "/foundations/data-visualization/", + "/foundations/spacing-and-layout/", + "/foundations/typography/", + "/inclusive-design/", + "/foundations/content/product-style-guide/", + "/introduction/about-paste/", + "/introduction/contributing/components/", + "/foundations/content/", + "/introduction/contributing/icons/", + "/introduction/contributing/patterns/", + "/introduction/for-designers/design-guidelines/", + "/introduction/for-engineers/manual-installation/", + "/introduction/for-engineers/quickstart/", + "/introduction/working-with-us/", + "/page-templates/", + "/page-templates/object-details/", + "/page-templates/objects-list/", + "/page-templates/settings/", + "/patterns/button-vs-anchor/", + "/patterns/confirmation/", + "/patterns/delete/", + "/patterns/data-export/", + "/patterns/filter-group/", + "/patterns/", + "/patterns/empty-state/", + "/patterns/error-state/", + "/patterns/navigation/", + "/patterns/notifications-and-feedback/", + "/patterns/privacy/", + "/patterns/status/", + "/primitives/combobox-primitive/", + "/patterns/create/", + "/primitives/", + "/primitives/menu-primitive/", + "/primitives/disclosure-primitive/", + "/primitives/modal-dialog-primitive/", + "/primitives/non-modal-dialog-primitive/", + "/primitives/tabs-primitive/", + "/primitives/text/", + "/primitives/tooltip-primitive/", + "/primitives/listbox-primitive/", + "/roadmap/", + "/theme/", + "/theme/changing-theme/", + "/theme/dark-theme/", + "/tokens/design-tokens-package/", + "/tokens/", + "/primitives/box/", ]; const SITEMAP_CHUNKS: string[][] = []; @@ -183,4 +183,4 @@ for (var i = 0, len = SITEMAP.length; i < len; i += CHUNK_SIZE) { SITEMAP_CHUNKS.push(SITEMAP.slice(i, i + CHUNK_SIZE)); } -export {SITEMAP_CHUNKS}; +export { SITEMAP_CHUNKS }; diff --git a/cypress/integration/sitemap-vrt/index.spec.ts b/cypress/integration/sitemap-vrt/index.spec.ts index 5c7adc5064..b627644c1a 100644 --- a/cypress/integration/sitemap-vrt/index.spec.ts +++ b/cypress/integration/sitemap-vrt/index.spec.ts @@ -1,9 +1,9 @@ -import {SITEMAP_CHUNKS} from './constants'; +import { SITEMAP_CHUNKS } from "./constants"; -describe('Full Site VRT Batch 1', function () { +describe("Full Site VRT Batch 1", function () { SITEMAP_CHUNKS[0].forEach((url) => { it(`should vrt ${url}`, () => { - cy.visualRegressionTestUrl({url, testName: url}); + cy.visualRegressionTestUrl({ url, testName: url }); }); }); }); diff --git a/cypress/integration/token-list/index.spec.ts b/cypress/integration/token-list/index.spec.ts index d0f090fdf9..1bba292404 100644 --- a/cypress/integration/token-list/index.spec.ts +++ b/cypress/integration/token-list/index.spec.ts @@ -1,78 +1,78 @@ // ℹ️ If we use anon functions instead of arrow functions, we can leverage Mocha's context and pull the test name directly from this -describe('Token list filter with no existing search params', function () { +describe("Token list filter with no existing search params", function () { // ℹ️ We are able to reference `this.title` because we have bound this describe block to the Cypress context. const testSuiteName = this.title; beforeEach(() => { - cy.visit('/tokens/list'); + cy.visit("/tokens/list"); }); - describe('Visual regression tests', () => { - it('Basic VRT', () => { - cy.visualRegressionTestUrl({url: '/tokens/list', testName: `${testSuiteName}-basic-page-check`}); + describe("Visual regression tests", () => { + it("Basic VRT", () => { + cy.visualRegressionTestUrl({ url: "/tokens/list", testName: `${testSuiteName}-basic-page-check` }); }); }); }); -describe('Token list filter format control and theme control', function () { +describe("Token list filter format control and theme control", function () { beforeEach(() => { - cy.visit('/tokens/list'); + cy.visit("/tokens/list"); }); - it('controls format of token name (default = css)', () => { + it("controls format of token name (default = css)", () => { const tokenNode = cy.get('[data-cy="tokens-table-container"] li:first dt [data-paste-element="TEXT"]'); - cy.get('[data-cy="format-control"]').should('have.value', 'css'); + cy.get('[data-cy="format-control"]').should("have.value", "css"); cy.wait(300); tokenNode.contains(/^[$]/); tokenNode.contains(/[^A-Z]/); }); - it('controls format of token name (Javascript)', () => { + it("controls format of token name (Javascript)", () => { const tokenNode = cy.get('[data-cy="tokens-table-container"] li:first dt [data-paste-element="TEXT"]'); - cy.get('[data-cy="format-control"]').select('javascript').should('have.value', 'javascript'); + cy.get('[data-cy="format-control"]').select("javascript").should("have.value", "javascript"); cy.wait(300); tokenNode.contains(/^[a-z]/); tokenNode.contains(/[^$-]/); }); - it('controls format of token name (CSS)', () => { + it("controls format of token name (CSS)", () => { const tokenNode = cy.get('[data-cy="tokens-table-container"] li:first dt [data-paste-element="TEXT"]'); - cy.get('[data-cy="format-control"]').select('css').should('have.value', 'css'); + cy.get('[data-cy="format-control"]').select("css").should("have.value", "css"); cy.wait(300); tokenNode.contains(/^[$]/); tokenNode.contains(/[^A-Z]/); }); - it('controls the theme of filtered tokens', () => { - cy.get('[data-cy="theme-control"]').select('dark').should('have.value', 'dark'); + it("controls the theme of filtered tokens", () => { + cy.get('[data-cy="theme-control"]').select("dark").should("have.value", "dark"); cy.get('[data-cy="tokens-table-container"] li:first dd [data-paste-element="TEXT"]:first').should( - 'include.text', - 'rgb(18, 28, 45)' + "include.text", + "rgb(18, 28, 45)", ); - cy.get('[data-cy="theme-control"]').select('default').should('have.value', 'default'); + cy.get('[data-cy="theme-control"]').select("default").should("have.value", "default"); cy.get('[data-cy="tokens-table-container"] li:first dd [data-paste-element="TEXT"]:first').should( - 'include.text', - 'rgb(244, 244, 246)' + "include.text", + "rgb(244, 244, 246)", ); }); - it('has a responsive layout', () => { - cy.get('[data-cy="input-column"]').should('have.css', 'min-width', '0px'); - cy.viewport('iphone-x'); - cy.get('[data-cy="input-column"]').should('have.css', 'min-width', '100%'); + it("has a responsive layout", () => { + cy.get('[data-cy="input-column"]').should("have.css", "min-width", "0px"); + cy.viewport("iphone-x"); + cy.get('[data-cy="input-column"]').should("have.css", "min-width", "100%"); }); }); -describe('Token Card', function () { +describe("Token Card", function () { beforeEach(() => { - cy.visit('/tokens/list'); + cy.visit("/tokens/list"); }); - it('has a responsive layout', () => { - cy.get('[data-paste-element=TOKEN_CARD] dd').should('have.css', 'display', 'flex'); - cy.get('[data-paste-element=TOKEN_CARD] dd ul').should('have.css', 'maxWidth', '192px'); - cy.viewport('iphone-x'); - cy.get('[data-paste-element=TOKEN_CARD] dd').should('have.css', 'display', 'block'); - cy.get('[data-paste-element=TOKEN_CARD] dd ul').should('have.css', 'maxWidth', 'none'); + it("has a responsive layout", () => { + cy.get("[data-paste-element=TOKEN_CARD] dd").should("have.css", "display", "flex"); + cy.get("[data-paste-element=TOKEN_CARD] dd ul").should("have.css", "maxWidth", "192px"); + cy.viewport("iphone-x"); + cy.get("[data-paste-element=TOKEN_CARD] dd").should("have.css", "display", "block"); + cy.get("[data-paste-element=TOKEN_CARD] dd ul").should("have.css", "maxWidth", "none"); }); }); diff --git a/cypress/integration/word-list/index.spec.ts b/cypress/integration/word-list/index.spec.ts index cdf2f4f9ca..e48466450d 100644 --- a/cypress/integration/word-list/index.spec.ts +++ b/cypress/integration/word-list/index.spec.ts @@ -1,26 +1,26 @@ -describe('Word list with no filters', function () { +describe("Word list with no filters", function () { beforeEach(() => { - cy.visit('/foundations/content/word-list'); + cy.visit("/foundations/content/word-list"); }); - it('should have a pre-populated list of words in the table', () => { - cy.get('[data-cy="word-list-table"] tbody tr').its('length').should('be.greaterThan', 70); + it("should have a pre-populated list of words in the table", () => { + cy.get('[data-cy="word-list-table"] tbody tr').its("length").should("be.greaterThan", 70); }); }); -describe('Word list with filters', function () { +describe("Word list with filters", function () { beforeEach(() => { - cy.visit('/foundations/content/word-list'); + cy.visit("/foundations/content/word-list"); }); - it('should filter the table when a filter string is provided', () => { - cy.get('[data-cy="word-list-table"] tbody tr').as('table-rows'); - cy.get('[data-cy="word-list-filter-input"]').click().type('ad'); - cy.get('@table-rows').its('length').should('eq', 4); + it("should filter the table when a filter string is provided", () => { + cy.get('[data-cy="word-list-table"] tbody tr').as("table-rows"); + cy.get('[data-cy="word-list-filter-input"]').click().type("ad"); + cy.get("@table-rows").its("length").should("eq", 4); }); - it('should show empty state when nothing returned', () => { - cy.get('[data-cy="word-list-filter-input"]').click().type('adddd'); - cy.get('[data-cy="word-list-table"]').should('not.exist'); - cy.get('[data-cy="word-list-empty-state"]').should('be.visible'); + it("should show empty state when nothing returned", () => { + cy.get('[data-cy="word-list-filter-input"]').click().type("adddd"); + cy.get('[data-cy="word-list-table"]').should("not.exist"); + cy.get('[data-cy="word-list-empty-state"]').should("be.visible"); }); }); diff --git a/cypress/support/commands/index.ts b/cypress/support/commands/index.ts index ed5dbd5761..ecb3461918 100644 --- a/cypress/support/commands/index.ts +++ b/cypress/support/commands/index.ts @@ -1 +1 @@ -import './parent-commands'; +import "./parent-commands"; diff --git a/cypress/support/commands/parent-commands.ts b/cypress/support/commands/parent-commands.ts index d160d2acd7..2ebafe8126 100644 --- a/cypress/support/commands/parent-commands.ts +++ b/cypress/support/commands/parent-commands.ts @@ -1,4 +1,4 @@ -import {DEFAULT_VRT_OPTIONS, vrtIsEnabled} from '../utils/vrt'; +import { DEFAULT_VRT_OPTIONS, vrtIsEnabled } from "../utils/vrt"; /** * @file Custom parent commands @@ -8,101 +8,106 @@ import {DEFAULT_VRT_OPTIONS, vrtIsEnabled} from '../utils/vrt'; * @see https://on.cypress.io/custom-commands#Parent-Commands */ -Cypress.Commands.add('getDocsPageContentArea', () => cy.get('#paste-docs-content-area')); +Cypress.Commands.add("getDocsPageContentArea", () => cy.get("#paste-docs-content-area")); Cypress.Commands.add( - 'pageHeaderShouldBeVisible', - ({headerText, shouldHaveGithubLink, shouldHaveStorybook, shouldHaveOpenGraph}) => { - cy.contains('h1', headerText).should('be.visible'); - shouldHaveGithubLink && cy.contains('Github').should('be.visible'); - shouldHaveStorybook && cy.contains('Storybook').should('be.visible'); - shouldHaveOpenGraph && cy.get('meta[property="og:image"]').should('exist'); - } + "pageHeaderShouldBeVisible", + ({ headerText, shouldHaveGithubLink, shouldHaveStorybook, shouldHaveOpenGraph }) => { + cy.contains("h1", headerText).should("be.visible"); + shouldHaveGithubLink && cy.contains("Github").should("be.visible"); + shouldHaveStorybook && cy.contains("Storybook").should("be.visible"); + shouldHaveOpenGraph && cy.get('meta[property="og:image"]').should("exist"); + }, ); -Cypress.Commands.add('overviewTableRendersCorrectly', () => { - cy.get('table').first().as('componentsTable').should('be.visible'); - cy.get('@componentsTable').find('thead').find('tr').find('th').as('overviewTableHeaders'); - cy.get('@componentsTable').find('tbody').find('tr').as('tableRows'); +Cypress.Commands.add("overviewTableRendersCorrectly", () => { + cy.get("table").first().as("componentsTable").should("be.visible"); + cy.get("@componentsTable").find("thead").find("tr").find("th").as("overviewTableHeaders"); + cy.get("@componentsTable").find("tbody").find("tr").as("tableRows"); // Table has correct number of headers - cy.get('@overviewTableHeaders').should('have.length', 6); + cy.get("@overviewTableHeaders").should("have.length", 6); // Table has correct text for headers - const headers = ['Name', 'Status', 'Code ready', 'Design assets', 'Documentation', 'Peer review']; - cy.get('@overviewTableHeaders').each((header, index) => { + const headers = ["Name", "Status", "Code ready", "Design assets", "Documentation", "Peer review"]; + cy.get("@overviewTableHeaders").each((header, index) => { // using include here to do a loose match of headers - cy.wrap(header).should('include.text', headers[index]); + cy.wrap(header).should("include.text", headers[index]); }); // verify at least one row is rendered. - cy.get('@tableRows').its('length').should('be.greaterThan', 0); + cy.get("@tableRows").its("length").should("be.greaterThan", 0); }); -Cypress.Commands.add('checkInPageNavigationLinks', () => { - cy.getDocsPageContentArea().as('contentArea'); +Cypress.Commands.add("checkInPageNavigationLinks", () => { + cy.getDocsPageContentArea().as("contentArea"); - cy.get('@contentArea').find('[data-cy="page-aside-anchor"]').as('pageAsideAnchors'); + cy.get("@contentArea").find('[data-cy="page-aside-anchor"]').as("pageAsideAnchors"); - cy.get('@contentArea') + cy.get("@contentArea") .find( - '[data-cy="anchored-heading-h2"]:not(#component-changelog a),[data-cy="anchored-heading-h3"]:not(#component-changelog a)' + '[data-cy="anchored-heading-h2"]:not(#component-changelog a),[data-cy="anchored-heading-h3"]:not(#component-changelog a)', ) - .as('anchoredHeadings'); - - cy.get('@pageAsideAnchors').then((anchors) => { - cy.get('@anchoredHeadings').each((anchor, idx) => { - cy.wrap(anchor).should('have.attr', 'href').and('include', '#'); - cy.wrap(anchors[idx]).should('have.attr', 'href').and('include', '#').and('eql', anchor.attr('href')); + .as("anchoredHeadings"); + + cy.get("@pageAsideAnchors").then((anchors) => { + cy.get("@anchoredHeadings").each((anchor, idx) => { + cy.wrap(anchor).should("have.attr", "href").and("include", "#"); + cy.wrap(anchors[idx]) + .should("have.attr", "href") + .and("include", "#") + .and("eql", anchor.attr("href")); }); }); }); -Cypress.Commands.add('checkPageAside', () => { - cy.getDocsPageContentArea().getInFixedContainer('[data-cy="page-aside"]').as('pageAside'); - cy.get('@pageAside').find('[data-cy="table-of-contents"]').should('be.visible'); - cy.get('@pageAside').contains('button', 'Rate this page').should('be.visible'); - cy.get('@pageAside').find('[data-cy="page-aside-anchor"]').should('be.visible'); +Cypress.Commands.add("checkPageAside", () => { + cy.getDocsPageContentArea().getInFixedContainer('[data-cy="page-aside"]').as("pageAside"); + cy.get("@pageAside").find('[data-cy="table-of-contents"]').should("be.visible"); + cy.get("@pageAside").contains("button", "Rate this page").should("be.visible"); + cy.get("@pageAside").find('[data-cy="page-aside-anchor"]').should("be.visible"); }); -Cypress.Commands.add('checkLivePreviews', () => { - cy.getDocsPageContentArea().find('[data-cy="live-preview"]').should('have.length.above', 0); +Cypress.Commands.add("checkLivePreviews", () => { + cy.getDocsPageContentArea().find('[data-cy="live-preview"]').should("have.length.above", 0); }); -Cypress.Commands.add('checkDoDonts', () => { - cy.getDocsPageContentArea().find('[data-cy="do-dont-container"]').and('have.length.above', 0); - cy.getDocsPageContentArea().find('[data-cy="do-box"]').and('have.length.above', 0); - cy.getDocsPageContentArea().find('[data-cy="dont-box"]').and('have.length.above', 0); +Cypress.Commands.add("checkDoDonts", () => { + cy.getDocsPageContentArea().find('[data-cy="do-dont-container"]').and("have.length.above", 0); + cy.getDocsPageContentArea().find('[data-cy="do-box"]').and("have.length.above", 0); + cy.getDocsPageContentArea().find('[data-cy="dont-box"]').and("have.length.above", 0); }); -Cypress.Commands.add('checkChangelogRevealer', () => { - cy.getInFixedContainer('#component-changelog') - .as('changelogContainer') - .contains('h2', 'Changelog') - .should('be.visible') +Cypress.Commands.add("checkChangelogRevealer", () => { + cy.getInFixedContainer("#component-changelog") + .as("changelogContainer") + .contains("h2", "Changelog") + .should("be.visible") .click(); // Note: when cypress is upgraded, we can specify ScrollBehavior here to center if not default - cy.get('@changelogContainer').find('[data-cy="changelog-revealer-content"]').should('be.visible'); + cy.get("@changelogContainer").find('[data-cy="changelog-revealer-content"]').should("be.visible"); }); -Cypress.Commands.add('getInFixedContainer', (selector) => { - cy.get(selector).as('target'); +Cypress.Commands.add("getInFixedContainer", (selector) => { + cy.get(selector).as("target"); return cy - .get('@target') - .invoke('innerHeight') + .get("@target") + .invoke("innerHeight") .then((height) => { - return cy.get('@target').scrollIntoView({offset: {top: (height as number) / 2, left: 0}, ensureScrollable: true}); + return cy + .get("@target") + .scrollIntoView({ offset: { top: (height as number) / 2, left: 0 }, ensureScrollable: true }); }); }); -Cypress.Commands.add('visualRegressionTestUrl', ({url, testName}) => { +Cypress.Commands.add("visualRegressionTestUrl", ({ url, testName }) => { cy.visit(url); cy.wait(2500); - cy.log('[VRT]: checking if VRT is enabled'); + cy.log("[VRT]: checking if VRT is enabled"); if (vrtIsEnabled()) { - cy.log('[VRT]: VRT is enabled, proceed.'); + cy.log("[VRT]: VRT is enabled, proceed."); const vrtOptions = { ...DEFAULT_VRT_OPTIONS, @@ -119,7 +124,7 @@ Cypress.Commands.add('visualRegressionTestUrl', ({url, testName}) => { cy.log(`[VRT]: Taking snapshot with these params: ${vrtOptions}`); cy.percySnapshot(testName, vrtOptions); } else { - cy.log('[VRT]: VRT is not enabled, skipping'); + cy.log("[VRT]: VRT is not enabled, skipping"); } expect(true).to.equal(true); diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.ts index d10b6821dc..28c852a52a 100644 --- a/cypress/support/e2e.ts +++ b/cypress/support/e2e.ts @@ -13,16 +13,16 @@ // https://on.cypress.io/configuration // *********************************************************** -import '@percy/cypress'; +import "@percy/cypress"; // Import commands.js using ES2015 syntax: -import './commands'; +import "./commands"; // Alternatively you can use CommonJS syntax: // require('./commands') const resizeObserverLoopErrRe = /^[^(ResizeObserver loop limit exceeded)]/; -Cypress.on('uncaught:exception', (err) => { +Cypress.on("uncaught:exception", (err) => { /* returning false here prevents Cypress from failing the test Benign error occurs when an observer takes longer than one frame to execute, like in the case of disclosures opening on the website sidebar. diff --git a/cypress/support/utils/vrt.ts b/cypress/support/utils/vrt.ts index 5aaffc066e..c0470fdf13 100644 --- a/cypress/support/utils/vrt.ts +++ b/cypress/support/utils/vrt.ts @@ -1,5 +1,5 @@ enum EnvironmentVariables { - UseCypressVRT = 'USE_CYPRESS_VRT', + UseCypressVRT = "USE_CYPRESS_VRT", } export const DEFAULT_VRT_OPTIONS = {}; @@ -9,6 +9,6 @@ export const DEFAULT_VRT_OPTIONS = {}; */ export const vrtIsEnabled = (): boolean => { const vrtEnabled = Cypress.env(EnvironmentVariables.UseCypressVRT); - cy.log(`[VRT]: VRT is ${vrtEnabled ? '' : 'not '}enabled`); + cy.log(`[VRT]: VRT is ${vrtEnabled ? "" : "not "}enabled`); return Cypress.env(EnvironmentVariables.UseCypressVRT); }; diff --git a/dangerfile.ts b/dangerfile.ts index d0ca61b941..633ef36455 100644 --- a/dangerfile.ts +++ b/dangerfile.ts @@ -1,12 +1,12 @@ +import changesetsThatNeedCoreCheck from "./.danger/changesets-that-need-core-check"; +import missingChangesetsCheck from "./.danger/missing-changesets-check"; +import missingUpgradeGuide from "./.danger/missing-upgrade-guide-check"; // https://danger.systems/js/reference.html -import packageJsonCheck from './.danger/package-json-check'; -import missingChangesetsCheck from './.danger/missing-changesets-check'; -import changesetsThatNeedCoreCheck from './.danger/changesets-that-need-core-check'; -import missingUpgradeGuide from './.danger/missing-upgrade-guide-check'; -import websitePageVrtCheck from './.danger/website-page-vrt-check'; -import pinExternalDeps from './.danger/pin-external-deps'; -import {getRepoPackages} from './tools/utils/getRepoPackages'; -import type {PackageShape} from './tools/utils/getRepoPackages'; +import packageJsonCheck from "./.danger/package-json-check"; +import pinExternalDeps from "./.danger/pin-external-deps"; +import websitePageVrtCheck from "./.danger/website-page-vrt-check"; +import { getRepoPackages } from "./tools/utils/getRepoPackages"; +import type { PackageShape } from "./tools/utils/getRepoPackages"; // eslint-disable-next-line import/no-default-export export default async (): Promise => { diff --git a/internal-docs/engineering/ci.md b/internal-docs/engineering/ci.md index 1bd3853026..952db8db11 100644 --- a/internal-docs/engineering/ci.md +++ b/internal-docs/engineering/ci.md @@ -7,7 +7,7 @@ - [Lint](#lint) - [Test React 17](#test-react-17) - [Test React 16](#test-react-16) - - [Prettier checks](#prettier-checks) + - [Code formatting checks](#code-formatting-checks) - [Categorize the PR using labels](#categorize-the-pr-using-labels) - [Danger checks](#danger-checks) - [Check package sizes](#check-package-sizes) @@ -55,9 +55,12 @@ This job downloads the build cache of the monorepo, and then runs our Jest test This job downloads the build cache of the monorepo, and then runs our Jest test suite using React 16. -### Prettier checks +### Code formatting checks + +This job downloads the build cache of the monorepo, and then runs [BiomeJS](https://biomejs.dev/) and [Prettier](https://prettier.io/). BiomeJS runs on all TS(X) / JS(X) / JSON(C) / CSS files. Prettier runs on everything else, such as HTML, MDX, etc... + +Biome was selected due to its tremendous performance improvements over prettier to run on our main codebase. It lacks complete support for all file extensions, so prettier is still used where needed on unsupported file types. -This job downloads the build cache of the monorepo, and then runs Prettier. ### Categorize the PR using labels diff --git a/internal-docs/engineering/technologies.md b/internal-docs/engineering/technologies.md index 2ee4c70a48..7ae5600799 100644 --- a/internal-docs/engineering/technologies.md +++ b/internal-docs/engineering/technologies.md @@ -118,4 +118,4 @@ Our icons are converted from SVG to React components at compile time using our o ## Code Style -We use eslint (https://eslint.org/) and Prettier ([https://prettier.io/](https://prettier.io/)) to maintain a consistent, readable code style throughout the entire monorepo. +We use eslint (https://eslint.org/), [BiomeJS](https://biomejs.dev/), and Prettier ([https://prettier.io/](https://prettier.io/)) to maintain a consistent, readable code style throughout the entire monorepo. diff --git a/internal-docs/engineering/testing.md b/internal-docs/engineering/testing.md index 7c94655167..faef716fd6 100644 --- a/internal-docs/engineering/testing.md +++ b/internal-docs/engineering/testing.md @@ -9,7 +9,7 @@ - [End-to-end testing](#end-to-end-testing) - [Visual Regression Testing (VRT)](#visual-regression-testing-vrt) - [Linting](#linting) - - [PrettierJS](#prettierjs) + - [BiomeJS and PrettierJS](#biomejs-and-prettierjs) - [Commit lint](#commit-lint) - [Running tests/checks](#running-testschecks) - [Locally](#locally) @@ -98,11 +98,11 @@ Linting should be performed: If your code fails to meet the ESLint rules, you will “break the build”. This will prevent you from merging a PR or publishing new packages on `main`. -### PrettierJS +### BiomeJS and PrettierJS -Manually formatting code can be tiresome so we use [PrettierJS](https://prettier.io/) (Prettier) to do the leg work for you. Prettier is an opinionated code formatter which is configured to respect our ESLint rules. +Manually formatting code can be tiresome so we use [BiomeJS](https://biomejs.dev/) and [PrettierJS](https://prettier.io/) (Prettier) to do the leg work for you. They are both an opinionated code formatter which is configured to respect our ESLint rules. -It is configured to format your code when you commit it to git automatically. If using an IDE or Code Editor it is also recommended, if your IDE or editor supports it, to set it to “format on save”. The setting is often found in the user settings of your editor, and may require a Prettier plugin or extension. +It is configured to format your code when you commit it to git automatically. If using an IDE or Code Editor it is also recommended, if your IDE or editor supports it, to set it to “format on save”. The setting is often found in the user settings of your editor, and may require a plugin or extension. ### Commit lint diff --git a/jest.config.js b/jest.config.js index fbaa4f09fa..e07b997a9d 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,29 +1,29 @@ -const TestTheme = require('./.jest/globals/TestTheme'); +const TestTheme = require("./.jest/globals/TestTheme"); module.exports = { globals: { TestTheme, }, - testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.(js|jsx|ts|tsx)?$', - testEnvironment: 'jsdom', + testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.(js|jsx|ts|tsx)?$", + testEnvironment: "jsdom", testPathIgnorePatterns: [ - '/packages/(?:.+?)/dist/', - '/packages/(?:.+?)/.cache/', - '/cypress/', - '/apps/', - '/packages/(?:.+?)/.next/', - '/templates/(?:.+?)/.next/', - '/packages/(?:.+?)/.netlify/', + "/packages/(?:.+?)/dist/", + "/packages/(?:.+?)/.cache/", + "/cypress/", + "/apps/", + "/packages/(?:.+?)/.next/", + "/templates/(?:.+?)/.next/", + "/packages/(?:.+?)/.netlify/", ], - cacheDirectory: '.jest-cache', - coverageDirectory: '.jest-coverage', + cacheDirectory: ".jest-cache", + coverageDirectory: ".jest-coverage", coveragePathIgnorePatterns: [ - '/packages/(?:.+?)/dist/', - '/packages/(?:.+?)/cjs/', - '/packages/(?:.+?)/esm/', - '/apps/', + "/packages/(?:.+?)/dist/", + "/packages/(?:.+?)/cjs/", + "/packages/(?:.+?)/esm/", + "/apps/", ], - coverageReporters: ['html', 'text'], + coverageReporters: ["html", "text"], coverageThreshold: { global: { branches: 100, @@ -33,25 +33,25 @@ module.exports = { }, }, moduleNameMapper: { - '\\.css$': 'identity-obj-proxy', + "\\.css$": "identity-obj-proxy", // monkey-patch introduced for @testing-library/user-event to improve asynchronous test readability // taken from this github issue: https://github.com/testing-library/user-event/issues/938#issuecomment-1111976312 - '^@testing-library/user-event$': '/tools/test/act-user-event.ts', - '^@testing-library/real-user-event$': require.resolve('@testing-library/user-event'), + "^@testing-library/user-event$": "/tools/test/act-user-event.ts", + "^@testing-library/real-user-event$": require.resolve("@testing-library/user-event"), // monkey-patch to help with @testing-library/reat-hooks being deprecated // the render hook method is being exported from @testing-library/react in later versions - '^@testing-library/react$': '/tools/test/react-testing-library.ts', - '^@testing-library/real-react$': require.resolve('@testing-library/react'), + "^@testing-library/react$": "/tools/test/react-testing-library.ts", + "^@testing-library/real-react$": require.resolve("@testing-library/react"), // helper method to handle the changes in the react-dom api for react 18 - '^testing-tools/react-dom-create-root$': '/tools/test/react-dom-create-root.ts', + "^testing-tools/react-dom-create-root$": "/tools/test/react-dom-create-root.ts", // jest can't find lerna for the codemod tests, so we need to tell it where to look - '^lerna$': require.resolve('lerna'), + "^lerna$": require.resolve("lerna"), }, - transformIgnorePatterns: ['node_modules/'], + transformIgnorePatterns: ["node_modules/"], transform: { - '^.+\\.(js|jsx|ts|tsx)?$': '@swc/jest', + "^.+\\.(js|jsx|ts|tsx)?$": "@swc/jest", }, - extensionsToTreatAsEsm: ['.ts', '.tsx'], - setupFilesAfterEnv: ['/.jest/setupFilesAfterEnv.js'], - snapshotSerializers: ['@emotion/jest/serializer'], + extensionsToTreatAsEsm: [".ts", ".tsx"], + setupFilesAfterEnv: ["/.jest/setupFilesAfterEnv.js"], + snapshotSerializers: ["@emotion/jest/serializer"], }; diff --git a/package.json b/package.json index cf3ba30b3d..4ef0dc4ca8 100644 --- a/package.json +++ b/package.json @@ -6,12 +6,7 @@ "author": "Twilio Inc.", "license": "MIT", "workspaces": { - "packages": [ - "apps/**/*", - "packages/**/*", - "templates/**/*", - "!packages/paste-core/core-bundle/**/*" - ] + "packages": ["apps/**/*", "packages/**/*", "templates/**/*", "!packages/paste-core/core-bundle/**/*"] }, "types": "./types/index.d.ts", "engines": { @@ -43,7 +38,7 @@ "build:theme-designer": "yarn nx run @twilio-paste/theme-designer:build", "build:nextjs-template": "yarn nx run @twilio-paste/nextjs-template:build", "build:contrast-checking": "yarn nx run @twilio-paste/token-contrast-checker:build", - "pre-push": "concurrently \"yarn:lint\" \"yarn:test\" \"yarn:prettier\" \"yarn:type-check\"", + "pre-push": "concurrently \"yarn:lint\" \"yarn:test\" \"yarn:format\" \"yarn:type-check\"", "prerelease": "yarn build && yarn lint && yarn test", "release": "yarn changeset publish", "release:next": "yarn lerna publish -m 'chore(release): pre release' --conventional-commits --canary --preid beta --dist-tag next", @@ -63,8 +58,6 @@ "start:test:storybook": "start-server-and-test 'NODE_ENV=test yarn start:storybook' http://localhost:9001 'yarn test:storybook'", "serve:website": "yarn workspace @twilio-paste/website start", "package-size-action-build": "yarn build", - "prettier": "prettier --list-different '{.storybook,packages,templates}/**/*.{ts,tsx}'", - "prettier-clean": "prettier --write '{.storybook,packages,templates}/**/*.{ts,tsx}'", "lint": "yarn pre-test && yarn lint:repo && yarn lint:core && yarn lint:website && yarn lint:remix && yarn lint:contrast-checker && yarn lint:nextjs-template && yarn lint:vscode-intellisense", "lint:core": "eslint -c .eslintrc.core.js --ext .tsx,.ts ./packages/{paste-color-contrast-utils,paste-core,paste-customization,paste-design-tokens,paste-icons,paste-libraries,paste-style-props,paste-theme,paste-types,paste-utils}/**/src", "lint:website": "eslint -c ./packages/paste-website/.eslintrc --ext .tsx,.ts ./packages/paste-website", @@ -73,6 +66,9 @@ "lint:nextjs-template": "eslint -c ./templates/paste-nextjs-template/.eslintrc.json --ext .tsx,.ts ./templates/paste-nextjs-template", "lint:vscode-intellisense": "eslint -c ./apps/vs-code-intellisense/.eslintrc.json --ext .tsx,.ts ./apps/vs-code-intellisense", "lint:repo": "eslint -c .eslintrc.repo.js --ext .tsx,.ts .", + "format": "biome format ./ && prettier --list-different ./packages/", + "format:write": "biome format ./ --write", + "format:ci": "biome ci ./ --linter-enabled=false && prettier --list-different ./packages/", "type-check": "yarn prebuild && yarn nx run-many --target=tsc", "tsc": "echo 'Did you mean to run yarn type-check?'", "chromatic": "chromatic", @@ -94,6 +90,7 @@ "@babel/preset-react": "^7.18.6", "@babel/preset-typescript": "^7.21.4", "@babel/types": "^7.21.4", + "@biomejs/biome": "1.2.2", "@changesets/changelog-github": "^0.2.8", "@changesets/cli": "^2.13.1", "@commitlint/cli": "16.2.1", @@ -224,9 +221,5 @@ } }, "packageManager": "yarn@3.6.3", - "browserslist": [ - "last 2 versions", - "not dead", - "not IE 11" - ] + "browserslist": ["last 2 versions", "not dead", "not IE 11"] } diff --git a/packages/paste-codemods/tools/__tests__/tools.spec.ts b/packages/paste-codemods/tools/__tests__/tools.spec.ts index 9d5e69ac79..03fdfc98d7 100644 --- a/packages/paste-codemods/tools/__tests__/tools.spec.ts +++ b/packages/paste-codemods/tools/__tests__/tools.spec.ts @@ -1,51 +1,51 @@ -import type {PackageShape} from '../../../../tools/utils/getRepoPackages'; -import {generatePackageExportsMap} from '../generatePackageExportsMap'; +import type { PackageShape } from "../../../../tools/utils/getRepoPackages"; +import { generatePackageExportsMap } from "../generatePackageExportsMap"; // This is a simplified mock of paste packages const mockGetPastePackages = async (): Promise => [ { - name: '@twilio-paste/stack', - version: '0.1.49', + name: "@twilio-paste/stack", + version: "0.1.49", private: false, - location: '/Users/sisber/twilio/dsys/paste/packages/paste-core/layout/stack', + location: "/Users/sisber/twilio/dsys/paste/packages/paste-core/layout/stack", }, { - name: '@twilio-paste/box', - version: '2.11.6', + name: "@twilio-paste/box", + version: "2.11.6", private: false, - location: '/Users/sisber/twilio/dsys/paste/packages/paste-core/primitives/box', + location: "/Users/sisber/twilio/dsys/paste/packages/paste-core/primitives/box", }, { - name: '@twilio-paste/combobox-primitive', - version: '0.1.9', + name: "@twilio-paste/combobox-primitive", + version: "0.1.9", private: false, - location: '/Users/sisber/twilio/dsys/paste/packages/paste-core/primitives/combobox', + location: "/Users/sisber/twilio/dsys/paste/packages/paste-core/primitives/combobox", }, { - name: '@twilio-paste/disclosure-primitive', - version: '0.2.6', + name: "@twilio-paste/disclosure-primitive", + version: "0.2.6", private: false, - location: '/Users/sisber/twilio/dsys/paste/packages/paste-core/primitives/disclosure', + location: "/Users/sisber/twilio/dsys/paste/packages/paste-core/primitives/disclosure", }, ]; -describe('generatePackageExportsMap', () => { - it('Creates mapping file successfully from mock', async () => { +describe("generatePackageExportsMap", () => { + it("Creates mapping file successfully from mock", async () => { const mockMapping = await generatePackageExportsMap(mockGetPastePackages); expect(mockMapping).toEqual({ - BOX_PROPS_TO_BLOCK: '@twilio-paste/core/box', - Box: '@twilio-paste/core/box', - ComboboxPrimitive: '@twilio-paste/core/combobox-primitive', - DisclosurePrimitive: '@twilio-paste/core/disclosure-primitive', - DisclosurePrimitiveContent: '@twilio-paste/core/disclosure-primitive', - Stack: '@twilio-paste/core/stack', - StyledBox: '@twilio-paste/core/box', - getCustomElementStyles: '@twilio-paste/core/box', - safelySpreadBoxProps: '@twilio-paste/core/box', - useComboboxPrimitive: '@twilio-paste/core/combobox-primitive', - useDisclosurePrimitiveState: '@twilio-paste/core/disclosure-primitive', - useMultiSelectPrimitive: '@twilio-paste/core/combobox-primitive', + BOX_PROPS_TO_BLOCK: "@twilio-paste/core/box", + Box: "@twilio-paste/core/box", + ComboboxPrimitive: "@twilio-paste/core/combobox-primitive", + DisclosurePrimitive: "@twilio-paste/core/disclosure-primitive", + DisclosurePrimitiveContent: "@twilio-paste/core/disclosure-primitive", + Stack: "@twilio-paste/core/stack", + StyledBox: "@twilio-paste/core/box", + getCustomElementStyles: "@twilio-paste/core/box", + safelySpreadBoxProps: "@twilio-paste/core/box", + useComboboxPrimitive: "@twilio-paste/core/combobox-primitive", + useDisclosurePrimitiveState: "@twilio-paste/core/disclosure-primitive", + useMultiSelectPrimitive: "@twilio-paste/core/combobox-primitive", }); }); diff --git a/packages/paste-codemods/tools/create-package-mappings.ts b/packages/paste-codemods/tools/create-package-mappings.ts index b71f1669b2..181bd62829 100644 --- a/packages/paste-codemods/tools/create-package-mappings.ts +++ b/packages/paste-codemods/tools/create-package-mappings.ts @@ -1,15 +1,15 @@ -import path from 'path'; +import path from "path"; -import {writeToFile} from '../../../tools/utils/writeToFile'; -import {generatePackageExportsMap} from './generatePackageExportsMap'; +import { writeToFile } from "../../../tools/utils/writeToFile"; +import { generatePackageExportsMap } from "./generatePackageExportsMap"; (async () => { const mapping = await generatePackageExportsMap(); // Write to disk - writeToFile(path.join(__dirname, '.cache/mappings.json'), mapping, { - successMessage: 'Wrote core packages export mapping to .cache/mappings.json file!', - errorMessage: 'Could not generate mappings!', + writeToFile(path.join(__dirname, ".cache/mappings.json"), mapping, { + successMessage: "Wrote core packages export mapping to .cache/mappings.json file!", + errorMessage: "Could not generate mappings!", formatJson: true, }); })(); diff --git a/packages/paste-codemods/tools/generatePackageExportsMap.ts b/packages/paste-codemods/tools/generatePackageExportsMap.ts index 199bf52541..a8aaed0817 100644 --- a/packages/paste-codemods/tools/generatePackageExportsMap.ts +++ b/packages/paste-codemods/tools/generatePackageExportsMap.ts @@ -1,4 +1,4 @@ -import {getRepoPackages} from '../../../tools/utils/getRepoPackages'; +import { getRepoPackages } from "../../../tools/utils/getRepoPackages"; export async function generatePackageExportsMap(getPackages = getRepoPackages): Promise> { // Object to store all the generated mappings for our codemod @@ -11,13 +11,13 @@ export async function generatePackageExportsMap(getPackages = getRepoPackages): const filteredPastePackages = allPastePackages?.filter((pkg) => { if (pkg.private) return false; // Only include Paste core packages (except core-bundle!) - if (!pkg.location.includes('/paste-core/') || pkg.location.includes('/paste-core/core-bundle')) return false; + if (!pkg.location.includes("/paste-core/") || pkg.location.includes("/paste-core/core-bundle")) return false; return true; }); - filteredPastePackages?.forEach(({name}) => { + filteredPastePackages?.forEach(({ name }) => { // convert package name to core name - const corePackageName = `@twilio-paste/core/${name.split('/')[1]}`; + const corePackageName = `@twilio-paste/core/${name.split("/")[1]}`; // Get the package's exported values to be mapped let packageExports = {}; diff --git a/packages/paste-codemods/transforms/__tests__/barreled-to-unbarreled.spec.tsx b/packages/paste-codemods/transforms/__tests__/barreled-to-unbarreled.spec.tsx index 1630383cd3..0beb0ce3fc 100644 --- a/packages/paste-codemods/transforms/__tests__/barreled-to-unbarreled.spec.tsx +++ b/packages/paste-codemods/transforms/__tests__/barreled-to-unbarreled.spec.tsx @@ -1,3 +1,3 @@ -const {defineTest} = require('jscodeshift/dist/testUtils'); +const { defineTest } = require("jscodeshift/dist/testUtils"); -defineTest(__dirname, 'barreled-to-unbarreled', null, 'barreled-to-unbarreled', {parser: 'ts'}); +defineTest(__dirname, "barreled-to-unbarreled", null, "barreled-to-unbarreled", { parser: "ts" }); diff --git a/packages/paste-codemods/transforms/barreled-to-unbarreled.js b/packages/paste-codemods/transforms/barreled-to-unbarreled.js index 4f3fab0521..961bc6b195 100644 --- a/packages/paste-codemods/transforms/barreled-to-unbarreled.js +++ b/packages/paste-codemods/transforms/barreled-to-unbarreled.js @@ -1,8 +1,8 @@ -const ComponentLookup = require('../tools/.cache/mappings.json'); +const ComponentLookup = require("../tools/.cache/mappings.json"); module.exports = function barreledToUnbarreled(fileInfo, api, options) { const j = api.jscodeshift; - const printOptions = options.printOptions || {quote: 'single', tabWidth: 2, trailingComma: true}; + const printOptions = options.printOptions || { quote: "single", tabWidth: 2, trailingComma: true }; const root = j(fileInfo.source); const importLookups = {}; @@ -10,7 +10,7 @@ module.exports = function barreledToUnbarreled(fileInfo, api, options) { const importSource = path.value.source.value; // If it isn't exactly from the package (i.e.: core/esm or core/dist etc) then skip it. - if (importSource !== '@twilio-paste/core') { + if (importSource !== "@twilio-paste/core") { return; } diff --git a/packages/paste-color-contrast-utils/__tests__/colorContrastPairingUtils.spec.ts b/packages/paste-color-contrast-utils/__tests__/colorContrastPairingUtils.spec.ts index 1b6e317896..32a5b37c84 100644 --- a/packages/paste-color-contrast-utils/__tests__/colorContrastPairingUtils.spec.ts +++ b/packages/paste-color-contrast-utils/__tests__/colorContrastPairingUtils.spec.ts @@ -1,209 +1,209 @@ +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore type declaration warning for these token fixtures +import { tokens } from "../__fixtures__/tokens"; +import * as RawJSON from "../__fixtures__/tokens.raw.json"; +import * as RawExtraJSON from "../__fixtures__/tokensWithExtraPairings.raw.json"; import { + convertRawTokenJSONToArray, getContrastRatingForTokenPairing, + getTokensWithDataVisualizationContrastRequirements, getTokensWithTextContrastRequirements, getTokensWithUIControlContrastRequirements, - getTokensWithDataVisualizationContrastRequirements, - convertRawTokenJSONToArray, -} from '../src/utils'; -import * as RawJSON from '../__fixtures__/tokens.raw.json'; -import * as RawExtraJSON from '../__fixtures__/tokensWithExtraPairings.raw.json'; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore type declaration warning for these token fixtures -import {tokens} from '../__fixtures__/tokens'; +} from "../src/utils"; -describe('convertRawTokenJSONToArray', () => { - test('it should convert raw JSON to an array of tokens', () => { +describe("convertRawTokenJSONToArray", () => { + test("it should convert raw JSON to an array of tokens", () => { expect( convertRawTokenJSONToArray({ - 'color-text-weak': { - type: 'color', - category: 'text-color', - value: '#aeb2c1', - comment: 'Weaker body text for visual hierarchy. Inaccessible unless used on disabled controls.', - originalValue: '{!palette-gray-40}', - text_contrast_pairing: ['color-background-body'], - name: 'color-text-weak', + "color-text-weak": { + type: "color", + category: "text-color", + value: "#aeb2c1", + comment: "Weaker body text for visual hierarchy. Inaccessible unless used on disabled controls.", + originalValue: "{!palette-gray-40}", + text_contrast_pairing: ["color-background-body"], + name: "color-text-weak", }, - 'color-text-link-destructive-light': { - type: 'color', - category: 'text-color', - value: '#f6b1b1', - comment: 'Light shade of destructive link text to be used in interactions', - originalValue: '{!palette-red-30}', - name: 'color-text-link-destructive-light', + "color-text-link-destructive-light": { + type: "color", + category: "text-color", + value: "#f6b1b1", + comment: "Light shade of destructive link text to be used in interactions", + originalValue: "{!palette-red-30}", + name: "color-text-link-destructive-light", }, - }) + }), ).toEqual([ { - type: 'color', - category: 'text-color', - value: '#f6b1b1', - comment: 'Light shade of destructive link text to be used in interactions', - originalValue: '{!palette-red-30}', - name: 'color-text-link-destructive-light', + type: "color", + category: "text-color", + value: "#f6b1b1", + comment: "Light shade of destructive link text to be used in interactions", + originalValue: "{!palette-red-30}", + name: "color-text-link-destructive-light", }, { - type: 'color', - category: 'text-color', - value: '#aeb2c1', - comment: 'Weaker body text for visual hierarchy. Inaccessible unless used on disabled controls.', - originalValue: '{!palette-gray-40}', - text_contrast_pairing: ['color-background-body'], - name: 'color-text-weak', + type: "color", + category: "text-color", + value: "#aeb2c1", + comment: "Weaker body text for visual hierarchy. Inaccessible unless used on disabled controls.", + originalValue: "{!palette-gray-40}", + text_contrast_pairing: ["color-background-body"], + name: "color-text-weak", }, ]); }); }); -describe('getTokensWithTextContrastRequirements', () => { - test('it should only return tokens with text contrast requirements', () => { +describe("getTokensWithTextContrastRequirements", () => { + test("it should only return tokens with text contrast requirements", () => { expect(getTokensWithTextContrastRequirements(RawJSON.props)).toEqual([ { - category: 'text-color', - comment: 'Body text color', - name: 'color-text', - originalValue: '{!palette-gray-100}', - text_contrast_pairing: ['color-text-inverse-weaker', 'color-text-inverse'], - type: 'color', - value: '#121c2d', + category: "text-color", + comment: "Body text color", + name: "color-text", + originalValue: "{!palette-gray-100}", + text_contrast_pairing: ["color-text-inverse-weaker", "color-text-inverse"], + type: "color", + value: "#121c2d", }, { - category: 'text-color', - comment: 'Weak body text for visual hierarchy.', - name: 'color-text-weak', - originalValue: '{!palette-gray-60}', - text_contrast_pairing: ['color-text-link-destructive-light'], - type: 'color', - value: '#606b85', + category: "text-color", + comment: "Weak body text for visual hierarchy.", + name: "color-text-weak", + originalValue: "{!palette-gray-60}", + text_contrast_pairing: ["color-text-link-destructive-light"], + type: "color", + value: "#606b85", }, ]); }); }); -describe('getTokensWithUIControlContrastRequirements', () => { - test('it should only return tokens with text contrast requirements', () => { +describe("getTokensWithUIControlContrastRequirements", () => { + test("it should only return tokens with text contrast requirements", () => { expect(getTokensWithUIControlContrastRequirements(RawJSON.props)).toEqual([ { - category: 'text-color', - comment: 'Twilio brand red, accessible on large text only.', - name: 'color-text-brand-highlight', - originalValue: '{!amaranth}', - type: 'color', - uicontrol_contrast_pairing: ['color-text-link-light'], - value: '#F22F46', + category: "text-color", + comment: "Twilio brand red, accessible on large text only.", + name: "color-text-brand-highlight", + originalValue: "{!amaranth}", + type: "color", + uicontrol_contrast_pairing: ["color-text-link-light"], + value: "#F22F46", }, ]); }); }); -describe('getTokensWithDataVisualizationContrastRequirements', () => { - test('it should only return tokens with data visualization contrast requirements', () => { +describe("getTokensWithDataVisualizationContrastRequirements", () => { + test("it should only return tokens with data visualization contrast requirements", () => { expect(getTokensWithDataVisualizationContrastRequirements(RawExtraJSON.props)).toEqual([ { - category: 'color', - comment: 'Color used for data visualizations. Must be used in a sequence.', - data_visualization_contrast_pairing: ['color-data-visualization-8', 'color-data-visualization-10'], - name: 'color-data-visualization-9', - originalValue: '{!palette-red-80}', - type: 'color', - uicontrol_contrast_pairing: ['color-background-body'], - value: '#750c0c', + category: "color", + comment: "Color used for data visualizations. Must be used in a sequence.", + data_visualization_contrast_pairing: ["color-data-visualization-8", "color-data-visualization-10"], + name: "color-data-visualization-9", + originalValue: "{!palette-red-80}", + type: "color", + uicontrol_contrast_pairing: ["color-background-body"], + value: "#750c0c", }, ]); }); }); -describe('getContrastRatingForTokenPairing', () => { - test('it should get the contrast ratio rating for only text color contrast requirements', () => { +describe("getContrastRatingForTokenPairing", () => { + test("it should get the contrast ratio rating for only text color contrast requirements", () => { const filteredTextContrastTokens = getTokensWithTextContrastRequirements(RawJSON.props); - expect(getContrastRatingForTokenPairing(filteredTextContrastTokens, tokens, 'text_contrast_pairing')).toEqual([ + expect(getContrastRatingForTokenPairing(filteredTextContrastTokens, tokens, "text_contrast_pairing")).toEqual([ { aa: false, aaLarge: true, aaa: false, aaaLarge: false, - background: 'color-text-inverse-weaker', - backgroundValue: '#606b85', + background: "color-text-inverse-weaker", + backgroundValue: "#606b85", contrast: 3.2032894523289137, - foreground: 'color-text', - foregroundValue: '#121c2d', + foreground: "color-text", + foregroundValue: "#121c2d", }, { aa: true, aaLarge: true, aaa: true, aaaLarge: true, - background: 'color-text-inverse', - backgroundValue: '#ffffff', + background: "color-text-inverse", + backgroundValue: "#ffffff", contrast: 17.077148214998438, - foreground: 'color-text', - foregroundValue: '#121c2d', + foreground: "color-text", + foregroundValue: "#121c2d", }, { aa: false, aaLarge: true, aaa: false, aaaLarge: false, - background: 'color-text-link-destructive-light', - backgroundValue: '#f6b1b1', + background: "color-text-link-destructive-light", + backgroundValue: "#f6b1b1", contrast: 3.006321755625877, - foreground: 'color-text-weak', - foregroundValue: '#606b85', + foreground: "color-text-weak", + foregroundValue: "#606b85", }, ]); }); - test('it should filter out undefined values from the results when there is a pairing with a token not present in the theme', () => { + test("it should filter out undefined values from the results when there is a pairing with a token not present in the theme", () => { const filteredTextContrastTokens = getTokensWithTextContrastRequirements(RawExtraJSON.props); - expect(getContrastRatingForTokenPairing(filteredTextContrastTokens, tokens, 'text_contrast_pairing')).toEqual([ + expect(getContrastRatingForTokenPairing(filteredTextContrastTokens, tokens, "text_contrast_pairing")).toEqual([ { aa: false, aaLarge: true, aaa: false, aaaLarge: false, - background: 'color-text-inverse-weaker', - backgroundValue: '#606b85', + background: "color-text-inverse-weaker", + backgroundValue: "#606b85", contrast: 3.2032894523289137, - foreground: 'color-text', - foregroundValue: '#121c2d', + foreground: "color-text", + foregroundValue: "#121c2d", }, { aa: true, aaLarge: true, aaa: true, aaaLarge: true, - background: 'color-text-inverse', - backgroundValue: '#ffffff', + background: "color-text-inverse", + backgroundValue: "#ffffff", contrast: 17.077148214998438, - foreground: 'color-text', - foregroundValue: '#121c2d', + foreground: "color-text", + foregroundValue: "#121c2d", }, { aa: false, aaLarge: true, aaa: false, aaaLarge: false, - background: 'color-text-link-destructive-light', - backgroundValue: '#f6b1b1', + background: "color-text-link-destructive-light", + backgroundValue: "#f6b1b1", contrast: 3.006321755625877, - foreground: 'color-text-weak', - foregroundValue: '#606b85', + foreground: "color-text-weak", + foregroundValue: "#606b85", }, ]); }); - test('it should get the contrast ratio rating for only ui control color contrast requirements', () => { + test("it should get the contrast ratio rating for only ui control color contrast requirements", () => { const filteredUIControlContrastTokens = getTokensWithUIControlContrastRequirements(RawJSON.props); expect( - getContrastRatingForTokenPairing(filteredUIControlContrastTokens, tokens, 'uicontrol_contrast_pairing') + getContrastRatingForTokenPairing(filteredUIControlContrastTokens, tokens, "uicontrol_contrast_pairing"), ).toEqual([ { aa: false, aaLarge: false, aaa: false, aaaLarge: false, - background: 'color-text-link-light', - backgroundValue: '#99cdff', + background: "color-text-link-light", + backgroundValue: "#99cdff", contrast: 2.3775737969258506, - foreground: 'color-text-brand-highlight', - foregroundValue: '#F22F46', + foreground: "color-text-brand-highlight", + foregroundValue: "#F22F46", }, ]); }); diff --git a/packages/paste-color-contrast-utils/__tests__/themeContrast.spec.ts b/packages/paste-color-contrast-utils/__tests__/themeContrast.spec.ts index 2e9bfbb078..b60e9a82d9 100644 --- a/packages/paste-color-contrast-utils/__tests__/themeContrast.spec.ts +++ b/packages/paste-color-contrast-utils/__tests__/themeContrast.spec.ts @@ -2,72 +2,72 @@ import { backgroundColors, borderColors, borderWidths, - radii, + boxShadows, dataVisualization, - fonts, fontSizes, fontWeights, + fonts, lineHeights, - boxShadows, + radii, sizings, spacings, textColors, zIndices, -} from '@twilio-paste/design-tokens'; +} from "@twilio-paste/design-tokens"; import { backgroundColors as darkBackgroundColors, borderColors as darkBorderColors, borderWidths as darkBorderWidths, - radii as darkRadii, + boxShadows as darkBoxShadows, dataVisualization as darkDataVisualization, - fonts as darkFonts, fontSizes as darkFontSizes, fontWeights as darkFontWeights, + fonts as darkFonts, lineHeights as darkLineHeights, - boxShadows as darkBoxShadows, + radii as darkRadii, sizings as darkSizings, spacings as darkSpacings, textColors as darkTextColors, zIndices as darkZIndices, -} from '@twilio-paste/design-tokens/dist/themes/dark/tokens.common'; -import { - backgroundColors as twilioBackgroundColors, - borderColors as twilioBorderColors, - borderWidths as twilioBorderWidths, - radii as twilioRadii, - dataVisualization as twilioDataVisualization, - fonts as twilioFonts, - fontSizes as twilioFontSizes, - fontWeights as twilioFontWeights, - lineHeights as twilioLineHeights, - boxShadows as twilioBoxShadows, - sizings as twilioSizings, - spacings as twilioSpacings, - textColors as twilioTextColors, - zIndices as twilioZIndices, -} from '@twilio-paste/design-tokens/dist/themes/twilio/tokens.common'; +} from "@twilio-paste/design-tokens/dist/themes/dark/tokens.common"; import { backgroundColors as twilioDarkBackgroundColors, borderColors as twilioDarkBorderColors, borderWidths as twilioDarkBorderWidths, - radii as twilioDarkRadii, + boxShadows as twilioDarkBoxShadows, dataVisualization as twilioDarkDataVisualization, - fonts as twilioDarkFonts, fontSizes as twilioDarkFontSizes, fontWeights as twilioDarkFontWeights, + fonts as twilioDarkFonts, lineHeights as twilioDarkLineHeights, - boxShadows as twilioDarkBoxShadows, + radii as twilioDarkRadii, sizings as twilioDarkSizings, spacings as twilioDarkSpacings, textColors as twilioDarkTextColors, zIndices as twilioDarkZIndices, -} from '@twilio-paste/design-tokens/dist/themes/twilio-dark/tokens.common'; +} from "@twilio-paste/design-tokens/dist/themes/twilio-dark/tokens.common"; +import { + backgroundColors as twilioBackgroundColors, + borderColors as twilioBorderColors, + borderWidths as twilioBorderWidths, + boxShadows as twilioBoxShadows, + dataVisualization as twilioDataVisualization, + fontSizes as twilioFontSizes, + fontWeights as twilioFontWeights, + fonts as twilioFonts, + lineHeights as twilioLineHeights, + radii as twilioRadii, + sizings as twilioSizings, + spacings as twilioSpacings, + textColors as twilioTextColors, + zIndices as twilioZIndices, +} from "@twilio-paste/design-tokens/dist/themes/twilio/tokens.common"; import { + getContrastRatingsOfTokensWithDataVisualizationContrastRequirements, getContrastRatingsOfTokensWithTextContrastRequirements, getContrastRatingsOfTokensWithUIControlContrastRequirements, - getContrastRatingsOfTokensWithDataVisualizationContrastRequirements, -} from '../src/utils'; +} from "../src/utils"; const defaultThemeTextColorContrastRatings = getContrastRatingsOfTokensWithTextContrastRequirements({ backgroundColors, @@ -267,73 +267,73 @@ const twilioDarkThemeDataVisualizationColorContrastRatings = zIndices: twilioDarkZIndices, }); -describe('Default Theme', () => { - describe('Text color contrast ratio for token pairs', () => { - test.each(defaultThemeTextColorContrastRatings)('ratio check for %p', (rating) => { +describe("Default Theme", () => { + describe("Text color contrast ratio for token pairs", () => { + test.each(defaultThemeTextColorContrastRatings)("ratio check for %p", (rating) => { expect(rating.contrast).toBeGreaterThanOrEqual(4.5); }); }); - describe('UI Control color contrast ratio for token pairs', () => { - test.each(defaultThemeUiControlColorContrastRatings)('ratio check for %p', (rating) => { + describe("UI Control color contrast ratio for token pairs", () => { + test.each(defaultThemeUiControlColorContrastRatings)("ratio check for %p", (rating) => { expect(rating.contrast).toBeGreaterThanOrEqual(3); }); }); - describe('Data visualization color contrast ratio for token pairs', () => { - test.each(defaultThemeDataVisualizationColorContrastRatings)('ratio check for %p', (rating) => { + describe("Data visualization color contrast ratio for token pairs", () => { + test.each(defaultThemeDataVisualizationColorContrastRatings)("ratio check for %p", (rating) => { expect(rating.contrast).toBeGreaterThanOrEqual(2.25); }); }); }); -describe('Dark Theme', () => { - describe('Text color contrast ratio for token pairs', () => { - test.each(darkThemeTextColorContrastRatings)('ratio check for %p', (rating) => { +describe("Dark Theme", () => { + describe("Text color contrast ratio for token pairs", () => { + test.each(darkThemeTextColorContrastRatings)("ratio check for %p", (rating) => { expect(rating.contrast).toBeGreaterThanOrEqual(4.5); }); }); - describe('UI Control color contrast ratio for token pairs', () => { - test.each(darkThemeUiControlColorContrastRatings)('ratio check for %p', (rating) => { + describe("UI Control color contrast ratio for token pairs", () => { + test.each(darkThemeUiControlColorContrastRatings)("ratio check for %p", (rating) => { expect(rating.contrast).toBeGreaterThanOrEqual(3); }); }); - describe('Data visualization color contrast ratio for token pairs', () => { - test.each(darkThemeDataVisualizationColorContrastRatings)('ratio check for %p', (rating) => { + describe("Data visualization color contrast ratio for token pairs", () => { + test.each(darkThemeDataVisualizationColorContrastRatings)("ratio check for %p", (rating) => { expect(rating.contrast).toBeGreaterThanOrEqual(2); }); }); }); -describe('Twilio Theme', () => { - describe('Text color contrast ratio for token pairs', () => { - test.each(twilioThemeTextColorContrastRatings)('ratio check for %p', (rating) => { +describe("Twilio Theme", () => { + describe("Text color contrast ratio for token pairs", () => { + test.each(twilioThemeTextColorContrastRatings)("ratio check for %p", (rating) => { expect(rating.contrast).toBeGreaterThanOrEqual(4.5); }); }); - describe('UI Control color contrast ratio for token pairs', () => { - test.each(twilioThemeUiControlColorContrastRatings)('ratio check for %p', (rating) => { + describe("UI Control color contrast ratio for token pairs", () => { + test.each(twilioThemeUiControlColorContrastRatings)("ratio check for %p", (rating) => { expect(rating.contrast).toBeGreaterThanOrEqual(3); }); }); - describe('Data visualization color contrast ratio for token pairs', () => { - test.each(twilioThemeDataVisualizationColorContrastRatings)('ratio check for %p', (rating) => { + describe("Data visualization color contrast ratio for token pairs", () => { + test.each(twilioThemeDataVisualizationColorContrastRatings)("ratio check for %p", (rating) => { expect(rating.contrast).toBeGreaterThanOrEqual(2); }); }); }); -describe('Twilio Dark Theme', () => { - describe('Text color contrast ratio for token pairs', () => { - test.each(twilioDarkThemeTextColorContrastRatings)('ratio check for %p', (rating) => { +describe("Twilio Dark Theme", () => { + describe("Text color contrast ratio for token pairs", () => { + test.each(twilioDarkThemeTextColorContrastRatings)("ratio check for %p", (rating) => { expect(rating.contrast).toBeGreaterThanOrEqual(4.5); }); }); - describe('UI Control color contrast ratio for token pairs', () => { - test.each(twilioDarkThemeUiControlColorContrastRatings)('ratio check for %p', (rating) => { + describe("UI Control color contrast ratio for token pairs", () => { + test.each(twilioDarkThemeUiControlColorContrastRatings)("ratio check for %p", (rating) => { expect(rating.contrast).toBeGreaterThanOrEqual(3); }); }); - describe('Data visualization color contrast ratio for token pairs', () => { - test.each(twilioDarkThemeDataVisualizationColorContrastRatings)('ratio check for %p', (rating) => { + describe("Data visualization color contrast ratio for token pairs", () => { + test.each(twilioDarkThemeDataVisualizationColorContrastRatings)("ratio check for %p", (rating) => { expect(rating.contrast).toBeGreaterThanOrEqual(2); }); }); diff --git a/packages/paste-color-contrast-utils/build.js b/packages/paste-color-contrast-utils/build.js index 709e55862a..9ed632b018 100644 --- a/packages/paste-color-contrast-utils/build.js +++ b/packages/paste-color-contrast-utils/build.js @@ -1,3 +1,3 @@ -const {build} = require('../../tools/build/esbuild'); +const { build } = require("../../tools/build/esbuild"); -build(require('./package.json')); +build(require("./package.json")); diff --git a/packages/paste-color-contrast-utils/src/index.ts b/packages/paste-color-contrast-utils/src/index.ts index 04bca77e0d..178cd64f81 100644 --- a/packages/paste-color-contrast-utils/src/index.ts +++ b/packages/paste-color-contrast-utils/src/index.ts @@ -1 +1 @@ -export * from './utils'; +export * from "./utils"; diff --git a/packages/paste-color-contrast-utils/src/utils.ts b/packages/paste-color-contrast-utils/src/utils.ts index 5c9c1e4aa4..6ab5361409 100644 --- a/packages/paste-color-contrast-utils/src/utils.ts +++ b/packages/paste-color-contrast-utils/src/utils.ts @@ -1,9 +1,9 @@ -import ColorCombos from 'color-combos'; -import type {ColorCombo} from 'color-combos'; -import type {GenericTokensShape, AllGenericTokens} from '@twilio-paste/design-tokens/types/GenericTokensShape'; -import type {DesignToken, DesignTokensJSON, TokenPairContrastRating} from '@twilio-paste/design-tokens/types'; -import DefaultRawTokenJSON from '@twilio-paste/design-tokens/dist/tokens.raw.json'; -import camelCase from 'lodash/camelCase'; +import DefaultRawTokenJSON from "@twilio-paste/design-tokens/dist/tokens.raw.json"; +import type { DesignToken, DesignTokensJSON, TokenPairContrastRating } from "@twilio-paste/design-tokens/types"; +import type { AllGenericTokens, GenericTokensShape } from "@twilio-paste/design-tokens/types/GenericTokensShape"; +import ColorCombos from "color-combos"; +import type { ColorCombo } from "color-combos"; +import camelCase from "lodash/camelCase"; /** * Filter out any ratings that are not at least aa for text color contrast requirements @@ -38,7 +38,7 @@ export const getNumberOfUIControlFailures = (ratings: TokenPairContrastRating[]) export const flattenCategorizedTokens = (tokens: Partial): AllGenericTokens => { let flatTheme = {}; Object.values(tokens).forEach((value) => { - flatTheme = {...flatTheme, ...value}; + flatTheme = { ...flatTheme, ...value }; }); return flatTheme; }; @@ -70,7 +70,7 @@ export const convertRawTokenJSONToArray = (rawTokens: DesignTokensJSON): DesignT export const getTokensWithTextContrastRequirements = (rawTokens: DesignTokensJSON): DesignToken[] => convertRawTokenJSONToArray(rawTokens) // filter by type and contrast pairing type - .filter((token) => token.type === 'color' && token.text_contrast_pairing != null); + .filter((token) => token.type === "color" && token.text_contrast_pairing != null); /** * get all color tokens that have ui control contrast requirements @@ -81,7 +81,7 @@ export const getTokensWithTextContrastRequirements = (rawTokens: DesignTokensJSO export const getTokensWithUIControlContrastRequirements = (rawTokens: DesignTokensJSON): DesignToken[] => convertRawTokenJSONToArray(rawTokens) // filter by type and contrast pairing type - .filter((token) => token.type === 'color' && token.uicontrol_contrast_pairing != null); + .filter((token) => token.type === "color" && token.uicontrol_contrast_pairing != null); /** * get all color tokens that have ui control contrast requirements @@ -92,7 +92,7 @@ export const getTokensWithUIControlContrastRequirements = (rawTokens: DesignToke export const getTokensWithDataVisualizationContrastRequirements = (rawTokens: DesignTokensJSON): DesignToken[] => convertRawTokenJSONToArray(rawTokens) // filter by type and contrast pairing type - .filter((token) => token.type === 'color' && token.data_visualization_contrast_pairing != null); + .filter((token) => token.type === "color" && token.data_visualization_contrast_pairing != null); /** * build an array of contrast results for each token pairing @@ -105,7 +105,7 @@ export const getTokensWithDataVisualizationContrastRequirements = (rawTokens: De export const getContrastRatingForTokenPairing = ( filteredTokens: DesignToken[], tokens: AllGenericTokens, - pairingKey: 'text_contrast_pairing' | 'uicontrol_contrast_pairing' | 'data_visualization_contrast_pairing' + pairingKey: "text_contrast_pairing" | "uicontrol_contrast_pairing" | "data_visualization_contrast_pairing", ): TokenPairContrastRating[] => { return filteredTokens.reduce((tokenRatings: TokenPairContrastRating[], token: DesignToken) => { /** array of tokens that are paired with this token for the type of contrast checking we're doing */ @@ -124,7 +124,7 @@ export const getContrastRatingForTokenPairing = ( /** value of the token we're comparing to based on finding it by it's name in the full token list */ const tokenToCompareValue = tokens[tokenToCompareName]; /** accessibility rating as per ColorCombos */ - let comboRating = {aa: false, aaLarge: false, aaa: false, aaaLarge: false}; + let comboRating = { aa: false, aaLarge: false, aaa: false, aaaLarge: false }; /** color contrast ratio of the two colors */ let comboContrast = 0; /** color combinations of the two colors */ @@ -174,13 +174,13 @@ export const getContrastRatingForTokenPairing = ( * @return {*} {TokenPairContrastRating[]} */ export const getContrastRatingsOfTokensWithTextContrastRequirements = ( - tokens: Partial + tokens: Partial, ): TokenPairContrastRating[] => { // always use the Default raw JSON to get the pairings as other themes won't inherit them automatically const defaultThemeRawJSON = DefaultRawTokenJSON.props; const tokenWithTextContrastRequirements = getTokensWithTextContrastRequirements(defaultThemeRawJSON); const flattenedTokens = flattenCategorizedTokens(tokens); - return getContrastRatingForTokenPairing(tokenWithTextContrastRequirements, flattenedTokens, 'text_contrast_pairing'); + return getContrastRatingForTokenPairing(tokenWithTextContrastRequirements, flattenedTokens, "text_contrast_pairing"); }; /** @@ -194,7 +194,7 @@ export const getContrastRatingsOfTokensWithTextContrastRequirements = ( * @return {*} {TokenPairContrastRating[]} */ export const getContrastRatingsOfTokensWithUIControlContrastRequirements = ( - tokens: Partial + tokens: Partial, ): TokenPairContrastRating[] => { // always use the Default raw JSON to get the pairings as other themes won't inherit them automatically const defaultThemeRawJSON = DefaultRawTokenJSON.props; @@ -203,7 +203,7 @@ export const getContrastRatingsOfTokensWithUIControlContrastRequirements = ( return getContrastRatingForTokenPairing( tokenWithUIControlContrastRequirements, flattenedTokens, - 'uicontrol_contrast_pairing' + "uicontrol_contrast_pairing", ); }; @@ -218,7 +218,7 @@ export const getContrastRatingsOfTokensWithUIControlContrastRequirements = ( * @return {*} {TokenPairContrastRating[]} */ export const getContrastRatingsOfTokensWithDataVisualizationContrastRequirements = ( - tokens: Partial + tokens: Partial, ): TokenPairContrastRating[] => { // always use the Default raw JSON to get the pairings as other themes won't inherit them automatically const defaultThemeRawJSON = DefaultRawTokenJSON.props; @@ -228,6 +228,6 @@ export const getContrastRatingsOfTokensWithDataVisualizationContrastRequirements return getContrastRatingForTokenPairing( tokenWithDataVisualizationContrastRequirements, flattenedTokens, - 'data_visualization_contrast_pairing' + "data_visualization_contrast_pairing", ); }; diff --git a/packages/paste-core/components/account-switcher/__tests__/AccountSwitcher.spec.tsx b/packages/paste-core/components/account-switcher/__tests__/AccountSwitcher.spec.tsx index 82080758c0..1a713117f3 100644 --- a/packages/paste-core/components/account-switcher/__tests__/AccountSwitcher.spec.tsx +++ b/packages/paste-core/components/account-switcher/__tests__/AccountSwitcher.spec.tsx @@ -1,72 +1,72 @@ -import * as React from 'react'; -import {render, screen, act} from '@testing-library/react'; +import { act, render, screen } from "@testing-library/react"; +import * as React from "react"; -import {AccountSwitcherMenu} from '../stories/AccountSwitcher.stories'; -import {CustomElementName, DefaultElementName} from '../stories/AccountSwitcher.customization.stories'; +import { CustomElementName, DefaultElementName } from "../stories/AccountSwitcher.customization.stories"; +import { AccountSwitcherMenu } from "../stories/AccountSwitcher.stories"; -describe('AccountSwitcher', () => { - describe('element naming', () => { - it('should set all default element names', async () => { +describe("AccountSwitcher", () => { + describe("element naming", () => { + it("should set all default element names", async () => { await act(async () => { render(); }); - expect(screen.getByRole('button', {name: 'Switch accounts'}).dataset.pasteElement).toEqual( - 'ACCOUNT_SWITCHER_BADGE_BUTTON' + expect(screen.getByRole("button", { name: "Switch accounts" }).dataset.pasteElement).toEqual( + "ACCOUNT_SWITCHER_BADGE_BUTTON", ); - expect(screen.getByRole('menu').dataset.pasteElement).toEqual('ACCOUNT_SWITCHER'); - expect(screen.getByRole('menuitem', {name: 'Account settings'}).dataset.pasteElement).toEqual( - 'ACCOUNT_SWITCHER_ITEM' + expect(screen.getByRole("menu").dataset.pasteElement).toEqual("ACCOUNT_SWITCHER"); + expect(screen.getByRole("menuitem", { name: "Account settings" }).dataset.pasteElement).toEqual( + "ACCOUNT_SWITCHER_ITEM", ); - expect(screen.getByRole('menuitemradio', {name: 'Owl Telehealth'}).dataset.pasteElement).toEqual( - 'ACCOUNT_SWITCHER_ITEM_RADIO' + expect(screen.getByRole("menuitemradio", { name: "Owl Telehealth" }).dataset.pasteElement).toEqual( + "ACCOUNT_SWITCHER_ITEM_RADIO", ); - expect(screen.getAllByRole('separator')[0].dataset.pasteElement).toEqual('ACCOUNT_SWITCHER_SEPARATOR'); + expect(screen.getAllByRole("separator")[0].dataset.pasteElement).toEqual("ACCOUNT_SWITCHER_SEPARATOR"); }); }); - describe('element name overrides', () => { - it('should set all custom element names', async () => { + describe("element name overrides", () => { + it("should set all custom element names", async () => { await act(async () => { render(); }); - expect(screen.getByRole('button', {name: 'Switch accounts'}).dataset.pasteElement).toEqual('FOO_BUTTON'); - expect(screen.getByRole('menu').dataset.pasteElement).toEqual('BAR'); - expect(screen.getByRole('menuitem', {name: 'Account settings'}).dataset.pasteElement).toEqual('BAZ'); - expect(screen.getByRole('menuitemradio', {name: 'Owl Telehealth'}).dataset.pasteElement).toEqual('BAZ_RADIO'); - expect(screen.getAllByRole('separator')[0].dataset.pasteElement).toEqual('LINE'); + expect(screen.getByRole("button", { name: "Switch accounts" }).dataset.pasteElement).toEqual("FOO_BUTTON"); + expect(screen.getByRole("menu").dataset.pasteElement).toEqual("BAR"); + expect(screen.getByRole("menuitem", { name: "Account settings" }).dataset.pasteElement).toEqual("BAZ"); + expect(screen.getByRole("menuitemradio", { name: "Owl Telehealth" }).dataset.pasteElement).toEqual("BAZ_RADIO"); + expect(screen.getAllByRole("separator")[0].dataset.pasteElement).toEqual("LINE"); }); }); - describe('customization of styles', () => { - it('should set all custom styles', async () => { + describe("customization of styles", () => { + it("should set all custom styles", async () => { await act(async () => { render(); }); - expect(screen.getByRole('button', {name: 'Switch accounts'})).toHaveStyleRule( - 'background-color', - 'rgb(214, 31, 31)' + expect(screen.getByRole("button", { name: "Switch accounts" })).toHaveStyleRule( + "background-color", + "rgb(214, 31, 31)", ); - expect(screen.getByRole('menu')).toHaveStyleRule('border-color', 'rgb(117, 12, 12)'); - expect(screen.getByRole('menuitem', {name: 'Account settings'})).toHaveStyleRule( - 'background-color', - 'rgb(0, 20, 137)' + expect(screen.getByRole("menu")).toHaveStyleRule("border-color", "rgb(117, 12, 12)"); + expect(screen.getByRole("menuitem", { name: "Account settings" })).toHaveStyleRule( + "background-color", + "rgb(0, 20, 137)", ); - expect(screen.getByRole('menuitemradio', {name: 'Owl Telehealth'})).toHaveStyleRule('font-style', 'italic'); + expect(screen.getByRole("menuitemradio", { name: "Owl Telehealth" })).toHaveStyleRule("font-style", "italic"); }); }); - describe('customization of styles with custom name', () => { - it('should set all custom styles', async () => { + describe("customization of styles with custom name", () => { + it("should set all custom styles", async () => { await act(async () => { render(); }); - expect(screen.getByRole('button', {name: 'Switch accounts'})).toHaveStyleRule( - 'background-color', - 'rgb(214, 31, 31)' + expect(screen.getByRole("button", { name: "Switch accounts" })).toHaveStyleRule( + "background-color", + "rgb(214, 31, 31)", ); - expect(screen.getByRole('menu')).toHaveStyleRule('border-color', 'rgb(117, 12, 12)'); - expect(screen.getByRole('menuitem', {name: 'Account settings'})).toHaveStyleRule( - 'background-color', - 'rgb(0, 20, 137)' + expect(screen.getByRole("menu")).toHaveStyleRule("border-color", "rgb(117, 12, 12)"); + expect(screen.getByRole("menuitem", { name: "Account settings" })).toHaveStyleRule( + "background-color", + "rgb(0, 20, 137)", ); - expect(screen.getByRole('menuitemradio', {name: 'Owl Telehealth'})).toHaveStyleRule('font-style', 'italic'); + expect(screen.getByRole("menuitemradio", { name: "Owl Telehealth" })).toHaveStyleRule("font-style", "italic"); }); }); }); diff --git a/packages/paste-core/components/account-switcher/build.js b/packages/paste-core/components/account-switcher/build.js index a4edeab49b..27dd98f98e 100644 --- a/packages/paste-core/components/account-switcher/build.js +++ b/packages/paste-core/components/account-switcher/build.js @@ -1,3 +1,3 @@ -const {build} = require('../../../../tools/build/esbuild'); +const { build } = require("../../../../tools/build/esbuild"); -build(require('./package.json')); +build(require("./package.json")); diff --git a/packages/paste-core/components/account-switcher/src/AccountSwitcher.tsx b/packages/paste-core/components/account-switcher/src/AccountSwitcher.tsx index 528f55f126..3fc494113f 100644 --- a/packages/paste-core/components/account-switcher/src/AccountSwitcher.tsx +++ b/packages/paste-core/components/account-switcher/src/AccountSwitcher.tsx @@ -1,20 +1,20 @@ -import * as React from 'react'; -import {Menu} from '@twilio-paste/menu'; -import type {MenuProps} from '@twilio-paste/menu'; +import { Menu } from "@twilio-paste/menu"; +import type { MenuProps } from "@twilio-paste/menu"; +import * as React from "react"; export interface AccountSwitcherProps extends MenuProps { children: NonNullable; } const AccountSwitcher = React.forwardRef( - ({children, element = 'ACCOUNT_SWITCHER', ...props}, ref) => { + ({ children, element = "ACCOUNT_SWITCHER", ...props }, ref) => { return ( {children} ); - } + }, ); -AccountSwitcher.displayName = 'AccountSwitcher'; -export {AccountSwitcher}; +AccountSwitcher.displayName = "AccountSwitcher"; +export { AccountSwitcher }; diff --git a/packages/paste-core/components/account-switcher/src/AccountSwitcherBadge.tsx b/packages/paste-core/components/account-switcher/src/AccountSwitcherBadge.tsx index 74146894cb..0e9b4260cb 100644 --- a/packages/paste-core/components/account-switcher/src/AccountSwitcherBadge.tsx +++ b/packages/paste-core/components/account-switcher/src/AccountSwitcherBadge.tsx @@ -1,20 +1,20 @@ -import * as React from 'react'; -import {MenuBadge} from '@twilio-paste/menu'; -import type {MenuBadgeProps} from '@twilio-paste/menu'; +import { MenuBadge } from "@twilio-paste/menu"; +import type { MenuBadgeProps } from "@twilio-paste/menu"; +import * as React from "react"; -export interface AccountSwitcherBadgeProps extends Omit { +export interface AccountSwitcherBadgeProps extends Omit { children: NonNullable; } const AccountSwitcherBadge = React.forwardRef( - ({children, element = 'ACCOUNT_SWITCHER_BADGE', ...props}, ref) => { + ({ children, element = "ACCOUNT_SWITCHER_BADGE", ...props }, ref) => { return ( {children} ); - } + }, ); -AccountSwitcherBadge.displayName = 'AccountSwitcherBadge'; -export {AccountSwitcherBadge}; +AccountSwitcherBadge.displayName = "AccountSwitcherBadge"; +export { AccountSwitcherBadge }; diff --git a/packages/paste-core/components/account-switcher/src/AccountSwitcherGroup.tsx b/packages/paste-core/components/account-switcher/src/AccountSwitcherGroup.tsx index 0968e35f84..82b3fa9709 100644 --- a/packages/paste-core/components/account-switcher/src/AccountSwitcherGroup.tsx +++ b/packages/paste-core/components/account-switcher/src/AccountSwitcherGroup.tsx @@ -1,18 +1,18 @@ -import * as React from 'react'; -import {MenuGroup} from '@twilio-paste/menu'; -import type {MenuGroupProps} from '@twilio-paste/menu'; +import { MenuGroup } from "@twilio-paste/menu"; +import type { MenuGroupProps } from "@twilio-paste/menu"; +import * as React from "react"; export type AccountSwitcherGroupProps = MenuGroupProps; const AccountSwitcherGroup = React.forwardRef( - ({children, element = 'ACCOUNT_SWITCHER_GROUP', label, ...props}, ref) => { + ({ children, element = "ACCOUNT_SWITCHER_GROUP", label, ...props }, ref) => { return ( {children} ); - } + }, ); -AccountSwitcherGroup.displayName = 'AccountSwitcherGroup'; -export {AccountSwitcherGroup}; +AccountSwitcherGroup.displayName = "AccountSwitcherGroup"; +export { AccountSwitcherGroup }; diff --git a/packages/paste-core/components/account-switcher/src/AccountSwitcherItem.tsx b/packages/paste-core/components/account-switcher/src/AccountSwitcherItem.tsx index 74ef0e7c00..85646cf2f7 100644 --- a/packages/paste-core/components/account-switcher/src/AccountSwitcherItem.tsx +++ b/packages/paste-core/components/account-switcher/src/AccountSwitcherItem.tsx @@ -1,20 +1,20 @@ -import * as React from 'react'; -import {MenuItem} from '@twilio-paste/menu'; -import type {MenuItemProps} from '@twilio-paste/menu'; +import { MenuItem } from "@twilio-paste/menu"; +import type { MenuItemProps } from "@twilio-paste/menu"; +import * as React from "react"; export interface AccountSwitcherItemProps extends MenuItemProps { children: NonNullable; } const AccountSwitcherItem = React.forwardRef( - ({children, element = 'ACCOUNT_SWITCHER_ITEM', ...props}, ref) => { + ({ children, element = "ACCOUNT_SWITCHER_ITEM", ...props }, ref) => { return ( {children} ); - } + }, ); -AccountSwitcherItem.displayName = 'AccountSwitcherItem'; -export {AccountSwitcherItem}; +AccountSwitcherItem.displayName = "AccountSwitcherItem"; +export { AccountSwitcherItem }; diff --git a/packages/paste-core/components/account-switcher/src/AccountSwitcherItemRadio.tsx b/packages/paste-core/components/account-switcher/src/AccountSwitcherItemRadio.tsx index a749098725..7285134c40 100644 --- a/packages/paste-core/components/account-switcher/src/AccountSwitcherItemRadio.tsx +++ b/packages/paste-core/components/account-switcher/src/AccountSwitcherItemRadio.tsx @@ -1,20 +1,20 @@ -import * as React from 'react'; -import {MenuItemRadio} from '@twilio-paste/menu'; -import type {MenuItemRadioProps} from '@twilio-paste/menu'; +import { MenuItemRadio } from "@twilio-paste/menu"; +import type { MenuItemRadioProps } from "@twilio-paste/menu"; +import * as React from "react"; export interface AccountSwitcherItemRadioProps extends MenuItemRadioProps { children: NonNullable; } const AccountSwitcherItemRadio = React.forwardRef( - ({children, element = 'ACCOUNT_SWITCHER_ITEM_RADIO', ...props}, ref) => { + ({ children, element = "ACCOUNT_SWITCHER_ITEM_RADIO", ...props }, ref) => { return ( {children} ); - } + }, ); -AccountSwitcherItemRadio.displayName = 'AccountSwitcherItemRadio'; -export {AccountSwitcherItemRadio}; +AccountSwitcherItemRadio.displayName = "AccountSwitcherItemRadio"; +export { AccountSwitcherItemRadio }; diff --git a/packages/paste-core/components/account-switcher/src/AccountSwitcherSeparator.tsx b/packages/paste-core/components/account-switcher/src/AccountSwitcherSeparator.tsx index 8259fa9cc1..f8fcdac4b5 100644 --- a/packages/paste-core/components/account-switcher/src/AccountSwitcherSeparator.tsx +++ b/packages/paste-core/components/account-switcher/src/AccountSwitcherSeparator.tsx @@ -1,19 +1,19 @@ -import * as React from 'react'; -import {MenuSeparator} from '@twilio-paste/menu'; -import type {MenuSeparatorProps} from '@twilio-paste/menu'; +import { MenuSeparator } from "@twilio-paste/menu"; +import type { MenuSeparatorProps } from "@twilio-paste/menu"; +import * as React from "react"; export type AccountSwitcherSeparatorProps = MenuSeparatorProps; const AccountSwitcherSeparator = React.forwardRef( - ({children, element = 'ACCOUNT_SWITCHER_SEPARATOR', ...props}, ref) => { + ({ children, element = "ACCOUNT_SWITCHER_SEPARATOR", ...props }, ref) => { return ( {children} ); - } + }, ); -AccountSwitcherSeparator.displayName = 'AccountSwitcherSeparator'; +AccountSwitcherSeparator.displayName = "AccountSwitcherSeparator"; -export {AccountSwitcherSeparator}; +export { AccountSwitcherSeparator }; diff --git a/packages/paste-core/components/account-switcher/src/index.tsx b/packages/paste-core/components/account-switcher/src/index.tsx index 8ce48464b9..77094eda46 100644 --- a/packages/paste-core/components/account-switcher/src/index.tsx +++ b/packages/paste-core/components/account-switcher/src/index.tsx @@ -1,7 +1,7 @@ -export * from './AccountSwitcher'; -export * from './AccountSwitcherGroup'; -export * from './AccountSwitcherSeparator'; -export * from './AccountSwitcherItem'; -export * from './AccountSwitcherItemRadio'; -export * from './AccountSwitcherBadge'; -export * from './useAccountSwitcher'; +export * from "./AccountSwitcher"; +export * from "./AccountSwitcherGroup"; +export * from "./AccountSwitcherSeparator"; +export * from "./AccountSwitcherItem"; +export * from "./AccountSwitcherItemRadio"; +export * from "./AccountSwitcherBadge"; +export * from "./useAccountSwitcher"; diff --git a/packages/paste-core/components/account-switcher/src/useAccountSwitcher.ts b/packages/paste-core/components/account-switcher/src/useAccountSwitcher.ts index dcdbd7c1bf..c9150eb6cc 100644 --- a/packages/paste-core/components/account-switcher/src/useAccountSwitcher.ts +++ b/packages/paste-core/components/account-switcher/src/useAccountSwitcher.ts @@ -1 +1 @@ -export {useMenuState as useAccountSwitcherState} from '@twilio-paste/menu'; +export { useMenuState as useAccountSwitcherState } from "@twilio-paste/menu"; diff --git a/packages/paste-core/components/account-switcher/stories/AccountSwitcher.customization.stories.tsx b/packages/paste-core/components/account-switcher/stories/AccountSwitcher.customization.stories.tsx index f5c1975d04..aaf4279491 100644 --- a/packages/paste-core/components/account-switcher/stories/AccountSwitcher.customization.stories.tsx +++ b/packages/paste-core/components/account-switcher/stories/AccountSwitcher.customization.stories.tsx @@ -1,6 +1,6 @@ -import * as React from 'react'; -import type {StoryFn} from '@storybook/react'; -import {CustomizationProvider} from '@twilio-paste/customization'; +import type { StoryFn } from "@storybook/react"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import * as React from "react"; import { AccountSwitcher, @@ -10,26 +10,26 @@ import { AccountSwitcherItemRadio, AccountSwitcherSeparator, useAccountSwitcherState, -} from '../src'; +} from "../src"; // eslint-disable-next-line import/no-default-export export default { - title: 'Components/AccountSwitcher/Customization', + title: "Components/AccountSwitcher/Customization", }; export const DefaultElementName: StoryFn = () => { - const accountSwitcher = useAccountSwitcherState({visible: true}); - const [selectedAccount, setSelectedAccount] = React.useState('Owl Telehealth'); + const accountSwitcher = useAccountSwitcherState({ visible: true }); + const [selectedAccount, setSelectedAccount] = React.useState("Owl Telehealth"); return ( @@ -40,8 +40,8 @@ export const DefaultElementName: StoryFn = () => { setSelectedAccount('Owl Telehealth')} + checked={selectedAccount === "Owl Telehealth"} + onChange={() => setSelectedAccount("Owl Telehealth")} {...accountSwitcher} > Owl Telehealth @@ -49,8 +49,8 @@ export const DefaultElementName: StoryFn = () => { setSelectedAccount('Owl Health Demo')} + checked={selectedAccount === "Owl Health Demo"} + onChange={() => setSelectedAccount("Owl Health Demo")} {...accountSwitcher} > Owl Health Demo @@ -58,8 +58,8 @@ export const DefaultElementName: StoryFn = () => { setSelectedAccount('Owl Subway')} + checked={selectedAccount === "Owl Subway"} + onChange={() => setSelectedAccount("Owl Subway")} {...accountSwitcher} > Owl Subway @@ -86,18 +86,18 @@ export const DefaultElementName: StoryFn = () => { }; export const CustomElementName: StoryFn = () => { - const accountSwitcher = useAccountSwitcherState({visible: true}); - const [selectedAccount, setSelectedAccount] = React.useState('Owl Telehealth'); + const accountSwitcher = useAccountSwitcherState({ visible: true }); + const [selectedAccount, setSelectedAccount] = React.useState("Owl Telehealth"); return ( @@ -109,8 +109,8 @@ export const CustomElementName: StoryFn = () => { element="BAZ_RADIO" name="recent_accounts" value="Owl Telehealth" - checked={selectedAccount === 'Owl Telehealth'} - onChange={() => setSelectedAccount('Owl Telehealth')} + checked={selectedAccount === "Owl Telehealth"} + onChange={() => setSelectedAccount("Owl Telehealth")} {...accountSwitcher} > Owl Telehealth @@ -119,8 +119,8 @@ export const CustomElementName: StoryFn = () => { element="BAZ_RADIO" name="recent_accounts" value="Owl Health Demo" - checked={selectedAccount === 'Owl Health Demo'} - onChange={() => setSelectedAccount('Owl Health Demo')} + checked={selectedAccount === "Owl Health Demo"} + onChange={() => setSelectedAccount("Owl Health Demo")} {...accountSwitcher} > Owl Health Demo @@ -129,8 +129,8 @@ export const CustomElementName: StoryFn = () => { element="BAZ_RADIO" name="recent_accounts" value="Owl Subway" - checked={selectedAccount === 'Owl Subway'} - onChange={() => setSelectedAccount('Owl Subway')} + checked={selectedAccount === "Owl Subway"} + onChange={() => setSelectedAccount("Owl Subway")} {...accountSwitcher} > Owl Subway diff --git a/packages/paste-core/components/account-switcher/stories/AccountSwitcher.stories.tsx b/packages/paste-core/components/account-switcher/stories/AccountSwitcher.stories.tsx index 104d033bb6..4c220d97a7 100644 --- a/packages/paste-core/components/account-switcher/stories/AccountSwitcher.stories.tsx +++ b/packages/paste-core/components/account-switcher/stories/AccountSwitcher.stories.tsx @@ -1,5 +1,5 @@ -import * as React from 'react'; -import type {StoryFn} from '@storybook/react'; +import type { StoryFn } from "@storybook/react"; +import * as React from "react"; import { AccountSwitcher, @@ -9,16 +9,16 @@ import { AccountSwitcherItemRadio, AccountSwitcherSeparator, useAccountSwitcherState, -} from '../src'; +} from "../src"; // eslint-disable-next-line import/no-default-export export default { - title: 'Components/AccountSwitcher', + title: "Components/AccountSwitcher", }; export const AccountSwitcherMenu: StoryFn = () => { - const accountSwitcher = useAccountSwitcherState({visible: true}); - const [selectedAccount, setSelectedAccount] = React.useState('Owl Telehealth'); + const accountSwitcher = useAccountSwitcherState({ visible: true }); + const [selectedAccount, setSelectedAccount] = React.useState("Owl Telehealth"); return ( <> @@ -29,8 +29,8 @@ export const AccountSwitcherMenu: StoryFn = () => { setSelectedAccount('Owl Telehealth')} + checked={selectedAccount === "Owl Telehealth"} + onChange={() => setSelectedAccount("Owl Telehealth")} {...accountSwitcher} > Owl Telehealth @@ -38,8 +38,8 @@ export const AccountSwitcherMenu: StoryFn = () => { setSelectedAccount('Owl Health Demo')} + checked={selectedAccount === "Owl Health Demo"} + onChange={() => setSelectedAccount("Owl Health Demo")} {...accountSwitcher} > Owl Health Demo @@ -47,8 +47,8 @@ export const AccountSwitcherMenu: StoryFn = () => { setSelectedAccount('Owl Subway')} + checked={selectedAccount === "Owl Subway"} + onChange={() => setSelectedAccount("Owl Subway")} {...accountSwitcher} > Owl Subway diff --git a/packages/paste-core/components/alert-dialog/__tests__/customization.spec.tsx b/packages/paste-core/components/alert-dialog/__tests__/customization.spec.tsx index ffa8a10741..ea368ae21a 100644 --- a/packages/paste-core/components/alert-dialog/__tests__/customization.spec.tsx +++ b/packages/paste-core/components/alert-dialog/__tests__/customization.spec.tsx @@ -1,20 +1,20 @@ -import * as React from 'react'; -import {render, screen} from '@testing-library/react'; +import { render, screen } from "@testing-library/react"; +import * as React from "react"; -import {CustomizedAlertDialog, CustomizedDestructiveAlertDialog} from '../stories/index.stories'; +import { CustomizedAlertDialog, CustomizedDestructiveAlertDialog } from "../stories/index.stories"; -jest.mock('@twilio-paste/modal-dialog-primitive', () => { - const actual = jest.requireActual('@twilio-paste/modal-dialog-primitive'); - const {forwardRef: mockForwardRef} = jest.requireActual('react'); +jest.mock("@twilio-paste/modal-dialog-primitive", () => { + const actual = jest.requireActual("@twilio-paste/modal-dialog-primitive"); + const { forwardRef: mockForwardRef } = jest.requireActual("react"); const MockModalDialogPrimitiveOverlay = mockForwardRef( ( { children, - 'data-paste-element': dataPasteElement, + "data-paste-element": dataPasteElement, style, className, - }: {children: any; 'data-paste-element': string; style: any; className: string}, - ref: any + }: { children: any; "data-paste-element": string; style: any; className: string }, + ref: any, ) => (
{ > {children}
- ) + ), ); return { ...actual, @@ -33,62 +33,62 @@ jest.mock('@twilio-paste/modal-dialog-primitive', () => { }; }); -describe('Alert Dialog `element` prop', () => { - it('should set the default element prop on Alert Dialog', () => { - const {container} = render(, { - wrapper: ({children}) =>
{children}
, +describe("Alert Dialog `element` prop", () => { + it("should set the default element prop on Alert Dialog", () => { + const { container } = render(, { + wrapper: ({ children }) =>
{children}
, }); - expect(screen.getByTestId('alert_dialog').getAttribute('data-paste-element')).toEqual('ALERT_DIALOG'); + expect(screen.getByTestId("alert_dialog").getAttribute("data-paste-element")).toEqual("ALERT_DIALOG"); expect(container.querySelector('[data-paste-element="ALERT_DIALOG_HEADER_WRAPPER"]')).toBeInTheDocument(); - expect(screen.getByText('Alert Dialog').getAttribute('data-paste-element')).toEqual('ALERT_DIALOG_HEADER'); + expect(screen.getByText("Alert Dialog").getAttribute("data-paste-element")).toEqual("ALERT_DIALOG_HEADER"); expect( screen - .getByText('Are you sure you want to submit this application? No information can be changed after submitting.') - .getAttribute('data-paste-element') - ).toEqual('ALERT_DIALOG_BODY'); + .getByText("Are you sure you want to submit this application? No information can be changed after submitting.") + .getAttribute("data-paste-element"), + ).toEqual("ALERT_DIALOG_BODY"); expect(container.querySelector('[data-paste-element="ALERT_DIALOG_FOOTER"]')).toBeInTheDocument(); }); - it('should set the custom element prop on Alert Dialog', () => { - const {container} = render(); - expect(screen.getByTestId('destructive_alert_dialog').getAttribute('data-paste-element')).toEqual('FOO'); + it("should set the custom element prop on Alert Dialog", () => { + const { container } = render(); + expect(screen.getByTestId("destructive_alert_dialog").getAttribute("data-paste-element")).toEqual("FOO"); expect(container.querySelector('[data-paste-element="FOO_HEADER_WRAPPER"]')).toBeInTheDocument(); - expect(screen.getByText('Alert Dialog').getAttribute('data-paste-element')).toEqual('FOO_HEADER'); + expect(screen.getByText("Alert Dialog").getAttribute("data-paste-element")).toEqual("FOO_HEADER"); expect( screen - .getByText('Are you sure you want to delete this data? This action cannot be undone.') - .getAttribute('data-paste-element') - ).toEqual('FOO_BODY'); + .getByText("Are you sure you want to delete this data? This action cannot be undone.") + .getAttribute("data-paste-element"), + ).toEqual("FOO_BODY"); expect(container.querySelector('[data-paste-element="FOO_FOOTER"]')).toBeInTheDocument(); }); }); -describe('Alert Dialog customization', () => { - it('should apply styles to Alert Dialog', () => { - const {container} = render(); - expect(screen.getByTestId('alert_dialog')).toHaveStyleRule('background-color', 'rgb(255, 251, 234)'); +describe("Alert Dialog customization", () => { + it("should apply styles to Alert Dialog", () => { + const { container } = render(); + expect(screen.getByTestId("alert_dialog")).toHaveStyleRule("background-color", "rgb(255, 251, 234)"); expect(container.querySelector('[data-paste-element="ALERT_DIALOG_HEADER_WRAPPER"]')).toHaveStyleRule( - 'border', - 'inherit' + "border", + "inherit", ); - expect(screen.getByText('Alert Dialog')).toHaveStyleRule('background-color', 'rgb(235, 244, 255)'); + expect(screen.getByText("Alert Dialog")).toHaveStyleRule("background-color", "rgb(235, 244, 255)"); expect( screen.getByText( - 'Are you sure you want to submit this application? No information can be changed after submitting.' - ) - ).toHaveStyleRule('background-color', 'rgb(237, 253, 243)'); + "Are you sure you want to submit this application? No information can be changed after submitting.", + ), + ).toHaveStyleRule("background-color", "rgb(237, 253, 243)"); expect(container.querySelector('[data-paste-element="ALERT_DIALOG_FOOTER"]')).toHaveStyleRule( - 'padding-top', - '1rem' + "padding-top", + "1rem", ); }); - it('should apply styles to Alert Dialog with custom element prop', () => { - const {container} = render(); - expect(screen.getByTestId('destructive_alert_dialog')).toHaveStyleRule('background-color', 'rgb(214, 31, 31)'); - expect(container.querySelector('[data-paste-element="FOO_HEADER_WRAPPER"]')).toHaveStyleRule('border', 'inherit'); - expect(screen.getByText('Alert Dialog')).toHaveStyleRule('background-color', 'rgb(235, 244, 255)'); + it("should apply styles to Alert Dialog with custom element prop", () => { + const { container } = render(); + expect(screen.getByTestId("destructive_alert_dialog")).toHaveStyleRule("background-color", "rgb(214, 31, 31)"); + expect(container.querySelector('[data-paste-element="FOO_HEADER_WRAPPER"]')).toHaveStyleRule("border", "inherit"); + expect(screen.getByText("Alert Dialog")).toHaveStyleRule("background-color", "rgb(235, 244, 255)"); expect( - screen.getByText('Are you sure you want to delete this data? This action cannot be undone.') - ).toHaveStyleRule('background-color', 'rgb(237, 253, 243)'); - expect(container.querySelector('[data-paste-element="FOO_FOOTER"]')).toHaveStyleRule('padding-top', '1rem'); + screen.getByText("Are you sure you want to delete this data? This action cannot be undone."), + ).toHaveStyleRule("background-color", "rgb(237, 253, 243)"); + expect(container.querySelector('[data-paste-element="FOO_FOOTER"]')).toHaveStyleRule("padding-top", "1rem"); }); }); diff --git a/packages/paste-core/components/alert-dialog/__tests__/index.spec.tsx b/packages/paste-core/components/alert-dialog/__tests__/index.spec.tsx index 4da7f1a06d..2c707229b7 100644 --- a/packages/paste-core/components/alert-dialog/__tests__/index.spec.tsx +++ b/packages/paste-core/components/alert-dialog/__tests__/index.spec.tsx @@ -1,70 +1,70 @@ -import * as React from 'react'; -import {render, screen} from '@testing-library/react'; -import type {RenderOptions} from '@testing-library/react'; -import {Theme} from '@twilio-paste/theme'; +import { render, screen } from "@testing-library/react"; +import type { RenderOptions } from "@testing-library/react"; +import { Theme } from "@twilio-paste/theme"; +import * as React from "react"; import { AlertDialogWithTwoActions, DestructiveAlertDialog, DisabledButtonDestructiveAlertDialog, -} from '../stories/index.stories'; +} from "../stories/index.stories"; -const ThemeWrapper: RenderOptions['wrapper'] = ({children}) => ( +const ThemeWrapper: RenderOptions["wrapper"] = ({ children }) => ( {children} ); -describe('Alert Dialog', () => { - it('Should render an alert dialog box', () => { +describe("Alert Dialog", () => { + it("Should render an alert dialog box", () => { render(); - expect(screen.getByText('Submit application')).toBeDefined(); + expect(screen.getByText("Submit application")).toBeDefined(); }); - it('Should have two, labeled buttons when a secondary label and action is given', () => { + it("Should have two, labeled buttons when a secondary label and action is given", () => { render(); - const buttons = screen.getAllByRole('button'); + const buttons = screen.getAllByRole("button"); expect(buttons).toHaveLength(2); - expect(buttons[0]).toHaveTextContent('Cancel'); - expect(buttons[1]).toHaveTextContent('Submit'); + expect(buttons[0]).toHaveTextContent("Cancel"); + expect(buttons[1]).toHaveTextContent("Submit"); }); - it('Should have a destructive button style when the destructive prop is included', () => { - render(, {wrapper: ThemeWrapper}); - const button = screen.getByRole('button', {name: 'Delete'}); - expect(button).toHaveStyleRule('background-color', 'rgb(214, 31, 31)'); + it("Should have a destructive button style when the destructive prop is included", () => { + render(, { wrapper: ThemeWrapper }); + const button = screen.getByRole("button", { name: "Delete" }); + expect(button).toHaveStyleRule("background-color", "rgb(214, 31, 31)"); }); - it('Should have a disabled destructive button style when the onConfirmDisabled prop is included', () => { - render(, {wrapper: ThemeWrapper}); - const button = screen.getByRole('button', {name: 'Delete'}); - expect(button).toHaveStyleRule('background-color', 'rgb(225, 227, 234)'); + it("Should have a disabled destructive button style when the onConfirmDisabled prop is included", () => { + render(, { wrapper: ThemeWrapper }); + const button = screen.getByRole("button", { name: "Delete" }); + expect(button).toHaveStyleRule("background-color", "rgb(225, 227, 234)"); }); - it('Should have a heading the same as the heading prop', () => { + it("Should have a heading the same as the heading prop", () => { render(); - expect(screen.getByRole('heading')).toHaveTextContent('Submit application'); + expect(screen.getByRole("heading")).toHaveTextContent("Submit application"); }); - it('Should have the correct aria attributes', () => { + it("Should have the correct aria attributes", () => { render(); - expect(screen.getByRole('alertdialog')).toBeTruthy(); - expect(screen.getByRole('alertdialog').getAttribute('aria-modal')).toEqual('true'); - expect(screen.getByRole('alertdialog').getAttribute('aria-labelledby')).toEqual( - screen.getByRole('heading').getAttribute('id') + expect(screen.getByRole("alertdialog")).toBeTruthy(); + expect(screen.getByRole("alertdialog").getAttribute("aria-modal")).toEqual("true"); + expect(screen.getByRole("alertdialog").getAttribute("aria-labelledby")).toEqual( + screen.getByRole("heading").getAttribute("id"), ); - expect(screen.getByRole('alertdialog').getAttribute('aria-describedby')).toEqual( + expect(screen.getByRole("alertdialog").getAttribute("aria-describedby")).toEqual( screen - .getByText('Are you sure you want to submit this application? No information can be changed after submitting.') - .getAttribute('id') + .getByText("Are you sure you want to submit this application? No information can be changed after submitting.") + .getAttribute("id"), ); }); - it('Should have correct attributes when button is disabled', () => { - render(, {wrapper: ThemeWrapper}); - expect(screen.getByRole('button', {name: 'Delete'})).toHaveAttribute('disabled'); + it("Should have correct attributes when button is disabled", () => { + render(, { wrapper: ThemeWrapper }); + expect(screen.getByRole("button", { name: "Delete" })).toHaveAttribute("disabled"); }); - it('Should have the initial focus land on the first focusable item', () => { + it("Should have the initial focus land on the first focusable item", () => { render(); - expect(document.activeElement).toEqual(screen.getAllByRole('button')[0]); + expect(document.activeElement).toEqual(screen.getAllByRole("button")[0]); }); }); diff --git a/packages/paste-core/components/alert-dialog/build.js b/packages/paste-core/components/alert-dialog/build.js index a4edeab49b..27dd98f98e 100644 --- a/packages/paste-core/components/alert-dialog/build.js +++ b/packages/paste-core/components/alert-dialog/build.js @@ -1,3 +1,3 @@ -const {build} = require('../../../../tools/build/esbuild'); +const { build } = require("../../../../tools/build/esbuild"); -build(require('./package.json')); +build(require("./package.json")); diff --git a/packages/paste-core/components/alert-dialog/src/AlertDialogBody.tsx b/packages/paste-core/components/alert-dialog/src/AlertDialogBody.tsx index d53df6d231..0153acd064 100644 --- a/packages/paste-core/components/alert-dialog/src/AlertDialogBody.tsx +++ b/packages/paste-core/components/alert-dialog/src/AlertDialogBody.tsx @@ -1,15 +1,15 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; -import type {HTMLPasteProps} from '@twilio-paste/types'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import type { HTMLPasteProps } from "@twilio-paste/types"; +import * as React from "react"; -export interface AlertDialogBodyProps extends HTMLPasteProps<'div'>, Pick { +export interface AlertDialogBodyProps extends HTMLPasteProps<"div">, Pick { bodyID: string; children: NonNullable; } export const AlertDialogBody = React.forwardRef( - ({bodyID, children, element = 'ALERT_DIALOG_BODY', ...props}, ref) => { + ({ bodyID, children, element = "ALERT_DIALOG_BODY", ...props }, ref) => { return ( ); - } + }, ); -AlertDialogBody.displayName = 'AlertDialogBody'; +AlertDialogBody.displayName = "AlertDialogBody"; diff --git a/packages/paste-core/components/alert-dialog/src/AlertDialogContent.tsx b/packages/paste-core/components/alert-dialog/src/AlertDialogContent.tsx index e39c9cb355..8c907ea3f4 100644 --- a/packages/paste-core/components/alert-dialog/src/AlertDialogContent.tsx +++ b/packages/paste-core/components/alert-dialog/src/AlertDialogContent.tsx @@ -1,15 +1,15 @@ -import {css, styled} from '@twilio-paste/styling-library'; -import {ModalDialogContent} from '@twilio-paste/modal'; -import type {ModalDialogContentProps} from '@twilio-paste/modal'; +import { ModalDialogContent } from "@twilio-paste/modal"; +import type { ModalDialogContentProps } from "@twilio-paste/modal"; +import { css, styled } from "@twilio-paste/styling-library"; export type AlertDialogContentProps = ModalDialogContentProps; const AlertDialogContent = styled(ModalDialogContent)(() => css({ - maxWidth: 'size40', - }) + maxWidth: "size40", + }), ); -AlertDialogContent.displayName = 'AlertDialogContent'; +AlertDialogContent.displayName = "AlertDialogContent"; -export {AlertDialogContent}; +export { AlertDialogContent }; diff --git a/packages/paste-core/components/alert-dialog/src/AlertDialogFooter.tsx b/packages/paste-core/components/alert-dialog/src/AlertDialogFooter.tsx index a30b7df8e5..253ba95bf6 100644 --- a/packages/paste-core/components/alert-dialog/src/AlertDialogFooter.tsx +++ b/packages/paste-core/components/alert-dialog/src/AlertDialogFooter.tsx @@ -1,11 +1,11 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; -import {Button} from '@twilio-paste/button'; -import {Stack} from '@twilio-paste/stack'; -import type {HTMLPasteProps} from '@twilio-paste/types'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import { Button } from "@twilio-paste/button"; +import { Stack } from "@twilio-paste/stack"; +import type { HTMLPasteProps } from "@twilio-paste/types"; +import * as React from "react"; -export interface AlertDialogFooterProps extends HTMLPasteProps<'div'>, Pick { +export interface AlertDialogFooterProps extends HTMLPasteProps<"div">, Pick { destructive?: boolean; onConfirm: () => void; onConfirmLabel: string; @@ -18,7 +18,7 @@ export const AlertDialogFooter = React.forwardRef { - const primaryVariant = destructive ? 'destructive' : 'primary'; + const primaryVariant = destructive ? "destructive" : "primary"; return ( ); - } + }, ); -AlertDialogFooter.displayName = 'AlertDialogFooter'; +AlertDialogFooter.displayName = "AlertDialogFooter"; diff --git a/packages/paste-core/components/alert-dialog/src/AlertDialogHeader.tsx b/packages/paste-core/components/alert-dialog/src/AlertDialogHeader.tsx index cc5d0030c2..9db23dd7cf 100644 --- a/packages/paste-core/components/alert-dialog/src/AlertDialogHeader.tsx +++ b/packages/paste-core/components/alert-dialog/src/AlertDialogHeader.tsx @@ -1,16 +1,16 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; -import {Heading} from '@twilio-paste/heading'; -import type {HTMLPasteProps} from '@twilio-paste/types'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import { Heading } from "@twilio-paste/heading"; +import type { HTMLPasteProps } from "@twilio-paste/types"; +import * as React from "react"; -export interface AlertDialogHeaderProps extends HTMLPasteProps<'header'>, Pick { +export interface AlertDialogHeaderProps extends HTMLPasteProps<"header">, Pick { children: string; headingID: string; } export const AlertDialogHeader = React.forwardRef( - ({children, element = 'ALERT_DIALOG_HEADER', headingID, ...props}, ref) => { + ({ children, element = "ALERT_DIALOG_HEADER", headingID, ...props }, ref) => { return ( ); - } + }, ); -AlertDialogHeader.displayName = 'AlertDialogHeader'; +AlertDialogHeader.displayName = "AlertDialogHeader"; diff --git a/packages/paste-core/components/alert-dialog/src/index.tsx b/packages/paste-core/components/alert-dialog/src/index.tsx index 814c41e914..9fab0f3ce8 100644 --- a/packages/paste-core/components/alert-dialog/src/index.tsx +++ b/packages/paste-core/components/alert-dialog/src/index.tsx @@ -1,21 +1,21 @@ -import * as React from 'react'; -import {useUID} from '@twilio-paste/uid-library'; -import {useTransition} from '@twilio-paste/animation-library'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; -import {ModalDialogOverlay} from '@twilio-paste/modal'; -import type {HTMLPasteProps} from '@twilio-paste/types'; +import { useTransition } from "@twilio-paste/animation-library"; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import { ModalDialogOverlay } from "@twilio-paste/modal"; +import type { HTMLPasteProps } from "@twilio-paste/types"; +import { useUID } from "@twilio-paste/uid-library"; +import * as React from "react"; -import {AlertDialogHeader} from './AlertDialogHeader'; -import {AlertDialogBody} from './AlertDialogBody'; -import {AlertDialogContent} from './AlertDialogContent'; -import {AlertDialogFooter} from './AlertDialogFooter'; +import { AlertDialogBody } from "./AlertDialogBody"; +import { AlertDialogContent } from "./AlertDialogContent"; +import { AlertDialogFooter } from "./AlertDialogFooter"; +import { AlertDialogHeader } from "./AlertDialogHeader"; // eslint-disable-next-line @typescript-eslint/no-explicit-any const getAnimationStates = (): any => ({ - from: {opacity: 0, transform: `scale(0.675)`}, - enter: {opacity: 1, transform: `scale(1)`}, - leave: {opacity: 0, transform: `scale(0.675)`}, + from: { opacity: 0, transform: `scale(0.675)` }, + enter: { opacity: 1, transform: `scale(1)` }, + leave: { opacity: 0, transform: `scale(0.675)` }, // https://www.react-spring.dev/docs/advanced/config config: { mass: 0.5, @@ -24,7 +24,7 @@ const getAnimationStates = (): any => ({ }, }); -export interface AlertDialogProps extends HTMLPasteProps<'div'>, Pick { +export interface AlertDialogProps extends HTMLPasteProps<"div">, Pick { children: NonNullable; destructive?: boolean; heading: string; @@ -41,7 +41,7 @@ export const AlertDialog = React.forwardRef( { children, destructive, - element = 'ALERT_DIALOG', + element = "ALERT_DIALOG", heading, isOpen, onConfirm, @@ -51,7 +51,7 @@ export const AlertDialog = React.forwardRef( onConfirmDisabled, ...props }, - ref + ref, ) => { const transitions = useTransition(isOpen, getAnimationStates()); const headingID = useUID(); @@ -62,7 +62,7 @@ export const AlertDialog = React.forwardRef( {transitions( (styles, item) => item && ( - + ( /> - ) + ), )} ); - } + }, ); -AlertDialog.displayName = 'AlertDialog'; +AlertDialog.displayName = "AlertDialog"; diff --git a/packages/paste-core/components/alert-dialog/stories/index.stories.tsx b/packages/paste-core/components/alert-dialog/stories/index.stories.tsx index d3faa24443..1ebee777a8 100644 --- a/packages/paste-core/components/alert-dialog/stories/index.stories.tsx +++ b/packages/paste-core/components/alert-dialog/stories/index.stories.tsx @@ -1,32 +1,32 @@ -import * as React from 'react'; -import type {Story} from '@storybook/react'; -import {useUID} from '@twilio-paste/uid-library'; -import {Button} from '@twilio-paste/button'; -import {Heading} from '@twilio-paste/heading'; -import {Modal, ModalBody, ModalFooter, ModalFooterActions, ModalHeader, ModalHeading} from '@twilio-paste/modal'; -import {Paragraph} from '@twilio-paste/paragraph'; -import {CustomizationProvider} from '@twilio-paste/customization'; -import {useTheme} from '@twilio-paste/theme'; -import {Box} from '@twilio-paste/box'; -import {Input} from '@twilio-paste/input'; -import {Label} from '@twilio-paste/label'; -import {HelpText} from '@twilio-paste/help-text'; +import type { Story } from "@storybook/react"; +import { Box } from "@twilio-paste/box"; +import { Button } from "@twilio-paste/button"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import { Heading } from "@twilio-paste/heading"; +import { HelpText } from "@twilio-paste/help-text"; +import { Input } from "@twilio-paste/input"; +import { Label } from "@twilio-paste/label"; +import { Modal, ModalBody, ModalFooter, ModalFooterActions, ModalHeader, ModalHeading } from "@twilio-paste/modal"; +import { Paragraph } from "@twilio-paste/paragraph"; +import { useTheme } from "@twilio-paste/theme"; +import { useUID } from "@twilio-paste/uid-library"; +import * as React from "react"; -import {AlertDialog} from '../src'; -import {AlertDialogHeader} from '../src/AlertDialogHeader'; -import {AlertDialogBody} from '../src/AlertDialogBody'; -import {AlertDialogContent} from '../src/AlertDialogContent'; -import {AlertDialogFooter} from '../src/AlertDialogFooter'; +import { AlertDialog } from "../src"; +import { AlertDialogBody } from "../src/AlertDialogBody"; +import { AlertDialogContent } from "../src/AlertDialogContent"; +import { AlertDialogFooter } from "../src/AlertDialogFooter"; +import { AlertDialogHeader } from "../src/AlertDialogHeader"; // eslint-disable-next-line import/no-default-export export default { - title: 'Components/Alert Dialog', + title: "Components/Alert Dialog", component: AlertDialog, excludeStories: [ - 'AlertDialogWithTwoActions', - 'DestructiveAlertDialog', - 'OpenAlertDialogFromButton', - 'OpenAlertDialogFromModal', + "AlertDialogWithTwoActions", + "DestructiveAlertDialog", + "OpenAlertDialogFromButton", + "OpenAlertDialogFromModal", ], }; @@ -49,9 +49,9 @@ export const AlertDialogWithTwoActionsStory = (): React.ReactNode => { return ; }; -AlertDialogWithTwoActionsStory.storyName = 'Alert Dialog With Two Actions'; +AlertDialogWithTwoActionsStory.storyName = "Alert Dialog With Two Actions"; AlertDialogWithTwoActionsStory.parameters = { - chromatic: {disableSnapshot: true}, + chromatic: { disableSnapshot: true }, a11y: { // no need to a11y check customization disable: true, @@ -78,22 +78,22 @@ export const DestructiveAlertDialogStory = (): React.ReactNode => { return ; }; -DestructiveAlertDialogStory.storyName = 'Destructive Alert Dialog'; +DestructiveAlertDialogStory.storyName = "Destructive Alert Dialog"; DestructiveAlertDialogStory.parameters = { - chromatic: {disableSnapshot: true}, + chromatic: { disableSnapshot: true }, a11y: { // no need to a11y check customization disable: true, }, }; -export const DisabledButtonDestructiveAlertDialog = ({dialogIsOpen = false}): JSX.Element => { +export const DisabledButtonDestructiveAlertDialog = ({ dialogIsOpen = false }): JSX.Element => { const [isOpen, setIsOpen] = React.useState(dialogIsOpen); - const [inputString, setInputString] = React.useState(''); + const [inputString, setInputString] = React.useState(""); const [inputHasError, setInputHasError] = React.useState(false); const [isDisabled, setIsDisabled] = React.useState(true); const handleOpen = (): void => { - if (inputString !== '') setIsDisabled(false); + if (inputString !== "") setIsDisabled(false); setIsOpen(true); }; const handleDismiss = (): void => { @@ -102,9 +102,9 @@ export const DisabledButtonDestructiveAlertDialog = ({dialogIsOpen = false}): JS setInputHasError(false); }; const handleConfirm = (): void => { - if (inputString === 'Toyota TCB Automobile (Gevelsberg)') { + if (inputString === "Toyota TCB Automobile (Gevelsberg)") { setIsOpen(false); - setInputString(''); + setInputString(""); setInputHasError(false); setIsDisabled(true); } else { @@ -113,7 +113,7 @@ export const DisabledButtonDestructiveAlertDialog = ({dialogIsOpen = false}): JS }; const handleChange = (e): void => { setInputString(e.target.value); - if (e.target.value !== '') setIsDisabled(false); + if (e.target.value !== "") setIsDisabled(false); else setIsDisabled(true); }; return ( @@ -146,7 +146,7 @@ export const DisabledButtonDestructiveAlertDialog = ({dialogIsOpen = false}): JS hasError={inputHasError} value={inputString} /> - + To confirm this deletion, please input the name of this regulatory bundle. @@ -183,9 +183,9 @@ export const OpenAlertDialogFromButtonStory = (): React.ReactNode => { return ; }; -OpenAlertDialogFromButtonStory.storyName = 'Open Alert Dialog From Button'; +OpenAlertDialogFromButtonStory.storyName = "Open Alert Dialog From Button"; OpenAlertDialogFromButtonStory.parameters = { - chromatic: {disableSnapshot: true}, + chromatic: { disableSnapshot: true }, a11y: { // no need to a11y check customization disable: true, @@ -247,9 +247,9 @@ export const OpenAlertDialogFromModalStory = (): React.ReactNode => { return ; }; -OpenAlertDialogFromModalStory.storyName = 'Open Alert Dialog From Modal'; +OpenAlertDialogFromModalStory.storyName = "Open Alert Dialog From Modal"; OpenAlertDialogFromModalStory.parameters = { - chromatic: {disableSnapshot: true}, + chromatic: { disableSnapshot: true }, a11y: { // no need to a11y check customization disable: true, @@ -270,7 +270,7 @@ export const AlertDialogVRT = (): React.ReactNode => { ); }; -AlertDialogVRT.storyName = 'Alert Dialog for VRT'; +AlertDialogVRT.storyName = "Alert Dialog for VRT"; export const DestructiveAlertDialogVRT = (): React.ReactNode => { const alertDialogHeadingID = useUID(); @@ -292,7 +292,7 @@ export const DestructiveAlertDialogVRT = (): React.ReactNode => { ); }; -DestructiveAlertDialogVRT.storyName = 'Destructive Alert Dialog for VRT'; +DestructiveAlertDialogVRT.storyName = "Destructive Alert Dialog for VRT"; export const CustomizedAlertDialog: Story = () => { const theme = useTheme(); @@ -301,11 +301,11 @@ export const CustomizedAlertDialog: Story = () => { disableAnimations={true} theme={theme} elements={{ - ALERT_DIALOG: {backgroundColor: 'colorBackgroundSubaccount'}, - ALERT_DIALOG_HEADER_WRAPPER: {border: 'inherit'}, - ALERT_DIALOG_HEADER: {fontFamily: 'fontFamilyCode', backgroundColor: 'colorBackgroundNeutralWeakest'}, - ALERT_DIALOG_BODY: {backgroundColor: 'colorBackgroundSuccessWeakest'}, - ALERT_DIALOG_FOOTER: {paddingTop: 'space50', backgroundColor: 'colorBackgroundWarningWeakest'}, + ALERT_DIALOG: { backgroundColor: "colorBackgroundSubaccount" }, + ALERT_DIALOG_HEADER_WRAPPER: { border: "inherit" }, + ALERT_DIALOG_HEADER: { fontFamily: "fontFamilyCode", backgroundColor: "colorBackgroundNeutralWeakest" }, + ALERT_DIALOG_BODY: { backgroundColor: "colorBackgroundSuccessWeakest" }, + ALERT_DIALOG_FOOTER: { paddingTop: "space50", backgroundColor: "colorBackgroundWarningWeakest" }, }} > { disableAnimations={true} theme={currentTheme} elements={{ - FOO: {backgroundColor: 'colorBackgroundError'}, - FOO_HEADER_WRAPPER: {border: 'inherit'}, - FOO_HEADER: {fontFamily: 'fontFamilyCode', backgroundColor: 'colorBackgroundNeutralWeakest'}, - FOO_BODY: {backgroundColor: 'colorBackgroundSuccessWeakest'}, - FOO_FOOTER: {paddingTop: 'space50', backgroundColor: 'colorBackgroundWarningWeakest'}, + FOO: { backgroundColor: "colorBackgroundError" }, + FOO_HEADER_WRAPPER: { border: "inherit" }, + FOO_HEADER: { fontFamily: "fontFamilyCode", backgroundColor: "colorBackgroundNeutralWeakest" }, + FOO_BODY: { backgroundColor: "colorBackgroundSuccessWeakest" }, + FOO_FOOTER: { paddingTop: "space50", backgroundColor: "colorBackgroundWarningWeakest" }, }} > { - describe('Dismiss button', () => { - it('Should add a dismiss button when onDismiss is passed as a function to call', () => { +describe("Alert", () => { + describe("Dismiss button", () => { + it("Should add a dismiss button when onDismiss is passed as a function to call", () => { const eventHandlerMock: jest.Mock = jest.fn(); - const {getByRole} = render( + const { getByRole } = render( This is an alert - + , ); - expect(getByRole('button')).toBeInTheDocument(); + expect(getByRole("button")).toBeInTheDocument(); }); - it('Should call the onDismiss event handler when close button clicked', () => { + it("Should call the onDismiss event handler when close button clicked", () => { const eventHandlerMock: jest.Mock = jest.fn(); - const {getByRole} = render( + const { getByRole } = render( This is an alert - + , ); - const button = getByRole('button'); + const button = getByRole("button"); userEvent.click(button); expect(eventHandlerMock).toHaveBeenCalledTimes(1); }); }); - describe('Aria roles', () => { - it('Should add the role of status to the neutral alert', () => { - const {getByRole} = render(This is an alert); - expect(getByRole('status')).toBeInTheDocument(); + describe("Aria roles", () => { + it("Should add the role of status to the neutral alert", () => { + const { getByRole } = render(This is an alert); + expect(getByRole("status")).toBeInTheDocument(); }); - it('Should add the role of alert to the error alert', () => { - const {getByRole} = render(This is an alert); - expect(getByRole('alert')).toBeInTheDocument(); + it("Should add the role of alert to the error alert", () => { + const { getByRole } = render(This is an alert); + expect(getByRole("alert")).toBeInTheDocument(); }); - it('Should add the role of alert to the warning alert', () => { - const {getByRole} = render(This is an alert); - expect(getByRole('alert')).toBeInTheDocument(); + it("Should add the role of alert to the warning alert", () => { + const { getByRole } = render(This is an alert); + expect(getByRole("alert")).toBeInTheDocument(); }); - it('Should add the provided role to the alert', () => { - const {getByRole} = render( + it("Should add the provided role to the alert", () => { + const { getByRole } = render( This is an alert - + , ); - expect(getByRole('tab')).toBeInTheDocument(); + expect(getByRole("tab")).toBeInTheDocument(); }); }); - describe('Customization', () => { - it('should set default data-paste-element attribute on Alert and customizable Alert children', (): void => { + describe("Customization", () => { + it("should set default data-paste-element attribute on Alert and customizable Alert children", (): void => { render( This is my test alert - +
, ); - const alert = screen.getByTestId('alert-customization'); - expect(alert).toHaveAttribute('data-paste-element', 'ALERT'); + const alert = screen.getByTestId("alert-customization"); + expect(alert).toHaveAttribute("data-paste-element", "ALERT"); expect(alert.querySelector('[data-paste-element="ALERT_ICON"]')).toBeInTheDocument(); expect(alert.querySelector('[data-paste-element="ALERT_DISMISS_BUTTON"]')).toBeInTheDocument(); expect(alert.querySelector('[data-paste-element="ALERT_DISMISS_ICON"]')).toBeInTheDocument(); }); - it('should add custom styles to Alert and Alert children', (): void => { + it("should add custom styles to Alert and Alert children", (): void => { render( This is my test alert - +
, ); - const alert = screen.getByTestId('alert-customization'); + const alert = screen.getByTestId("alert-customization"); - expect(alert).toHaveStyleRule('background-color', 'rgb(244, 244, 246)'); - expect(alert.querySelector('[data-paste-element="ALERT_ICON"]')).toHaveStyleRule('color', 'rgb(0, 20, 137)'); + expect(alert).toHaveStyleRule("background-color", "rgb(244, 244, 246)"); + expect(alert.querySelector('[data-paste-element="ALERT_ICON"]')).toHaveStyleRule("color", "rgb(0, 20, 137)"); expect(alert.querySelector('[data-paste-element="ALERT_DISMISS_BUTTON"]')).toHaveStyleRule( - 'background-color', - 'rgb(18, 28, 45)' + "background-color", + "rgb(18, 28, 45)", ); expect(alert.querySelector('[data-paste-element="ALERT_DISMISS_ICON"]')).toHaveStyleRule( - 'color', - 'rgb(255, 255, 255)' + "color", + "rgb(255, 255, 255)", ); }); - it('should set custom element name and properly apply styles to Alert and customizable children', (): void => { + it("should set custom element name and properly apply styles to Alert and customizable children", (): void => { render( This is my test alert - + , ); - const alert = screen.getByTestId('alert-customization'); - expect(alert).toHaveAttribute('data-paste-element', 'MYALERT'); + const alert = screen.getByTestId("alert-customization"); + expect(alert).toHaveAttribute("data-paste-element", "MYALERT"); expect(alert.querySelector('[data-paste-element="MYALERT_ICON"]')).toBeInTheDocument(); expect(alert.querySelector('[data-paste-element="MYALERT_DISMISS_BUTTON"]')).toBeInTheDocument(); expect(alert.querySelector('[data-paste-element="MYALERT_DISMISS_ICON"]')).toBeInTheDocument(); - expect(alert).toHaveStyleRule('background-color', 'rgb(244, 244, 246)'); - expect(alert.querySelector('[data-paste-element="MYALERT_ICON"]')).toHaveStyleRule('color', 'rgb(0, 20, 137)'); + expect(alert).toHaveStyleRule("background-color", "rgb(244, 244, 246)"); + expect(alert.querySelector('[data-paste-element="MYALERT_ICON"]')).toHaveStyleRule("color", "rgb(0, 20, 137)"); expect(alert.querySelector('[data-paste-element="MYALERT_DISMISS_BUTTON"]')).toHaveStyleRule( - 'background-color', - 'rgb(18, 28, 45)' + "background-color", + "rgb(18, 28, 45)", ); expect(alert.querySelector('[data-paste-element="MYALERT_DISMISS_ICON"]')).toHaveStyleRule( - 'color', - 'rgb(255, 255, 255)' + "color", + "rgb(255, 255, 255)", ); }); }); - describe('i18n', () => { - it('should have default dismiss button text', () => { + describe("i18n", () => { + it("should have default dismiss button text", () => { render( This is an alert - + , ); - const dismissButton = screen.getByRole('button', {name: 'Dismiss alert'}); + const dismissButton = screen.getByRole("button", { name: "Dismiss alert" }); expect(dismissButton).toBeDefined(); }); - it('should use i18nDismissLabel for dismiss button text', () => { + it("should use i18nDismissLabel for dismiss button text", () => { render( C'est une alerte neutre. - + , ); - const dismissButton = screen.getByRole('button', {name: "Fermez l'alerte"}); + const dismissButton = screen.getByRole("button", { name: "Fermez l'alerte" }); expect(dismissButton).toBeDefined(); }); - it('should have default error variant icon text', () => { + it("should have default error variant icon text", () => { render( This is an alert - + , ); - const alert = screen.getByTestId('alert-i18n'); + const alert = screen.getByTestId("alert-i18n"); const icon = alert.querySelector('[data-paste-element="ALERT_ICON"]'); - expect(icon?.textContent).toEqual('(error)'); + expect(icon?.textContent).toEqual("(error)"); }); - it('should have default neutral variant icon text', () => { + it("should have default neutral variant icon text", () => { render( This is an alert - + , ); - const alert = screen.getByTestId('alert-i18n'); + const alert = screen.getByTestId("alert-i18n"); const icon = alert.querySelector('[data-paste-element="ALERT_ICON"]'); - expect(icon?.textContent).toEqual('(information)'); + expect(icon?.textContent).toEqual("(information)"); }); - it('should have default warning variant icon text', () => { + it("should have default warning variant icon text", () => { render( This is an alert - + , ); - const alert = screen.getByTestId('alert-i18n'); + const alert = screen.getByTestId("alert-i18n"); const icon = alert.querySelector('[data-paste-element="ALERT_ICON"]'); - expect(icon?.textContent).toEqual('(warning)'); + expect(icon?.textContent).toEqual("(warning)"); }); - it('should use the i18nErrorLabel for error variant icon text', () => { + it("should use the i18nErrorLabel for error variant icon text", () => { render( C'est une alerte. - + , ); - const alert = screen.getByTestId('alert-i18n'); + const alert = screen.getByTestId("alert-i18n"); const icon = alert.querySelector('[data-paste-element="ALERT_ICON"]'); - expect(icon?.textContent).toEqual('(erreur)'); + expect(icon?.textContent).toEqual("(erreur)"); }); - it('should use the i18nNeutralLabel for neutral variant icon text', () => { + it("should use the i18nNeutralLabel for neutral variant icon text", () => { render( C'est une alerte. - + , ); - const alert = screen.getByTestId('alert-i18n'); + const alert = screen.getByTestId("alert-i18n"); const icon = alert.querySelector('[data-paste-element="ALERT_ICON"]'); - expect(icon?.textContent).toEqual('(information)'); + expect(icon?.textContent).toEqual("(information)"); }); - it('should use the i18nWarningLabel for warning variant icon text', () => { + it("should use the i18nWarningLabel for warning variant icon text", () => { render( C'est une alerte. - + , ); - const alert = screen.getByTestId('alert-i18n'); + const alert = screen.getByTestId("alert-i18n"); const icon = alert.querySelector('[data-paste-element="ALERT_ICON"]'); - expect(icon?.textContent).toEqual('(avertissement)'); + expect(icon?.textContent).toEqual("(avertissement)"); }); }); }); diff --git a/packages/paste-core/components/alert/build.js b/packages/paste-core/components/alert/build.js index a4edeab49b..27dd98f98e 100644 --- a/packages/paste-core/components/alert/build.js +++ b/packages/paste-core/components/alert/build.js @@ -1,3 +1,3 @@ -const {build} = require('../../../../tools/build/esbuild'); +const { build } = require("../../../../tools/build/esbuild"); -build(require('./package.json')); +build(require("./package.json")); diff --git a/packages/paste-core/components/alert/src/index.tsx b/packages/paste-core/components/alert/src/index.tsx index fbd691b5cf..01b35f3a73 100644 --- a/packages/paste-core/components/alert/src/index.tsx +++ b/packages/paste-core/components/alert/src/index.tsx @@ -1,36 +1,36 @@ -import * as React from 'react'; -import type {BoxProps} from '@twilio-paste/box'; -import type {HTMLPasteProps, ValueOf} from '@twilio-paste/types'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import {MediaObject, MediaFigure, MediaBody} from '@twilio-paste/media-object'; -import {Button} from '@twilio-paste/button'; -import {ScreenReaderOnly} from '@twilio-paste/screen-reader-only'; -import {CloseIcon} from '@twilio-paste/icons/esm/CloseIcon'; -import {ErrorIcon} from '@twilio-paste/icons/esm/ErrorIcon'; -import {NeutralIcon} from '@twilio-paste/icons/esm/NeutralIcon'; -import {WarningIcon} from '@twilio-paste/icons/esm/WarningIcon'; +import type { BoxProps } from "@twilio-paste/box"; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import { Button } from "@twilio-paste/button"; +import { CloseIcon } from "@twilio-paste/icons/esm/CloseIcon"; +import { ErrorIcon } from "@twilio-paste/icons/esm/ErrorIcon"; +import { NeutralIcon } from "@twilio-paste/icons/esm/NeutralIcon"; +import { WarningIcon } from "@twilio-paste/icons/esm/WarningIcon"; +import { MediaBody, MediaFigure, MediaObject } from "@twilio-paste/media-object"; +import { ScreenReaderOnly } from "@twilio-paste/screen-reader-only"; +import type { HTMLPasteProps, ValueOf } from "@twilio-paste/types"; +import * as React from "react"; -type AlertVariantKeys = 'ERROR' | 'NEUTRAL' | 'WARNING'; +type AlertVariantKeys = "ERROR" | "NEUTRAL" | "WARNING"; export const AlertRoles = { - ERROR: 'alert', - NEUTRAL: 'status', - WARNING: 'alert', + ERROR: "alert", + NEUTRAL: "status", + WARNING: "alert", } as const; export const AlertVariants = { - ERROR: 'error', - NEUTRAL: 'neutral', - WARNING: 'warning', + ERROR: "error", + NEUTRAL: "neutral", + WARNING: "warning", } as const; export const AlertBackgroundColors = { - ERROR: 'colorBackgroundErrorWeakest', - NEUTRAL: 'colorBackgroundNeutralWeakest', - WARNING: 'colorBackgroundWarningWeakest', + ERROR: "colorBackgroundErrorWeakest", + NEUTRAL: "colorBackgroundNeutralWeakest", + WARNING: "colorBackgroundWarningWeakest", } as const; export const AlertTextColors = { - ERROR: 'colorTextError', - NEUTRAL: 'colorTextNeutral', - WARNING: 'colorTextWarningStrong', + ERROR: "colorTextError", + NEUTRAL: "colorTextNeutral", + WARNING: "colorTextWarningStrong", } as const; // eslint-disable-next-line @typescript-eslint/no-redeclare @@ -42,7 +42,7 @@ export type AlertRoles = ValueOf; // eslint-disable-next-line @typescript-eslint/no-redeclare export type AlertTextColors = ValueOf; -export interface AlertProps extends HTMLPasteProps<'div'>, Pick { +export interface AlertProps extends HTMLPasteProps<"div">, Pick { children: NonNullable; onDismiss?: () => void; role?: string; @@ -96,14 +96,14 @@ const Alert = React.forwardRef( onDismiss, variant, role, - element = 'ALERT', - i18nDismissLabel = 'Dismiss alert', - i18nErrorLabel = '(error)', - i18nNeutralLabel = '(information)', - i18nWarningLabel = '(warning)', + element = "ALERT", + i18nDismissLabel = "Dismiss alert", + i18nErrorLabel = "(error)", + i18nNeutralLabel = "(information)", + i18nWarningLabel = "(warning)", ...props }, - ref + ref, ) => { const i18nLabelVariantMap = { error: i18nErrorLabel, @@ -131,7 +131,7 @@ const Alert = React.forwardRef( {children} - {onDismiss && typeof onDismiss === 'function' && ( + {onDismiss && typeof onDismiss === "function" && ( - + , ); - const btnGroup = screen.getByRole('group'); - expect(btnGroup).toHaveAttribute('aria-label', 'test'); + const btnGroup = screen.getByRole("group"); + expect(btnGroup).toHaveAttribute("aria-label", "test"); }); }); -describe('ButtonGroup customization', () => { - it('should set an element data attribute on ButtonGroup', () => { +describe("ButtonGroup customization", () => { + it("should set an element data attribute on ButtonGroup", () => { render(); - const btnGroup = screen.getByRole('group'); - expect(btnGroup.dataset.pasteElement).toEqual('BUTTON_GROUP'); + const btnGroup = screen.getByRole("group"); + expect(btnGroup.dataset.pasteElement).toEqual("BUTTON_GROUP"); }); - it('should set custom element data attributes on ButtonGroup', () => { + it("should set custom element data attributes on ButtonGroup", () => { render(); - const btnGroup = screen.getByRole('group'); - expect(btnGroup.dataset.pasteElement).toEqual('MY_BUTTON_GROUP'); + const btnGroup = screen.getByRole("group"); + expect(btnGroup.dataset.pasteElement).toEqual("MY_BUTTON_GROUP"); }); - it('should add custom styling to ButtonGroup', () => { + it("should add custom styling to ButtonGroup", () => { render( - + , ); - const btnGroup = screen.getByRole('group'); - expect(btnGroup).toHaveStyleRule('background-color', 'rgb(20, 176, 83)'); + const btnGroup = screen.getByRole("group"); + expect(btnGroup).toHaveStyleRule("background-color", "rgb(20, 176, 83)"); }); - it('should add custom styling to a custom element for ButtonGroup', () => { + it("should add custom styling to a custom element for ButtonGroup", () => { render( - + , ); - const btnGroup = screen.getByRole('group'); - expect(btnGroup).toHaveStyleRule('background-color', 'rgb(20, 176, 83)'); + const btnGroup = screen.getByRole("group"); + expect(btnGroup).toHaveStyleRule("background-color", "rgb(20, 176, 83)"); }); }); diff --git a/packages/paste-core/components/button-group/build.js b/packages/paste-core/components/button-group/build.js index a4edeab49b..27dd98f98e 100644 --- a/packages/paste-core/components/button-group/build.js +++ b/packages/paste-core/components/button-group/build.js @@ -1,3 +1,3 @@ -const {build} = require('../../../../tools/build/esbuild'); +const { build } = require("../../../../tools/build/esbuild"); -build(require('./package.json')); +build(require("./package.json")); diff --git a/packages/paste-core/components/button-group/src/ButtonGroup.tsx b/packages/paste-core/components/button-group/src/ButtonGroup.tsx index 85e113bb9b..3c8affb638 100644 --- a/packages/paste-core/components/button-group/src/ButtonGroup.tsx +++ b/packages/paste-core/components/button-group/src/ButtonGroup.tsx @@ -1,7 +1,7 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; -import {styled, css} from '@twilio-paste/styling-library'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import { css, styled } from "@twilio-paste/styling-library"; +import * as React from "react"; const AttachedStyled = styled.span( css({ @@ -9,53 +9,53 @@ const AttachedStyled = styled.span( * NOTE: allow hover and focus indication to remain visible on all sides of a button despite * sibling elements being rendered immediately adjacent under the attached styles */ - '& > button': { + "& > button": { zIndex: 1, }, - '& > button:hover, & > button[aria-pressed=true]': { + "& > button:hover, & > button[aria-pressed=true]": { zIndex: 2, }, - '& > button:focus': { + "& > button:focus": { zIndex: 3, }, - '& > button:disabled': { + "& > button:disabled": { zIndex: 0, }, - '& > button:first-of-type': { + "& > button:first-of-type": { borderTopRightRadius: 0, borderBottomRightRadius: 0, }, - '& > button:not(:first-of-type):not(:last-of-type)': { + "& > button:not(:first-of-type):not(:last-of-type)": { borderRadius: 0, - marginLeft: '1px', + marginLeft: "1px", }, - '& > button:last-of-type': { - marginLeft: '1px', + "& > button:last-of-type": { + marginLeft: "1px", borderTopLeftRadius: 0, borderBottomLeftRadius: 0, }, - }) + }), ); const UnattachedStyled = styled.span( css({ - '& > button:not(:first-of-type)': { - marginLeft: 'space40', + "& > button:not(:first-of-type)": { + marginLeft: "space40", }, - '& > button:first-of-type': { - marginLeft: 'space0', + "& > button:first-of-type": { + marginLeft: "space0", }, - }) + }), ); -export interface ButtonGroupProps extends Omit, 'children'> { - element?: BoxProps['element']; +export interface ButtonGroupProps extends Omit, "children"> { + element?: BoxProps["element"]; attached?: boolean; children: React.ReactElement[]; } export const ButtonGroup = React.forwardRef( - ({element = 'BUTTON_GROUP', children, attached = false, ...props}, ref) => { + ({ element = "BUTTON_GROUP", children, attached = false, ...props }, ref) => { return ( ( {children} ); - } + }, ); -ButtonGroup.displayName = 'ButtonGroup'; +ButtonGroup.displayName = "ButtonGroup"; diff --git a/packages/paste-core/components/button-group/src/index.tsx b/packages/paste-core/components/button-group/src/index.tsx index cd9c57b0a1..d22eaf4c2e 100644 --- a/packages/paste-core/components/button-group/src/index.tsx +++ b/packages/paste-core/components/button-group/src/index.tsx @@ -1 +1 @@ -export * from './ButtonGroup'; +export * from "./ButtonGroup"; diff --git a/packages/paste-core/components/button-group/stories/index.stories.tsx b/packages/paste-core/components/button-group/stories/index.stories.tsx index 7c21df78f1..809dc60ccb 100644 --- a/packages/paste-core/components/button-group/stories/index.stories.tsx +++ b/packages/paste-core/components/button-group/stories/index.stories.tsx @@ -1,22 +1,22 @@ -import * as React from 'react'; -import type {StoryFn} from '@storybook/react'; -import {useUID} from '@twilio-paste/uid-library'; -import {Button} from '@twilio-paste/button'; -import {Popover, PopoverContainer, PopoverButton} from '@twilio-paste/popover'; -import {Text} from '@twilio-paste/text'; -import {CustomizationProvider} from '@twilio-paste/customization'; -import {useTheme} from '@twilio-paste/theme'; +import type { StoryFn } from "@storybook/react"; +import { Button } from "@twilio-paste/button"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import { Popover, PopoverButton, PopoverContainer } from "@twilio-paste/popover"; +import { Text } from "@twilio-paste/text"; +import { useTheme } from "@twilio-paste/theme"; +import { useUID } from "@twilio-paste/uid-library"; +import * as React from "react"; -import {ButtonGroup} from '../src'; -import type {ButtonGroupProps} from '../src'; +import { ButtonGroup } from "../src"; +import type { ButtonGroupProps } from "../src"; // eslint-disable-next-line import/no-default-export export default { - title: 'Components/Button Group', + title: "Components/Button Group", component: ButtonGroup, }; -type ButtonGroupStoryProps = Partial>; +type ButtonGroupStoryProps = Partial>; export const Unattached: StoryFn = (props) => ( @@ -43,7 +43,7 @@ export const FewButtons: StoryFn = () => ( export const ManyButtons: StoryFn = () => ( - {[...'ABCDEFGHIJKLMNOPQRSTUVWXYZ'].map((letter) => ( + {[..."ABCDEFGHIJKLMNOPQRSTUVWXYZ"].map((letter) => ( @@ -115,9 +115,9 @@ export const Customized: StoryFn = () => { theme={currentTheme} elements={{ BUTTON_GROUP: { - padding: 'space40', - backgroundColor: 'colorBackgroundPrimaryWeakest', - borderRadius: 'borderRadius30', + padding: "space40", + backgroundColor: "colorBackgroundPrimaryWeakest", + borderRadius: "borderRadius30", }, }} > diff --git a/packages/paste-core/components/button/__tests__/button.test.tsx b/packages/paste-core/components/button/__tests__/button.test.tsx index 752a8781cf..72cf243725 100644 --- a/packages/paste-core/components/button/__tests__/button.test.tsx +++ b/packages/paste-core/components/button/__tests__/button.test.tsx @@ -1,162 +1,162 @@ -import * as React from 'react'; -import {render, screen} from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import {PlusIcon} from '@twilio-paste/icons/esm/PlusIcon'; -import {CustomizationProvider} from '@twilio-paste/customization'; +import { render, screen } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import { PlusIcon } from "@twilio-paste/icons/esm/PlusIcon"; +import * as React from "react"; -import {Button} from '../src'; +import { Button } from "../src"; const NOOP = (): void => {}; -const HREF = 'https://twilio.paste.design'; +const HREF = "https://twilio.paste.design"; -describe('Button', () => { - describe('Button Errors', () => { +describe("Button", () => { + describe("Button Errors", () => { it('Throws an error when a href is passed but an "a" tag is not', () => { // hide console errors from terminal when throwing expected errors - const spy = jest.spyOn(console, 'error'); + const spy = jest.spyOn(console, "error"); spy.mockImplementation(() => {}); expect(() => render( - ) + , + ), ).toThrow(); spy.mockRestore(); }); it('Throws an error when an "a" tag is passed but a href is not', () => { // hide console errors from terminal when throwing expected errors - const spy = jest.spyOn(console, 'error'); + const spy = jest.spyOn(console, "error"); spy.mockImplementation(() => {}); expect(() => render( - ) + , + ), ).toThrow(); spy.mockRestore(); }); - it('Throws an error when the user should use an Anchor component instead', () => { + it("Throws an error when the user should use an Anchor component instead", () => { // hide console errors from terminal when throwing expected errors - const spy = jest.spyOn(console, 'error'); + const spy = jest.spyOn(console, "error"); spy.mockImplementation(() => {}); expect(() => render( - ) + , + ), ).toThrow(); expect(() => render( - ) + , + ), ).toThrow(); spy.mockRestore(); }); it('Throws an error when an "a" tag is passed but not using correct variant', () => { // hide console errors from terminal when throwing expected errors - const spy = jest.spyOn(console, 'error'); + const spy = jest.spyOn(console, "error"); spy.mockImplementation(() => {}); expect(() => render( - ) + , + ), ).toThrow(); expect(() => render( - ) + , + ), ).toThrow(); spy.mockRestore(); }); it('Throws an error when an "a" tag is passed with disabled or loading state', () => { // hide console errors from terminal when throwing expected errors - const spy = jest.spyOn(console, 'error'); + const spy = jest.spyOn(console, "error"); spy.mockImplementation(() => {}); expect(() => render( - ) + , + ), ).toThrow(); expect(() => render( - ) + , + ), ).toThrow(); spy.mockRestore(); }); - it('Throws an error when size=reset is not applied to variant=reset', () => { + it("Throws an error when size=reset is not applied to variant=reset", () => { // hide console errors from terminal when throwing expected errors - const spy = jest.spyOn(console, 'error'); + const spy = jest.spyOn(console, "error"); spy.mockImplementation(() => {}); expect(() => render( - ) + , + ), ).toThrow(); spy.mockRestore(); }); - it('Throws an error when using fullWidth with an icon sizing', () => { + it("Throws an error when using fullWidth with an icon sizing", () => { // hide console errors from terminal when throwing expected errors - const spy = jest.spyOn(console, 'error'); + const spy = jest.spyOn(console, "error"); spy.mockImplementation(() => {}); expect(() => render( - ) + , + ), ).toThrow(); spy.mockRestore(); }); - it('Throws an error when using fullWidth with an icon_small sizing', () => { + it("Throws an error when using fullWidth with an icon_small sizing", () => { // hide console errors from terminal when throwing expected errors - const spy = jest.spyOn(console, 'error'); + const spy = jest.spyOn(console, "error"); spy.mockImplementation(() => {}); expect(() => render( - ) + , + ), ).toThrow(); spy.mockRestore(); }); - it('Throws an error when not passing children', () => { + it("Throws an error when not passing children", () => { // hide console errors from terminal when throwing expected errors - const spy = jest.spyOn(console, 'error'); + const spy = jest.spyOn(console, "error"); spy.mockImplementation(() => {}); // @ts-expect-error expect button to throw expect(() => render( + , ); - expect(getByRole('button')).toHaveAttribute('aria-expanded', 'true'); + expect(getByRole("button")).toHaveAttribute("aria-expanded", "true"); }); - it('Has an aria-haspopup attribute', () => { - const {getByRole} = render( + it("Has an aria-haspopup attribute", () => { + const { getByRole } = render( + , ); - expect(getByRole('button')).toHaveAttribute('aria-haspopup', 'true'); + expect(getByRole("button")).toHaveAttribute("aria-haspopup", "true"); }); - it('Has an aria-controls attribute', () => { - const {getByRole} = render( + it("Has an aria-controls attribute", () => { + const { getByRole } = render( + , ); - expect(getByRole('button')).toHaveAttribute('aria-controls', 'some-id'); + expect(getByRole("button")).toHaveAttribute("aria-controls", "some-id"); }); - it('Has an aria-busy attribute when loading', () => { - const {getByRole} = render( + it("Has an aria-busy attribute when loading", () => { + const { getByRole } = render( - + , ); - const button = getByRole('button'); + const button = getByRole("button"); - expect(button).toHaveAttribute('aria-busy', 'true'); + expect(button).toHaveAttribute("aria-busy", "true"); expect(button).toBeDisabled(); }); - it('Has disabled set on HTML when disabled', () => { - const {getByRole} = render( + it("Has disabled set on HTML when disabled", () => { + const { getByRole } = render( + , ); - expect(getByRole('button')).toBeDisabled(); + expect(getByRole("button")).toBeDisabled(); }); }); - describe('Button data attributes', () => { - it('Has an data-foo attribute', () => { - const {getByRole} = render( + describe("Button data attributes", () => { + it("Has an data-foo attribute", () => { + const { getByRole } = render( + , ); - expect(getByRole('button')).toHaveAttribute('data-foo', 'test'); + expect(getByRole("button")).toHaveAttribute("data-foo", "test"); }); }); - describe('Button render as', () => { - it('Renders a button as a link', () => { - const {getByRole} = render( + describe("Button render as", () => { + it("Renders a button as a link", () => { + const { getByRole } = render( + , ); - expect(getByRole('link')).toBeInTheDocument(); + expect(getByRole("link")).toBeInTheDocument(); }); }); - describe('Button margin styles', () => { - it('Renders a button with margin: space0', () => { - const {getByTestId} = render( + describe("Button margin styles", () => { + it("Renders a button with margin: space0", () => { + const { getByTestId } = render( + , ); - expect(getByTestId('button-margin')).toHaveStyleRule('margin', 'space0'); + expect(getByTestId("button-margin")).toHaveStyleRule("margin", "space0"); }); }); - describe('Button inner padding', () => { - it('should not set padding for buttons with only one child', () => { - const {getByText} = render(); - expect(getByText('Hello')).not.toHaveStyleRule('padding', 'undefined'); + describe("Button inner padding", () => { + it("should not set padding for buttons with only one child", () => { + const { getByText } = render(); + expect(getByText("Hello")).not.toHaveStyleRule("padding", "undefined"); }); - it('should set padding between rendered children', () => { - const {getByText} = render( + it("should set padding between rendered children", () => { + const { getByText } = render( + , ); - expect(getByText('Hello')).toHaveStyleRule('column-gap', 'space20'); + expect(getByText("Hello")).toHaveStyleRule("column-gap", "space20"); }); }); - describe('button event handlers', () => { - it('Should call the appropriate event handlers', () => { + describe("button event handlers", () => { + it("Should call the appropriate event handlers", () => { const onClickMock: jest.Mock = jest.fn(); const onMouseDownMock: jest.Mock = jest.fn(); const onMouseUpMock: jest.Mock = jest.fn(); @@ -293,7 +293,7 @@ describe('Button', () => { const onFocusMock: jest.Mock = jest.fn(); const onBlurMock: jest.Mock = jest.fn(); - const {getByRole} = render( + const { getByRole } = render( + , ); - const button = getByRole('button'); + const button = getByRole("button"); userEvent.click(button); expect(onMouseDownMock).toHaveBeenCalledTimes(1); @@ -329,210 +329,210 @@ describe('Button', () => { }); }); - describe('button default styles', () => { - it('should have the correct styles for the primary variant', () => { - const {getByTestId, getByText} = render( + describe("button default styles", () => { + it("should have the correct styles for the primary variant", () => { + const { getByTestId, getByText } = render( + , ); - const button = getByTestId('primary-styles'); + const button = getByTestId("primary-styles"); - expect(button).not.toHaveStyleRule('text-align', 'left'); - expect(button).toHaveStyleRule('color', 'colorTextInverse'); - expect(button).toHaveStyleRule('background-color', 'colorBackgroundPrimary'); - expect(button).toHaveStyleRule('box-shadow', 'shadowBorderPrimary'); + expect(button).not.toHaveStyleRule("text-align", "left"); + expect(button).toHaveStyleRule("color", "colorTextInverse"); + expect(button).toHaveStyleRule("background-color", "colorBackgroundPrimary"); + expect(button).toHaveStyleRule("box-shadow", "shadowBorderPrimary"); - expect(getByText('Primary')).toHaveStyleRule('justify-content', 'center'); + expect(getByText("Primary")).toHaveStyleRule("justify-content", "center"); }); - it('should have the correct styles for the primary_icon variant', () => { - const {getByTestId} = render( + it("should have the correct styles for the primary_icon variant", () => { + const { getByTestId } = render( + , ); - const button = getByTestId('primary-icon-styles'); + const button = getByTestId("primary-icon-styles"); - expect(button).not.toHaveStyleRule('text-align', 'left'); - expect(button).toHaveStyleRule('color', 'colorTextPrimary'); + expect(button).not.toHaveStyleRule("text-align", "left"); + expect(button).toHaveStyleRule("color", "colorTextPrimary"); }); - it('should have the correct styles for the secondary variant', () => { - const {getByTestId, getByText} = render( + it("should have the correct styles for the secondary variant", () => { + const { getByTestId, getByText } = render( + , ); - const button = getByTestId('secondary-styles'); + const button = getByTestId("secondary-styles"); - expect(button).not.toHaveStyleRule('text-align', 'left'); - expect(button).toHaveStyleRule('color', 'colorText'); - expect(button).toHaveStyleRule('background-color', 'colorBackgroundBody'); - expect(button).toHaveStyleRule('box-shadow', 'shadowBorderWeak'); + expect(button).not.toHaveStyleRule("text-align", "left"); + expect(button).toHaveStyleRule("color", "colorText"); + expect(button).toHaveStyleRule("background-color", "colorBackgroundBody"); + expect(button).toHaveStyleRule("box-shadow", "shadowBorderWeak"); - expect(getByText('Secondary')).toHaveStyleRule('justify-content', 'center'); + expect(getByText("Secondary")).toHaveStyleRule("justify-content", "center"); }); - it('should have the correct styles for the secondary_icon variant', () => { - const {getByTestId} = render( + it("should have the correct styles for the secondary_icon variant", () => { + const { getByTestId } = render( + , ); - const button = getByTestId('secondary-icon-styles'); + const button = getByTestId("secondary-icon-styles"); - expect(button).not.toHaveStyleRule('text-align', 'left'); - expect(button).toHaveStyleRule('color', 'colorTextIcon'); + expect(button).not.toHaveStyleRule("text-align", "left"); + expect(button).toHaveStyleRule("color", "colorTextIcon"); }); - it('should have the correct styles for the destructive variant', () => { - const {getByTestId, getByText} = render( + it("should have the correct styles for the destructive variant", () => { + const { getByTestId, getByText } = render( + , ); - const button = getByTestId('destructive-styles'); + const button = getByTestId("destructive-styles"); - expect(button).not.toHaveStyleRule('text-align', 'left'); - expect(button).toHaveStyleRule('color', 'colorTextInverse'); - expect(button).toHaveStyleRule('background-color', 'colorBackgroundDestructive'); - expect(button).toHaveStyleRule('box-shadow', 'shadowBorderDestructive'); + expect(button).not.toHaveStyleRule("text-align", "left"); + expect(button).toHaveStyleRule("color", "colorTextInverse"); + expect(button).toHaveStyleRule("background-color", "colorBackgroundDestructive"); + expect(button).toHaveStyleRule("box-shadow", "shadowBorderDestructive"); - expect(getByText('Destructive')).toHaveStyleRule('justify-content', 'center'); + expect(getByText("Destructive")).toHaveStyleRule("justify-content", "center"); }); - it('should have the correct styles for the destructive_icon variant', () => { - const {getByTestId} = render( + it("should have the correct styles for the destructive_icon variant", () => { + const { getByTestId } = render( + , ); - const button = getByTestId('destructive-icon-styles'); + const button = getByTestId("destructive-icon-styles"); - expect(button).not.toHaveStyleRule('text-align', 'left'); - expect(button).toHaveStyleRule('color', 'colorTextDestructive'); + expect(button).not.toHaveStyleRule("text-align", "left"); + expect(button).toHaveStyleRule("color", "colorTextDestructive"); }); - it('should have the correct styles for the destructive_secondary variant', () => { - const {getByTestId, getByText} = render( + it("should have the correct styles for the destructive_secondary variant", () => { + const { getByTestId, getByText } = render( + , ); - const button = getByTestId('destructive_secondary-styles'); - expect(button).not.toHaveStyleRule('text-align', 'left'); - expect(button).toHaveStyleRule('color', 'colorTextDestructive'); - expect(button).toHaveStyleRule('background-color', 'colorBackgroundBody'); - expect(button).toHaveStyleRule('box-shadow', 'shadowBorderWeak'); + const button = getByTestId("destructive_secondary-styles"); + expect(button).not.toHaveStyleRule("text-align", "left"); + expect(button).toHaveStyleRule("color", "colorTextDestructive"); + expect(button).toHaveStyleRule("background-color", "colorBackgroundBody"); + expect(button).toHaveStyleRule("box-shadow", "shadowBorderWeak"); - expect(getByText('Destructive secondary')).toHaveStyleRule('justify-content', 'center'); + expect(getByText("Destructive secondary")).toHaveStyleRule("justify-content", "center"); }); - it('should have the correct styles for the destructive_link variant', () => { - const {getByTestId, getByText} = render( + it("should have the correct styles for the destructive_link variant", () => { + const { getByTestId, getByText } = render( + , ); - const button = getByTestId('destructive_link-styles'); + const button = getByTestId("destructive_link-styles"); - expect(button).toHaveStyleRule('text-align', 'left'); - expect(button).toHaveStyleRule('color', 'colorTextLinkDestructive'); - expect(button).toHaveStyleRule('transition', 'none'); - expect(getByText('Destructive link')).not.toHaveStyleRule('justify-content', 'center'); + expect(button).toHaveStyleRule("text-align", "left"); + expect(button).toHaveStyleRule("color", "colorTextLinkDestructive"); + expect(button).toHaveStyleRule("transition", "none"); + expect(getByText("Destructive link")).not.toHaveStyleRule("justify-content", "center"); }); - it('should have the correct styles for the link variant', () => { - const {getByTestId, getByText} = render( + it("should have the correct styles for the link variant", () => { + const { getByTestId, getByText } = render( + , ); - const button = getByTestId('link-styles'); + const button = getByTestId("link-styles"); - expect(button).toHaveStyleRule('text-align', 'left'); - expect(button).toHaveStyleRule('color', 'colorTextPrimary'); - expect(button).toHaveStyleRule('transition', 'none'); + expect(button).toHaveStyleRule("text-align", "left"); + expect(button).toHaveStyleRule("color", "colorTextPrimary"); + expect(button).toHaveStyleRule("transition", "none"); - expect(getByText('Link')).not.toHaveStyleRule('justify-content', 'center'); + expect(getByText("Link")).not.toHaveStyleRule("justify-content", "center"); }); - it('should have the correct styles for the reset variant', () => { - const {getByText, getByTestId} = render( + it("should have the correct styles for the reset variant", () => { + const { getByText, getByTestId } = render( + , ); - expect(getByText('Reset')).not.toHaveStyleRule('justify-content', 'center'); - expect(getByTestId('reset-styles')).not.toHaveStyleRule('text-align', 'left'); + expect(getByText("Reset")).not.toHaveStyleRule("justify-content", "center"); + expect(getByTestId("reset-styles")).not.toHaveStyleRule("text-align", "left"); }); - it('should have the correct styles for a link button in loading state', () => { - const {getByText, getByTestId} = render( + it("should have the correct styles for a link button in loading state", () => { + const { getByText, getByTestId } = render( - + , ); - const buttonContent = getByText('Loading link'); - const themeWrapper = getByTestId('wrapping-div').firstChild as ChildNode; + const buttonContent = getByText("Loading link"); + const themeWrapper = getByTestId("wrapping-div").firstChild as ChildNode; const loadingIconWrapper = themeWrapper.lastChild as ChildNode; - expect(getByTestId('loading-link-styles')).toHaveStyleRule('text-align', 'left'); + expect(getByTestId("loading-link-styles")).toHaveStyleRule("text-align", "left"); - expect(buttonContent).toHaveStyleRule('opacity', '0'); + expect(buttonContent).toHaveStyleRule("opacity", "0"); - expect(loadingIconWrapper).toHaveStyleRule('position', 'absolute'); - expect(loadingIconWrapper).toHaveStyleRule('top', '0'); - expect(loadingIconWrapper).toHaveStyleRule('right', '0'); - expect(loadingIconWrapper).toHaveStyleRule('bottom', '0'); - expect(loadingIconWrapper).toHaveStyleRule('left', '0'); - expect(loadingIconWrapper).toHaveStyleRule('display', 'flex'); - expect(loadingIconWrapper).toHaveStyleRule('align-items', 'center'); - expect(loadingIconWrapper).toHaveStyleRule('justify-content', 'center'); + expect(loadingIconWrapper).toHaveStyleRule("position", "absolute"); + expect(loadingIconWrapper).toHaveStyleRule("top", "0"); + expect(loadingIconWrapper).toHaveStyleRule("right", "0"); + expect(loadingIconWrapper).toHaveStyleRule("bottom", "0"); + expect(loadingIconWrapper).toHaveStyleRule("left", "0"); + expect(loadingIconWrapper).toHaveStyleRule("display", "flex"); + expect(loadingIconWrapper).toHaveStyleRule("align-items", "center"); + expect(loadingIconWrapper).toHaveStyleRule("justify-content", "center"); }); - it('should have the correct styles for the link variant in disabled state', () => { - const {getByTestId} = render( + it("should have the correct styles for the link variant in disabled state", () => { + const { getByTestId } = render( + , ); - const buttonComponent = getByTestId('disabled-link-styles'); + const buttonComponent = getByTestId("disabled-link-styles"); - expect(buttonComponent).toHaveStyleRule('text-align', 'left'); - expect(buttonComponent).toHaveStyleRule('color', 'colorTextWeaker'); + expect(buttonComponent).toHaveStyleRule("text-align", "left"); + expect(buttonComponent).toHaveStyleRule("color", "colorTextWeaker"); - expect(buttonComponent).toHaveStyleRule('cursor', 'not-allowed'); + expect(buttonComponent).toHaveStyleRule("cursor", "not-allowed"); }); }); - describe('i18n', () => { - it('should have showExternal icon text', () => { + describe("i18n", () => { + it("should have showExternal icon text", () => { render( + , ); - const externalAnchor = screen.getByRole('link'); + const externalAnchor = screen.getByRole("link"); const showExternalIcon = externalAnchor.querySelector('[data-paste-element="ICON"]'); - expect(showExternalIcon?.textContent).toEqual('(link takes you to an external page)'); + expect(showExternalIcon?.textContent).toEqual("(link takes you to an external page)"); }); - it('should have showExternal icon text when i18nShowExternalLinkLabel prop is used', () => { + it("should have showExternal icon text when i18nShowExternalLinkLabel prop is used", () => { render( + , ); - const externalAnchor = screen.getByRole('link'); + const externalAnchor = screen.getByRole("link"); const showExternalIcon = externalAnchor.querySelector('[data-paste-element="ICON"]'); - expect(showExternalIcon?.textContent).toEqual('(este enlace redirige a una página externa)'); + expect(showExternalIcon?.textContent).toEqual("(este enlace redirige a una página externa)"); }); }); - describe('toggle button', () => { - it('Does not have aria-pressed attribute when pressed undefined', () => { - const {getByRole} = render( + describe("toggle button", () => { + it("Does not have aria-pressed attribute when pressed undefined", () => { + const { getByRole } = render( - + , ); - const button = getByRole('button'); + const button = getByRole("button"); - expect(button).not.toHaveAttribute('aria-pressed', 'false'); + expect(button).not.toHaveAttribute("aria-pressed", "false"); }); - it('Has an aria-pressed attribute when pressed is false', () => { - const {getByRole} = render( + it("Has an aria-pressed attribute when pressed is false", () => { + const { getByRole } = render( - + , ); - const button = getByRole('button'); + const button = getByRole("button"); - expect(button).toHaveAttribute('aria-pressed', 'false'); + expect(button).toHaveAttribute("aria-pressed", "false"); }); - it('Has an aria-pressed attribute when pressed is true', () => { - const {getByRole} = render( + it("Has an aria-pressed attribute when pressed is true", () => { + const { getByRole } = render( - + , ); - const button = getByRole('button'); + const button = getByRole("button"); - expect(button).toHaveAttribute('aria-pressed', 'true'); + expect(button).toHaveAttribute("aria-pressed", "true"); }); }); }); diff --git a/packages/paste-core/components/button/__tests__/customization.test.tsx b/packages/paste-core/components/button/__tests__/customization.test.tsx index aed07e3f3c..b98f42225c 100644 --- a/packages/paste-core/components/button/__tests__/customization.test.tsx +++ b/packages/paste-core/components/button/__tests__/customization.test.tsx @@ -1,75 +1,75 @@ -import * as React from 'react'; -import {render} from '@testing-library/react'; -import {CustomizationProvider} from '@twilio-paste/customization'; -import type {PasteCustomCSS} from '@twilio-paste/customization'; +import { render } from "@testing-library/react"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import type { PasteCustomCSS } from "@twilio-paste/customization"; +import * as React from "react"; -import {AnyButton} from '../stories/customization.stories'; +import { AnyButton } from "../stories/customization.stories"; const customButtonStyles = { - backgroundColor: 'colorBackgroundBusy', - borderRadius: 'borderRadius0', - borderWidth: 'borderWidth40', - borderColor: 'colorBorderError', - fontWeight: 'fontWeightLight', + backgroundColor: "colorBackgroundBusy", + borderRadius: "borderRadius0", + borderWidth: "borderWidth40", + borderColor: "colorBorderError", + fontWeight: "fontWeightLight", variants: { - destructive: {backgroundColor: 'colorBackgroundDestructiveStrongest', color: 'colorTextWeaker'}, - link: {padding: 'space40', borderRadius: 'borderRadiusCircle'}, + destructive: { backgroundColor: "colorBackgroundDestructiveStrongest", color: "colorTextWeaker" }, + link: { padding: "space40", borderRadius: "borderRadiusCircle" }, destructive_link: { - padding: 'space40', - borderRadius: 'borderRadiusCircle', - backgroundColor: 'colorBackgroundDestructiveWeak', - color: 'colorTextWarningStrong', - fontWeight: 'fontWeightBold', + padding: "space40", + borderRadius: "borderRadiusCircle", + backgroundColor: "colorBackgroundDestructiveWeak", + color: "colorTextWarningStrong", + fontWeight: "fontWeightBold", }, }, } as PasteCustomCSS; -describe('Button customization', () => { - it('should set element data attribute on Button', () => { - const {getByTestId} = render(); - const button = getByTestId('button_for_customization'); - expect(button.getAttribute('data-paste-element')).toEqual('BUTTON'); +describe("Button customization", () => { + it("should set element data attribute on Button", () => { + const { getByTestId } = render(); + const button = getByTestId("button_for_customization"); + expect(button.getAttribute("data-paste-element")).toEqual("BUTTON"); }); - it('should set custom element data attribute on Button', () => { - const {getByTestId} = render(); - const button = getByTestId('button_for_customization'); - expect(button.getAttribute('data-paste-element')).toEqual('foo'); + it("should set custom element data attribute on Button", () => { + const { getByTestId } = render(); + const button = getByTestId("button_for_customization"); + expect(button.getAttribute("data-paste-element")).toEqual("foo"); }); - it('should add custom styles to Button', () => { - const {getByTestId} = render( - + it("should add custom styles to Button", () => { + const { getByTestId } = render( + - + , ); - const button = getByTestId('button_for_customization'); - expect(button).toHaveStyleRule('background-color', 'rgb(244, 124, 34)'); - expect(button).toHaveStyleRule('border-color', 'rgb(214, 31, 31)'); - expect(button).toHaveStyleRule('font-weight', '400'); + const button = getByTestId("button_for_customization"); + expect(button).toHaveStyleRule("background-color", "rgb(244, 124, 34)"); + expect(button).toHaveStyleRule("border-color", "rgb(214, 31, 31)"); + expect(button).toHaveStyleRule("font-weight", "400"); }); - it('should add custom styles to Button variants', () => { - const {getByTestId} = render( - + it("should add custom styles to Button variants", () => { + const { getByTestId } = render( + - + , ); - const button = getByTestId('button_for_customization'); - expect(button).toHaveStyleRule('background-color', 'rgb(246, 177, 177)'); - expect(button).toHaveStyleRule('padding', '0.75rem'); - expect(button).toHaveStyleRule('font-weight', '700'); + const button = getByTestId("button_for_customization"); + expect(button).toHaveStyleRule("background-color", "rgb(246, 177, 177)"); + expect(button).toHaveStyleRule("padding", "0.75rem"); + expect(button).toHaveStyleRule("font-weight", "700"); }); - it('should add custom styles to Button with custom element prop', () => { - const {getByTestId} = render( - + it("should add custom styles to Button with custom element prop", () => { + const { getByTestId } = render( + - + , ); - const button = getByTestId('button_for_customization'); - expect(button).toHaveStyleRule('border-color', 'rgb(214, 31, 31)'); - expect(button).toHaveStyleRule('border-width', '8px'); - expect(button).toHaveStyleRule('border-radius', '0'); + const button = getByTestId("button_for_customization"); + expect(button).toHaveStyleRule("border-color", "rgb(214, 31, 31)"); + expect(button).toHaveStyleRule("border-width", "8px"); + expect(button).toHaveStyleRule("border-radius", "0"); }); }); diff --git a/packages/paste-core/components/button/build.js b/packages/paste-core/components/button/build.js index a4edeab49b..27dd98f98e 100644 --- a/packages/paste-core/components/button/build.js +++ b/packages/paste-core/components/button/build.js @@ -1,3 +1,3 @@ -const {build} = require('../../../../tools/build/esbuild'); +const { build } = require("../../../../tools/build/esbuild"); -build(require('./package.json')); +build(require("./package.json")); diff --git a/packages/paste-core/components/button/src/Button.tsx b/packages/paste-core/components/button/src/Button.tsx index 7654df968a..bb92720f8f 100644 --- a/packages/paste-core/components/button/src/Button.tsx +++ b/packages/paste-core/components/button/src/Button.tsx @@ -1,31 +1,31 @@ -import * as React from 'react'; -import {Box} from '@twilio-paste/box'; -import {Spinner} from '@twilio-paste/spinner'; -import {secureExternalLink} from '@twilio-paste/anchor'; -import {useSpring, animated} from '@twilio-paste/animation-library'; -import {ArrowForwardIcon} from '@twilio-paste/icons/esm/ArrowForwardIcon'; -import {LinkExternalIcon} from '@twilio-paste/icons/esm/LinkExternalIcon'; +import { secureExternalLink } from "@twilio-paste/anchor"; +import { animated, useSpring } from "@twilio-paste/animation-library"; +import { Box } from "@twilio-paste/box"; +import { ArrowForwardIcon } from "@twilio-paste/icons/esm/ArrowForwardIcon"; +import { LinkExternalIcon } from "@twilio-paste/icons/esm/LinkExternalIcon"; +import { Spinner } from "@twilio-paste/spinner"; +import * as React from "react"; +import { DestructiveButton } from "./DestructiveButton"; +import { DestructiveIconButton } from "./DestructiveIconButton"; +import { DestructiveLinkButton } from "./DestructiveLinkButton"; +import { DestructiveSecondaryButton } from "./DestructiveSecondaryButton"; +import { InverseButton } from "./InverseButton"; +import { InverseLinkButton } from "./InverseLinkButton"; +import { LinkButton } from "./LinkButton"; +import { PrimaryButton } from "./PrimaryButton"; +import { PrimaryIconButton } from "./PrimaryIconButton"; +import { ResetButton } from "./ResetButton"; +import { SecondaryButton } from "./SecondaryButton"; +import { SecondaryIconButton } from "./SecondaryIconButton"; import type { + ButtonContentsProps, ButtonProps, ButtonSizes, - ButtonContentsProps, - DirectButtonProps, - ButtonVariants, ButtonStates, -} from './types'; -import {PrimaryButton} from './PrimaryButton'; -import {PrimaryIconButton} from './PrimaryIconButton'; -import {SecondaryButton} from './SecondaryButton'; -import {SecondaryIconButton} from './SecondaryIconButton'; -import {DestructiveButton} from './DestructiveButton'; -import {DestructiveIconButton} from './DestructiveIconButton'; -import {DestructiveLinkButton} from './DestructiveLinkButton'; -import {DestructiveSecondaryButton} from './DestructiveSecondaryButton'; -import {LinkButton} from './LinkButton'; -import {InverseButton} from './InverseButton'; -import {InverseLinkButton} from './InverseLinkButton'; -import {ResetButton} from './ResetButton'; + ButtonVariants, + DirectButtonProps, +} from "./types"; const AnimatedBox = animated(Box); @@ -36,21 +36,21 @@ const AnimatedBox = animated(Box); * - 'default' otherwise */ const getButtonSize = (variant: ButtonVariants, children: React.ReactNode, size?: ButtonSizes): ButtonSizes => { - let smartSize: ButtonSizes = 'default'; + let smartSize: ButtonSizes = "default"; if (size != null) { smartSize = size; - } else if (variant === 'link' || variant === 'destructive_link' || variant === 'reset') { - smartSize = 'reset'; + } else if (variant === "link" || variant === "destructive_link" || variant === "reset") { + smartSize = "reset"; } else if (React.Children.count(children) === 1) { React.Children.forEach(children, (child) => { if ( React.isValidElement(child) && // @ts-expect-error we know displayName will exist in React - typeof child.type.displayName === 'string' && + typeof child.type.displayName === "string" && // @ts-expect-error we know displayName will exist in React - child.type.displayName.includes('Icon') + child.type.displayName.includes("Icon") ) { - smartSize = 'icon'; + smartSize = "icon"; } }); } @@ -59,12 +59,12 @@ const getButtonSize = (variant: ButtonVariants, children: React.ReactNode, size? const getButtonState = (disabled?: boolean, loading?: boolean): ButtonStates => { if (disabled) { - return 'disabled'; + return "disabled"; } if (loading) { - return 'loading'; + return "loading"; } - return 'default'; + return "default"; }; const handlePropValidation = ({ @@ -79,21 +79,21 @@ const handlePropValidation = ({ loading, pressed, }: ButtonProps): void => { - const hasHref = href != null && href !== ''; + const hasHref = href != null && href !== ""; const hasTabIndex = tabIndex != null; // Link validation - if (as !== 'a' && hasHref) { + if (as !== "a" && hasHref) { throw new Error(`[Paste: Button] You cannot pass href into a button without the 'a' tag. Use 'as="a"'.`); } - if (as === 'a') { + if (as === "a") { if (!hasHref) { throw new Error(`[Paste: Button] Missing href prop for link button.`); } - if (variant === 'link' || variant === 'inverse_link') { + if (variant === "link" || variant === "inverse_link") { throw new Error(`[Paste: Button] Using Button component as an Anchor. Use the Paste Anchor component instead.`); } - if (variant !== 'primary' && variant !== 'secondary' && variant !== 'reset' && variant !== 'inverse') { + if (variant !== "primary" && variant !== "secondary" && variant !== "reset" && variant !== "inverse") { throw new Error(`[Paste: Button] ); -export const CustomizedPrimaryButton: StoryFn = (_args, {parameters: {isTestEnvironment}}) => ( +export const CustomizedPrimaryButton: StoryFn = (_args, { parameters: { isTestEnvironment } }) => ( } @@ -90,7 +90,7 @@ export const CustomizedPrimaryButton: StoryFn = (_args, {parameters: {isTestEnvi /> ); -export const CustomizedSecondaryButton: StoryFn = (_args, {parameters: {isTestEnvironment}}) => ( +export const CustomizedSecondaryButton: StoryFn = (_args, { parameters: { isTestEnvironment } }) => ( } @@ -98,7 +98,7 @@ export const CustomizedSecondaryButton: StoryFn = (_args, {parameters: {isTestEn /> ); -export const CustomizedLinkButton: StoryFn = (_args, {parameters: {isTestEnvironment}}) => ( +export const CustomizedLinkButton: StoryFn = (_args, { parameters: { isTestEnvironment } }) => ( } @@ -106,7 +106,7 @@ export const CustomizedLinkButton: StoryFn = (_args, {parameters: {isTestEnviron /> ); -export const CustomizedDestructivePrimaryButton: StoryFn = (_args, {parameters: {isTestEnvironment}}) => ( +export const CustomizedDestructivePrimaryButton: StoryFn = (_args, { parameters: { isTestEnvironment } }) => ( } @@ -114,7 +114,7 @@ export const CustomizedDestructivePrimaryButton: StoryFn = (_args, {parameters: /> ); -export const CustomizedDestructiveSecondaryButton: StoryFn = (_args, {parameters: {isTestEnvironment}}) => ( +export const CustomizedDestructiveSecondaryButton: StoryFn = (_args, { parameters: { isTestEnvironment } }) => ( } @@ -122,7 +122,7 @@ export const CustomizedDestructiveSecondaryButton: StoryFn = (_args, {parameters /> ); -export const CustomizedDestructiveLinkButton: StoryFn = (_args, {parameters: {isTestEnvironment}}) => ( +export const CustomizedDestructiveLinkButton: StoryFn = (_args, { parameters: { isTestEnvironment } }) => ( } @@ -132,8 +132,8 @@ export const CustomizedDestructiveLinkButton: StoryFn = (_args, {parameters: {is // eslint-disable-next-line import/no-default-export export default { - title: 'Components/Button/Customization', - excludeStories: ['AnyButton'], + title: "Components/Button/Customization", + excludeStories: ["AnyButton"], parameters: { a11y: { // no need to a11y check customization diff --git a/packages/paste-core/components/button/stories/index.stories.tsx b/packages/paste-core/components/button/stories/index.stories.tsx index 7cab28cba2..7abef81b05 100644 --- a/packages/paste-core/components/button/stories/index.stories.tsx +++ b/packages/paste-core/components/button/stories/index.stories.tsx @@ -1,37 +1,37 @@ -import * as React from 'react'; -import {PlusIcon} from '@twilio-paste/icons/esm/PlusIcon'; -import {CheckboxCheckIcon} from '@twilio-paste/icons/esm/CheckboxCheckIcon'; -import {BoldIcon} from '@twilio-paste/icons/esm/BoldIcon'; -import {PauseIcon} from '@twilio-paste/icons/esm/PauseIcon'; -import {PlayIcon} from '@twilio-paste/icons/esm/PlayIcon'; -import {Box} from '@twilio-paste/box'; -import {Heading} from '@twilio-paste/heading'; -import {Stack} from '@twilio-paste/stack'; -import {CloseIcon} from '@twilio-paste/icons/esm/CloseIcon'; -import {ScreenReaderOnly} from '@twilio-paste/screen-reader-only'; -import {isRenderingOnServer} from '@twilio-paste/animation-library'; +import { isRenderingOnServer } from "@twilio-paste/animation-library"; +import { Box } from "@twilio-paste/box"; +import { Heading } from "@twilio-paste/heading"; +import { BoldIcon } from "@twilio-paste/icons/esm/BoldIcon"; +import { CheckboxCheckIcon } from "@twilio-paste/icons/esm/CheckboxCheckIcon"; +import { CloseIcon } from "@twilio-paste/icons/esm/CloseIcon"; +import { PauseIcon } from "@twilio-paste/icons/esm/PauseIcon"; +import { PlayIcon } from "@twilio-paste/icons/esm/PlayIcon"; +import { PlusIcon } from "@twilio-paste/icons/esm/PlusIcon"; +import { ScreenReaderOnly } from "@twilio-paste/screen-reader-only"; +import { Stack } from "@twilio-paste/stack"; +import * as React from "react"; -import {Button} from '../src'; -import type {ButtonVariants, ButtonSizes} from '../src/types'; +import { Button } from "../src"; +import type { ButtonSizes, ButtonVariants } from "../src/types"; const ButtonSizeOptions = [ - 'default', - 'small', - 'icon', - 'icon_small', - 'reset', - 'rounded_small', - 'circle', - 'circle_small', + "default", + "small", + "icon", + "icon_small", + "reset", + "rounded_small", + "circle", + "circle_small", ]; -const AllSizeOptions: React.FC> = ({variant}) => { +const AllSizeOptions: React.FC> = ({ variant }) => { const allButtons: React.ReactNode[] = []; ButtonSizeOptions.forEach((size, index) => { - if (variant === 'reset' && size !== 'reset') return; + if (variant === "reset" && size !== "reset") return; const children = - size === 'icon' || size === 'icon_small' || size === 'circle' || size === 'circle_small' ? ( + size === "icon" || size === "icon_small" || size === "circle" || size === "circle_small" ? ( ) : ( variant @@ -44,21 +44,21 @@ const AllSizeOptions: React.FC {children} - {size !== 'icon' && - size !== 'icon_small' && - size !== 'reset' && - size !== 'circle' && - size !== 'circle_small' && ( + {size !== "icon" && + size !== "icon_small" && + size !== "reset" && + size !== "circle" && + size !== "circle_small" && ( )} - {size !== 'icon' && - size !== 'icon_small' && - size !== 'reset' && - size !== 'circle' && - size !== 'circle_small' && ( + {size !== "icon" && + size !== "icon_small" && + size !== "reset" && + size !== "circle" && + size !== "circle_small" && ( - {chats.map(({id}) => ( + {chats.map(({ id }) => ( {id} diff --git a/packages/paste-core/components/chat-log/stories/customization.stories.tsx b/packages/paste-core/components/chat-log/stories/customization.stories.tsx index be3cddad0d..9c239fd453 100644 --- a/packages/paste-core/components/chat-log/stories/customization.stories.tsx +++ b/packages/paste-core/components/chat-log/stories/customization.stories.tsx @@ -1,28 +1,28 @@ -import * as React from 'react'; -import {CustomizationProvider} from '@twilio-paste/customization'; -import {Avatar} from '@twilio-paste/avatar'; -import {DownloadIcon} from '@twilio-paste/icons/esm/DownloadIcon'; -import {useTheme} from '@twilio-paste/theme'; -import type {StoryFn} from '@storybook/react'; +import type { StoryFn } from "@storybook/react"; +import { Avatar } from "@twilio-paste/avatar"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import { DownloadIcon } from "@twilio-paste/icons/esm/DownloadIcon"; +import { useTheme } from "@twilio-paste/theme"; +import * as React from "react"; import { - ChatMessage, - ChatBubble, - ChatMessageMeta, - ChatMessageMetaItem, ChatAttachment, - ComposerAttachmentCard, - ChatAttachmentLink, ChatAttachmentDescription, + ChatAttachmentLink, ChatBookend, ChatBookendItem, + ChatBubble, ChatEvent, ChatLog, -} from '../src'; + ChatMessage, + ChatMessageMeta, + ChatMessageMetaItem, + ComposerAttachmentCard, +} from "../src"; // eslint-disable-next-line import/no-default-export export default { - title: 'Components/ChatLog/Customization', + title: "Components/ChatLog/Customization", parameters: { a11y: { // no need to a11y check customization @@ -31,7 +31,7 @@ export default { }, }; -export const CustomizedMessages: StoryFn = (_args, {parameters: {isTestEnvironment}}) => { +export const CustomizedMessages: StoryFn = (_args, { parameters: { isTestEnvironment } }) => { const currentTheme = useTheme(); return ( @@ -90,7 +90,7 @@ export const CustomizedMessages: StoryFn = (_args, {parameters: {isTestEnvironme ); }; -export const CustomizedChatAttachments: StoryFn = (_args, {parameters: {isTestEnvironment}}) => { +export const CustomizedChatAttachments: StoryFn = (_args, { parameters: { isTestEnvironment } }) => { const currentTheme = useTheme(); return ( @@ -174,7 +174,7 @@ export const CustomizedChatAttachments: StoryFn = (_args, {parameters: {isTestEn ); }; -export const CustomizedChatBookend: StoryFn = (_args, {parameters: {isTestEnvironment}}) => { +export const CustomizedChatBookend: StoryFn = (_args, { parameters: { isTestEnvironment } }) => { const currentTheme = useTheme(); return ( @@ -198,7 +198,7 @@ export const CustomizedChatBookend: StoryFn = (_args, {parameters: {isTestEnviro ); }; -export const CustomizedChatEvent: StoryFn = (_args, {parameters: {isTestEnvironment}}) => { +export const CustomizedChatEvent: StoryFn = (_args, { parameters: { isTestEnvironment } }) => { const currentTheme = useTheme(); return ( diff --git a/packages/paste-core/components/chat-log/stories/index.stories.tsx b/packages/paste-core/components/chat-log/stories/index.stories.tsx index e58215557e..0c775c6313 100644 --- a/packages/paste-core/components/chat-log/stories/index.stories.tsx +++ b/packages/paste-core/components/chat-log/stories/index.stories.tsx @@ -1,31 +1,31 @@ -import * as React from 'react'; -import {Avatar} from '@twilio-paste/avatar'; -import {Box} from '@twilio-paste/box'; -import {HelpText} from '@twilio-paste/help-text'; -import {Stack} from '@twilio-paste/stack'; -import {Button} from '@twilio-paste/button'; -import {ArrowDownIcon} from '@twilio-paste/icons/esm/ArrowDownIcon'; -import {DownloadIcon} from '@twilio-paste/icons/esm/DownloadIcon'; -import {useUID} from '@twilio-paste/uid-library'; -import type {StoryFn} from '@storybook/react'; +import type { StoryFn } from "@storybook/react"; +import { Avatar } from "@twilio-paste/avatar"; +import { Box } from "@twilio-paste/box"; +import { Button } from "@twilio-paste/button"; +import { HelpText } from "@twilio-paste/help-text"; +import { ArrowDownIcon } from "@twilio-paste/icons/esm/ArrowDownIcon"; +import { DownloadIcon } from "@twilio-paste/icons/esm/DownloadIcon"; +import { Stack } from "@twilio-paste/stack"; +import { useUID } from "@twilio-paste/uid-library"; +import * as React from "react"; import { - ChatMessage, - ChatBubble, - ChatMessageMeta, - ChatMessageMetaItem, ChatAttachment, - ChatAttachmentLink, ChatAttachmentDescription, - ChatLog, + ChatAttachmentLink, ChatBookend, ChatBookendItem, + ChatBubble, ChatEvent, -} from '../src'; + ChatLog, + ChatMessage, + ChatMessageMeta, + ChatMessageMetaItem, +} from "../src"; // eslint-disable-next-line import/no-default-export export default { - title: 'Components/ChatLog', + title: "Components/ChatLog", }; export const NewMessagesButton: StoryFn = () => ( @@ -99,7 +99,7 @@ export const ScrollingChatLog: StoryFn = () => { Quisque ullamcorper ipsum vitae lorem euismod sodales. Donec a nisi eget eros laoreet pellentesque. Donec sed bibendum justo, at ornare mi. Sed eget tempor metus, sed sagittis lacus. Donec commodo nisi in ligula - accumsan euismod. Nam ornare lobortis orci, eget rhoncus ligula euismod ut.{' '} + accumsan euismod. Nam ornare lobortis orci, eget rhoncus ligula euismod ut.{" "} Donec sit amet orci hendrerit, varius diam in, porttitor felis. @@ -188,7 +188,7 @@ export const ExampleChatLog: StoryFn = () => ( Quisque ullamcorper ipsum vitae lorem euismod sodales. Donec a nisi eget eros laoreet pellentesque. Donec sed bibendum justo, at ornare mi. Sed eget tempor metus, sed sagittis lacus. Donec commodo nisi in ligula accumsan - euismod. Nam ornare lobortis orci, eget rhoncus ligula euismod ut.{' '} + euismod. Nam ornare lobortis orci, eget rhoncus ligula euismod ut.{" "} }> diff --git a/packages/paste-core/components/checkbox/__tests__/checkbox.test.tsx b/packages/paste-core/components/checkbox/__tests__/checkbox.test.tsx index 8eb26c3119..c9ed31a29c 100644 --- a/packages/paste-core/components/checkbox/__tests__/checkbox.test.tsx +++ b/packages/paste-core/components/checkbox/__tests__/checkbox.test.tsx @@ -1,232 +1,232 @@ -import * as React from 'react'; -import {render, fireEvent, screen} from '@testing-library/react'; -import {CustomizationProvider} from '@twilio-paste/customization'; -import type {PasteCustomCSS} from '@twilio-paste/customization'; - -import {Checkbox, CheckboxGroup} from '../src'; - -const getCustomizationStyles = (element = 'CHECKBOX'): {[key: string]: PasteCustomCSS} => ({ - [`${element}_GROUP`]: {padding: 'space60'}, - [`${element}_GROUP_SET`]: {marginLeft: 'space60'}, - [`${element}_GROUP_FIELD`]: {marginBottom: 'space60'}, - [`${element}_GROUP_ERROR_TEXT_WRAPPER`]: {marginBottom: 'space60'}, - [`${element}`]: {padding: 'space30'}, - [`${element}_CONTROL`]: {borderRadius: 'borderRadius20'}, - [`${element}_ICON`]: {color: 'colorTextIconNeutral'}, - [`${element}_LABEL_TEXT`]: {color: 'colorTextNeutral'}, - [`${element}_HELP_TEXT_WRAPPER`]: {marginBottom: 'space60'}, +import { fireEvent, render, screen } from "@testing-library/react"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import type { PasteCustomCSS } from "@twilio-paste/customization"; +import * as React from "react"; + +import { Checkbox, CheckboxGroup } from "../src"; + +const getCustomizationStyles = (element = "CHECKBOX"): { [key: string]: PasteCustomCSS } => ({ + [`${element}_GROUP`]: { padding: "space60" }, + [`${element}_GROUP_SET`]: { marginLeft: "space60" }, + [`${element}_GROUP_FIELD`]: { marginBottom: "space60" }, + [`${element}_GROUP_ERROR_TEXT_WRAPPER`]: { marginBottom: "space60" }, + [`${element}`]: { padding: "space30" }, + [`${element}_CONTROL`]: { borderRadius: "borderRadius20" }, + [`${element}_ICON`]: { color: "colorTextIconNeutral" }, + [`${element}_LABEL_TEXT`]: { color: "colorTextNeutral" }, + [`${element}_HELP_TEXT_WRAPPER`]: { marginBottom: "space60" }, }); const NOOP = (): void => {}; const defaultProps = { - id: 'foo', - name: 'foo', + id: "foo", + name: "foo", }; const defaultGroupProps = { - legend: 'This is a group legend', - name: 'bar', - value: 'bar', + legend: "This is a group legend", + name: "bar", + value: "bar", onChange: NOOP, }; -describe('Checkbox', () => { - it('should render', () => { - const {container} = render(foo); - const checkbox = screen.getByRole('checkbox'); +describe("Checkbox", () => { + it("should render", () => { + const { container } = render(foo); + const checkbox = screen.getByRole("checkbox"); expect(checkbox).not.toBeNull(); expect(checkbox.id).toBeDefined(); const checkIcon = container.querySelector('[data-paste-element="CHECKBOX_ICON"]'); - expect(checkIcon).toHaveStyleRule('display', 'none'); + expect(checkIcon).toHaveStyleRule("display", "none"); }); - it('should render as invalid', () => { - const {getByRole} = render( + it("should render as invalid", () => { + const { getByRole } = render( foo - + , ); - expect(getByRole('checkbox').getAttribute('aria-invalid')).toBeTruthy(); + expect(getByRole("checkbox").getAttribute("aria-invalid")).toBeTruthy(); }); - it('should use the id prop when passed', () => { + it("should use the id prop when passed", () => { render( foo - + , ); - const checkbox = screen.getByRole('checkbox'); - expect(checkbox.id).toBe('my-id'); + const checkbox = screen.getByRole("checkbox"); + expect(checkbox.id).toBe("my-id"); }); - it('should render as checked when defaultChecked', () => { - const {getByLabelText, container} = render( + it("should render as checked when defaultChecked", () => { + const { getByLabelText, container } = render( foo - + , ); - expect((getByLabelText('foo') as HTMLInputElement).checked).toBeTruthy(); + expect((getByLabelText("foo") as HTMLInputElement).checked).toBeTruthy(); const checkIcon = container.querySelector('[data-paste-element="CHECKBOX_ICON"]'); - expect(checkIcon).toHaveStyleRule('display', 'block'); + expect(checkIcon).toHaveStyleRule("display", "block"); }); - it('should render as checked when controlled', () => { - const {getByLabelText, container} = render( + it("should render as checked when controlled", () => { + const { getByLabelText, container } = render( foo - + , ); - expect((getByLabelText('foo') as HTMLInputElement).checked).toBeTruthy(); + expect((getByLabelText("foo") as HTMLInputElement).checked).toBeTruthy(); const checkIcon = container.querySelector('[data-paste-element="CHECKBOX_ICON"'); - expect(checkIcon).toHaveStyleRule('display', 'block'); + expect(checkIcon).toHaveStyleRule("display", "block"); }); - it('should render a required dot', () => { + it("should render a required dot", () => { render( foo - + , ); - const label = screen.getByText('foo'); + const label = screen.getByText("foo"); const requiredDot = label.querySelector('[data-paste-element="REQUIRED_DOT"]'); expect(requiredDot).toBeDefined(); }); - it('should render as indeterminate', () => { - const {getByLabelText} = render( + it("should render as indeterminate", () => { + const { getByLabelText } = render( foo - + , ); - expect(getByLabelText('foo').getAttribute('aria-checked')).toBe('mixed'); + expect(getByLabelText("foo").getAttribute("aria-checked")).toBe("mixed"); }); - it('should render as disabled', () => { - const {getByLabelText} = render( + it("should render as disabled", () => { + const { getByLabelText } = render( foo - + , ); - expect((getByLabelText('foo') as HTMLInputElement).disabled).toBeTruthy(); + expect((getByLabelText("foo") as HTMLInputElement).disabled).toBeTruthy(); }); - it('should render an id', () => { - const {getByLabelText} = render(foo); - expect(getByLabelText('foo').id).toBe('foo'); + it("should render an id", () => { + const { getByLabelText } = render(foo); + expect(getByLabelText("foo").id).toBe("foo"); }); - it('should render a name', () => { - const {getByLabelText} = render(foo); - expect((getByLabelText('foo') as HTMLInputElement).name).toBe('foo'); + it("should render a name", () => { + const { getByLabelText } = render(foo); + expect((getByLabelText("foo") as HTMLInputElement).name).toBe("foo"); }); - it('should render aria attributes', () => { - const {getByLabelText} = render( + it("should render aria attributes", () => { + const { getByLabelText } = render( foo - + , ); - expect(getByLabelText('foo').getAttribute('aria-label')).toBe('foo'); - expect(getByLabelText('foo').getAttribute('aria-labelledby')).toBe('bar'); - expect(getByLabelText('foo').getAttribute('aria-busy')).toBe('true'); + expect(getByLabelText("foo").getAttribute("aria-label")).toBe("foo"); + expect(getByLabelText("foo").getAttribute("aria-labelledby")).toBe("bar"); + expect(getByLabelText("foo").getAttribute("aria-busy")).toBe("true"); }); - it('renders a helpText message when helpText prop is present', () => { - const helpText = 'I am a helpText message'; - const {getByText} = render( + it("renders a helpText message when helpText prop is present", () => { + const helpText = "I am a helpText message"; + const { getByText } = render( foo - + , ); expect(getByText(helpText)).toBeDefined(); }); }); -describe('Checkbox Group', () => { - it('should render', () => { - const {container} = render( +describe("Checkbox Group", () => { + it("should render", () => { + const { container } = render( foo - + , ); - expect(container.querySelector('fieldset')).not.toBeNull(); + expect(container.querySelector("fieldset")).not.toBeNull(); }); - it('should render a legend', () => { - const {getByText} = render( + it("should render a legend", () => { + const { getByText } = render( foo - + , ); - expect(getByText('This is a group legend')).not.toBeNull(); + expect(getByText("This is a group legend")).not.toBeNull(); }); - it('should have a required a required dot in the legend', () => { + it("should have a required a required dot in the legend", () => { render( foo - + , ); - const fieldset = screen.getByRole('group'); + const fieldset = screen.getByRole("group"); const requiredDot = fieldset.querySelector('[data-paste-element="LEGEND_REQUIRED_DOT"]'); expect(requiredDot).toBeDefined(); }); - it('should render a name', () => { - const {getByRole} = render( + it("should render a name", () => { + const { getByRole } = render( foo - + , ); - expect((getByRole('checkbox') as HTMLInputElement).name).toBe(defaultProps.name); + expect((getByRole("checkbox") as HTMLInputElement).name).toBe(defaultProps.name); }); - it('should render a disabled checkbox in the checkbox group', () => { - const {getByRole} = render( + it("should render a disabled checkbox in the checkbox group", () => { + const { getByRole } = render( foo - + , ); - expect((getByRole('checkbox') as HTMLInputElement).disabled).toBeTruthy(); + expect((getByRole("checkbox") as HTMLInputElement).disabled).toBeTruthy(); }); - it('renders a helpText message when helpText prop is present', () => { - const helpText = 'I am a helpText message'; - const {getByText} = render( + it("renders a helpText message when helpText prop is present", () => { + const helpText = "I am a helpText message"; + const { getByText } = render( foo - + , ); expect(getByText(helpText)).toBeDefined(); }); - it('renders an errorText message when errorText prop is present', () => { - const errorText = 'I am an errorText message'; - const {getByText} = render( + it("renders an errorText message when errorText prop is present", () => { + const errorText = "I am an errorText message"; + const { getByText } = render( foo - + , ); expect(getByText(errorText)).toBeDefined(); }); }); -describe('Checkbox event handlers', () => { - it('Should call the appropriate event handlers', () => { +describe("Checkbox event handlers", () => { + it("Should call the appropriate event handlers", () => { const onChangeMock: jest.Mock = jest.fn(); const onFocusMock: jest.Mock = jest.fn(); const onBlurMock: jest.Mock = jest.fn(); - const {getByTestId} = render( + const { getByTestId } = render( { onBlur={onBlurMock} > foo - + , ); - fireEvent.click(getByTestId('checkbox-button')); + fireEvent.click(getByTestId("checkbox-button")); expect(onChangeMock).toHaveBeenCalledTimes(1); - fireEvent.focus(getByTestId('checkbox-button')); + fireEvent.focus(getByTestId("checkbox-button")); expect(onFocusMock).toHaveBeenCalledTimes(1); - fireEvent.blur(getByTestId('checkbox-button')); + fireEvent.blur(getByTestId("checkbox-button")); expect(onBlurMock).toHaveBeenCalledTimes(1); }); - it('Should not call onChange handler when uncontrolled', () => { + it("Should not call onChange handler when uncontrolled", () => { const onChangeMock: jest.Mock = jest.fn(); - const {getByTestId} = render( + const { getByTestId } = render( foo - + , ); - fireEvent.click(getByTestId('checkbox-button')); + fireEvent.click(getByTestId("checkbox-button")); expect(onChangeMock).toHaveBeenCalledTimes(0); }); - it('Should check the checkbox when controlled', () => { + it("Should check the checkbox when controlled", () => { const MockCheckBox = (): JSX.Element => { const [checked, setChecked] = React.useState(false); return ( @@ -279,13 +279,13 @@ describe('Checkbox event handlers', () => { ); }; - const {getByTestId} = render(); + const { getByTestId } = render(); - fireEvent.click(getByTestId('checkbox-button')); - expect((getByTestId('checkbox-button') as HTMLInputElement).checked).toBe(true); + fireEvent.click(getByTestId("checkbox-button")); + expect((getByTestId("checkbox-button") as HTMLInputElement).checked).toBe(true); }); - it('Should check the checkbox when uncontrolled', () => { + it("Should check the checkbox when uncontrolled", () => { const MockCheckBox = (): JSX.Element => { return ( @@ -294,24 +294,24 @@ describe('Checkbox event handlers', () => { ); }; - const {getByTestId} = render(); + const { getByTestId } = render(); - fireEvent.click(getByTestId('checkbox-button')); - expect((getByTestId('checkbox-button') as HTMLInputElement).checked).toBe(true); + fireEvent.click(getByTestId("checkbox-button")); + expect((getByTestId("checkbox-button") as HTMLInputElement).checked).toBe(true); }); }); -describe('Customization', () => { - it('Should set an element data attribute for Checkbox', (): void => { - const {container} = render( +describe("Customization", () => { + it("Should set an element data attribute for Checkbox", (): void => { + const { container } = render( foo - + , ); - expect(screen.getByTestId('checkbox-group')).toHaveAttribute('data-paste-element', 'CHECKBOX_GROUP'); + expect(screen.getByTestId("checkbox-group")).toHaveAttribute("data-paste-element", "CHECKBOX_GROUP"); expect(container.querySelector('[data-paste-element="CHECKBOX_GROUP_SET"]')).toBeInTheDocument(); expect(container.querySelector('[data-paste-element="CHECKBOX_GROUP_FIELD"]')).toBeInTheDocument(); expect(container.querySelector('[data-paste-element="CHECKBOX_GROUP_ERROR_TEXT_WRAPPER"]')).toBeInTheDocument(); @@ -321,16 +321,16 @@ describe('Customization', () => { expect(container.querySelector('[data-paste-element="CHECKBOX_LABEL_TEXT"]')).toBeInTheDocument(); expect(container.querySelector('[data-paste-element="CHECKBOX_HELP_TEXT_WRAPPER"]')).toBeInTheDocument(); }); - it('Should set a custom element data attribute on Checkbox', (): void => { - const {container} = render( + it("Should set a custom element data attribute on Checkbox", (): void => { + const { container } = render( foo - + , ); - expect(screen.getByTestId('checkbox-group')).toHaveAttribute('data-paste-element', 'MY_CHECKBOX_GROUP'); + expect(screen.getByTestId("checkbox-group")).toHaveAttribute("data-paste-element", "MY_CHECKBOX_GROUP"); expect(container.querySelector('[data-paste-element="MY_CHECKBOX_GROUP_SET"]')).toBeInTheDocument(); expect(container.querySelector('[data-paste-element="MY_CHECKBOX_GROUP_FIELD"]')).toBeInTheDocument(); expect(container.querySelector('[data-paste-element="MY_CHECKBOX_GROUP_ERROR_TEXT_WRAPPER"]')).toBeInTheDocument(); @@ -341,45 +341,45 @@ describe('Customization', () => { expect(container.querySelector('[data-paste-element="SPECIAL_CHECKBOX_HELP_TEXT_WRAPPER"]')).toBeInTheDocument(); }); - it('should add custom styling to default Checkbox', (): void => { - const {container} = render( + it("should add custom styling to default Checkbox", (): void => { + const { container } = render( foo - + , ); - expect(screen.getByTestId('checkbox-group')).toHaveStyleRule('padding', '1.25rem'); + expect(screen.getByTestId("checkbox-group")).toHaveStyleRule("padding", "1.25rem"); expect(container.querySelector('[data-paste-element="CHECKBOX_GROUP_SET"]')).toHaveStyleRule( - 'margin-left', - '1.25rem' + "margin-left", + "1.25rem", ); expect(container.querySelector('[data-paste-element="CHECKBOX_GROUP_FIELD"]')).toHaveStyleRule( - 'margin-bottom', - '1.25rem' + "margin-bottom", + "1.25rem", ); expect(container.querySelector('[data-paste-element="CHECKBOX_GROUP_ERROR_TEXT_WRAPPER"]')).toHaveStyleRule( - 'margin-bottom', - '1.25rem' + "margin-bottom", + "1.25rem", ); - expect(container.querySelector('[data-paste-element="CHECKBOX"]')).toHaveStyleRule('padding', '0.5rem'); - expect(container.querySelector('[data-paste-element="CHECKBOX_CONTROL"]')).toHaveStyleRule('border-radius', '4px'); - expect(container.querySelector('[data-paste-element="CHECKBOX_ICON"]')).toHaveStyleRule('color', 'rgb(0, 20, 137)'); + expect(container.querySelector('[data-paste-element="CHECKBOX"]')).toHaveStyleRule("padding", "0.5rem"); + expect(container.querySelector('[data-paste-element="CHECKBOX_CONTROL"]')).toHaveStyleRule("border-radius", "4px"); + expect(container.querySelector('[data-paste-element="CHECKBOX_ICON"]')).toHaveStyleRule("color", "rgb(0, 20, 137)"); expect(container.querySelector('[data-paste-element="CHECKBOX_LABEL_TEXT"]')).toHaveStyleRule( - 'color', - 'rgb(0, 20, 137)' + "color", + "rgb(0, 20, 137)", ); expect(container.querySelector('[data-paste-element="CHECKBOX_HELP_TEXT_WRAPPER"]')).toHaveStyleRule( - 'margin-bottom', - '1.25rem' + "margin-bottom", + "1.25rem", ); }); - it('should add custom styling to a custom named Checkbox', (): void => { - const {container} = render( - + it("should add custom styling to a custom named Checkbox", (): void => { + const { container } = render( + { foo - + , ); - expect(screen.getByTestId('checkbox-group')).toHaveStyleRule('padding', '1.25rem'); + expect(screen.getByTestId("checkbox-group")).toHaveStyleRule("padding", "1.25rem"); expect(container.querySelector('[data-paste-element="MY_CHECKBOX_GROUP_SET"]')).toHaveStyleRule( - 'margin-left', - '1.25rem' + "margin-left", + "1.25rem", ); expect(container.querySelector('[data-paste-element="MY_CHECKBOX_GROUP_FIELD"]')).toHaveStyleRule( - 'margin-bottom', - '1.25rem' + "margin-bottom", + "1.25rem", ); expect(container.querySelector('[data-paste-element="MY_CHECKBOX_GROUP_ERROR_TEXT_WRAPPER"]')).toHaveStyleRule( - 'margin-bottom', - '1.25rem' + "margin-bottom", + "1.25rem", ); - expect(container.querySelector('[data-paste-element="MY_CHECKBOX"]')).toHaveStyleRule('padding', '0.5rem'); + expect(container.querySelector('[data-paste-element="MY_CHECKBOX"]')).toHaveStyleRule("padding", "0.5rem"); expect(container.querySelector('[data-paste-element="MY_CHECKBOX_CONTROL"]')).toHaveStyleRule( - 'border-radius', - '4px' + "border-radius", + "4px", ); expect(container.querySelector('[data-paste-element="MY_CHECKBOX_ICON"]')).toHaveStyleRule( - 'color', - 'rgb(0, 20, 137)' + "color", + "rgb(0, 20, 137)", ); expect(container.querySelector('[data-paste-element="MY_CHECKBOX_LABEL_TEXT"]')).toHaveStyleRule( - 'color', - 'rgb(0, 20, 137)' + "color", + "rgb(0, 20, 137)", ); expect(container.querySelector('[data-paste-element="MY_CHECKBOX_HELP_TEXT_WRAPPER"]')).toHaveStyleRule( - 'margin-bottom', - '1.25rem' + "margin-bottom", + "1.25rem", ); }); }); -describe('i18n', () => { - it('Should have default text for the required dot in the legend', () => { +describe("i18n", () => { + it("Should have default text for the required dot in the legend", () => { render( foo - + , ); - const fieldset = screen.getByRole('group'); + const fieldset = screen.getByRole("group"); const requiredDot = fieldset.querySelector('[data-paste-element="LEGEND_REQUIRED_DOT"]'); - expect(requiredDot?.textContent).toEqual('(required)'); + expect(requiredDot?.textContent).toEqual("(required)"); }); - it('Should use the i18nRequiredLabel prop for the required dot in the legend', () => { + it("Should use the i18nRequiredLabel prop for the required dot in the legend", () => { render( foo - + , ); - const fieldset = screen.getByRole('group'); + const fieldset = screen.getByRole("group"); const requiredDot = fieldset.querySelector('[data-paste-element="LEGEND_REQUIRED_DOT"]'); - expect(requiredDot?.textContent).toEqual('(requis)'); + expect(requiredDot?.textContent).toEqual("(requis)"); }); }); diff --git a/packages/paste-core/components/checkbox/__tests__/checkboxdisclaimer.test.tsx b/packages/paste-core/components/checkbox/__tests__/checkboxdisclaimer.test.tsx index 756aaea705..d5e3287e53 100644 --- a/packages/paste-core/components/checkbox/__tests__/checkboxdisclaimer.test.tsx +++ b/packages/paste-core/components/checkbox/__tests__/checkboxdisclaimer.test.tsx @@ -1,115 +1,115 @@ -import * as React from 'react'; -import {render} from '@testing-library/react'; -import {CustomizationProvider} from '@twilio-paste/customization'; +import { render } from "@testing-library/react"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import * as React from "react"; -import {CheckboxDisclaimer} from '../src'; +import { CheckboxDisclaimer } from "../src"; const defaultProps = { - id: 'foo', - name: 'foo', - value: 'foo', + id: "foo", + name: "foo", + value: "foo", }; -describe('Checkbox Disclaimer', () => { - it('should render', () => { - const {getByRole} = render(foo); - expect(getByRole('checkbox')).not.toBeNull(); +describe("Checkbox Disclaimer", () => { + it("should render", () => { + const { getByRole } = render(foo); + expect(getByRole("checkbox")).not.toBeNull(); }); - it('should render a required dot', () => { - const {getByText} = render( + it("should render a required dot", () => { + const { getByText } = render( foo - + , ); - const label = getByText('foo'); + const label = getByText("foo"); const requiredDot = label.querySelector('[data-paste-element="REQUIRED_DOT"]'); expect(requiredDot).toBeDefined(); }); - it('renders a errorText message when errorText prop is present', () => { - const errorText = 'This is the error text.'; - const {getByText} = render( + it("renders a errorText message when errorText prop is present", () => { + const errorText = "This is the error text."; + const { getByText } = render( foo - + , ); expect(getByText(errorText)).toBeDefined(); }); }); -describe('Customization', () => { - it('Should set a default element data attribute Checkbox Disclaimer', () => { - const {container} = render( +describe("Customization", () => { + it("Should set a default element data attribute Checkbox Disclaimer", () => { + const { container } = render( foo - + , ); expect(container.querySelector('[data-paste-element="CHECKBOX_DISCLAIMER"]')).toBeInTheDocument(); expect( - container.querySelector('[data-paste-element="CHECKBOX_DISCLAIMER_ERROR_TEXT_WRAPPER"]') + container.querySelector('[data-paste-element="CHECKBOX_DISCLAIMER_ERROR_TEXT_WRAPPER"]'), ).toBeInTheDocument(); }); - it('Should set a custom element data attribute for a custom named Checkbox Disclaimer', () => { - const {container} = render( + it("Should set a custom element data attribute for a custom named Checkbox Disclaimer", () => { + const { container } = render( foo - + , ); expect(container.querySelector('[data-paste-element="MY_CHECKBOX_DISCLAIMER"]')).toBeInTheDocument(); expect( - container.querySelector('[data-paste-element="MY_CHECKBOX_DISCLAIMER_ERROR_TEXT_WRAPPER"]') + container.querySelector('[data-paste-element="MY_CHECKBOX_DISCLAIMER_ERROR_TEXT_WRAPPER"]'), ).toBeInTheDocument(); }); - it('Should add custom styling to a default Checkbox Disclaimer', () => { - const {container} = render( + it("Should add custom styling to a default Checkbox Disclaimer", () => { + const { container } = render( foo - + , ); expect(container.querySelector('[data-paste-element="CHECKBOX_DISCLAIMER"]')).toHaveStyleRule( - 'background-color', - 'rgb(254, 236, 236)' + "background-color", + "rgb(254, 236, 236)", ); expect(container.querySelector('[data-paste-element="CHECKBOX_DISCLAIMER_ERROR_TEXT_WRAPPER"]')).toHaveStyleRule( - 'margin-top', - '1.25rem' + "margin-top", + "1.25rem", ); }); - it('Should add custom styling to a custom named Checkbox Disclaimer', () => { - const {container} = render( + it("Should add custom styling to a custom named Checkbox Disclaimer", () => { + const { container } = render( foo - + , ); expect(container.querySelector('[data-paste-element="MY_CHECKBOX_DISCLAIMER"]')).toHaveStyleRule( - 'background-color', - 'rgb(254, 236, 236)' + "background-color", + "rgb(254, 236, 236)", ); expect(container.querySelector('[data-paste-element="MY_CHECKBOX_DISCLAIMER_ERROR_TEXT_WRAPPER"]')).toHaveStyleRule( - 'margin-top', - '1.25rem' + "margin-top", + "1.25rem", ); }); }); diff --git a/packages/paste-core/components/checkbox/build.js b/packages/paste-core/components/checkbox/build.js index a4edeab49b..27dd98f98e 100644 --- a/packages/paste-core/components/checkbox/build.js +++ b/packages/paste-core/components/checkbox/build.js @@ -1,3 +1,3 @@ -const {build} = require('../../../../tools/build/esbuild'); +const { build } = require("../../../../tools/build/esbuild"); -build(require('./package.json')); +build(require("./package.json")); diff --git a/packages/paste-core/components/checkbox/src/Checkbox.tsx b/packages/paste-core/components/checkbox/src/Checkbox.tsx index d509eaffc2..9cc48b0883 100644 --- a/packages/paste-core/components/checkbox/src/Checkbox.tsx +++ b/packages/paste-core/components/checkbox/src/Checkbox.tsx @@ -1,41 +1,41 @@ -import * as React from 'react'; -import {useUID} from '@twilio-paste/uid-library'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; -import {CheckboxCheckIcon} from '@twilio-paste/icons/esm/CheckboxCheckIcon'; -import {MinusIcon} from '@twilio-paste/icons/esm/MinusIcon'; import { BaseRadioCheckboxControl, + BaseRadioCheckboxHelpText, BaseRadioCheckboxLabel, BaseRadioCheckboxLabelText, - BaseRadioCheckboxHelpText, -} from '@twilio-paste/base-radio-checkbox'; -import {MediaObject, MediaFigure, MediaBody} from '@twilio-paste/media-object'; -import {RequiredDot} from '@twilio-paste/label'; -import type {HTMLPasteProps} from '@twilio-paste/types'; - -import {CheckboxContext} from './CheckboxContext'; +} from "@twilio-paste/base-radio-checkbox"; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import { CheckboxCheckIcon } from "@twilio-paste/icons/esm/CheckboxCheckIcon"; +import { MinusIcon } from "@twilio-paste/icons/esm/MinusIcon"; +import { RequiredDot } from "@twilio-paste/label"; +import { MediaBody, MediaFigure, MediaObject } from "@twilio-paste/media-object"; +import type { HTMLPasteProps } from "@twilio-paste/types"; +import { useUID } from "@twilio-paste/uid-library"; +import * as React from "react"; + +import { CheckboxContext } from "./CheckboxContext"; const selectAllStyleProps = { - paddingTop: 'space20', - paddingRight: 'space30', - paddingBottom: 'space20', - paddingLeft: 'space30', - borderRadius: 'borderRadius10', - backgroundColor: 'colorBackground', + paddingTop: "space20", + paddingRight: "space30", + paddingBottom: "space20", + paddingLeft: "space30", + borderRadius: "borderRadius10", + backgroundColor: "colorBackground", }; const selectAllActiveStyleProps = { ...selectAllStyleProps, - backgroundColor: 'colorBackground', + backgroundColor: "colorBackground", }; const selectAllChildStyleProps = { - paddingLeft: 'space30', - paddingRight: 'space30', + paddingLeft: "space30", + paddingRight: "space30", }; -export interface CheckboxProps extends HTMLPasteProps<'input'>, Pick { +export interface CheckboxProps extends HTMLPasteProps<"input">, Pick { children: NonNullable; hasError?: boolean; helpText?: string | React.ReactNode; @@ -49,16 +49,16 @@ export interface CheckboxProps extends HTMLPasteProps<'input'>, Pick; const HiddenCheckbox = React.forwardRef((props, ref) => ( (( /> )); -HiddenCheckbox.displayName = 'HiddenCheckbox'; +HiddenCheckbox.displayName = "HiddenCheckbox"; const CheckboxIcon: React.FC<{ indeterminate: boolean | undefined; checked: boolean | undefined; - element: BoxProps['element']; -}> = ({checked, element, indeterminate}) => { + element: BoxProps["element"]; +}> = ({ checked, element, indeterminate }) => { if (indeterminate) { return ; } return ( ( ( { checked, defaultChecked, - element = 'CHECKBOX', + element = "CHECKBOX", children, helpText, id, @@ -117,11 +117,11 @@ const Checkbox = React.forwardRef( onChange, ...props }, - ref + ref, ) => { if (checked != null && defaultChecked != null) { throw new Error( - `[Paste Checkbox] Do not provide both 'defaultChecked' and 'checked' to Checkbox at the same time. Please consider if you want this component to be controlled or uncontrolled.` + `[Paste Checkbox] Do not provide both 'defaultChecked' and 'checked' to Checkbox at the same time. Please consider if you want this component to be controlled or uncontrolled.`, ); } @@ -150,7 +150,7 @@ const Checkbox = React.forwardRef( checkboxGroupContext.onChange(event); } }, - [onChange, checkboxGroupContext.onChange] + [onChange, checkboxGroupContext.onChange], ); // Prioritizing direct props values over whatever CheckboxGroupContext passes down @@ -177,7 +177,7 @@ const Checkbox = React.forwardRef( name={name} onChange={handleChange} aria-describedby={helpTextId} - aria-checked={indeterminate ? 'mixed' : checked} + aria-checked={indeterminate ? "mixed" : checked} aria-invalid={hasError} id={checkboxId} required={required} @@ -196,7 +196,7 @@ const Checkbox = React.forwardRef( {required && ( @@ -215,8 +215,8 @@ const Checkbox = React.forwardRef( )} ); - } + }, ); -Checkbox.displayName = 'Checkbox'; +Checkbox.displayName = "Checkbox"; -export {Checkbox, HiddenCheckbox, CheckboxIcon}; +export { Checkbox, HiddenCheckbox, CheckboxIcon }; diff --git a/packages/paste-core/components/checkbox/src/CheckboxContext.tsx b/packages/paste-core/components/checkbox/src/CheckboxContext.tsx index 04ec068dbc..1e7c227018 100644 --- a/packages/paste-core/components/checkbox/src/CheckboxContext.tsx +++ b/packages/paste-core/components/checkbox/src/CheckboxContext.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import * as React from "react"; interface CheckboxContextValue { disabled: boolean; @@ -15,4 +15,4 @@ const CheckboxContext = React.createContext({ onChange: () => {}, }); -export {CheckboxContext}; +export { CheckboxContext }; diff --git a/packages/paste-core/components/checkbox/src/CheckboxDisclaimer.tsx b/packages/paste-core/components/checkbox/src/CheckboxDisclaimer.tsx index f02197dabe..8ebcd615b8 100644 --- a/packages/paste-core/components/checkbox/src/CheckboxDisclaimer.tsx +++ b/packages/paste-core/components/checkbox/src/CheckboxDisclaimer.tsx @@ -1,18 +1,18 @@ -import * as React from 'react'; -import {Box} from '@twilio-paste/box'; -import {HelpText} from '@twilio-paste/help-text'; +import { Box } from "@twilio-paste/box"; +import { HelpText } from "@twilio-paste/help-text"; +import * as React from "react"; -import {Checkbox} from './Checkbox'; -import type {CheckboxProps} from './Checkbox'; +import { Checkbox } from "./Checkbox"; +import type { CheckboxProps } from "./Checkbox"; export interface CheckboxDisclaimerProps - extends Omit { + extends Omit { children: NonNullable; errorText?: string | React.ReactNode; } const CheckboxDisclaimer = React.forwardRef( - ({children, element = 'CHECKBOX_DISCLAIMER', errorText, ...props}, ref) => { + ({ children, element = "CHECKBOX_DISCLAIMER", errorText, ...props }, ref) => { return ( <> @@ -27,9 +27,9 @@ const CheckboxDisclaimer = React.forwardRef ); - } + }, ); -CheckboxDisclaimer.displayName = 'CheckboxDisclaimer'; +CheckboxDisclaimer.displayName = "CheckboxDisclaimer"; -export {CheckboxDisclaimer}; +export { CheckboxDisclaimer }; diff --git a/packages/paste-core/components/checkbox/src/CheckboxGroup.tsx b/packages/paste-core/components/checkbox/src/CheckboxGroup.tsx index 1115a62e7b..9de149382f 100644 --- a/packages/paste-core/components/checkbox/src/CheckboxGroup.tsx +++ b/packages/paste-core/components/checkbox/src/CheckboxGroup.tsx @@ -1,9 +1,9 @@ -import * as React from 'react'; -import {InlineControlGroup} from '@twilio-paste/inline-control-group'; -import type {InlineControlGroupProps} from '@twilio-paste/inline-control-group'; +import { InlineControlGroup } from "@twilio-paste/inline-control-group"; +import type { InlineControlGroupProps } from "@twilio-paste/inline-control-group"; +import * as React from "react"; -import type {CheckboxProps} from './Checkbox'; -import {CheckboxContext} from './CheckboxContext'; +import type { CheckboxProps } from "./Checkbox"; +import { CheckboxContext } from "./CheckboxContext"; export interface CheckboxGroupProps extends InlineControlGroupProps { isSelectAll?: boolean; @@ -16,17 +16,17 @@ const CheckboxGroup = React.forwardRef( ( { children, - element = 'CHECKBOX_GROUP', + element = "CHECKBOX_GROUP", disabled = false, errorText, isSelectAll = false, name, onChange, - orientation = 'vertical', - i18nRequiredLabel = '(required)', + orientation = "vertical", + i18nRequiredLabel = "(required)", ...props }, - ref + ref, ) => { const onChangeHandler = React.useCallback( (event: React.ChangeEvent): void => { @@ -34,7 +34,7 @@ const CheckboxGroup = React.forwardRef( onChange(event.target.checked); } }, - [onChange] + [onChange], ); const contextValue = React.useMemo(() => { @@ -62,16 +62,16 @@ const CheckboxGroup = React.forwardRef( return React.isValidElement(child) ? React.cloneElement(child as React.ReactElement, { isSelectAll: isSelectAll && index === 0, - isSelectAllChild: isSelectAll && orientation === 'vertical' && index !== 0, + isSelectAllChild: isSelectAll && orientation === "vertical" && index !== 0, }) : child; })} ); - } + }, ); -CheckboxGroup.displayName = 'CheckboxGroup'; +CheckboxGroup.displayName = "CheckboxGroup"; -export {CheckboxGroup}; +export { CheckboxGroup }; diff --git a/packages/paste-core/components/checkbox/src/index.tsx b/packages/paste-core/components/checkbox/src/index.tsx index ed33472e25..009b59ba48 100644 --- a/packages/paste-core/components/checkbox/src/index.tsx +++ b/packages/paste-core/components/checkbox/src/index.tsx @@ -1,3 +1,3 @@ -export * from './Checkbox'; -export * from './CheckboxGroup'; -export * from './CheckboxDisclaimer'; +export * from "./Checkbox"; +export * from "./CheckboxGroup"; +export * from "./CheckboxDisclaimer"; diff --git a/packages/paste-core/components/checkbox/stories/checkbox.stories.tsx b/packages/paste-core/components/checkbox/stories/checkbox.stories.tsx index 2f5301588f..07739f0df0 100644 --- a/packages/paste-core/components/checkbox/stories/checkbox.stories.tsx +++ b/packages/paste-core/components/checkbox/stories/checkbox.stories.tsx @@ -1,16 +1,16 @@ -import * as React from 'react'; -import {useUID} from '@twilio-paste/uid-library'; -import {Anchor} from '@twilio-paste/anchor'; -import {Stack} from '@twilio-paste/stack'; -import {Text} from '@twilio-paste/text'; +import { Anchor } from "@twilio-paste/anchor"; +import { Stack } from "@twilio-paste/stack"; +import { Text } from "@twilio-paste/text"; +import { useUID } from "@twilio-paste/uid-library"; +import * as React from "react"; -import {Checkbox, CheckboxGroup, CheckboxDisclaimer} from '../src'; +import { Checkbox, CheckboxDisclaimer, CheckboxGroup } from "../src"; // eslint-disable-next-line import/no-default-export export default { - title: 'Components/Checkbox', + title: "Components/Checkbox", component: Checkbox, - subcomponents: {CheckboxGroup, CheckboxDisclaimer}, + subcomponents: { CheckboxGroup, CheckboxDisclaimer }, }; export const DefaultCheckbox = (): React.ReactNode => { @@ -20,7 +20,7 @@ export const DefaultCheckbox = (): React.ReactNode => { ); }; -DefaultCheckbox.storyName = 'Checkbox'; +DefaultCheckbox.storyName = "Checkbox"; export const CheckboxChecked = (): React.ReactNode => { const [checked, setChecked] = React.useState(true); @@ -39,7 +39,7 @@ export const CheckboxChecked = (): React.ReactNode => { ); }; -CheckboxChecked.storyName = 'Checkbox - Checked'; +CheckboxChecked.storyName = "Checkbox - Checked"; export const CheckboxWithNoID = (): React.ReactNode => { const [checked, setChecked] = React.useState(true); @@ -57,7 +57,7 @@ export const CheckboxWithNoID = (): React.ReactNode => { ); }; -CheckboxWithNoID.storyName = 'Checkbox - With no ID'; +CheckboxWithNoID.storyName = "Checkbox - With no ID"; export const CheckboxDefaultChecked = (): React.ReactNode => { return ( @@ -66,7 +66,7 @@ export const CheckboxDefaultChecked = (): React.ReactNode => { ); }; -CheckboxDefaultChecked.storyName = 'Checkbox - defaultChecked'; +CheckboxDefaultChecked.storyName = "Checkbox - defaultChecked"; export const CheckboxRequired = (): React.ReactNode => { return ( @@ -76,7 +76,7 @@ export const CheckboxRequired = (): React.ReactNode => { ); }; -CheckboxRequired.storyName = 'Checkbox - Required'; +CheckboxRequired.storyName = "Checkbox - Required"; export const CheckboxDisabled = (): React.ReactNode => { return ( @@ -86,7 +86,7 @@ export const CheckboxDisabled = (): React.ReactNode => { ); }; -CheckboxDisabled.storyName = 'Checkbox - Disabled'; +CheckboxDisabled.storyName = "Checkbox - Disabled"; export const CheckboxDisabledChecked = (): React.ReactNode => { const [checked, setChecked] = React.useState(true); @@ -106,7 +106,7 @@ export const CheckboxDisabledChecked = (): React.ReactNode => { ); }; -CheckboxDisabledChecked.storyName = 'Checkbox - Disabled & Checked'; +CheckboxDisabledChecked.storyName = "Checkbox - Disabled & Checked"; export const CheckboxError = (): React.ReactNode => { return ( @@ -116,7 +116,7 @@ export const CheckboxError = (): React.ReactNode => { ); }; -CheckboxError.storyName = 'Checkbox - Error'; +CheckboxError.storyName = "Checkbox - Error"; export const CheckboxErrorChecked = (): React.ReactNode => { const [checked, setChecked] = React.useState(true); @@ -136,7 +136,7 @@ export const CheckboxErrorChecked = (): React.ReactNode => { ); }; -CheckboxErrorChecked.storyName = 'Checkbox - Error & Checked'; +CheckboxErrorChecked.storyName = "Checkbox - Error & Checked"; export const CheckboxErrorDisabled = (): React.ReactNode => { return ( @@ -146,7 +146,7 @@ export const CheckboxErrorDisabled = (): React.ReactNode => { ); }; -CheckboxErrorDisabled.storyName = 'Checkbox - Error & Disabled'; +CheckboxErrorDisabled.storyName = "Checkbox - Error & Disabled"; export const CheckboxErrorDisabledChecked = (): React.ReactNode => { return ( @@ -156,7 +156,7 @@ export const CheckboxErrorDisabledChecked = (): React.ReactNode => { ); }; -CheckboxErrorDisabledChecked.storyName = 'Checkbox - Error & Disabled & Checked'; +CheckboxErrorDisabledChecked.storyName = "Checkbox - Error & Disabled & Checked"; export const CheckboxHelpTextString = (): React.ReactNode => { return ( @@ -166,7 +166,7 @@ export const CheckboxHelpTextString = (): React.ReactNode => { ); }; -CheckboxHelpTextString.storyName = 'Checkbox - Help text string'; +CheckboxHelpTextString.storyName = "Checkbox - Help text string"; export const CheckboxHelpTextChildren = (): React.ReactNode => { return ( @@ -185,7 +185,7 @@ export const CheckboxHelpTextChildren = (): React.ReactNode => { ); }; -CheckboxHelpTextChildren.storyName = 'Checkbox - Help text children'; +CheckboxHelpTextChildren.storyName = "Checkbox - Help text children"; export const CheckboxSelectAll = (): React.ReactNode => { const [checked, setChecked] = React.useState(true); @@ -205,7 +205,7 @@ export const CheckboxSelectAll = (): React.ReactNode => { ); }; -CheckboxSelectAll.storyName = 'Checkbox - Select all'; +CheckboxSelectAll.storyName = "Checkbox - Select all"; export const CheckboxControlled = (): React.ReactNode => { const [checked1, setChecked1] = React.useState(true); @@ -250,7 +250,7 @@ export const CheckboxControlled = (): React.ReactNode => { ); }; -CheckboxControlled.storyName = 'Checkbox - Controlled'; +CheckboxControlled.storyName = "Checkbox - Controlled"; export const DefaultCheckboxGroup = (): React.ReactNode => { const [checked1, setChecked1] = React.useState(true); @@ -310,7 +310,7 @@ export const DefaultCheckboxGroup = (): React.ReactNode => { ); }; -DefaultCheckboxGroup.storyName = 'CheckboxGroup'; +DefaultCheckboxGroup.storyName = "CheckboxGroup"; export const CheckboxGroupError = (): React.ReactNode => { return ( @@ -328,7 +328,7 @@ export const CheckboxGroupError = (): React.ReactNode => { ); }; -CheckboxGroupError.storyName = 'Checkbox Group - Error'; +CheckboxGroupError.storyName = "Checkbox Group - Error"; export const CheckboxGroupDisabled = (): React.ReactNode => { return ( @@ -346,7 +346,7 @@ export const CheckboxGroupDisabled = (): React.ReactNode => { ); }; -CheckboxGroupDisabled.storyName = 'Checkbox Group - Disabled'; +CheckboxGroupDisabled.storyName = "Checkbox Group - Disabled"; export const CheckboxGroupOverrideDisabled = (): React.ReactNode => { return ( @@ -364,7 +364,7 @@ export const CheckboxGroupOverrideDisabled = (): React.ReactNode => { ); }; -CheckboxGroupOverrideDisabled.storyName = 'Checkbox Group - Override Disabled'; +CheckboxGroupOverrideDisabled.storyName = "Checkbox Group - Override Disabled"; export const CheckboxGroupHorizontal = (): React.ReactNode => { return ( @@ -388,7 +388,7 @@ export const CheckboxGroupHorizontal = (): React.ReactNode => { ); }; -CheckboxGroupHorizontal.storyName = 'Checkbox Group - Horizontal'; +CheckboxGroupHorizontal.storyName = "Checkbox Group - Horizontal"; export const CheckboxGroupHorizontalDisabled = (): React.ReactNode => { return ( @@ -406,7 +406,7 @@ export const CheckboxGroupHorizontalDisabled = (): React.ReactNode => { ); }; -CheckboxGroupHorizontalDisabled.storyName = 'Checkbox Group - Horizontal disabled'; +CheckboxGroupHorizontalDisabled.storyName = "Checkbox Group - Horizontal disabled"; export const CheckboxGroupHorizontalError = (): React.ReactNode => { return ( @@ -436,7 +436,7 @@ export const CheckboxGroupHorizontalError = (): React.ReactNode => { ); }; -CheckboxGroupHorizontalError.storyName = 'Checkbox Group - Horizontal error'; +CheckboxGroupHorizontalError.storyName = "Checkbox Group - Horizontal error"; export const CheckboxIndeterminateGroup = (): React.ReactNode => { const [checkedItems, setCheckedItems] = React.useState([true, false]); @@ -475,7 +475,7 @@ export const CheckboxIndeterminateGroup = (): React.ReactNode => { ); }; -CheckboxIndeterminateGroup.storyName = 'Checkbox - Indeterminate group'; +CheckboxIndeterminateGroup.storyName = "Checkbox - Indeterminate group"; export const CheckboxIndeterminateGroupDisabled = (): React.ReactNode => { const [checkedItems, setCheckedItems] = React.useState([true, false]); @@ -554,7 +554,7 @@ export const CheckboxIndeterminateGroupDisabled = (): React.ReactNode => { ); }; -CheckboxIndeterminateGroupDisabled.storyName = 'Checkbox - Indeterminate group disabled'; +CheckboxIndeterminateGroupDisabled.storyName = "Checkbox - Indeterminate group disabled"; export const CheckboxIndeterminateHorizontalGroup = (): React.ReactNode => { const [checkedItems, setCheckedItems] = React.useState([true, false]); @@ -593,7 +593,7 @@ export const CheckboxIndeterminateHorizontalGroup = (): React.ReactNode => { ); }; -CheckboxIndeterminateHorizontalGroup.storyName = 'Checkbox - Indeterminate horizontal group'; +CheckboxIndeterminateHorizontalGroup.storyName = "Checkbox - Indeterminate horizontal group"; export const DefaultCheckboxDisclaimer = (): React.ReactNode => { return ( @@ -608,7 +608,7 @@ export const DefaultCheckboxDisclaimer = (): React.ReactNode => { ); }; -DefaultCheckboxDisclaimer.storyName = 'Checkbox Disclaimer'; +DefaultCheckboxDisclaimer.storyName = "Checkbox Disclaimer"; export const CheckboxDisclaimerRequired = (): React.ReactNode => { return ( @@ -623,7 +623,7 @@ export const CheckboxDisclaimerRequired = (): React.ReactNode => { ); }; -CheckboxDisclaimerRequired.storyName = 'Checkbox Disclaimer - Required'; +CheckboxDisclaimerRequired.storyName = "Checkbox Disclaimer - Required"; export const CheckboxDisclaimerError = (): React.ReactNode => { return ( @@ -638,7 +638,7 @@ export const CheckboxDisclaimerError = (): React.ReactNode => { ); }; -CheckboxDisclaimerError.storyName = 'Checkbox Disclaimer - Error'; +CheckboxDisclaimerError.storyName = "Checkbox Disclaimer - Error"; export const CheckboxDisclaimerDisabled = (): React.ReactNode => { return ( @@ -651,4 +651,4 @@ export const CheckboxDisclaimerDisabled = (): React.ReactNode => { ); }; -CheckboxDisclaimerDisabled.storyName = 'Checkbox Disclaimer - Disabled'; +CheckboxDisclaimerDisabled.storyName = "Checkbox Disclaimer - Disabled"; diff --git a/packages/paste-core/components/checkbox/stories/customization.stories.tsx b/packages/paste-core/components/checkbox/stories/customization.stories.tsx index 934d4ccba3..26ffcd54fa 100644 --- a/packages/paste-core/components/checkbox/stories/customization.stories.tsx +++ b/packages/paste-core/components/checkbox/stories/customization.stories.tsx @@ -1,15 +1,15 @@ -import * as React from 'react'; -import type {StoryFn} from '@storybook/react'; -import {useUID} from '@twilio-paste/uid-library'; -import {Anchor} from '@twilio-paste/anchor'; -import {Text} from '@twilio-paste/text'; -import {Paragraph} from '@twilio-paste/paragraph'; -import {useTheme} from '@twilio-paste/theme'; -import {CustomizationProvider} from '@twilio-paste/customization'; +import type { StoryFn } from "@storybook/react"; +import { Anchor } from "@twilio-paste/anchor"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import { Paragraph } from "@twilio-paste/paragraph"; +import { Text } from "@twilio-paste/text"; +import { useTheme } from "@twilio-paste/theme"; +import { useUID } from "@twilio-paste/uid-library"; +import * as React from "react"; -import {Checkbox, CheckboxGroup, CheckboxDisclaimer} from '../src'; +import { Checkbox, CheckboxDisclaimer, CheckboxGroup } from "../src"; -export const CustomizedCheckboxGroup: StoryFn = (_args, {parameters: {isTestEnvironment}}) => { +export const CustomizedCheckboxGroup: StoryFn = (_args, { parameters: { isTestEnvironment } }) => { const [checked1, setChecked1] = React.useState(true); const [checked2, setChecked2] = React.useState(false); const [checked3, setChecked3] = React.useState(false); @@ -23,19 +23,19 @@ export const CustomizedCheckboxGroup: StoryFn = (_args, {parameters: {isTestEnvi disableAnimations={isTestEnvironment} theme={theme} elements={{ - CHECKBOX_GROUP: {padding: 'space30'}, - CHECKBOX_GROUP_SET: {marginLeft: 'space60'}, - CHECKBOX_GROUP_ITEM: {marginBottom: 'space60'}, - CHECKBOX_GROUP_ERROR_TEXT_WRAPPER: {marginBottom: 'space60'}, - CHECKBOX: {padding: 'space30'}, // the whole box - CHECKBOX_CONTROL: {borderRadius: 'borderRadius20'}, - CHECKBOX_LABEL_TEXT: {color: 'colorTextNeutral'}, - MY_CHECKBOX_GROUP: {padding: 'space30'}, - MY_CHECKBOX_GROUP_SET: {marginLeft: 'space60'}, - MY_CHECKBOX_GROUP_ITEM: {marginBottom: 'space60'}, - MY_CHECKBOX: {padding: 'space30'}, // the whole box - MY_CHECKBOX_CONTROL: {borderRadius: 'borderRadius20'}, - MY_CHECKBOX_LABEL_TEXT: {color: 'colorTextNeutral'}, + CHECKBOX_GROUP: { padding: "space30" }, + CHECKBOX_GROUP_SET: { marginLeft: "space60" }, + CHECKBOX_GROUP_ITEM: { marginBottom: "space60" }, + CHECKBOX_GROUP_ERROR_TEXT_WRAPPER: { marginBottom: "space60" }, + CHECKBOX: { padding: "space30" }, // the whole box + CHECKBOX_CONTROL: { borderRadius: "borderRadius20" }, + CHECKBOX_LABEL_TEXT: { color: "colorTextNeutral" }, + MY_CHECKBOX_GROUP: { padding: "space30" }, + MY_CHECKBOX_GROUP_SET: { marginLeft: "space60" }, + MY_CHECKBOX_GROUP_ITEM: { marginBottom: "space60" }, + MY_CHECKBOX: { padding: "space30" }, // the whole box + MY_CHECKBOX_CONTROL: { borderRadius: "borderRadius20" }, + MY_CHECKBOX_LABEL_TEXT: { color: "colorTextNeutral" }, }} > Using default element name: @@ -146,17 +146,17 @@ export const CustomizedCheckboxGroup: StoryFn = (_args, {parameters: {isTestEnvi ); }; -export const CustomizedCheckboxDisclaimer: StoryFn = (_args, {parameters: {isTestEnvironment}}) => { +export const CustomizedCheckboxDisclaimer: StoryFn = (_args, { parameters: { isTestEnvironment } }) => { const theme = useTheme(); return ( Using default element name: @@ -190,7 +190,7 @@ export const CustomizedCheckboxDisclaimer: StoryFn = (_args, {parameters: {isTes // eslint-disable-next-line import/no-default-export export default { - title: 'Components/Checkbox/Customization', + title: "Components/Checkbox/Customization", component: CustomizedCheckboxGroup, parameters: { a11y: { diff --git a/packages/paste-core/components/code-block/__tests__/customization.spec.tsx b/packages/paste-core/components/code-block/__tests__/customization.spec.tsx index 34036a90e2..49cf357aa9 100644 --- a/packages/paste-core/components/code-block/__tests__/customization.spec.tsx +++ b/packages/paste-core/components/code-block/__tests__/customization.spec.tsx @@ -1,54 +1,61 @@ -import * as React from 'react'; -import {CustomizationProvider} from '@twilio-paste/customization'; -import {render, screen} from '@testing-library/react'; - -import {CodeBlock, CodeBlockWrapper, CodeBlockHeader, CodeBlockTabList, CodeBlockTab, CodeBlockTabPanel} from '../src'; +import { render, screen } from "@testing-library/react"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import * as React from "react"; + +import { + CodeBlock, + CodeBlockHeader, + CodeBlockTab, + CodeBlockTabList, + CodeBlockTabPanel, + CodeBlockWrapper, +} from "../src"; const jsCode = `(num) => num + 1`; -const CustomizationWrapper: React.FC = ({children}) => ( +const CustomizationWrapper: React.FC = ({ children }) => ( {children} ); -const CustomizationMyWrapper: React.FC = ({children}) => ( +const CustomizationMyWrapper: React.FC = ({ children }) => ( {children} ); -describe('Customization', () => { - describe('CodeBlock', () => { - it('should set a default element data attribute', () => { +describe("Customization", () => { + describe("CodeBlock", () => { + it("should set a default element data attribute", () => { render( My code block @@ -61,31 +68,31 @@ describe('Customization', () => { , { wrapper: CustomizationWrapper, - } + }, ); - const codeBlock = screen.getByTestId('code-block'); - const content = codeBlock.querySelector('pre')?.parentElement; - const heading = screen.getByRole('heading', {name: 'My code block'}); + const codeBlock = screen.getByTestId("code-block"); + const content = codeBlock.querySelector("pre")?.parentElement; + const heading = screen.getByRole("heading", { name: "My code block" }); const wrapper = heading.parentElement; - const tabList = screen.getByRole('tablist'); - const tab = screen.getByRole('tab', {name: 'JavaScript'}); + const tabList = screen.getByRole("tablist"); + const tab = screen.getByRole("tab", { name: "JavaScript" }); const tabPanel = codeBlock.parentElement; - const copyButton = screen.getByRole('button', {name: 'Copy code block'}); - const externalLink = screen.getByRole('link', {name: 'Open code block in new page'}); - - expect(wrapper?.getAttribute('data-paste-element')).toBe('CODE_BLOCK_WRAPPER'); - expect(content?.getAttribute('data-paste-element')).toBe('CODE_BLOCK_CONTENT'); - expect(tabList.getAttribute('data-paste-element')).toBe('CODE_BLOCK_TAB_LIST'); - expect(tab.getAttribute('data-paste-element')).toBe('CODE_BLOCK_TAB'); - expect(tabPanel?.getAttribute('data-paste-element')).toBe('CODE_BLOCK_TAB_PANEL'); - expect(codeBlock.getAttribute('data-paste-element')).toBe('CODE_BLOCK'); - expect(heading.getAttribute('data-paste-element')).toBe('CODE_BLOCK_HEADER'); - expect(copyButton.getAttribute('data-paste-element')).toBe('CODE_BLOCK_COPY_BUTTON'); - expect(externalLink.getAttribute('data-paste-element')).toBe('CODE_BLOCK_EXTERNAL_LINK'); + const copyButton = screen.getByRole("button", { name: "Copy code block" }); + const externalLink = screen.getByRole("link", { name: "Open code block in new page" }); + + expect(wrapper?.getAttribute("data-paste-element")).toBe("CODE_BLOCK_WRAPPER"); + expect(content?.getAttribute("data-paste-element")).toBe("CODE_BLOCK_CONTENT"); + expect(tabList.getAttribute("data-paste-element")).toBe("CODE_BLOCK_TAB_LIST"); + expect(tab.getAttribute("data-paste-element")).toBe("CODE_BLOCK_TAB"); + expect(tabPanel?.getAttribute("data-paste-element")).toBe("CODE_BLOCK_TAB_PANEL"); + expect(codeBlock.getAttribute("data-paste-element")).toBe("CODE_BLOCK"); + expect(heading.getAttribute("data-paste-element")).toBe("CODE_BLOCK_HEADER"); + expect(copyButton.getAttribute("data-paste-element")).toBe("CODE_BLOCK_COPY_BUTTON"); + expect(externalLink.getAttribute("data-paste-element")).toBe("CODE_BLOCK_EXTERNAL_LINK"); }); - it('should set a custom element data attribute', () => { + it("should set a custom element data attribute", () => { render( My code block @@ -104,31 +111,31 @@ describe('Customization', () => { , { wrapper: CustomizationMyWrapper, - } + }, ); - const codeBlock = screen.getByTestId('code-block'); - const content = codeBlock.querySelector('pre')?.parentElement; - const heading = screen.getByRole('heading', {name: 'My code block'}); + const codeBlock = screen.getByTestId("code-block"); + const content = codeBlock.querySelector("pre")?.parentElement; + const heading = screen.getByRole("heading", { name: "My code block" }); const wrapper = heading.parentElement; - const tabList = screen.getByRole('tablist'); - const tab = screen.getByRole('tab', {name: 'JavaScript'}); + const tabList = screen.getByRole("tablist"); + const tab = screen.getByRole("tab", { name: "JavaScript" }); const tabPanel = codeBlock.parentElement; - const copyButton = screen.getByRole('button', {name: 'Copy code block'}); - const externalLink = screen.getByRole('link', {name: 'Open code block in new page'}); - - expect(wrapper?.getAttribute('data-paste-element')).toBe('MY_CODE_BLOCK_WRAPPER'); - expect(content?.getAttribute('data-paste-element')).toBe('MY_CODE_BLOCK_CONTENT'); - expect(tabList.getAttribute('data-paste-element')).toBe('MY_CODE_BLOCK_TAB_LIST'); - expect(tab.getAttribute('data-paste-element')).toBe('MY_CODE_BLOCK_TAB'); - expect(tabPanel?.getAttribute('data-paste-element')).toBe('MY_CODE_BLOCK_TAB_PANEL'); - expect(codeBlock.getAttribute('data-paste-element')).toBe('MY_CODE_BLOCK'); - expect(heading.getAttribute('data-paste-element')).toBe('MY_CODE_BLOCK_HEADER'); - expect(copyButton.getAttribute('data-paste-element')).toBe('MY_CODE_BLOCK_COPY_BUTTON'); - expect(externalLink.getAttribute('data-paste-element')).toBe('MY_CODE_BLOCK_EXTERNAL_LINK'); + const copyButton = screen.getByRole("button", { name: "Copy code block" }); + const externalLink = screen.getByRole("link", { name: "Open code block in new page" }); + + expect(wrapper?.getAttribute("data-paste-element")).toBe("MY_CODE_BLOCK_WRAPPER"); + expect(content?.getAttribute("data-paste-element")).toBe("MY_CODE_BLOCK_CONTENT"); + expect(tabList.getAttribute("data-paste-element")).toBe("MY_CODE_BLOCK_TAB_LIST"); + expect(tab.getAttribute("data-paste-element")).toBe("MY_CODE_BLOCK_TAB"); + expect(tabPanel?.getAttribute("data-paste-element")).toBe("MY_CODE_BLOCK_TAB_PANEL"); + expect(codeBlock.getAttribute("data-paste-element")).toBe("MY_CODE_BLOCK"); + expect(heading.getAttribute("data-paste-element")).toBe("MY_CODE_BLOCK_HEADER"); + expect(copyButton.getAttribute("data-paste-element")).toBe("MY_CODE_BLOCK_COPY_BUTTON"); + expect(externalLink.getAttribute("data-paste-element")).toBe("MY_CODE_BLOCK_EXTERNAL_LINK"); }); - it('should add custom styles to the component', () => { + it("should add custom styles to the component", () => { render( My code block @@ -141,31 +148,31 @@ describe('Customization', () => { , { wrapper: CustomizationWrapper, - } + }, ); - const codeBlock = screen.getByTestId('code-block'); - const content = codeBlock.querySelector('pre')?.parentElement; - const heading = screen.getByRole('heading', {name: 'My code block'}); + const codeBlock = screen.getByTestId("code-block"); + const content = codeBlock.querySelector("pre")?.parentElement; + const heading = screen.getByRole("heading", { name: "My code block" }); const wrapper = heading.parentElement; - const tabList = screen.getByRole('tablist'); - const tab = screen.getByRole('tab', {name: 'JavaScript'}); + const tabList = screen.getByRole("tablist"); + const tab = screen.getByRole("tab", { name: "JavaScript" }); const tabPanel = codeBlock.parentElement; - const copyButton = screen.getByRole('button', {name: 'Copy code block'}); - const externalLink = screen.getByRole('link', {name: 'Open code block in new page'}); - - expect(codeBlock).toHaveStyleRule('width', '31.5rem'); - expect(content).toHaveStyleRule('width', '31.5rem'); - expect(wrapper).toHaveStyleRule('width', '31.5rem'); - expect(heading).toHaveStyleRule('border-top-right-radius', '8px'); - expect(tabList).toHaveStyleRule('column-gap', '0'); - expect(tab).toHaveStyleRule('border-radius', '0'); - expect(tabPanel).toHaveStyleRule('border-bottom-right-radius', '8px'); - expect(copyButton).toHaveStyleRule('background-color', 'rgb(254, 236, 236)'); - expect(externalLink).toHaveStyleRule('background-color', 'rgb(254, 236, 236)'); + const copyButton = screen.getByRole("button", { name: "Copy code block" }); + const externalLink = screen.getByRole("link", { name: "Open code block in new page" }); + + expect(codeBlock).toHaveStyleRule("width", "31.5rem"); + expect(content).toHaveStyleRule("width", "31.5rem"); + expect(wrapper).toHaveStyleRule("width", "31.5rem"); + expect(heading).toHaveStyleRule("border-top-right-radius", "8px"); + expect(tabList).toHaveStyleRule("column-gap", "0"); + expect(tab).toHaveStyleRule("border-radius", "0"); + expect(tabPanel).toHaveStyleRule("border-bottom-right-radius", "8px"); + expect(copyButton).toHaveStyleRule("background-color", "rgb(254, 236, 236)"); + expect(externalLink).toHaveStyleRule("background-color", "rgb(254, 236, 236)"); }); - it('should set custom styles with custom element names', () => { + it("should set custom styles with custom element names", () => { render( My code block @@ -184,28 +191,28 @@ describe('Customization', () => { , { wrapper: CustomizationMyWrapper, - } + }, ); - const codeBlock = screen.getByTestId('code-block'); - const content = codeBlock.querySelector('pre')?.parentElement; - const heading = screen.getByRole('heading', {name: 'My code block'}); + const codeBlock = screen.getByTestId("code-block"); + const content = codeBlock.querySelector("pre")?.parentElement; + const heading = screen.getByRole("heading", { name: "My code block" }); const wrapper = heading.parentElement; - const tabList = screen.getByRole('tablist'); - const tab = screen.getByRole('tab', {name: 'JavaScript'}); + const tabList = screen.getByRole("tablist"); + const tab = screen.getByRole("tab", { name: "JavaScript" }); const tabPanel = codeBlock.parentElement; - const copyButton = screen.getByRole('button', {name: 'Copy code block'}); - const externalLink = screen.getByRole('link', {name: 'Open code block in new page'}); - - expect(codeBlock).toHaveStyleRule('width', '31.5rem'); - expect(content).toHaveStyleRule('width', '31.5rem'); - expect(wrapper).toHaveStyleRule('width', '31.5rem'); - expect(heading).toHaveStyleRule('border-top-right-radius', '8px'); - expect(tabList).toHaveStyleRule('column-gap', '0'); - expect(tab).toHaveStyleRule('border-radius', '0'); - expect(tabPanel).toHaveStyleRule('border-bottom-right-radius', '8px'); - expect(copyButton).toHaveStyleRule('background-color', 'rgb(254, 236, 236)'); - expect(externalLink).toHaveStyleRule('background-color', 'rgb(254, 236, 236)'); + const copyButton = screen.getByRole("button", { name: "Copy code block" }); + const externalLink = screen.getByRole("link", { name: "Open code block in new page" }); + + expect(codeBlock).toHaveStyleRule("width", "31.5rem"); + expect(content).toHaveStyleRule("width", "31.5rem"); + expect(wrapper).toHaveStyleRule("width", "31.5rem"); + expect(heading).toHaveStyleRule("border-top-right-radius", "8px"); + expect(tabList).toHaveStyleRule("column-gap", "0"); + expect(tab).toHaveStyleRule("border-radius", "0"); + expect(tabPanel).toHaveStyleRule("border-bottom-right-radius", "8px"); + expect(copyButton).toHaveStyleRule("background-color", "rgb(254, 236, 236)"); + expect(externalLink).toHaveStyleRule("background-color", "rgb(254, 236, 236)"); }); }); }); diff --git a/packages/paste-core/components/code-block/__tests__/index.spec.tsx b/packages/paste-core/components/code-block/__tests__/index.spec.tsx index 54c85c0c25..92f95c7256 100644 --- a/packages/paste-core/components/code-block/__tests__/index.spec.tsx +++ b/packages/paste-core/components/code-block/__tests__/index.spec.tsx @@ -1,10 +1,17 @@ -import * as React from 'react'; -import {render, screen} from '@testing-library/react'; -import {Theme} from '@twilio-paste/theme'; - -import {CopyButton, getCopyButtonText} from '../src/CopyButton'; -import {ExternalLinkButton} from '../src/ExternalLinkButton'; -import {CodeBlock, CodeBlockWrapper, CodeBlockHeader, CodeBlockTabList, CodeBlockTab, CodeBlockTabPanel} from '../src'; +import { render, screen } from "@testing-library/react"; +import { Theme } from "@twilio-paste/theme"; +import * as React from "react"; + +import { + CodeBlock, + CodeBlockHeader, + CodeBlockTab, + CodeBlockTabList, + CodeBlockTabPanel, + CodeBlockWrapper, +} from "../src"; +import { CopyButton, getCopyButtonText } from "../src/CopyButton"; +import { ExternalLinkButton } from "../src/ExternalLinkButton"; const jsCode = `(num) => num + 1`; @@ -27,37 +34,37 @@ lab = TkLabel.new(root) { } `; -describe('CodeBlock', () => { - it('should render', () => { +describe("CodeBlock", () => { + it("should render", () => { render( - + , ); - const copyButton = screen.getByRole('button', {name: 'Copy code block'}); + const copyButton = screen.getByRole("button", { name: "Copy code block" }); expect(copyButton).toBeDefined(); - const rubyText = screen.getByText('#!/usr/bin/ruby'); + const rubyText = screen.getByText("#!/usr/bin/ruby"); expect(rubyText).toBeDefined(); }); - it('should render a code block with a link', () => { + it("should render a code block with a link", () => { render( - + , ); - const copyButton = screen.getByRole('button', {name: 'Copy code block'}); + const copyButton = screen.getByRole("button", { name: "Copy code block" }); expect(copyButton).toBeDefined(); - const link = screen.getByRole('link', {name: 'Open code block in new page'}); + const link = screen.getByRole("link", { name: "Open code block in new page" }); expect(link).toBeDefined(); }); - describe('i18n', () => { - it('should use i18n labels for copy button and external link', () => { + describe("i18n", () => { + it("should use i18n labels for copy button and external link", () => { render( { i18nCopyLabelBefore="before" i18nLinkLabel="external link" /> - + , ); - const copyButton = screen.getByRole('button', {name: 'before'}); + const copyButton = screen.getByRole("button", { name: "before" }); expect(copyButton).toBeDefined(); - const link = screen.getByRole('link', {name: 'external link'}); + const link = screen.getByRole("link", { name: "external link" }); expect(link).toBeDefined(); }); }); }); -describe('CodeBlockHeader', () => { - it('should render a heading', () => { +describe("CodeBlockHeader", () => { + it("should render a heading", () => { render( <> My code block Another code block - + , ); - const headerLevel3 = screen.getByRole('heading', {name: 'My code block'}); + const headerLevel3 = screen.getByRole("heading", { name: "My code block" }); expect(headerLevel3).toBeDefined(); - expect(headerLevel3.tagName).toBe('H3'); + expect(headerLevel3.tagName).toBe("H3"); - const headerLevel2 = screen.getByRole('heading', {name: 'Another code block'}); + const headerLevel2 = screen.getByRole("heading", { name: "Another code block" }); expect(headerLevel2).toBeDefined(); - expect(headerLevel2.tagName).toBe('H2'); + expect(headerLevel2.tagName).toBe("H2"); }); }); -describe('CodeBlockTabs', () => { - it('should render an accessible tab set', () => { +describe("CodeBlockTabs", () => { + it("should render an accessible tab set", () => { render( @@ -115,70 +122,70 @@ describe('CodeBlockTabs', () => { - + , ); - const tablist = screen.getByRole('tablist'); + const tablist = screen.getByRole("tablist"); expect(tablist).toBeDefined(); - const javascriptTab = screen.getByRole('tab', {name: 'JavaScript'}); + const javascriptTab = screen.getByRole("tab", { name: "JavaScript" }); expect(javascriptTab).toBeDefined(); - expect(javascriptTab.getAttribute('aria-selected')).toBe('true'); + expect(javascriptTab.getAttribute("aria-selected")).toBe("true"); - const javascriptTabPanel = screen.getByTestId('js-block').parentElement; + const javascriptTabPanel = screen.getByTestId("js-block").parentElement; expect(javascriptTabPanel).toBeDefined(); - expect(javascriptTab.getAttribute('aria-controls')).toBe(javascriptTabPanel?.id); - expect(javascriptTabPanel?.getAttribute('aria-labelledby')).toBe(javascriptTab.id); + expect(javascriptTab.getAttribute("aria-controls")).toBe(javascriptTabPanel?.id); + expect(javascriptTabPanel?.getAttribute("aria-labelledby")).toBe(javascriptTab.id); - const rubyTab = screen.getByRole('tab', {name: 'Ruby'}); + const rubyTab = screen.getByRole("tab", { name: "Ruby" }); expect(rubyTab).toBeDefined(); - expect(rubyTab.getAttribute('aria-selected')).toBe('false'); + expect(rubyTab.getAttribute("aria-selected")).toBe("false"); - const rubyTabPanel = screen.getByTestId('ruby-block').parentElement; + const rubyTabPanel = screen.getByTestId("ruby-block").parentElement; expect(rubyTabPanel).toBeDefined(); - expect(rubyTab.getAttribute('aria-controls')).toBe(rubyTabPanel?.id); - expect(rubyTabPanel?.getAttribute('aria-labelledby')).toBe(rubyTab.id); + expect(rubyTab.getAttribute("aria-controls")).toBe(rubyTabPanel?.id); + expect(rubyTabPanel?.getAttribute("aria-labelledby")).toBe(rubyTab.id); }); }); -describe('CopyButton', () => { - it('should render', () => { +describe("CopyButton", () => { + it("should render", () => { render( - + , ); - const button = screen.getByRole('button'); - const tooltip = screen.getByRole('tooltip', {hidden: true}); + const button = screen.getByRole("button"); + const tooltip = screen.getByRole("tooltip", { hidden: true }); expect(button).toBeDefined(); expect(tooltip).not.toBeVisible(); }); - describe('getCopyButtonText', () => { - it('returns the correct string depending on the copied arg', () => { - const getText = getCopyButtonText('before', 'after'); + describe("getCopyButtonText", () => { + it("returns the correct string depending on the copied arg", () => { + const getText = getCopyButtonText("before", "after"); - expect(getText(false)).toBe('before'); - expect(getText(true)).toBe('after'); + expect(getText(false)).toBe("before"); + expect(getText(true)).toBe("after"); }); }); }); -describe('ExternalLinkButton', () => { - it('should render', () => { +describe("ExternalLinkButton", () => { + it("should render", () => { render( - + , ); - const link = screen.getByRole('link'); - const tooltip = screen.getByRole('tooltip', {hidden: true}); + const link = screen.getByRole("link"); + const tooltip = screen.getByRole("tooltip", { hidden: true }); expect(link).toBeDefined(); - expect(link.getAttribute('href')).toBe('https://www.google.com'); + expect(link.getAttribute("href")).toBe("https://www.google.com"); expect(tooltip).not.toBeVisible(); }); }); diff --git a/packages/paste-core/components/code-block/build.js b/packages/paste-core/components/code-block/build.js index a4edeab49b..27dd98f98e 100644 --- a/packages/paste-core/components/code-block/build.js +++ b/packages/paste-core/components/code-block/build.js @@ -1,3 +1,3 @@ -const {build} = require('../../../../tools/build/esbuild'); +const { build } = require("../../../../tools/build/esbuild"); -build(require('./package.json')); +build(require("./package.json")); diff --git a/packages/paste-core/components/code-block/src/CodeBlock.tsx b/packages/paste-core/components/code-block/src/CodeBlock.tsx index cdad3ec45e..217a315e89 100644 --- a/packages/paste-core/components/code-block/src/CodeBlock.tsx +++ b/packages/paste-core/components/code-block/src/CodeBlock.tsx @@ -1,21 +1,21 @@ -import * as React from 'react'; -import {SyntaxHighlighter} from '@twilio-paste/syntax-highlighter-library'; -import type {SnippetLanguages} from '@twilio-paste/syntax-highlighter-library'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxProps, BoxStyleProps} from '@twilio-paste/box'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps, BoxStyleProps } from "@twilio-paste/box"; +import { SyntaxHighlighter } from "@twilio-paste/syntax-highlighter-library"; +import type { SnippetLanguages } from "@twilio-paste/syntax-highlighter-library"; +import * as React from "react"; -import {getPasteSyntaxTheme} from './CodeBlockTheme'; -import {CopyButton} from './CopyButton'; -import {ExternalLinkButton} from './ExternalLinkButton'; +import { getPasteSyntaxTheme } from "./CodeBlockTheme"; +import { CopyButton } from "./CopyButton"; +import { ExternalLinkButton } from "./ExternalLinkButton"; -type CodeBlockVariants = 'multi-line' | 'single-line'; +type CodeBlockVariants = "multi-line" | "single-line"; -export interface CodeBlockProps extends Partial> { +export interface CodeBlockProps extends Partial> { children?: never; language: SnippetLanguages; code: string; variant?: CodeBlockVariants; - element?: BoxProps['element']; + element?: BoxProps["element"]; showLineNumbers?: boolean; wrapLines?: boolean; maxLines?: number; @@ -27,29 +27,29 @@ export interface CodeBlockProps extends Partial } const CodeBlockVariantStyles: Record = { - 'single-line': { - gridTemplateColumns: '1fr auto', + "single-line": { + gridTemplateColumns: "1fr auto", gridTemplateAreas: '"code-block button-group"', - columnGap: 'space40', - borderRadius: 'borderRadius20', - paddingY: 'space60', + columnGap: "space40", + borderRadius: "borderRadius20", + paddingY: "space60", }, - 'multi-line': { - gridTemplateRows: 'auto 1fr', + "multi-line": { + gridTemplateRows: "auto 1fr", gridTemplateAreas: '"button-group" "code-block"', - rowGap: 'space20', - paddingTop: 'space50', - paddingBottom: 'space90', + rowGap: "space20", + paddingTop: "space50", + paddingBottom: "space90", }, }; export const CodeBlock = React.forwardRef( ( { - element = 'CODE_BLOCK', + element = "CODE_BLOCK", language, code, - variant = 'multi-line', + variant = "multi-line", showLineNumbers, wrapLines, maxLines, @@ -60,7 +60,7 @@ export const CodeBlock = React.forwardRef( copyTextFormatter, ...props }, - ref + ref, ) => { return ( ( flexDirection="row" alignItems="center" columnGap="space40" - justifyContent={variant === 'multi-line' ? 'flex-end' : undefined} + justifyContent={variant === "multi-line" ? "flex-end" : undefined} gridArea="button-group" > @@ -117,7 +117,7 @@ export const CodeBlock = React.forwardRef( ); - } + }, ); -CodeBlock.displayName = 'CodeBlock'; +CodeBlock.displayName = "CodeBlock"; diff --git a/packages/paste-core/components/code-block/src/CodeBlockHeader.tsx b/packages/paste-core/components/code-block/src/CodeBlockHeader.tsx index 75a0618b5f..2f026f41fc 100644 --- a/packages/paste-core/components/code-block/src/CodeBlockHeader.tsx +++ b/packages/paste-core/components/code-block/src/CodeBlockHeader.tsx @@ -1,16 +1,16 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; -import type {asTags} from '@twilio-paste/heading'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import type { asTags } from "@twilio-paste/heading"; +import * as React from "react"; -export interface CodeBlockHeaderProps extends Partial> { +export interface CodeBlockHeaderProps extends Partial> { children: string; - element?: BoxProps['element']; + element?: BoxProps["element"]; as?: asTags; } export const CodeBlockHeader = React.forwardRef( - ({children, element = 'CODE_BLOCK_HEADER', as = 'h3', ...props}, ref) => ( + ({ children, element = "CODE_BLOCK_HEADER", as = "h3", ...props }, ref) => ( {children} - ) + ), ); -CodeBlockHeader.displayName = 'CodeBlockHeader'; +CodeBlockHeader.displayName = "CodeBlockHeader"; diff --git a/packages/paste-core/components/code-block/src/CodeBlockTab.tsx b/packages/paste-core/components/code-block/src/CodeBlockTab.tsx index 59c2c67dc4..a554d30074 100644 --- a/packages/paste-core/components/code-block/src/CodeBlockTab.tsx +++ b/packages/paste-core/components/code-block/src/CodeBlockTab.tsx @@ -1,20 +1,20 @@ -import * as React from 'react'; -import type {BoxProps} from '@twilio-paste/box'; -import {Tab} from '@twilio-paste/tabs'; -import type {TabProps} from '@twilio-paste/tabs'; +import type { BoxProps } from "@twilio-paste/box"; +import { Tab } from "@twilio-paste/tabs"; +import type { TabProps } from "@twilio-paste/tabs"; +import * as React from "react"; export interface CodeBlockTabProps extends TabProps { - element?: BoxProps['element']; + element?: BoxProps["element"]; } export const CodeBlockTab = React.forwardRef( - ({children, element = 'CODE_BLOCK_TAB', ...props}, ref) => { + ({ children, element = "CODE_BLOCK_TAB", ...props }, ref) => { return ( {children} ); - } + }, ); -CodeBlockTab.displayName = 'CodeBlockTab'; +CodeBlockTab.displayName = "CodeBlockTab"; diff --git a/packages/paste-core/components/code-block/src/CodeBlockTabList.tsx b/packages/paste-core/components/code-block/src/CodeBlockTabList.tsx index 3db757dfe5..94da84e5d0 100644 --- a/packages/paste-core/components/code-block/src/CodeBlockTabList.tsx +++ b/packages/paste-core/components/code-block/src/CodeBlockTabList.tsx @@ -1,15 +1,15 @@ -import * as React from 'react'; -import {Box} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; -import {TabList} from '@twilio-paste/tabs'; -import type {TabListProps} from '@twilio-paste/tabs'; +import { Box } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import { TabList } from "@twilio-paste/tabs"; +import type { TabListProps } from "@twilio-paste/tabs"; +import * as React from "react"; -export interface CodeBlockTabListProps extends Omit { - element?: BoxProps['element']; +export interface CodeBlockTabListProps extends Omit { + element?: BoxProps["element"]; } export const CodeBlockTabList = React.forwardRef( - ({children, element = 'CODE_BLOCK_TAB_LIST', ...props}, ref) => { + ({ children, element = "CODE_BLOCK_TAB_LIST", ...props }, ref) => { return ( @@ -17,7 +17,7 @@ export const CodeBlockTabList = React.forwardRef ); - } + }, ); -CodeBlockTabList.displayName = 'CodeBlockTabList'; +CodeBlockTabList.displayName = "CodeBlockTabList"; diff --git a/packages/paste-core/components/code-block/src/CodeBlockTabPanel.tsx b/packages/paste-core/components/code-block/src/CodeBlockTabPanel.tsx index 870fbe423a..11c539b258 100644 --- a/packages/paste-core/components/code-block/src/CodeBlockTabPanel.tsx +++ b/packages/paste-core/components/code-block/src/CodeBlockTabPanel.tsx @@ -1,20 +1,20 @@ -import * as React from 'react'; -import type {BoxProps} from '@twilio-paste/box'; -import {TabPanel} from '@twilio-paste/tabs'; +import type { BoxProps } from "@twilio-paste/box"; +import { TabPanel } from "@twilio-paste/tabs"; +import * as React from "react"; -export interface CodeBlockTabPanelProps extends Partial> { +export interface CodeBlockTabPanelProps extends Partial> { children?: React.ReactNode; - element?: BoxProps['element']; + element?: BoxProps["element"]; } export const CodeBlockTabPanel = React.forwardRef( - ({children, element = 'CODE_BLOCK_TAB_PANEL', ...props}, ref) => { + ({ children, element = "CODE_BLOCK_TAB_PANEL", ...props }, ref) => { return ( {children} ); - } + }, ); -CodeBlockTabPanel.displayName = 'CodeBlockTabPanel'; +CodeBlockTabPanel.displayName = "CodeBlockTabPanel"; diff --git a/packages/paste-core/components/code-block/src/CodeBlockTheme.ts b/packages/paste-core/components/code-block/src/CodeBlockTheme.ts index 9923349655..aecd289c61 100644 --- a/packages/paste-core/components/code-block/src/CodeBlockTheme.ts +++ b/packages/paste-core/components/code-block/src/CodeBlockTheme.ts @@ -1,207 +1,207 @@ -import {css} from '@twilio-paste/styling-library'; -import type {CSSObject} from '@twilio-paste/styling-library'; -import {useTheme} from '@twilio-paste/theme'; +import { css } from "@twilio-paste/styling-library"; +import type { CSSObject } from "@twilio-paste/styling-library"; +import { useTheme } from "@twilio-paste/theme"; export const getPasteSyntaxTheme = (maxLines?: number): CSSObject => { const theme = useTheme(); return css({ 'code[class*="language-"]': { - color: '#d6deeb', - fontFamily: 'fontFamilyCode', - textAlign: 'left', - whiteSpace: 'pre', - wordSpacing: 'normal', - wordBreak: 'normal', - wordWrap: 'normal', - lineHeight: '1.5', - fontSize: '1em', - MozTabSize: '4', - OTabSize: '4', - tabSize: '4', - WebkitHyphens: 'none', - MozHyphens: 'none', - msHyphens: 'none', - hyphens: 'none', + color: "#d6deeb", + fontFamily: "fontFamilyCode", + textAlign: "left", + whiteSpace: "pre", + wordSpacing: "normal", + wordBreak: "normal", + wordWrap: "normal", + lineHeight: "1.5", + fontSize: "1em", + MozTabSize: "4", + OTabSize: "4", + tabSize: "4", + WebkitHyphens: "none", + MozHyphens: "none", + msHyphens: "none", + hyphens: "none", }, 'pre[class*="language-"]': { - color: 'white', - fontFamily: 'fontFamilyCode', - textAlign: 'left', - whiteSpace: 'pre', - wordSpacing: 'normal', - wordBreak: 'normal', - wordWrap: 'normal', - lineHeight: '1.5', - fontSize: '1em', - MozTabSize: '4', - OTabSize: '4', - tabSize: '4', - WebkitHyphens: 'none', - MozHyphens: 'none', - msHyphens: 'none', - hyphens: 'none', - margin: '0', - overflow: 'auto', - background: 'inherit', - display: '-webkit-box', + color: "white", + fontFamily: "fontFamilyCode", + textAlign: "left", + whiteSpace: "pre", + wordSpacing: "normal", + wordBreak: "normal", + wordWrap: "normal", + lineHeight: "1.5", + fontSize: "1em", + MozTabSize: "4", + OTabSize: "4", + tabSize: "4", + WebkitHyphens: "none", + MozHyphens: "none", + msHyphens: "none", + hyphens: "none", + margin: "0", + overflow: "auto", + background: "inherit", + display: "-webkit-box", WebkitLineClamp: `${maxLines}`, - WebkitBoxOrient: 'vertical', - width: '100%', + WebkitBoxOrient: "vertical", + width: "100%", }, 'pre[class*="language-"]::-moz-selection': { - textShadow: 'none', - background: 'inherit', + textShadow: "none", + background: "inherit", }, 'pre[class*="language-"] ::-moz-selection': { - textShadow: 'none', - background: 'inherit', + textShadow: "none", + background: "inherit", }, 'code[class*="language-"]::-moz-selection': { - textShadow: 'none', - background: 'inherit', + textShadow: "none", + background: "inherit", }, 'code[class*="language-"] ::-moz-selection': { - textShadow: 'none', - background: 'inherit', + textShadow: "none", + background: "inherit", }, 'pre[class*="language-"]::selection': { - textShadow: 'none', - background: 'inherit', + textShadow: "none", + background: "inherit", }, 'pre[class*="language-"] ::selection': { - textShadow: 'none', - background: 'inherit', + textShadow: "none", + background: "inherit", }, 'code[class*="language-"]::selection': { - textShadow: 'none', - background: 'inherit', + textShadow: "none", + background: "inherit", }, 'code[class*="language-"] ::selection': { - textShadow: 'none', - background: 'inherit', + textShadow: "none", + background: "inherit", }, ':not(pre) > code[class*="language-"]': { - color: 'white', - background: '#011627', - padding: '0.1em', - borderRadius: '0.3em', - whiteSpace: 'normal', + color: "white", + background: "#011627", + padding: "0.1em", + borderRadius: "0.3em", + whiteSpace: "normal", }, comment: { - color: 'rgb(136, 145, 170)', - fontStyle: 'italic', + color: "rgb(136, 145, 170)", + fontStyle: "italic", }, linenumber: { - color: 'colorTextInverseWeak', - fontStyle: 'none', + color: "colorTextInverseWeak", + fontStyle: "none", }, prolog: { - color: 'rgb(99, 119, 119)', - fontStyle: 'italic', + color: "rgb(99, 119, 119)", + fontStyle: "italic", }, cdata: { - color: 'rgb(99, 119, 119)', - fontStyle: 'italic', + color: "rgb(99, 119, 119)", + fontStyle: "italic", }, punctuation: { - color: 'rgb(199, 146, 234)', + color: "rgb(199, 146, 234)", }, - '.namespace': { - color: 'rgb(178, 204, 214)', + ".namespace": { + color: "rgb(178, 204, 214)", }, deleted: { - color: 'rgba(239, 83, 80, 0.56)', - fontStyle: 'italic', + color: "rgba(239, 83, 80, 0.56)", + fontStyle: "italic", }, symbol: { - color: 'rgb(128, 203, 196)', + color: "rgb(128, 203, 196)", }, property: { - color: 'rgb(128, 203, 196)', + color: "rgb(128, 203, 196)", }, tag: { - color: 'rgb(127, 219, 202)', + color: "rgb(127, 219, 202)", }, operator: { - color: 'rgb(127, 219, 202)', + color: "rgb(127, 219, 202)", }, keyword: { - color: 'rgb(127, 219, 202)', + color: "rgb(127, 219, 202)", }, boolean: { - color: 'rgb(255, 88, 116)', + color: "rgb(255, 88, 116)", }, number: { - color: 'rgb(247, 140, 108)', + color: "rgb(247, 140, 108)", }, constant: { - color: 'rgb(130, 170, 255)', + color: "rgb(130, 170, 255)", }, function: { - color: 'rgb(130, 170, 255)', + color: "rgb(130, 170, 255)", }, builtin: { - color: 'rgb(130, 170, 255)', + color: "rgb(130, 170, 255)", }, char: { - color: 'rgb(130, 170, 255)', + color: "rgb(130, 170, 255)", }, selector: { - color: 'rgb(199, 146, 234)', - fontStyle: 'italic', + color: "rgb(199, 146, 234)", + fontStyle: "italic", }, doctype: { - color: 'rgb(199, 146, 234)', - fontStyle: 'italic', + color: "rgb(199, 146, 234)", + fontStyle: "italic", }, - 'attr-name': { - color: 'rgb(173, 219, 103)', - fontStyle: 'italic', + "attr-name": { + color: "rgb(173, 219, 103)", + fontStyle: "italic", }, inserted: { - color: 'rgb(173, 219, 103)', - fontStyle: 'italic', + color: "rgb(173, 219, 103)", + fontStyle: "italic", }, string: { - color: 'rgb(173, 219, 103)', + color: "rgb(173, 219, 103)", }, url: { - color: 'rgb(173, 219, 103)', + color: "rgb(173, 219, 103)", }, entity: { - color: 'rgb(173, 219, 103)', + color: "rgb(173, 219, 103)", }, - '.language-css .token.string': { - color: 'rgb(173, 219, 103)', + ".language-css .token.string": { + color: "rgb(173, 219, 103)", }, - '.style .token.string': { - color: 'rgb(173, 219, 103)', + ".style .token.string": { + color: "rgb(173, 219, 103)", }, - 'class-name': { - color: 'rgb(255, 203, 139)', + "class-name": { + color: "rgb(255, 203, 139)", }, atrule: { - color: 'rgb(255, 203, 139)', + color: "rgb(255, 203, 139)", }, - 'attr-value': { - color: 'rgb(255, 203, 139)', + "attr-value": { + color: "rgb(255, 203, 139)", }, regex: { - color: 'rgb(214, 222, 235)', + color: "rgb(214, 222, 235)", }, important: { - color: 'rgb(214, 222, 235)', - fontWeight: 'bold', + color: "rgb(214, 222, 235)", + fontWeight: "bold", }, variable: { - color: 'rgb(214, 222, 235)', + color: "rgb(214, 222, 235)", }, bold: { - fontWeight: 'bold', + fontWeight: "bold", }, italic: { - fontStyle: 'italic', + fontStyle: "italic", }, })(theme); }; diff --git a/packages/paste-core/components/code-block/src/CodeBlockWrapper.tsx b/packages/paste-core/components/code-block/src/CodeBlockWrapper.tsx index df6ba1694a..11e8d9862a 100644 --- a/packages/paste-core/components/code-block/src/CodeBlockWrapper.tsx +++ b/packages/paste-core/components/code-block/src/CodeBlockWrapper.tsx @@ -1,8 +1,8 @@ -import * as React from 'react'; -import {Box} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; -import {Tabs} from '@twilio-paste/tabs'; -import type {TabStateReturn} from '@twilio-paste/tabs'; +import { Box } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import { Tabs } from "@twilio-paste/tabs"; +import type { TabStateReturn } from "@twilio-paste/tabs"; +import * as React from "react"; export interface CodeBlockTabStateReturn extends TabStateReturn { [key: string]: any; @@ -10,12 +10,12 @@ export interface CodeBlockTabStateReturn extends TabStateReturn { export interface CodeBlockWrapperProps { children?: React.ReactNode; - element?: BoxProps['element']; + element?: BoxProps["element"]; state?: CodeBlockTabStateReturn; } export const CodeBlockWrapper = React.forwardRef( - ({children, state, element = 'CODE_BLOCK_WRAPPER'}, ref) => { + ({ children, state, element = "CODE_BLOCK_WRAPPER" }, ref) => { return ( ); - } + }, ); -CodeBlockWrapper.displayName = 'CodeBlockWrapper'; +CodeBlockWrapper.displayName = "CodeBlockWrapper"; diff --git a/packages/paste-core/components/code-block/src/CopyButton.tsx b/packages/paste-core/components/code-block/src/CopyButton.tsx index d77756f621..6a3b49220b 100644 --- a/packages/paste-core/components/code-block/src/CopyButton.tsx +++ b/packages/paste-core/components/code-block/src/CopyButton.tsx @@ -1,17 +1,17 @@ -import * as React from 'react'; -import {Button} from '@twilio-paste/button'; -import {Box} from '@twilio-paste/box'; -import {useClipboard} from '@twilio-paste/clipboard-copy-library'; -import {ScreenReaderOnly} from '@twilio-paste/screen-reader-only'; -import {CopyIcon} from '@twilio-paste/icons/esm/CopyIcon'; -import {Tooltip, useTooltipState} from '@twilio-paste/tooltip'; -import type {BoxProps} from '@twilio-paste/box'; +import { Box } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import { Button } from "@twilio-paste/button"; +import { useClipboard } from "@twilio-paste/clipboard-copy-library"; +import { CopyIcon } from "@twilio-paste/icons/esm/CopyIcon"; +import { ScreenReaderOnly } from "@twilio-paste/screen-reader-only"; +import { Tooltip, useTooltipState } from "@twilio-paste/tooltip"; +import * as React from "react"; interface CopyButtonProps { text: string; i18nCopyLabelBefore?: string; i18nCopyLabelAfter?: string; - element?: BoxProps['element']; + element?: BoxProps["element"]; copyTextFormatter?: (code: string) => string; } @@ -23,9 +23,9 @@ export const getCopyButtonText = (labelBefore: string, labelAfter: string) => { export const CopyButton: React.FC> = ({ text, - i18nCopyLabelBefore = 'Copy code block', - i18nCopyLabelAfter = 'Copied!', - element = 'COPY_BUTTON', + i18nCopyLabelBefore = "Copy code block", + i18nCopyLabelAfter = "Copied!", + element = "COPY_BUTTON", copyTextFormatter, }) => { const tooltipState = useTooltipState(); @@ -37,7 +37,7 @@ export const CopyButton: React.FC> = ({ return getCopyButtonText(i18nCopyLabelBefore, i18nCopyLabelAfter); }, [i18nCopyLabelBefore, i18nCopyLabelAfter]); - const clipboard = useClipboard({copiedTimeout: 1500}); + const clipboard = useClipboard({ copiedTimeout: 1500 }); const handleCopy = React.useCallback(() => { const formattedText = copyTextFormatter ? copyTextFormatter(text) : text; clipboard.copy(formattedText); @@ -75,4 +75,4 @@ export const CopyButton: React.FC> = ({ ); }; -CopyButton.displayName = 'CopyButton'; +CopyButton.displayName = "CopyButton"; diff --git a/packages/paste-core/components/code-block/src/ExternalLinkButton.tsx b/packages/paste-core/components/code-block/src/ExternalLinkButton.tsx index 7df531bc1e..c9176f4b52 100644 --- a/packages/paste-core/components/code-block/src/ExternalLinkButton.tsx +++ b/packages/paste-core/components/code-block/src/ExternalLinkButton.tsx @@ -1,20 +1,20 @@ -import * as React from 'react'; -import {Button} from '@twilio-paste/button'; -import {ScreenReaderOnly} from '@twilio-paste/screen-reader-only'; -import {LinkExternalIcon} from '@twilio-paste/icons/esm/LinkExternalIcon'; -import {Tooltip, useTooltipState} from '@twilio-paste/tooltip'; -import type {BoxProps} from '@twilio-paste/box'; +import type { BoxProps } from "@twilio-paste/box"; +import { Button } from "@twilio-paste/button"; +import { LinkExternalIcon } from "@twilio-paste/icons/esm/LinkExternalIcon"; +import { ScreenReaderOnly } from "@twilio-paste/screen-reader-only"; +import { Tooltip, useTooltipState } from "@twilio-paste/tooltip"; +import * as React from "react"; interface ExternalLinkButtonProps { href: string; i18nLinkLabel?: string; - element?: BoxProps['element']; + element?: BoxProps["element"]; } export const ExternalLinkButton: React.FC> = ({ - i18nLinkLabel = 'Open code block in new page', + i18nLinkLabel = "Open code block in new page", href, - element = 'EXTERNAL_LINK', + element = "EXTERNAL_LINK", }) => { const tooltipState = useTooltipState(); const tooltipText = i18nLinkLabel; @@ -46,4 +46,4 @@ export const ExternalLinkButton: React.FCmessages->create( ) );`; -export const CustomizedCodeBlock: StoryFn = (_args, {parameters: {isTestEnvironment}}) => { +export const CustomizedCodeBlock: StoryFn = (_args, { parameters: { isTestEnvironment } }) => { const currentTheme = useTheme(); return ( @@ -68,22 +75,22 @@ export const CustomizedCodeBlock: StoryFn = (_args, {parameters: {isTestEnvironm theme={currentTheme} elements={{ CODE_BLOCK_WRAPPER: { - width: 'size50', + width: "size50", }, CODE_BLOCK_HEADER: { - backgroundColor: 'colorBackgroundErrorWeakest', - color: 'colorTextErrorStronger', - borderTopLeftRadius: 'borderRadius30', - borderTopRightRadius: 'borderRadius30', - fontSize: 'fontSize20', + backgroundColor: "colorBackgroundErrorWeakest", + color: "colorTextErrorStronger", + borderTopLeftRadius: "borderRadius30", + borderTopRightRadius: "borderRadius30", + fontSize: "fontSize20", }, CODE_BLOCK_COPY_BUTTON: { - backgroundColor: 'colorBackgroundErrorWeakest', - color: 'colorTextErrorStronger', + backgroundColor: "colorBackgroundErrorWeakest", + color: "colorTextErrorStronger", }, CODE_BLOCK_EXTERNAL_LINK: { - backgroundColor: 'colorBackgroundErrorWeakest', - color: 'colorTextErrorStronger', + backgroundColor: "colorBackgroundErrorWeakest", + color: "colorTextErrorStronger", }, }} > @@ -95,7 +102,7 @@ export const CustomizedCodeBlock: StoryFn = (_args, {parameters: {isTestEnvironm ); }; -export const CustomizedCodeBlockGroup: StoryFn = (_args, {parameters: {isTestEnvironment}}) => { +export const CustomizedCodeBlockGroup: StoryFn = (_args, { parameters: { isTestEnvironment } }) => { const currentTheme = useTheme(); return ( @@ -104,37 +111,37 @@ export const CustomizedCodeBlockGroup: StoryFn = (_args, {parameters: {isTestEnv theme={currentTheme} elements={{ CODE_BLOCK_WRAPPER: { - width: 'size50', + width: "size50", }, CODE_BLOCK_HEADER: { - backgroundColor: 'colorBackgroundErrorWeakest', - color: 'colorTextErrorStronger', - borderTopLeftRadius: 'borderRadius30', - borderTopRightRadius: 'borderRadius30', - fontSize: 'fontSize20', + backgroundColor: "colorBackgroundErrorWeakest", + color: "colorTextErrorStronger", + borderTopLeftRadius: "borderRadius30", + borderTopRightRadius: "borderRadius30", + fontSize: "fontSize20", }, CODE_BLOCK_TAB_LIST: { - backgroundColor: 'colorBackgroundErrorWeakest', - columnGap: 'space0', + backgroundColor: "colorBackgroundErrorWeakest", + columnGap: "space0", }, CODE_BLOCK_TAB: { - borderRadius: 'borderRadius0', + borderRadius: "borderRadius0", }, CODE_BLOCK_TAB_PANEL: { - borderStyle: 'solid', - borderWidth: 'borderWidth20', - borderColor: 'colorBorderDestructiveWeak', - borderBottomLeftRadius: 'borderRadius30', - borderBottomRightRadius: 'borderRadius30', - overflow: 'hidden', + borderStyle: "solid", + borderWidth: "borderWidth20", + borderColor: "colorBorderDestructiveWeak", + borderBottomLeftRadius: "borderRadius30", + borderBottomRightRadius: "borderRadius30", + overflow: "hidden", }, CODE_BLOCK_COPY_BUTTON: { - backgroundColor: 'colorBackgroundErrorWeakest', - color: 'colorTextErrorStronger', + backgroundColor: "colorBackgroundErrorWeakest", + color: "colorTextErrorStronger", }, CODE_BLOCK_EXTERNAL_LINK: { - backgroundColor: 'colorBackgroundErrorWeakest', - color: 'colorTextErrorStronger', + backgroundColor: "colorBackgroundErrorWeakest", + color: "colorTextErrorStronger", }, }} > diff --git a/packages/paste-core/components/code-block/stories/index.stories.tsx b/packages/paste-core/components/code-block/stories/index.stories.tsx index c501794987..9b8109754c 100644 --- a/packages/paste-core/components/code-block/stories/index.stories.tsx +++ b/packages/paste-core/components/code-block/stories/index.stories.tsx @@ -1,12 +1,19 @@ -import * as React from 'react'; -import type {StoryFn} from '@storybook/react'; -import {Box} from '@twilio-paste/box'; - -import {CodeBlock, CodeBlockWrapper, CodeBlockHeader, CodeBlockTabList, CodeBlockTab, CodeBlockTabPanel} from '../src'; +import type { StoryFn } from "@storybook/react"; +import { Box } from "@twilio-paste/box"; +import * as React from "react"; + +import { + CodeBlock, + CodeBlockHeader, + CodeBlockTab, + CodeBlockTabList, + CodeBlockTabPanel, + CodeBlockWrapper, +} from "../src"; // eslint-disable-next-line import/no-default-export export default { - title: 'Components/Code Block', + title: "Components/Code Block", component: CodeBlock, }; @@ -150,7 +157,7 @@ export const CustomCopyFormatter: StoryFn = () => ( language="shell" code={`$ curl -G https://api.twilio.com/2010-04-01/Accounts -u '[YOUR ACCOUNT SID]:[YOUR AUTH TOKEN]'`} copyTextFormatter={(code) => { - return code.replace('[YOUR ACCOUNT SID]', 'XXXXXXX').replace('[YOUR AUTH TOKEN]', '1234567890'); + return code.replace("[YOUR ACCOUNT SID]", "XXXXXXX").replace("[YOUR AUTH TOKEN]", "1234567890"); }} /> ); diff --git a/packages/paste-core/components/combobox/__tests__/Combobox.spec.tsx b/packages/paste-core/components/combobox/__tests__/Combobox.spec.tsx index 7f53351301..b6fe89bb44 100644 --- a/packages/paste-core/components/combobox/__tests__/Combobox.spec.tsx +++ b/packages/paste-core/components/combobox/__tests__/Combobox.spec.tsx @@ -1,29 +1,29 @@ -import * as React from 'react'; -import filter from 'lodash/filter'; -import uniq from 'lodash/uniq'; -import {render, screen, fireEvent, waitFor} from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import type {RenderOptions} from '@testing-library/react'; -import {Theme} from '@twilio-paste/theme'; -import {Button} from '@twilio-paste/button'; -import {CloseIcon} from '@twilio-paste/icons/esm/CloseIcon'; -import {Box} from '@twilio-paste/box'; -import type {useVirtual as _useVirtual} from 'react-virtual'; - -import {useCombobox, Combobox} from '../src'; -import type {ComboboxProps} from '../src/types'; -import {getIndexedItems, getGroupedItems} from '../src/helpers'; +import { fireEvent, render, screen, waitFor } from "@testing-library/react"; +import type { RenderOptions } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { Box } from "@twilio-paste/box"; +import { Button } from "@twilio-paste/button"; +import { CloseIcon } from "@twilio-paste/icons/esm/CloseIcon"; +import { Theme } from "@twilio-paste/theme"; +import filter from "lodash/filter"; +import uniq from "lodash/uniq"; +import * as React from "react"; +import type { useVirtual as _useVirtual } from "react-virtual"; + +import { Combobox, useCombobox } from "../src"; +import { getGroupedItems, getIndexedItems } from "../src/helpers"; +import type { ComboboxProps } from "../src/types"; type UseVirtual = typeof _useVirtual; const mockScrollToIndex = jest.fn(); -jest.mock('react-virtual', () => { - const {useVirtual} = jest.requireActual('react-virtual'); +jest.mock("react-virtual", () => { + const { useVirtual } = jest.requireActual("react-virtual"); return { useVirtual: (config: Parameters) => { - const {scrollToIndex, ...returnValue} = useVirtual(config); + const { scrollToIndex, ...returnValue } = useVirtual(config); return { ...returnValue, scrollToIndex: mockScrollToIndex, @@ -32,46 +32,46 @@ jest.mock('react-virtual', () => { }; }); -const items = ['Alert', 'Anchor', 'Button', 'Card', 'Heading', 'List', 'Modal', 'Paragraph']; +const items = ["Alert", "Anchor", "Button", "Card", "Heading", "List", "Modal", "Paragraph"]; const objectItems = [ - {code: 'AD', label: 'Andorra', phone: '376'}, - {code: 'AE', label: 'United Arab Emirates', phone: '971'}, - {code: 'AF', label: 'Afghanistan', phone: '93'}, - {code: 'AG', label: 'Antigua and Barbuda', phone: '1-268'}, - {code: 'AI', label: 'Anguilla', phone: '1-264'}, - {code: 'AL', label: 'Albania', phone: '355'}, - {code: 'AM', label: 'Armenia', phone: '374'}, - {code: 'AO', label: 'Angola', phone: '244'}, - {code: 'AQ', label: 'Antarctica', phone: '672'}, - {code: 'AR', label: 'Argentina', phone: '54'}, - {code: 'AS', label: 'American Samoa', phone: '1-684'}, - {code: 'AT', label: 'Austria', phone: '43'}, + { code: "AD", label: "Andorra", phone: "376" }, + { code: "AE", label: "United Arab Emirates", phone: "971" }, + { code: "AF", label: "Afghanistan", phone: "93" }, + { code: "AG", label: "Antigua and Barbuda", phone: "1-268" }, + { code: "AI", label: "Anguilla", phone: "1-264" }, + { code: "AL", label: "Albania", phone: "355" }, + { code: "AM", label: "Armenia", phone: "374" }, + { code: "AO", label: "Angola", phone: "244" }, + { code: "AQ", label: "Antarctica", phone: "672" }, + { code: "AR", label: "Argentina", phone: "54" }, + { code: "AS", label: "American Samoa", phone: "1-684" }, + { code: "AT", label: "Austria", phone: "43" }, ]; const groupedItems = [ - {group: 'Components', label: 'Alert'}, - {group: 'Components', label: 'Anchor'}, - {group: 'Components', label: 'Button'}, - {group: 'Components', label: 'Card'}, - {group: 'Components', label: 'Heading'}, - {group: 'Components', label: 'List'}, - {group: 'Components', label: 'Modal'}, - {group: 'Components', label: 'Paragraph'}, - {group: 'Primitives', label: 'Box'}, - {group: 'Primitives', label: 'Text'}, - {group: 'Primitives', label: 'Non-modal dialog'}, - {group: 'Layout', label: 'Grid'}, - {label: 'Design Tokens'}, + { group: "Components", label: "Alert" }, + { group: "Components", label: "Anchor" }, + { group: "Components", label: "Button" }, + { group: "Components", label: "Card" }, + { group: "Components", label: "Heading" }, + { group: "Components", label: "List" }, + { group: "Components", label: "Modal" }, + { group: "Components", label: "Paragraph" }, + { group: "Primitives", label: "Box" }, + { group: "Primitives", label: "Text" }, + { group: "Primitives", label: "Non-modal dialog" }, + { group: "Layout", label: "Grid" }, + { label: "Design Tokens" }, ]; const smallGroupedItems = [ - {group: 'Components', label: 'Alert'}, - {group: 'Primitives', label: 'Box'}, - {label: 'Design Tokens'}, + { group: "Components", label: "Alert" }, + { group: "Primitives", label: "Box" }, + { label: "Design Tokens" }, ]; -const ThemeWrapper: RenderOptions['wrapper'] = ({children}) => ( +const ThemeWrapper: RenderOptions["wrapper"] = ({ children }) => ( {children} ); @@ -81,7 +81,7 @@ function getFilteredItems(inputValue: string): any[] { } const ComboboxMock = (): JSX.Element => { - const [inputValue, setInputValue] = React.useState(''); + const [inputValue, setInputValue] = React.useState(""); const filteredItems = React.useMemo(() => getFilteredItems(inputValue), [inputValue]); return ( @@ -102,8 +102,8 @@ const ComboboxMock = (): JSX.Element => { }; const GroupedMockCombobox: React.FC< - React.PropsWithChildren<{groupLabelTemplate?: ComboboxProps['groupLabelTemplate']}> -> = ({groupLabelTemplate}) => { + React.PropsWithChildren<{ groupLabelTemplate?: ComboboxProps["groupLabelTemplate"] }> +> = ({ groupLabelTemplate }) => { return (
{item.label}
} - itemToString={(item) => (item && typeof item !== 'string' ? item.label : null)} + itemToString={(item) => (item && typeof item !== "string" ? item.label : null)} /> ); }; @@ -124,13 +124,13 @@ function getFilteredObjectItems(inputValue: string): any[] { } const ControlledCombobox = (): JSX.Element => { - const [inputValue, setInputValue] = React.useState(''); + const [inputValue, setInputValue] = React.useState(""); const filteredItems = React.useMemo(() => getFilteredObjectItems(inputValue), [inputValue]); const [selectedItem, setSelectedItem] = React.useState({}); - const {reset, ...state} = useCombobox({ + const { reset, ...state } = useCombobox({ items: filteredItems, - itemToString: (item) => (item ? item.label : ''), + itemToString: (item) => (item ? item.label : ""), onSelectedItemChange: (changes) => { setSelectedItem(changes.selectedItem); }, @@ -176,214 +176,214 @@ const ControlledCombobox = (): JSX.Element => { ); }; -describe('Combobox', () => { +describe("Combobox", () => { beforeEach(() => { jest.clearAllMocks(); }); - describe('Unit tests', () => { - it('should return an indexed array of items', () => { + describe("Unit tests", () => { + it("should return an indexed array of items", () => { expect(getIndexedItems(smallGroupedItems)).toStrictEqual([ - {group: 'Components', index: 0, label: 'Alert'}, - {group: 'Primitives', index: 1, label: 'Box'}, - {index: 2, label: 'Design Tokens'}, + { group: "Components", index: 0, label: "Alert" }, + { group: "Primitives", index: 1, label: "Box" }, + { index: 2, label: "Design Tokens" }, ]); }); - it('should return grouped object of items with original array index', () => { - expect(getGroupedItems(getIndexedItems(smallGroupedItems), 'group')).toStrictEqual({ - Components: [{group: 'Components', index: 0, label: 'Alert'}], - Primitives: [{group: 'Primitives', index: 1, label: 'Box'}], - undefined: [{index: 2, label: 'Design Tokens'}], + it("should return grouped object of items with original array index", () => { + expect(getGroupedItems(getIndexedItems(smallGroupedItems), "group")).toStrictEqual({ + Components: [{ group: "Components", index: 0, label: "Alert" }], + Primitives: [{ group: "Primitives", index: 1, label: "Box" }], + undefined: [{ index: 2, label: "Design Tokens" }], }); }); }); - describe('Render', () => { - it('should render a combobox with aria attributes', () => { - render(, {wrapper: ThemeWrapper}); - const renderedCombobox = screen.getByRole('combobox'); - expect(renderedCombobox.getAttribute('aria-haspopup')).toEqual('listbox'); - expect(renderedCombobox.getAttribute('aria-owns')).toEqual(screen.getByRole('listbox').id); - expect(renderedCombobox.getAttribute('aria-expanded')).toEqual('true'); + describe("Render", () => { + it("should render a combobox with aria attributes", () => { + render(, { wrapper: ThemeWrapper }); + const renderedCombobox = screen.getByRole("combobox"); + expect(renderedCombobox.getAttribute("aria-haspopup")).toEqual("listbox"); + expect(renderedCombobox.getAttribute("aria-owns")).toEqual(screen.getByRole("listbox").id); + expect(renderedCombobox.getAttribute("aria-expanded")).toEqual("true"); }); - it('should render a textbox with aria attributes', () => { - render(, {wrapper: ThemeWrapper}); - const renderedCombobox = screen.getByRole('textbox'); - expect(renderedCombobox.getAttribute('aria-controls')).toEqual(screen.getByRole('listbox').id); - expect(renderedCombobox.getAttribute('aria-labelledby')).toEqual(document.querySelector('label')!.id); - expect(renderedCombobox.getAttribute('aria-describedby')).not.toEqual(''); + it("should render a textbox with aria attributes", () => { + render(, { wrapper: ThemeWrapper }); + const renderedCombobox = screen.getByRole("textbox"); + expect(renderedCombobox.getAttribute("aria-controls")).toEqual(screen.getByRole("listbox").id); + expect(renderedCombobox.getAttribute("aria-labelledby")).toEqual(document.querySelector("label")!.id); + expect(renderedCombobox.getAttribute("aria-describedby")).not.toEqual(""); }); - it('should render a list with aria attributes', () => { - render(, {wrapper: ThemeWrapper}); - const renderedCombobox = screen.getByRole('listbox'); - expect(renderedCombobox.getAttribute('aria-labelledby')).toEqual(document.querySelector('label')!.id); + it("should render a list with aria attributes", () => { + render(, { wrapper: ThemeWrapper }); + const renderedCombobox = screen.getByRole("listbox"); + expect(renderedCombobox.getAttribute("aria-labelledby")).toEqual(document.querySelector("label")!.id); }); - it('should render a list with unique option ids', () => { - render(, {wrapper: ThemeWrapper}); - const renderedOptions = screen.getAllByRole('option'); + it("should render a list with unique option ids", () => { + render(, { wrapper: ThemeWrapper }); + const renderedOptions = screen.getAllByRole("option"); const optionIDs = renderedOptions.map((option) => option.id); const uniqueIDs = uniq(optionIDs); expect(uniqueIDs.length).toEqual(optionIDs.length); - expect(renderedOptions[3].getAttribute('aria-disabled')).toEqual('true'); + expect(renderedOptions[3].getAttribute("aria-disabled")).toEqual("true"); }); - it('should render a label for that matches the input id', () => { - render(, {wrapper: ThemeWrapper}); - const renderedLabel = document.querySelector('label'); - const renderedTextbox = screen.getByRole('textbox'); - expect(renderedLabel!.getAttribute('for')).toEqual(renderedTextbox.getAttribute('id')); + it("should render a label for that matches the input id", () => { + render(, { wrapper: ThemeWrapper }); + const renderedLabel = document.querySelector("label"); + const renderedTextbox = screen.getByRole("textbox"); + expect(renderedLabel!.getAttribute("for")).toEqual(renderedTextbox.getAttribute("id")); }); - it('should render a required combobox', () => { - render(, {wrapper: ThemeWrapper}); - const renderedTextbox = screen.getByRole('textbox'); - expect(renderedTextbox.getAttribute('required')).toEqual(''); + it("should render a required combobox", () => { + render(, { wrapper: ThemeWrapper }); + const renderedTextbox = screen.getByRole("textbox"); + expect(renderedTextbox.getAttribute("required")).toEqual(""); }); - it('should set correct aria-activedescendant when highlighted index changes', async () => { - render(, {wrapper: ThemeWrapper}); + it("should set correct aria-activedescendant when highlighted index changes", async () => { + render(, { wrapper: ThemeWrapper }); const targetIndex = 1; const target = items[targetIndex]; userEvent.hover(screen.getByText(target)); - expect(screen.getByRole('textbox').getAttribute('aria-activedescendant')).toMatch( - /downshift-([1-9]\d\d|[1-9]\d|\d)-item-1/g + expect(screen.getByRole("textbox").getAttribute("aria-activedescendant")).toMatch( + /downshift-([1-9]\d\d|[1-9]\d|\d)-item-1/g, ); }); }); - describe('Groups', () => { - it('should render a group of options', () => { - render(, {wrapper: ThemeWrapper}); - const renderedGroups = screen.getAllByRole('group'); + describe("Groups", () => { + it("should render a group of options", () => { + render(, { wrapper: ThemeWrapper }); + const renderedGroups = screen.getAllByRole("group"); // check groups, group label and number of options per group - expect(renderedGroups[0].getAttribute('aria-label')).toEqual('Components'); + expect(renderedGroups[0].getAttribute("aria-label")).toEqual("Components"); expect(renderedGroups[0].querySelectorAll('[role="option"]').length).toEqual(8); - expect(renderedGroups[1].getAttribute('aria-label')).toEqual('Primitives'); + expect(renderedGroups[1].getAttribute("aria-label")).toEqual("Primitives"); expect(renderedGroups[1].querySelectorAll('[role="option"]').length).toEqual(3); - expect(renderedGroups[2].getAttribute('aria-label')).toEqual('Layout'); + expect(renderedGroups[2].getAttribute("aria-label")).toEqual("Layout"); expect(renderedGroups[2].querySelectorAll('[role="option"]').length).toEqual(1); }); - it('should render any items not identified as part of the group as ungrouped options', () => { - render(, {wrapper: ThemeWrapper}); - const renderedListbox = screen.getByRole('listbox'); - const renderedGroups = screen.getAllByRole('group'); + it("should render any items not identified as part of the group as ungrouped options", () => { + render(, { wrapper: ThemeWrapper }); + const renderedListbox = screen.getByRole("listbox"); + const renderedGroups = screen.getAllByRole("group"); // check we have 3 groups expect(renderedGroups.length).toEqual(3); // check any options that are not nested in groups expect( - renderedListbox.querySelectorAll('[role="listbox"] > [role="presentation"] > [role="option"]').length + renderedListbox.querySelectorAll('[role="listbox"] > [role="presentation"] > [role="option"]').length, ).toEqual(1); }); - it('should render a listbox with groups of options that contains no duplicate ids', () => { - render(, {wrapper: ThemeWrapper}); - const renderedOptions = screen.getAllByRole('option'); + it("should render a listbox with groups of options that contains no duplicate ids", () => { + render(, { wrapper: ThemeWrapper }); + const renderedOptions = screen.getAllByRole("option"); const optionIDs = renderedOptions.map((option) => option.id); const uniqueIDs = uniq(optionIDs); expect(uniqueIDs.length).toEqual(optionIDs.length); }); - it('should render a custom group label', () => { + it("should render a custom group label", () => { render( hi {groupName}} />, { wrapper: ThemeWrapper, }); - const renderedGroups = screen.getAllByRole('group'); + const renderedGroups = screen.getAllByRole("group"); expect(renderedGroups[0].querySelector('[role="group"] > li[role="presentation"]')!.textContent).toEqual( - 'hi Components' + "hi Components", ); expect(renderedGroups[1].querySelector('[role="group"] > li[role="presentation"]')!.textContent).toEqual( - 'hi Primitives' + "hi Primitives", ); expect(renderedGroups[2].querySelector('[role="group"] > li[role="presentation"]')!.textContent).toEqual( - 'hi Layout' + "hi Layout", ); }); - it('should select item using keyboard', () => { - render(, {wrapper: ThemeWrapper}); + it("should select item using keyboard", () => { + render(, { wrapper: ThemeWrapper }); // open the combobox - fireEvent.click(screen.getByRole('textbox')); + fireEvent.click(screen.getByRole("textbox")); // select the third item using ArrowDown keyDown - fireEvent.keyDown(screen.getByRole('textbox'), {key: 'ArrowDown', code: 'ArrowDown'}); - fireEvent.keyDown(screen.getByRole('textbox'), {key: 'ArrowDown', code: 'ArrowDown'}); - fireEvent.keyDown(screen.getByRole('textbox'), {key: 'ArrowDown', code: 'ArrowDown'}); - fireEvent.keyDown(screen.getByRole('textbox'), {key: 'Enter', code: 'Enter'}); + fireEvent.keyDown(screen.getByRole("textbox"), { key: "ArrowDown", code: "ArrowDown" }); + fireEvent.keyDown(screen.getByRole("textbox"), { key: "ArrowDown", code: "ArrowDown" }); + fireEvent.keyDown(screen.getByRole("textbox"), { key: "ArrowDown", code: "ArrowDown" }); + fireEvent.keyDown(screen.getByRole("textbox"), { key: "Enter", code: "Enter" }); // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore Property 'value' does not exist on type 'HTMLElement' (I get it, but this is right) - expect(screen.getByRole('textbox').value).toEqual('Button'); + expect(screen.getByRole("textbox").value).toEqual("Button"); // select the first item using ArrowUp keyDown - fireEvent.keyDown(screen.getByRole('textbox'), {key: 'ArrowUp', code: 'ArrowUp'}); - fireEvent.keyDown(screen.getByRole('textbox'), {key: 'ArrowUp', code: 'ArrowUp'}); - fireEvent.keyDown(screen.getByRole('textbox'), {key: 'Enter', code: 'Enter'}); + fireEvent.keyDown(screen.getByRole("textbox"), { key: "ArrowUp", code: "ArrowUp" }); + fireEvent.keyDown(screen.getByRole("textbox"), { key: "ArrowUp", code: "ArrowUp" }); + fireEvent.keyDown(screen.getByRole("textbox"), { key: "Enter", code: "Enter" }); // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore Property 'value' does not exist on type 'HTMLElement' (I get it, but this is right) - expect(screen.getByRole('textbox').value).toEqual('Alert'); + expect(screen.getByRole("textbox").value).toEqual("Alert"); }); it('should not run react virtual\'s "scroll to" function when "groupItemsBy" is defined as a string', () => { // bc grouped comboboxes are not yet virtualized - render(, {wrapper: ThemeWrapper}); + render(, { wrapper: ThemeWrapper }); const targetIndex = 1; const target = groupedItems[targetIndex]; userEvent.hover(screen.getByText(target.label)); - expect(screen.getByRole('textbox').getAttribute('aria-activedescendant')).toMatch( - /downshift-([1-9]\d\d|[1-9]\d|\d)-item-1/g + expect(screen.getByRole("textbox").getAttribute("aria-activedescendant")).toMatch( + /downshift-([1-9]\d\d|[1-9]\d|\d)-item-1/g, ); expect(mockScrollToIndex).not.toHaveBeenCalled(); }); }); - describe('Controlled Combobox', () => { - it('should be able to clear a Combobox', () => { - render(, {wrapper: ThemeWrapper}); + describe("Controlled Combobox", () => { + it("should be able to clear a Combobox", () => { + render(, { wrapper: ThemeWrapper }); // open the combobox - fireEvent.click(screen.getByRole('textbox')); + fireEvent.click(screen.getByRole("textbox")); // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore Property 'value' does not exist on type 'HTMLElement' (I get it, but this is right) - expect(screen.getByRole('textbox').value).toEqual(''); + expect(screen.getByRole("textbox").value).toEqual(""); // select the first item - fireEvent.click(screen.getAllByRole('option')[0]); + fireEvent.click(screen.getAllByRole("option")[0]); // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore Property 'value' does not exist on type 'HTMLElement' (I get it, but this is right) - expect(screen.getByRole('textbox').value).toEqual('Andorra'); - expect(screen.getByTestId('input-value-span').textContent).toEqual('"Andorra"'); - expect(screen.getByTestId('selected-item-span').textContent).toEqual( - '{"code":"AD","label":"Andorra","phone":"376"}' + expect(screen.getByRole("textbox").value).toEqual("Andorra"); + expect(screen.getByTestId("input-value-span").textContent).toEqual('"Andorra"'); + expect(screen.getByTestId("selected-item-span").textContent).toEqual( + '{"code":"AD","label":"Andorra","phone":"376"}', ); // click the clear button - fireEvent.click(screen.getByText('Clear')); + fireEvent.click(screen.getByText("Clear")); // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore Property 'value' does not exist on type 'HTMLElement' (I get it, but this is right) - expect(screen.getByRole('textbox').value).toEqual(''); - expect(screen.getByTestId('input-value-span').textContent).toEqual('""'); - expect(screen.getByTestId('selected-item-span').textContent).toEqual('null'); + expect(screen.getByRole("textbox").value).toEqual(""); + expect(screen.getByTestId("input-value-span").textContent).toEqual('""'); + expect(screen.getByTestId("selected-item-span").textContent).toEqual("null"); }); - it('should set correct aria-activedescendant when highlighted index changes', async () => { - render(, {wrapper: ThemeWrapper}); + it("should set correct aria-activedescendant when highlighted index changes", async () => { + render(, { wrapper: ThemeWrapper }); - userEvent.click(screen.getByRole('textbox')); + userEvent.click(screen.getByRole("textbox")); const targetIndex = 1; const target = objectItems[targetIndex]; - userEvent.hover(screen.getByText(target.label, {exact: false})); // text broken up by characters + userEvent.hover(screen.getByText(target.label, { exact: false })); // text broken up by characters - expect(screen.getByRole('textbox').getAttribute('aria-activedescendant')).toMatch( - /downshift-([1-9]\d\d|[1-9]\d|\d)-item-1/g + expect(screen.getByRole("textbox").getAttribute("aria-activedescendant")).toMatch( + /downshift-([1-9]\d\d|[1-9]\d|\d)-item-1/g, ); }); }); diff --git a/packages/paste-core/components/combobox/__tests__/GrowingInput.spec.tsx b/packages/paste-core/components/combobox/__tests__/GrowingInput.spec.tsx index b16d5dbeb8..c616a12ba7 100644 --- a/packages/paste-core/components/combobox/__tests__/GrowingInput.spec.tsx +++ b/packages/paste-core/components/combobox/__tests__/GrowingInput.spec.tsx @@ -1,22 +1,22 @@ -import * as React from 'react'; -import {render, screen, fireEvent} from '@testing-library/react'; -import type {RenderOptions} from '@testing-library/react'; -import {Theme} from '@twilio-paste/theme'; +import { fireEvent, render, screen } from "@testing-library/react"; +import type { RenderOptions } from "@testing-library/react"; +import { Theme } from "@twilio-paste/theme"; +import * as React from "react"; -import {GrowingInput} from '../src/multiselect/GrowingInput'; +import { GrowingInput } from "../src/multiselect/GrowingInput"; -const TEST_ID = 'growing-input-test-id-123'; +const TEST_ID = "growing-input-test-id-123"; -describe('GrowingInput component', () => { - it('should set the correct width and have an id', () => { +describe("GrowingInput component", () => { + it("should set the correct width and have an id", () => { render( - + , ); - const input = screen.getByRole('textbox'); + const input = screen.getByRole("textbox"); - expect(input).toHaveStyleRule('width', '100%'); - expect(input.getAttribute('id')).toEqual(TEST_ID); + expect(input).toHaveStyleRule("width", "100%"); + expect(input.getAttribute("id")).toEqual(TEST_ID); }); }); diff --git a/packages/paste-core/components/combobox/__tests__/MultiselectCombobox.spec.tsx b/packages/paste-core/components/combobox/__tests__/MultiselectCombobox.spec.tsx index 1311a97bc5..1162bdf9ac 100644 --- a/packages/paste-core/components/combobox/__tests__/MultiselectCombobox.spec.tsx +++ b/packages/paste-core/components/combobox/__tests__/MultiselectCombobox.spec.tsx @@ -1,25 +1,25 @@ -import * as React from 'react'; -import {render, act, screen, fireEvent} from '@testing-library/react'; -import type {RenderOptions} from '@testing-library/react'; -import {Theme} from '@twilio-paste/theme'; -import {Form} from '@twilio-paste/form'; -import {Button} from '@twilio-paste/button'; -import filter from 'lodash/filter'; -import uniq from 'lodash/uniq'; - -import {MultiselectCombobox, useMultiselectCombobox} from '../src'; -import type {MultiselectComboboxProps} from '../src'; +import { act, fireEvent, render, screen } from "@testing-library/react"; +import type { RenderOptions } from "@testing-library/react"; +import { Button } from "@twilio-paste/button"; +import { Form } from "@twilio-paste/form"; +import { Theme } from "@twilio-paste/theme"; +import filter from "lodash/filter"; +import uniq from "lodash/uniq"; +import * as React from "react"; + +import { MultiselectCombobox, useMultiselectCombobox } from "../src"; +import type { MultiselectComboboxProps } from "../src"; const items = [ - 'Alert', - 'Anchor', - 'Button', - 'Card', - 'Heading', - 'A component with a really really really really really really really really long name', - 'List', - 'Modal', - 'Paragraph', + "Alert", + "Anchor", + "Button", + "Card", + "Heading", + "A component with a really really really really really really really really long name", + "List", + "Modal", + "Paragraph", ]; function getFilteredItems(inputValue: string): string[] { @@ -30,12 +30,12 @@ function getFilteredItems(inputValue: string): string[] { }); } -const ThemeWrapper: RenderOptions['wrapper'] = ({children}) => ( +const ThemeWrapper: RenderOptions["wrapper"] = ({ children }) => ( {children} ); const MultiselectComboboxMock: React.FC> = (props) => { - const [inputValue, setInputValue] = React.useState(''); + const [inputValue, setInputValue] = React.useState(""); const filteredItems = React.useMemo(() => getFilteredItems(inputValue), [inputValue]); return ( > = (pr items={filteredItems} disabledItems={[items[3]]} initialIsOpen - onInputValueChange={({inputValue: newInputValue = ''}) => { + onInputValueChange={({ inputValue: newInputValue = "" }) => { setInputValue(newInputValue); }} onSelectedItemsChange={() => { @@ -63,19 +63,19 @@ interface GroupedItem { label: string; } const groupedItems = [ - {group: 'Components', label: 'Alert'}, - {group: 'Components', label: 'Anchor'}, - {group: 'Components', label: 'Button'}, - {group: 'Components', label: 'Card'}, - {group: 'Components', label: 'Heading'}, - {group: 'Components', label: 'List'}, - {group: 'Components', label: 'Modal'}, - {group: 'Components', label: 'Paragraph'}, - {group: 'Primitives', label: 'Box'}, - {group: 'Primitives', label: 'Text'}, - {group: 'Primitives', label: 'Non-modal dialog'}, - {group: 'Layout', label: 'Grid'}, - {label: 'Design Tokens'}, + { group: "Components", label: "Alert" }, + { group: "Components", label: "Anchor" }, + { group: "Components", label: "Button" }, + { group: "Components", label: "Card" }, + { group: "Components", label: "Heading" }, + { group: "Components", label: "List" }, + { group: "Components", label: "Modal" }, + { group: "Components", label: "Paragraph" }, + { group: "Primitives", label: "Box" }, + { group: "Primitives", label: "Text" }, + { group: "Primitives", label: "Non-modal dialog" }, + { group: "Layout", label: "Grid" }, + { label: "Design Tokens" }, ]; function getFilteredGroupedItems(inputValue: string): GroupedItem[] { @@ -87,7 +87,7 @@ const onSubmitMock = jest.fn(); const onKeyDownMock = jest.fn(); const GroupedMultiselectComboboxMock: React.FC> = (props) => { - const [inputValue, setInputValue] = React.useState(''); + const [inputValue, setInputValue] = React.useState(""); const filteredItems = React.useMemo(() => getFilteredGroupedItems(inputValue), [inputValue]); return ( @@ -96,8 +96,8 @@ const GroupedMultiselectComboboxMock: React.FC selectedItemsLabelText="Selected Paste components" groupItemsBy="group" items={filteredItems} - itemToString={(item: GroupedItem) => (item ? item.label : '')} - onInputValueChange={({inputValue: newInputValue = ''}) => { + itemToString={(item: GroupedItem) => (item ? item.label : "")} + onInputValueChange={({ inputValue: newInputValue = "" }) => { setInputValue(newInputValue); }} labelText="Choose a component:" @@ -111,7 +111,7 @@ const GroupedMultiselectComboboxMock: React.FC }; const StateHookMock: React.FC> = (props) => { - const [inputValue, setInputValue] = React.useState(''); + const [inputValue, setInputValue] = React.useState(""); const filteredItems = React.useMemo(() => getFilteredGroupedItems(inputValue), [inputValue]); const state = useMultiselectCombobox({ @@ -129,8 +129,8 @@ const StateHookMock: React.FC> = (props) => { groupItemsBy="group" items={filteredItems} inputValue={inputValue} - itemToString={(item: GroupedItem) => (item ? item.label : '')} - onInputValueChange={({inputValue: newInputValue = ''}) => { + itemToString={(item: GroupedItem) => (item ? item.label : "")} + onInputValueChange={({ inputValue: newInputValue = "" }) => { setInputValue(newInputValue); }} onSelectedItemsChange={props.onSelectedItemsChange} @@ -144,88 +144,88 @@ const StateHookMock: React.FC> = (props) => { ); }; -describe('MultiselectCombobox', () => { +describe("MultiselectCombobox", () => { beforeEach(() => { jest.clearAllMocks(); }); - describe('Render', () => { - it('should render a combobox with aria attributes', () => { + describe("Render", () => { + it("should render a combobox with aria attributes", () => { render(, { wrapper: ThemeWrapper, }); // PillGroup aria attributes - const [pillGroupListbox, dropdownListbox] = screen.getAllByRole('listbox'); - expect(pillGroupListbox.getAttribute('aria-label')).toBeDefined(); - expect(pillGroupListbox.getAttribute('aria-describedby')).toBeDefined(); + const [pillGroupListbox, dropdownListbox] = screen.getAllByRole("listbox"); + expect(pillGroupListbox.getAttribute("aria-label")).toBeDefined(); + expect(pillGroupListbox.getAttribute("aria-describedby")).toBeDefined(); // Combobox aria attributes - const renderedCombobox = screen.getByRole('combobox'); - expect(renderedCombobox.getAttribute('aria-haspopup')).toEqual('listbox'); - expect(renderedCombobox.getAttribute('aria-owns')).toEqual(dropdownListbox.id); - expect(renderedCombobox.getAttribute('aria-expanded')).toEqual('false'); + const renderedCombobox = screen.getByRole("combobox"); + expect(renderedCombobox.getAttribute("aria-haspopup")).toEqual("listbox"); + expect(renderedCombobox.getAttribute("aria-owns")).toEqual(dropdownListbox.id); + expect(renderedCombobox.getAttribute("aria-expanded")).toEqual("false"); fireEvent.click(renderedCombobox); - expect(renderedCombobox.getAttribute('aria-expanded')).toEqual('true'); + expect(renderedCombobox.getAttribute("aria-expanded")).toEqual("true"); // Textbox aria attributes - const renderedTextbox = screen.getByRole('textbox'); - expect(renderedTextbox.getAttribute('aria-controls')).toEqual(dropdownListbox.id); - expect(renderedTextbox.getAttribute('aria-describedby')).not.toEqual(''); - expect(renderedTextbox.getAttribute('aria-labelledby')).toEqual(document.querySelector('label')!.id); - expect(renderedTextbox.getAttribute('required')).toEqual(null); + const renderedTextbox = screen.getByRole("textbox"); + expect(renderedTextbox.getAttribute("aria-controls")).toEqual(dropdownListbox.id); + expect(renderedTextbox.getAttribute("aria-describedby")).not.toEqual(""); + expect(renderedTextbox.getAttribute("aria-labelledby")).toEqual(document.querySelector("label")!.id); + expect(renderedTextbox.getAttribute("required")).toEqual(null); // unique option ids - const renderedOptions = screen.getAllByRole('option'); - expect(renderedOptions[3].getAttribute('aria-disabled')).toEqual('true'); + const renderedOptions = screen.getAllByRole("option"); + expect(renderedOptions[3].getAttribute("aria-disabled")).toEqual("true"); const optionIDs = renderedOptions.map((option) => option.id); const uniqueIDs = uniq(optionIDs); expect(uniqueIDs.length).toEqual(optionIDs.length); // Label matches the input id - const renderedLabel = document.querySelector('label'); - expect(renderedLabel!.getAttribute('for')).toEqual(renderedTextbox.getAttribute('id')); + const renderedLabel = document.querySelector("label"); + expect(renderedLabel!.getAttribute("for")).toEqual(renderedTextbox.getAttribute("id")); }); - it('should clear the input on selection', async () => { + it("should clear the input on selection", async () => { render(, { wrapper: ThemeWrapper, }); // Open the combobox - const renderedCombobox = screen.getByRole('combobox'); + const renderedCombobox = screen.getByRole("combobox"); fireEvent.click(renderedCombobox); // Focus the textbox - const renderedTextbox = screen.getByRole('textbox'); + const renderedTextbox = screen.getByRole("textbox"); renderedTextbox.focus(); // Value should be '' - expect(renderedTextbox.getAttribute('value')).toEqual(''); + expect(renderedTextbox.getAttribute("value")).toEqual(""); // Change the value to 'Al' - fireEvent.change(renderedTextbox, {target: {value: 'Al'}}); - expect(renderedTextbox.getAttribute('value')).toEqual('Al'); + fireEvent.change(renderedTextbox, { target: { value: "Al" } }); + expect(renderedTextbox.getAttribute("value")).toEqual("Al"); // Selecting an option clears the value in the input box - const renderedOptions = screen.getAllByRole('option'); + const renderedOptions = screen.getAllByRole("option"); fireEvent.click(renderedOptions[0]); - expect(renderedTextbox.getAttribute('value')).toEqual(''); + expect(renderedTextbox.getAttribute("value")).toEqual(""); }); - it('should handle required correctly', async () => { + it("should handle required correctly", async () => { render(, { wrapper: ThemeWrapper, }); // Open the combobox - const renderedCombobox = screen.getByRole('combobox'); + const renderedCombobox = screen.getByRole("combobox"); fireEvent.click(renderedCombobox); // Focus the textbox - const renderedTextbox = screen.getByRole('textbox'); + const renderedTextbox = screen.getByRole("textbox"); renderedTextbox.focus(); expect(onKeyDownMock).toHaveBeenCalledTimes(0); - fireEvent.keyDown(renderedTextbox, {key: 'Enter', code: 'Enter'}); + fireEvent.keyDown(renderedTextbox, { key: "Enter", code: "Enter" }); expect(onKeyDownMock).toHaveBeenCalledTimes(1); // No form submit @@ -233,23 +233,23 @@ describe('MultiselectCombobox', () => { }); }); - describe('Groups', () => { - it('should render a group of options', () => { - render(, {wrapper: ThemeWrapper}); - const renderedGroups = screen.getAllByRole('group'); + describe("Groups", () => { + it("should render a group of options", () => { + render(, { wrapper: ThemeWrapper }); + const renderedGroups = screen.getAllByRole("group"); // check groups, group label and number of options per group - expect(renderedGroups[0].getAttribute('aria-label')).toEqual('Components'); + expect(renderedGroups[0].getAttribute("aria-label")).toEqual("Components"); expect(renderedGroups[0].querySelectorAll('[role="option"]').length).toEqual(8); - expect(renderedGroups[1].getAttribute('aria-label')).toEqual('Primitives'); + expect(renderedGroups[1].getAttribute("aria-label")).toEqual("Primitives"); expect(renderedGroups[1].querySelectorAll('[role="option"]').length).toEqual(3); - expect(renderedGroups[2].getAttribute('aria-label')).toEqual('Layout'); + expect(renderedGroups[2].getAttribute("aria-label")).toEqual("Layout"); expect(renderedGroups[2].querySelectorAll('[role="option"]').length).toEqual(1); }); - it('should render any items not identified as part of the group as ungrouped options', () => { - const {getAllByRole} = render(, {wrapper: ThemeWrapper}); - const [pillGroupListbox, dropdownListbox] = getAllByRole('listbox'); - const renderedGroups = getAllByRole('group'); + it("should render any items not identified as part of the group as ungrouped options", () => { + const { getAllByRole } = render(, { wrapper: ThemeWrapper }); + const [pillGroupListbox, dropdownListbox] = getAllByRole("listbox"); + const renderedGroups = getAllByRole("group"); // Check there's a listbox for the pill group expect(pillGroupListbox).toBeDefined(); @@ -258,82 +258,82 @@ describe('MultiselectCombobox', () => { expect(renderedGroups.length).toEqual(3); // check any options that are not nested in groups expect( - dropdownListbox.querySelectorAll('[role="listbox"] > [role="presentation"] > [role="option"]').length + dropdownListbox.querySelectorAll('[role="listbox"] > [role="presentation"] > [role="option"]').length, ).toEqual(1); }); - it('should render a listbox with groups of options that contains no duplicate ids', () => { - render(, {wrapper: ThemeWrapper}); - const renderedOptions = screen.getAllByRole('option'); + it("should render a listbox with groups of options that contains no duplicate ids", () => { + render(, { wrapper: ThemeWrapper }); + const renderedOptions = screen.getAllByRole("option"); const optionIDs = renderedOptions.map((option) => option.id); const uniqueIDs = uniq(optionIDs); expect(uniqueIDs.length).toEqual(optionIDs.length); }); - it('should render a custom group label', () => { + it("should render a custom group label", () => { render( hi {groupName}} />, { wrapper: ThemeWrapper, }); - const renderedGroups = screen.getAllByRole('group'); + const renderedGroups = screen.getAllByRole("group"); expect(renderedGroups[0].querySelector('[role="group"] > li[role="presentation"]')!.textContent).toEqual( - 'hi Components' + "hi Components", ); expect(renderedGroups[1].querySelector('[role="group"] > li[role="presentation"]')!.textContent).toEqual( - 'hi Primitives' + "hi Primitives", ); expect(renderedGroups[2].querySelector('[role="group"] > li[role="presentation"]')!.textContent).toEqual( - 'hi Layout' + "hi Layout", ); }); - it('should select item using keyboard', () => { + it("should select item using keyboard", () => { const mockSelectedItemsChangeFn = jest.fn((selectedItems) => selectedItems); render(, { wrapper: ThemeWrapper, }); // open the combobox - fireEvent.click(screen.getByRole('textbox')); + fireEvent.click(screen.getByRole("textbox")); // select the third item using ArrowDown keyDown - fireEvent.keyDown(screen.getByRole('textbox'), {key: 'ArrowDown', code: 'ArrowDown'}); - fireEvent.keyDown(screen.getByRole('textbox'), {key: 'ArrowDown', code: 'ArrowDown'}); - fireEvent.keyDown(screen.getByRole('textbox'), {key: 'ArrowDown', code: 'ArrowDown'}); - fireEvent.keyDown(screen.getByRole('textbox'), {key: 'Enter', code: 'Enter'}); + fireEvent.keyDown(screen.getByRole("textbox"), { key: "ArrowDown", code: "ArrowDown" }); + fireEvent.keyDown(screen.getByRole("textbox"), { key: "ArrowDown", code: "ArrowDown" }); + fireEvent.keyDown(screen.getByRole("textbox"), { key: "ArrowDown", code: "ArrowDown" }); + fireEvent.keyDown(screen.getByRole("textbox"), { key: "Enter", code: "Enter" }); expect(mockSelectedItemsChangeFn).toHaveBeenCalledTimes(1); - expect(mockSelectedItemsChangeFn.mock.results[0].value).toEqual([{group: 'Components', label: 'Button'}]); + expect(mockSelectedItemsChangeFn.mock.results[0].value).toEqual([{ group: "Components", label: "Button" }]); // select the first item using ArrowUp keyDown - fireEvent.keyDown(screen.getByRole('textbox'), {key: 'ArrowUp', code: 'ArrowUp'}); - fireEvent.keyDown(screen.getByRole('textbox'), {key: 'ArrowUp', code: 'ArrowUp'}); - fireEvent.keyDown(screen.getByRole('textbox'), {key: 'Enter', code: 'Enter'}); + fireEvent.keyDown(screen.getByRole("textbox"), { key: "ArrowUp", code: "ArrowUp" }); + fireEvent.keyDown(screen.getByRole("textbox"), { key: "ArrowUp", code: "ArrowUp" }); + fireEvent.keyDown(screen.getByRole("textbox"), { key: "Enter", code: "Enter" }); expect(mockSelectedItemsChangeFn).toHaveBeenCalledTimes(2); expect(mockSelectedItemsChangeFn.mock.results[1].value).toEqual([ - {group: 'Components', label: 'Button'}, - {group: 'Components', label: 'Alert'}, + { group: "Components", label: "Button" }, + { group: "Components", label: "Alert" }, ]); - fireEvent.keyDown(screen.getByRole('textbox'), {key: 'Enter', code: 'Enter'}); + fireEvent.keyDown(screen.getByRole("textbox"), { key: "Enter", code: "Enter" }); expect(mockSelectedItemsChangeFn).toHaveBeenCalledTimes(3); - expect(mockSelectedItemsChangeFn.mock.results[2].value).toEqual([{group: 'Components', label: 'Button'}]); + expect(mockSelectedItemsChangeFn.mock.results[2].value).toEqual([{ group: "Components", label: "Button" }]); }); }); - describe('Inversion of control', () => { - it('allows clearing selected items from an external button click', () => { + describe("Inversion of control", () => { + it("allows clearing selected items from an external button click", () => { const mockSelectedItemsChangeFn = jest.fn((selectedItems) => selectedItems); render(, { wrapper: ThemeWrapper, }); - const pillGroup = screen.getAllByRole('listbox')[0]; + const pillGroup = screen.getAllByRole("listbox")[0]; expect(pillGroup?.childNodes.length).toBe(2); act(() => { - screen.getByRole('button', {name: 'Clear'}).click(); + screen.getByRole("button", { name: "Clear" }).click(); }); expect(pillGroup?.childNodes.length).toBe(0); expect(mockSelectedItemsChangeFn).toHaveBeenCalledTimes(1); - expect(mockSelectedItemsChangeFn.mock.results[0].value).toEqual({activeIndex: -1, selectedItems: [], type: 10}); + expect(mockSelectedItemsChangeFn.mock.results[0].value).toEqual({ activeIndex: -1, selectedItems: [], type: 10 }); }); }); }); diff --git a/packages/paste-core/components/combobox/__tests__/combobox-customization.spec.tsx b/packages/paste-core/components/combobox/__tests__/combobox-customization.spec.tsx index 53d37c8d13..cff9b36291 100644 --- a/packages/paste-core/components/combobox/__tests__/combobox-customization.spec.tsx +++ b/packages/paste-core/components/combobox/__tests__/combobox-customization.spec.tsx @@ -1,30 +1,30 @@ -import * as React from 'react'; -import {render, screen} from '@testing-library/react'; -import type {RenderOptions} from '@testing-library/react'; -import {CustomizationProvider} from '@twilio-paste/customization'; -import type {PasteCustomCSS} from '@twilio-paste/customization'; -import {InformationIcon} from '@twilio-paste/icons/esm/InformationIcon'; -import {Text} from '@twilio-paste/text'; +import { render, screen } from "@testing-library/react"; +import type { RenderOptions } from "@testing-library/react"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import type { PasteCustomCSS } from "@twilio-paste/customization"; +import { InformationIcon } from "@twilio-paste/icons/esm/InformationIcon"; +import { Text } from "@twilio-paste/text"; +import * as React from "react"; -import {Combobox} from '../src'; +import { Combobox } from "../src"; -const getStyles = (element = 'COMBOBOX'): {[key: string]: PasteCustomCSS} => ({ - [`${element}_WRAPPER`]: {backgroundColor: 'colorBackgroundStrong', fontFamily: 'fontFamilyCode'}, - [`${element}`]: {backgroundColor: 'colorBackgroundPrimaryWeakest'}, - [`${element}_ELEMENT`]: {cursor: 'pointer'}, - [`${element}_CHEVRON_WRAPPER`]: {backgroundColor: 'colorBackgroundBrandHighlightWeakest'}, - [`${element}_LISTBOX`]: {backgroundColor: 'colorBackgroundPrimaryWeaker'}, - [`${element}_LIST`]: {backgroundColor: 'colorBackgroundPrimaryWeak'}, - [`${element}_GROUPNAME`]: {fontFamily: 'fontFamilyText', cursor: 'help'}, - [`${element}_GROUPNAME_TEXT`]: {fontWeight: 'fontWeightLight'}, - [`${element}_LIST_ITEM`]: {backgroundColor: 'colorBackgroundPrimaryStrong'}, - [`${element}_LIST_ITEM_TEXT`]: {color: 'colorTextWeakest', fontWeight: 'fontWeightBold'}, - [`${element}_PREFIX`]: {backgroundColor: 'colorBackgroundRequired', borderRadius: 'borderRadius20'}, - [`${element}_SUFFIX`]: {backgroundColor: 'colorBackgroundSubaccount', borderRadius: 'borderRadiusCircle'}, +const getStyles = (element = "COMBOBOX"): { [key: string]: PasteCustomCSS } => ({ + [`${element}_WRAPPER`]: { backgroundColor: "colorBackgroundStrong", fontFamily: "fontFamilyCode" }, + [`${element}`]: { backgroundColor: "colorBackgroundPrimaryWeakest" }, + [`${element}_ELEMENT`]: { cursor: "pointer" }, + [`${element}_CHEVRON_WRAPPER`]: { backgroundColor: "colorBackgroundBrandHighlightWeakest" }, + [`${element}_LISTBOX`]: { backgroundColor: "colorBackgroundPrimaryWeaker" }, + [`${element}_LIST`]: { backgroundColor: "colorBackgroundPrimaryWeak" }, + [`${element}_GROUPNAME`]: { fontFamily: "fontFamilyText", cursor: "help" }, + [`${element}_GROUPNAME_TEXT`]: { fontWeight: "fontWeightLight" }, + [`${element}_LIST_ITEM`]: { backgroundColor: "colorBackgroundPrimaryStrong" }, + [`${element}_LIST_ITEM_TEXT`]: { color: "colorTextWeakest", fontWeight: "fontWeightBold" }, + [`${element}_PREFIX`]: { backgroundColor: "colorBackgroundRequired", borderRadius: "borderRadius20" }, + [`${element}_SUFFIX`]: { backgroundColor: "colorBackgroundSubaccount", borderRadius: "borderRadiusCircle" }, }); -const initCustomizationWrapper = (elementName?: string | undefined): RenderOptions['wrapper'] => - function Wrapper({children}) { +const initCustomizationWrapper = (elementName?: string | undefined): RenderOptions["wrapper"] => + function Wrapper({ children }) { return ( {children} @@ -32,12 +32,12 @@ const initCustomizationWrapper = (elementName?: string | undefined): RenderOptio ); }; -const ComboboxToTest = ({element = 'COMBOBOX'}): React.ReactElement => ( +const ComboboxToTest = ({ element = "COMBOBOX" }): React.ReactElement => ( ( initialIsOpen element={element} optionTemplate={(item) =>
{item.number}
} - itemToString={(item) => (item ? item.letter : '')} + itemToString={(item) => (item ? item.letter : "")} insertBefore={Z} insertAfter={} /> ); -describe('Combobox data-paste-element attributes', () => { - it('should set the correct attributes on all Combobox components', () => { - const {container} = render(, {wrapper: initCustomizationWrapper()}); +describe("Combobox data-paste-element attributes", () => { + it("should set the correct attributes on all Combobox components", () => { + const { container } = render(, { wrapper: initCustomizationWrapper() }); expect(container.querySelector('[data-paste-element="COMBOBOX"]')).toBeInTheDocument(); expect(container.querySelector('[data-paste-element="COMBOBOX_WRAPPER"]')).toBeInTheDocument(); expect(container.querySelector('[data-paste-element="COMBOBOX_ELEMENT"]')).toBeInTheDocument(); expect(container.querySelector('[data-paste-element="COMBOBOX_CHEVRON_WRAPPER"]')).toBeInTheDocument(); - expect(screen.getByRole('listbox').getAttribute('data-paste-element')).toEqual('COMBOBOX_LISTBOX'); - expect(screen.getAllByRole('group')[0].getAttribute('data-paste-element')).toEqual('COMBOBOX_LIST'); - expect(screen.getAllByRole('presentation')).toHaveLength(2); - expect(screen.getAllByRole('presentation')[0].getAttribute('data-paste-element')).toEqual('COMBOBOX_GROUPNAME'); - expect(screen.getAllByRole('option')).toHaveLength(3); - expect(screen.getAllByRole('option')[0].getAttribute('data-paste-element')).toEqual('COMBOBOX_LIST_ITEM'); - expect(screen.getByRole('listbox').querySelectorAll('[data-paste-element="COMBOBOX_LIST_ITEM_TEXT"]')).toHaveLength( - 3 + expect(screen.getByRole("listbox").getAttribute("data-paste-element")).toEqual("COMBOBOX_LISTBOX"); + expect(screen.getAllByRole("group")[0].getAttribute("data-paste-element")).toEqual("COMBOBOX_LIST"); + expect(screen.getAllByRole("presentation")).toHaveLength(2); + expect(screen.getAllByRole("presentation")[0].getAttribute("data-paste-element")).toEqual("COMBOBOX_GROUPNAME"); + expect(screen.getAllByRole("option")).toHaveLength(3); + expect(screen.getAllByRole("option")[0].getAttribute("data-paste-element")).toEqual("COMBOBOX_LIST_ITEM"); + expect(screen.getByRole("listbox").querySelectorAll('[data-paste-element="COMBOBOX_LIST_ITEM_TEXT"]')).toHaveLength( + 3, ); expect(container.querySelector('[data-paste-element="COMBOBOX_PREFIX"]')).toBeInTheDocument(); expect(container.querySelector('[data-paste-element="COMBOBOX_SUFFIX"]')).toBeInTheDocument(); }); - it('should set the correct attributes on all Combobox components with custom element prop', () => { - const {container} = render(, {wrapper: initCustomizationWrapper()}); + it("should set the correct attributes on all Combobox components with custom element prop", () => { + const { container } = render(, { wrapper: initCustomizationWrapper() }); expect(container.querySelector('[data-paste-element="FOO"]')).toBeInTheDocument(); expect(container.querySelector('[data-paste-element="FOO_WRAPPER"]')).toBeInTheDocument(); expect(container.querySelector('[data-paste-element="FOO_ELEMENT"]')).toBeInTheDocument(); expect(container.querySelector('[data-paste-element="FOO_CHEVRON_WRAPPER"]')).toBeInTheDocument(); - expect(screen.getByRole('listbox').getAttribute('data-paste-element')).toEqual('FOO_LISTBOX'); - expect(screen.getAllByRole('group')[0].getAttribute('data-paste-element')).toEqual('FOO_LIST'); - expect(screen.getAllByRole('presentation')).toHaveLength(2); - expect(screen.getAllByRole('presentation')[0].getAttribute('data-paste-element')).toEqual('FOO_GROUPNAME'); - expect(screen.getAllByRole('option')).toHaveLength(3); - expect(screen.getAllByRole('option')[0].getAttribute('data-paste-element')).toEqual('FOO_LIST_ITEM'); - expect(screen.getByRole('listbox').querySelectorAll('[data-paste-element="FOO_LIST_ITEM_TEXT"]')).toHaveLength(3); + expect(screen.getByRole("listbox").getAttribute("data-paste-element")).toEqual("FOO_LISTBOX"); + expect(screen.getAllByRole("group")[0].getAttribute("data-paste-element")).toEqual("FOO_LIST"); + expect(screen.getAllByRole("presentation")).toHaveLength(2); + expect(screen.getAllByRole("presentation")[0].getAttribute("data-paste-element")).toEqual("FOO_GROUPNAME"); + expect(screen.getAllByRole("option")).toHaveLength(3); + expect(screen.getAllByRole("option")[0].getAttribute("data-paste-element")).toEqual("FOO_LIST_ITEM"); + expect(screen.getByRole("listbox").querySelectorAll('[data-paste-element="FOO_LIST_ITEM_TEXT"]')).toHaveLength(3); expect(container.querySelector('[data-paste-element="FOO_PREFIX"]')).toBeInTheDocument(); expect(container.querySelector('[data-paste-element="FOO_SUFFIX"]')).toBeInTheDocument(); }); }); -describe('Combobox customization', () => { - it('should add styles to Combobox', () => { - const {container} = render(, {wrapper: initCustomizationWrapper('COMBOBOX')}); +describe("Combobox customization", () => { + it("should add styles to Combobox", () => { + const { container } = render(, { wrapper: initCustomizationWrapper("COMBOBOX") }); expect(container.querySelector('[data-paste-element="COMBOBOX"]')).toHaveStyleRule( - 'background-color', - 'rgb(235, 244, 255)' + "background-color", + "rgb(235, 244, 255)", ); expect(container.querySelector('[data-paste-element="COMBOBOX_WRAPPER"]')).toHaveStyleRule( - 'background-color', - 'rgb(225, 227, 234)' + "background-color", + "rgb(225, 227, 234)", ); - expect(container.querySelector('[data-paste-element="COMBOBOX_ELEMENT"]')).toHaveStyleRule('cursor', 'pointer'); + expect(container.querySelector('[data-paste-element="COMBOBOX_ELEMENT"]')).toHaveStyleRule("cursor", "pointer"); expect(container.querySelector('[data-paste-element="COMBOBOX_CHEVRON_WRAPPER"]')).toHaveStyleRule( - 'background-color', - 'rgba(242, 47, 70, 0.1)' + "background-color", + "rgba(242, 47, 70, 0.1)", ); - const listbox = screen.getByRole('listbox'); + const listbox = screen.getByRole("listbox"); - expect(listbox).toHaveStyleRule('background-color', 'rgb(204, 228, 255)'); + expect(listbox).toHaveStyleRule("background-color", "rgb(204, 228, 255)"); expect(listbox.querySelector('[data-paste-element="COMBOBOX_LIST"]')).toHaveStyleRule( - 'background-color', - 'rgb(153, 205, 255)' + "background-color", + "rgb(153, 205, 255)", ); - expect(listbox.querySelector('[data-paste-element="COMBOBOX_GROUPNAME"]')).toHaveStyleRule('cursor', 'help'); + expect(listbox.querySelector('[data-paste-element="COMBOBOX_GROUPNAME"]')).toHaveStyleRule("cursor", "help"); expect(listbox.querySelector('[data-paste-element="COMBOBOX_LIST_ITEM"]')).toHaveStyleRule( - 'background-color', - 'rgb(0, 20, 137)' + "background-color", + "rgb(0, 20, 137)", ); expect(listbox.querySelector('[data-paste-element="COMBOBOX_LIST_ITEM_TEXT"]')).toHaveStyleRule( - 'font-weight', - '700' + "font-weight", + "700", ); expect(container.querySelector('[data-paste-element="COMBOBOX_PREFIX"]')).toHaveStyleRule( - 'background-color', - 'rgb(235, 86, 86)' + "background-color", + "rgb(235, 86, 86)", ); expect(container.querySelector('[data-paste-element="COMBOBOX_SUFFIX"]')).toHaveStyleRule( - 'background-color', - 'rgb(255, 241, 179)' + "background-color", + "rgb(255, 241, 179)", ); }); - it('should add styles to Combobox with custom element attribute', () => { - const {container} = render(, {wrapper: initCustomizationWrapper('FOO')}); + it("should add styles to Combobox with custom element attribute", () => { + const { container } = render(, { wrapper: initCustomizationWrapper("FOO") }); expect(container.querySelector('[data-paste-element="FOO"]')).toHaveStyleRule( - 'background-color', - 'rgb(235, 244, 255)' + "background-color", + "rgb(235, 244, 255)", ); expect(container.querySelector('[data-paste-element="FOO_WRAPPER"]')).toHaveStyleRule( - 'background-color', - 'rgb(225, 227, 234)' + "background-color", + "rgb(225, 227, 234)", ); - expect(container.querySelector('[data-paste-element="FOO_ELEMENT"]')).toHaveStyleRule('cursor', 'pointer'); + expect(container.querySelector('[data-paste-element="FOO_ELEMENT"]')).toHaveStyleRule("cursor", "pointer"); expect(container.querySelector('[data-paste-element="FOO_CHEVRON_WRAPPER"]')).toHaveStyleRule( - 'background-color', - 'rgba(242, 47, 70, 0.1)' + "background-color", + "rgba(242, 47, 70, 0.1)", ); - expect(screen.getByRole('listbox')).toHaveStyleRule('background-color', 'rgb(204, 228, 255)'); - expect(screen.getByRole('listbox').querySelector('[data-paste-element="FOO_LIST"]')).toHaveStyleRule( - 'background-color', - 'rgb(153, 205, 255)' + expect(screen.getByRole("listbox")).toHaveStyleRule("background-color", "rgb(204, 228, 255)"); + expect(screen.getByRole("listbox").querySelector('[data-paste-element="FOO_LIST"]')).toHaveStyleRule( + "background-color", + "rgb(153, 205, 255)", ); - expect(screen.getByRole('listbox').querySelector('[data-paste-element="FOO_GROUPNAME"]')).toHaveStyleRule( - 'cursor', - 'help' + expect(screen.getByRole("listbox").querySelector('[data-paste-element="FOO_GROUPNAME"]')).toHaveStyleRule( + "cursor", + "help", ); - expect(screen.getByRole('listbox').querySelector('[data-paste-element="FOO_LIST_ITEM"]')).toHaveStyleRule( - 'background-color', - 'rgb(0, 20, 137)' + expect(screen.getByRole("listbox").querySelector('[data-paste-element="FOO_LIST_ITEM"]')).toHaveStyleRule( + "background-color", + "rgb(0, 20, 137)", ); - expect(screen.getByRole('listbox').querySelector('[data-paste-element="FOO_LIST_ITEM_TEXT"]')).toHaveStyleRule( - 'font-weight', - '700' + expect(screen.getByRole("listbox").querySelector('[data-paste-element="FOO_LIST_ITEM_TEXT"]')).toHaveStyleRule( + "font-weight", + "700", ); expect(container.querySelector('[data-paste-element="FOO_PREFIX"]')).toHaveStyleRule( - 'background-color', - 'rgb(235, 86, 86)' + "background-color", + "rgb(235, 86, 86)", ); expect(container.querySelector('[data-paste-element="FOO_SUFFIX"]')).toHaveStyleRule( - 'background-color', - 'rgb(255, 241, 179)' + "background-color", + "rgb(255, 241, 179)", ); }); }); diff --git a/packages/paste-core/components/combobox/__tests__/multiselect-combobox-customization.spec.tsx b/packages/paste-core/components/combobox/__tests__/multiselect-combobox-customization.spec.tsx index fedc8bbafc..62915494d4 100644 --- a/packages/paste-core/components/combobox/__tests__/multiselect-combobox-customization.spec.tsx +++ b/packages/paste-core/components/combobox/__tests__/multiselect-combobox-customization.spec.tsx @@ -1,32 +1,32 @@ -import * as React from 'react'; -import {render, screen} from '@testing-library/react'; -import type {RenderOptions} from '@testing-library/react'; -import {CustomizationProvider} from '@twilio-paste/customization'; -import type {PasteCustomCSS} from '@twilio-paste/customization'; -import {InformationIcon} from '@twilio-paste/icons/esm/InformationIcon'; -import {Text} from '@twilio-paste/text'; - -import {MultiselectCombobox} from '../src'; - -const getStyles = (element = 'MULTISELECT_COMBOBOX'): {[key: string]: PasteCustomCSS} => ({ - [`${element}_WRAPPER`]: {backgroundColor: 'colorBackgroundStrong', fontFamily: 'fontFamilyCode'}, - [`${element}`]: {backgroundColor: 'colorBackgroundPrimaryWeakest'}, - [`${element}_PILL_GROUP`]: {backgroundColor: 'colorBackgroundWarning'}, - [`${element}_PILL`]: {backgroundColor: 'colorBackgroundWarningWeakest'}, - [`${element}_ELEMENT`]: {cursor: 'pointer'}, - [`${element}_CHEVRON_WRAPPER`]: {backgroundColor: 'colorBackgroundBrandHighlightWeakest'}, - [`${element}_LISTBOX`]: {backgroundColor: 'colorBackgroundPrimaryWeaker'}, - [`${element}_LIST`]: {backgroundColor: 'colorBackgroundPrimaryWeak'}, - [`${element}_GROUPNAME`]: {fontFamily: 'fontFamilyText', cursor: 'help'}, - [`${element}_GROUPNAME_TEXT`]: {fontWeight: 'fontWeightLight'}, - [`${element}_LIST_ITEM`]: {backgroundColor: 'colorBackgroundPrimaryStrong'}, - [`${element}_LIST_ITEM_TEXT`]: {color: 'colorTextWeakest', fontWeight: 'fontWeightBold'}, - [`${element}_PREFIX`]: {backgroundColor: 'colorBackgroundRequired', borderRadius: 'borderRadius20'}, - [`${element}_SUFFIX`]: {backgroundColor: 'colorBackgroundSubaccount', borderRadius: 'borderRadiusCircle'}, +import { render, screen } from "@testing-library/react"; +import type { RenderOptions } from "@testing-library/react"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import type { PasteCustomCSS } from "@twilio-paste/customization"; +import { InformationIcon } from "@twilio-paste/icons/esm/InformationIcon"; +import { Text } from "@twilio-paste/text"; +import * as React from "react"; + +import { MultiselectCombobox } from "../src"; + +const getStyles = (element = "MULTISELECT_COMBOBOX"): { [key: string]: PasteCustomCSS } => ({ + [`${element}_WRAPPER`]: { backgroundColor: "colorBackgroundStrong", fontFamily: "fontFamilyCode" }, + [`${element}`]: { backgroundColor: "colorBackgroundPrimaryWeakest" }, + [`${element}_PILL_GROUP`]: { backgroundColor: "colorBackgroundWarning" }, + [`${element}_PILL`]: { backgroundColor: "colorBackgroundWarningWeakest" }, + [`${element}_ELEMENT`]: { cursor: "pointer" }, + [`${element}_CHEVRON_WRAPPER`]: { backgroundColor: "colorBackgroundBrandHighlightWeakest" }, + [`${element}_LISTBOX`]: { backgroundColor: "colorBackgroundPrimaryWeaker" }, + [`${element}_LIST`]: { backgroundColor: "colorBackgroundPrimaryWeak" }, + [`${element}_GROUPNAME`]: { fontFamily: "fontFamilyText", cursor: "help" }, + [`${element}_GROUPNAME_TEXT`]: { fontWeight: "fontWeightLight" }, + [`${element}_LIST_ITEM`]: { backgroundColor: "colorBackgroundPrimaryStrong" }, + [`${element}_LIST_ITEM_TEXT`]: { color: "colorTextWeakest", fontWeight: "fontWeightBold" }, + [`${element}_PREFIX`]: { backgroundColor: "colorBackgroundRequired", borderRadius: "borderRadius20" }, + [`${element}_SUFFIX`]: { backgroundColor: "colorBackgroundSubaccount", borderRadius: "borderRadiusCircle" }, }); -const initCustomizationWrapper = (elementName?: string | undefined): RenderOptions['wrapper'] => - function Wrapper({children}) { +const initCustomizationWrapper = (elementName?: string | undefined): RenderOptions["wrapper"] => + function Wrapper({ children }) { return ( {children} @@ -35,12 +35,12 @@ const initCustomizationWrapper = (elementName?: string | undefined): RenderOptio }; const items = [ - {letter: 'a', number: 1}, - {letter: 'a', number: 2}, - {letter: 'b', number: 3}, + { letter: "a", number: 1 }, + { letter: "a", number: 2 }, + { letter: "b", number: 3 }, ]; -const MultiselectComboboxToTest = ({element = 'MULTISELECT_COMBOBOX'}): React.ReactElement => ( +const MultiselectComboboxToTest = ({ element = "MULTISELECT_COMBOBOX" }): React.ReactElement => (
{item.number}
} - itemToString={(item) => (item ? item.letter : '')} + itemToString={(item) => (item ? item.letter : "")} insertBefore={Z} insertAfter={} /> ); -describe('MultiselectCombobox data-paste-element attributes', () => { - it('should set the correct attributes on all MultiselectCombobox components', () => { - const {container, getByRole} = render(, {wrapper: initCustomizationWrapper()}); - expect(getByRole('textbox').dataset.pasteElement).toEqual('MULTISELECT_COMBOBOX_ELEMENT'); +describe("MultiselectCombobox data-paste-element attributes", () => { + it("should set the correct attributes on all MultiselectCombobox components", () => { + const { container, getByRole } = render(, { wrapper: initCustomizationWrapper() }); + expect(getByRole("textbox").dataset.pasteElement).toEqual("MULTISELECT_COMBOBOX_ELEMENT"); expect(container.querySelector('[data-paste-element="MULTISELECT_COMBOBOX"]')).toBeInTheDocument(); expect(container.querySelector('[data-paste-element="MULTISELECT_COMBOBOX_WRAPPER"]')).toBeInTheDocument(); expect(container.querySelector('[data-paste-element="MULTISELECT_COMBOBOX_ELEMENT"]')).toBeInTheDocument(); @@ -67,53 +67,53 @@ describe('MultiselectCombobox data-paste-element attributes', () => { expect(container.querySelectorAll(`[data-paste-element="MULTISELECT_COMBOBOX_PILL"]`).length).toEqual(2); expect( - container.querySelectorAll(`[data-paste-element="MULTISELECT_COMBOBOX_PILL"]`)[0].getAttribute('role') - ).toEqual('option'); + container.querySelectorAll(`[data-paste-element="MULTISELECT_COMBOBOX_PILL"]`)[0].getAttribute("role"), + ).toEqual("option"); - const dropdownlistbox = screen.getByRole('listbox', {name: 'Choose a letter:'}); + const dropdownlistbox = screen.getByRole("listbox", { name: "Choose a letter:" }); expect(dropdownlistbox.querySelectorAll(`[data-paste-element="MULTISELECT_COMBOBOX_LIST_ITEM"]`).length).toEqual(3); expect( - dropdownlistbox.querySelectorAll(`[data-paste-element="MULTISELECT_COMBOBOX_LIST_ITEM"]`)[0].getAttribute('role') - ).toEqual('option'); + dropdownlistbox.querySelectorAll(`[data-paste-element="MULTISELECT_COMBOBOX_LIST_ITEM"]`)[0].getAttribute("role"), + ).toEqual("option"); - const [pillgroupListbox, comboboxListbox] = screen.getAllByRole('listbox'); - expect(pillgroupListbox.getAttribute('data-paste-element')).toEqual('MULTISELECT_COMBOBOX_PILL_GROUP'); - expect(comboboxListbox.getAttribute('data-paste-element')).toEqual('MULTISELECT_COMBOBOX_LISTBOX'); - expect(screen.getAllByRole('group')[0].getAttribute('data-paste-element')).toEqual('MULTISELECT_COMBOBOX_LIST'); - expect(screen.getAllByRole('presentation')).toHaveLength(2); - expect(screen.getAllByRole('presentation')[0].getAttribute('data-paste-element')).toEqual( - 'MULTISELECT_COMBOBOX_GROUPNAME' + const [pillgroupListbox, comboboxListbox] = screen.getAllByRole("listbox"); + expect(pillgroupListbox.getAttribute("data-paste-element")).toEqual("MULTISELECT_COMBOBOX_PILL_GROUP"); + expect(comboboxListbox.getAttribute("data-paste-element")).toEqual("MULTISELECT_COMBOBOX_LISTBOX"); + expect(screen.getAllByRole("group")[0].getAttribute("data-paste-element")).toEqual("MULTISELECT_COMBOBOX_LIST"); + expect(screen.getAllByRole("presentation")).toHaveLength(2); + expect(screen.getAllByRole("presentation")[0].getAttribute("data-paste-element")).toEqual( + "MULTISELECT_COMBOBOX_GROUPNAME", ); expect(dropdownlistbox.querySelectorAll('[data-paste-element="MULTISELECT_COMBOBOX_LIST_ITEM_TEXT"]')).toHaveLength( - 3 + 3, ); expect(container.querySelector('[data-paste-element="MULTISELECT_COMBOBOX_PREFIX"]')).toBeInTheDocument(); expect(container.querySelector('[data-paste-element="MULTISELECT_COMBOBOX_SUFFIX"]')).toBeInTheDocument(); }); - it('should set the correct attributes on all MultiselectCombobox components with custom element prop', () => { - const {container} = render(, {wrapper: initCustomizationWrapper()}); + it("should set the correct attributes on all MultiselectCombobox components with custom element prop", () => { + const { container } = render(, { wrapper: initCustomizationWrapper() }); expect(container.querySelector('[data-paste-element="FOO"]')).toBeInTheDocument(); expect(container.querySelector('[data-paste-element="FOO_WRAPPER"]')).toBeInTheDocument(); expect(container.querySelector('[data-paste-element="FOO_ELEMENT"]')).toBeInTheDocument(); expect(container.querySelector('[data-paste-element="FOO_CHEVRON_WRAPPER"]')).toBeInTheDocument(); expect(container.querySelectorAll(`[data-paste-element="FOO_PILL"]`).length).toEqual(2); - expect(container.querySelectorAll(`[data-paste-element="FOO_PILL"]`)[0].getAttribute('role')).toEqual('option'); + expect(container.querySelectorAll(`[data-paste-element="FOO_PILL"]`)[0].getAttribute("role")).toEqual("option"); - const [pillgroupListbox, comboboxListbox] = screen.getAllByRole('listbox'); + const [pillgroupListbox, comboboxListbox] = screen.getAllByRole("listbox"); expect(comboboxListbox.querySelectorAll(`[data-paste-element="FOO_LIST_ITEM"]`).length).toEqual(3); - expect(comboboxListbox.querySelectorAll(`[data-paste-element="FOO_LIST_ITEM"]`)[0].getAttribute('role')).toEqual( - 'option' + expect(comboboxListbox.querySelectorAll(`[data-paste-element="FOO_LIST_ITEM"]`)[0].getAttribute("role")).toEqual( + "option", ); - expect(pillgroupListbox.getAttribute('data-paste-element')).toEqual('FOO_PILL_GROUP'); - expect(comboboxListbox.getAttribute('data-paste-element')).toEqual('FOO_LISTBOX'); - expect(screen.getAllByRole('group')[0].getAttribute('data-paste-element')).toEqual('FOO_LIST'); - expect(screen.getAllByRole('presentation')).toHaveLength(2); - expect(screen.getAllByRole('presentation')[0].getAttribute('data-paste-element')).toEqual('FOO_GROUPNAME'); + expect(pillgroupListbox.getAttribute("data-paste-element")).toEqual("FOO_PILL_GROUP"); + expect(comboboxListbox.getAttribute("data-paste-element")).toEqual("FOO_LISTBOX"); + expect(screen.getAllByRole("group")[0].getAttribute("data-paste-element")).toEqual("FOO_LIST"); + expect(screen.getAllByRole("presentation")).toHaveLength(2); + expect(screen.getAllByRole("presentation")[0].getAttribute("data-paste-element")).toEqual("FOO_GROUPNAME"); expect(comboboxListbox.querySelectorAll('[data-paste-element="FOO_LIST_ITEM_TEXT"]')).toHaveLength(3); expect(container.querySelector('[data-paste-element="FOO_PREFIX"]')).toBeInTheDocument(); @@ -121,96 +121,98 @@ describe('MultiselectCombobox data-paste-element attributes', () => { }); }); -describe('MultiselectCombobox customization', () => { - it('should add styles to MultiselectCombobox', () => { - const {container} = render(, { - wrapper: initCustomizationWrapper('MULTISELECT_COMBOBOX'), +describe("MultiselectCombobox customization", () => { + it("should add styles to MultiselectCombobox", () => { + const { container } = render(, { + wrapper: initCustomizationWrapper("MULTISELECT_COMBOBOX"), }); expect(container.querySelector('[data-paste-element="MULTISELECT_COMBOBOX"]')).toHaveStyleRule( - 'background-color', - 'rgb(235, 244, 255)' + "background-color", + "rgb(235, 244, 255)", ); expect(container.querySelector('[data-paste-element="MULTISELECT_COMBOBOX_WRAPPER"]')).toHaveStyleRule( - 'background-color', - 'rgb(225, 227, 234)' + "background-color", + "rgb(225, 227, 234)", ); expect(container.querySelector('[data-paste-element="MULTISELECT_COMBOBOX_ELEMENT"]')).toHaveStyleRule( - 'cursor', - 'pointer' + "cursor", + "pointer", ); expect(container.querySelector('[data-paste-element="MULTISELECT_COMBOBOX_CHEVRON_WRAPPER"]')).toHaveStyleRule( - 'background-color', - 'rgba(242, 47, 70, 0.1)' + "background-color", + "rgba(242, 47, 70, 0.1)", ); - const dropdownlistbox = screen.getByRole('listbox', {name: 'Choose a letter:'}); + const dropdownlistbox = screen.getByRole("listbox", { name: "Choose a letter:" }); - expect(dropdownlistbox).toHaveStyleRule('background-color', 'rgb(204, 228, 255)'); + expect(dropdownlistbox).toHaveStyleRule("background-color", "rgb(204, 228, 255)"); expect(dropdownlistbox.querySelector('[data-paste-element="MULTISELECT_COMBOBOX_LIST"]')).toHaveStyleRule( - 'background-color', - 'rgb(153, 205, 255)' + "background-color", + "rgb(153, 205, 255)", ); expect(dropdownlistbox.querySelector('[data-paste-element="MULTISELECT_COMBOBOX_GROUPNAME"]')).toHaveStyleRule( - 'cursor', - 'help' + "cursor", + "help", ); expect(dropdownlistbox.querySelector('[data-paste-element="MULTISELECT_COMBOBOX_LIST_ITEM"]')).toHaveStyleRule( - 'background-color', - 'rgb(0, 20, 137)' + "background-color", + "rgb(0, 20, 137)", ); expect(dropdownlistbox.querySelector('[data-paste-element="MULTISELECT_COMBOBOX_LIST_ITEM_TEXT"]')).toHaveStyleRule( - 'font-weight', - '700' + "font-weight", + "700", ); expect(container.querySelector('[data-paste-element="MULTISELECT_COMBOBOX_PREFIX"]')).toHaveStyleRule( - 'background-color', - 'rgb(235, 86, 86)' + "background-color", + "rgb(235, 86, 86)", ); expect(container.querySelector('[data-paste-element="MULTISELECT_COMBOBOX_SUFFIX"]')).toHaveStyleRule( - 'background-color', - 'rgb(255, 241, 179)' + "background-color", + "rgb(255, 241, 179)", ); }); - it('should add styles to MultiselectCombobox with custom element attribute', () => { - const {container} = render(, {wrapper: initCustomizationWrapper('FOO')}); + it("should add styles to MultiselectCombobox with custom element attribute", () => { + const { container } = render(, { + wrapper: initCustomizationWrapper("FOO"), + }); expect(container.querySelector('[data-paste-element="FOO"]')).toHaveStyleRule( - 'background-color', - 'rgb(235, 244, 255)' + "background-color", + "rgb(235, 244, 255)", ); expect(container.querySelector('[data-paste-element="FOO_WRAPPER"]')).toHaveStyleRule( - 'background-color', - 'rgb(225, 227, 234)' + "background-color", + "rgb(225, 227, 234)", ); - expect(container.querySelector('[data-paste-element="FOO_ELEMENT"]')).toHaveStyleRule('cursor', 'pointer'); + expect(container.querySelector('[data-paste-element="FOO_ELEMENT"]')).toHaveStyleRule("cursor", "pointer"); expect(container.querySelector('[data-paste-element="FOO_CHEVRON_WRAPPER"]')).toHaveStyleRule( - 'background-color', - 'rgba(242, 47, 70, 0.1)' + "background-color", + "rgba(242, 47, 70, 0.1)", ); - const dropdownlistbox = screen.getByRole('listbox', {name: 'Choose a letter:'}); + const dropdownlistbox = screen.getByRole("listbox", { name: "Choose a letter:" }); - expect(dropdownlistbox).toHaveStyleRule('background-color', 'rgb(204, 228, 255)'); + expect(dropdownlistbox).toHaveStyleRule("background-color", "rgb(204, 228, 255)"); expect(dropdownlistbox.querySelector('[data-paste-element="FOO_LIST"]')).toHaveStyleRule( - 'background-color', - 'rgb(153, 205, 255)' + "background-color", + "rgb(153, 205, 255)", ); - expect(dropdownlistbox.querySelector('[data-paste-element="FOO_GROUPNAME"]')).toHaveStyleRule('cursor', 'help'); + expect(dropdownlistbox.querySelector('[data-paste-element="FOO_GROUPNAME"]')).toHaveStyleRule("cursor", "help"); expect(dropdownlistbox.querySelector('[data-paste-element="FOO_LIST_ITEM"]')).toHaveStyleRule( - 'background-color', - 'rgb(0, 20, 137)' + "background-color", + "rgb(0, 20, 137)", ); expect(dropdownlistbox.querySelector('[data-paste-element="FOO_LIST_ITEM_TEXT"]')).toHaveStyleRule( - 'font-weight', - '700' + "font-weight", + "700", ); expect(container.querySelector('[data-paste-element="FOO_PREFIX"]')).toHaveStyleRule( - 'background-color', - 'rgb(235, 86, 86)' + "background-color", + "rgb(235, 86, 86)", ); expect(container.querySelector('[data-paste-element="FOO_SUFFIX"]')).toHaveStyleRule( - 'background-color', - 'rgb(255, 241, 179)' + "background-color", + "rgb(255, 241, 179)", ); }); }); diff --git a/packages/paste-core/components/combobox/__tests__/virtualization.spec.tsx b/packages/paste-core/components/combobox/__tests__/virtualization.spec.tsx index f853d1a0a1..76a6ac42f0 100644 --- a/packages/paste-core/components/combobox/__tests__/virtualization.spec.tsx +++ b/packages/paste-core/components/combobox/__tests__/virtualization.spec.tsx @@ -1,28 +1,28 @@ -import * as React from 'react'; -import {render, screen} from '@testing-library/react'; -import type {RenderOptions} from '@testing-library/react'; -import {matchers} from '@emotion/jest'; -import {CustomizationProvider} from '@twilio-paste/customization'; -import type {useVirtual as UseVirtual, VirtualItem} from 'react-virtual/types'; +import { matchers } from "@emotion/jest"; +import { render, screen } from "@testing-library/react"; +import type { RenderOptions } from "@testing-library/react"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import * as React from "react"; +import type { VirtualItem, useVirtual as UseVirtual } from "react-virtual/types"; -import {Combobox} from '../src'; +import { Combobox } from "../src"; const mockMeasureRef = jest.fn(); -jest.mock('react-virtual', () => { +jest.mock("react-virtual", () => { /* * mocking this to verify that the measure refs are being invoked --> they are being used * need to test this because it is essential that the virtualization ref is attached to the correct element for the virtual listbox to render correctly */ - const {useVirtual} = jest.requireActual('react-virtual'); + const { useVirtual } = jest.requireActual("react-virtual"); return { useVirtual: (config: Parameters) => { - const {virtualItems, ...returnValue} = useVirtual(config); + const { virtualItems, ...returnValue } = useVirtual(config); return { ...returnValue, - virtualItems: virtualItems.map(({measureRef, ...virtualItem}: VirtualItem) => ({ + virtualItems: virtualItems.map(({ measureRef, ...virtualItem }: VirtualItem) => ({ ...virtualItem, measureRef: mockMeasureRef.mockImplementation((element) => measureRef(element)), })), @@ -33,56 +33,56 @@ jest.mock('react-virtual', () => { expect.extend(matchers); -const CustomizationWrapper: RenderOptions['wrapper'] = ({children}) => ( +const CustomizationWrapper: RenderOptions["wrapper"] = ({ children }) => ( {children} ); -describe('Combobox - Virtualization', () => { - describe('Without option template', () => { - const items = ['a', 'b', 'c', 'd', 'e']; - it('should apply the correct height to the virtualized list box', () => { +describe("Combobox - Virtualization", () => { + describe("Without option template", () => { + const items = ["a", "b", "c", "d", "e"]; + it("should apply the correct height to the virtualized list box", () => { render(, { wrapper: CustomizationWrapper, }); - const resizedLiElement = screen.getAllByRole('presentation', {hidden: true})[1]; + const resizedLiElement = screen.getAllByRole("presentation", { hidden: true })[1]; - expect(resizedLiElement.getAttribute('style')).toEqual('margin: 0px; height: 200px;'); + expect(resizedLiElement.getAttribute("style")).toEqual("margin: 0px; height: 200px;"); }); - it('should apply the correct styles to the virtualized list box', () => { + it("should apply the correct styles to the virtualized list box", () => { render(, { wrapper: CustomizationWrapper, }); - const optionElements = screen.getAllByRole('option', {hidden: true}); + const optionElements = screen.getAllByRole("option", { hidden: true }); expect(optionElements.length).toEqual(5); const [first, second, third, fourth, fifth] = optionElements; - expect(first).toHaveStyleRule('transform', 'translateY(0px)'); - expect(first).toHaveAttribute('aria-setsize', '5'); - expect(first).toHaveAttribute('aria-posinset', '1'); + expect(first).toHaveStyleRule("transform", "translateY(0px)"); + expect(first).toHaveAttribute("aria-setsize", "5"); + expect(first).toHaveAttribute("aria-posinset", "1"); - expect(second).toHaveStyleRule('transform', 'translateY(50px)'); - expect(second).toHaveAttribute('aria-setsize', '5'); - expect(second).toHaveAttribute('aria-posinset', '2'); + expect(second).toHaveStyleRule("transform", "translateY(50px)"); + expect(second).toHaveAttribute("aria-setsize", "5"); + expect(second).toHaveAttribute("aria-posinset", "2"); - expect(third).toHaveStyleRule('transform', 'translateY(100px)'); - expect(third).toHaveAttribute('aria-setsize', '5'); - expect(third).toHaveAttribute('aria-posinset', '3'); + expect(third).toHaveStyleRule("transform", "translateY(100px)"); + expect(third).toHaveAttribute("aria-setsize", "5"); + expect(third).toHaveAttribute("aria-posinset", "3"); - expect(fourth).toHaveStyleRule('transform', 'translateY(150px)'); - expect(fourth).toHaveAttribute('aria-setsize', '5'); - expect(fourth).toHaveAttribute('aria-posinset', '4'); + expect(fourth).toHaveStyleRule("transform", "translateY(150px)"); + expect(fourth).toHaveAttribute("aria-setsize", "5"); + expect(fourth).toHaveAttribute("aria-posinset", "4"); - expect(fifth).toHaveStyleRule('transform', 'translateY(200px)'); - expect(fifth).toHaveAttribute('aria-setsize', '5'); - expect(fifth).toHaveAttribute('aria-posinset', '5'); + expect(fifth).toHaveStyleRule("transform", "translateY(200px)"); + expect(fifth).toHaveAttribute("aria-setsize", "5"); + expect(fifth).toHaveAttribute("aria-posinset", "5"); }); - it('should call the measure ref from virtualize when component is mounted', () => { + it("should call the measure ref from virtualize when component is mounted", () => { render(, { wrapper: CustomizationWrapper, }); @@ -91,104 +91,104 @@ describe('Combobox - Virtualization', () => { }); }); - describe('With option template', () => { + describe("With option template", () => { const items = [ { - label: 'a', - value: 'a-english', + label: "a", + value: "a-english", }, { - label: 'b', - value: 'b-english', + label: "b", + value: "b-english", }, { - label: 'c', - value: 'c-english', + label: "c", + value: "c-english", }, { - label: 'd', - value: 'd-english', + label: "d", + value: "d-english", }, { - label: 'e', - value: 'e-english', + label: "e", + value: "e-english", }, ]; - it('should apply the correct height to the virtualized list box', () => { + it("should apply the correct height to the virtualized list box", () => { render( label} - itemToString={({label}) => label} + optionTemplate={({ label }) => label} + itemToString={({ label }) => label} labelText="Choose a letter:" initialIsOpen />, { wrapper: CustomizationWrapper, - } + }, ); - const resizedLiElement = screen.getAllByRole('presentation', {hidden: true})[1]; + const resizedLiElement = screen.getAllByRole("presentation", { hidden: true })[1]; - expect(resizedLiElement.getAttribute('style')).toEqual('margin: 0px; height: 200px;'); + expect(resizedLiElement.getAttribute("style")).toEqual("margin: 0px; height: 200px;"); }); - it('should apply the correct styles to the virtualized list box', () => { + it("should apply the correct styles to the virtualized list box", () => { render( label} - itemToString={({label}) => label} + optionTemplate={({ label }) => label} + itemToString={({ label }) => label} labelText="Choose a letter:" initialIsOpen />, { wrapper: CustomizationWrapper, - } + }, ); - const optionElements = screen.getAllByRole('option', {hidden: true}); + const optionElements = screen.getAllByRole("option", { hidden: true }); expect(optionElements.length).toEqual(5); const [first, second, third, fourth, fifth] = optionElements; - expect(first).toHaveStyleRule('transform', 'translateY(0px)'); - expect(first).toHaveAttribute('aria-setsize', '5'); - expect(first).toHaveAttribute('aria-posinset', '1'); + expect(first).toHaveStyleRule("transform", "translateY(0px)"); + expect(first).toHaveAttribute("aria-setsize", "5"); + expect(first).toHaveAttribute("aria-posinset", "1"); - expect(second).toHaveStyleRule('transform', 'translateY(50px)'); - expect(second).toHaveAttribute('aria-setsize', '5'); - expect(second).toHaveAttribute('aria-posinset', '2'); + expect(second).toHaveStyleRule("transform", "translateY(50px)"); + expect(second).toHaveAttribute("aria-setsize", "5"); + expect(second).toHaveAttribute("aria-posinset", "2"); - expect(third).toHaveStyleRule('transform', 'translateY(100px)'); - expect(third).toHaveAttribute('aria-setsize', '5'); - expect(third).toHaveAttribute('aria-posinset', '3'); + expect(third).toHaveStyleRule("transform", "translateY(100px)"); + expect(third).toHaveAttribute("aria-setsize", "5"); + expect(third).toHaveAttribute("aria-posinset", "3"); - expect(fourth).toHaveStyleRule('transform', 'translateY(150px)'); - expect(fourth).toHaveAttribute('aria-setsize', '5'); - expect(fourth).toHaveAttribute('aria-posinset', '4'); + expect(fourth).toHaveStyleRule("transform", "translateY(150px)"); + expect(fourth).toHaveAttribute("aria-setsize", "5"); + expect(fourth).toHaveAttribute("aria-posinset", "4"); - expect(fifth).toHaveStyleRule('transform', 'translateY(200px)'); - expect(fifth).toHaveAttribute('aria-setsize', '5'); - expect(fifth).toHaveAttribute('aria-posinset', '5'); + expect(fifth).toHaveStyleRule("transform", "translateY(200px)"); + expect(fifth).toHaveAttribute("aria-setsize", "5"); + expect(fifth).toHaveAttribute("aria-posinset", "5"); }); - it('should call the measure ref from virtualize when component is mounted', () => { + it("should call the measure ref from virtualize when component is mounted", () => { render( label} - itemToString={({label}) => label} + optionTemplate={({ label }) => label} + itemToString={({ label }) => label} labelText="Choose a letter:" initialIsOpen />, { wrapper: CustomizationWrapper, - } + }, ); expect(mockMeasureRef).toHaveBeenCalled(); diff --git a/packages/paste-core/components/combobox/build.js b/packages/paste-core/components/combobox/build.js index a4edeab49b..27dd98f98e 100644 --- a/packages/paste-core/components/combobox/build.js +++ b/packages/paste-core/components/combobox/build.js @@ -1,3 +1,3 @@ -const {build} = require('../../../../tools/build/esbuild'); +const { build } = require("../../../../tools/build/esbuild"); -build(require('./package.json')); +build(require("./package.json")); diff --git a/packages/paste-core/components/combobox/src/ComboboxItems.tsx b/packages/paste-core/components/combobox/src/ComboboxItems.tsx index 895e668ea5..c43bfc38bd 100644 --- a/packages/paste-core/components/combobox/src/ComboboxItems.tsx +++ b/packages/paste-core/components/combobox/src/ComboboxItems.tsx @@ -1,21 +1,21 @@ -import * as React from 'react'; -import type {VirtualItem} from 'react-virtual'; -import find from 'lodash/find'; -import {Box} from '@twilio-paste/box'; +import { Box } from "@twilio-paste/box"; +import find from "lodash/find"; +import * as React from "react"; +import type { VirtualItem } from "react-virtual"; -import {ComboboxListboxOption} from './styles/ComboboxListboxOption'; -import {ComboboxListboxGroup} from './styles/ComboboxListboxGroup'; -import {getIndexedItems, getGroupedItems} from './helpers'; -import type {ComboboxItemsProps} from './types'; +import { getGroupedItems, getIndexedItems } from "./helpers"; +import { ComboboxListboxGroup } from "./styles/ComboboxListboxGroup"; +import { ComboboxListboxOption } from "./styles/ComboboxListboxOption"; +import type { ComboboxItemsProps } from "./types"; const ComboboxItems: React.FC< - React.PropsWithChildren & {ref: React.Ref} + React.PropsWithChildren & { ref: React.Ref } > = React.memo( React.forwardRef( ( { items, - element = 'COMBOBOX', + element = "COMBOBOX", getItemProps, highlightedIndex, selectedItems, @@ -27,14 +27,14 @@ const ComboboxItems: React.FC< virtualItems, emptyState: EmptyState, }, - ref + ref, ) => { /* * Use option template if provided * otherwise, return the items array. */ const templatizedItems = React.useMemo(() => { - return optionTemplate != null && typeof optionTemplate === 'function' + return optionTemplate != null && typeof optionTemplate === "function" ? items.map((item) => optionTemplate(item)) : items; }, [JSON.stringify(items), optionTemplate]); @@ -60,13 +60,13 @@ const ComboboxItems: React.FC< return ( -
  • - {virtualItems.map(({measureRef, index: virtualItemIndex, start}: VirtualItem) => { +
  • + {virtualItems.map(({ measureRef, index: virtualItemIndex, start }: VirtualItem) => { const item = templatizedItems[virtualItemIndex]; const disabled = disabledItems != null && disabledItems.includes(items[virtualItemIndex]); return ( {groupedItemKeys.map((groupedItemKey) => { - const isUncategorized = groupedItemKey === 'undefined'; + const isUncategorized = groupedItemKey === "undefined"; // Wrapped in '$' characters in case of clash with a provided group named "Uncategorized" - const groupKey = isUncategorized ? '$$$Uncategorized$$$' : groupedItemKey; + const groupKey = isUncategorized ? "$$$Uncategorized$$$" : groupedItemKey; return ( - {groupedItems[groupedItemKey].map(({index, ...item}: Record) => { + {groupedItems[groupedItemKey].map(({ index, ...item }: Record) => { const disabled = disabledItems != null && find(disabledItems, item); return ( {optionTemplate ? optionTemplate(item) : item} @@ -149,10 +149,10 @@ const ComboboxItems: React.FC< })} ); - } - ) + }, + ), ); -ComboboxItems.displayName = 'ComboboxItems'; +ComboboxItems.displayName = "ComboboxItems"; -export {ComboboxItems}; +export { ComboboxItems }; diff --git a/packages/paste-core/components/combobox/src/ListboxPositioner.tsx b/packages/paste-core/components/combobox/src/ListboxPositioner.tsx index dc1ac5055d..2600af38ea 100644 --- a/packages/paste-core/components/combobox/src/ListboxPositioner.tsx +++ b/packages/paste-core/components/combobox/src/ListboxPositioner.tsx @@ -1,7 +1,7 @@ -import * as React from 'react'; -import {Box, type BoxStyleProps} from '@twilio-paste/box'; -import {useRect} from '@radix-ui/react-use-rect'; -import {useWindowSize} from '@twilio-paste/utils'; +import { useRect } from "@radix-ui/react-use-rect"; +import { Box, type BoxStyleProps } from "@twilio-paste/box"; +import { useWindowSize } from "@twilio-paste/utils"; +import * as React from "react"; interface ListBoxPositionerProps { children: React.ReactNode; @@ -9,8 +9,8 @@ interface ListBoxPositionerProps { dropdownBoxRef: React.RefObject; } -export const ListBoxPositioner: React.FC = ({inputBoxRef, dropdownBoxRef, ...props}) => { - const {height: windowHeight} = useWindowSize(); +export const ListBoxPositioner: React.FC = ({ inputBoxRef, dropdownBoxRef, ...props }) => { + const { height: windowHeight } = useWindowSize(); const inputBoxDimensions = useRect(inputBoxRef.current); const dropdownBoxDimensions = useRect(dropdownBoxRef.current); const dropdownBoxHeight = dropdownBoxDimensions?.height; @@ -36,7 +36,7 @@ export const ListBoxPositioner: React.FC = ({inputBoxRef if (windowHeight) { if (dropdownBoxHeight >= windowHeight) { return { - position: 'fixed', + position: "fixed", top: 0, left: inputBoxDimensions?.left, right: inputBoxDimensions?.right, @@ -48,7 +48,7 @@ export const ListBoxPositioner: React.FC = ({inputBoxRef inputBoxDimensions?.top - dropdownBoxHeight > 0 ) { return { - position: 'fixed', + position: "fixed", // 6px to account for border things, should be fine on all themes top: inputBoxDimensions?.top - dropdownBoxHeight - 6, left: inputBoxDimensions?.left, @@ -59,7 +59,7 @@ export const ListBoxPositioner: React.FC = ({inputBoxRef } return { - position: 'fixed', + position: "fixed", top: inputBoxDimensions?.bottom, left: inputBoxDimensions?.left, right: inputBoxDimensions?.right, @@ -69,4 +69,4 @@ export const ListBoxPositioner: React.FC = ({inputBoxRef return ; }; -ListBoxPositioner.displayName = 'ListBoxPositioner'; +ListBoxPositioner.displayName = "ListBoxPositioner"; diff --git a/packages/paste-core/components/combobox/src/helpers.tsx b/packages/paste-core/components/combobox/src/helpers.tsx index 15acaade3b..4bb15179b8 100644 --- a/packages/paste-core/components/combobox/src/helpers.tsx +++ b/packages/paste-core/components/combobox/src/helpers.tsx @@ -1,9 +1,9 @@ -import type {HelpTextVariants} from '@twilio-paste/help-text'; -import type {InputVariants} from '@twilio-paste/input'; -import groupBy from 'lodash/groupBy'; -import type {BoxStyleProps} from '@twilio-paste/box'; +import type { BoxStyleProps } from "@twilio-paste/box"; +import type { HelpTextVariants } from "@twilio-paste/help-text"; +import type { InputVariants } from "@twilio-paste/input"; +import groupBy from "lodash/groupBy"; -import type {Item} from './types'; +import type { Item } from "./types"; type IndexedItem = Item & { index: number; @@ -16,38 +16,38 @@ type IndexedItem = Item & { */ export const getIndexedItems = (items: Item[]): IndexedItem[] => { return items.map((item, index) => { - if (typeof item === 'string') { - return {label: item, index}; + if (typeof item === "string") { + return { label: item, index }; } - return {...item, index}; + return { ...item, index }; }); }; // Creates a grouped object of items with the original flat array index export const getGroupedItems = (items: IndexedItem[], groupItemsBy: string): any => { - return groupBy(items, (item: Item) => (typeof item === 'string' ? 'Uncategorized' : item[groupItemsBy])); + return groupBy(items, (item: Item) => (typeof item === "string" ? "Uncategorized" : item[groupItemsBy])); }; export const getHelpTextVariant = (variant: InputVariants, hasError: boolean | undefined): HelpTextVariants => { - if (hasError && variant === 'inverse') { - return 'error_inverse'; + if (hasError && variant === "inverse") { + return "error_inverse"; } if (hasError) { - return 'error'; + return "error"; } - if (variant === 'inverse') { - return 'inverse'; + if (variant === "inverse") { + return "inverse"; } - return 'default'; + return "default"; }; export const visuallyHiddenStyles: BoxStyleProps = { - clip: 'rect(0 0 0 0)', - height: '1px', - margin: 'spaceNegative10', - overflow: 'hidden', - padding: 'space0', - position: 'absolute', - whiteSpace: 'nowrap', - width: '1px', + clip: "rect(0 0 0 0)", + height: "1px", + margin: "spaceNegative10", + overflow: "hidden", + padding: "space0", + position: "absolute", + whiteSpace: "nowrap", + width: "1px", }; diff --git a/packages/paste-core/components/combobox/src/index.tsx b/packages/paste-core/components/combobox/src/index.tsx index 56a01ec7c1..94a458f14d 100644 --- a/packages/paste-core/components/combobox/src/index.tsx +++ b/packages/paste-core/components/combobox/src/index.tsx @@ -1,15 +1,15 @@ export { useComboboxPrimitive as useCombobox, useMultiSelectPrimitive as useMultiselectCombobox, -} from '@twilio-paste/combobox-primitive'; +} from "@twilio-paste/combobox-primitive"; export type { UseComboboxPrimitiveState as UseComboboxState, UseComboboxPrimitiveStateChange as UseComboboxStateChange, -} from '@twilio-paste/combobox-primitive'; -export * from './singleselect/Combobox'; -export * from './multiselect/MultiselectCombobox'; -export * from './styles/ComboboxInputWrapper'; -export * from './styles/ComboboxListbox'; -export * from './styles/ComboboxListboxOption'; -export * from './styles/ComboboxListboxGroup'; -export type {MultiselectComboboxProps, ComboboxProps} from './types'; +} from "@twilio-paste/combobox-primitive"; +export * from "./singleselect/Combobox"; +export * from "./multiselect/MultiselectCombobox"; +export * from "./styles/ComboboxInputWrapper"; +export * from "./styles/ComboboxListbox"; +export * from "./styles/ComboboxListboxOption"; +export * from "./styles/ComboboxListboxGroup"; +export type { MultiselectComboboxProps, ComboboxProps } from "./types"; diff --git a/packages/paste-core/components/combobox/src/multiselect/GrowingInput.tsx b/packages/paste-core/components/combobox/src/multiselect/GrowingInput.tsx index 528857b928..e13338fbf6 100644 --- a/packages/paste-core/components/combobox/src/multiselect/GrowingInput.tsx +++ b/packages/paste-core/components/combobox/src/multiselect/GrowingInput.tsx @@ -1,22 +1,22 @@ -import * as React from 'react'; -import type {BoxProps} from '@twilio-paste/box'; -import {Box} from '@twilio-paste/box'; -import {InputElement} from '@twilio-paste/input'; +import type { BoxProps } from "@twilio-paste/box"; +import { Box } from "@twilio-paste/box"; +import { InputElement } from "@twilio-paste/input"; +import * as React from "react"; interface GrowingInputProps { initialValue?: string; - element?: BoxProps['element']; + element?: BoxProps["element"]; onChange?: (event: React.ChangeEvent) => void; id: string; - value?: HTMLInputElement['value']; + value?: HTMLInputElement["value"]; } export const GrowingInput = React.forwardRef( - ({element = 'GROWING_INPUT', onChange, initialValue = '', value, ...props}, ref) => { + ({ element = "GROWING_INPUT", onChange, initialValue = "", value, ...props }, ref) => { const [text, setText] = React.useState(value || initialValue); React.useEffect(() => { - setText(value || ''); + setText(value || ""); }, [value]); /* @@ -43,13 +43,13 @@ export const GrowingInput = React.forwardRef { event.preventDefault(); // Used to set the width of the growing input - setText(event.currentTarget.value.replace(/ +/g, ' ')); + setText(event.currentTarget.value.replace(/ +/g, " ")); if (onChange != null) { onChange(event); @@ -71,6 +71,6 @@ export const GrowingInput = React.forwardRef ); - } + }, ); -GrowingInput.displayName = 'GrowingInput'; +GrowingInput.displayName = "GrowingInput"; diff --git a/packages/paste-core/components/combobox/src/multiselect/MultiselectCombobox.tsx b/packages/paste-core/components/combobox/src/multiselect/MultiselectCombobox.tsx index 1e5c1d1b18..cdb512eedf 100644 --- a/packages/paste-core/components/combobox/src/multiselect/MultiselectCombobox.tsx +++ b/packages/paste-core/components/combobox/src/multiselect/MultiselectCombobox.tsx @@ -1,30 +1,30 @@ -import * as React from 'react'; -import {useVirtual} from 'react-virtual'; -import includes from 'lodash/includes'; -import {useWindowSize} from '@twilio-paste/utils'; -import {useUID} from '@twilio-paste/uid-library'; -import {ChevronDownIcon} from '@twilio-paste/icons/esm/ChevronDownIcon'; -import {Box} from '@twilio-paste/box'; -import {Label} from '@twilio-paste/label'; -import {HelpText} from '@twilio-paste/help-text'; -import {ScreenReaderOnly} from '@twilio-paste/screen-reader-only'; -import {FormPillGroup, FormPill, useFormPillState} from '@twilio-paste/form-pill-group'; -import {useComboboxPrimitive} from '@twilio-paste/combobox-primitive'; -import {InputBox, InputChevronWrapper, getInputChevronIconColor} from '@twilio-paste/input-box'; -import {Portal} from '@twilio-paste/reakit-library'; +import { Box } from "@twilio-paste/box"; +import { useComboboxPrimitive } from "@twilio-paste/combobox-primitive"; +import { FormPill, FormPillGroup, useFormPillState } from "@twilio-paste/form-pill-group"; +import { HelpText } from "@twilio-paste/help-text"; +import { ChevronDownIcon } from "@twilio-paste/icons/esm/ChevronDownIcon"; +import { InputBox, InputChevronWrapper, getInputChevronIconColor } from "@twilio-paste/input-box"; +import { Label } from "@twilio-paste/label"; +import { Portal } from "@twilio-paste/reakit-library"; +import { ScreenReaderOnly } from "@twilio-paste/screen-reader-only"; +import { useUID } from "@twilio-paste/uid-library"; +import { useWindowSize } from "@twilio-paste/utils"; +import includes from "lodash/includes"; +import * as React from "react"; +import { useVirtual } from "react-virtual"; -import {GrowingInput} from './GrowingInput'; -import {extractPropsFromState} from './extractPropsFromState'; -import {ListBoxPositioner} from '../ListboxPositioner'; -import {ComboboxItems} from '../ComboboxItems'; -import {ComboboxListbox} from '../styles/ComboboxListbox'; -import type {MultiselectComboboxProps} from '../types'; -import {getHelpTextVariant} from '../helpers'; +import { ComboboxItems } from "../ComboboxItems"; +import { ListBoxPositioner } from "../ListboxPositioner"; +import { getHelpTextVariant } from "../helpers"; +import { ComboboxListbox } from "../styles/ComboboxListbox"; +import type { MultiselectComboboxProps } from "../types"; +import { GrowingInput } from "./GrowingInput"; +import { extractPropsFromState } from "./extractPropsFromState"; export const MultiselectCombobox = React.forwardRef( ( { - element = 'MULTISELECT_COMBOBOX', + element = "MULTISELECT_COMBOBOX", disabled, hasError, helpText, @@ -35,11 +35,11 @@ export const MultiselectCombobox = React.forwardRef | null): string => (item ? item.toString() : ''), + itemToString = (item: string | Record | null): string => (item ? item.toString() : ""), labelText, optionTemplate, required, - variant = 'default', + variant = "default", initialIsOpen, onHighlightedIndexChange, onInputValueChange, @@ -48,18 +48,18 @@ export const MultiselectCombobox = React.forwardRef { const a11yLabelId = useUID(); const helpTextId = useUID(); const pillState = useFormPillState(); const parentRef = React.useRef(null); - const {width} = useWindowSize(); + const { width } = useWindowSize(); // gets the dimensions of the inputBox to position the listbox const inputBoxRef = React.useRef(null); @@ -71,7 +71,7 @@ export const MultiselectCombobox = React.forwardRef) => { - if (event.code === 'Enter' && required && selectedItems.length === 0) { + if (event.code === "Enter" && required && selectedItems.length === 0) { // Don't submit the form event.preventDefault(); } onKeyDown?.(event); }, - [required, selectedItems, onKeyDown] + [required, selectedItems, onKeyDown], ); // Fix the a11y issue where `aria-expanded` isn't being set until the dropdown opens the very first time const comboboxProps = getComboboxProps({ disabled, - role: 'combobox', + role: "combobox", }); - const ariaExpanded = comboboxProps['aria-expanded'] || 'false'; + const ariaExpanded = comboboxProps["aria-expanded"] || "false"; return ( @@ -289,7 +289,7 @@ export const MultiselectCombobox = React.forwardRef - + ); - } + }, ); -MultiselectCombobox.displayName = 'MultiselectCombobox'; +MultiselectCombobox.displayName = "MultiselectCombobox"; diff --git a/packages/paste-core/components/combobox/src/multiselect/extractPropsFromState.tsx b/packages/paste-core/components/combobox/src/multiselect/extractPropsFromState.tsx index 90ed16cc8c..4669ad82ea 100644 --- a/packages/paste-core/components/combobox/src/multiselect/extractPropsFromState.tsx +++ b/packages/paste-core/components/combobox/src/multiselect/extractPropsFromState.tsx @@ -1,13 +1,13 @@ -import {useMultiSelectPrimitive} from '@twilio-paste/combobox-primitive'; -import type {UseMultiSelectPrimitiveReturnValue} from '@twilio-paste/combobox-primitive'; -import isEmpty from 'lodash/isEmpty'; +import { useMultiSelectPrimitive } from "@twilio-paste/combobox-primitive"; +import type { UseMultiSelectPrimitiveReturnValue } from "@twilio-paste/combobox-primitive"; +import isEmpty from "lodash/isEmpty"; -import type {Item, MultiselectComboboxProps} from '../types'; +import type { Item, MultiselectComboboxProps } from "../types"; interface DefaultStateProps { - initialSelectedItems: MultiselectComboboxProps['initialSelectedItems']; - onSelectedItemsChange: MultiselectComboboxProps['onSelectedItemsChange']; - state: MultiselectComboboxProps['state']; + initialSelectedItems: MultiselectComboboxProps["initialSelectedItems"]; + onSelectedItemsChange: MultiselectComboboxProps["onSelectedItemsChange"]; + state: MultiselectComboboxProps["state"]; } export const extractPropsFromState = ({ diff --git a/packages/paste-core/components/combobox/src/singleselect/Combobox.tsx b/packages/paste-core/components/combobox/src/singleselect/Combobox.tsx index a8ed6bb817..a79a355c7d 100644 --- a/packages/paste-core/components/combobox/src/singleselect/Combobox.tsx +++ b/packages/paste-core/components/combobox/src/singleselect/Combobox.tsx @@ -1,36 +1,36 @@ -import * as React from 'react'; -import {useVirtual} from 'react-virtual'; -import {useUID} from '@twilio-paste/uid-library'; -import {useWindowSize} from '@twilio-paste/utils'; -import {ChevronDownIcon} from '@twilio-paste/icons/esm/ChevronDownIcon'; -import {Box} from '@twilio-paste/box'; -import {InputBox, InputChevronWrapper, getInputChevronIconColor} from '@twilio-paste/input-box'; -import {Label} from '@twilio-paste/label'; -import {HelpText} from '@twilio-paste/help-text'; -import type {HelpTextVariants} from '@twilio-paste/help-text'; -import type {InputVariants} from '@twilio-paste/input'; -import {Portal} from '@twilio-paste/reakit-library'; +import { Box } from "@twilio-paste/box"; +import { HelpText } from "@twilio-paste/help-text"; +import type { HelpTextVariants } from "@twilio-paste/help-text"; +import { ChevronDownIcon } from "@twilio-paste/icons/esm/ChevronDownIcon"; +import type { InputVariants } from "@twilio-paste/input"; +import { InputBox, InputChevronWrapper, getInputChevronIconColor } from "@twilio-paste/input-box"; +import { Label } from "@twilio-paste/label"; +import { Portal } from "@twilio-paste/reakit-library"; +import { useUID } from "@twilio-paste/uid-library"; +import { useWindowSize } from "@twilio-paste/utils"; +import * as React from "react"; +import { useVirtual } from "react-virtual"; -import {ComboboxInputSelect} from '../styles/ComboboxInputSelect'; -import {ComboboxInputWrapper} from '../styles/ComboboxInputWrapper'; -import {ComboboxListbox} from '../styles/ComboboxListbox'; -import {ComboboxItems} from '../ComboboxItems'; -import type {ComboboxProps} from '../types'; -import {extractPropsFromState} from './extractPropsFromState'; -import {ListBoxPositioner} from '../ListboxPositioner'; -import {visuallyHiddenStyles} from '../helpers'; +import { ComboboxItems } from "../ComboboxItems"; +import { ListBoxPositioner } from "../ListboxPositioner"; +import { visuallyHiddenStyles } from "../helpers"; +import { ComboboxInputSelect } from "../styles/ComboboxInputSelect"; +import { ComboboxInputWrapper } from "../styles/ComboboxInputWrapper"; +import { ComboboxListbox } from "../styles/ComboboxListbox"; +import type { ComboboxProps } from "../types"; +import { extractPropsFromState } from "./extractPropsFromState"; const getHelpTextVariant = (variant: InputVariants, hasError: boolean | undefined): HelpTextVariants => { - if (hasError && variant === 'inverse') { - return 'error_inverse'; + if (hasError && variant === "inverse") { + return "error_inverse"; } if (hasError) { - return 'error'; + return "error"; } - if (variant === 'inverse') { - return 'inverse'; + if (variant === "inverse") { + return "inverse"; } - return 'default'; + return "default"; }; const Combobox = React.forwardRef( @@ -38,7 +38,7 @@ const Combobox = React.forwardRef( { autocomplete, disabled, - element = 'COMBOBOX', + element = "COMBOBOX", hasError, hideVisibleLabel, helpText, @@ -60,18 +60,18 @@ const Combobox = React.forwardRef( selectedItem, groupItemsBy, groupLabelTemplate, - variant = 'default', + variant = "default", emptyState, getA11yStatusMessage, getA11ySelectionMessage, state, ...props }, - ref + ref, ) => { const parentRef = React.useRef(null); const helpTextId = useUID(); - const {width} = useWindowSize(); + const { width } = useWindowSize(); // gets the dimensions of the inputBox to position the listbox const inputBoxRef = React.useRef(null); @@ -114,7 +114,7 @@ const Combobox = React.forwardRef( isOpen === undefined ) { throw new Error( - '[Combobox]: One of getComboboxProps, getInputProps, getItemProps, getLabelProps, getMenuProps, getToggleButtonProps, highlightedIndex or isOpen is missing from the state object. Please make sure this is provided.' + "[Combobox]: One of getComboboxProps, getInputProps, getItemProps, getLabelProps, getMenuProps, getToggleButtonProps, highlightedIndex or isOpen is missing from the state object. Please make sure this is provided.", ); } @@ -140,12 +140,12 @@ const Combobox = React.forwardRef( rowVirtualizer.scrollToIndex(items.indexOf(internalSelectedItem)); } }, - [items, internalSelectedItem] + [items, internalSelectedItem], ); return ( - + @@ -159,12 +159,12 @@ const Combobox = React.forwardRef( variant={variant} ref={inputBoxRef} > - + event.preventDefault()} : undefined)} + {...getInputProps({ disabled, required, ref, ...props })} + {...(!autocomplete ? { onChange: (event: React.ChangeEvent) => event.preventDefault() } : undefined)} autocomplete={autocomplete} aria-describedby={helpText != null ? helpTextId : null} element={`${element}_ELEMENT`} @@ -182,7 +182,7 @@ const Combobox = React.forwardRef( - ); - } + }, ); -Combobox.displayName = 'Combobox'; +Combobox.displayName = "Combobox"; -export {Combobox}; +export { Combobox }; diff --git a/packages/paste-core/components/combobox/src/singleselect/extractPropsFromState.tsx b/packages/paste-core/components/combobox/src/singleselect/extractPropsFromState.tsx index 669a47f6c0..3d72166856 100644 --- a/packages/paste-core/components/combobox/src/singleselect/extractPropsFromState.tsx +++ b/packages/paste-core/components/combobox/src/singleselect/extractPropsFromState.tsx @@ -1,29 +1,29 @@ -import * as React from 'react'; -import {useComboboxPrimitive} from '@twilio-paste/combobox-primitive'; +import { useComboboxPrimitive } from "@twilio-paste/combobox-primitive"; import type { + UseComboboxPrimitiveReturnValue, UseComboboxPrimitiveState, UseComboboxPrimitiveStateChange, UseComboboxPrimitiveStateChangeOptions, - UseComboboxPrimitiveReturnValue, -} from '@twilio-paste/combobox-primitive'; -import isEmpty from 'lodash/isEmpty'; +} from "@twilio-paste/combobox-primitive"; +import isEmpty from "lodash/isEmpty"; +import * as React from "react"; -import type {ComboboxProps} from '../types'; +import type { ComboboxProps } from "../types"; type DefaultStateProps = { - onInputValueChange: ComboboxProps['onInputValueChange']; - onIsOpenChange: ComboboxProps['onIsOpenChange']; - onSelectedItemChange: ComboboxProps['onSelectedItemChange']; - onHighlightedIndexChange: ComboboxProps['onHighlightedIndexChange']; - itemToString: ComboboxProps['itemToString']; - initialIsOpen: ComboboxProps['initialIsOpen']; - inputValue: ComboboxProps['inputValue']; - selectedItem: ComboboxProps['selectedItem']; - initialSelectedItem: ComboboxProps['initialSelectedItem']; - items: ComboboxProps['items']; - disabledItems: ComboboxProps['disabledItems']; - getA11yStatusMessage: ComboboxProps['getA11yStatusMessage']; - getA11ySelectionMessage: ComboboxProps['getA11ySelectionMessage']; + onInputValueChange: ComboboxProps["onInputValueChange"]; + onIsOpenChange: ComboboxProps["onIsOpenChange"]; + onSelectedItemChange: ComboboxProps["onSelectedItemChange"]; + onHighlightedIndexChange: ComboboxProps["onHighlightedIndexChange"]; + itemToString: ComboboxProps["itemToString"]; + initialIsOpen: ComboboxProps["initialIsOpen"]; + inputValue: ComboboxProps["inputValue"]; + selectedItem: ComboboxProps["selectedItem"]; + initialSelectedItem: ComboboxProps["initialSelectedItem"]; + items: ComboboxProps["items"]; + disabledItems: ComboboxProps["disabledItems"]; + getA11yStatusMessage: ComboboxProps["getA11yStatusMessage"]; + getA11ySelectionMessage: ComboboxProps["getA11ySelectionMessage"]; }; const getDefaultState = ({ @@ -43,7 +43,7 @@ const getDefaultState = ({ }: DefaultStateProps): Partial> => { const stateReducer = ( state: UseComboboxPrimitiveState, - actionAndChanges: UseComboboxPrimitiveStateChangeOptions + actionAndChanges: UseComboboxPrimitiveStateChangeOptions, ): Partial> => { // If the item to be selected is disabled, return the current state without changes if (disabledItems?.includes(actionAndChanges.changes.selectedItem)) { @@ -63,25 +63,25 @@ const getDefaultState = ({ onHighlightedIndexChange(changes); } }, - [onHighlightedIndexChange] + [onHighlightedIndexChange], ), onInputValueChange, onIsOpenChange, onSelectedItemChange, - ...(itemToString != null && {itemToString}), - ...(initialIsOpen != null && {initialIsOpen}), + ...(itemToString != null && { itemToString }), + ...(initialIsOpen != null && { initialIsOpen }), // We remap inputValue to defaultInputValue because we want downshift to manage the state of controlled inputs - ...(inputValue != null && {defaultInputValue: inputValue}), - ...(selectedItem != null && {selectedItem}), - ...(getA11yStatusMessage != null && {getA11yStatusMessage}), - ...(getA11ySelectionMessage != null && {getA11ySelectionMessage}), + ...(inputValue != null && { defaultInputValue: inputValue }), + ...(selectedItem != null && { selectedItem }), + ...(getA11yStatusMessage != null && { getA11yStatusMessage }), + ...(getA11ySelectionMessage != null && { getA11ySelectionMessage }), }); }; export const extractPropsFromState = ({ state, ...props -}: DefaultStateProps & {state?: Partial>}): Partial< +}: DefaultStateProps & { state?: Partial> }): Partial< UseComboboxPrimitiveReturnValue > => { if (state != null && !isEmpty(state)) { diff --git a/packages/paste-core/components/combobox/src/styles/ComboboxInputSelect.tsx b/packages/paste-core/components/combobox/src/styles/ComboboxInputSelect.tsx index f0a5edab68..a23e80d408 100644 --- a/packages/paste-core/components/combobox/src/styles/ComboboxInputSelect.tsx +++ b/packages/paste-core/components/combobox/src/styles/ComboboxInputSelect.tsx @@ -1,13 +1,13 @@ -import * as React from 'react'; -import {InputElement} from '@twilio-paste/input'; +import { InputElement } from "@twilio-paste/input"; +import * as React from "react"; -import type {ComboboxProps} from '../types'; +import type { ComboboxProps } from "../types"; -const ComboboxInputSelect = React.forwardRef(({...props}, ref) => { +const ComboboxInputSelect = React.forwardRef(({ ...props }, ref) => { return ( (({ ); }); -ComboboxInputSelect.displayName = 'ComboboxInputSelect'; +ComboboxInputSelect.displayName = "ComboboxInputSelect"; -export {ComboboxInputSelect}; +export { ComboboxInputSelect }; diff --git a/packages/paste-core/components/combobox/src/styles/ComboboxInputWrapper.tsx b/packages/paste-core/components/combobox/src/styles/ComboboxInputWrapper.tsx index 1f4093aaa9..f1de93614a 100644 --- a/packages/paste-core/components/combobox/src/styles/ComboboxInputWrapper.tsx +++ b/packages/paste-core/components/combobox/src/styles/ComboboxInputWrapper.tsx @@ -1,20 +1,20 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import * as React from "react"; export interface ComboboxInputWrapperProps { children: NonNullable; } const ComboboxInputWrapper = React.forwardRef( - ({children, ...props}, ref) => { + ({ children, ...props }, ref) => { return ( {children} ); - } + }, ); -ComboboxInputWrapper.displayName = 'ComboboxInputWrapper'; +ComboboxInputWrapper.displayName = "ComboboxInputWrapper"; -export {ComboboxInputWrapper}; +export { ComboboxInputWrapper }; diff --git a/packages/paste-core/components/combobox/src/styles/ComboboxListbox.tsx b/packages/paste-core/components/combobox/src/styles/ComboboxListbox.tsx index 42ad1b88bf..f550e8644c 100644 --- a/packages/paste-core/components/combobox/src/styles/ComboboxListbox.tsx +++ b/packages/paste-core/components/combobox/src/styles/ComboboxListbox.tsx @@ -1,14 +1,14 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import * as React from "react"; -export interface ComboboxListboxProps extends Pick { +export interface ComboboxListboxProps extends Pick { children: NonNullable; hidden: boolean; } const ComboboxListbox = React.forwardRef( - ({children, element = 'COMBOBOX_LISTBOX', hidden, ...props}, ref) => { + ({ children, element = "COMBOBOX_LISTBOX", hidden, ...props }, ref) => { // Unmount children when hidden if (hidden) { return ; @@ -45,9 +45,9 @@ const ComboboxListbox = React.forwardRef {children} ); - } + }, ); -ComboboxListbox.displayName = 'ComboboxListbox'; +ComboboxListbox.displayName = "ComboboxListbox"; -export {ComboboxListbox}; +export { ComboboxListbox }; diff --git a/packages/paste-core/components/combobox/src/styles/ComboboxListboxGroup.tsx b/packages/paste-core/components/combobox/src/styles/ComboboxListboxGroup.tsx index 0346bb8fa5..2d9d69fc09 100644 --- a/packages/paste-core/components/combobox/src/styles/ComboboxListboxGroup.tsx +++ b/packages/paste-core/components/combobox/src/styles/ComboboxListboxGroup.tsx @@ -1,22 +1,22 @@ -import * as React from 'react'; -import {Box} from '@twilio-paste/box'; -import {Text} from '@twilio-paste/text'; +import { Box } from "@twilio-paste/box"; +import { Text } from "@twilio-paste/text"; +import * as React from "react"; -import type {ComboboxProps} from '../types'; +import type { ComboboxProps } from "../types"; -export interface ComboboxListboxGroupProps extends Pick { +export interface ComboboxListboxGroupProps extends Pick { children: NonNullable; groupName?: string | undefined; } const ComboboxListboxGroup = React.forwardRef( - ({children, element = 'COMBOBOX', groupName, groupLabelTemplate}, ref) => { + ({ children, element = "COMBOBOX", groupName, groupLabelTemplate }, ref) => { return ( {groupName ? ( @@ -56,9 +56,9 @@ const ComboboxListboxGroup = React.forwardRef ); - } + }, ); -ComboboxListboxGroup.displayName = 'ComboboxListboxGroup'; +ComboboxListboxGroup.displayName = "ComboboxListboxGroup"; -export {ComboboxListboxGroup}; +export { ComboboxListboxGroup }; diff --git a/packages/paste-core/components/combobox/src/styles/ComboboxListboxOption.tsx b/packages/paste-core/components/combobox/src/styles/ComboboxListboxOption.tsx index cab1c0ec67..ae7c2bbb0e 100644 --- a/packages/paste-core/components/combobox/src/styles/ComboboxListboxOption.tsx +++ b/packages/paste-core/components/combobox/src/styles/ComboboxListboxOption.tsx @@ -1,36 +1,36 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import {SelectedIcon} from '@twilio-paste/icons/esm/SelectedIcon'; -import type {BoxProps, BoxStyleProps} from '@twilio-paste/box'; -import {Text} from '@twilio-paste/text'; -import type {PositionOptions} from '@twilio-paste/style-props'; -import type {VirtualItem} from 'react-virtual'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps, BoxStyleProps } from "@twilio-paste/box"; +import { SelectedIcon } from "@twilio-paste/icons/esm/SelectedIcon"; +import type { PositionOptions } from "@twilio-paste/style-props"; +import { Text } from "@twilio-paste/text"; +import * as React from "react"; +import type { VirtualItem } from "react-virtual"; -export interface ComboboxListboxOptionProps extends Pick { +export interface ComboboxListboxOptionProps extends Pick { children: NonNullable; highlighted?: boolean; selected?: boolean; disabled?: boolean; - variant: 'default' | 'groupOption'; - startHeight?: VirtualItem['start']; + variant: "default" | "groupOption"; + startHeight?: VirtualItem["start"]; } -const VariantStyles: {[key in ComboboxListboxOptionProps['variant']]: BoxStyleProps} = { +const VariantStyles: { [key in ComboboxListboxOptionProps["variant"]]: BoxStyleProps } = { groupOption: { - paddingLeft: 'space90', - paddingRight: 'space50', + paddingLeft: "space90", + paddingRight: "space50", }, default: { - paddingLeft: 'space50', - paddingRight: 'space50', + paddingLeft: "space50", + paddingRight: "space50", }, }; const getVirtualStyles = (startHeight: number): Record => ({ - position: 'absolute' as PositionOptions, + position: "absolute" as PositionOptions, top: 0, left: 0, - width: '100%', + width: "100%", transform: `translateY(${startHeight}px)`, }); @@ -38,15 +38,15 @@ const ComboboxListboxOption = React.forwardRef { const virtualItemStyles = startHeight != null ? getVirtualStyles(startHeight) : {}; @@ -63,20 +63,20 @@ const ComboboxListboxOption = React.forwardRef ); - } + }, ); -ComboboxListboxOption.displayName = 'ComboboxListboxOption'; +ComboboxListboxOption.displayName = "ComboboxListboxOption"; -export {ComboboxListboxOption}; +export { ComboboxListboxOption }; diff --git a/packages/paste-core/components/combobox/src/types.ts b/packages/paste-core/components/combobox/src/types.ts index f8786d96eb..b5b25366e2 100644 --- a/packages/paste-core/components/combobox/src/types.ts +++ b/packages/paste-core/components/combobox/src/types.ts @@ -1,26 +1,26 @@ -import type React from 'react'; -import type {BoxProps, BoxStyleProps} from '@twilio-paste/box'; +import type { BoxProps, BoxStyleProps } from "@twilio-paste/box"; import type { UseComboboxPrimitiveProps, - UseComboboxPrimitiveState, UseComboboxPrimitiveReturnValue, + UseComboboxPrimitiveState, UseMultiSelectPrimitiveReturnValue, UseMultiSelectPrimitiveStateChange, -} from '@twilio-paste/combobox-primitive'; -import type {InputVariants, InputProps} from '@twilio-paste/input'; -import type {VirtualItem} from 'react-virtual'; +} from "@twilio-paste/combobox-primitive"; +import type { InputProps, InputVariants } from "@twilio-paste/input"; +import type React from "react"; +import type { VirtualItem } from "react-virtual"; export type { UseComboboxPrimitiveGetItemPropsOptions, UseComboboxPrimitiveGetMenuPropsOptions, GetComboboxPrimitivePropsCommonOptions, -} from '@twilio-paste/combobox-primitive'; +} from "@twilio-paste/combobox-primitive"; export type Item = string | Record; export type OptionTemplateFn = (item: ProvidedItem) => React.ReactNode; -type ScrollAlignment = 'start' | 'center' | 'end' | 'auto'; +type ScrollAlignment = "start" | "center" | "end" | "auto"; interface ScrollToOptions { align: ScrollAlignment; @@ -42,8 +42,8 @@ export type HighlightedIndexChanges = { }; export interface ComboboxProps - extends Omit, - Pick { + extends Omit, + Pick { autocomplete?: boolean; helpText?: string | React.ReactNode; labelText: string | NonNullable; @@ -56,18 +56,18 @@ export interface ComboboxProps hideVisibleLabel?: boolean; // Downshift useCombobox Hook Props. Thes are mainly covered in https://github.com/downshift-js/downshift/blob/master/src/hooks/useCombobox/README.md#advanced-props docs - initialIsOpen?: UseComboboxPrimitiveProps['initialIsOpen']; - initialSelectedItem?: UseComboboxPrimitiveProps['initialSelectedItem']; - items: UseComboboxPrimitiveProps['items']; - itemToString?: UseComboboxPrimitiveProps['itemToString']; - onHighlightedIndexChange?: UseComboboxPrimitiveProps['onHighlightedIndexChange']; - onInputValueChange?: UseComboboxPrimitiveProps['onInputValueChange']; - onIsOpenChange?: UseComboboxPrimitiveProps['onIsOpenChange']; - onSelectedItemChange?: UseComboboxPrimitiveProps['onSelectedItemChange']; - selectedItem?: UseComboboxPrimitiveProps['selectedItem']; - inputValue?: UseComboboxPrimitiveProps['inputValue']; - getA11yStatusMessage?: UseComboboxPrimitiveProps['getA11yStatusMessage']; - getA11ySelectionMessage?: UseComboboxPrimitiveProps['getA11ySelectionMessage']; + initialIsOpen?: UseComboboxPrimitiveProps["initialIsOpen"]; + initialSelectedItem?: UseComboboxPrimitiveProps["initialSelectedItem"]; + items: UseComboboxPrimitiveProps["items"]; + itemToString?: UseComboboxPrimitiveProps["itemToString"]; + onHighlightedIndexChange?: UseComboboxPrimitiveProps["onHighlightedIndexChange"]; + onInputValueChange?: UseComboboxPrimitiveProps["onInputValueChange"]; + onIsOpenChange?: UseComboboxPrimitiveProps["onIsOpenChange"]; + onSelectedItemChange?: UseComboboxPrimitiveProps["onSelectedItemChange"]; + selectedItem?: UseComboboxPrimitiveProps["selectedItem"]; + inputValue?: UseComboboxPrimitiveProps["inputValue"]; + getA11yStatusMessage?: UseComboboxPrimitiveProps["getA11yStatusMessage"]; + getA11ySelectionMessage?: UseComboboxPrimitiveProps["getA11ySelectionMessage"]; // Downshift useCombobox Hook return props for when you are using the hook outside of the component state?: Partial>; @@ -88,34 +88,34 @@ export interface ComboboxProps export interface MultiselectComboboxProps extends Omit< ComboboxProps, - | 'autocomplete' - | 'initialSelectedItem' - | 'selectedItem' - | 'onSelectedItemChange' - | 'getA11yStatusMessage' - | 'getA11ySelectionMessage' - | 'state' + | "autocomplete" + | "initialSelectedItem" + | "selectedItem" + | "onSelectedItemChange" + | "getA11yStatusMessage" + | "getA11ySelectionMessage" + | "state" // until such time as we have a usecase for hidden multi-select comboboxes - | 'hideVisibleLabel' + | "hideVisibleLabel" > { initialSelectedItems?: any[]; onSelectedItemsChange?: (newSelectedItems: UseMultiSelectPrimitiveStateChange) => void; selectedItemsLabelText: string; i18nKeyboardControls?: string; - maxHeight?: BoxStyleProps['maxHeight']; + maxHeight?: BoxStyleProps["maxHeight"]; state?: UseMultiSelectPrimitiveReturnValue; } export interface ComboboxItemsProps extends Pick< ComboboxProps, - 'groupItemsBy' | 'optionTemplate' | 'groupLabelTemplate' | 'element' | 'emptyState' | 'state' + "groupItemsBy" | "optionTemplate" | "groupLabelTemplate" | "element" | "emptyState" | "state" > { items: Item[]; selectedItems?: Item[]; disabledItems?: Item[]; getItemProps: any; - highlightedIndex: UseComboboxPrimitiveState['highlightedIndex']; - totalSize: RowVirtualizer['totalSize']; - virtualItems: RowVirtualizer['virtualItems']; + highlightedIndex: UseComboboxPrimitiveState["highlightedIndex"]; + totalSize: RowVirtualizer["totalSize"]; + virtualItems: RowVirtualizer["virtualItems"]; } diff --git a/packages/paste-core/components/combobox/stories/Combobox-customization.stories.tsx b/packages/paste-core/components/combobox/stories/Combobox-customization.stories.tsx index 7ffd1e5e83..15a3020549 100644 --- a/packages/paste-core/components/combobox/stories/Combobox-customization.stories.tsx +++ b/packages/paste-core/components/combobox/stories/Combobox-customization.stories.tsx @@ -1,15 +1,15 @@ -import * as React from 'react'; -import type {StoryFn} from '@storybook/react'; -import {Stack} from '@twilio-paste/stack'; -import {CustomizationProvider} from '@twilio-paste/customization'; -import {Card} from '@twilio-paste/card'; -import {Text} from '@twilio-paste/text'; -import {InformationIcon} from '@twilio-paste/icons/esm/InformationIcon'; -import {useTheme} from '@twilio-paste/theme'; +import type { StoryFn } from "@storybook/react"; +import { Card } from "@twilio-paste/card"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import { InformationIcon } from "@twilio-paste/icons/esm/InformationIcon"; +import { Stack } from "@twilio-paste/stack"; +import { Text } from "@twilio-paste/text"; +import { useTheme } from "@twilio-paste/theme"; +import * as React from "react"; -import {Combobox} from '../src'; +import { Combobox } from "../src"; -const items = ['a', 'b', 'c']; +const items = ["a", "b", "c"]; interface GroupedItem { letter: string; @@ -17,16 +17,16 @@ interface GroupedItem { } const groupedItems = [ - {letter: 'a', number: 1}, - {letter: 'a', number: 2}, - {letter: 'b', number: 3}, - {letter: 'b', number: 4}, - {letter: 'b', number: 5}, - {letter: 'c', number: 6}, - {letter: 'd', number: 7}, + { letter: "a", number: 1 }, + { letter: "a", number: 2 }, + { letter: "b", number: 3 }, + { letter: "b", number: 4 }, + { letter: "b", number: 5 }, + { letter: "c", number: 6 }, + { letter: "d", number: 7 }, ]; -const ShowCustomization: React.FC> = ({ +const ShowCustomization: React.FC> = ({ isTestEnvironment, children, }): React.ReactElement => { @@ -39,19 +39,19 @@ const ShowCustomization: React.FC {children} @@ -62,37 +62,37 @@ const ShowCustomization: React.FC - {React.cloneElement(children as React.ReactElement, {element: 'FOO'})} + {React.cloneElement(children as React.ReactElement, { element: "FOO" })} ); }; -export const CustomizedCombobox: StoryFn = (_args, {parameters: {isTestEnvironment}}) => ( +export const CustomizedCombobox: StoryFn = (_args, { parameters: { isTestEnvironment } }) => ( ); -CustomizedCombobox.storyName = 'Combobox - Default'; +CustomizedCombobox.storyName = "Combobox - Default"; -export const CustomizedComboboxGroups: StoryFn = (_args, {parameters: {isTestEnvironment}}) => ( +export const CustomizedComboboxGroups: StoryFn = (_args, { parameters: { isTestEnvironment } }) => (
    {item.number}
    } - itemToString={(item: GroupedItem) => (item ? item.letter : '')} + itemToString={(item: GroupedItem) => (item ? item.letter : "")} />
    ); -CustomizedComboboxGroups.storyName = 'Combobox - With groups'; +CustomizedComboboxGroups.storyName = "Combobox - With groups"; -export const CustomizedComboboxBeforeAndAfter: StoryFn = (_args, {parameters: {isTestEnvironment}}) => ( +export const CustomizedComboboxBeforeAndAfter: StoryFn = (_args, { parameters: { isTestEnvironment } }) => (
    {item.number}
    } - itemToString={(item: GroupedItem) => (item ? item.letter : '')} + itemToString={(item: GroupedItem) => (item ? item.letter : "")} insertBefore={Z} insertAfter={} />
    ); -CustomizedComboboxBeforeAndAfter.storyName = 'Combobox - With prefix and suffix'; +CustomizedComboboxBeforeAndAfter.storyName = "Combobox - With prefix and suffix"; // eslint-disable-next-line import/no-default-export export default { - title: 'Components/Combobox/Customization - Combobox', + title: "Components/Combobox/Customization - Combobox", component: CustomizedCombobox, parameters: { a11y: { diff --git a/packages/paste-core/components/combobox/stories/Combobox.stories.tsx b/packages/paste-core/components/combobox/stories/Combobox.stories.tsx index e6fa77ff80..5ec77fac05 100644 --- a/packages/paste-core/components/combobox/stories/Combobox.stories.tsx +++ b/packages/paste-core/components/combobox/stories/Combobox.stories.tsx @@ -1,36 +1,36 @@ -import * as React from 'react'; -import _ from 'lodash'; -import type {StoryFn, Meta, StoryContext} from '@storybook/react'; -import {useUID} from '@twilio-paste/uid-library'; -import {Anchor} from '@twilio-paste/anchor'; -import {Button} from '@twilio-paste/button'; -import {Box} from '@twilio-paste/box'; -import {Label} from '@twilio-paste/label'; -import {Text} from '@twilio-paste/text'; -import {Select, Option} from '@twilio-paste/select'; -import {MediaObject, MediaFigure, MediaBody} from '@twilio-paste/media-object'; -import {InformationIcon} from '@twilio-paste/icons/esm/InformationIcon'; -import {AttachIcon} from '@twilio-paste/icons/esm/AttachIcon'; -import {SearchIcon} from '@twilio-paste/icons/esm/SearchIcon'; -import {CloseIcon} from '@twilio-paste/icons/esm/CloseIcon'; -import {Modal, ModalBody, ModalHeader, ModalHeading} from '@twilio-paste/modal'; - -import {Combobox, useCombobox} from '../src'; +import type { Meta, StoryContext, StoryFn } from "@storybook/react"; +import { Anchor } from "@twilio-paste/anchor"; +import { Box } from "@twilio-paste/box"; +import { Button } from "@twilio-paste/button"; +import { AttachIcon } from "@twilio-paste/icons/esm/AttachIcon"; +import { CloseIcon } from "@twilio-paste/icons/esm/CloseIcon"; +import { InformationIcon } from "@twilio-paste/icons/esm/InformationIcon"; +import { SearchIcon } from "@twilio-paste/icons/esm/SearchIcon"; +import { Label } from "@twilio-paste/label"; +import { MediaBody, MediaFigure, MediaObject } from "@twilio-paste/media-object"; +import { Modal, ModalBody, ModalHeader, ModalHeading } from "@twilio-paste/modal"; +import { Option, Select } from "@twilio-paste/select"; +import { Text } from "@twilio-paste/text"; +import { useUID } from "@twilio-paste/uid-library"; +import _ from "lodash"; +import * as React from "react"; + +import { Combobox, useCombobox } from "../src"; const items = [ - 'Alert', - 'Anchor', - 'Button', - 'Card', - 'Heading', - 'A component with a really really really really really really really really long name', - 'List', - 'Modal', - 'Paragraph', + "Alert", + "Anchor", + "Button", + "Card", + "Heading", + "A component with a really really really really really really really really long name", + "List", + "Modal", + "Paragraph", ]; function createLargeArray>( - template: (index?: number | undefined) => TemplateResult + template: (index?: number | undefined) => TemplateResult, ): TemplateResult[] { // eslint-disable-next-line unicorn/prefer-spread return Array.from(new Array(1000), (_empty, index) => template(index)); @@ -42,14 +42,14 @@ interface IconItems { iconLeft?: undefined; } const iconItems = [ - {label: 'Alert', iconRight: true}, - {label: 'Anchor'}, - {label: 'Button', iconLeft: true}, - {label: 'Card', iconRight: true}, - {label: 'Heading'}, - {label: 'List', iconRight: true}, - {label: 'Modal', iconLeft: true}, - {label: 'Paragraph', iconRight: true}, + { label: "Alert", iconRight: true }, + { label: "Anchor" }, + { label: "Button", iconLeft: true }, + { label: "Card", iconRight: true }, + { label: "Heading" }, + { label: "List", iconRight: true }, + { label: "Modal", iconLeft: true }, + { label: "Paragraph", iconRight: true }, ]; interface ObjectItem { @@ -58,33 +58,33 @@ interface ObjectItem { phone: string; } const objectItems = [ - {code: 'AD', label: 'Andorra', phone: '376'}, - {code: 'AE', label: 'United Arab Emirates', phone: '971'}, - {code: 'AF', label: 'Afghanistan', phone: '93'}, - {code: 'AG', label: 'Antigua and Barbuda', phone: '1-268'}, - {code: 'AI', label: 'Anguilla', phone: '1-264'}, - {code: 'AL', label: 'Albania', phone: '355'}, - {code: 'AM', label: 'Armenia', phone: '374'}, - {code: 'AO', label: 'Angola', phone: '244'}, - {code: 'AQ', label: 'Antarctica', phone: '672'}, - {code: 'AR', label: 'Argentina', phone: '54'}, - {code: 'AS', label: 'American Samoa', phone: '1-684'}, - {code: 'AT', label: 'Austria', phone: '44'}, - {code: 'BS', label: 'Bahamas', phone: '43'}, - {code: 'BH', label: 'Bahrain', phone: '48'}, - {code: 'BD', label: 'Bangladesh', phone: '50'}, - {code: 'BB', label: 'Barbados', phone: '52'}, - {code: 'BY', label: 'Belarus', phone: '112'}, - {code: 'BE', label: 'Belgium', phone: '56'}, - {code: 'BZ', label: 'Belize', phone: '84'}, - {code: 'BJ', label: 'Benin', phone: '204'}, - {code: 'BM', label: 'Bermuda', phone: '60'}, - {code: 'BT', label: 'Bhutan', phone: '64'}, - {code: 'BO', label: 'Bolivia', phone: '68'}, - {code: 'BW', label: 'Botswana', phone: '72'}, - {code: 'BR', label: 'Brazil', phone: '76'}, - {code: 'KH', label: 'Cambodia', phone: '116'}, - {code: 'CA', label: 'Canada', phone: '124'}, + { code: "AD", label: "Andorra", phone: "376" }, + { code: "AE", label: "United Arab Emirates", phone: "971" }, + { code: "AF", label: "Afghanistan", phone: "93" }, + { code: "AG", label: "Antigua and Barbuda", phone: "1-268" }, + { code: "AI", label: "Anguilla", phone: "1-264" }, + { code: "AL", label: "Albania", phone: "355" }, + { code: "AM", label: "Armenia", phone: "374" }, + { code: "AO", label: "Angola", phone: "244" }, + { code: "AQ", label: "Antarctica", phone: "672" }, + { code: "AR", label: "Argentina", phone: "54" }, + { code: "AS", label: "American Samoa", phone: "1-684" }, + { code: "AT", label: "Austria", phone: "44" }, + { code: "BS", label: "Bahamas", phone: "43" }, + { code: "BH", label: "Bahrain", phone: "48" }, + { code: "BD", label: "Bangladesh", phone: "50" }, + { code: "BB", label: "Barbados", phone: "52" }, + { code: "BY", label: "Belarus", phone: "112" }, + { code: "BE", label: "Belgium", phone: "56" }, + { code: "BZ", label: "Belize", phone: "84" }, + { code: "BJ", label: "Benin", phone: "204" }, + { code: "BM", label: "Bermuda", phone: "60" }, + { code: "BT", label: "Bhutan", phone: "64" }, + { code: "BO", label: "Bolivia", phone: "68" }, + { code: "BW", label: "Botswana", phone: "72" }, + { code: "BR", label: "Brazil", phone: "76" }, + { code: "KH", label: "Cambodia", phone: "116" }, + { code: "CA", label: "Canada", phone: "124" }, ]; interface GroupedItem { @@ -92,24 +92,24 @@ interface GroupedItem { label: string; } const groupedItems = [ - {group: 'Components', label: 'Alert'}, - {group: 'Components', label: 'Anchor'}, - {group: 'Components', label: 'Button'}, - {group: 'Components', label: 'Card'}, - {group: 'Components', label: 'Heading'}, - {group: 'Components', label: 'List'}, - {group: 'Components', label: 'Modal'}, - {group: 'Components', label: 'Paragraph'}, - {group: 'Primitives', label: 'Box'}, - {group: 'Primitives', label: 'Text'}, - {group: 'Primitives', label: 'Non-modal dialog'}, - {group: 'Layout', label: 'Grid'}, - {label: 'Design Tokens'}, + { group: "Components", label: "Alert" }, + { group: "Components", label: "Anchor" }, + { group: "Components", label: "Button" }, + { group: "Components", label: "Card" }, + { group: "Components", label: "Heading" }, + { group: "Components", label: "List" }, + { group: "Components", label: "Modal" }, + { group: "Components", label: "Paragraph" }, + { group: "Primitives", label: "Box" }, + { group: "Primitives", label: "Text" }, + { group: "Primitives", label: "Non-modal dialog" }, + { group: "Layout", label: "Grid" }, + { label: "Design Tokens" }, ]; // eslint-disable-next-line import/no-default-export export default { - title: 'Components/Combobox/Combobox', + title: "Components/Combobox/Combobox", component: Combobox, // wraps each story in a div that has a fixed height. This makes it so chromatic takes a large enough screenshot to see the listbox. decorators: [ @@ -143,12 +143,12 @@ export const DefaultCombobox: StoryFn = () => { ) : null} )} - itemToString={(item: IconItems) => (item ? String(item.label) : '')} + itemToString={(item: IconItems) => (item ? String(item.label) : "")} /> ); }; -DefaultCombobox.storyName = 'Combobox'; +DefaultCombobox.storyName = "Combobox"; export const BottomOfScreen: StoryFn = () => { return ( @@ -174,17 +174,17 @@ export const BottomOfScreen: StoryFn = () => { ) : null} )} - itemToString={(item: IconItems) => (item ? String(item.label) : '')} + itemToString={(item: IconItems) => (item ? String(item.label) : "")} /> ); }; -BottomOfScreen.storyName = 'Bottom of screen'; +BottomOfScreen.storyName = "Bottom of screen"; BottomOfScreen.parameters = { - chromatic: {disableSnapshot: true}, + chromatic: { disableSnapshot: true }, }; -const ItemToString = ({name}: {name: string}): string => name; +const ItemToString = ({ name }: { name: string }): string => name; export const VirtualizedCombobox: StoryFn = () => { const itemsForVirtualCombobox = React.useMemo(() => createLargeArray((index) => (index as number).toString()), []); @@ -201,16 +201,16 @@ export const VirtualizedCombobox: StoryFn = () => { ); }; -VirtualizedCombobox.storyName = 'Combobox - Virtualized without option template'; +VirtualizedCombobox.storyName = "Combobox - Virtualized without option template"; export const VirtualizedCombobox1: StoryFn = () => { const itemsForVirtualCombobox = React.useMemo( () => createLargeArray((index) => ({ name: `Item ${index as number}`, - subtext: 'Virtualized combobox from Twilio Paste', + subtext: "Virtualized combobox from Twilio Paste", })), - [] + [], ); return ( @@ -219,7 +219,7 @@ export const VirtualizedCombobox1: StoryFn = () => { initialIsOpen itemToString={ItemToString} items={itemsForVirtualCombobox} - optionTemplate={({name, subtext}: {name: string; subtext: string}): string => `${name} - ${subtext}`} + optionTemplate={({ name, subtext }: { name: string; subtext: string }): string => `${name} - ${subtext}`} labelText="Select a virtualized item" helpText="This large list is virtualized" /> @@ -227,16 +227,16 @@ export const VirtualizedCombobox1: StoryFn = () => { ); }; -VirtualizedCombobox1.storyName = 'Combobox - Virtualized with string option template'; +VirtualizedCombobox1.storyName = "Combobox - Virtualized with string option template"; export const VirtualizedCombobox2: StoryFn = () => { const itemsForVirtualCombobox = React.useMemo( () => createLargeArray((index) => ({ name: `Item ${index as number}`, - subtext: 'Virtualized combobox from Twilio Paste', + subtext: "Virtualized combobox from Twilio Paste", })), - [] + [], ); return ( @@ -244,7 +244,7 @@ export const VirtualizedCombobox2: StoryFn = () => { initialIsOpen items={itemsForVirtualCombobox} itemToString={ItemToString} - optionTemplate={({name, subtext}) => ( + optionTemplate={({ name, subtext }) => ( {name} @@ -259,7 +259,7 @@ export const VirtualizedCombobox2: StoryFn = () => { ); }; -VirtualizedCombobox2.storyName = 'Combobox - Virtualized with React child option template'; +VirtualizedCombobox2.storyName = "Combobox - Virtualized with React child option template"; export const ComboboxInverse: StoryFn = () => { return ( @@ -284,14 +284,14 @@ export const ComboboxInverse: StoryFn = () => { ) : null} )} - itemToString={(item: IconItems) => (item ? String(item.label) : '')} + itemToString={(item: IconItems) => (item ? String(item.label) : "")} variant="inverse" /> ); }; -ComboboxInverse.storyName = 'Combobox - Inverse'; +ComboboxInverse.storyName = "Combobox - Inverse"; export const ComboboxAutocomplete: StoryFn = () => { const [inputItems, setInputItems] = React.useState(items); @@ -299,7 +299,7 @@ export const ComboboxAutocomplete: StoryFn = () => { { + onInputValueChange={({ inputValue }) => { if (inputValue !== undefined) { setInputItems(items.filter((item) => item.toLowerCase().startsWith(inputValue.toLowerCase()))); } @@ -310,19 +310,19 @@ export const ComboboxAutocomplete: StoryFn = () => { ); }; -ComboboxAutocomplete.storyName = 'Combobox - Autocomplete'; +ComboboxAutocomplete.storyName = "Combobox - Autocomplete"; export const ComboboxHiddenLabel: StoryFn = () => { return ; }; -ComboboxHiddenLabel.storyName = 'Combobox - Non-visble label'; +ComboboxHiddenLabel.storyName = "Combobox - Non-visble label"; export const ComboboxRequired: StoryFn = () => { return ; }; -ComboboxRequired.storyName = 'Combobox - Required'; +ComboboxRequired.storyName = "Combobox - Required"; export const ComboboxRequiredInverse: StoryFn = () => { return ( @@ -338,13 +338,13 @@ export const ComboboxRequiredInverse: StoryFn = () => { ); }; -ComboboxRequiredInverse.storyName = 'Combobox - Required inverse'; +ComboboxRequiredInverse.storyName = "Combobox - Required inverse"; export const ComboboxError: StoryFn = () => { return ; }; -ComboboxError.storyName = 'Combobox - Error'; +ComboboxError.storyName = "Combobox - Error"; export const ComboboxErrorInverse: StoryFn = () => { return ( @@ -360,7 +360,7 @@ export const ComboboxErrorInverse: StoryFn = () => { ); }; -ComboboxErrorInverse.storyName = 'Combobox - Error inverse'; +ComboboxErrorInverse.storyName = "Combobox - Error inverse"; export const ComboboxDisabled: StoryFn = () => { return ( @@ -374,7 +374,7 @@ export const ComboboxDisabled: StoryFn = () => { ); }; -ComboboxDisabled.storyName = 'Combobox - Disabled'; +ComboboxDisabled.storyName = "Combobox - Disabled"; export const ComboboxDisabledItems: StoryFn = () => { return ( @@ -388,7 +388,7 @@ export const ComboboxDisabledItems: StoryFn = () => { ); }; -ComboboxDisabledItems.storyName = 'Combobox - Disabled Items'; +ComboboxDisabledItems.storyName = "Combobox - Disabled Items"; export const ComboboxDisabledInverse: StoryFn = () => { return ( @@ -405,7 +405,7 @@ export const ComboboxDisabledInverse: StoryFn = () => { ); }; -ComboboxDisabledInverse.storyName = 'Combobox - Disabled inverse'; +ComboboxDisabledInverse.storyName = "Combobox - Disabled inverse"; export const ComboboxInsertBeforeAndAfter: StoryFn = () => { return ( @@ -427,7 +427,7 @@ export const ComboboxInsertBeforeAndAfter: StoryFn = () => { ); }; -ComboboxInsertBeforeAndAfter.storyName = 'Combobox - Insert before and after'; +ComboboxInsertBeforeAndAfter.storyName = "Combobox - Insert before and after"; export const ComboboxDisabledInsertBeforeAndAfter: StoryFn = () => { return ( @@ -450,7 +450,7 @@ export const ComboboxDisabledInsertBeforeAndAfter: StoryFn = () => { ); }; -ComboboxDisabledInsertBeforeAndAfter.storyName = 'Combobox - Disabled insert before and after'; +ComboboxDisabledInsertBeforeAndAfter.storyName = "Combobox - Disabled insert before and after"; export const ComboboxInsertBeforeAndAfterInverse: StoryFn = () => { return ( @@ -475,7 +475,7 @@ export const ComboboxInsertBeforeAndAfterInverse: StoryFn = () => { ); }; -ComboboxInsertBeforeAndAfterInverse.storyName = 'Combobox - Insert before and after inverse'; +ComboboxInsertBeforeAndAfterInverse.storyName = "Combobox - Insert before and after inverse"; export const ComboboxDisabledInsertBeforeAndAfterInverse: StoryFn = () => { return ( @@ -501,7 +501,7 @@ export const ComboboxDisabledInsertBeforeAndAfterInverse: StoryFn = () => { ); }; -ComboboxDisabledInsertBeforeAndAfterInverse.storyName = 'Combobox - Disabled insert before and after inverse'; +ComboboxDisabledInsertBeforeAndAfterInverse.storyName = "Combobox - Disabled insert before and after inverse"; export const ComboboxObject: StoryFn = () => { const [inputItems, setInputItems] = React.useState(objectItems); @@ -516,20 +516,20 @@ export const ComboboxObject: StoryFn = () => { {item.code} | {item.label} | {item.phone}
  • )} - onInputValueChange={({inputValue}) => { + onInputValueChange={({ inputValue }) => { if (inputValue !== undefined) { setInputItems( - _.filter(objectItems, (item: ObjectItem) => item.label.toLowerCase().startsWith(inputValue.toLowerCase())) + _.filter(objectItems, (item: ObjectItem) => item.label.toLowerCase().startsWith(inputValue.toLowerCase())), ); } }} - itemToString={(item: ObjectItem) => (item ? item.label : '')} + itemToString={(item: ObjectItem) => (item ? item.label : "")} disabledItems={objectItems.slice(2, 5)} /> ); }; -ComboboxObject.storyName = 'Combobox - Object'; +ComboboxObject.storyName = "Combobox - Object"; export const ComboboxOverflowLongValue: StoryFn = () => { const [inputItems, setInputItems] = React.useState(items); @@ -540,7 +540,7 @@ export const ComboboxOverflowLongValue: StoryFn = () => { helpText="This is the help text" labelText="Choose a component:" initialSelectedItem={inputItems[5]} - onInputValueChange={({inputValue}) => { + onInputValueChange={({ inputValue }) => { if (inputValue !== undefined) { setInputItems(items.filter((item) => item.toLowerCase().startsWith(inputValue.toLowerCase()))); } @@ -551,11 +551,11 @@ export const ComboboxOverflowLongValue: StoryFn = () => { ); }; -ComboboxOverflowLongValue.storyName = 'Combobox - overflow long value'; +ComboboxOverflowLongValue.storyName = "Combobox - overflow long value"; export const ComboboxControlled: StoryFn = () => { - const [value, setValue] = React.useState('United Arab Emirates'); - const [selectedItem, setSelectedItem] = React.useState({code: 'AE', label: 'United Arab Emirates', phone: '971'}); + const [value, setValue] = React.useState("United Arab Emirates"); + const [selectedItem, setSelectedItem] = React.useState({ code: "AE", label: "United Arab Emirates", phone: "971" }); const [inputItems, setInputItems] = React.useState(objectItems); return ( <> @@ -573,20 +573,22 @@ export const ComboboxControlled: StoryFn = () => { optionTemplate={(item: ObjectItem) => { return ( - {item.code} | {item.label} | {item.phone}{' '} - {item && selectedItem && item.label === selectedItem.label ? '✅' : null} + {item.code} | {item.label} | {item.phone}{" "} + {item && selectedItem && item.label === selectedItem.label ? "✅" : null} ); }} - onInputValueChange={({inputValue}) => { + onInputValueChange={({ inputValue }) => { if (inputValue !== undefined) { setInputItems( - _.filter(objectItems, (item: ObjectItem) => item.label.toLowerCase().startsWith(inputValue.toLowerCase())) + _.filter(objectItems, (item: ObjectItem) => + item.label.toLowerCase().startsWith(inputValue.toLowerCase()), + ), ); setValue(inputValue); } }} - itemToString={(item: ObjectItem) => (item ? item.label : '')} + itemToString={(item: ObjectItem) => (item ? item.label : "")} selectedItem={selectedItem} onSelectedItemChange={(changes) => { setSelectedItem(changes.selectedItem); @@ -597,29 +599,29 @@ export const ComboboxControlled: StoryFn = () => { ); }; -ComboboxControlled.storyName = 'Combobox - Controlled'; +ComboboxControlled.storyName = "Combobox - Controlled"; export const ComboboxControlledUsingState: StoryFn = () => { - const [value, setValue] = React.useState('United Arab Emirates'); + const [value, setValue] = React.useState("United Arab Emirates"); const [selectedItem, setSelectedItem] = React.useState({ - code: 'AE', - label: 'United Arab Emirates', - phone: '971', + code: "AE", + label: "United Arab Emirates", + phone: "971", } as ObjectItem); const [inputItems, setInputItems] = React.useState(objectItems as ObjectItem[]); - const {reset, ...state} = useCombobox({ + const { reset, ...state } = useCombobox({ initialInputValue: value, items: inputItems, - itemToString: (item) => (item ? item.label : ''), + itemToString: (item) => (item ? item.label : ""), onSelectedItemChange: (changes) => { if (changes.selectedItem != null) { setSelectedItem(changes.selectedItem); } }, - onInputValueChange: ({inputValue}) => { + onInputValueChange: ({ inputValue }) => { if (inputValue !== undefined) { setInputItems( - _.filter(objectItems, (item: ObjectItem) => item.label.toLowerCase().startsWith(inputValue.toLowerCase())) + _.filter(objectItems, (item: ObjectItem) => item.label.toLowerCase().startsWith(inputValue.toLowerCase())), ); setValue(inputValue); } @@ -634,16 +636,16 @@ export const ComboboxControlledUsingState: StoryFn = () => { Selected item state: {JSON.stringify(selectedItem)} (item ? item.label : '')} + itemToString={(item) => (item ? item.label : "")} labelText="Choose a country:" helpText="This is the help text" optionTemplate={(item: ObjectItem) => ( - {item.code} | {item.label} | {item.phone}{' '} - {item && selectedItem && item.label === selectedItem.label ? '✅' : null} + {item.code} | {item.label} | {item.phone}{" "} + {item && selectedItem && item.label === selectedItem.label ? "✅" : null} )} insertAfter={ @@ -651,12 +653,12 @@ export const ComboboxControlledUsingState: StoryFn = () => { variant="link" size="reset" onClick={() => { - setValue(''); + setValue(""); setSelectedItem({} as ObjectItem); reset(); }} > - {value !== '' ? ( + {value !== "" ? ( ) : ( @@ -668,7 +670,7 @@ export const ComboboxControlledUsingState: StoryFn = () => { ); }; -ComboboxControlledUsingState.storyName = 'Combobox - Controlled using state'; +ComboboxControlledUsingState.storyName = "Combobox - Controlled using state"; export const ComboboxOpen: StoryFn = () => { return ( @@ -677,12 +679,12 @@ export const ComboboxOpen: StoryFn = () => { labelText="Choose a country:" initialIsOpen optionTemplate={(item: ObjectItem) =>
    {item.label}
    } - itemToString={(item: ObjectItem) => (item ? item.label : '')} + itemToString={(item: ObjectItem) => (item ? item.label : "")} /> ); }; -ComboboxOpen.storyName = 'Combobox - Open'; +ComboboxOpen.storyName = "Combobox - Open"; export const ComboboxOptionGroups: StoryFn = () => { return ( @@ -692,12 +694,12 @@ export const ComboboxOptionGroups: StoryFn = () => { labelText="Choose a component:" helpText="This is group" optionTemplate={(item: GroupedItem) =>
    {item.label}
    } - itemToString={(item: GroupedItem) => (item ? item.label : '')} + itemToString={(item: GroupedItem) => (item ? item.label : "")} /> ); }; -ComboboxOptionGroups.storyName = 'Combobox - Option groups'; +ComboboxOptionGroups.storyName = "Combobox - Option groups"; export const ComboboxOptionGroupsOpen: StoryFn = () => { return ( @@ -709,7 +711,7 @@ export const ComboboxOptionGroupsOpen: StoryFn = () => { initialIsOpen optionTemplate={(item: GroupedItem) =>
    {item.label}
    } groupLabelTemplate={(groupName: string) => { - if (groupName === 'Components') { + if (groupName === "Components") { return ( @@ -721,12 +723,12 @@ export const ComboboxOptionGroupsOpen: StoryFn = () => { } return groupName; }} - itemToString={(item: GroupedItem) => (item ? item.label : '')} + itemToString={(item: GroupedItem) => (item ? item.label : "")} /> ); }; -ComboboxOptionGroupsOpen.storyName = 'Combobox - Option groups open'; +ComboboxOptionGroupsOpen.storyName = "Combobox - Option groups open"; export const ComboboxOptionGroupsAutocomplete: StoryFn = () => { const [inputItems, setInputItems] = React.useState(groupedItems); @@ -738,22 +740,24 @@ export const ComboboxOptionGroupsAutocomplete: StoryFn = () => { labelText="Choose a component:" helpText="This is the help text" optionTemplate={(item: GroupedItem) =>
    {item.label}
    } - onInputValueChange={({inputValue}) => { + onInputValueChange={({ inputValue }) => { if (inputValue !== undefined) { setInputItems( - _.filter(groupedItems, (item: GroupedItem) => item.label.toLowerCase().startsWith(inputValue.toLowerCase())) + _.filter(groupedItems, (item: GroupedItem) => + item.label.toLowerCase().startsWith(inputValue.toLowerCase()), + ), ); } }} - itemToString={(item: GroupedItem) => (item ? item.label : '')} + itemToString={(item: GroupedItem) => (item ? item.label : "")} /> ); }; -ComboboxOptionGroupsAutocomplete.storyName = 'Combobox - Option groups autocomplete'; +ComboboxOptionGroupsAutocomplete.storyName = "Combobox - Option groups autocomplete"; export const ComboboxListboxZIndex: StoryFn = () => { - const [selectValue, setSelectValue] = React.useState(''); + const [selectValue, setSelectValue] = React.useState(""); const selectID = useUID(); return ( <> @@ -778,7 +782,7 @@ export const ComboboxListboxZIndex: StoryFn = () => { ) : null}
    )} - itemToString={(item: IconItems) => (item ? String(item.label) : '')} + itemToString={(item: IconItems) => (item ? String(item.label) : "")} initialIsOpen /> @@ -795,7 +799,7 @@ export const ComboboxListboxZIndex: StoryFn = () => { ); }; -ComboboxListboxZIndex.storyName = 'Combobox - Listbox zIndex'; +ComboboxListboxZIndex.storyName = "Combobox - Listbox zIndex"; const SampleEmptyState: React.FC = () => ( <> @@ -814,7 +818,7 @@ export const ComboboxEmptyState: StoryFn = () => { autocomplete items={inputItems} inputValue="test123" - onInputValueChange={({inputValue}) => { + onInputValueChange={({ inputValue }) => { if (inputValue !== undefined) { setInputItems(items.filter((item) => item.toLowerCase().startsWith(inputValue.toLowerCase()))); } @@ -827,7 +831,7 @@ export const ComboboxEmptyState: StoryFn = () => { ); }; -ComboboxEmptyState.storyName = 'Combobox - EmptyState'; +ComboboxEmptyState.storyName = "Combobox - EmptyState"; export const ComboboxInModal: StoryFn = () => { const [modalIsOpen, setModalIsOpen] = React.useState(true); @@ -868,7 +872,7 @@ export const ComboboxInModal: StoryFn = () => { ) : null} )} - itemToString={(item: IconItems) => (item ? String(item.label) : '')} + itemToString={(item: IconItems) => (item ? String(item.label) : "")} /> diff --git a/packages/paste-core/components/combobox/stories/GrowingInput.stories.tsx b/packages/paste-core/components/combobox/stories/GrowingInput.stories.tsx index 342405c511..7941947990 100644 --- a/packages/paste-core/components/combobox/stories/GrowingInput.stories.tsx +++ b/packages/paste-core/components/combobox/stories/GrowingInput.stories.tsx @@ -1,10 +1,10 @@ -import * as React from 'react'; -import type {StoryFn} from '@storybook/react'; -import {Box} from '@twilio-paste/box'; -import {Label} from '@twilio-paste/label'; -import {useUID} from '@twilio-paste/uid-library'; +import type { StoryFn } from "@storybook/react"; +import { Box } from "@twilio-paste/box"; +import { Label } from "@twilio-paste/label"; +import { useUID } from "@twilio-paste/uid-library"; +import * as React from "react"; -import {GrowingInput} from '../src/multiselect/GrowingInput'; +import { GrowingInput } from "../src/multiselect/GrowingInput"; export const GrowingInputDemo: StoryFn = () => { const id = useUID(); @@ -21,14 +21,14 @@ export const GrowingInputDemo: StoryFn = () => { ); }; -GrowingInputDemo.storyName = 'GrowingInput'; +GrowingInputDemo.storyName = "GrowingInput"; GrowingInputDemo.parameters = { // Nothing to VRT. Story for developer experience - chromatic: {disableSnapshot: true}, + chromatic: { disableSnapshot: true }, }; // eslint-disable-next-line import/no-default-export export default { - title: 'Components/Combobox', + title: "Components/Combobox", component: GrowingInputDemo, }; diff --git a/packages/paste-core/components/combobox/stories/MultiselectCombobox-customization.stories.tsx b/packages/paste-core/components/combobox/stories/MultiselectCombobox-customization.stories.tsx index 8592b7fcb3..b112e2496e 100644 --- a/packages/paste-core/components/combobox/stories/MultiselectCombobox-customization.stories.tsx +++ b/packages/paste-core/components/combobox/stories/MultiselectCombobox-customization.stories.tsx @@ -1,15 +1,15 @@ -import * as React from 'react'; -import type {StoryFn} from '@storybook/react'; -import {Stack} from '@twilio-paste/stack'; -import {CustomizationProvider} from '@twilio-paste/customization'; -import {Card} from '@twilio-paste/card'; -import {Text} from '@twilio-paste/text'; -import {InformationIcon} from '@twilio-paste/icons/esm/InformationIcon'; -import {useTheme} from '@twilio-paste/theme'; +import type { StoryFn } from "@storybook/react"; +import { Card } from "@twilio-paste/card"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import { InformationIcon } from "@twilio-paste/icons/esm/InformationIcon"; +import { Stack } from "@twilio-paste/stack"; +import { Text } from "@twilio-paste/text"; +import { useTheme } from "@twilio-paste/theme"; +import * as React from "react"; -import {MultiselectCombobox} from '../src'; +import { MultiselectCombobox } from "../src"; -const items = ['a', 'b', 'c']; +const items = ["a", "b", "c"]; const initialSelectedItems = [items[0], items[1]]; interface GroupedItem { @@ -18,17 +18,17 @@ interface GroupedItem { } const groupedItems = [ - {letter: 'a', number: 1}, - {letter: 'a', number: 2}, - {letter: 'b', number: 3}, - {letter: 'b', number: 4}, - {letter: 'b', number: 5}, - {letter: 'c', number: 6}, - {letter: 'd', number: 7}, + { letter: "a", number: 1 }, + { letter: "a", number: 2 }, + { letter: "b", number: 3 }, + { letter: "b", number: 4 }, + { letter: "b", number: 5 }, + { letter: "c", number: 6 }, + { letter: "d", number: 7 }, ]; const initialSelectedGroupedItems = [groupedItems[0], groupedItems[1], groupedItems[2]]; -const ShowCustomization: React.FC> = ({ +const ShowCustomization: React.FC> = ({ isTestEnvironment, children, }): React.ReactElement => { @@ -42,25 +42,25 @@ const ShowCustomization: React.FC @@ -72,31 +72,31 @@ const ShowCustomization: React.FC - {React.cloneElement(children as React.ReactElement, {element: 'FOO'})} + {React.cloneElement(children as React.ReactElement, { element: "FOO" })} ); }; -export const CustomizedCombobox: StoryFn = (_args, {parameters: {isTestEnvironment}}) => ( +export const CustomizedCombobox: StoryFn = (_args, { parameters: { isTestEnvironment } }) => ( ); -CustomizedCombobox.storyName = 'MultiselectCombobox - Default'; +CustomizedCombobox.storyName = "MultiselectCombobox - Default"; -export const CustomizedComboboxGroups: StoryFn = (_args, {parameters: {isTestEnvironment}}) => ( +export const CustomizedComboboxGroups: StoryFn = (_args, { parameters: { isTestEnvironment } }) => (
    {item.number}
    } - itemToString={(item: GroupedItem) => (item ? `${item.number}` : '')} + itemToString={(item: GroupedItem) => (item ? `${item.number}` : "")} initialSelectedItems={initialSelectedGroupedItems} />
    ); -CustomizedComboboxGroups.storyName = 'MultiselectCombobox - With groups'; +CustomizedComboboxGroups.storyName = "MultiselectCombobox - With groups"; -export const CustomizedComboboxBeforeAndAfter: StoryFn = (_args, {parameters: {isTestEnvironment}}) => ( +export const CustomizedComboboxBeforeAndAfter: StoryFn = (_args, { parameters: { isTestEnvironment } }) => (
    {item.number}
    } - itemToString={(item: GroupedItem) => (item ? `${item.number}` : '')} + itemToString={(item: GroupedItem) => (item ? `${item.number}` : "")} insertBefore={Z} insertAfter={} initialSelectedItems={initialSelectedGroupedItems} />
    ); -CustomizedComboboxBeforeAndAfter.storyName = 'MultiselectCombobox - With prefix and suffix'; +CustomizedComboboxBeforeAndAfter.storyName = "MultiselectCombobox - With prefix and suffix"; // eslint-disable-next-line import/no-default-export export default { - title: 'Components/Combobox/Customization - MultiselectCombobox', + title: "Components/Combobox/Customization - MultiselectCombobox", component: CustomizedCombobox, parameters: { a11y: { diff --git a/packages/paste-core/components/combobox/stories/MultiselectCombobox.stories.tsx b/packages/paste-core/components/combobox/stories/MultiselectCombobox.stories.tsx index d3a791c20d..1c9eff5afc 100644 --- a/packages/paste-core/components/combobox/stories/MultiselectCombobox.stories.tsx +++ b/packages/paste-core/components/combobox/stories/MultiselectCombobox.stories.tsx @@ -1,36 +1,36 @@ -import * as React from 'react'; -import type {Meta, StoryFn, StoryContext} from '@storybook/react'; -import {Box} from '@twilio-paste/box'; -import {Text} from '@twilio-paste/text'; -import {Anchor} from '@twilio-paste/anchor'; -import {MediaObject, MediaFigure, MediaBody} from '@twilio-paste/media-object'; -import {InformationIcon} from '@twilio-paste/icons/esm/InformationIcon'; -import {AttachIcon} from '@twilio-paste/icons/esm/AttachIcon'; -import filter from 'lodash/filter'; -import {Form} from '@twilio-paste/form'; -import {Modal, ModalBody, ModalHeader, ModalHeading} from '@twilio-paste/modal'; -import {Button} from '@twilio-paste/button'; -import {useUID} from '@twilio-paste/uid-library'; - -import {MultiselectCombobox, useMultiselectCombobox} from '../src'; +import type { Meta, StoryContext, StoryFn } from "@storybook/react"; +import { Anchor } from "@twilio-paste/anchor"; +import { Box } from "@twilio-paste/box"; +import { Button } from "@twilio-paste/button"; +import { Form } from "@twilio-paste/form"; +import { AttachIcon } from "@twilio-paste/icons/esm/AttachIcon"; +import { InformationIcon } from "@twilio-paste/icons/esm/InformationIcon"; +import { MediaBody, MediaFigure, MediaObject } from "@twilio-paste/media-object"; +import { Modal, ModalBody, ModalHeader, ModalHeading } from "@twilio-paste/modal"; +import { Text } from "@twilio-paste/text"; +import { useUID } from "@twilio-paste/uid-library"; +import filter from "lodash/filter"; +import * as React from "react"; + +import { MultiselectCombobox, useMultiselectCombobox } from "../src"; function createLargeArray>( - template: (index?: number | undefined) => TemplateResult + template: (index?: number | undefined) => TemplateResult, ): TemplateResult[] { // eslint-disable-next-line unicorn/prefer-spread return Array.from(new Array(1000), (_empty, index) => template(index)); } const items = [ - 'Alert', - 'Anchor', - 'Button', - 'Card', - 'Heading', - 'A component with a really really really really really really really really long name', - 'List', - 'Modal', - 'Paragraph', + "Alert", + "Anchor", + "Button", + "Card", + "Heading", + "A component with a really really really really really really really really long name", + "List", + "Modal", + "Paragraph", ]; function getFilteredItems(inputValue: string): string[] { @@ -45,7 +45,7 @@ function getFilteredItems(inputValue: string): string[] { * Basic */ export const MultiselectComboboxBasic = (): React.ReactNode => { - const [inputValue, setInputValue] = React.useState(''); + const [inputValue, setInputValue] = React.useState(""); const filteredItems = React.useMemo(() => getFilteredItems(inputValue), [inputValue]); return ( @@ -54,7 +54,7 @@ export const MultiselectComboboxBasic = (): React.ReactNode => { selectedItemsLabelText="Selected Paste components" helpText="Paste components are the building blocks of your product UI." items={filteredItems} - onInputValueChange={({inputValue: newInputValue = ''}) => { + onInputValueChange={({ inputValue: newInputValue = "" }) => { setInputValue(newInputValue); }} onSelectedItemsChange={(selectedItems) => { @@ -64,10 +64,10 @@ export const MultiselectComboboxBasic = (): React.ReactNode => { /> ); }; -MultiselectComboboxBasic.storyName = 'Basic'; +MultiselectComboboxBasic.storyName = "Basic"; export const BottomOfScreen = (): React.ReactNode => { - const [inputValue, setInputValue] = React.useState(''); + const [inputValue, setInputValue] = React.useState(""); const filteredItems = React.useMemo(() => getFilteredItems(inputValue), [inputValue]); return ( @@ -78,7 +78,7 @@ export const BottomOfScreen = (): React.ReactNode => { selectedItemsLabelText="Selected Paste components" helpText="Paste components are the building blocks of your product UI." items={filteredItems} - onInputValueChange={({inputValue: newInputValue = ''}) => { + onInputValueChange={({ inputValue: newInputValue = "" }) => { setInputValue(newInputValue); }} onSelectedItemsChange={(selectedItems) => { @@ -89,16 +89,16 @@ export const BottomOfScreen = (): React.ReactNode => { ); }; -BottomOfScreen.storyName = 'Bottom of screen'; +BottomOfScreen.storyName = "Bottom of screen"; BottomOfScreen.parameters = { - chromatic: {disableSnapshot: true}, + chromatic: { disableSnapshot: true }, }; /* * Basic - Inverse */ export const MultiselectComboboxInverse = (): React.ReactNode => { - const [inputValue, setInputValue] = React.useState(''); + const [inputValue, setInputValue] = React.useState(""); const filteredItems = React.useMemo(() => getFilteredItems(inputValue), [inputValue]); return ( @@ -109,7 +109,7 @@ export const MultiselectComboboxInverse = (): React.ReactNode => { selectedItemsLabelText="Selected Paste components" helpText="Paste components are the building blocks of your product UI." items={filteredItems} - onInputValueChange={({inputValue: newInputValue = ''}) => { + onInputValueChange={({ inputValue: newInputValue = "" }) => { setInputValue(newInputValue); }} onSelectedItemsChange={(selectedItems) => { @@ -120,13 +120,13 @@ export const MultiselectComboboxInverse = (): React.ReactNode => { ); }; -MultiselectComboboxInverse.storyName = 'variant Inverse'; +MultiselectComboboxInverse.storyName = "variant Inverse"; /* * Basic - Disabled */ export const MultiselectComboboxDisabled = (): React.ReactNode => { - const [inputValue, setInputValue] = React.useState(''); + const [inputValue, setInputValue] = React.useState(""); const filteredItems = React.useMemo(() => getFilteredItems(inputValue), [inputValue]); return ( @@ -137,7 +137,7 @@ export const MultiselectComboboxDisabled = (): React.ReactNode => { selectedItemsLabelText="Selected Paste components" helpText="Paste components are the building blocks of your product UI." items={filteredItems} - onInputValueChange={({inputValue: newInputValue = ''}) => { + onInputValueChange={({ inputValue: newInputValue = "" }) => { setInputValue(newInputValue); }} onSelectedItemsChange={(selectedItems) => { @@ -147,13 +147,13 @@ export const MultiselectComboboxDisabled = (): React.ReactNode => { /> ); }; -MultiselectComboboxDisabled.storyName = 'Basic - Disabled'; +MultiselectComboboxDisabled.storyName = "Basic - Disabled"; /* * Basic - Disabled, Inverse, Required */ export const MultiselectComboboxDisabledInverseRequired = (): React.ReactNode => { - const [inputValue, setInputValue] = React.useState(''); + const [inputValue, setInputValue] = React.useState(""); const filteredItems = React.useMemo(() => getFilteredItems(inputValue), [inputValue]); return ( @@ -166,7 +166,7 @@ export const MultiselectComboboxDisabledInverseRequired = (): React.ReactNode => selectedItemsLabelText="Selected Paste components" helpText="Paste components are the building blocks of your product UI." items={filteredItems} - onInputValueChange={({inputValue: newInputValue = ''}) => { + onInputValueChange={({ inputValue: newInputValue = "" }) => { setInputValue(newInputValue); }} onSelectedItemsChange={(selectedItems) => { @@ -177,13 +177,13 @@ export const MultiselectComboboxDisabledInverseRequired = (): React.ReactNode => ); }; -MultiselectComboboxDisabledInverseRequired.storyName = 'Basic - Disabled, Inverse, Required'; +MultiselectComboboxDisabledInverseRequired.storyName = "Basic - Disabled, Inverse, Required"; /* * Basic - Error */ export const MultiselectComboboxError = (): React.ReactNode => { - const [inputValue, setInputValue] = React.useState(''); + const [inputValue, setInputValue] = React.useState(""); const filteredItems = React.useMemo(() => getFilteredItems(inputValue), [inputValue]); return ( @@ -193,9 +193,9 @@ export const MultiselectComboboxError = (): React.ReactNode => { selectedItemsLabelText="Selected Paste components" helpText="Paste components are the building blocks of your product UI." items={filteredItems} - initialSelectedItems={['Alert', 'Anchor']} + initialSelectedItems={["Alert", "Anchor"]} initialIsOpen - onInputValueChange={({inputValue: newInputValue = ''}) => { + onInputValueChange={({ inputValue: newInputValue = "" }) => { setInputValue(newInputValue); }} onSelectedItemsChange={(selectedItems) => { @@ -205,13 +205,13 @@ export const MultiselectComboboxError = (): React.ReactNode => { /> ); }; -MultiselectComboboxError.storyName = 'Basic - Error'; +MultiselectComboboxError.storyName = "Basic - Error"; /* * Basic - Required */ export const MultiselectComboboxRequired = (): React.ReactNode => { - const [inputValue, setInputValue] = React.useState(''); + const [inputValue, setInputValue] = React.useState(""); const filteredItems = React.useMemo(() => getFilteredItems(inputValue), [inputValue]); return ( @@ -219,7 +219,7 @@ export const MultiselectComboboxRequired = (): React.ReactNode => { onSubmit={(event) => { event.preventDefault(); // eslint-disable-next-line no-console - console.log('The form was submit'); + console.log("The form was submit"); }} > { selectedItemsLabelText="Selected Paste components" helpText="Paste components are the building blocks of your product UI." items={filteredItems} - initialSelectedItems={['Alert', 'Anchor']} - onInputValueChange={({inputValue: newInputValue = ''}) => { + initialSelectedItems={["Alert", "Anchor"]} + onInputValueChange={({ inputValue: newInputValue = "" }) => { setInputValue(newInputValue); }} onSelectedItemsChange={(selectedItems) => { @@ -240,13 +240,13 @@ export const MultiselectComboboxRequired = (): React.ReactNode => { ); }; -MultiselectComboboxRequired.storyName = 'Basic - Required'; +MultiselectComboboxRequired.storyName = "Basic - Required"; /* * initialSelectedItems */ export const MultiselectComboboxInitialSelectedItems = (): React.ReactNode => { - const [inputValue, setInputValue] = React.useState(''); + const [inputValue, setInputValue] = React.useState(""); const filteredItems = React.useMemo(() => getFilteredItems(inputValue), [inputValue]); return ( @@ -255,8 +255,8 @@ export const MultiselectComboboxInitialSelectedItems = (): React.ReactNode => { selectedItemsLabelText="Selected Paste components" helpText="Paste components are the building blocks of your product UI." items={filteredItems} - initialSelectedItems={['Alert', 'Anchor']} - onInputValueChange={({inputValue: newInputValue = ''}) => { + initialSelectedItems={["Alert", "Anchor"]} + onInputValueChange={({ inputValue: newInputValue = "" }) => { setInputValue(newInputValue); }} onSelectedItemsChange={(selectedItems) => { @@ -266,7 +266,7 @@ export const MultiselectComboboxInitialSelectedItems = (): React.ReactNode => { /> ); }; -MultiselectComboboxInitialSelectedItems.storyName = 'with initialSelectedItems'; +MultiselectComboboxInitialSelectedItems.storyName = "with initialSelectedItems"; /* * insertBefore and insertAfter @@ -293,7 +293,7 @@ function getFilteredBooks(inputValue: string): Book[] { } export const MultiselectComboboxBeforeAfter = (): React.ReactNode => { - const [inputValue, setInputValue] = React.useState(''); + const [inputValue, setInputValue] = React.useState(""); const filteredItems = React.useMemo(() => getFilteredBooks(inputValue), [inputValue]); return ( @@ -302,7 +302,7 @@ export const MultiselectComboboxBeforeAfter = (): React.ReactNode => { selectedItemsLabelText="Selected books:" helpText="Reading books can be good for your mental health." items={filteredItems} - itemToString={(item: Book) => (item ? `${item.title} - ${item.author}` : '')} + itemToString={(item: Book) => (item ? `${item.title} - ${item.author}` : "")} initialSelectedItems={filteredItems.slice(20, 50)} insertBefore={ @@ -314,7 +314,7 @@ export const MultiselectComboboxBeforeAfter = (): React.ReactNode => { } - optionTemplate={({title, author}: Book) => ( + optionTemplate={({ title, author }: Book) => ( {title} @@ -322,7 +322,7 @@ export const MultiselectComboboxBeforeAfter = (): React.ReactNode => { )} - onInputValueChange={({inputValue: newInputValue = ''}) => { + onInputValueChange={({ inputValue: newInputValue = "" }) => { setInputValue(newInputValue); }} onSelectedItemsChange={(selectedItems) => { @@ -332,13 +332,13 @@ export const MultiselectComboboxBeforeAfter = (): React.ReactNode => { /> ); }; -MultiselectComboboxBeforeAfter.storyName = 'with insertBefore and insertAfter'; +MultiselectComboboxBeforeAfter.storyName = "with insertBefore and insertAfter"; /* * maxHeight */ export const MultiselectComboboxMaxHeight = (): React.ReactNode => { - const [inputValue, setInputValue] = React.useState(''); + const [inputValue, setInputValue] = React.useState(""); const filteredItems = React.useMemo(() => getFilteredBooks(inputValue), [inputValue]); return ( @@ -347,7 +347,7 @@ export const MultiselectComboboxMaxHeight = (): React.ReactNode => { selectedItemsLabelText="Selected books:" helpText="Reading books can be good for your mental health." items={filteredItems} - itemToString={(item: Book) => (item ? `${item.title} - ${item.author}` : '')} + itemToString={(item: Book) => (item ? `${item.title} - ${item.author}` : "")} initialSelectedItems={filteredItems.slice(20, 80)} maxHeight="100px" insertBefore={ @@ -360,7 +360,7 @@ export const MultiselectComboboxMaxHeight = (): React.ReactNode => { } - optionTemplate={({title, author}: Book) => ( + optionTemplate={({ title, author }: Book) => ( {title} @@ -368,7 +368,7 @@ export const MultiselectComboboxMaxHeight = (): React.ReactNode => { )} - onInputValueChange={({inputValue: newInputValue = ''}) => { + onInputValueChange={({ inputValue: newInputValue = "" }) => { setInputValue(newInputValue); }} onSelectedItemsChange={(selectedItems) => { @@ -378,13 +378,13 @@ export const MultiselectComboboxMaxHeight = (): React.ReactNode => { /> ); }; -MultiselectComboboxMaxHeight.storyName = 'with maxHeight'; +MultiselectComboboxMaxHeight.storyName = "with maxHeight"; /* * optionTemplate */ export const MultiselectComboboxOptionTemplate = (): React.ReactNode => { - const [inputValue, setInputValue] = React.useState(''); + const [inputValue, setInputValue] = React.useState(""); const filteredItems = React.useMemo(() => getFilteredBooks(inputValue), [inputValue]); return ( @@ -393,8 +393,8 @@ export const MultiselectComboboxOptionTemplate = (): React.ReactNode => { selectedItemsLabelText="Selected books:" helpText="Reading books can be good for your mental health." items={filteredItems} - itemToString={(item: Book) => (item ? `${item.title} - ${item.author}` : '')} - optionTemplate={({title, author}: Book) => ( + itemToString={(item: Book) => (item ? `${item.title} - ${item.author}` : "")} + optionTemplate={({ title, author }: Book) => ( {title} @@ -402,7 +402,7 @@ export const MultiselectComboboxOptionTemplate = (): React.ReactNode => { )} - onInputValueChange={({inputValue: newInputValue = ''}) => { + onInputValueChange={({ inputValue: newInputValue = "" }) => { setInputValue(newInputValue); }} onSelectedItemsChange={(selectedItems) => { @@ -412,13 +412,13 @@ export const MultiselectComboboxOptionTemplate = (): React.ReactNode => { /> ); }; -MultiselectComboboxOptionTemplate.storyName = 'with optionTemplate'; +MultiselectComboboxOptionTemplate.storyName = "with optionTemplate"; /* * optionTemplate - disabled options */ export const MultiselectComboboxOptionTemplatedisabled = (): React.ReactNode => { - const [inputValue, setInputValue] = React.useState(''); + const [inputValue, setInputValue] = React.useState(""); const filteredItems = React.useMemo(() => getFilteredBooks(inputValue), [inputValue]); return ( @@ -427,8 +427,8 @@ export const MultiselectComboboxOptionTemplatedisabled = (): React.ReactNode => selectedItemsLabelText="Selected books:" helpText="Reading books can be good for your mental health." items={filteredItems} - itemToString={(item: Book) => (item ? `${item.title} - ${item.author}` : '')} - optionTemplate={({title, author}: Book) => ( + itemToString={(item: Book) => (item ? `${item.title} - ${item.author}` : "")} + optionTemplate={({ title, author }: Book) => ( {title} @@ -438,7 +438,7 @@ export const MultiselectComboboxOptionTemplatedisabled = (): React.ReactNode => )} disabledItems={filteredItems.slice(2, 8)} initialIsOpen - onInputValueChange={({inputValue: newInputValue = ''}) => { + onInputValueChange={({ inputValue: newInputValue = "" }) => { setInputValue(newInputValue); }} onSelectedItemsChange={(selectedItems) => { @@ -448,7 +448,7 @@ export const MultiselectComboboxOptionTemplatedisabled = (): React.ReactNode => /> ); }; -MultiselectComboboxOptionTemplatedisabled.storyName = 'with optionTemplate - disabled options'; +MultiselectComboboxOptionTemplatedisabled.storyName = "with optionTemplate - disabled options"; /* * groupedItemsBy @@ -458,19 +458,19 @@ interface GroupedItem { label: string; } const groupedItems = [ - {group: 'Components', label: 'Alert'}, - {group: 'Components', label: 'Anchor'}, - {group: 'Components', label: 'Button'}, - {group: 'Components', label: 'Card'}, - {group: 'Components', label: 'Heading'}, - {group: 'Components', label: 'List'}, - {group: 'Components', label: 'Modal'}, - {group: 'Components', label: 'Paragraph'}, - {group: 'Primitives', label: 'Box'}, - {group: 'Primitives', label: 'Text'}, - {group: 'Primitives', label: 'Non-modal dialog'}, - {group: 'Layout', label: 'Grid'}, - {label: 'Design Tokens'}, + { group: "Components", label: "Alert" }, + { group: "Components", label: "Anchor" }, + { group: "Components", label: "Button" }, + { group: "Components", label: "Card" }, + { group: "Components", label: "Heading" }, + { group: "Components", label: "List" }, + { group: "Components", label: "Modal" }, + { group: "Components", label: "Paragraph" }, + { group: "Primitives", label: "Box" }, + { group: "Primitives", label: "Text" }, + { group: "Primitives", label: "Non-modal dialog" }, + { group: "Layout", label: "Grid" }, + { label: "Design Tokens" }, ]; function getFilteredGroupedItems(inputValue: string): GroupedItem[] { @@ -479,15 +479,15 @@ function getFilteredGroupedItems(inputValue: string): GroupedItem[] { } export const MultiselectComboboxOptionGroups = (): React.ReactNode => { - const [inputValue, setInputValue] = React.useState(''); + const [inputValue, setInputValue] = React.useState(""); const filteredItems = React.useMemo(() => getFilteredGroupedItems(inputValue), [inputValue]); return ( (item ? item.label : '')} - onInputValueChange={({inputValue: newInputValue = ''}) => { + itemToString={(item: GroupedItem) => (item ? item.label : "")} + onInputValueChange={({ inputValue: newInputValue = "" }) => { setInputValue(newInputValue); }} onSelectedItemsChange={(selectedItems) => { @@ -500,7 +500,7 @@ export const MultiselectComboboxOptionGroups = (): React.ReactNode => { initialIsOpen optionTemplate={(item: GroupedItem) =>
    {item.label}
    } groupLabelTemplate={(groupName: string) => { - if (groupName === 'Components') { + if (groupName === "Components") { return ( @@ -516,7 +516,7 @@ export const MultiselectComboboxOptionGroups = (): React.ReactNode => { ); }; -MultiselectComboboxOptionGroups.storyName = 'with groups'; +MultiselectComboboxOptionGroups.storyName = "with groups"; const SampleEmptyState: React.FC = () => ( <> @@ -528,7 +528,7 @@ const SampleEmptyState: React.FC = () => ( ); export const MultiselectComboboxEmptyState = (): React.ReactNode => { - const [inputValue, setInputValue] = React.useState('test123'); + const [inputValue, setInputValue] = React.useState("test123"); const filteredItems = React.useMemo(() => getFilteredGroupedItems(inputValue), [inputValue]); return ( @@ -537,8 +537,8 @@ export const MultiselectComboboxEmptyState = (): React.ReactNode => { items={filteredItems} emptyState={SampleEmptyState} inputValue={inputValue} - itemToString={(item: GroupedItem) => (item ? item.label : '')} - onInputValueChange={({inputValue: newInputValue = ''}) => { + itemToString={(item: GroupedItem) => (item ? item.label : "")} + onInputValueChange={({ inputValue: newInputValue = "" }) => { setInputValue(newInputValue); }} onSelectedItemsChange={(selectedItems) => { @@ -553,7 +553,7 @@ export const MultiselectComboboxEmptyState = (): React.ReactNode => { return
    {item.label}
    ; }} groupLabelTemplate={(groupName: string) => { - if (groupName === 'Components') { + if (groupName === "Components") { return ( @@ -569,10 +569,10 @@ export const MultiselectComboboxEmptyState = (): React.ReactNode => { ); }; -MultiselectComboboxEmptyState.storyName = 'with empty state'; +MultiselectComboboxEmptyState.storyName = "with empty state"; export const MultiselectComboboxStateHook = (): React.ReactNode => { - const [inputValue, setInputValue] = React.useState(''); + const [inputValue, setInputValue] = React.useState(""); const filteredItems = React.useMemo(() => getFilteredGroupedItems(inputValue), [inputValue]); const onSelectedItemsChange = React.useCallback((selectedItems) => { @@ -596,8 +596,8 @@ export const MultiselectComboboxStateHook = (): React.ReactNode => { items={filteredItems} emptyState={SampleEmptyState} inputValue={inputValue} - itemToString={(item: GroupedItem) => (item ? item.label : '')} - onInputValueChange={({inputValue: newInputValue = ''}) => { + itemToString={(item: GroupedItem) => (item ? item.label : "")} + onInputValueChange={({ inputValue: newInputValue = "" }) => { setInputValue(newInputValue); }} onSelectedItemsChange={onSelectedItemsChange} @@ -609,7 +609,7 @@ export const MultiselectComboboxStateHook = (): React.ReactNode => { return
    {item.label}
    ; }} groupLabelTemplate={(groupName: string) => { - if (groupName === 'Components') { + if (groupName === "Components") { return ( @@ -626,13 +626,13 @@ export const MultiselectComboboxStateHook = (): React.ReactNode => { ); }; -MultiselectComboboxStateHook.storyName = 'with state hook'; +MultiselectComboboxStateHook.storyName = "with state hook"; export const MultiselectComboboxInModal: StoryFn = () => { const [modalIsOpen, setModalIsOpen] = React.useState(true); const handleOpen = (): void => setModalIsOpen(true); const handleClose = (): void => setModalIsOpen(false); - const [inputValue, setInputValue] = React.useState(''); + const [inputValue, setInputValue] = React.useState(""); const filteredItems = React.useMemo(() => getFilteredItems(inputValue), [inputValue]); const modalHeadingId = useUID(); @@ -653,7 +653,7 @@ export const MultiselectComboboxInModal: StoryFn = () => { selectedItemsLabelText="Selected Paste components" helpText="Paste components are the building blocks of your product UI." items={filteredItems} - onInputValueChange={({inputValue: newInputValue = ''}) => { + onInputValueChange={({ inputValue: newInputValue = "" }) => { setInputValue(newInputValue); }} onSelectedItemsChange={(selectedItems) => { @@ -677,7 +677,7 @@ MultiselectComboboxInModal.parameters = { // eslint-disable-next-line import/no-default-export export default { - title: 'Components/Combobox/MultiselectCombobox', + title: "Components/Combobox/MultiselectCombobox", // wraps each story in a div that has a fixed height. This makes it so chromatic takes a large enough screenshot to see the listbox. decorators: [ (Story: StoryFn, context: StoryContext): React.ReactNode => ( diff --git a/packages/paste-core/components/data-grid/__tests__/cell-management.spec.ts b/packages/paste-core/components/data-grid/__tests__/cell-management.spec.ts index 864f22c0dc..ed2e54680e 100644 --- a/packages/paste-core/components/data-grid/__tests__/cell-management.spec.ts +++ b/packages/paste-core/components/data-grid/__tests__/cell-management.spec.ts @@ -1,15 +1,15 @@ import { - isCell, + delayedSetFocusable, getClosestCellFrom, + isCell, updateTabIndexForActionable, - delayedSetFocusable, -} from '../src/utils/cell-management'; +} from "../src/utils/cell-management"; -describe('cell-management utils', () => { - it('update tabIndex for actionable correctly', () => { - const td = document.createElement('td'); - const input = document.createElement('input'); - const select = document.createElement('select'); +describe("cell-management utils", () => { + it("update tabIndex for actionable correctly", () => { + const td = document.createElement("td"); + const input = document.createElement("input"); + const select = document.createElement("select"); td.append(input); td.append(select); @@ -29,8 +29,8 @@ describe('cell-management utils', () => { expect(select.tabIndex).toBe(-1); }); - it('delayedSetFocus fires after a delay', () => { - const input = document.createElement('input'); + it("delayedSetFocus fires after a delay", () => { + const input = document.createElement("input"); input.tabIndex = -1; expect(input.tabIndex).toBe(-1); @@ -44,11 +44,11 @@ describe('cell-management utils', () => { expect(input.tabIndex).toBe(0); }); - it('isCell correctly detects DataGrid cells', () => { - const td = document.createElement('td'); - const th = document.createElement('th'); - const div = document.createElement('div'); - const input = document.createElement('input'); + it("isCell correctly detects DataGrid cells", () => { + const td = document.createElement("td"); + const th = document.createElement("th"); + const div = document.createElement("div"); + const input = document.createElement("input"); expect(isCell(td)).toBe(true); expect(isCell(th)).toBe(true); @@ -56,14 +56,14 @@ describe('cell-management utils', () => { expect(isCell(input)).toBe(false); }); - it('getClosestCellFrom fetches the closest parent DataGrid cell from an element correctly', () => { - const gridId = 'data-grid'; - const grid = document.createElement('div'); + it("getClosestCellFrom fetches the closest parent DataGrid cell from an element correctly", () => { + const gridId = "data-grid"; + const grid = document.createElement("div"); grid.id = gridId; - const td = document.createElement('td'); - const input = document.createElement('input'); - const select = document.createElement('select'); - const randomInput = document.createElement('input'); + const td = document.createElement("td"); + const input = document.createElement("input"); + const select = document.createElement("select"); + const randomInput = document.createElement("input"); td.append(input); td.append(select); diff --git a/packages/paste-core/components/data-grid/__tests__/customization.spec.tsx b/packages/paste-core/components/data-grid/__tests__/customization.spec.tsx index f82ad618a4..cddd0a6a4b 100644 --- a/packages/paste-core/components/data-grid/__tests__/customization.spec.tsx +++ b/packages/paste-core/components/data-grid/__tests__/customization.spec.tsx @@ -1,83 +1,83 @@ -import * as React from 'react'; -import {CustomizationProvider} from '@twilio-paste/customization'; -import {render} from '@testing-library/react'; +import { render } from "@testing-library/react"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import * as React from "react"; -import {PlainDataGrid} from '../stories/components/PlainDataGrid'; -import {customElementStyles} from '../stories/components/CustomizableDataGrid'; +import { customElementStyles } from "../stories/components/CustomizableDataGrid"; +import { PlainDataGrid } from "../stories/components/PlainDataGrid"; -describe('Data Grid Customization', () => { - it('can be customized generically', () => { - const {getByTestId} = render( +describe("Data Grid Customization", () => { + it("can be customized generically", () => { + const { getByTestId } = render( - + , ); - const datagrid = getByTestId('data-grid'); - const datagridHead = getByTestId('data-grid-head'); - const datagridHeader = getByTestId('data-grid-header'); - const datagridBody = getByTestId('data-grid-body'); - const datagridFoot = getByTestId('data-grid-foot'); - const datagridRow = getByTestId('data-grid-row'); - const datagridCell = getByTestId('data-grid-cell'); + const datagrid = getByTestId("data-grid"); + const datagridHead = getByTestId("data-grid-head"); + const datagridHeader = getByTestId("data-grid-header"); + const datagridBody = getByTestId("data-grid-body"); + const datagridFoot = getByTestId("data-grid-foot"); + const datagridRow = getByTestId("data-grid-row"); + const datagridCell = getByTestId("data-grid-cell"); // data-element atttributes - expect(datagrid.getAttribute('data-paste-element')).toBe('DATA_GRID'); - expect(datagridHead.getAttribute('data-paste-element')).toBe('DATA_GRID_HEAD'); - expect(datagridHeader.getAttribute('data-paste-element')).toBe('DATA_GRID_HEADER'); - expect(datagridBody.getAttribute('data-paste-element')).toBe('DATA_GRID_BODY'); - expect(datagridFoot.getAttribute('data-paste-element')).toBe('DATA_GRID_FOOT'); - expect(datagridRow.getAttribute('data-paste-element')).toBe('DATA_GRID_ROW'); - expect(datagridCell.getAttribute('data-paste-element')).toBe('DATA_GRID_CELL'); + expect(datagrid.getAttribute("data-paste-element")).toBe("DATA_GRID"); + expect(datagridHead.getAttribute("data-paste-element")).toBe("DATA_GRID_HEAD"); + expect(datagridHeader.getAttribute("data-paste-element")).toBe("DATA_GRID_HEADER"); + expect(datagridBody.getAttribute("data-paste-element")).toBe("DATA_GRID_BODY"); + expect(datagridFoot.getAttribute("data-paste-element")).toBe("DATA_GRID_FOOT"); + expect(datagridRow.getAttribute("data-paste-element")).toBe("DATA_GRID_ROW"); + expect(datagridCell.getAttribute("data-paste-element")).toBe("DATA_GRID_CELL"); // Style overrides - expect(datagridRow).toHaveStyleRule('border-color', 'rgb(96, 107, 133)'); - expect(datagrid).toHaveStyleRule('border-color', 'rgb(96, 107, 133)'); - expect(datagrid).toHaveStyleRule('font-size', '0.75rem'); - expect(datagridHead).toHaveStyleRule('font-weight', '600'); - expect(datagridHead).toHaveStyleRule('background-color', 'rgb(225, 227, 234)'); - expect(datagridHead).toHaveStyleRule('border-color', 'rgb(96, 107, 133)'); - expect(datagridFoot).toHaveStyleRule('font-weight', '600'); - expect(datagridFoot).toHaveStyleRule('background-color', 'rgb(225, 227, 234)'); - expect(datagridFoot).toHaveStyleRule('border-color', 'rgb(96, 107, 133)'); - expect(datagridHeader).toHaveStyleRule('padding', '0.125rem'); - expect(datagridCell).toHaveStyleRule('padding', '0.125rem'); + expect(datagridRow).toHaveStyleRule("border-color", "rgb(96, 107, 133)"); + expect(datagrid).toHaveStyleRule("border-color", "rgb(96, 107, 133)"); + expect(datagrid).toHaveStyleRule("font-size", "0.75rem"); + expect(datagridHead).toHaveStyleRule("font-weight", "600"); + expect(datagridHead).toHaveStyleRule("background-color", "rgb(225, 227, 234)"); + expect(datagridHead).toHaveStyleRule("border-color", "rgb(96, 107, 133)"); + expect(datagridFoot).toHaveStyleRule("font-weight", "600"); + expect(datagridFoot).toHaveStyleRule("background-color", "rgb(225, 227, 234)"); + expect(datagridFoot).toHaveStyleRule("border-color", "rgb(96, 107, 133)"); + expect(datagridHeader).toHaveStyleRule("padding", "0.125rem"); + expect(datagridCell).toHaveStyleRule("padding", "0.125rem"); }); - it('can be customized uniquely', () => { - const {getByTestId} = render( - + it("can be customized uniquely", () => { + const { getByTestId } = render( + - + , ); - const datagrid = getByTestId('data-grid'); - const datagridHead = getByTestId('data-grid-head'); - const datagridHeader = getByTestId('data-grid-header'); - const datagridBody = getByTestId('data-grid-body'); - const datagridFoot = getByTestId('data-grid-foot'); - const datagridRow = getByTestId('data-grid-row'); - const datagridCell = getByTestId('data-grid-cell'); + const datagrid = getByTestId("data-grid"); + const datagridHead = getByTestId("data-grid-head"); + const datagridHeader = getByTestId("data-grid-header"); + const datagridBody = getByTestId("data-grid-body"); + const datagridFoot = getByTestId("data-grid-foot"); + const datagridRow = getByTestId("data-grid-row"); + const datagridCell = getByTestId("data-grid-cell"); // data-element atttributes - expect(datagrid.getAttribute('data-paste-element')).toBe('FOO'); - expect(datagridHead.getAttribute('data-paste-element')).toBe('FOO_HEAD'); - expect(datagridHeader.getAttribute('data-paste-element')).toBe('FOO_HEADER'); - expect(datagridBody.getAttribute('data-paste-element')).toBe('FOO_BODY'); - expect(datagridFoot.getAttribute('data-paste-element')).toBe('FOO_FOOT'); - expect(datagridRow.getAttribute('data-paste-element')).toBe('FOO_ROW'); - expect(datagridCell.getAttribute('data-paste-element')).toBe('FOO_CELL'); + expect(datagrid.getAttribute("data-paste-element")).toBe("FOO"); + expect(datagridHead.getAttribute("data-paste-element")).toBe("FOO_HEAD"); + expect(datagridHeader.getAttribute("data-paste-element")).toBe("FOO_HEADER"); + expect(datagridBody.getAttribute("data-paste-element")).toBe("FOO_BODY"); + expect(datagridFoot.getAttribute("data-paste-element")).toBe("FOO_FOOT"); + expect(datagridRow.getAttribute("data-paste-element")).toBe("FOO_ROW"); + expect(datagridCell.getAttribute("data-paste-element")).toBe("FOO_CELL"); // Style overrides - expect(datagridRow).toHaveStyleRule('border-color', 'rgb(96, 107, 133)'); - expect(datagrid).toHaveStyleRule('border-color', 'rgb(96, 107, 133)'); - expect(datagrid).toHaveStyleRule('font-size', '0.75rem'); - expect(datagridHead).toHaveStyleRule('font-weight', '600'); - expect(datagridHead).toHaveStyleRule('background-color', 'rgb(225, 227, 234)'); - expect(datagridHead).toHaveStyleRule('border-color', 'rgb(96, 107, 133)'); - expect(datagridFoot).toHaveStyleRule('font-weight', '600'); - expect(datagridFoot).toHaveStyleRule('background-color', 'rgb(225, 227, 234)'); - expect(datagridFoot).toHaveStyleRule('border-color', 'rgb(96, 107, 133)'); - expect(datagridHeader).toHaveStyleRule('padding', '0.125rem'); - expect(datagridCell).toHaveStyleRule('padding', '0.125rem'); + expect(datagridRow).toHaveStyleRule("border-color", "rgb(96, 107, 133)"); + expect(datagrid).toHaveStyleRule("border-color", "rgb(96, 107, 133)"); + expect(datagrid).toHaveStyleRule("font-size", "0.75rem"); + expect(datagridHead).toHaveStyleRule("font-weight", "600"); + expect(datagridHead).toHaveStyleRule("background-color", "rgb(225, 227, 234)"); + expect(datagridHead).toHaveStyleRule("border-color", "rgb(96, 107, 133)"); + expect(datagridFoot).toHaveStyleRule("font-weight", "600"); + expect(datagridFoot).toHaveStyleRule("background-color", "rgb(225, 227, 234)"); + expect(datagridFoot).toHaveStyleRule("border-color", "rgb(96, 107, 133)"); + expect(datagridHeader).toHaveStyleRule("padding", "0.125rem"); + expect(datagridCell).toHaveStyleRule("padding", "0.125rem"); }); }); diff --git a/packages/paste-core/components/data-grid/__tests__/index.spec.tsx b/packages/paste-core/components/data-grid/__tests__/index.spec.tsx index 97d48c9cc9..32fc830296 100644 --- a/packages/paste-core/components/data-grid/__tests__/index.spec.tsx +++ b/packages/paste-core/components/data-grid/__tests__/index.spec.tsx @@ -1,127 +1,127 @@ -import * as React from 'react'; -import {Button} from '@twilio-paste/button'; -import {act, render, screen} from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; +import { act, render, screen } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { Button } from "@twilio-paste/button"; +import * as React from "react"; -import {DataGridCell, DataGridHeaderSort, DataGridHeader} from '../src'; +import { DataGridCell, DataGridHeader, DataGridHeaderSort } from "../src"; import { ColumnSpanDataGrid, ComposableCellsDataGrid, - SortableColumnsDataGrid, PaginatedDataGrid, PlainDataGrid, -} from '../stories/index.stories'; + SortableColumnsDataGrid, +} from "../stories/index.stories"; const checkTagName = (el: Element, name: string): void => expect(el.tagName).toBe(name.toUpperCase()); -describe('Data Grid', () => { - describe('Semantics', () => { +describe("Data Grid", () => { + describe("Semantics", () => { // eslint-disable-next-line jest/expect-expect - it('uses table elements in the DOM', () => { - const {getByTestId} = render(); - const dataGrid = getByTestId('data-grid'); - checkTagName(dataGrid, 'table'); + it("uses table elements in the DOM", () => { + const { getByTestId } = render(); + const dataGrid = getByTestId("data-grid"); + checkTagName(dataGrid, "table"); const thead = dataGrid.children[0]; const theadTr = thead.children[0]; const theadTrTh = theadTr.children[0]; - checkTagName(thead, 'thead'); - checkTagName(theadTr, 'tr'); - checkTagName(theadTrTh, 'th'); + checkTagName(thead, "thead"); + checkTagName(theadTr, "tr"); + checkTagName(theadTrTh, "th"); const tbody = dataGrid.children[1]; const tbodyTr = tbody.children[0]; const tbodyTrTd = tbodyTr.children[0]; - checkTagName(tbody, 'tbody'); - checkTagName(tbodyTr, 'tr'); - checkTagName(tbodyTrTd, 'td'); + checkTagName(tbody, "tbody"); + checkTagName(tbodyTr, "tr"); + checkTagName(tbodyTrTd, "td"); }); - it('has the correct aria label and role', () => { - const {getByTestId} = render(); - const dataGrid = getByTestId('data-grid'); - expect(dataGrid.getAttribute('aria-label')).toBeDefined(); - expect(dataGrid.getAttribute('role')).toBe('grid'); + it("has the correct aria label and role", () => { + const { getByTestId } = render(); + const dataGrid = getByTestId("data-grid"); + expect(dataGrid.getAttribute("aria-label")).toBeDefined(); + expect(dataGrid.getAttribute("role")).toBe("grid"); }); }); - describe('Column Span', () => { - it('applies colSpan attribute as expected', () => { - const {getByTestId} = render(); - const th = getByTestId('data-grid-header'); - expect(th).toHaveAttribute('colspan', '5'); + describe("Column Span", () => { + it("applies colSpan attribute as expected", () => { + const { getByTestId } = render(); + const th = getByTestId("data-grid-header"); + expect(th).toHaveAttribute("colspan", "5"); }); }); - describe('Composable Cells functionality', () => { - it('has proper keyboard navigation behavior', () => { - const {getByTestId} = render(); - const headerCell = getByTestId('header-1'); - const firstRowFirstInputCell = getByTestId('input-0-0'); + describe("Composable Cells functionality", () => { + it("has proper keyboard navigation behavior", () => { + const { getByTestId } = render(); + const headerCell = getByTestId("header-1"); + const firstRowFirstInputCell = getByTestId("input-0-0"); const firstInputCell = firstRowFirstInputCell?.parentElement?.parentElement; if (firstInputCell == null) { - throw new Error('cannot find firstInputCell'); + throw new Error("cannot find firstInputCell"); } act(() => { headerCell.focus(); }); - userEvent.keyboard('{arrowright}'); - expect(document.activeElement?.innerHTML).toBe('Last Name'); + userEvent.keyboard("{arrowright}"); + expect(document.activeElement?.innerHTML).toBe("Last Name"); - userEvent.keyboard('{arrowleft}'); + userEvent.keyboard("{arrowleft}"); expect(headerCell).toHaveFocus(); - userEvent.keyboard('{arrowdown}'); - expect(headerCell.getAttribute('tabindex')).toBe('-1'); + userEvent.keyboard("{arrowdown}"); + expect(headerCell.getAttribute("tabindex")).toBe("-1"); expect(firstInputCell).toHaveFocus(); - expect(firstInputCell.getAttribute('tabindex')).toBe('0'); + expect(firstInputCell.getAttribute("tabindex")).toBe("0"); - userEvent.keyboard('{arrowup}'); - expect(firstInputCell.getAttribute('tabindex')).toBe('-1'); - expect(headerCell.getAttribute('tabindex')).toBe('0'); + userEvent.keyboard("{arrowup}"); + expect(firstInputCell.getAttribute("tabindex")).toBe("-1"); + expect(headerCell.getAttribute("tabindex")).toBe("0"); expect(headerCell).toHaveFocus(); }); - it('toggles actionable mode with [enter] and [escape] keys', () => { - const {getByTestId} = render(); - const wrapper = getByTestId('data-grid'); - const headerCell = getByTestId('header-1'); - const firstRowFirstInputCell = getByTestId('input-0-0'); + it("toggles actionable mode with [enter] and [escape] keys", () => { + const { getByTestId } = render(); + const wrapper = getByTestId("data-grid"); + const headerCell = getByTestId("header-1"); + const firstRowFirstInputCell = getByTestId("input-0-0"); const firstInputCell = firstRowFirstInputCell?.parentElement?.parentElement; if (firstInputCell == null) { - throw new Error('cannot find firstInputCell'); + throw new Error("cannot find firstInputCell"); } act(() => { headerCell.focus(); }); - expect(wrapper.getAttribute('data-actionable')).toBe('false'); - userEvent.keyboard('{enter}'); - expect(wrapper.getAttribute('data-actionable')).toBe('true'); - userEvent.keyboard('{esc}'); - expect(wrapper.getAttribute('data-actionable')).toBe('false'); + expect(wrapper.getAttribute("data-actionable")).toBe("false"); + userEvent.keyboard("{enter}"); + expect(wrapper.getAttribute("data-actionable")).toBe("true"); + userEvent.keyboard("{esc}"); + expect(wrapper.getAttribute("data-actionable")).toBe("false"); // TEST: should enable Actionable mode when clicking into the DataGrid - expect(wrapper.getAttribute('data-actionable')).toBe('false'); + expect(wrapper.getAttribute("data-actionable")).toBe("false"); userEvent.click(headerCell); - expect(wrapper.getAttribute('data-actionable')).toBe('true'); + expect(wrapper.getAttribute("data-actionable")).toBe("true"); }); - it('should correctly tab through focusable elements in actionable mode', () => { - const {getByTestId} = render(); - const headerCell = getByTestId('header-1'); - const firstRowFirstInputCell = getByTestId('input-0-0'); - const firstRowSecondInputCell = getByTestId('input-0-1'); - const secondRowFirstInputCell = getByTestId('input-1-0'); + it("should correctly tab through focusable elements in actionable mode", () => { + const { getByTestId } = render(); + const headerCell = getByTestId("header-1"); + const firstRowFirstInputCell = getByTestId("input-0-0"); + const firstRowSecondInputCell = getByTestId("input-0-1"); + const secondRowFirstInputCell = getByTestId("input-1-0"); const firstInputCell = firstRowFirstInputCell?.parentElement?.parentElement; if (firstInputCell == null) { - throw new Error('cannot find firstInputCell'); + throw new Error("cannot find firstInputCell"); } act(() => { @@ -129,9 +129,9 @@ describe('Data Grid', () => { }); // Down to input cell - userEvent.keyboard('{arrowdown}'); + userEvent.keyboard("{arrowdown}"); // Swap to actionable - userEvent.keyboard('{enter}'); + userEvent.keyboard("{enter}"); expect(firstRowFirstInputCell).toHaveFocus(); userEvent.tab(); @@ -148,16 +148,16 @@ describe('Data Grid', () => { act(() => { headerCell.focus(); }); - userEvent.keyboard('{enter}'); - userEvent.keyboard('{arrowdown}'); + userEvent.keyboard("{enter}"); + userEvent.keyboard("{arrowdown}"); expect(firstInputCell).toHaveFocus(); - userEvent.keyboard('{enter}'); + userEvent.keyboard("{enter}"); userEvent.tab(); expect(firstRowSecondInputCell).toHaveFocus(); }); - it('has one tab stop in navigational mode and remembers the last focus', async () => { - const {getByTestId} = render( + it("has one tab stop in navigational mode and remembers the last focus", async () => { + const { getByTestId } = render(
    -
    +
    , ); - const beforeDataGridButton = getByTestId('before'); - const headerCell = getByTestId('header-1'); - const firstInputCell = getByTestId('input-0-0')?.parentElement?.parentElement; - const afterDataGridButton = getByTestId('after'); + const beforeDataGridButton = getByTestId("before"); + const headerCell = getByTestId("header-1"); + const firstInputCell = getByTestId("input-0-0")?.parentElement?.parentElement; + const afterDataGridButton = getByTestId("after"); if (firstInputCell == null) { - throw new Error('cannot find firstInputCell'); + throw new Error("cannot find firstInputCell"); } // Focus the button before the DataGrid @@ -184,50 +184,50 @@ describe('Data Grid', () => { // Tab into the DataGrid userEvent.tab(); expect(headerCell).toHaveFocus(); - expect(headerCell.getAttribute('tabIndex')).toBe('0'); + expect(headerCell.getAttribute("tabIndex")).toBe("0"); // Down - userEvent.keyboard('{arrowdown}'); - expect(headerCell.getAttribute('tabindex')).toBe('-1'); + userEvent.keyboard("{arrowdown}"); + expect(headerCell.getAttribute("tabindex")).toBe("-1"); expect(firstInputCell).toHaveFocus(); - expect(firstInputCell.getAttribute('tabindex')).toBe('0'); + expect(firstInputCell.getAttribute("tabindex")).toBe("0"); // Tab out of the DataGrid userEvent.tab(); expect(afterDataGridButton).toHaveFocus(); // Return into the DataGrid - userEvent.tab({shift: true}); + userEvent.tab({ shift: true }); expect(firstInputCell).toHaveFocus(); - expect(firstInputCell.getAttribute('tabindex')).toBe('0'); + expect(firstInputCell.getAttribute("tabindex")).toBe("0"); }); - it('should change the focus correctly when swapping to and from actionable mode', async () => { - const {getByTestId} = render(); - const headerCell = getByTestId('header-1'); - const firstRowFirstInputCell = getByTestId('input-0-0'); + it("should change the focus correctly when swapping to and from actionable mode", async () => { + const { getByTestId } = render(); + const headerCell = getByTestId("header-1"); + const firstRowFirstInputCell = getByTestId("input-0-0"); // Focus doesnt change when no focusable children act(() => { headerCell.focus(); }); - userEvent.keyboard('{enter}'); + userEvent.keyboard("{enter}"); expect(headerCell).toHaveFocus(); // Down to input firstChild - userEvent.keyboard('{esc}'); - userEvent.keyboard('{arrowdown}'); - userEvent.keyboard('{enter}'); + userEvent.keyboard("{esc}"); + userEvent.keyboard("{arrowdown}"); + userEvent.keyboard("{enter}"); expect(firstRowFirstInputCell).toHaveFocus(); // Up back to cell - userEvent.keyboard('{esc}'); + userEvent.keyboard("{esc}"); expect(firstRowFirstInputCell?.parentElement?.parentElement).toHaveFocus(); }); }); - describe('Paginated data grid', () => { - it('returns the first focused cell to the first cell in the datatable after pagination', async () => { - const {getByTestId} = render(); - const firstThCell = getByTestId('first-cell'); - const firstTdCell = getByTestId('cell-0-0'); + describe("Paginated data grid", () => { + it("returns the first focused cell to the first cell in the datatable after pagination", async () => { + const { getByTestId } = render(); + const firstThCell = getByTestId("first-cell"); + const firstTdCell = getByTestId("cell-0-0"); // I added this particular sequence because it was a reproducable bug in my manual tests act(() => { @@ -235,78 +235,78 @@ describe('Data Grid', () => { }); expect(firstThCell).toHaveFocus(); - userEvent.keyboard('{arrowdown}'); + userEvent.keyboard("{arrowdown}"); expect(firstTdCell).toHaveFocus(); // Swap to page 2 userEvent.tab(); userEvent.tab(); userEvent.tab(); - userEvent.keyboard('{enter}'); + userEvent.keyboard("{enter}"); // Bring the focus back to the DataGrid - userEvent.tab({shift: true}); - userEvent.tab({shift: true}); - userEvent.tab({shift: true}); // 3rd one because left arrow appears + userEvent.tab({ shift: true }); + userEvent.tab({ shift: true }); + userEvent.tab({ shift: true }); // 3rd one because left arrow appears // The first cell is focused, rather than the last cell we were on expect(firstThCell).toHaveFocus(); }); }); - describe('Sorting', () => { - it('should correctly set aria-sort on TH when sorting is enabled', () => { - const {getByTestId} = render(); - const header = getByTestId('header'); - const headerSort = getByTestId('header-sort'); + describe("Sorting", () => { + it("should correctly set aria-sort on TH when sorting is enabled", () => { + const { getByTestId } = render(); + const header = getByTestId("header"); + const headerSort = getByTestId("header-sort"); - expect(header.getAttribute('aria-sort')).toBe('ascending'); + expect(header.getAttribute("aria-sort")).toBe("ascending"); act(() => { headerSort.click(); }); - expect(header.getAttribute('aria-sort')).toBe('descending'); + expect(header.getAttribute("aria-sort")).toBe("descending"); act(() => { headerSort.click(); }); - expect(header.getAttribute('aria-sort')).toBe('ascending'); + expect(header.getAttribute("aria-sort")).toBe("ascending"); }); }); }); -describe('i18n', () => { - describe('DataGridHeaderSort', () => { - it('should have default ascending label', () => { +describe("i18n", () => { + describe("DataGridHeaderSort", () => { + it("should have default ascending label", () => { render(); - const button = screen.getByRole('button', {name: 'Sort ascending'}); + const button = screen.getByRole("button", { name: "Sort ascending" }); expect(button).toBeDefined(); }); - it('should have default descending label', () => { + it("should have default descending label", () => { render(); - const button = screen.getByRole('button', {name: 'Sort descending'}); + const button = screen.getByRole("button", { name: "Sort descending" }); expect(button).toBeDefined(); }); - it('should have default unsorted label', () => { + it("should have default unsorted label", () => { render(); - const button = screen.getByRole('button', {name: 'Unsorted'}); + const button = screen.getByRole("button", { name: "Unsorted" }); expect(button).toBeDefined(); }); - it('should use i18nAscendingLabel for the ascending label', () => { + it("should use i18nAscendingLabel for the ascending label", () => { render(); - const button = screen.getByRole('button', {name: 'Tri croissant'}); + const button = screen.getByRole("button", { name: "Tri croissant" }); expect(button).toBeDefined(); }); - it('should use i18nDescendingLabel for the descending label', () => { + it("should use i18nDescendingLabel for the descending label", () => { render(); - const button = screen.getByRole('button', {name: 'Tri décroissant'}); + const button = screen.getByRole("button", { name: "Tri décroissant" }); expect(button).toBeDefined(); }); - it('should use i18nUnsortedLabel for the unsorted label', () => { + it("should use i18nUnsortedLabel for the unsorted label", () => { render(); - const button = screen.getByRole('button', {name: 'Non triés'}); + const button = screen.getByRole("button", { name: "Non triés" }); expect(button).toBeDefined(); }); }); diff --git a/packages/paste-core/components/data-grid/__tests__/reakit-hasFocus.spec.tsx b/packages/paste-core/components/data-grid/__tests__/reakit-hasFocus.spec.tsx index 0c4b49c290..587b74cec3 100644 --- a/packages/paste-core/components/data-grid/__tests__/reakit-hasFocus.spec.tsx +++ b/packages/paste-core/components/data-grid/__tests__/reakit-hasFocus.spec.tsx @@ -1,11 +1,11 @@ +import { render, screen } from "@testing-library/react"; /* * Copied from Reakit and modified to work in Paste * https://github.com/reakit/reakit/blob/a211d94da9f3b683182568a56479b91afb1b85ae/packages/reakit-utils/src/__tests__/hasFocus-test.tsx */ -import * as React from 'react'; -import {render, screen} from '@testing-library/react'; +import * as React from "react"; -import {hasFocus} from '../src/utils/reakit/reakit-hasFocus'; +import { hasFocus } from "../src/utils/reakit/reakit-hasFocus"; const TestComponent = (): JSX.Element => { return ( @@ -22,26 +22,26 @@ const TestComponent = (): JSX.Element => { ); }; -test('hasFocus', () => { +test("hasFocus", () => { render(); - const item1 = screen.getByLabelText('item1'); + const item1 = screen.getByLabelText("item1"); expect(hasFocus(item1)).toBe(false); item1.focus(); - expect(hasFocus(screen.getByLabelText('item1'))).toBe(false); - expect(hasFocus(screen.getByLabelText('item1-1'))).toBe(false); + expect(hasFocus(screen.getByLabelText("item1"))).toBe(false); + expect(hasFocus(screen.getByLabelText("item1-1"))).toBe(false); - const item11 = screen.getByLabelText('item1-1'); + const item11 = screen.getByLabelText("item1-1"); item11.focus(); - expect(hasFocus(screen.getByLabelText('item1-1'))).toBe(true); + expect(hasFocus(screen.getByLabelText("item1-1"))).toBe(true); - const item2 = screen.getByLabelText('item2'); + const item2 = screen.getByLabelText("item2"); item2.focus(); - expect(hasFocus(screen.getByLabelText('item2'))).toBe(true); - expect(hasFocus(screen.getByLabelText('item3-1'))).toBe(false); + expect(hasFocus(screen.getByLabelText("item2"))).toBe(true); + expect(hasFocus(screen.getByLabelText("item3-1"))).toBe(false); - const item3 = screen.getByLabelText('item3'); + const item3 = screen.getByLabelText("item3"); item3.focus(); - expect(hasFocus(screen.getByLabelText('item3'))).toBe(true); - expect(hasFocus(screen.getByLabelText('item3-1'))).toBe(true); + expect(hasFocus(screen.getByLabelText("item3"))).toBe(true); + expect(hasFocus(screen.getByLabelText("item3-1"))).toBe(true); }); diff --git a/packages/paste-core/components/data-grid/build.js b/packages/paste-core/components/data-grid/build.js index a4edeab49b..27dd98f98e 100644 --- a/packages/paste-core/components/data-grid/build.js +++ b/packages/paste-core/components/data-grid/build.js @@ -1,3 +1,3 @@ -const {build} = require('../../../../tools/build/esbuild'); +const { build } = require("../../../../tools/build/esbuild"); -build(require('./package.json')); +build(require("./package.json")); diff --git a/packages/paste-core/components/data-grid/src/DataGrid.tsx b/packages/paste-core/components/data-grid/src/DataGrid.tsx index ba6c64fe2c..105f622c4f 100644 --- a/packages/paste-core/components/data-grid/src/DataGrid.tsx +++ b/packages/paste-core/components/data-grid/src/DataGrid.tsx @@ -1,22 +1,22 @@ -import * as React from 'react'; -import {useUID} from '@twilio-paste/uid-library'; -import {useCompositeState, Composite} from '@twilio-paste/reakit-library'; -import {Table} from '@twilio-paste/table'; -import type {TableProps} from '@twilio-paste/table'; +import { Composite, useCompositeState } from "@twilio-paste/reakit-library"; +import { Table } from "@twilio-paste/table"; +import type { TableProps } from "@twilio-paste/table"; +import { useUID } from "@twilio-paste/uid-library"; +import * as React from "react"; -import {DataGridContext} from './DataGridContext'; +import { DataGridContext } from "./DataGridContext"; import { + delayedSetFocusable, ensureFocus, getActiveElement, - getFirstFocusableIn, getClosestCellFrom, getClosestGridCellFromCurrentFocus, + getFirstFocusableIn, isCell, - delayedSetFocusable, -} from './utils'; +} from "./utils"; export interface DataGridProps extends TableProps { - 'aria-label': string; + "aria-label": string; } /** @@ -27,10 +27,10 @@ export interface DataGridProps extends TableProps { * @param {string} element - customization element */ export const DataGrid = React.forwardRef( - ({element = 'DATA_GRID', striped = false, ...props}, ref) => { + ({ element = "DATA_GRID", striped = false, ...props }, ref) => { const dataGridId = `data-grid-${useUID()}`; const lastFocusedElement = React.useRef(null); - const compositeState = useCompositeState({unstable_virtual: false}); + const compositeState = useCompositeState({ unstable_virtual: false }); const [actionable, setActionable] = React.useState(false); /** @@ -73,7 +73,7 @@ export const DataGrid = React.forwardRef( } } }, - [dataGridId] + [dataGridId], ); /** @@ -86,7 +86,7 @@ export const DataGrid = React.forwardRef( * Wrapping cases in {} to avoid ESLint error * https://eslint.org/docs/rules/no-case-declarations */ - case 'Enter': { + case "Enter": { // Set the actionable state setActionable(true); @@ -105,7 +105,7 @@ export const DataGrid = React.forwardRef( } break; } - case 'Escape': { + case "Escape": { // Set the actionable state setActionable(false); // From the current focus target, find the closest parent cell @@ -122,7 +122,7 @@ export const DataGrid = React.forwardRef( break; } }, - [actionable, dataGridId] + [actionable, dataGridId], ); const dataGridState = { @@ -150,7 +150,7 @@ export const DataGrid = React.forwardRef( /> ); - } + }, ); -DataGrid.displayName = 'DataGrid'; +DataGrid.displayName = "DataGrid"; diff --git a/packages/paste-core/components/data-grid/src/DataGridBody.tsx b/packages/paste-core/components/data-grid/src/DataGridBody.tsx index 54a09fa96e..11bc544eba 100644 --- a/packages/paste-core/components/data-grid/src/DataGridBody.tsx +++ b/packages/paste-core/components/data-grid/src/DataGridBody.tsx @@ -1,6 +1,6 @@ -import * as React from 'react'; -import {TBody} from '@twilio-paste/table'; -import type {TBodyProps} from '@twilio-paste/table'; +import { TBody } from "@twilio-paste/table"; +import type { TBodyProps } from "@twilio-paste/table"; +import * as React from "react"; /** * DataGrid body wrapper component. @@ -8,8 +8,8 @@ import type {TBodyProps} from '@twilio-paste/table'; * @param {string} element - customization element */ export const DataGridBody = React.forwardRef( - ({element = 'DATA_GRID_BODY', ...props}, ref) => { + ({ element = "DATA_GRID_BODY", ...props }, ref) => { return ; - } + }, ); -DataGridBody.displayName = 'DataGridBody'; +DataGridBody.displayName = "DataGridBody"; diff --git a/packages/paste-core/components/data-grid/src/DataGridCell.tsx b/packages/paste-core/components/data-grid/src/DataGridCell.tsx index d5229762d2..41f802c19e 100644 --- a/packages/paste-core/components/data-grid/src/DataGridCell.tsx +++ b/packages/paste-core/components/data-grid/src/DataGridCell.tsx @@ -1,21 +1,21 @@ -import * as React from 'react'; -import type {BoxElementProps} from '@twilio-paste/box'; -import {CompositeItem} from '@twilio-paste/reakit-library'; -import {useMutationObservable} from '@twilio-paste/utils'; -import isElement from 'lodash/isElement'; +import type { BoxElementProps } from "@twilio-paste/box"; +import { CompositeItem } from "@twilio-paste/reakit-library"; +import { useMutationObservable } from "@twilio-paste/utils"; +import isElement from "lodash/isElement"; +import * as React from "react"; -import {DataGridContext} from './DataGridContext'; -import {updateTabIndexForActionable, isCell, ensureFocus} from './utils'; -import {Td} from './table/Td'; -import {Th} from './table/Th'; -import type {TdProps} from './table/Td'; +import { DataGridContext } from "./DataGridContext"; +import { Td } from "./table/Td"; +import type { TdProps } from "./table/Td"; +import { Th } from "./table/Th"; +import { ensureFocus, isCell, updateTabIndexForActionable } from "./utils"; // This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export -type CellType = 'th' | 'td'; -export interface DataGridCellProps extends Pick { +type CellType = "th" | "td"; +export interface DataGridCellProps extends Pick { as?: CellType; - element?: BoxElementProps['element']; + element?: BoxElementProps["element"]; colSpan?: number; } @@ -27,8 +27,8 @@ export interface DataGridCellProps extends Pick { * @param {number} [colSpan] - how many columns the cell spans across */ export const DataGridCell: React.FC> = ({ - element = 'DATA_GRID_CELL', - as = 'td', + element = "DATA_GRID_CELL", + as = "td", ...props }) => { const dataGridState = React.useContext(DataGridContext); @@ -62,7 +62,7 @@ export const DataGridCell: React.FC> * when in actionable mode */ if ( - mutation.attributeName === 'tabindex' && + mutation.attributeName === "tabindex" && dataGridState.actionable && target.tabIndex === 0 && isCell(target) @@ -71,7 +71,7 @@ export const DataGridCell: React.FC> } }); }, - [dataGridState.actionable] + [dataGridState.actionable], ); useMutationObservable(cellRef.current, onListMutation); @@ -90,10 +90,10 @@ export const DataGridCell: React.FC> {...dataGridState} element={element} ref={cellRef} - as={as === 'td' ? Td : Th} + as={as === "td" ? Td : Th} onClick={handleMouseDown} /> ); }; -DataGridCell.displayName = 'DataGridCell'; +DataGridCell.displayName = "DataGridCell"; diff --git a/packages/paste-core/components/data-grid/src/DataGridContext.tsx b/packages/paste-core/components/data-grid/src/DataGridContext.tsx index b76421b62c..f97b5d198f 100644 --- a/packages/paste-core/components/data-grid/src/DataGridContext.tsx +++ b/packages/paste-core/components/data-grid/src/DataGridContext.tsx @@ -1,5 +1,5 @@ -import * as React from 'react'; -import type {CompositeStateReturn} from '@twilio-paste/reakit-library'; +import type { CompositeStateReturn } from "@twilio-paste/reakit-library"; +import * as React from "react"; interface DataGridState extends Partial { actionable: boolean; diff --git a/packages/paste-core/components/data-grid/src/DataGridFoot.tsx b/packages/paste-core/components/data-grid/src/DataGridFoot.tsx index fd16e0fba4..d111e94d5b 100644 --- a/packages/paste-core/components/data-grid/src/DataGridFoot.tsx +++ b/packages/paste-core/components/data-grid/src/DataGridFoot.tsx @@ -1,6 +1,6 @@ -import * as React from 'react'; -import {TFoot} from '@twilio-paste/table'; -import type {TFootProps} from '@twilio-paste/table'; +import { TFoot } from "@twilio-paste/table"; +import type { TFootProps } from "@twilio-paste/table"; +import * as React from "react"; /** * DataGrid foot wrapper component. @@ -8,9 +8,9 @@ import type {TFootProps} from '@twilio-paste/table'; * @param {string} element - customization element */ export const DataGridFoot = React.forwardRef( - ({element = 'DATA_GRID_FOOT', ...props}, ref) => { + ({ element = "DATA_GRID_FOOT", ...props }, ref) => { return ; - } + }, ); -DataGridFoot.displayName = 'DataGridFoot'; +DataGridFoot.displayName = "DataGridFoot"; diff --git a/packages/paste-core/components/data-grid/src/DataGridHead.tsx b/packages/paste-core/components/data-grid/src/DataGridHead.tsx index cb2caf3e5a..49861198ab 100644 --- a/packages/paste-core/components/data-grid/src/DataGridHead.tsx +++ b/packages/paste-core/components/data-grid/src/DataGridHead.tsx @@ -1,6 +1,6 @@ -import * as React from 'react'; -import {THead} from '@twilio-paste/table'; -import type {THeadProps} from '@twilio-paste/table'; +import { THead } from "@twilio-paste/table"; +import type { THeadProps } from "@twilio-paste/table"; +import * as React from "react"; /** * DataGrid head wrapper component. @@ -8,9 +8,9 @@ import type {THeadProps} from '@twilio-paste/table'; * @param {string} element - customization element */ export const DataGridHead = React.forwardRef( - ({element = 'DATA_GRID_HEAD', ...props}, ref) => { + ({ element = "DATA_GRID_HEAD", ...props }, ref) => { return ; - } + }, ); -DataGridHead.displayName = 'DataGridHead'; +DataGridHead.displayName = "DataGridHead"; diff --git a/packages/paste-core/components/data-grid/src/DataGridHeader.tsx b/packages/paste-core/components/data-grid/src/DataGridHeader.tsx index c85c06a8eb..e96f43ca23 100644 --- a/packages/paste-core/components/data-grid/src/DataGridHeader.tsx +++ b/packages/paste-core/components/data-grid/src/DataGridHeader.tsx @@ -1,7 +1,7 @@ -import * as React from 'react'; +import * as React from "react"; -import {DataGridCell} from './DataGridCell'; -import type {ThProps} from './table/Th'; +import { DataGridCell } from "./DataGridCell"; +import type { ThProps } from "./table/Th"; /** * DataGrid header (th) component. @@ -11,10 +11,10 @@ import type {ThProps} from './table/Th'; * @param {number} [colSpan] - how many columns the cell spans across */ export const DataGridHeader: React.FC> = ({ - element = 'DATA_GRID_HEADER', + element = "DATA_GRID_HEADER", ...props }) => { return ; }; -DataGridHeader.displayName = 'DataGridHeader'; +DataGridHeader.displayName = "DataGridHeader"; diff --git a/packages/paste-core/components/data-grid/src/DataGridHeaderSort.tsx b/packages/paste-core/components/data-grid/src/DataGridHeaderSort.tsx index cba35f0e13..b3eb5d0f46 100644 --- a/packages/paste-core/components/data-grid/src/DataGridHeaderSort.tsx +++ b/packages/paste-core/components/data-grid/src/DataGridHeaderSort.tsx @@ -1,16 +1,16 @@ -import * as React from 'react'; -import type {BoxProps} from '@twilio-paste/box'; -import {Button} from '@twilio-paste/button'; -import {ScreenReaderOnly} from '@twilio-paste/screen-reader-only'; -import {ArrowDownIcon} from '@twilio-paste/icons/esm/ArrowDownIcon'; -import {ArrowUpIcon} from '@twilio-paste/icons/esm/ArrowUpIcon'; -import {UnsortedIcon} from '@twilio-paste/icons/esm/UnsortedIcon'; +import type { BoxProps } from "@twilio-paste/box"; +import { Button } from "@twilio-paste/button"; +import { ArrowDownIcon } from "@twilio-paste/icons/esm/ArrowDownIcon"; +import { ArrowUpIcon } from "@twilio-paste/icons/esm/ArrowUpIcon"; +import { UnsortedIcon } from "@twilio-paste/icons/esm/UnsortedIcon"; +import { ScreenReaderOnly } from "@twilio-paste/screen-reader-only"; +import * as React from "react"; -export type SortDirection = 'ascending' | 'descending' | 'none'; +export type SortDirection = "ascending" | "descending" | "none"; interface DataGridHeaderSortIconProps { direction: SortDirection; - element?: BoxProps['element']; + element?: BoxProps["element"]; } const DataGridHeaderSortIcon: React.FC> = ({ @@ -18,18 +18,18 @@ const DataGridHeaderSortIcon: React.FC { switch (direction) { - case 'ascending': + case "ascending": return ; - case 'descending': + case "descending": return ; - case 'none': + case "none": return ; default: return null; } }; -DataGridHeaderSortIcon.displayName = 'DataGridHeaderSortIcon'; +DataGridHeaderSortIcon.displayName = "DataGridHeaderSortIcon"; export interface DataGridHeaderSortProps extends DataGridHeaderSortIconProps { onClick?: () => void; @@ -48,10 +48,10 @@ export interface DataGridHeaderSortProps extends DataGridHeaderSortIconProps { export const DataGridHeaderSort: React.FC> = ({ direction, onClick, - element = 'DATA_GRID_HEADER_SORT', - i18nAscendingLabel = 'Sort ascending', - i18nDescendingLabel = 'Sort descending', - i18nUnsortedLabel = 'Unsorted', + element = "DATA_GRID_HEADER_SORT", + i18nAscendingLabel = "Sort ascending", + i18nDescendingLabel = "Sort descending", + i18nUnsortedLabel = "Unsorted", ...props }) => { const i18nLabelDirectionMap = { @@ -68,4 +68,4 @@ export const DataGridHeaderSort: React.FC; selected?: boolean; - element?: BoxElementProps['element']; + element?: BoxElementProps["element"]; } /** @@ -18,11 +18,11 @@ export interface DataGridRowProps { * @param {string} element - customization element */ export const DataGridRow = React.forwardRef( - ({element = 'DATA_GRID_ROW', ...props}, ref) => { + ({ element = "DATA_GRID_ROW", ...props }, ref) => { const dataGridState = React.useContext(DataGridContext); return ; - } + }, ); -DataGridRow.displayName = 'DataGridRow'; +DataGridRow.displayName = "DataGridRow"; diff --git a/packages/paste-core/components/data-grid/src/index.tsx b/packages/paste-core/components/data-grid/src/index.tsx index 614e5aec19..56775872e8 100644 --- a/packages/paste-core/components/data-grid/src/index.tsx +++ b/packages/paste-core/components/data-grid/src/index.tsx @@ -1,8 +1,8 @@ -export * from './DataGrid'; -export * from './DataGridHead'; -export * from './DataGridRow'; -export * from './DataGridHeader'; -export * from './DataGridHeaderSort'; -export * from './DataGridBody'; -export * from './DataGridCell'; -export * from './DataGridFoot'; +export * from "./DataGrid"; +export * from "./DataGridHead"; +export * from "./DataGridRow"; +export * from "./DataGridHeader"; +export * from "./DataGridHeaderSort"; +export * from "./DataGridBody"; +export * from "./DataGridCell"; +export * from "./DataGridFoot"; diff --git a/packages/paste-core/components/data-grid/src/table/Td.tsx b/packages/paste-core/components/data-grid/src/table/Td.tsx index c181bce0e9..79143642e7 100644 --- a/packages/paste-core/components/data-grid/src/table/Td.tsx +++ b/packages/paste-core/components/data-grid/src/table/Td.tsx @@ -1,13 +1,13 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {TdProps as TableTdProps} from '@twilio-paste/table'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { TdProps as TableTdProps } from "@twilio-paste/table"; +import * as React from "react"; export interface TdProps extends TableTdProps { onClick?: React.MouseEventHandler; } export const Td = React.forwardRef( - ({textAlign = 'left', element = 'DATA_GRID_TD', ...props}, ref) => { + ({ textAlign = "left", element = "DATA_GRID_TD", ...props }, ref) => { return ( ( wordWrap="break-word" color="inherit" _first={{ - paddingLeft: 'space50', + paddingLeft: "space50", }} _last={{ - paddingRight: 'space50', + paddingRight: "space50", }} _focus={{ - outline: 'none', - boxShadow: 'shadowFocusInset', + outline: "none", + boxShadow: "shadowFocusInset", }} /> ); - } + }, ); -Td.displayName = 'Td'; +Td.displayName = "Td"; diff --git a/packages/paste-core/components/data-grid/src/table/Th.tsx b/packages/paste-core/components/data-grid/src/table/Th.tsx index a1a7ca3ab4..734a9af488 100644 --- a/packages/paste-core/components/data-grid/src/table/Th.tsx +++ b/packages/paste-core/components/data-grid/src/table/Th.tsx @@ -1,13 +1,13 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {ThProps as TableThProps} from '@twilio-paste/table'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { ThProps as TableThProps } from "@twilio-paste/table"; +import * as React from "react"; export interface ThProps extends TableThProps { onClick?: React.MouseEventHandler; } export const Th = React.forwardRef( - ({width, textAlign = 'left', element = 'DATA_GRID_TH', ...props}, ref) => { + ({ width, textAlign = "left", element = "DATA_GRID_TH", ...props }, ref) => { return ( ( verticalAlign="inherit" color="inherit" _first={{ - paddingLeft: 'space50', + paddingLeft: "space50", }} _last={{ - paddingRight: 'space50', + paddingRight: "space50", }} _focus={{ - outline: 'none', - boxShadow: 'shadowFocusInset', + outline: "none", + boxShadow: "shadowFocusInset", }} /> ); - } + }, ); -Th.displayName = 'Th'; +Th.displayName = "Th"; diff --git a/packages/paste-core/components/data-grid/src/table/Tr.tsx b/packages/paste-core/components/data-grid/src/table/Tr.tsx index 40ff0d911e..052d558172 100644 --- a/packages/paste-core/components/data-grid/src/table/Tr.tsx +++ b/packages/paste-core/components/data-grid/src/table/Tr.tsx @@ -1,7 +1,7 @@ -import * as React from 'react'; -import {styled, css} from '@twilio-paste/styling-library'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {TrProps as TableTrProps} from '@twilio-paste/table'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import { css, styled } from "@twilio-paste/styling-library"; +import type { TrProps as TableTrProps } from "@twilio-paste/table"; +import * as React from "react"; export interface TrProps extends TableTrProps { role: string; @@ -11,17 +11,17 @@ export interface TrProps extends TableTrProps { const StyledTr = styled.tr( css({ - '&[aria-selected=true] > td': { - borderColor: 'colorBorderPrimaryWeaker', + "&[aria-selected=true] > td": { + borderColor: "colorBorderPrimaryWeaker", }, - '&[aria-selected=true] > th': { - borderColor: 'colorBorderPrimaryWeaker', + "&[aria-selected=true] > th": { + borderColor: "colorBorderPrimaryWeaker", }, - }) + }), ); export const Tr = React.forwardRef( - ({element = 'DATA_GRID_TR', striped, ...props}, ref) => { + ({ element = "DATA_GRID_TR", striped, ...props }, ref) => { return ( ( // @ts-expect-error: we don't have polymorphic box typings yet as={StyledTr} aria-selected={props.selected} - _even={{backgroundColor: striped ? 'colorBackgroundRowStriped' : 'transparent'}} + _even={{ backgroundColor: striped ? "colorBackgroundRowStriped" : "transparent" }} _selected={{ - backgroundColor: 'colorBackgroundPrimaryWeakest', + backgroundColor: "colorBackgroundPrimaryWeakest", }} /> ); - } + }, ); -Tr.displayName = 'Tr'; +Tr.displayName = "Tr"; diff --git a/packages/paste-core/components/data-grid/src/utils/cell-management.ts b/packages/paste-core/components/data-grid/src/utils/cell-management.ts index 05afbaa36f..c8d896a6c2 100644 --- a/packages/paste-core/components/data-grid/src/utils/cell-management.ts +++ b/packages/paste-core/components/data-grid/src/utils/cell-management.ts @@ -1,4 +1,4 @@ -import {getActiveElement, getAllFocusableIn} from './reakit'; +import { getActiveElement, getAllFocusableIn } from "./reakit"; /** * Sets the correct tabindex for elements based on whether actionable @@ -39,7 +39,7 @@ export const delayedSetFocusable = (element?: HTMLElement): void => { * @returns {boolean}. */ export const isCell = (element: Element): boolean => { - return element.tagName === 'TD' || element.tagName === 'TH'; + return element.tagName === "TD" || element.tagName === "TH"; }; /** diff --git a/packages/paste-core/components/data-grid/src/utils/index.ts b/packages/paste-core/components/data-grid/src/utils/index.ts index e331250fca..e5d3010450 100644 --- a/packages/paste-core/components/data-grid/src/utils/index.ts +++ b/packages/paste-core/components/data-grid/src/utils/index.ts @@ -1,2 +1,2 @@ -export * from './cell-management'; -export * from './reakit'; +export * from "./cell-management"; +export * from "./reakit"; diff --git a/packages/paste-core/components/data-grid/src/utils/reakit/index.ts b/packages/paste-core/components/data-grid/src/utils/reakit/index.ts index 77a405180f..a9b4d84f84 100644 --- a/packages/paste-core/components/data-grid/src/utils/reakit/index.ts +++ b/packages/paste-core/components/data-grid/src/utils/reakit/index.ts @@ -3,6 +3,6 @@ * Search for "CHANGED:" to find modifications in files with the "-modded" suffix. * https://github.com/reakit/reakit/tree/master/packages/reakit-utils/src */ -export {getAllFocusableIn, getFirstFocusableIn} from './reakit-tabbable-modded'; -export {ensureFocus} from './reakit-ensureFocus'; -export {getActiveElement} from './reakit-getActiveElement-modded'; +export { getAllFocusableIn, getFirstFocusableIn } from "./reakit-tabbable-modded"; +export { ensureFocus } from "./reakit-ensureFocus"; +export { getActiveElement } from "./reakit-getActiveElement-modded"; diff --git a/packages/paste-core/components/data-grid/src/utils/reakit/reakit-ensureFocus.ts b/packages/paste-core/components/data-grid/src/utils/reakit/reakit-ensureFocus.ts index a8ec711874..50c67d9c65 100644 --- a/packages/paste-core/components/data-grid/src/utils/reakit/reakit-ensureFocus.ts +++ b/packages/paste-core/components/data-grid/src/utils/reakit/reakit-ensureFocus.ts @@ -1,4 +1,4 @@ -import {hasFocus} from './reakit-hasFocus'; +import { hasFocus } from "./reakit-hasFocus"; type EnsureFocusOptions = FocusOptions & { isActive?: typeof hasFocus; @@ -27,15 +27,15 @@ type EnsureFocusOptions = FocusOptions & { */ export function ensureFocus( element: HTMLElement, - {preventScroll, isActive = hasFocus}: EnsureFocusOptions = {} + { preventScroll, isActive = hasFocus }: EnsureFocusOptions = {}, ): number { if (isActive(element)) return -1; - element.focus({preventScroll}); + element.focus({ preventScroll }); if (isActive(element)) return -1; return requestAnimationFrame(() => { - element.focus({preventScroll}); + element.focus({ preventScroll }); }); } diff --git a/packages/paste-core/components/data-grid/src/utils/reakit/reakit-getActiveElement-modded.ts b/packages/paste-core/components/data-grid/src/utils/reakit/reakit-getActiveElement-modded.ts index f0fff2b662..681ba0b1f3 100644 --- a/packages/paste-core/components/data-grid/src/utils/reakit/reakit-getActiveElement-modded.ts +++ b/packages/paste-core/components/data-grid/src/utils/reakit/reakit-getActiveElement-modded.ts @@ -1,11 +1,11 @@ -import {getDocument} from './reakit-getDocument'; +import { getDocument } from "./reakit-getDocument"; /** * Returns `element.ownerDocument.activeElement`. */ // CHANGED: added return type export function getActiveElement(element?: Element | Document | null): Element | null { - const {activeElement} = getDocument(element); + const { activeElement } = getDocument(element); if (!activeElement?.nodeName) { /* * In IE11, activeElement might be an empty object if we're interacting diff --git a/packages/paste-core/components/data-grid/src/utils/reakit/reakit-hasFocus.ts b/packages/paste-core/components/data-grid/src/utils/reakit/reakit-hasFocus.ts index ae62fd1f70..f4c293c4ad 100644 --- a/packages/paste-core/components/data-grid/src/utils/reakit/reakit-hasFocus.ts +++ b/packages/paste-core/components/data-grid/src/utils/reakit/reakit-hasFocus.ts @@ -1,4 +1,4 @@ -import {getActiveElement} from './reakit-getActiveElement-modded'; +import { getActiveElement } from "./reakit-getActiveElement-modded"; /** * Checks if `element` has focus. Elements that are referenced by @@ -13,7 +13,7 @@ export function hasFocus(element: Element): boolean { const activeElement = getActiveElement(element); if (!activeElement) return false; if (activeElement === element) return true; - const activeDescendant = activeElement.getAttribute('aria-activedescendant'); + const activeDescendant = activeElement.getAttribute("aria-activedescendant"); if (!activeDescendant) return false; return activeDescendant === element.id; } diff --git a/packages/paste-core/components/data-grid/src/utils/reakit/reakit-matches.ts b/packages/paste-core/components/data-grid/src/utils/reakit/reakit-matches.ts index 387106c324..fd0fbfd9a1 100644 --- a/packages/paste-core/components/data-grid/src/utils/reakit/reakit-matches.ts +++ b/packages/paste-core/components/data-grid/src/utils/reakit/reakit-matches.ts @@ -4,10 +4,10 @@ * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/matches */ export function matches(element: Element, selectors: string): boolean { - if ('matches' in element) { + if ("matches" in element) { return element.matches(selectors); } - if ('msMatchesSelector' in element) { + if ("msMatchesSelector" in element) { /* eslint-disable @typescript-eslint/no-explicit-any */ return (element as any).msMatchesSelector(selectors); } diff --git a/packages/paste-core/components/data-grid/src/utils/reakit/reakit-tabbable-modded.ts b/packages/paste-core/components/data-grid/src/utils/reakit/reakit-tabbable-modded.ts index c54327be24..d83194b5b7 100644 --- a/packages/paste-core/components/data-grid/src/utils/reakit/reakit-tabbable-modded.ts +++ b/packages/paste-core/components/data-grid/src/utils/reakit/reakit-tabbable-modded.ts @@ -1,9 +1,9 @@ -import {matches} from './reakit-matches'; +import { matches } from "./reakit-matches"; const selector = "input:not([type='hidden']):not([disabled]), select:not([disabled]), " + - 'textarea:not([disabled]), a[href], button:not([disabled]), [tabindex], ' + - 'iframe, object, embed, area[href], audio[controls], video[controls], ' + + "textarea:not([disabled]), a[href], button:not([disabled]), [tabindex], " + + "iframe, object, embed, area[href], audio[controls], video[controls], " + "[contenteditable]:not([contenteditable='false'])"; /* diff --git a/packages/paste-core/components/data-grid/stories/components/ColumnSpanDataGrid.tsx b/packages/paste-core/components/data-grid/stories/components/ColumnSpanDataGrid.tsx index 5c71bab586..139bcf173c 100644 --- a/packages/paste-core/components/data-grid/stories/components/ColumnSpanDataGrid.tsx +++ b/packages/paste-core/components/data-grid/stories/components/ColumnSpanDataGrid.tsx @@ -1,11 +1,11 @@ -import * as React from 'react'; -import type {BoxProps} from '@twilio-paste/box'; +import type { BoxProps } from "@twilio-paste/box"; +import * as React from "react"; -import {DataGrid, DataGridHead, DataGridRow, DataGridHeader, DataGridBody, DataGridCell} from '../../src'; -import {TableBodyData} from './constants'; +import { DataGrid, DataGridBody, DataGridCell, DataGridHead, DataGridHeader, DataGridRow } from "../../src"; +import { TableBodyData } from "./constants"; -export const ColumnSpanDataGrid: React.FC> = ({ - element = 'DATA_GRID', +export const ColumnSpanDataGrid: React.FC> = ({ + element = "DATA_GRID", }) => { return ( @@ -20,15 +20,15 @@ export const ColumnSpanDataGrid: React.FC ( {row.map((col, colIndex) => ( {col} diff --git a/packages/paste-core/components/data-grid/stories/components/ComposableCellsDataGrid.tsx b/packages/paste-core/components/data-grid/stories/components/ComposableCellsDataGrid.tsx index 6d27e51b24..9b2371901e 100644 --- a/packages/paste-core/components/data-grid/stories/components/ComposableCellsDataGrid.tsx +++ b/packages/paste-core/components/data-grid/stories/components/ComposableCellsDataGrid.tsx @@ -1,12 +1,12 @@ -import * as React from 'react'; -import {Box} from '@twilio-paste/box'; -import {Input} from '@twilio-paste/input'; -import {Menu, useMenuState, MenuButton, MenuItem, MenuSeparator} from '@twilio-paste/menu'; -import {MoreIcon} from '@twilio-paste/icons/esm/MoreIcon'; -import {Select, Option} from '@twilio-paste/select'; +import { Box } from "@twilio-paste/box"; +import { MoreIcon } from "@twilio-paste/icons/esm/MoreIcon"; +import { Input } from "@twilio-paste/input"; +import { Menu, MenuButton, MenuItem, MenuSeparator, useMenuState } from "@twilio-paste/menu"; +import { Option, Select } from "@twilio-paste/select"; +import * as React from "react"; -import {DataGrid, DataGridHead, DataGridRow, DataGridHeader, DataGridBody, DataGridCell} from '../../src'; -import {TableHeaderData, TableBodyData} from './constants'; +import { DataGrid, DataGridBody, DataGridCell, DataGridHead, DataGridHeader, DataGridRow } from "../../src"; +import { TableBodyData, TableHeaderData } from "./constants"; const ActionMenu = (): JSX.Element => { const menu = useMenuState(); @@ -53,7 +53,7 @@ export const ComposableCellsDataGrid = (): JSX.Element => { {}} /> diff --git a/packages/paste-core/components/data-grid/stories/components/CustomizableDataGrid.tsx b/packages/paste-core/components/data-grid/stories/components/CustomizableDataGrid.tsx index fd3c3c9422..f3d4fc05f8 100644 --- a/packages/paste-core/components/data-grid/stories/components/CustomizableDataGrid.tsx +++ b/packages/paste-core/components/data-grid/stories/components/CustomizableDataGrid.tsx @@ -1,40 +1,40 @@ -import * as React from 'react'; -import {Heading} from '@twilio-paste/heading'; -import {Stack} from '@twilio-paste/stack'; -import {CustomizationProvider} from '@twilio-paste/customization'; -import {useTheme} from '@twilio-paste/theme'; +import { CustomizationProvider } from "@twilio-paste/customization"; +import { Heading } from "@twilio-paste/heading"; +import { Stack } from "@twilio-paste/stack"; +import { useTheme } from "@twilio-paste/theme"; +import * as React from "react"; -import {PlainDataGrid} from './PlainDataGrid'; +import { PlainDataGrid } from "./PlainDataGrid"; -export const customElementStyles = (prefix = 'DATA_GRID'): {[key: string]: any} => ({ +export const customElementStyles = (prefix = "DATA_GRID"): { [key: string]: any } => ({ [prefix]: { - fontSize: 'fontSize20', - borderColor: 'colorBorderStrong', + fontSize: "fontSize20", + borderColor: "colorBorderStrong", }, [`${prefix}_HEAD`]: { - backgroundColor: 'colorBackgroundStrong', - fontWeight: 'fontWeightSemibold', - borderColor: 'colorBorderStrong', - color: 'colorText', + backgroundColor: "colorBackgroundStrong", + fontWeight: "fontWeightSemibold", + borderColor: "colorBorderStrong", + color: "colorText", }, [`${prefix}_FOOT`]: { - backgroundColor: 'colorBackgroundStrong', - fontWeight: 'fontWeightSemibold', - borderColor: 'colorBorderStrong', - color: 'colorText', + backgroundColor: "colorBackgroundStrong", + fontWeight: "fontWeightSemibold", + borderColor: "colorBorderStrong", + color: "colorText", }, [`${prefix}_HEADER`]: { - padding: 'space10', + padding: "space10", }, [`${prefix}_ROW`]: { - borderColor: 'colorBorderStrong', + borderColor: "colorBorderStrong", // _even - '&:nth-of-type(2n)': { - backgroundColor: 'colorBackgroundBody', + "&:nth-of-type(2n)": { + backgroundColor: "colorBackgroundBody", }, }, [`${prefix}_CELL`]: { - padding: 'space10', + padding: "space10", }, }); @@ -53,7 +53,7 @@ export const CustomizableDataGrid = (): JSX.Element => { Custom element - + diff --git a/packages/paste-core/components/data-grid/stories/components/DataGridLayouts.tsx b/packages/paste-core/components/data-grid/stories/components/DataGridLayouts.tsx index 0d5bf08aec..f59ce62cc2 100644 --- a/packages/paste-core/components/data-grid/stories/components/DataGridLayouts.tsx +++ b/packages/paste-core/components/data-grid/stories/components/DataGridLayouts.tsx @@ -1,13 +1,21 @@ -import * as React from 'react'; -import {Box} from '@twilio-paste/box'; -import {Text} from '@twilio-paste/text'; -import {Stack} from '@twilio-paste/stack'; -import {Heading} from '@twilio-paste/heading'; -import {Anchor} from '@twilio-paste/anchor'; -import {Truncate} from '@twilio-paste/truncate'; -import {Button} from '@twilio-paste/button'; +import { Anchor } from "@twilio-paste/anchor"; +import { Box } from "@twilio-paste/box"; +import { Button } from "@twilio-paste/button"; +import { Heading } from "@twilio-paste/heading"; +import { Stack } from "@twilio-paste/stack"; +import { Text } from "@twilio-paste/text"; +import { Truncate } from "@twilio-paste/truncate"; +import * as React from "react"; -import {DataGrid, DataGridHead, DataGridRow, DataGridHeader, DataGridBody, DataGridCell, DataGridFoot} from '../../src'; +import { + DataGrid, + DataGridBody, + DataGridCell, + DataGridFoot, + DataGridHead, + DataGridHeader, + DataGridRow, +} from "../../src"; export const DataGridLayouts = (): React.ReactNode => { return ( @@ -380,4 +388,4 @@ export const DataGridLayouts = (): React.ReactNode => { ); }; -DataGridLayouts.storyName = 'Data Grid Layouts'; +DataGridLayouts.storyName = "Data Grid Layouts"; diff --git a/packages/paste-core/components/data-grid/stories/components/I18nDataGrid.tsx b/packages/paste-core/components/data-grid/stories/components/I18nDataGrid.tsx index d2b03ea143..959e1785eb 100644 --- a/packages/paste-core/components/data-grid/stories/components/I18nDataGrid.tsx +++ b/packages/paste-core/components/data-grid/stories/components/I18nDataGrid.tsx @@ -1,17 +1,17 @@ -import * as React from 'react'; -import {Box} from '@twilio-paste/box'; +import { Box } from "@twilio-paste/box"; +import * as React from "react"; import { DataGrid, + DataGridBody, + DataGridCell, DataGridHead, - DataGridRow, DataGridHeader, DataGridHeaderSort, - DataGridBody, - DataGridCell, -} from '../../src'; -import type {SortDirection} from '../../src'; -import {I18nTableHeaderData, I18nTableBodyData} from './constants'; + DataGridRow, +} from "../../src"; +import type { SortDirection } from "../../src"; +import { I18nTableBodyData, I18nTableHeaderData } from "./constants"; // Sorting function const simpleComparator = (a: string[], b: string[], ascending: boolean, columnId: number): number => { @@ -25,7 +25,7 @@ const simpleComparator = (a: string[], b: string[], ascending: boolean, columnId }; const numColumns = I18nTableHeaderData.length; -const initialHeaderData = [...new Array(numColumns)].map((_, index) => (index === 0 ? 'ascending' : 'none')); +const initialHeaderData = [...new Array(numColumns)].map((_, index) => (index === 0 ? "ascending" : "none")); const initialBodyData = I18nTableBodyData.sort((a, b) => simpleComparator(a, b, true, 0)); export const I18nDataGrid = (): React.ReactNode => { @@ -35,17 +35,17 @@ export const I18nDataGrid = (): React.ReactNode => { // Handle sorting behavior const handleSortingColumn = (columnId: number): void => { // Update the state of the sort direction in column headers - const newSortedColumns: Array = sortedColumns.map(() => 'none'); - if (sortedColumns[columnId] === 'ascending') { - newSortedColumns[columnId] = 'descending'; + const newSortedColumns: Array = sortedColumns.map(() => "none"); + if (sortedColumns[columnId] === "ascending") { + newSortedColumns[columnId] = "descending"; } else { - newSortedColumns[columnId] = 'ascending'; + newSortedColumns[columnId] = "ascending"; } setSortedColumns(newSortedColumns); // Update the table data to be sorted correctly setSortedData( - I18nTableBodyData.sort((a, b) => simpleComparator(a, b, newSortedColumns[columnId] === 'ascending', columnId)) + I18nTableBodyData.sort((a, b) => simpleComparator(a, b, newSortedColumns[columnId] === "ascending", columnId)), ); }; @@ -104,4 +104,4 @@ export const I18nDataGrid = (): React.ReactNode => { /* eslint-enable react/no-array-index-key */ }; -I18nDataGrid.storyName = 'i18n Data Grid'; +I18nDataGrid.storyName = "i18n Data Grid"; diff --git a/packages/paste-core/components/data-grid/stories/components/KitchenSinkDataGrid.tsx b/packages/paste-core/components/data-grid/stories/components/KitchenSinkDataGrid.tsx index 837f3d26af..eb1067c6e9 100644 --- a/packages/paste-core/components/data-grid/stories/components/KitchenSinkDataGrid.tsx +++ b/packages/paste-core/components/data-grid/stories/components/KitchenSinkDataGrid.tsx @@ -1,29 +1,29 @@ -import * as React from 'react'; -import {Box} from '@twilio-paste/box'; -import {Input} from '@twilio-paste/input'; -import {ScreenReaderOnly} from '@twilio-paste/screen-reader-only'; -import {CheckboxGroup, Checkbox} from '@twilio-paste/checkbox'; -import {useUID, useUIDSeed} from '@twilio-paste/uid-library'; +import { Box } from "@twilio-paste/box"; +import { Checkbox, CheckboxGroup } from "@twilio-paste/checkbox"; +import { Input } from "@twilio-paste/input"; import { Pagination, - PaginationItems, PaginationArrow, - PaginationNumbers, - PaginationNumber, PaginationEllipsis, -} from '@twilio-paste/pagination'; + PaginationItems, + PaginationNumber, + PaginationNumbers, +} from "@twilio-paste/pagination"; +import { ScreenReaderOnly } from "@twilio-paste/screen-reader-only"; +import { useUID, useUIDSeed } from "@twilio-paste/uid-library"; +import * as React from "react"; -import type {SortDirection} from '../../src'; +import type { SortDirection } from "../../src"; import { DataGrid, + DataGridBody, + DataGridCell, DataGridHead, - DataGridRow, DataGridHeader, DataGridHeaderSort, - DataGridBody, - DataGridCell, -} from '../../src'; -import {TableHeaderData, PaginatedTableBodyData} from './constants'; + DataGridRow, +} from "../../src"; +import { PaginatedTableBodyData, TableHeaderData } from "./constants"; // Sorting function const simpleComparator = (a: string[], b: string[], ascending: boolean, columnId: number): number => { @@ -39,14 +39,14 @@ const simpleComparator = (a: string[], b: string[], ascending: boolean, columnId const numColumns = TableHeaderData.length + 1; // +1 for checkbox; const initialHeaderData = [...new Array(numColumns)].map((_, index) => { if (index === 0) return null; - if (index === 1) return 'ascending'; - return 'none'; + if (index === 1) return "ascending"; + return "none"; }); // Add the first column for checkbox state const initialBodyData = PaginatedTableBodyData.map((row) => [false, ...row]).sort( (a, b) => // @ts-expect-error won't be boolean - simpleComparator(a, b, true, 1) // passing 1 instead of 0 to skip checkbox column + simpleComparator(a, b, true, 1), // passing 1 instead of 0 to skip checkbox column ); const getRange = (start: number, end: number): number[] => { @@ -200,7 +200,7 @@ const CheckboxCell: React.FC> = ({ } return undefined; }, - [onClick, checkboxRef] + [onClick, checkboxRef], ); return ( @@ -245,11 +245,11 @@ export const KitchenSinkDataGrid = (): JSX.Element => { // Handle sorting behavior const handleSortingColumn = (columnId: number): void => { // Update the state of the sort direction in column headers - const newSortedColumns: Array = sortedColumns.map(() => 'none'); - if (sortedColumns[columnId] === 'ascending') { - newSortedColumns[columnId] = 'descending'; + const newSortedColumns: Array = sortedColumns.map(() => "none"); + if (sortedColumns[columnId] === "ascending") { + newSortedColumns[columnId] = "descending"; } else { - newSortedColumns[columnId] = 'ascending'; + newSortedColumns[columnId] = "ascending"; } setSortedColumns(newSortedColumns); @@ -257,8 +257,8 @@ export const KitchenSinkDataGrid = (): JSX.Element => { setSortedData( initialBodyData.sort((a, b) => // @ts-expect-error won't be boolean - simpleComparator(a, b, newSortedColumns[columnId] === 'ascending', columnId) - ) + simpleComparator(a, b, newSortedColumns[columnId] === "ascending", columnId), + ), ); }; @@ -275,7 +275,7 @@ export const KitchenSinkDataGrid = (): JSX.Element => { const newSortedData = sortedData.map(([_, ...row]) => [checked, ...row]); setSortedData(newSortedData); }} - id={seed('select-all')} + id={seed("select-all")} checked={allChecked} indeterminate={indeterminate} label="Select all" diff --git a/packages/paste-core/components/data-grid/stories/components/LoadingDataGrid.tsx b/packages/paste-core/components/data-grid/stories/components/LoadingDataGrid.tsx index e18389f683..388f9e880f 100644 --- a/packages/paste-core/components/data-grid/stories/components/LoadingDataGrid.tsx +++ b/packages/paste-core/components/data-grid/stories/components/LoadingDataGrid.tsx @@ -1,8 +1,16 @@ -import * as React from 'react'; -import {SkeletonLoader} from '@twilio-paste/skeleton-loader'; +import { SkeletonLoader } from "@twilio-paste/skeleton-loader"; +import * as React from "react"; -import {DataGrid, DataGridHead, DataGridRow, DataGridHeader, DataGridBody, DataGridCell, DataGridFoot} from '../../src'; -import {TableHeaderData, TableBodyData} from './constants'; +import { + DataGrid, + DataGridBody, + DataGridCell, + DataGridFoot, + DataGridHead, + DataGridHeader, + DataGridRow, +} from "../../src"; +import { TableBodyData, TableHeaderData } from "./constants"; export const LoadingDataGrid = (): JSX.Element => { // Used for random looking column widths diff --git a/packages/paste-core/components/data-grid/stories/components/PaginatedDataGrid.tsx b/packages/paste-core/components/data-grid/stories/components/PaginatedDataGrid.tsx index 4c3e1e9a0c..006ef0bd5b 100644 --- a/packages/paste-core/components/data-grid/stories/components/PaginatedDataGrid.tsx +++ b/packages/paste-core/components/data-grid/stories/components/PaginatedDataGrid.tsx @@ -1,19 +1,19 @@ -import * as React from 'react'; -import {Box} from '@twilio-paste/box'; -import {ScreenReaderOnly} from '@twilio-paste/screen-reader-only'; -import {CheckboxGroup, Checkbox} from '@twilio-paste/checkbox'; -import {useUID, useUIDSeed} from '@twilio-paste/uid-library'; +import { Box } from "@twilio-paste/box"; +import { Checkbox, CheckboxGroup } from "@twilio-paste/checkbox"; import { Pagination, - PaginationItems, PaginationArrow, - PaginationNumbers, - PaginationNumber, PaginationEllipsis, -} from '@twilio-paste/pagination'; + PaginationItems, + PaginationNumber, + PaginationNumbers, +} from "@twilio-paste/pagination"; +import { ScreenReaderOnly } from "@twilio-paste/screen-reader-only"; +import { useUID, useUIDSeed } from "@twilio-paste/uid-library"; +import * as React from "react"; -import {DataGrid, DataGridHead, DataGridRow, DataGridHeader, DataGridBody, DataGridCell} from '../../src'; -import {TableHeaderData, PaginatedTableBodyData} from './constants'; +import { DataGrid, DataGridBody, DataGridCell, DataGridHead, DataGridHeader, DataGridRow } from "../../src"; +import { PaginatedTableBodyData, TableHeaderData } from "./constants"; const getRange = (start: number, end: number): number[] => { return [...new Array(end - start + 1)].map((_, index) => index + start); @@ -85,7 +85,7 @@ const DataGridPagination: React.FC { onPageChange(pageNumber); }, - [onPageChange] + [onPageChange], ); const paginationState = calculatePaginationState(currentPage, pageCount); @@ -169,7 +169,7 @@ const CheckboxCell: React.FC> = ({ return undefined; }, - [onClick, checkboxRef] + [onClick, checkboxRef], ); return ( @@ -223,7 +223,7 @@ export const PaginatedDataGrid = (): JSX.Element => { const newCheckedItems = checkedItems.map(() => checked); setCheckedItems(newCheckedItems); }} - id={seed('select-all')} + id={seed("select-all")} checked={allChecked} indeterminate={indeterminate} label="Select all" diff --git a/packages/paste-core/components/data-grid/stories/components/PlainDataGrid.tsx b/packages/paste-core/components/data-grid/stories/components/PlainDataGrid.tsx index 1e2b635461..a7510c4869 100644 --- a/packages/paste-core/components/data-grid/stories/components/PlainDataGrid.tsx +++ b/packages/paste-core/components/data-grid/stories/components/PlainDataGrid.tsx @@ -1,19 +1,27 @@ -import * as React from 'react'; -import {Anchor} from '@twilio-paste/anchor'; -import type {BoxProps} from '@twilio-paste/box'; -import {Paragraph} from '@twilio-paste/paragraph'; +import { Anchor } from "@twilio-paste/anchor"; +import type { BoxProps } from "@twilio-paste/box"; +import { Paragraph } from "@twilio-paste/paragraph"; +import * as React from "react"; -import {DataGrid, DataGridHead, DataGridRow, DataGridHeader, DataGridBody, DataGridCell, DataGridFoot} from '../../src'; -import {TableHeaderData, TableBodyData} from './constants'; +import { + DataGrid, + DataGridBody, + DataGridCell, + DataGridFoot, + DataGridHead, + DataGridHeader, + DataGridRow, +} from "../../src"; +import { TableBodyData, TableHeaderData } from "./constants"; -export const PlainDataGrid: React.FC> = ({ - element = 'DATA_GRID', +export const PlainDataGrid: React.FC> = ({ + element = "DATA_GRID", }) => { /* eslint-disable react/no-array-index-key */ return ( <> - Note: for DataGrids with no interactivity, use the{' '} + Note: for DataGrids with no interactivity, use the{" "} Table component instead! @@ -34,15 +42,15 @@ export const PlainDataGrid: React.FC ( {row.map((col, colIndex) => ( {col} diff --git a/packages/paste-core/components/data-grid/stories/components/SelectableRowsDataGrid.tsx b/packages/paste-core/components/data-grid/stories/components/SelectableRowsDataGrid.tsx index c4d840b7d3..76eeaf871a 100644 --- a/packages/paste-core/components/data-grid/stories/components/SelectableRowsDataGrid.tsx +++ b/packages/paste-core/components/data-grid/stories/components/SelectableRowsDataGrid.tsx @@ -1,11 +1,11 @@ -import * as React from 'react'; -import {Box} from '@twilio-paste/box'; -import {ScreenReaderOnly} from '@twilio-paste/screen-reader-only'; -import {CheckboxGroup, Checkbox} from '@twilio-paste/checkbox'; -import {useUIDSeed} from '@twilio-paste/uid-library'; +import { Box } from "@twilio-paste/box"; +import { Checkbox, CheckboxGroup } from "@twilio-paste/checkbox"; +import { ScreenReaderOnly } from "@twilio-paste/screen-reader-only"; +import { useUIDSeed } from "@twilio-paste/uid-library"; +import * as React from "react"; -import {DataGrid, DataGridHead, DataGridRow, DataGridHeader, DataGridBody, DataGridCell} from '../../src'; -import {TableHeaderData, TableBodyData} from './constants'; +import { DataGrid, DataGridBody, DataGridCell, DataGridHead, DataGridHeader, DataGridRow } from "../../src"; +import { TableBodyData, TableHeaderData } from "./constants"; interface CheckboxCellProps { onClick: (checked: boolean) => void; @@ -40,7 +40,7 @@ const CheckboxCell: React.FC> = ({ return undefined; }, - [onClick, checkboxRef] + [onClick, checkboxRef], ); return ( @@ -96,7 +96,7 @@ export const SelectableRowsDataGrid = (): JSX.Element => { const newCheckedItems = checkedItems.map(() => checked); setCheckedItems(newCheckedItems); }} - id={seed('select-all')} + id={seed("select-all")} checked={allChecked} indeterminate={indeterminate} label="Select all" diff --git a/packages/paste-core/components/data-grid/stories/components/SortableColumnsDataGrid.tsx b/packages/paste-core/components/data-grid/stories/components/SortableColumnsDataGrid.tsx index b2a81862fa..ead5a8308b 100644 --- a/packages/paste-core/components/data-grid/stories/components/SortableColumnsDataGrid.tsx +++ b/packages/paste-core/components/data-grid/stories/components/SortableColumnsDataGrid.tsx @@ -1,18 +1,18 @@ -import * as React from 'react'; -import {Box} from '@twilio-paste/box'; +import { Box } from "@twilio-paste/box"; +import * as React from "react"; import { DataGrid, - DataGridHead, - DataGridRow, - DataGridHeader, - DataGridHeaderSort, DataGridBody, DataGridCell, DataGridFoot, -} from '../../src'; -import type {SortDirection} from '../../src'; -import {TableHeaderData, TableBodyData} from './constants'; + DataGridHead, + DataGridHeader, + DataGridHeaderSort, + DataGridRow, +} from "../../src"; +import type { SortDirection } from "../../src"; +import { TableBodyData, TableHeaderData } from "./constants"; // Sorting function const simpleComparator = (a: string[], b: string[], ascending: boolean, columnId: number): number => { @@ -26,7 +26,7 @@ const simpleComparator = (a: string[], b: string[], ascending: boolean, columnId }; const numColumns = TableHeaderData.length; -const initialHeaderData = [...new Array(numColumns)].map((_, index) => (index === 0 ? 'ascending' : 'none')); +const initialHeaderData = [...new Array(numColumns)].map((_, index) => (index === 0 ? "ascending" : "none")); const initialBodyData = TableBodyData.sort((a, b) => simpleComparator(a, b, true, 0)); export const SortableColumnsDataGrid = (): JSX.Element => { @@ -36,17 +36,17 @@ export const SortableColumnsDataGrid = (): JSX.Element => { // Handle sorting behavior const handleSortingColumn = (columnId: number): void => { // Update the state of the sort direction in column headers - const newSortedColumns: Array = sortedColumns.map(() => 'none'); - if (sortedColumns[columnId] === 'ascending') { - newSortedColumns[columnId] = 'descending'; + const newSortedColumns: Array = sortedColumns.map(() => "none"); + if (sortedColumns[columnId] === "ascending") { + newSortedColumns[columnId] = "descending"; } else { - newSortedColumns[columnId] = 'ascending'; + newSortedColumns[columnId] = "ascending"; } setSortedColumns(newSortedColumns); // Update the table data to be sorted correctly setSortedData( - TableBodyData.sort((a, b) => simpleComparator(a, b, newSortedColumns[columnId] === 'ascending', columnId)) + TableBodyData.sort((a, b) => simpleComparator(a, b, newSortedColumns[columnId] === "ascending", columnId)), ); }; diff --git a/packages/paste-core/components/data-grid/stories/components/StickyHeaderDataGrid.tsx b/packages/paste-core/components/data-grid/stories/components/StickyHeaderDataGrid.tsx index 2ea32c1235..31e8e865a0 100644 --- a/packages/paste-core/components/data-grid/stories/components/StickyHeaderDataGrid.tsx +++ b/packages/paste-core/components/data-grid/stories/components/StickyHeaderDataGrid.tsx @@ -1,10 +1,18 @@ -import * as React from 'react'; -import type {BoxProps} from '@twilio-paste/box'; +import type { BoxProps } from "@twilio-paste/box"; +import * as React from "react"; -import {DataGrid, DataGridHead, DataGridRow, DataGridHeader, DataGridBody, DataGridCell, DataGridFoot} from '../../src'; +import { + DataGrid, + DataGridBody, + DataGridCell, + DataGridFoot, + DataGridHead, + DataGridHeader, + DataGridRow, +} from "../../src"; -export const StickyHeaderDataGrid: React.FC> = ({ - element = 'DATA_GRID', +export const StickyHeaderDataGrid: React.FC> = ({ + element = "DATA_GRID", }) => { /* eslint-disable react/no-array-index-key */ return ( diff --git a/packages/paste-core/components/data-grid/stories/components/constants.ts b/packages/paste-core/components/data-grid/stories/components/constants.ts index 71c4e1e858..5f3f32ce16 100644 --- a/packages/paste-core/components/data-grid/stories/components/constants.ts +++ b/packages/paste-core/components/data-grid/stories/components/constants.ts @@ -1,143 +1,143 @@ -export const TableHeaderData = ['First Name', 'Last Name', 'Country', 'Email', 'Phone']; +export const TableHeaderData = ["First Name", "Last Name", "Country", "Email", "Phone"]; export const TableBodyData = [ - ['Lottie', 'Hintz', 'Republic of Korea', 'John.Zulauf@gmail.com', '1-652-451-4330'], + ["Lottie", "Hintz", "Republic of Korea", "John.Zulauf@gmail.com", "1-652-451-4330"], [ - 'Paige', - 'Kshlerin', - 'British Indian Ocean Territory (Chagos Archipelago)', - 'Natalie.Klein@yahoo.com', - '668.667.3238 x27714', + "Paige", + "Kshlerin", + "British Indian Ocean Territory (Chagos Archipelago)", + "Natalie.Klein@yahoo.com", + "668.667.3238 x27714", ], - ['Kadin', 'Will', 'Haiti', 'Ora_Bartoletti@yahoo.com', '446.666.1937 x759'], - ['Troy', 'McDermott', 'Qatar', 'Richmond34@hotmail.com', '(209) 774-9227 x5109'], - ['Devyn', 'Weimann', 'Congo', 'Matilde86@gmail.com', '652-441-1766 x377'], - ['Triston', 'Dickinson', 'French Southern Territories', 'Violette.Kihn97@yahoo.com', '939.571.3994'], - ['Maeve', 'West', 'Norway', 'Mittie80@yahoo.com', '395.983.4598 x8023'], - ['Tracey', 'Farrell', 'Macao', 'Barrett72@yahoo.com', '1-805-781-6325'], - ['Jovanny', 'Mante', 'Pitcairn Islands', 'Fausto_Vandervort15@gmail.com', '(629) 375-5743 x726'], - ['Fritz', 'Bashirian', 'France', 'Magali.Harber@hotmail.com', '1-229-278-7567'], + ["Kadin", "Will", "Haiti", "Ora_Bartoletti@yahoo.com", "446.666.1937 x759"], + ["Troy", "McDermott", "Qatar", "Richmond34@hotmail.com", "(209) 774-9227 x5109"], + ["Devyn", "Weimann", "Congo", "Matilde86@gmail.com", "652-441-1766 x377"], + ["Triston", "Dickinson", "French Southern Territories", "Violette.Kihn97@yahoo.com", "939.571.3994"], + ["Maeve", "West", "Norway", "Mittie80@yahoo.com", "395.983.4598 x8023"], + ["Tracey", "Farrell", "Macao", "Barrett72@yahoo.com", "1-805-781-6325"], + ["Jovanny", "Mante", "Pitcairn Islands", "Fausto_Vandervort15@gmail.com", "(629) 375-5743 x726"], + ["Fritz", "Bashirian", "France", "Magali.Harber@hotmail.com", "1-229-278-7567"], ]; -export const I18nTableHeaderData = ['Prénom', 'Nom de famille', 'Pays', 'Email', 'N º de téléphone']; +export const I18nTableHeaderData = ["Prénom", "Nom de famille", "Pays", "Email", "N º de téléphone"]; export const I18nTableBodyData = [ - ['Lottie', 'Hintz', 'Corée du Sud', 'John.Zulauf@gmail.com', '1-652-451-4330'], + ["Lottie", "Hintz", "Corée du Sud", "John.Zulauf@gmail.com", "1-652-451-4330"], [ - 'Paige', - 'Kshlerin', + "Paige", + "Kshlerin", "Territoire britannique de l'océan Indien (Îles Chagos)", - 'Natalie.Klein@yahoo.com', - '668.667.3238 x27714', + "Natalie.Klein@yahoo.com", + "668.667.3238 x27714", ], - ['Kadin', 'Will', 'Haïti', 'Ora_Bartoletti@yahoo.com', '446.666.1937 x759'], - ['Troy', 'McDermott', 'Qatar', 'Richmond34@hotmail.com', '(209) 774-9227 x5109'], - ['Devyn', 'Weimann', 'République démocratique du Congo', 'Matilde86@gmail.com', '652-441-1766 x377'], - ['Triston', 'Dickinson', 'Terres australes françaises', 'Violette.Kihn97@yahoo.com', '939.571.3994'], - ['Maeve', 'West', 'Norvège', 'Mittie80@yahoo.com', '395.983.4598 x8023'], - ['Tracey', 'Farrell', 'Macao', 'Barrett72@yahoo.com', '1-805-781-6325'], - ['Jovanny', 'Mante', 'Îles Pitcairn', 'Fausto_Vandervort15@gmail.com', '(629) 375-5743 x726'], - ['Fritz', 'Bashirian', 'France', 'Magali.Harber@hotmail.com', '1-229-278-7567'], + ["Kadin", "Will", "Haïti", "Ora_Bartoletti@yahoo.com", "446.666.1937 x759"], + ["Troy", "McDermott", "Qatar", "Richmond34@hotmail.com", "(209) 774-9227 x5109"], + ["Devyn", "Weimann", "République démocratique du Congo", "Matilde86@gmail.com", "652-441-1766 x377"], + ["Triston", "Dickinson", "Terres australes françaises", "Violette.Kihn97@yahoo.com", "939.571.3994"], + ["Maeve", "West", "Norvège", "Mittie80@yahoo.com", "395.983.4598 x8023"], + ["Tracey", "Farrell", "Macao", "Barrett72@yahoo.com", "1-805-781-6325"], + ["Jovanny", "Mante", "Îles Pitcairn", "Fausto_Vandervort15@gmail.com", "(629) 375-5743 x726"], + ["Fritz", "Bashirian", "France", "Magali.Harber@hotmail.com", "1-229-278-7567"], ]; export const PaginatedTableBodyData = [ - ['Dana', 'Purdy', 'Kyrgyz Republic', 'Summer_Schulist82@gmail.com', '1-509-540-5248 x5237'], - ['Newton', 'Smith', 'Ireland', 'Julianne52@hotmail.com', '482.997.2560'], - ['Geoffrey', 'Nienow', 'Dominican Republic', 'Jerel32@yahoo.com', '(349) 361-1514 x577'], - ['Guillermo', 'Bartell', 'Panama', 'Consuelo_Wilderman@hotmail.com', '844-277-7328 x94110'], - ['Meaghan', 'Jast', 'Zimbabwe', 'Edward.Kovacek16@yahoo.com', '(894) 816-5971'], - ['Janie', 'Reilly', 'Mongolia', 'Laverna13@gmail.com', '312.889.0961 x652'], - ['Doris', 'Kuphal', 'Mozambique', 'Madaline.Zboncak86@yahoo.com', '762-716-6646 x362'], - ['Cordell', 'VonRueden', 'Estonia', 'Theresa_Crooks25@gmail.com', '563.870.3282 x76369'], - ['Ericka', 'Gislason', 'Macao', 'Preston73@hotmail.com', '1-378-991-9171 x4429'], - ['Juliet', 'Brown', 'Bangladesh', 'Ozella38@gmail.com', '(855) 416-2069'], - ['Kale', 'Terry', 'Malta', 'Neoma24@yahoo.com', '1-474-868-4014'], - ['Gilbert', 'Kling', 'Djibouti', 'Isabell0@gmail.com', '652-237-7686 x342'], - ['Eliza', 'Altenwerth', 'Fiji', 'Janet.Schimmel@hotmail.com', '1-943-324-8175 x60776'], - ['Angeline', 'Klocko', 'Guinea-Bissau', 'Haylie.OKeefe22@hotmail.com', '(750) 594-0481 x475'], - ['Ashlee', 'Haley', 'Madagascar', 'Estefania15@yahoo.com', '454-972-8055 x2182'], - ['Alberta', 'Upton', 'Bulgaria', 'Rafaela.Moen@gmail.com', '(455) 974-2352 x37422'], - ['Gerardo', 'Lemke', 'Armenia', 'Kade64@gmail.com', '1-868-933-7940'], - ['Keagan', 'Fisher', 'Lithuania', 'Lessie_Rodriguez@yahoo.com', '1-557-547-5213 x1108'], - ['Amanda', 'Blick', 'Slovakia (Slovak Republic)', 'Dominic_Jacobi66@hotmail.com', '876-598-7799 x9212'], - ['Donnie', 'Runolfsdottir', 'United States Minor Outlying Islands', 'Amely.Wolff@hotmail.com', '668-700-2505'], - ['Cleve', 'Simonis', 'Malaysia', 'Heidi_Kuphal33@hotmail.com', '997-990-4234 x61296'], - ['Korbin', 'Jast', 'Iran', 'Joaquin_Beer29@gmail.com', '1-959-606-7117 x30990'], - ['Lenna', 'Schuster', 'Djibouti', 'Hazel_Schneider@gmail.com', '255-264-4325'], - ['River', 'Grady', 'Panama', 'Micah_Turner@gmail.com', '(529) 639-4347 x59333'], - ['Brown', 'Jones', 'Nicaragua', 'Trycia_Metz@yahoo.com', '1-256-734-0106'], - ['Gino', 'Ledner', 'French Polynesia', 'Margaretta47@yahoo.com', '851.473.6903 x70407'], - ['Mario', 'Romaguera', 'Oman', 'Heber_Bernhard@yahoo.com', '1-817-374-1149 x77953'], - ['Kade', 'Feest', 'Mali', 'Angelo96@yahoo.com', '340-243-0935 x49950'], - ['Gerry', "O'Conner", 'Bouvet Island (Bouvetoya)', 'Brielle_Hirthe@hotmail.com', '579.499.8490 x3617'], - ['Mallie', 'Volkman', 'Guernsey', 'Filiberto.Christiansen@yahoo.com', '435.488.4322 x91443'], - ['Clotilde', 'Pollich', 'Italy', 'Jerrod2@hotmail.com', '(234) 902-2000 x86073'], - ['Erik', 'Homenick', 'Uzbekistan', 'Shyann6@gmail.com', '(831) 691-8639'], - ['Nona', 'Feil', 'Namibia', 'Earl33@hotmail.com', '778-960-3822'], - ['Mona', 'Dietrich', 'Saint Helena', 'Fabian34@hotmail.com', '(430) 939-3951'], - ['Ocie', 'Mills', 'Guinea', 'Luigi.Lind43@yahoo.com', '826.348.5825 x659'], - ['Retta', 'Rau', 'Philippines', 'Alessia31@yahoo.com', '519-401-7063 x2881'], - ['Ethyl', 'Gorczany', 'Bermuda', 'Kristoffer67@gmail.com', '(761) 491-3811 x0243'], - ['Orpha', 'Hahn', 'Morocco', 'Golden85@gmail.com', '549-692-1109 x7184'], - ['August', 'Bernhard', 'Saudi Arabia', 'Marietta92@yahoo.com', '502.292.8591 x374'], - ['Sandra', 'Mayert', 'Trinidad and Tobago', 'Ella_Hamill84@gmail.com', '450-909-6603 x2216'], - ['Elbert', 'Zulauf', 'Germany', 'Vivien_Kulas@yahoo.com', '692.877.6884'], - ['Kendrick', 'Wunsch', 'Chad', 'Naomi97@hotmail.com', '(974) 721-5042'], - ['Katlyn', 'Little', 'Jamaica', 'Toney.Carroll@yahoo.com', '(778) 241-7007'], - ['Ivory', 'Stroman', 'Guatemala', 'Buck.Hills53@gmail.com', '858-308-7139 x93478'], - ['Brisa', 'Bauch', 'Gambia', 'Wilma26@gmail.com', '(772) 715-4726 x69927'], - ['Candelario', 'Mills', 'Singapore', 'Gino_Nitzsche@hotmail.com', '487-619-2534 x80594'], - ['Novella', 'Kautzer', 'Mauritius', 'Osvaldo.Langosh@yahoo.com', '1-622-325-6527 x0857'], - ['Yolanda', "O'Keefe", 'Chad', 'Cordell.Wisozk@yahoo.com', '350-787-6845 x487'], - ['Jaleel', 'Pollich', 'Puerto Rico', 'Mozell.Zieme@hotmail.com', '283-456-6704 x421'], - ['Viva', 'Hammes', 'Dominica', 'Wilber60@yahoo.com', '1-928-412-0183 x051'], - ['Gage', 'Fadel', 'Sierra Leone', 'Hassie.Prohaska@yahoo.com', '1-517-756-3633 x74298'], - ['Samir', 'Muller', 'Singapore', 'Hardy3@yahoo.com', '(275) 642-3243 x63177'], - ['Charlene', 'Leffler', 'Jordan', 'Micah3@hotmail.com', '1-518-541-4229 x42630'], - ['Isidro', 'Hackett', 'Saint Barthelemy', 'Jany.Lang@hotmail.com', '254.895.5509'], - ['Garrick', 'Barrows', 'Liberia', 'Cathrine_Schoen60@yahoo.com', '1-644-620-1245'], - ['Wendell', 'Quigley', 'Zambia', 'Alycia.Weissnat@yahoo.com', '1-359-231-9374 x32138'], - ['Zackery', 'Lakin', 'Belgium', 'Maida_Herzog@gmail.com', '375.208.2651'], - ['Nola', 'Runolfsdottir', 'Libyan Arab Jamahiriya', 'Elena.Maggio@gmail.com', '1-944-553-0727 x085'], - ['Maximus', 'Yundt', 'Solomon Islands', 'Harold_Considine@gmail.com', '857-849-7065 x116'], - ['Rhea', 'Bosco', 'Afghanistan', 'Daryl_Smitham1@gmail.com', '241-750-2028'], - ['Susanna', 'Gerlach', 'United States Minor Outlying Islands', 'Jameson_Powlowski87@gmail.com', '1-646-911-3449'], - ['Murray', 'Rowe', 'Switzerland', 'Michelle.Sipes65@hotmail.com', '(273) 939-6217'], - ['Katlyn', 'Ankunding', 'Cape Verde', 'Randal60@gmail.com', '409.752.0839 x3057'], - ['Elody', 'Russel', 'Malaysia', 'Webster2@yahoo.com', '(430) 904-6170 x1920'], - ['Katherine', 'Ondricka', 'Cuba', 'Mitchel_Greenholt53@yahoo.com', '621.993.3379 x973'], - ['Jerald', 'Schinner', 'Timor-Leste', 'Stephen_Boyer@hotmail.com', '591.426.0485 x6715'], - ['Thora', 'Kling', 'Mauritania', 'Brown.Schumm13@hotmail.com', '576-913-2319 x36968'], - ['Blaze', 'Brakus', 'Afghanistan', 'Deondre_Abshire74@gmail.com', '832-217-7583 x582'], - ['Blake', 'Homenick', 'Angola', 'Lenna87@yahoo.com', '(690) 241-2156'], - ['Georgiana', 'Dicki', 'Isle of Man', 'Eric_Gulgowski98@hotmail.com', '1-813-216-9812 x33694'], - ['Juanita', 'Schmidt', 'Suriname', 'Kelsi3@gmail.com', '831.695.3141'], - ['Lauriane', 'Leffler', 'Kiribati', 'Matteo85@yahoo.com', '(668) 992-6556'], - ['Virgie', 'Herman', 'Suriname', 'Ahmed_Swaniawski@hotmail.com', '(661) 509-1813 x23911'], - ['Luna', 'Abshire', 'Montserrat', 'Mark.Rosenbaum93@gmail.com', '948-347-0408'], - ['Dwight', 'Shields', 'Suriname', 'Herminia.Konopelski53@yahoo.com', '407.962.0997 x08726'], - ['Sienna', 'Cremin', 'Jordan', 'Marlene.Schmitt48@yahoo.com', '(953) 817-9868'], - ['Blake', 'Aufderhar', 'Aruba', 'Emily_Boyer8@gmail.com', '(316) 572-7708 x4304'], - ['Camron', 'Smitham', 'Lesotho', 'Lucienne_Reynolds@yahoo.com', '426.971.4552'], - ['Keon', 'McDermott', 'Denmark', 'Elvis45@hotmail.com', '384-284-6416'], - ['Itzel', 'Prosacco', 'Syrian Arab Republic', 'Matt.Walsh74@hotmail.com', '(939) 760-5400 x938'], - ['Royal', 'Schaefer', 'Mauritius', 'Elyssa78@yahoo.com', '265-915-2483'], - ['Ahmed', 'Fay', 'Jordan', 'Anabel9@yahoo.com', '910.500.0553 x8346'], - ['Mable', 'Shields', 'Ethiopia', 'Walter.Schuster92@yahoo.com', '887.206.5824'], - ['Lazaro', 'Schiller', 'Isle of Man', 'Jorge27@yahoo.com', '1-886-911-4192 x2102'], - ['Dolly', 'Braun', 'Spain', 'Shania.Murazik@yahoo.com', '(855) 751-5256'], - ['Lexus', 'Mitchell', 'Greenland', 'Junius.Bartell60@hotmail.com', '(809) 876-3070 x106'], - ['Kathryn', 'Hermann', 'Finland', 'Shyanne_Howell23@yahoo.com', '(743) 754-7533'], - ['Lily', 'Moore', 'Bangladesh', 'Delphine.Kassulke8@hotmail.com', '797.985.5878'], - ['Clinton', 'Hegmann', 'Burkina Faso', 'Samantha69@gmail.com', '530.408.5548 x949'], - ['Nia', 'Ward', 'Central African Republic', 'Reese20@gmail.com', '920.461.6688 x7840'], - ['Leila', 'Pollich', 'Guernsey', 'Dulce_Borer@hotmail.com', '1-629-452-5075 x606'], - ['Reed', 'Pollich', 'Qatar', 'Lauriane_Hermann80@hotmail.com', '736-363-8718'], - ['Krystal', 'Stanton', 'Bangladesh', 'Francisca_Boyer@hotmail.com', '1-493-502-0113 x5815'], - ['Sidney', 'Rogahn', 'Germany', 'Josefina_Bergstrom@gmail.com', '1-947-816-5320 x040'], - ['Arnoldo', 'Schaden', 'Grenada', 'Agnes_Mann@gmail.com', '1-451-374-8117'], - ['Lucile', 'Brakus', 'Pitcairn Islands', 'Maud46@gmail.com', '921-696-6753'], - ['Ashly', 'Nikolaus', 'Martinique', 'Brandyn_Spencer@hotmail.com', '1-751-647-5226'], - ['Carol', 'Kozey', 'France', 'Vanessa_Rath84@yahoo.com', '463.612.9329 x09925'], - ['Kurt', 'Frami', 'Liberia', 'Kayleigh41@hotmail.com', '(944) 531-5068'], - ['Adan', 'Walter', 'Chile', 'Anya.Reinger@gmail.com', '806-549-2278'], + ["Dana", "Purdy", "Kyrgyz Republic", "Summer_Schulist82@gmail.com", "1-509-540-5248 x5237"], + ["Newton", "Smith", "Ireland", "Julianne52@hotmail.com", "482.997.2560"], + ["Geoffrey", "Nienow", "Dominican Republic", "Jerel32@yahoo.com", "(349) 361-1514 x577"], + ["Guillermo", "Bartell", "Panama", "Consuelo_Wilderman@hotmail.com", "844-277-7328 x94110"], + ["Meaghan", "Jast", "Zimbabwe", "Edward.Kovacek16@yahoo.com", "(894) 816-5971"], + ["Janie", "Reilly", "Mongolia", "Laverna13@gmail.com", "312.889.0961 x652"], + ["Doris", "Kuphal", "Mozambique", "Madaline.Zboncak86@yahoo.com", "762-716-6646 x362"], + ["Cordell", "VonRueden", "Estonia", "Theresa_Crooks25@gmail.com", "563.870.3282 x76369"], + ["Ericka", "Gislason", "Macao", "Preston73@hotmail.com", "1-378-991-9171 x4429"], + ["Juliet", "Brown", "Bangladesh", "Ozella38@gmail.com", "(855) 416-2069"], + ["Kale", "Terry", "Malta", "Neoma24@yahoo.com", "1-474-868-4014"], + ["Gilbert", "Kling", "Djibouti", "Isabell0@gmail.com", "652-237-7686 x342"], + ["Eliza", "Altenwerth", "Fiji", "Janet.Schimmel@hotmail.com", "1-943-324-8175 x60776"], + ["Angeline", "Klocko", "Guinea-Bissau", "Haylie.OKeefe22@hotmail.com", "(750) 594-0481 x475"], + ["Ashlee", "Haley", "Madagascar", "Estefania15@yahoo.com", "454-972-8055 x2182"], + ["Alberta", "Upton", "Bulgaria", "Rafaela.Moen@gmail.com", "(455) 974-2352 x37422"], + ["Gerardo", "Lemke", "Armenia", "Kade64@gmail.com", "1-868-933-7940"], + ["Keagan", "Fisher", "Lithuania", "Lessie_Rodriguez@yahoo.com", "1-557-547-5213 x1108"], + ["Amanda", "Blick", "Slovakia (Slovak Republic)", "Dominic_Jacobi66@hotmail.com", "876-598-7799 x9212"], + ["Donnie", "Runolfsdottir", "United States Minor Outlying Islands", "Amely.Wolff@hotmail.com", "668-700-2505"], + ["Cleve", "Simonis", "Malaysia", "Heidi_Kuphal33@hotmail.com", "997-990-4234 x61296"], + ["Korbin", "Jast", "Iran", "Joaquin_Beer29@gmail.com", "1-959-606-7117 x30990"], + ["Lenna", "Schuster", "Djibouti", "Hazel_Schneider@gmail.com", "255-264-4325"], + ["River", "Grady", "Panama", "Micah_Turner@gmail.com", "(529) 639-4347 x59333"], + ["Brown", "Jones", "Nicaragua", "Trycia_Metz@yahoo.com", "1-256-734-0106"], + ["Gino", "Ledner", "French Polynesia", "Margaretta47@yahoo.com", "851.473.6903 x70407"], + ["Mario", "Romaguera", "Oman", "Heber_Bernhard@yahoo.com", "1-817-374-1149 x77953"], + ["Kade", "Feest", "Mali", "Angelo96@yahoo.com", "340-243-0935 x49950"], + ["Gerry", "O'Conner", "Bouvet Island (Bouvetoya)", "Brielle_Hirthe@hotmail.com", "579.499.8490 x3617"], + ["Mallie", "Volkman", "Guernsey", "Filiberto.Christiansen@yahoo.com", "435.488.4322 x91443"], + ["Clotilde", "Pollich", "Italy", "Jerrod2@hotmail.com", "(234) 902-2000 x86073"], + ["Erik", "Homenick", "Uzbekistan", "Shyann6@gmail.com", "(831) 691-8639"], + ["Nona", "Feil", "Namibia", "Earl33@hotmail.com", "778-960-3822"], + ["Mona", "Dietrich", "Saint Helena", "Fabian34@hotmail.com", "(430) 939-3951"], + ["Ocie", "Mills", "Guinea", "Luigi.Lind43@yahoo.com", "826.348.5825 x659"], + ["Retta", "Rau", "Philippines", "Alessia31@yahoo.com", "519-401-7063 x2881"], + ["Ethyl", "Gorczany", "Bermuda", "Kristoffer67@gmail.com", "(761) 491-3811 x0243"], + ["Orpha", "Hahn", "Morocco", "Golden85@gmail.com", "549-692-1109 x7184"], + ["August", "Bernhard", "Saudi Arabia", "Marietta92@yahoo.com", "502.292.8591 x374"], + ["Sandra", "Mayert", "Trinidad and Tobago", "Ella_Hamill84@gmail.com", "450-909-6603 x2216"], + ["Elbert", "Zulauf", "Germany", "Vivien_Kulas@yahoo.com", "692.877.6884"], + ["Kendrick", "Wunsch", "Chad", "Naomi97@hotmail.com", "(974) 721-5042"], + ["Katlyn", "Little", "Jamaica", "Toney.Carroll@yahoo.com", "(778) 241-7007"], + ["Ivory", "Stroman", "Guatemala", "Buck.Hills53@gmail.com", "858-308-7139 x93478"], + ["Brisa", "Bauch", "Gambia", "Wilma26@gmail.com", "(772) 715-4726 x69927"], + ["Candelario", "Mills", "Singapore", "Gino_Nitzsche@hotmail.com", "487-619-2534 x80594"], + ["Novella", "Kautzer", "Mauritius", "Osvaldo.Langosh@yahoo.com", "1-622-325-6527 x0857"], + ["Yolanda", "O'Keefe", "Chad", "Cordell.Wisozk@yahoo.com", "350-787-6845 x487"], + ["Jaleel", "Pollich", "Puerto Rico", "Mozell.Zieme@hotmail.com", "283-456-6704 x421"], + ["Viva", "Hammes", "Dominica", "Wilber60@yahoo.com", "1-928-412-0183 x051"], + ["Gage", "Fadel", "Sierra Leone", "Hassie.Prohaska@yahoo.com", "1-517-756-3633 x74298"], + ["Samir", "Muller", "Singapore", "Hardy3@yahoo.com", "(275) 642-3243 x63177"], + ["Charlene", "Leffler", "Jordan", "Micah3@hotmail.com", "1-518-541-4229 x42630"], + ["Isidro", "Hackett", "Saint Barthelemy", "Jany.Lang@hotmail.com", "254.895.5509"], + ["Garrick", "Barrows", "Liberia", "Cathrine_Schoen60@yahoo.com", "1-644-620-1245"], + ["Wendell", "Quigley", "Zambia", "Alycia.Weissnat@yahoo.com", "1-359-231-9374 x32138"], + ["Zackery", "Lakin", "Belgium", "Maida_Herzog@gmail.com", "375.208.2651"], + ["Nola", "Runolfsdottir", "Libyan Arab Jamahiriya", "Elena.Maggio@gmail.com", "1-944-553-0727 x085"], + ["Maximus", "Yundt", "Solomon Islands", "Harold_Considine@gmail.com", "857-849-7065 x116"], + ["Rhea", "Bosco", "Afghanistan", "Daryl_Smitham1@gmail.com", "241-750-2028"], + ["Susanna", "Gerlach", "United States Minor Outlying Islands", "Jameson_Powlowski87@gmail.com", "1-646-911-3449"], + ["Murray", "Rowe", "Switzerland", "Michelle.Sipes65@hotmail.com", "(273) 939-6217"], + ["Katlyn", "Ankunding", "Cape Verde", "Randal60@gmail.com", "409.752.0839 x3057"], + ["Elody", "Russel", "Malaysia", "Webster2@yahoo.com", "(430) 904-6170 x1920"], + ["Katherine", "Ondricka", "Cuba", "Mitchel_Greenholt53@yahoo.com", "621.993.3379 x973"], + ["Jerald", "Schinner", "Timor-Leste", "Stephen_Boyer@hotmail.com", "591.426.0485 x6715"], + ["Thora", "Kling", "Mauritania", "Brown.Schumm13@hotmail.com", "576-913-2319 x36968"], + ["Blaze", "Brakus", "Afghanistan", "Deondre_Abshire74@gmail.com", "832-217-7583 x582"], + ["Blake", "Homenick", "Angola", "Lenna87@yahoo.com", "(690) 241-2156"], + ["Georgiana", "Dicki", "Isle of Man", "Eric_Gulgowski98@hotmail.com", "1-813-216-9812 x33694"], + ["Juanita", "Schmidt", "Suriname", "Kelsi3@gmail.com", "831.695.3141"], + ["Lauriane", "Leffler", "Kiribati", "Matteo85@yahoo.com", "(668) 992-6556"], + ["Virgie", "Herman", "Suriname", "Ahmed_Swaniawski@hotmail.com", "(661) 509-1813 x23911"], + ["Luna", "Abshire", "Montserrat", "Mark.Rosenbaum93@gmail.com", "948-347-0408"], + ["Dwight", "Shields", "Suriname", "Herminia.Konopelski53@yahoo.com", "407.962.0997 x08726"], + ["Sienna", "Cremin", "Jordan", "Marlene.Schmitt48@yahoo.com", "(953) 817-9868"], + ["Blake", "Aufderhar", "Aruba", "Emily_Boyer8@gmail.com", "(316) 572-7708 x4304"], + ["Camron", "Smitham", "Lesotho", "Lucienne_Reynolds@yahoo.com", "426.971.4552"], + ["Keon", "McDermott", "Denmark", "Elvis45@hotmail.com", "384-284-6416"], + ["Itzel", "Prosacco", "Syrian Arab Republic", "Matt.Walsh74@hotmail.com", "(939) 760-5400 x938"], + ["Royal", "Schaefer", "Mauritius", "Elyssa78@yahoo.com", "265-915-2483"], + ["Ahmed", "Fay", "Jordan", "Anabel9@yahoo.com", "910.500.0553 x8346"], + ["Mable", "Shields", "Ethiopia", "Walter.Schuster92@yahoo.com", "887.206.5824"], + ["Lazaro", "Schiller", "Isle of Man", "Jorge27@yahoo.com", "1-886-911-4192 x2102"], + ["Dolly", "Braun", "Spain", "Shania.Murazik@yahoo.com", "(855) 751-5256"], + ["Lexus", "Mitchell", "Greenland", "Junius.Bartell60@hotmail.com", "(809) 876-3070 x106"], + ["Kathryn", "Hermann", "Finland", "Shyanne_Howell23@yahoo.com", "(743) 754-7533"], + ["Lily", "Moore", "Bangladesh", "Delphine.Kassulke8@hotmail.com", "797.985.5878"], + ["Clinton", "Hegmann", "Burkina Faso", "Samantha69@gmail.com", "530.408.5548 x949"], + ["Nia", "Ward", "Central African Republic", "Reese20@gmail.com", "920.461.6688 x7840"], + ["Leila", "Pollich", "Guernsey", "Dulce_Borer@hotmail.com", "1-629-452-5075 x606"], + ["Reed", "Pollich", "Qatar", "Lauriane_Hermann80@hotmail.com", "736-363-8718"], + ["Krystal", "Stanton", "Bangladesh", "Francisca_Boyer@hotmail.com", "1-493-502-0113 x5815"], + ["Sidney", "Rogahn", "Germany", "Josefina_Bergstrom@gmail.com", "1-947-816-5320 x040"], + ["Arnoldo", "Schaden", "Grenada", "Agnes_Mann@gmail.com", "1-451-374-8117"], + ["Lucile", "Brakus", "Pitcairn Islands", "Maud46@gmail.com", "921-696-6753"], + ["Ashly", "Nikolaus", "Martinique", "Brandyn_Spencer@hotmail.com", "1-751-647-5226"], + ["Carol", "Kozey", "France", "Vanessa_Rath84@yahoo.com", "463.612.9329 x09925"], + ["Kurt", "Frami", "Liberia", "Kayleigh41@hotmail.com", "(944) 531-5068"], + ["Adan", "Walter", "Chile", "Anya.Reinger@gmail.com", "806-549-2278"], ]; diff --git a/packages/paste-core/components/data-grid/stories/customization.stories.tsx b/packages/paste-core/components/data-grid/stories/customization.stories.tsx index fa488433de..ac4de0c2c8 100644 --- a/packages/paste-core/components/data-grid/stories/customization.stories.tsx +++ b/packages/paste-core/components/data-grid/stories/customization.stories.tsx @@ -1,6 +1,6 @@ -export {CustomizableDataGrid} from './components/CustomizableDataGrid'; +export { CustomizableDataGrid } from "./components/CustomizableDataGrid"; // eslint-disable-next-line import/no-default-export export default { - title: 'Components/Data Grid/Customization', + title: "Components/Data Grid/Customization", }; diff --git a/packages/paste-core/components/data-grid/stories/index.stories.tsx b/packages/paste-core/components/data-grid/stories/index.stories.tsx index 08a935af77..1d721b690e 100644 --- a/packages/paste-core/components/data-grid/stories/index.stories.tsx +++ b/packages/paste-core/components/data-grid/stories/index.stories.tsx @@ -1,16 +1,16 @@ -export {PlainDataGrid} from './components/PlainDataGrid'; -export {ComposableCellsDataGrid} from './components/ComposableCellsDataGrid'; -export {LoadingDataGrid} from './components/LoadingDataGrid'; -export {SelectableRowsDataGrid} from './components/SelectableRowsDataGrid'; -export {PaginatedDataGrid} from './components/PaginatedDataGrid'; -export {SortableColumnsDataGrid} from './components/SortableColumnsDataGrid'; -export {KitchenSinkDataGrid} from './components/KitchenSinkDataGrid'; -export {I18nDataGrid} from './components/I18nDataGrid'; -export {DataGridLayouts} from './components/DataGridLayouts'; -export {ColumnSpanDataGrid} from './components/ColumnSpanDataGrid'; -export {StickyHeaderDataGrid} from './components/StickyHeaderDataGrid'; +export { PlainDataGrid } from "./components/PlainDataGrid"; +export { ComposableCellsDataGrid } from "./components/ComposableCellsDataGrid"; +export { LoadingDataGrid } from "./components/LoadingDataGrid"; +export { SelectableRowsDataGrid } from "./components/SelectableRowsDataGrid"; +export { PaginatedDataGrid } from "./components/PaginatedDataGrid"; +export { SortableColumnsDataGrid } from "./components/SortableColumnsDataGrid"; +export { KitchenSinkDataGrid } from "./components/KitchenSinkDataGrid"; +export { I18nDataGrid } from "./components/I18nDataGrid"; +export { DataGridLayouts } from "./components/DataGridLayouts"; +export { ColumnSpanDataGrid } from "./components/ColumnSpanDataGrid"; +export { StickyHeaderDataGrid } from "./components/StickyHeaderDataGrid"; // eslint-disable-next-line import/no-default-export export default { - title: 'Components/Data Grid', + title: "Components/Data Grid", }; diff --git a/packages/paste-core/components/date-picker/__tests__/index.spec.tsx b/packages/paste-core/components/date-picker/__tests__/index.spec.tsx index 489ce7485b..1ea73cae9a 100644 --- a/packages/paste-core/components/date-picker/__tests__/index.spec.tsx +++ b/packages/paste-core/components/date-picker/__tests__/index.spec.tsx @@ -1,178 +1,178 @@ -import * as React from 'react'; -import {CustomizationProvider} from '@twilio-paste/customization'; -import {render, screen} from '@testing-library/react'; +import { render, screen } from "@testing-library/react"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import * as React from "react"; -import {formatReturnDate} from '../src'; +import { formatReturnDate } from "../src"; import { DefaultDatePicker, DisabledDatePicker, ErrorDatePicker, InverseDatePicker, ReadonlyDatePicker, -} from '../stories/index.stories'; - -describe('formatReturnDate()', () => { - const TEST_DATE = '2021-02-14'; - - it('should format dates', () => { - expect(formatReturnDate(TEST_DATE, 'MMMM do yy')).toEqual('February 14th 21'); - expect(formatReturnDate(TEST_DATE, 'MMM DDD yyyy')).toEqual('Feb 045 2021'); - expect(formatReturnDate(TEST_DATE, 'MM dd yyyy')).toEqual('02 14 2021'); - expect(formatReturnDate(TEST_DATE, 'EEEEEE MMMMM dd yy')).toEqual('Su F 14 21'); - expect(formatReturnDate(TEST_DATE, 'E..EEE M Do yo')).toEqual('Sun..Sun 2 45th 2021st'); - expect(formatReturnDate(TEST_DATE, 'Mo d Yo')).toEqual('2nd 14 2021st'); +} from "../stories/index.stories"; + +describe("formatReturnDate()", () => { + const TEST_DATE = "2021-02-14"; + + it("should format dates", () => { + expect(formatReturnDate(TEST_DATE, "MMMM do yy")).toEqual("February 14th 21"); + expect(formatReturnDate(TEST_DATE, "MMM DDD yyyy")).toEqual("Feb 045 2021"); + expect(formatReturnDate(TEST_DATE, "MM dd yyyy")).toEqual("02 14 2021"); + expect(formatReturnDate(TEST_DATE, "EEEEEE MMMMM dd yy")).toEqual("Su F 14 21"); + expect(formatReturnDate(TEST_DATE, "E..EEE M Do yo")).toEqual("Sun..Sun 2 45th 2021st"); + expect(formatReturnDate(TEST_DATE, "Mo d Yo")).toEqual("2nd 14 2021st"); }); - it('should format dates with edge cases and catch errors', () => { + it("should format dates with edge cases and catch errors", () => { // test for first day of the year to avoid 1-day-off error - expect(formatReturnDate('2020-01-01', 'MM/dd/yyyy')).toEqual('01/01/2020'); + expect(formatReturnDate("2020-01-01", "MM/dd/yyyy")).toEqual("01/01/2020"); // test for edge cases (passing in time+date value) to throw an error expect(() => { - formatReturnDate('2022-03-01T03:35Z', 'MM/dd/yyyy'); - }).toThrow('[Paste Date Picker]: Please make sure dateValue string matches YYYY-MM-DD format'); + formatReturnDate("2022-03-01T03:35Z", "MM/dd/yyyy"); + }).toThrow("[Paste Date Picker]: Please make sure dateValue string matches YYYY-MM-DD format"); }); }); -describe('DatePicker', () => { - describe('DatePicker inner props', () => { +describe("DatePicker", () => { + describe("DatePicker inner props", () => { const initialProps = { - id: 'datepicker', - name: 'dp', + id: "datepicker", + name: "dp", disabled: true, readOnly: true, hasError: true, required: true, - defaultValue: '2020-03-21', - 'data-testid': 'datepickerid', + defaultValue: "2020-03-21", + "data-testid": "datepickerid", }; render(); - const InnerDatePicker = screen.getByTestId('datepickerid'); + const InnerDatePicker = screen.getByTestId("datepickerid"); - it('should set disabled correctly', () => { - expect(InnerDatePicker.getAttribute('disabled')).toEqual(''); - expect(InnerDatePicker).toHaveStyleRule('-webkit-text-fill-color', 'colorTextWeaker', {target: ':disabled'}); + it("should set disabled correctly", () => { + expect(InnerDatePicker.getAttribute("disabled")).toEqual(""); + expect(InnerDatePicker).toHaveStyleRule("-webkit-text-fill-color", "colorTextWeaker", { target: ":disabled" }); }); - it('should set readOnly correctly', () => { - expect(InnerDatePicker.getAttribute('aria-readonly')).toEqual('true'); - expect(InnerDatePicker.getAttribute('readOnly')).toEqual(''); + it("should set readOnly correctly", () => { + expect(InnerDatePicker.getAttribute("aria-readonly")).toEqual("true"); + expect(InnerDatePicker.getAttribute("readOnly")).toEqual(""); }); - it('should set hasErorr correctly', () => { - expect(InnerDatePicker.getAttribute('aria-invalid')).toEqual('true'); + it("should set hasErorr correctly", () => { + expect(InnerDatePicker.getAttribute("aria-invalid")).toEqual("true"); }); - it('should set id correctly', () => { - expect(InnerDatePicker.getAttribute('id')).toEqual(initialProps.id); + it("should set id correctly", () => { + expect(InnerDatePicker.getAttribute("id")).toEqual(initialProps.id); }); - it('should set name correctly', () => { - expect(InnerDatePicker.getAttribute('name')).toEqual(initialProps.name); + it("should set name correctly", () => { + expect(InnerDatePicker.getAttribute("name")).toEqual(initialProps.name); }); - it('should set defaultValue correctly', () => { - expect(InnerDatePicker.getAttribute('value')).toEqual(initialProps.defaultValue); + it("should set defaultValue correctly", () => { + expect(InnerDatePicker.getAttribute("value")).toEqual(initialProps.defaultValue); }); - it('should render with margin: space0', () => { - expect(InnerDatePicker).toHaveStyleRule('margin', 'space0'); + it("should render with margin: space0", () => { + expect(InnerDatePicker).toHaveStyleRule("margin", "space0"); }); - it('should set required correctly', () => { - expect(InnerDatePicker.getAttribute('required')).toEqual(''); + it("should set required correctly", () => { + expect(InnerDatePicker.getAttribute("required")).toEqual(""); }); }); - describe('Customization', () => { + describe("Customization", () => { const initialProps = { - id: 'datepicker', - name: 'dp', - defaultValue: '2020-03-21', - 'data-testid': 'datepickerid', + id: "datepicker", + name: "dp", + defaultValue: "2020-03-21", + "data-testid": "datepickerid", }; - it('should add the element dom attibute', () => { - const {container} = render(); + it("should add the element dom attibute", () => { + const { container } = render(); expect(container.querySelector('[data-paste-element="DATEPICKER"]')).toBeInTheDocument(); - expect(screen.getByTestId('datepickerid').getAttribute('data-paste-element')).toEqual('DATEPICKER_ELEMENT'); + expect(screen.getByTestId("datepickerid").getAttribute("data-paste-element")).toEqual("DATEPICKER_ELEMENT"); }); - it('should add a custom element dom attibute', () => { - const {container} = render(); + it("should add a custom element dom attibute", () => { + const { container } = render(); expect(container.querySelector('[data-paste-element="CUSTOM_DATE"]')).toBeInTheDocument(); - expect(screen.getByTestId('datepickerid').getAttribute('data-paste-element')).toEqual('CUSTOM_DATE_ELEMENT'); + expect(screen.getByTestId("datepickerid").getAttribute("data-paste-element")).toEqual("CUSTOM_DATE_ELEMENT"); }); - it('should add custom styles to the DatePicker Component', () => { - const {container} = render( + it("should add custom styles to the DatePicker Component", () => { + const { container } = render( - + , ); const renderedDatepicker = container.querySelector('[data-paste-element="DATEPICKER"]'); - const renderedDatepickerElement = screen.getByTestId('datepickerid'); - expect(renderedDatepicker).toHaveStyleRule('background-color', 'rgb(6, 3, 58)'); - expect(renderedDatepickerElement).toHaveStyleRule('background-color', 'rgb(242, 47, 70)'); + const renderedDatepickerElement = screen.getByTestId("datepickerid"); + expect(renderedDatepicker).toHaveStyleRule("background-color", "rgb(6, 3, 58)"); + expect(renderedDatepickerElement).toHaveStyleRule("background-color", "rgb(242, 47, 70)"); }); - it('should add custom styles to the DatePicker Component variant', () => { - const {container} = render( + it("should add custom styles to the DatePicker Component variant", () => { + const { container } = render( - + , ); const renderedDatepicker = container.querySelector('[data-paste-element="DATEPICKER"]'); - const renderedDatepickerElement = screen.getByTestId('datepickerid'); - expect(renderedDatepicker).toHaveStyleRule('background-color', 'rgb(0, 20, 137)'); - expect(renderedDatepickerElement).toHaveStyleRule('background-color', 'rgb(0, 20, 137)'); + const renderedDatepickerElement = screen.getByTestId("datepickerid"); + expect(renderedDatepicker).toHaveStyleRule("background-color", "rgb(0, 20, 137)"); + expect(renderedDatepickerElement).toHaveStyleRule("background-color", "rgb(0, 20, 137)"); }); - it('should add custom styles to a custom DatePicker Component', () => { - const {container} = render( + it("should add custom styles to a custom DatePicker Component", () => { + const { container } = render( - + , ); const renderedDatepicker = container.querySelector('[data-paste-element="CUSTOMDATE"]'); - const renderedDatepickerElement = screen.getByTestId('datepickerid'); - expect(renderedDatepicker).toHaveStyleRule('background-color', 'rgb(244, 124, 34)'); - expect(renderedDatepickerElement).toHaveStyleRule('background-color', 'rgb(214, 31, 31)'); + const renderedDatepickerElement = screen.getByTestId("datepickerid"); + expect(renderedDatepicker).toHaveStyleRule("background-color", "rgb(244, 124, 34)"); + expect(renderedDatepickerElement).toHaveStyleRule("background-color", "rgb(214, 31, 31)"); }); - it('should add custom styles to a custom DatePicker Component variant', () => { - const {container} = render( + it("should add custom styles to a custom DatePicker Component variant", () => { + const { container } = render( - + , ); const renderedDatepicker = container.querySelector('[data-paste-element="CUSTOMDATE"]'); - const renderedDatepickerElement = screen.getByTestId('datepickerid'); - expect(renderedDatepicker).toHaveStyleRule('background-color', 'rgb(231, 220, 250)'); - expect(renderedDatepickerElement).toHaveStyleRule('background-color', 'rgb(20, 176, 83)'); + const renderedDatepickerElement = screen.getByTestId("datepickerid"); + expect(renderedDatepicker).toHaveStyleRule("background-color", "rgb(231, 220, 250)"); + expect(renderedDatepickerElement).toHaveStyleRule("background-color", "rgb(20, 176, 83)"); }); }); }); diff --git a/packages/paste-core/components/date-picker/build.js b/packages/paste-core/components/date-picker/build.js index a4edeab49b..27dd98f98e 100644 --- a/packages/paste-core/components/date-picker/build.js +++ b/packages/paste-core/components/date-picker/build.js @@ -1,3 +1,3 @@ -const {build} = require('../../../../tools/build/esbuild'); +const { build } = require("../../../../tools/build/esbuild"); -build(require('./package.json')); +build(require("./package.json")); diff --git a/packages/paste-core/components/date-picker/src/DatePicker.tsx b/packages/paste-core/components/date-picker/src/DatePicker.tsx index 3d0ab8ee93..6291363b2a 100644 --- a/packages/paste-core/components/date-picker/src/DatePicker.tsx +++ b/packages/paste-core/components/date-picker/src/DatePicker.tsx @@ -1,13 +1,13 @@ -import * as React from 'react'; -import type {InputProps} from '@twilio-paste/input'; -import {Input} from '@twilio-paste/input'; +import type { InputProps } from "@twilio-paste/input"; +import { Input } from "@twilio-paste/input"; +import * as React from "react"; -export type DatePickerProps = Omit; +export type DatePickerProps = Omit; -const DatePicker = React.forwardRef(({element = 'DATEPICKER', ...props}, ref) => { +const DatePicker = React.forwardRef(({ element = "DATEPICKER", ...props }, ref) => { return ; }); -DatePicker.displayName = 'DatePicker'; +DatePicker.displayName = "DatePicker"; -export {DatePicker}; +export { DatePicker }; diff --git a/packages/paste-core/components/date-picker/src/index.tsx b/packages/paste-core/components/date-picker/src/index.tsx index e0e72ae789..64f209a625 100644 --- a/packages/paste-core/components/date-picker/src/index.tsx +++ b/packages/paste-core/components/date-picker/src/index.tsx @@ -1,2 +1,2 @@ -export * from './DatePicker'; -export * from './utils'; +export * from "./DatePicker"; +export * from "./utils"; diff --git a/packages/paste-core/components/date-picker/src/utils.ts b/packages/paste-core/components/date-picker/src/utils.ts index 1a9dd426a9..f5f63dfc9e 100644 --- a/packages/paste-core/components/date-picker/src/utils.ts +++ b/packages/paste-core/components/date-picker/src/utils.ts @@ -1,9 +1,9 @@ -import {format} from 'date-fns'; +import { format } from "date-fns"; // https://stackoverflow.com/questions/22061723/regex-date-validation-for-yyyy-mm-dd/22061800 const DATE_REGEX = /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/; -const NEUTRAL_TIME = 'T12:00:00-00:00'; +const NEUTRAL_TIME = "T12:00:00-00:00"; /** * dateValue must follow the format: 'YYYY-MM-DD' @@ -32,5 +32,5 @@ export const formatReturnDate = (dateValue: DateValueType, dateFormat: DateForma const datePlusNoonUTC = new Date(dateValue.concat(NEUTRAL_TIME)); return format(datePlusNoonUTC, dateFormat); } - throw new Error('[Paste Date Picker]: Please make sure dateValue string matches YYYY-MM-DD format'); + throw new Error("[Paste Date Picker]: Please make sure dateValue string matches YYYY-MM-DD format"); }; diff --git a/packages/paste-core/components/date-picker/stories/index.stories.tsx b/packages/paste-core/components/date-picker/stories/index.stories.tsx index 8dde99ed61..8fc9dc828e 100644 --- a/packages/paste-core/components/date-picker/stories/index.stories.tsx +++ b/packages/paste-core/components/date-picker/stories/index.stories.tsx @@ -1,17 +1,17 @@ -import * as React from 'react'; -import type {StoryFn} from '@storybook/react'; -import {CustomizationProvider} from '@twilio-paste/customization'; -import {useTheme} from '@twilio-paste/theme'; -import {Anchor} from '@twilio-paste/anchor'; -import {Box} from '@twilio-paste/box'; -import {Label} from '@twilio-paste/label'; -import {HelpText} from '@twilio-paste/help-text'; -import {useUID, useUIDSeed} from '@twilio-paste/uid-library'; -import {Combobox} from '@twilio-paste/combobox'; -import {Stack} from '@twilio-paste/stack'; +import type { StoryFn } from "@storybook/react"; +import { Anchor } from "@twilio-paste/anchor"; +import { Box } from "@twilio-paste/box"; +import { Combobox } from "@twilio-paste/combobox"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import { HelpText } from "@twilio-paste/help-text"; +import { Label } from "@twilio-paste/label"; +import { Stack } from "@twilio-paste/stack"; +import { useTheme } from "@twilio-paste/theme"; +import { useUID, useUIDSeed } from "@twilio-paste/uid-library"; +import * as React from "react"; -import {DatePicker, formatReturnDate} from '../src'; -import type {DatePickerProps} from '../src'; +import { DatePicker, formatReturnDate } from "../src"; +import type { DatePickerProps } from "../src"; export const DefaultDatePicker: React.FC> = (props) => { const uidDP = useUID(); @@ -200,11 +200,11 @@ export const DefaultValueDatePicker: React.FC> = (props) => { - const [value, setValue] = React.useState(''); - const [dateFormat, setDateFormat] = React.useState('MM dd yy'); + const [value, setValue] = React.useState(""); + const [dateFormat, setDateFormat] = React.useState("MM dd yy"); const uidDP = useUID(); const uidHT = useUID(); - const dateFormatOptions = ['MM dd yyyy', 'MMMM do yyyy', 'EEEEEE MMM do yy', 'MM/dd/yyyy']; + const dateFormatOptions = ["MM dd yyyy", "MMMM do yyyy", "EEEEEE MMM do yy", "MM/dd/yyyy"]; const handleChange = (val: string, format: string): string => { setValue(formatReturnDate(val, format)); return value; @@ -215,7 +215,7 @@ export const OnChangeDatePicker: React.FC { + onInputValueChange={({ inputValue }) => { if (inputValue !== undefined) setDateFormat(inputValue); }} /> @@ -251,7 +251,7 @@ export const LabelOnlyPicker: React.FC> }; export const DateRangePicker: React.FC> = (props) => { - const [startDate, setStartDate] = React.useState(''); + const [startDate, setStartDate] = React.useState(""); const startUidDP = useUID(); const endUidDP = useUID(); return ( @@ -324,7 +324,7 @@ export const DatePickerWithMinAndMax: React.FC { +export const CustomizedDatePicker: StoryFn = (_args, { parameters: { isTestEnvironment }, props }) => { const activeTheme = useTheme(); const uidSeed = useUIDSeed(); return ( @@ -333,67 +333,67 @@ export const CustomizedDatePicker: StoryFn = (_args, {parameters: {isTestEnviron theme={activeTheme} elements={{ DATEPICKER: { - backgroundColor: 'colorBackgroundPrimaryWeakest', - borderRadius: 'borderRadius30', - boxShadow: 'none', - borderStyle: 'solid', - borderWidth: 'borderWidth10', - borderColor: 'colorBorderPrimary', + backgroundColor: "colorBackgroundPrimaryWeakest", + borderRadius: "borderRadius30", + boxShadow: "none", + borderStyle: "solid", + borderWidth: "borderWidth10", + borderColor: "colorBorderPrimary", variants: { default: { - backgroundColor: 'colorBackgroundPrimaryWeakest', + backgroundColor: "colorBackgroundPrimaryWeakest", }, inverse: { - backgroundColor: 'colorBackgroundDestructiveWeakest', - borderColor: 'colorBorderDestructive', + backgroundColor: "colorBackgroundDestructiveWeakest", + borderColor: "colorBorderDestructive", }, }, }, DATEPICKER_ELEMENT: { - color: 'colorTextLinkStronger', - padding: 'space50', - '::placeholder': { - color: 'colorTextLink', + color: "colorTextLinkStronger", + padding: "space50", + "::placeholder": { + color: "colorTextLink", }, variants: { default: { - backgroundColor: 'colorBackgroundPrimaryWeakest', + backgroundColor: "colorBackgroundPrimaryWeakest", }, inverse: { - backgroundColor: 'colorBackgroundDestructiveWeakest', + backgroundColor: "colorBackgroundDestructiveWeakest", }, }, }, CUSTOM_DATE: { - backgroundColor: 'colorBackgroundDestructiveWeakest', - borderRadius: 'borderRadius30', - boxShadow: 'none', - borderStyle: 'solid', - borderWidth: 'borderWidth20', - borderColor: 'colorBorderDestructive', + backgroundColor: "colorBackgroundDestructiveWeakest", + borderRadius: "borderRadius30", + boxShadow: "none", + borderStyle: "solid", + borderWidth: "borderWidth20", + borderColor: "colorBorderDestructive", variants: { default: { - backgroundColor: 'colorBackgroundDestructiveWeakest', + backgroundColor: "colorBackgroundDestructiveWeakest", }, inverse: { - backgroundColor: 'colorBackgroundPrimaryWeakest', - borderColor: 'colorBorderPrimary', + backgroundColor: "colorBackgroundPrimaryWeakest", + borderColor: "colorBorderPrimary", }, }, }, CUSTOM_DATE_ELEMENT: { - color: 'colorTextLinkDestructive', - padding: 'space70', - '::placeholder': { - color: 'colorTextLinkDestructive', + color: "colorTextLinkDestructive", + padding: "space70", + "::placeholder": { + color: "colorTextLinkDestructive", }, variants: { default: { - backgroundColor: 'colorBackgroundDestructiveWeakest', + backgroundColor: "colorBackgroundDestructiveWeakest", }, inverse: { - backgroundColor: 'colorBackgroundPrimaryWeakest', - borderRadius: 'borderRadius30', + backgroundColor: "colorBackgroundPrimaryWeakest", + borderRadius: "borderRadius30", }, }, }, @@ -401,24 +401,24 @@ export const CustomizedDatePicker: StoryFn = (_args, {parameters: {isTestEnviron >
    - - + +
    -
    - - + +
    -
    @@ -433,6 +433,6 @@ CustomizedDatePicker.parameters = { // eslint-disable-next-line import/no-default-export export default { - title: 'Components/Date Picker', + title: "Components/Date Picker", component: DatePicker, }; diff --git a/packages/paste-core/components/description-list/__tests__/index.spec.tsx b/packages/paste-core/components/description-list/__tests__/index.spec.tsx index 0089595477..bfef097d1a 100644 --- a/packages/paste-core/components/description-list/__tests__/index.spec.tsx +++ b/packages/paste-core/components/description-list/__tests__/index.spec.tsx @@ -1,19 +1,19 @@ -import * as React from 'react'; -import {render, screen} from '@testing-library/react'; -import {Theme} from '@twilio-paste/theme'; -import {CustomizationProvider} from '@twilio-paste/customization'; +import { render, screen } from "@testing-library/react"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import { Theme } from "@twilio-paste/theme"; +import * as React from "react"; -import {DescriptionList, DescriptionListSet, DescriptionListTerm, DescriptionListDetails} from '../src'; +import { DescriptionList, DescriptionListDetails, DescriptionListSet, DescriptionListTerm } from "../src"; -const FONT_WEIGHT = 'font-weight'; -const MARGIN_LEFT = 'margin-left'; -const COLOR = 'color'; -const MARGIN = 'margin'; -const FONT_SIZE = 'font-size'; -const LINE_HEIGHT = 'line-height'; -const BACKGROUND_COLOR = 'background-color'; +const FONT_WEIGHT = "font-weight"; +const MARGIN_LEFT = "margin-left"; +const COLOR = "color"; +const MARGIN = "margin"; +const FONT_SIZE = "font-size"; +const LINE_HEIGHT = "line-height"; +const BACKGROUND_COLOR = "background-color"; -describe('DescriptionList', () => { +describe("DescriptionList", () => { render( @@ -31,39 +31,39 @@ describe('DescriptionList', () => { Three - + , ); - const terms = screen.getAllByRole('term'); - const details = screen.getAllByRole('definition'); + const terms = screen.getAllByRole("term"); + const details = screen.getAllByRole("definition"); - it('should render as terms and definitions', () => { + it("should render as terms and definitions", () => { expect(terms.length).toBe(3); expect(details.length).toBe(4); }); - describe('DescriptionListTerm', () => { - it('should apply the correct styling', () => { - expect(terms[0]).toHaveStyleRule(FONT_WEIGHT, '600'); - expect(terms[0]).toHaveStyleRule(MARGIN, '0'); - expect(terms[0]).toHaveStyleRule(COLOR, 'rgb(18, 28, 45)'); - expect(terms[0]).toHaveStyleRule(FONT_SIZE, '0.875rem'); - expect(terms[0]).toHaveStyleRule(LINE_HEIGHT, '1.25rem'); + describe("DescriptionListTerm", () => { + it("should apply the correct styling", () => { + expect(terms[0]).toHaveStyleRule(FONT_WEIGHT, "600"); + expect(terms[0]).toHaveStyleRule(MARGIN, "0"); + expect(terms[0]).toHaveStyleRule(COLOR, "rgb(18, 28, 45)"); + expect(terms[0]).toHaveStyleRule(FONT_SIZE, "0.875rem"); + expect(terms[0]).toHaveStyleRule(LINE_HEIGHT, "1.25rem"); }); }); - describe('DescriptionListDetails', () => { - it('should apply the correct styling', () => { - expect(details[0]).toHaveStyleRule(MARGIN, '0'); - expect(details[0]).toHaveStyleRule(FONT_WEIGHT, '400'); - expect(details[0]).toHaveStyleRule(COLOR, 'rgb(18, 28, 45)'); - expect(details[0]).toHaveStyleRule(FONT_SIZE, '0.875rem'); - expect(details[0]).toHaveStyleRule(LINE_HEIGHT, '1.25rem'); + describe("DescriptionListDetails", () => { + it("should apply the correct styling", () => { + expect(details[0]).toHaveStyleRule(MARGIN, "0"); + expect(details[0]).toHaveStyleRule(FONT_WEIGHT, "400"); + expect(details[0]).toHaveStyleRule(COLOR, "rgb(18, 28, 45)"); + expect(details[0]).toHaveStyleRule(FONT_SIZE, "0.875rem"); + expect(details[0]).toHaveStyleRule(LINE_HEIGHT, "1.25rem"); }); }); }); -describe('Customization', () => { - it('should set data paste element attribute', () => { +describe("Customization", () => { + it("should set data paste element attribute", () => { render( @@ -72,15 +72,15 @@ describe('Customization', () => { 1 - + , ); - expect(screen.getByText('A').closest('dl')?.dataset.pasteElement).toBe('DESCRIPTION_LIST'); - expect(screen.getByText('A').closest('div')?.dataset.pasteElement).toBe('DESCRIPTION_LIST_SET'); - expect(screen.getByRole('term').dataset.pasteElement).toBe('DESCRIPTION_LIST_TERM'); - expect(screen.getByRole('definition').dataset.pasteElement).toBe('DESCRIPTION_LIST_DETAILS'); + expect(screen.getByText("A").closest("dl")?.dataset.pasteElement).toBe("DESCRIPTION_LIST"); + expect(screen.getByText("A").closest("div")?.dataset.pasteElement).toBe("DESCRIPTION_LIST_SET"); + expect(screen.getByRole("term").dataset.pasteElement).toBe("DESCRIPTION_LIST_TERM"); + expect(screen.getByRole("definition").dataset.pasteElement).toBe("DESCRIPTION_LIST_DETAILS"); }); - it('should set custom data paste element attribute', () => { + it("should set custom data paste element attribute", () => { render( @@ -89,24 +89,24 @@ describe('Customization', () => { 1 - + , ); - expect(screen.getByText('A').closest('dl')?.dataset.pasteElement).toBe('FAZ'); - expect(screen.getByText('A').closest('div')?.dataset.pasteElement).toBe('BAZ'); - expect(screen.getByRole('term').dataset.pasteElement).toBe('FOO'); - expect(screen.getByRole('definition').dataset.pasteElement).toBe('BAR'); + expect(screen.getByText("A").closest("dl")?.dataset.pasteElement).toBe("FAZ"); + expect(screen.getByText("A").closest("div")?.dataset.pasteElement).toBe("BAZ"); + expect(screen.getByRole("term").dataset.pasteElement).toBe("FOO"); + expect(screen.getByRole("definition").dataset.pasteElement).toBe("BAR"); }); - it('should add custom styles', () => { + it("should add custom styles", () => { render( @@ -115,24 +115,24 @@ describe('Customization', () => { 1 - + , ); - expect(screen.getByText('A').closest('dl')).toHaveStyleRule(COLOR, 'rgb(109, 46, 209)'); - expect(screen.getByText('A').closest('div')).toHaveStyleRule(BACKGROUND_COLOR, 'rgb(237, 253, 243)'); - expect(screen.getByRole('term')).toHaveStyleRule(FONT_WEIGHT, '700'); - expect(screen.getByRole('definition')).toHaveStyleRule(MARGIN_LEFT, '0.125rem'); + expect(screen.getByText("A").closest("dl")).toHaveStyleRule(COLOR, "rgb(109, 46, 209)"); + expect(screen.getByText("A").closest("div")).toHaveStyleRule(BACKGROUND_COLOR, "rgb(237, 253, 243)"); + expect(screen.getByRole("term")).toHaveStyleRule(FONT_WEIGHT, "700"); + expect(screen.getByRole("definition")).toHaveStyleRule(MARGIN_LEFT, "0.125rem"); }); - it('should add custom styles with a custom data paste element attribute', () => { + it("should add custom styles with a custom data paste element attribute", () => { render( @@ -141,11 +141,11 @@ describe('Customization', () => { 1 - + , ); - expect(screen.getByText('A').closest('dl')).toHaveStyleRule(COLOR, 'rgb(109, 46, 209)'); - expect(screen.getByText('A').closest('div')).toHaveStyleRule(BACKGROUND_COLOR, 'rgb(237, 253, 243)'); - expect(screen.getByRole('term')).toHaveStyleRule(FONT_WEIGHT, '700'); - expect(screen.getByRole('definition')).toHaveStyleRule(MARGIN_LEFT, '0.125rem'); + expect(screen.getByText("A").closest("dl")).toHaveStyleRule(COLOR, "rgb(109, 46, 209)"); + expect(screen.getByText("A").closest("div")).toHaveStyleRule(BACKGROUND_COLOR, "rgb(237, 253, 243)"); + expect(screen.getByRole("term")).toHaveStyleRule(FONT_WEIGHT, "700"); + expect(screen.getByRole("definition")).toHaveStyleRule(MARGIN_LEFT, "0.125rem"); }); }); diff --git a/packages/paste-core/components/description-list/build.js b/packages/paste-core/components/description-list/build.js index a4edeab49b..27dd98f98e 100644 --- a/packages/paste-core/components/description-list/build.js +++ b/packages/paste-core/components/description-list/build.js @@ -1,3 +1,3 @@ -const {build} = require('../../../../tools/build/esbuild'); +const { build } = require("../../../../tools/build/esbuild"); -build(require('./package.json')); +build(require("./package.json")); diff --git a/packages/paste-core/components/description-list/src/DescriptionList.tsx b/packages/paste-core/components/description-list/src/DescriptionList.tsx index f1a7d37c2d..611c4812cf 100644 --- a/packages/paste-core/components/description-list/src/DescriptionList.tsx +++ b/packages/paste-core/components/description-list/src/DescriptionList.tsx @@ -1,22 +1,22 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import * as React from "react"; -export interface DescriptionListProps extends Omit, 'children'> { +export interface DescriptionListProps extends Omit, "children"> { children?: React.ReactNode; - element?: BoxProps['element']; + element?: BoxProps["element"]; } const DescriptionList = React.forwardRef( - ({element = 'DESCRIPTION_LIST', children, ...props}, ref) => { + ({ element = "DESCRIPTION_LIST", children, ...props }, ref) => { return ( {children} ); - } + }, ); -DescriptionList.displayName = 'DescriptionList'; +DescriptionList.displayName = "DescriptionList"; -export {DescriptionList}; +export { DescriptionList }; diff --git a/packages/paste-core/components/description-list/src/DescriptionListDetails.tsx b/packages/paste-core/components/description-list/src/DescriptionListDetails.tsx index c7c0413c45..20454a410d 100644 --- a/packages/paste-core/components/description-list/src/DescriptionListDetails.tsx +++ b/packages/paste-core/components/description-list/src/DescriptionListDetails.tsx @@ -1,14 +1,14 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import * as React from "react"; -export interface DescriptionListDetailsProps extends Omit, 'children'> { +export interface DescriptionListDetailsProps extends Omit, "children"> { children?: React.ReactNode; - element?: BoxProps['element']; + element?: BoxProps["element"]; } const DescriptionListDetails = React.forwardRef( - ({element = 'DESCRIPTION_LIST_DETAILS', children, ...props}, ref) => { + ({ element = "DESCRIPTION_LIST_DETAILS", children, ...props }, ref) => { return ( ); - } + }, ); -DescriptionListDetails.displayName = 'DescriptionListDetails'; +DescriptionListDetails.displayName = "DescriptionListDetails"; -export {DescriptionListDetails}; +export { DescriptionListDetails }; diff --git a/packages/paste-core/components/description-list/src/DescriptionListSet.tsx b/packages/paste-core/components/description-list/src/DescriptionListSet.tsx index 0828b13270..a84cf0a2a9 100644 --- a/packages/paste-core/components/description-list/src/DescriptionListSet.tsx +++ b/packages/paste-core/components/description-list/src/DescriptionListSet.tsx @@ -1,41 +1,41 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; -import {styled, css} from '@twilio-paste/styling-library'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import { css, styled } from "@twilio-paste/styling-library"; +import * as React from "react"; export const StyledDescriptionListSet = styled.div( css({ - '& > dd:last-of-type': { - marginBottom: 'space60', + "& > dd:last-of-type": { + marginBottom: "space60", }, - '& > dd:not(:last-of-type)': { - marginBottom: 'space10', + "& > dd:not(:last-of-type)": { + marginBottom: "space10", }, - '& > dt:last-of-type': { - marginBottom: 'space20', + "& > dt:last-of-type": { + marginBottom: "space20", }, - '& > dt:not(:last-of-type)': { - marginBottom: 'space10', + "& > dt:not(:last-of-type)": { + marginBottom: "space10", }, - }) + }), ); -export interface DescriptionSetListProps extends Omit, 'children'> { +export interface DescriptionSetListProps extends Omit, "children"> { children?: React.ReactNode; - element?: BoxProps['element']; + element?: BoxProps["element"]; } const DescriptionListSet = React.forwardRef( - ({element = 'DESCRIPTION_LIST_SET', children, ...props}, ref) => { + ({ element = "DESCRIPTION_LIST_SET", children, ...props }, ref) => { return ( // @ts-expect-error Use Box as styled div to apply complex css to the child terms and details {children} ); - } + }, ); -DescriptionListSet.displayName = 'DescriptionListSet'; +DescriptionListSet.displayName = "DescriptionListSet"; -export {DescriptionListSet}; +export { DescriptionListSet }; diff --git a/packages/paste-core/components/description-list/src/DescriptionListTerm.tsx b/packages/paste-core/components/description-list/src/DescriptionListTerm.tsx index ec9c4bac18..dec67b5c0e 100644 --- a/packages/paste-core/components/description-list/src/DescriptionListTerm.tsx +++ b/packages/paste-core/components/description-list/src/DescriptionListTerm.tsx @@ -1,14 +1,14 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import * as React from "react"; -export interface DescriptionListTermProps extends Omit, 'children'> { +export interface DescriptionListTermProps extends Omit, "children"> { children?: React.ReactNode; - element?: BoxProps['element']; + element?: BoxProps["element"]; } const DescriptionListTerm = React.forwardRef( - ({element = 'DESCRIPTION_LIST_TERM', children, ...props}, ref) => { + ({ element = "DESCRIPTION_LIST_TERM", children, ...props }, ref) => { return ( ); - } + }, ); -DescriptionListTerm.displayName = 'DescriptionListTerm'; +DescriptionListTerm.displayName = "DescriptionListTerm"; -export {DescriptionListTerm}; +export { DescriptionListTerm }; diff --git a/packages/paste-core/components/description-list/src/index.tsx b/packages/paste-core/components/description-list/src/index.tsx index fac4379714..e8fc247cd5 100644 --- a/packages/paste-core/components/description-list/src/index.tsx +++ b/packages/paste-core/components/description-list/src/index.tsx @@ -1,4 +1,4 @@ -export * from './DescriptionList'; -export * from './DescriptionListTerm'; -export * from './DescriptionListDetails'; -export * from './DescriptionListSet'; +export * from "./DescriptionList"; +export * from "./DescriptionListTerm"; +export * from "./DescriptionListDetails"; +export * from "./DescriptionListSet"; diff --git a/packages/paste-core/components/description-list/stories/index.stories.tsx b/packages/paste-core/components/description-list/stories/index.stories.tsx index 59309c7c54..0d43e48c51 100644 --- a/packages/paste-core/components/description-list/stories/index.stories.tsx +++ b/packages/paste-core/components/description-list/stories/index.stories.tsx @@ -1,16 +1,16 @@ -import * as React from 'react'; -import type {StoryFn} from '@storybook/react'; -import {CustomizationProvider} from '@twilio-paste/customization'; -import {Box} from '@twilio-paste/box'; -import {useTheme} from '@twilio-paste/theme'; -import {ProcessSuccessIcon} from '@twilio-paste/icons/esm/ProcessSuccessIcon'; -import {Text} from '@twilio-paste/text'; +import type { StoryFn } from "@storybook/react"; +import { Box } from "@twilio-paste/box"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import { ProcessSuccessIcon } from "@twilio-paste/icons/esm/ProcessSuccessIcon"; +import { Text } from "@twilio-paste/text"; +import { useTheme } from "@twilio-paste/theme"; +import * as React from "react"; -import {DescriptionList, DescriptionListSet, DescriptionListTerm, DescriptionListDetails} from '../src'; +import { DescriptionList, DescriptionListDetails, DescriptionListSet, DescriptionListTerm } from "../src"; // eslint-disable-next-line import/no-default-export export default { - title: 'Components/Description List', + title: "Components/Description List", component: DescriptionList, }; @@ -143,10 +143,10 @@ export const Customized: StoryFn = () => { diff --git a/packages/paste-core/components/detail-text/__tests__/index.spec.tsx b/packages/paste-core/components/detail-text/__tests__/index.spec.tsx index 774fc40b34..4ad271676e 100644 --- a/packages/paste-core/components/detail-text/__tests__/index.spec.tsx +++ b/packages/paste-core/components/detail-text/__tests__/index.spec.tsx @@ -1,72 +1,72 @@ -import * as React from 'react'; -import {render, screen} from '@testing-library/react'; -import {CustomizationProvider} from '@twilio-paste/customization'; +import { render, screen } from "@testing-library/react"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import * as React from "react"; -import {DetailText} from '../src'; +import { DetailText } from "../src"; -describe('DetailText', () => { - it('should render', () => { +describe("DetailText", () => { + it("should render", () => { render(test); - expect(screen.getByText('test')).toBeDefined(); + expect(screen.getByText("test")).toBeDefined(); }); - it('should render the element based on the as prop', () => { + it("should render the element based on the as prop", () => { render(test); - expect(screen.getByRole('listitem')).toBeDefined(); + expect(screen.getByRole("listitem")).toBeDefined(); }); - describe('Customization', () => { - it('should set default data paste element attribute', () => { + describe("Customization", () => { + it("should set default data paste element attribute", () => { render(test); - expect(screen.getByTestId('detail-text').dataset.pasteElement).toEqual('DETAIL_TEXT'); + expect(screen.getByTestId("detail-text").dataset.pasteElement).toEqual("DETAIL_TEXT"); }); - it('should set custom data paste element attribute', () => { + it("should set custom data paste element attribute", () => { render( test - + , ); - expect(screen.getByTestId('detail-text').dataset.pasteElement).toEqual('MY_DETAIL_TEXT'); + expect(screen.getByTestId("detail-text").dataset.pasteElement).toEqual("MY_DETAIL_TEXT"); }); - it('should add custom styles', () => { + it("should add custom styles", () => { render( test - + , ); - expect(screen.getByTestId('detail-text')).toHaveStyleRule('color', 'rgb(109, 46, 209)'); + expect(screen.getByTestId("detail-text")).toHaveStyleRule("color", "rgb(109, 46, 209)"); }); - it('should add custom styles with a custom data paste element attribute', () => { + it("should add custom styles with a custom data paste element attribute", () => { render( test - + , ); - expect(screen.getByTestId('detail-text')).toHaveStyleRule('color', 'rgb(109, 46, 209)'); + expect(screen.getByTestId("detail-text")).toHaveStyleRule("color", "rgb(109, 46, 209)"); }); }); }); diff --git a/packages/paste-core/components/detail-text/build.js b/packages/paste-core/components/detail-text/build.js index a4edeab49b..27dd98f98e 100644 --- a/packages/paste-core/components/detail-text/build.js +++ b/packages/paste-core/components/detail-text/build.js @@ -1,3 +1,3 @@ -const {build} = require('../../../../tools/build/esbuild'); +const { build } = require("../../../../tools/build/esbuild"); -build(require('./package.json')); +build(require("./package.json")); diff --git a/packages/paste-core/components/detail-text/src/index.tsx b/packages/paste-core/components/detail-text/src/index.tsx index 13b80f388e..deb4a6563e 100644 --- a/packages/paste-core/components/detail-text/src/index.tsx +++ b/packages/paste-core/components/detail-text/src/index.tsx @@ -1,16 +1,16 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import * as React from "react"; -export interface DetailTextProps extends Omit, 'children'> { +export interface DetailTextProps extends Omit, "children"> { children?: React.ReactNode; - element?: BoxProps['element']; - as?: BoxProps['as']; - marginTop?: 'space0' | 'space30'; + element?: BoxProps["element"]; + as?: BoxProps["as"]; + marginTop?: "space0" | "space30"; } export const DetailText = React.forwardRef( - ({element = 'DETAIL_TEXT', as = 'div', children, marginTop = 'space30', ...props}, ref) => { + ({ element = "DETAIL_TEXT", as = "div", children, marginTop = "space30", ...props }, ref) => { return ( ( {children} ); - } + }, ); -DetailText.displayName = 'DetailText'; +DetailText.displayName = "DetailText"; diff --git a/packages/paste-core/components/detail-text/stories/index.stories.tsx b/packages/paste-core/components/detail-text/stories/index.stories.tsx index 4f7d043133..84f4a5987a 100644 --- a/packages/paste-core/components/detail-text/stories/index.stories.tsx +++ b/packages/paste-core/components/detail-text/stories/index.stories.tsx @@ -1,14 +1,14 @@ -import * as React from 'react'; -import type {StoryFn} from '@storybook/react'; -import {Box} from '@twilio-paste/box'; -import {CustomizationProvider} from '@twilio-paste/customization'; -import {useTheme} from '@twilio-paste/theme'; +import type { StoryFn } from "@storybook/react"; +import { Box } from "@twilio-paste/box"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import { useTheme } from "@twilio-paste/theme"; +import * as React from "react"; -import {DetailText} from '../src'; +import { DetailText } from "../src"; // eslint-disable-next-line import/no-default-export export default { - title: 'Components/Detail Text', + title: "Components/Detail Text", component: DetailText, }; @@ -33,8 +33,8 @@ export const Customized: StoryFn = () => { theme={theme} elements={{ DETAIL_TEXT: { - color: 'colorTextNew', - marginTop: 'space60', + color: "colorTextNew", + marginTop: "space60", }, }} > diff --git a/packages/paste-core/components/disclosure/__tests__/disclosure.test.tsx b/packages/paste-core/components/disclosure/__tests__/disclosure.test.tsx index 3b0efb7c07..a04a8c9ef7 100644 --- a/packages/paste-core/components/disclosure/__tests__/disclosure.test.tsx +++ b/packages/paste-core/components/disclosure/__tests__/disclosure.test.tsx @@ -1,19 +1,19 @@ -import * as React from 'react'; -import {render, screen, waitFor} from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import {Theme} from '@twilio-paste/theme'; -import {CustomizationProvider} from '@twilio-paste/customization'; +import { render, screen, waitFor } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import { Theme } from "@twilio-paste/theme"; +import * as React from "react"; -import {Disclosure, DisclosureContent, DisclosureHeading, useDisclosureState} from '../src'; -import type {DisclosureHeadingProps, DisclosureProps} from '../src'; +import { Disclosure, DisclosureContent, DisclosureHeading, useDisclosureState } from "../src"; +import type { DisclosureHeadingProps, DisclosureProps } from "../src"; const MockDisclosure: React.FC< React.PropsWithChildren<{ - visible?: DisclosureProps['visible']; - disabled?: DisclosureHeadingProps['disabled']; - focusable?: DisclosureHeadingProps['focusable']; + visible?: DisclosureProps["visible"]; + disabled?: DisclosureHeadingProps["disabled"]; + focusable?: DisclosureHeadingProps["focusable"]; }> -> = ({visible, disabled, focusable}) => { +> = ({ visible, disabled, focusable }) => { return ( @@ -76,142 +76,142 @@ const StateHookMock = (): JSX.Element => { ); }; -describe('Disclosure', () => { - describe('Render', () => { - it('should render a disclosure button with aria attributes', () => { +describe("Disclosure", () => { + describe("Render", () => { + it("should render a disclosure button with aria attributes", () => { render(); - const renderedDisclosureButton = screen.getByRole('button'); - expect(renderedDisclosureButton.getAttribute('aria-expanded')).toEqual('false'); - expect(renderedDisclosureButton.getAttribute('aria-controls')).toEqual('disclosure'); - expect(renderedDisclosureButton.getAttribute('tabindex')).toEqual('0'); - expect(screen.getByTestId('disclosure').id).toEqual('disclosure'); + const renderedDisclosureButton = screen.getByRole("button"); + expect(renderedDisclosureButton.getAttribute("aria-expanded")).toEqual("false"); + expect(renderedDisclosureButton.getAttribute("aria-controls")).toEqual("disclosure"); + expect(renderedDisclosureButton.getAttribute("tabindex")).toEqual("0"); + expect(screen.getByTestId("disclosure").id).toEqual("disclosure"); }); - it('should render a disclosure open', async () => { + it("should render a disclosure open", async () => { await waitFor(() => { render(); }); - const renderedDisclosureButton = screen.getByRole('button'); - expect(renderedDisclosureButton.getAttribute('aria-expanded')).toEqual('true'); + const renderedDisclosureButton = screen.getByRole("button"); + expect(renderedDisclosureButton.getAttribute("aria-expanded")).toEqual("true"); }); - it('should update attributes when clicked', async () => { + it("should update attributes when clicked", async () => { render(); - const renderedDisclosureButton = screen.getByRole('button'); + const renderedDisclosureButton = screen.getByRole("button"); userEvent.click(renderedDisclosureButton); - expect(renderedDisclosureButton.getAttribute('aria-expanded')).toEqual('true'); + expect(renderedDisclosureButton.getAttribute("aria-expanded")).toEqual("true"); }); - it('should render a disabled disclosure', () => { + it("should render a disabled disclosure", () => { render(); - const renderedDisclosureButton = screen.getByRole('button'); - expect(renderedDisclosureButton.getAttribute('aria-disabled')).toEqual('true'); - expect(renderedDisclosureButton.getAttribute('tabindex')).toBeNull(); + const renderedDisclosureButton = screen.getByRole("button"); + expect(renderedDisclosureButton.getAttribute("aria-disabled")).toEqual("true"); + expect(renderedDisclosureButton.getAttribute("tabindex")).toBeNull(); }); - it('should render a disabled but focusable disclosure', () => { + it("should render a disabled but focusable disclosure", () => { render(); - const renderedDisclosureButton = screen.getByRole('button'); - expect(renderedDisclosureButton.getAttribute('aria-disabled')).toEqual('true'); - expect(renderedDisclosureButton.getAttribute('tabindex')).toEqual('0'); + const renderedDisclosureButton = screen.getByRole("button"); + expect(renderedDisclosureButton.getAttribute("aria-disabled")).toEqual("true"); + expect(renderedDisclosureButton.getAttribute("tabindex")).toEqual("0"); }); - it('should render a disclosure open and update attributes when clicked using a state hook', async () => { + it("should render a disclosure open and update attributes when clicked using a state hook", async () => { render(); - const toggleButton = screen.getByTestId('external-toggle'); - const disclosureButton = screen.getByTestId('disclosure-button'); - const disclosureContent = screen.getByTestId('disclosure-content'); - expect(disclosureButton.getAttribute('aria-expanded')).toEqual('false'); + const toggleButton = screen.getByTestId("external-toggle"); + const disclosureButton = screen.getByTestId("disclosure-button"); + const disclosureContent = screen.getByTestId("disclosure-content"); + expect(disclosureButton.getAttribute("aria-expanded")).toEqual("false"); expect(disclosureContent).not.toBeVisible(); userEvent.click(toggleButton); - expect(disclosureButton.getAttribute('aria-expanded')).toEqual('true'); + expect(disclosureButton.getAttribute("aria-expanded")).toEqual("true"); waitFor(() => { expect(disclosureContent).toBeVisible(); }); }); }); - describe('Customization', () => { - it('should set an element data attribute for Disclosure components', () => { + describe("Customization", () => { + it("should set an element data attribute for Disclosure components", () => { render( - + , ); - const renderedDisclosureHeading = screen.getByTestId('disclosure-heading'); - const renderedDisclosure = screen.getByTestId('disclosure'); - const renderedDisclosureContent = screen.getByTestId('disclosure-content'); + const renderedDisclosureHeading = screen.getByTestId("disclosure-heading"); + const renderedDisclosure = screen.getByTestId("disclosure"); + const renderedDisclosureContent = screen.getByTestId("disclosure-content"); - expect(renderedDisclosure.getAttribute('data-paste-element')).toEqual('DISCLOSURE'); - expect(renderedDisclosureHeading.getAttribute('data-paste-element')).toEqual('DISCLOSURE_HEADING'); - expect(renderedDisclosureContent.getAttribute('data-paste-element')).toEqual('DISCLOSURE_CONTENT'); + expect(renderedDisclosure.getAttribute("data-paste-element")).toEqual("DISCLOSURE"); + expect(renderedDisclosureHeading.getAttribute("data-paste-element")).toEqual("DISCLOSURE_HEADING"); + expect(renderedDisclosureContent.getAttribute("data-paste-element")).toEqual("DISCLOSURE_CONTENT"); }); - it('should set a custom element data attribute for custom named Disclosure components', () => { + it("should set a custom element data attribute for custom named Disclosure components", () => { render( - + , ); - const renderedDisclosureHeading = screen.getByTestId('disclosure-heading'); - const renderedDisclosure = screen.getByTestId('disclosure'); - const renderedDisclosureContent = screen.getByTestId('disclosure-content'); + const renderedDisclosureHeading = screen.getByTestId("disclosure-heading"); + const renderedDisclosure = screen.getByTestId("disclosure"); + const renderedDisclosureContent = screen.getByTestId("disclosure-content"); - expect(renderedDisclosure.getAttribute('data-paste-element')).toEqual('MY_DISCLOSURE'); - expect(renderedDisclosureHeading.getAttribute('data-paste-element')).toEqual('MY_DISCLOSURE_HEADING'); - expect(renderedDisclosureContent.getAttribute('data-paste-element')).toEqual('MY_DISCLOSURE_CONTENT'); + expect(renderedDisclosure.getAttribute("data-paste-element")).toEqual("MY_DISCLOSURE"); + expect(renderedDisclosureHeading.getAttribute("data-paste-element")).toEqual("MY_DISCLOSURE_HEADING"); + expect(renderedDisclosureContent.getAttribute("data-paste-element")).toEqual("MY_DISCLOSURE_CONTENT"); }); - it('should add custom styles to Disclosure components', () => { + it("should add custom styles to Disclosure components", () => { render( - + , ); - const renderedDisclosureHeading = screen.getByTestId('disclosure-heading'); + const renderedDisclosureHeading = screen.getByTestId("disclosure-heading"); const renderedDisclosureHeadingIcon = renderedDisclosureHeading.firstChild; - const renderedDisclosure = screen.getByTestId('disclosure'); - const renderedDisclosureContent = screen.getByTestId('disclosure-content'); - - expect(renderedDisclosure).toHaveStyleRule('padding', '2.25rem'); - expect(renderedDisclosureHeading).toHaveStyleRule('color', 'rgb(255, 255, 255)'); - expect(renderedDisclosureHeading).toHaveStyleRule('background-color', 'rgb(117, 12, 12)'); - expect(renderedDisclosureHeadingIcon).toHaveStyleRule('color', 'rgb(214, 31, 31)'); - expect(renderedDisclosureContent).toHaveStyleRule('color', 'rgb(173, 17, 17)'); + const renderedDisclosure = screen.getByTestId("disclosure"); + const renderedDisclosureContent = screen.getByTestId("disclosure-content"); + + expect(renderedDisclosure).toHaveStyleRule("padding", "2.25rem"); + expect(renderedDisclosureHeading).toHaveStyleRule("color", "rgb(255, 255, 255)"); + expect(renderedDisclosureHeading).toHaveStyleRule("background-color", "rgb(117, 12, 12)"); + expect(renderedDisclosureHeadingIcon).toHaveStyleRule("color", "rgb(214, 31, 31)"); + expect(renderedDisclosureContent).toHaveStyleRule("color", "rgb(173, 17, 17)"); }); - it('should add custom styles to custom named Disclosure components', () => { + it("should add custom styles to custom named Disclosure components", () => { render( - + , ); - const renderedDisclosureHeading = screen.getByTestId('disclosure-heading'); + const renderedDisclosureHeading = screen.getByTestId("disclosure-heading"); const renderedDisclosureHeadingIcon = renderedDisclosureHeading.firstChild; - const renderedDisclosure = screen.getByTestId('disclosure'); - const renderedDisclosureContent = screen.getByTestId('disclosure-content'); - - expect(renderedDisclosure).toHaveStyleRule('padding', '2.25rem'); - expect(renderedDisclosureHeading).toHaveStyleRule('color', 'rgb(255, 255, 255)'); - expect(renderedDisclosureHeading).toHaveStyleRule('background-color', 'rgb(117, 12, 12)'); - expect(renderedDisclosureHeadingIcon).toHaveStyleRule('color', 'rgb(214, 31, 31)'); - expect(renderedDisclosureContent).toHaveStyleRule('color', 'rgb(173, 17, 17)'); + const renderedDisclosure = screen.getByTestId("disclosure"); + const renderedDisclosureContent = screen.getByTestId("disclosure-content"); + + expect(renderedDisclosure).toHaveStyleRule("padding", "2.25rem"); + expect(renderedDisclosureHeading).toHaveStyleRule("color", "rgb(255, 255, 255)"); + expect(renderedDisclosureHeading).toHaveStyleRule("background-color", "rgb(117, 12, 12)"); + expect(renderedDisclosureHeadingIcon).toHaveStyleRule("color", "rgb(214, 31, 31)"); + expect(renderedDisclosureContent).toHaveStyleRule("color", "rgb(173, 17, 17)"); }); }); }); diff --git a/packages/paste-core/components/disclosure/build.js b/packages/paste-core/components/disclosure/build.js index a4edeab49b..27dd98f98e 100644 --- a/packages/paste-core/components/disclosure/build.js +++ b/packages/paste-core/components/disclosure/build.js @@ -1,3 +1,3 @@ -const {build} = require('../../../../tools/build/esbuild'); +const { build } = require("../../../../tools/build/esbuild"); -build(require('./package.json')); +build(require("./package.json")); diff --git a/packages/paste-core/components/disclosure/src/Disclosure.tsx b/packages/paste-core/components/disclosure/src/Disclosure.tsx index d122ac1088..0ece8e8714 100644 --- a/packages/paste-core/components/disclosure/src/Disclosure.tsx +++ b/packages/paste-core/components/disclosure/src/Disclosure.tsx @@ -1,21 +1,21 @@ -import * as React from 'react'; -import {useDisclosurePrimitiveState} from '@twilio-paste/disclosure-primitive'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; -import type {DisclosurePrimitiveInitialState} from '@twilio-paste/disclosure-primitive'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import { useDisclosurePrimitiveState } from "@twilio-paste/disclosure-primitive"; +import type { DisclosurePrimitiveInitialState } from "@twilio-paste/disclosure-primitive"; +import * as React from "react"; -import {DisclosureContext} from './DisclosureContext'; -import type {DisclosureVariants, DisclosureStateReturn} from './types'; +import { DisclosureContext } from "./DisclosureContext"; +import type { DisclosureStateReturn, DisclosureVariants } from "./types"; -export interface DisclosureProps extends DisclosurePrimitiveInitialState, Pick { +export interface DisclosureProps extends DisclosurePrimitiveInitialState, Pick { children: NonNullable; state?: DisclosureStateReturn; variant?: DisclosureVariants; } const Disclosure = React.forwardRef( - ({children, element = 'DISCLOSURE', variant = 'default', state, ...props}, ref) => { - const disclosure = state || useDisclosurePrimitiveState({animated: true, ...props}); + ({ children, element = "DISCLOSURE", variant = "default", state, ...props }, ref) => { + const disclosure = state || useDisclosurePrimitiveState({ animated: true, ...props }); const [isDisabled, setIsDisabled] = React.useState(false); const [isHeadingHovered, setIsHeadingHovered] = React.useState(false); @@ -35,10 +35,10 @@ const Disclosure = React.forwardRef( ); - } + }, ); -Disclosure.displayName = 'Disclosure'; +Disclosure.displayName = "Disclosure"; -export {Disclosure}; +export { Disclosure }; -export {useDisclosurePrimitiveState as useDisclosureState}; +export { useDisclosurePrimitiveState as useDisclosureState }; diff --git a/packages/paste-core/components/disclosure/src/DisclosureContent.tsx b/packages/paste-core/components/disclosure/src/DisclosureContent.tsx index 8acf61b22f..78229df25a 100644 --- a/packages/paste-core/components/disclosure/src/DisclosureContent.tsx +++ b/packages/paste-core/components/disclosure/src/DisclosureContent.tsx @@ -1,43 +1,43 @@ -import * as React from 'react'; -import {useSpring, animated} from '@twilio-paste/animation-library'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import {DisclosurePrimitiveContent} from '@twilio-paste/disclosure-primitive'; -import type {BoxProps, BoxStyleProps} from '@twilio-paste/box'; -import type {DisclosurePrimitiveContentProps} from '@twilio-paste/disclosure-primitive'; +import { animated, useSpring } from "@twilio-paste/animation-library"; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps, BoxStyleProps } from "@twilio-paste/box"; +import { DisclosurePrimitiveContent } from "@twilio-paste/disclosure-primitive"; +import type { DisclosurePrimitiveContentProps } from "@twilio-paste/disclosure-primitive"; +import * as React from "react"; -import {DisclosureContext} from './DisclosureContext'; +import { DisclosureContext } from "./DisclosureContext"; export const AnimatedDisclosureContent = animated(Box); const baseContainedStyles: BoxStyleProps = { - borderWidth: 'borderWidth10', - borderStyle: 'solid', - borderBottomLeftRadius: 'borderRadius20', - borderBottomRightRadius: 'borderRadius20', - borderTop: 'none', - transition: 'border-color 100ms ease-out', + borderWidth: "borderWidth10", + borderStyle: "solid", + borderBottomLeftRadius: "borderRadius20", + borderBottomRightRadius: "borderRadius20", + borderTop: "none", + transition: "border-color 100ms ease-out", }; const containedStyles: BoxStyleProps = { ...baseContainedStyles, - borderColor: 'colorBorderWeaker', + borderColor: "colorBorderWeaker", }; const containedHoverStyles: BoxStyleProps = { ...baseContainedStyles, - borderColor: 'colorBorderWeak', + borderColor: "colorBorderWeak", }; export interface DisclosureContentProps extends Omit, - Pick { + Pick { children: NonNullable; } const DisclosureContent = React.forwardRef( - ({children, element = 'DISCLOSURE_CONTENT', visible, ...props}, ref) => { - const {disclosure, variant, isHeadingHovered, isDisabled} = React.useContext(DisclosureContext); - const {opacity} = useSpring({ + ({ children, element = "DISCLOSURE_CONTENT", visible, ...props }, ref) => { + const { disclosure, variant, isHeadingHovered, isDisabled } = React.useContext(DisclosureContext); + const { opacity } = useSpring({ opacity: disclosure.visible ? 1 : 0, onRest: disclosure.stopAnimation, config: { @@ -49,7 +49,7 @@ const DisclosureContent = React.forwardRef ); - } + }, ); -DisclosureContent.displayName = 'DisclosureContent'; +DisclosureContent.displayName = "DisclosureContent"; -export {DisclosureContent}; +export { DisclosureContent }; diff --git a/packages/paste-core/components/disclosure/src/DisclosureContext.tsx b/packages/paste-core/components/disclosure/src/DisclosureContext.tsx index 5503fe3e60..c19d4633fe 100644 --- a/packages/paste-core/components/disclosure/src/DisclosureContext.tsx +++ b/packages/paste-core/components/disclosure/src/DisclosureContext.tsx @@ -1,7 +1,7 @@ -import * as React from 'react'; -import type {DisclosurePrimitveStateReturn} from '@twilio-paste/disclosure-primitive'; +import type { DisclosurePrimitveStateReturn } from "@twilio-paste/disclosure-primitive"; +import * as React from "react"; -import type {DisclosureVariants} from './types'; +import type { DisclosureVariants } from "./types"; export interface DisclosureContextProps { disclosure: DisclosurePrimitveStateReturn; @@ -14,4 +14,4 @@ export interface DisclosureContextProps { const DisclosureContext = React.createContext({} as any); -export {DisclosureContext}; +export { DisclosureContext }; diff --git a/packages/paste-core/components/disclosure/src/DisclosureHeading.tsx b/packages/paste-core/components/disclosure/src/DisclosureHeading.tsx index e4ca017ab3..69bdfd5938 100644 --- a/packages/paste-core/components/disclosure/src/DisclosureHeading.tsx +++ b/packages/paste-core/components/disclosure/src/DisclosureHeading.tsx @@ -1,35 +1,35 @@ -import * as React from 'react'; -import {useTheme} from '@twilio-paste/theme'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import {Heading} from '@twilio-paste/heading'; -import {ChevronDisclosureIcon} from '@twilio-paste/icons/esm/ChevronDisclosureIcon'; -import {DisclosurePrimitive} from '@twilio-paste/disclosure-primitive'; -import type {BoxProps, BoxStyleProps} from '@twilio-paste/box'; -import type {HeadingProps} from '@twilio-paste/heading'; -import type {DisclosurePrimitiveProps} from '@twilio-paste/disclosure-primitive'; - -import {DisclosureContext} from './DisclosureContext'; -import type {DisclosureVariants} from './types'; -import {IconSizeFromHeading} from './constants'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps, BoxStyleProps } from "@twilio-paste/box"; +import { DisclosurePrimitive } from "@twilio-paste/disclosure-primitive"; +import type { DisclosurePrimitiveProps } from "@twilio-paste/disclosure-primitive"; +import { Heading } from "@twilio-paste/heading"; +import type { HeadingProps } from "@twilio-paste/heading"; +import { ChevronDisclosureIcon } from "@twilio-paste/icons/esm/ChevronDisclosureIcon"; +import { useTheme } from "@twilio-paste/theme"; +import * as React from "react"; + +import { DisclosureContext } from "./DisclosureContext"; +import { IconSizeFromHeading } from "./constants"; +import type { DisclosureVariants } from "./types"; const baseContainedStyles: BoxStyleProps = { - borderWidth: 'borderWidth10', - borderStyle: 'solid', - borderRadius: 'borderRadius20', + borderWidth: "borderWidth10", + borderStyle: "solid", + borderRadius: "borderRadius20", }; const containedStyles: BoxStyleProps = { ...baseContainedStyles, - borderColor: 'colorBorderWeaker', + borderColor: "colorBorderWeaker", }; const containedHoverStyles: BoxStyleProps = { ...baseContainedStyles, - borderColor: 'colorBorderWeak', + borderColor: "colorBorderWeak", }; -export interface StyledDisclosureHeadingProps extends Omit, Pick { - renderAs: HeadingProps['as']; +export interface StyledDisclosureHeadingProps extends Omit, Pick { + renderAs: HeadingProps["as"]; customDisabled?: boolean; customFocusable?: boolean; disclosureVariant: DisclosureVariants; @@ -57,12 +57,12 @@ const StyledDisclosureHeading = React.forwardRef { const theme = useTheme(); - const disabledProp = props['aria-disabled']; - const isExpanded = props['aria-expanded']; - const iconSize = IconSizeFromHeading[variant] || 'sizeIcon20'; + const disabledProp = props["aria-disabled"]; + const isExpanded = props["aria-expanded"]; + const iconSize = IconSizeFromHeading[variant] || "sizeIcon20"; const shouldIconMove = isHovered && !isDisabled; const buttonRef = React.useRef(null); @@ -77,17 +77,17 @@ const StyledDisclosureHeading = React.forwardRef { - node.removeEventListener('mouseover', handleMouseOver); - node.removeEventListener('mouseout', handleMouseOut); + node.removeEventListener("mouseover", handleMouseOver); + node.removeEventListener("mouseout", handleMouseOut); }; } }, [buttonRef, setIsHovered]); let variantStyles: BoxStyleProps = {}; - if (disclosureVariant === 'contained') { + if (disclosureVariant === "contained") { variantStyles = containedStyles; if (isHovered && !isDisabled) { variantStyles = containedHoverStyles; @@ -96,9 +96,9 @@ const StyledDisclosureHeading = React.forwardRef @@ -137,13 +137,13 @@ const StyledDisclosureHeading = React.forwardRef @@ -151,29 +151,29 @@ const StyledDisclosureHeading = React.forwardRef ); - } + }, ); -StyledDisclosureHeading.displayName = 'StyledDisclosureHeading'; +StyledDisclosureHeading.displayName = "StyledDisclosureHeading"; export interface DisclosureHeadingProps - extends Omit, - Pick { + extends Omit, + Pick { children: NonNullable; - as: HeadingProps['as']; - marginBottom?: HeadingProps['marginBottom']; - variant: HeadingProps['variant']; + as: HeadingProps["as"]; + marginBottom?: HeadingProps["marginBottom"]; + variant: HeadingProps["variant"]; } const DisclosureHeading: React.FC> = ({ children, as, - element = 'DISCLOSURE_HEADING', + element = "DISCLOSURE_HEADING", disabled, focusable, ...props }) => { - const {disclosure, variant, setIsDisabled, setIsHeadingHovered, isHeadingHovered, isDisabled} = + const { disclosure, variant, setIsDisabled, setIsHeadingHovered, isHeadingHovered, isDisabled } = React.useContext(DisclosureContext); return ( > = (props) => { return ( @@ -50,7 +50,10 @@ export const ExampleDisclosures: React.FC< interface UseDelayedDisclosureStateProps extends DisclosureInitialState { delay: number; } -const useDelayedDisclosureState = ({delay, ...initialState}: UseDelayedDisclosureStateProps): DisclosureStateReturn => { +const useDelayedDisclosureState = ({ + delay, + ...initialState +}: UseDelayedDisclosureStateProps): DisclosureStateReturn => { const disclosure = useDisclosureState(initialState); const [transitioning, setTransitioning] = React.useState(false); return { @@ -68,48 +71,48 @@ const useDelayedDisclosureState = ({delay, ...initialState}: UseDelayedDisclosur // eslint-disable-next-line import/no-default-export export default { - title: 'Components/Disclosure', + title: "Components/Disclosure", decorators: [], - excludeStories: ['ExampleDisclosures'], + excludeStories: ["ExampleDisclosures"], component: Disclosure, - subcomponents: {DisclosureHeading, DisclosureContent}, + subcomponents: { DisclosureHeading, DisclosureContent }, }; export const HeadingVariant10 = (): React.ReactNode => { return ; }; -HeadingVariant10.storyName = 'Heading variant 10'; +HeadingVariant10.storyName = "Heading variant 10"; export const HeadingVariant20 = (): React.ReactNode => { return ; }; -HeadingVariant20.storyName = 'Heading variant 20'; +HeadingVariant20.storyName = "Heading variant 20"; export const HeadingVariant30 = (): React.ReactNode => { return ; }; -HeadingVariant30.storyName = 'Heading variant 30'; +HeadingVariant30.storyName = "Heading variant 30"; export const HeadingVariant40 = (): React.ReactNode => { return ; }; -HeadingVariant40.storyName = 'Heading variant 40'; +HeadingVariant40.storyName = "Heading variant 40"; export const HeadingVariant50 = (): React.ReactNode => { return ; }; -HeadingVariant50.storyName = 'Heading variant 50'; +HeadingVariant50.storyName = "Heading variant 50"; export const HeadingVariant60 = (): React.ReactNode => { return ; }; -HeadingVariant60.storyName = 'Heading variant 60'; +HeadingVariant60.storyName = "Heading variant 60"; export const Disabled = (): React.ReactNode => { return ; @@ -148,7 +151,7 @@ export const MultilineHeading = (): React.ReactNode => { ); }; -MultilineHeading.storyName = 'Multiline heading'; +MultilineHeading.storyName = "Multiline heading"; export const TruncatedHeader = (): React.ReactNode => { return ( @@ -170,7 +173,7 @@ export const TruncatedHeader = (): React.ReactNode => { ); }; -TruncatedHeader.storyName = 'Truncated Header'; +TruncatedHeader.storyName = "Truncated Header"; export const MediaObjectHeading = (): React.ReactNode => { return ( @@ -195,49 +198,49 @@ export const MediaObjectHeading = (): React.ReactNode => { ); }; -MediaObjectHeading.storyName = 'MediaObject in Heading'; +MediaObjectHeading.storyName = "MediaObject in Heading"; export const ContainedHeadingVariant10 = (): React.ReactNode => { return ; }; -ContainedHeadingVariant10.storyName = 'Contained Heading variant 10'; +ContainedHeadingVariant10.storyName = "Contained Heading variant 10"; export const ContainedHeadingVariant20 = (): React.ReactNode => { return ; }; -ContainedHeadingVariant20.storyName = 'Contained Heading variant 20'; +ContainedHeadingVariant20.storyName = "Contained Heading variant 20"; export const ContainedHeadingVariant30 = (): React.ReactNode => { return ; }; -ContainedHeadingVariant30.storyName = 'Contained Heading variant 30'; +ContainedHeadingVariant30.storyName = "Contained Heading variant 30"; export const ContainedHeadingVariant40 = (): React.ReactNode => { return ; }; -ContainedHeadingVariant40.storyName = 'Contained Heading variant 40'; +ContainedHeadingVariant40.storyName = "Contained Heading variant 40"; export const ContainedHeadingVariant50 = (): React.ReactNode => { return ; }; -ContainedHeadingVariant50.storyName = 'Contained Heading variant 50'; +ContainedHeadingVariant50.storyName = "Contained Heading variant 50"; export const ContainedHeadingVariant60 = (): React.ReactNode => { return ; }; -ContainedHeadingVariant60.storyName = 'Contained Heading variant 60'; +ContainedHeadingVariant60.storyName = "Contained Heading variant 60"; export const ContainedDisabled = (): React.ReactNode => { return ; }; -ContainedDisabled.storyName = 'Contained disabled'; +ContainedDisabled.storyName = "Contained disabled"; export const ContainedMultilineHeading = (): React.ReactNode => { return ( @@ -272,19 +275,19 @@ export const ContainedMultilineHeading = (): React.ReactNode => { ); }; -ContainedMultilineHeading.storyName = 'Contained multiline heading'; +ContainedMultilineHeading.storyName = "Contained multiline heading"; export const StateHook = (): React.ReactNode => { - const {transitioning, ...disclosure} = useDelayedDisclosureState({ + const { transitioning, ...disclosure } = useDelayedDisclosureState({ delay: 500, }); - const clickableHeading = disclosure.visible ? 'Hide with delay' : 'Show with delay'; + const clickableHeading = disclosure.visible ? "Hide with delay" : "Show with delay"; return ( <> This Disclosure should be visible on load, and take 1 second to open and close. - {transitioning ? 'Please wait...' : clickableHeading} + {transitioning ? "Please wait..." : clickableHeading} Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Fusce dapibus, tellus ac cursus @@ -297,24 +300,24 @@ export const StateHook = (): React.ReactNode => { ); }; -StateHook.storyName = 'State hook'; +StateHook.storyName = "State hook"; -export const Customization: StoryFn = (_args, {parameters: {isTestEnvironment}}) => { +export const Customization: StoryFn = (_args, { parameters: { isTestEnvironment } }) => { const currentTheme = useTheme(); return ( diff --git a/packages/paste-core/components/display-heading/__tests__/index.spec.tsx b/packages/paste-core/components/display-heading/__tests__/index.spec.tsx index 7df54661ff..0a68ea3a0d 100644 --- a/packages/paste-core/components/display-heading/__tests__/index.spec.tsx +++ b/packages/paste-core/components/display-heading/__tests__/index.spec.tsx @@ -1,36 +1,36 @@ -import * as React from 'react'; -import {render, screen} from '@testing-library/react'; -import {CustomizationProvider} from '@twilio-paste/customization'; -import {Theme} from '@twilio-paste/theme'; +import { render, screen } from "@testing-library/react"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import { Theme } from "@twilio-paste/theme"; +import * as React from "react"; -import {DisplayHeading} from '../src'; +import { DisplayHeading } from "../src"; -describe('DisplayHeading', () => { +describe("DisplayHeading", () => { it('should render as an h1 when passed as="h1', () => { render( test - + , ); - const renderedDisplayHeading = screen.getByRole('heading', {level: 1}); + const renderedDisplayHeading = screen.getByRole("heading", { level: 1 }); expect(renderedDisplayHeading).toBeDefined(); }); it('should render as an h2 when passed as="h2', () => { render( test - + , ); - const renderedDisplayHeading = screen.getByRole('heading', {level: 2}); + const renderedDisplayHeading = screen.getByRole("heading", { level: 2 }); expect(renderedDisplayHeading).toBeDefined(); }); it('should render as an h3 when passed as="h3', () => { render( test - + , ); - const renderedDisplayHeading = screen.getByRole('heading', {level: 3}); + const renderedDisplayHeading = screen.getByRole("heading", { level: 3 }); expect(renderedDisplayHeading).toBeDefined(); }); it('should remove bottom margin when passed margin="space0', () => { @@ -39,56 +39,56 @@ describe('DisplayHeading', () => { test - + , ); - const renderedDisplayHeading = screen.getByRole('heading', {level: 3}); - expect(renderedDisplayHeading).toHaveStyleRule('margin-bottom', '0'); + const renderedDisplayHeading = screen.getByRole("heading", { level: 3 }); + expect(renderedDisplayHeading).toHaveStyleRule("margin-bottom", "0"); }); }); -describe('Customization', () => { - it('should set a data paste element attribute on Display Heading', () => { +describe("Customization", () => { + it("should set a data paste element attribute on Display Heading", () => { render( test - + , ); - const renderedDisplayHeading = screen.getByRole('heading', {level: 3}); - expect(renderedDisplayHeading.getAttribute('data-paste-element')).toEqual('DISPLAY_HEADING'); + const renderedDisplayHeading = screen.getByRole("heading", { level: 3 }); + expect(renderedDisplayHeading.getAttribute("data-paste-element")).toEqual("DISPLAY_HEADING"); }); - it('should set a custom data paste element attribute on Display Heading', () => { + it("should set a custom data paste element attribute on Display Heading", () => { render( test - + , ); - const renderedDisplayHeading = screen.getByRole('heading', {level: 3}); - expect(renderedDisplayHeading.getAttribute('data-paste-element')).toEqual('foo'); + const renderedDisplayHeading = screen.getByRole("heading", { level: 3 }); + expect(renderedDisplayHeading.getAttribute("data-paste-element")).toEqual("foo"); }); - it('should add custom styles to Display Heading', () => { + it("should add custom styles to Display Heading", () => { render( test - + , ); - const renderedDisplayHeading = screen.getByRole('heading', {level: 1}); - expect(renderedDisplayHeading).toHaveStyleRule('color', 'rgb(96, 107, 133)'); + const renderedDisplayHeading = screen.getByRole("heading", { level: 1 }); + expect(renderedDisplayHeading).toHaveStyleRule("color", "rgb(96, 107, 133)"); }); - it('should add custom styles to a custom named Display Heading', () => { + it("should add custom styles to a custom named Display Heading", () => { render( - + test - + , ); - const renderedDisplayHeading = screen.getByRole('heading', {level: 1}); - expect(renderedDisplayHeading).toHaveStyleRule('color', 'rgb(96, 107, 133)'); + const renderedDisplayHeading = screen.getByRole("heading", { level: 1 }); + expect(renderedDisplayHeading).toHaveStyleRule("color", "rgb(96, 107, 133)"); }); }); diff --git a/packages/paste-core/components/display-heading/build.js b/packages/paste-core/components/display-heading/build.js index a4edeab49b..27dd98f98e 100644 --- a/packages/paste-core/components/display-heading/build.js +++ b/packages/paste-core/components/display-heading/build.js @@ -1,3 +1,3 @@ -const {build} = require('../../../../tools/build/esbuild'); +const { build } = require("../../../../tools/build/esbuild"); -build(require('./package.json')); +build(require("./package.json")); diff --git a/packages/paste-core/components/display-heading/src/index.tsx b/packages/paste-core/components/display-heading/src/index.tsx index 23231385fe..fa7509a9cc 100644 --- a/packages/paste-core/components/display-heading/src/index.tsx +++ b/packages/paste-core/components/display-heading/src/index.tsx @@ -1,52 +1,52 @@ -import * as React from 'react'; -import {Text, safelySpreadTextProps} from '@twilio-paste/text'; -import type {TextProps, TextStyleProps} from '@twilio-paste/text'; -import type {HTMLPasteProps} from '@twilio-paste/types'; +import { Text, safelySpreadTextProps } from "@twilio-paste/text"; +import type { TextProps, TextStyleProps } from "@twilio-paste/text"; +import type { HTMLPasteProps } from "@twilio-paste/types"; +import * as React from "react"; -type DisplayHeadingVariants = 'displayHeading10' | 'displayHeading20' | 'displayHeading30'; -type AsTags = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'div' | 'span' | 'header'; +type DisplayHeadingVariants = "displayHeading10" | "displayHeading20" | "displayHeading30"; +type AsTags = "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "div" | "span" | "header"; export interface DisplayHeadingProps - extends HTMLPasteProps<'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'div' | 'span' | 'header'>, - Pick { + extends HTMLPasteProps<"h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "div" | "span" | "header">, + Pick { as: AsTags; id?: string; - marginBottom?: 'space0'; + marginBottom?: "space0"; variant: DisplayHeadingVariants; } const getDisplayHeadingProps = ( displayHeadingVariant?: DisplayHeadingVariants, - marginBottom?: 'space0' + marginBottom?: "space0", ): TextStyleProps => { switch (displayHeadingVariant) { - case 'displayHeading10': + case "displayHeading10": return { - marginBottom: marginBottom || 'space170', - fontSize: 'fontSizeDisplay30', - fontWeight: 'fontWeightExtrabold', - lineHeight: 'lineHeightDisplay30', + marginBottom: marginBottom || "space170", + fontSize: "fontSizeDisplay30", + fontWeight: "fontWeightExtrabold", + lineHeight: "lineHeightDisplay30", }; - case 'displayHeading30': + case "displayHeading30": return { - marginBottom: marginBottom || 'space90', - fontSize: 'fontSizeDisplay10', - fontWeight: 'fontWeightExtrabold', - lineHeight: 'lineHeightDisplay10', + marginBottom: marginBottom || "space90", + fontSize: "fontSizeDisplay10", + fontWeight: "fontWeightExtrabold", + lineHeight: "lineHeightDisplay10", }; - case 'displayHeading20': + case "displayHeading20": default: return { - marginBottom: marginBottom || 'space130', - fontSize: 'fontSizeDisplay20', - fontWeight: 'fontWeightExtrabold', - lineHeight: 'lineHeightDisplay20', + marginBottom: marginBottom || "space130", + fontSize: "fontSizeDisplay20", + fontWeight: "fontWeightExtrabold", + lineHeight: "lineHeightDisplay20", }; } }; const DisplayHeading = React.forwardRef( - ({element = 'DISPLAY_HEADING', as, children, display = 'block', id, marginBottom, variant, ...props}, ref) => { + ({ element = "DISPLAY_HEADING", as, children, display = "block", id, marginBottom, variant, ...props }, ref) => { return ( {children} ); - } + }, ); -DisplayHeading.displayName = 'DisplayHeading'; +DisplayHeading.displayName = "DisplayHeading"; -export {DisplayHeading}; +export { DisplayHeading }; diff --git a/packages/paste-core/components/display-heading/stories/index.stories.tsx b/packages/paste-core/components/display-heading/stories/index.stories.tsx index 72393d8b5b..e65ea43043 100644 --- a/packages/paste-core/components/display-heading/stories/index.stories.tsx +++ b/packages/paste-core/components/display-heading/stories/index.stories.tsx @@ -1,12 +1,12 @@ -import * as React from 'react'; -import {CustomizationProvider} from '@twilio-paste/customization'; -import {useTheme} from '@twilio-paste/theme'; +import { CustomizationProvider } from "@twilio-paste/customization"; +import { useTheme } from "@twilio-paste/theme"; +import * as React from "react"; -import {DisplayHeading} from '../src'; +import { DisplayHeading } from "../src"; // eslint-disable-next-line import/no-default-export export default { - title: 'Components/Display Heading', + title: "Components/Display Heading", component: DisplayHeading, }; @@ -53,7 +53,7 @@ export const DisplayHeading30 = (): React.ReactNode => { export const Customization = (): React.ReactNode => { const theme = useTheme(); return ( - + Display Heading with customization diff --git a/packages/paste-core/components/display-pill-group/__tests__/index.spec.tsx b/packages/paste-core/components/display-pill-group/__tests__/index.spec.tsx index 26a8565c43..fe44540c2a 100644 --- a/packages/paste-core/components/display-pill-group/__tests__/index.spec.tsx +++ b/packages/paste-core/components/display-pill-group/__tests__/index.spec.tsx @@ -1,86 +1,86 @@ -import * as React from 'react'; -import {render} from '@testing-library/react'; -import {CustomizationProvider} from '@twilio-paste/customization'; +import { render } from "@testing-library/react"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import * as React from "react"; -import {DisplayPillGroup, DisplayPill} from '../src'; -import {Basic} from '../stories/index.stories'; -import {CustomDisplayPillGroup} from '../stories/customization.stories'; +import { DisplayPill, DisplayPillGroup } from "../src"; +import { CustomDisplayPillGroup } from "../stories/customization.stories"; +import { Basic } from "../stories/index.stories"; -describe('DisplayPillGroup', () => { +describe("DisplayPillGroup", () => { // Verifies that the correct aria attributes and semantics are met - describe('Rendered shape', () => { - it('should render correctly', () => { - const {getByTestId, getByText} = render(); - expect(getByText('Tennis')).toBeDefined(); + describe("Rendered shape", () => { + it("should render correctly", () => { + const { getByTestId, getByText } = render(); + expect(getByText("Tennis")).toBeDefined(); - const group = getByTestId('display-pill-group'); - expect(group.getAttribute('aria-label')).toBe('Your favorite sports:'); - expect(group.tagName).toBe('UL'); + const group = getByTestId("display-pill-group"); + expect(group.getAttribute("aria-label")).toBe("Your favorite sports:"); + expect(group.tagName).toBe("UL"); - const pillLink = getByTestId('display-pill-anchor'); - expect(pillLink.getAttribute('href')).toBe('https://google.com'); - expect(pillLink.getAttribute('rel')).toBe('noreferrer noopener'); - expect(pillLink.getAttribute('target')).toBe('_blank'); - expect(pillLink.tagName).toBe('A'); + const pillLink = getByTestId("display-pill-anchor"); + expect(pillLink.getAttribute("href")).toBe("https://google.com"); + expect(pillLink.getAttribute("rel")).toBe("noreferrer noopener"); + expect(pillLink.getAttribute("target")).toBe("_blank"); + expect(pillLink.tagName).toBe("A"); - const pillStandard = getByTestId('display-pill-standard'); - expect(pillStandard.tagName).toBe('DIV'); + const pillStandard = getByTestId("display-pill-standard"); + expect(pillStandard.tagName).toBe("DIV"); }); }); // Verifies the component is fully customizable - describe('Customization', () => { - it('should set an element data attribute for DisplayPillGroup & DisplayPill', () => { - const {getByTestId} = render(); - const group = getByTestId('display-pill-group'); - expect(group.getAttribute('data-paste-element')).toEqual('DISPLAY_PILL_GROUP'); + describe("Customization", () => { + it("should set an element data attribute for DisplayPillGroup & DisplayPill", () => { + const { getByTestId } = render(); + const group = getByTestId("display-pill-group"); + expect(group.getAttribute("data-paste-element")).toEqual("DISPLAY_PILL_GROUP"); - const pillLink = getByTestId('display-pill-anchor'); - expect(pillLink.getAttribute('data-paste-element')).toEqual('DISPLAY_PILL'); + const pillLink = getByTestId("display-pill-anchor"); + expect(pillLink.getAttribute("data-paste-element")).toEqual("DISPLAY_PILL"); - const pillStandard = getByTestId('display-pill-standard'); - expect(pillStandard.getAttribute('data-paste-element')).toEqual('DISPLAY_PILL'); + const pillStandard = getByTestId("display-pill-standard"); + expect(pillStandard.getAttribute("data-paste-element")).toEqual("DISPLAY_PILL"); }); - it('should set a custom element data attribute for DisplayPillGroup & DisplayPill', () => { - const {getByTestId} = render( + it("should set a custom element data attribute for DisplayPillGroup & DisplayPill", () => { + const { getByTestId } = render( A - + , ); - const group = getByTestId('group'); - expect(group.getAttribute('data-paste-element')).toEqual('CUSTOM_GROUP'); - const pill = getByTestId('pill'); - expect(pill.getAttribute('data-paste-element')).toEqual('CUSTOM_PILL'); + const group = getByTestId("group"); + expect(group.getAttribute("data-paste-element")).toEqual("CUSTOM_GROUP"); + const pill = getByTestId("pill"); + expect(pill.getAttribute("data-paste-element")).toEqual("CUSTOM_PILL"); }); - it('should add custom styles to DisplayPillGroup & DisplayPill', () => { - const {getByTestId} = render(); + it("should add custom styles to DisplayPillGroup & DisplayPill", () => { + const { getByTestId } = render(); - const group = getByTestId('display-pill-group'); - expect(group).toHaveStyleRule('margin', '0.75rem'); + const group = getByTestId("display-pill-group"); + expect(group).toHaveStyleRule("margin", "0.75rem"); - const pillLink = getByTestId('display-pill-anchor'); - expect(pillLink).toHaveStyleRule('background-color', 'rgb(245, 240, 252)'); + const pillLink = getByTestId("display-pill-anchor"); + expect(pillLink).toHaveStyleRule("background-color", "rgb(245, 240, 252)"); - const pillStandard = getByTestId('display-pill-standard'); - expect(pillStandard).toHaveStyleRule('background-color', 'rgb(245, 240, 252)'); + const pillStandard = getByTestId("display-pill-standard"); + expect(pillStandard).toHaveStyleRule("background-color", "rgb(245, 240, 252)"); }); - it('should add custom styles to custom element DisplayPillGroup & DisplayPill', () => { - const {getByTestId} = render( + it("should add custom styles to custom element DisplayPillGroup & DisplayPill", () => { + const { getByTestId } = render( @@ -96,16 +96,16 @@ describe('DisplayPillGroup', () => { Football - + , ); - const group = getByTestId('display-pill-group'); - expect(group).toHaveStyleRule('margin', '0.75rem'); + const group = getByTestId("display-pill-group"); + expect(group).toHaveStyleRule("margin", "0.75rem"); - const pillLink = getByTestId('display-pill-anchor'); - expect(pillLink).toHaveStyleRule('background-color', 'rgb(231, 220, 250)'); + const pillLink = getByTestId("display-pill-anchor"); + expect(pillLink).toHaveStyleRule("background-color", "rgb(231, 220, 250)"); - const pillStandard = getByTestId('display-pill-standard'); - expect(pillStandard).toHaveStyleRule('background-color', 'rgb(231, 220, 250)'); + const pillStandard = getByTestId("display-pill-standard"); + expect(pillStandard).toHaveStyleRule("background-color", "rgb(231, 220, 250)"); }); }); }); diff --git a/packages/paste-core/components/display-pill-group/build.js b/packages/paste-core/components/display-pill-group/build.js index a4edeab49b..27dd98f98e 100644 --- a/packages/paste-core/components/display-pill-group/build.js +++ b/packages/paste-core/components/display-pill-group/build.js @@ -1,3 +1,3 @@ -const {build} = require('../../../../tools/build/esbuild'); +const { build } = require("../../../../tools/build/esbuild"); -build(require('./package.json')); +build(require("./package.json")); diff --git a/packages/paste-core/components/display-pill-group/src/DisplayPill.tsx b/packages/paste-core/components/display-pill-group/src/DisplayPill.tsx index 9e4cd84b79..97e7007df6 100644 --- a/packages/paste-core/components/display-pill-group/src/DisplayPill.tsx +++ b/packages/paste-core/components/display-pill-group/src/DisplayPill.tsx @@ -1,10 +1,10 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxElementProps} from '@twilio-paste/box'; -import type {HTMLPasteProps} from '@twilio-paste/types'; -import {secureExternalLink} from '@twilio-paste/anchor'; +import { secureExternalLink } from "@twilio-paste/anchor"; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxElementProps } from "@twilio-paste/box"; +import type { HTMLPasteProps } from "@twilio-paste/types"; +import * as React from "react"; -type DisplayPillProps = HTMLPasteProps<'a'> & Pick; +type DisplayPillProps = HTMLPasteProps<"a"> & Pick; /** * Display represents a saved entity as part of a collection, usually as a result of multi selection. @@ -24,7 +24,7 @@ type DisplayPillProps = HTMLPasteProps<'a'> & Pick; * @see https://paste.twilio.design/components/display-pill-group */ export const DisplayPill = React.forwardRef( - ({element = 'DISPLAY_PILL', ...props}, ref) => { + ({ element = "DISPLAY_PILL", ...props }, ref) => { return ( {...(props.href ? secureExternalLink(props.href) : {})} ref={ref} element={element} - as={props.href ? 'a' : 'div'} + as={props.href ? "a" : "div"} alignItems="center" backgroundColor="colorBackgroundWeak" borderRadius="borderRadiusPill" boxShadow="shadowBorderWeaker" color="colorTextWeak" columnGap="space20" - cursor={props.href ? 'pointer' : 'default'} + cursor={props.href ? "pointer" : "default"} display="flex" fontSize="fontSize20" fontWeight="fontWeightMedium" @@ -50,22 +50,22 @@ export const DisplayPill = React.forwardRef _hover={ props.href ? { - backgroundColor: 'colorBackground', - boxShadow: 'shadowBorder', - textDecoration: 'none', + backgroundColor: "colorBackground", + boxShadow: "shadowBorder", + textDecoration: "none", } : undefined } _focus={{ - boxShadow: 'shadowFocus', - textDecoration: 'none', + boxShadow: "shadowFocus", + textDecoration: "none", }} > {props.children} ); - } + }, ); -DisplayPill.displayName = 'DisplayPill'; +DisplayPill.displayName = "DisplayPill"; diff --git a/packages/paste-core/components/display-pill-group/src/DisplayPillGroup.tsx b/packages/paste-core/components/display-pill-group/src/DisplayPillGroup.tsx index a5de1d1219..85efdfdd28 100644 --- a/packages/paste-core/components/display-pill-group/src/DisplayPillGroup.tsx +++ b/packages/paste-core/components/display-pill-group/src/DisplayPillGroup.tsx @@ -1,9 +1,9 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {HTMLPasteProps} from '@twilio-paste/types'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { HTMLPasteProps } from "@twilio-paste/types"; +import * as React from "react"; -export interface DisplayPillGroupProps extends HTMLPasteProps<'ol'> { - 'aria-label': string; +export interface DisplayPillGroupProps extends HTMLPasteProps<"ol"> { + "aria-label": string; element?: string; children: React.ReactNode; } @@ -18,7 +18,7 @@ export interface DisplayPillGroupProps extends HTMLPasteProps<'ol'> { * @see https://paste.twilio.design/components/display-pill-group */ export const DisplayPillGroup = React.forwardRef( - ({element = 'DISPLAY_PILL_GROUP', ...props}, ref) => { + ({ element = "DISPLAY_PILL_GROUP", ...props }, ref) => { return ( ); - } + }, ); -DisplayPillGroup.displayName = 'DisplayPillGroup'; +DisplayPillGroup.displayName = "DisplayPillGroup"; diff --git a/packages/paste-core/components/display-pill-group/src/index.tsx b/packages/paste-core/components/display-pill-group/src/index.tsx index 0bde4551f5..c9599c62e5 100644 --- a/packages/paste-core/components/display-pill-group/src/index.tsx +++ b/packages/paste-core/components/display-pill-group/src/index.tsx @@ -1,2 +1,2 @@ -export * from './DisplayPill'; -export * from './DisplayPillGroup'; +export * from "./DisplayPill"; +export * from "./DisplayPillGroup"; diff --git a/packages/paste-core/components/display-pill-group/stories/customization.stories.tsx b/packages/paste-core/components/display-pill-group/stories/customization.stories.tsx index fcf4e732b8..8575b814b3 100644 --- a/packages/paste-core/components/display-pill-group/stories/customization.stories.tsx +++ b/packages/paste-core/components/display-pill-group/stories/customization.stories.tsx @@ -1,10 +1,10 @@ -import * as React from 'react'; -import {useTheme} from '@twilio-paste/theme'; -import {CustomizationProvider} from '@twilio-paste/customization'; -import {CalendarIcon} from '@twilio-paste/icons/esm/CalendarIcon'; +import { CustomizationProvider } from "@twilio-paste/customization"; +import { CalendarIcon } from "@twilio-paste/icons/esm/CalendarIcon"; +import { useTheme } from "@twilio-paste/theme"; +import * as React from "react"; -import {DisplayPillGroup} from '../src/DisplayPillGroup'; -import {DisplayPill} from '../src/DisplayPill'; +import { DisplayPill } from "../src/DisplayPill"; +import { DisplayPillGroup } from "../src/DisplayPillGroup"; export const CustomDisplayPillGroup = (): JSX.Element => { const currentTheme = useTheme(); @@ -13,17 +13,17 @@ export const CustomDisplayPillGroup = (): JSX.Element => { disableAnimations={true} theme={{ ...currentTheme, - textColors: {...currentTheme.textColors, colorTextLink: 'red'}, - fonts: {...currentTheme.fonts, fontFamilyText: 'arial'}, + textColors: { ...currentTheme.textColors, colorTextLink: "red" }, + fonts: { ...currentTheme.fonts, fontFamilyText: "arial" }, }} elements={{ DISPLAY_PILL_GROUP: { - margin: 'space40', + margin: "space40", }, DISPLAY_PILL: { - backgroundColor: 'colorBackgroundNew', - color: 'colorText', - padding: 'space40', + backgroundColor: "colorBackgroundNew", + color: "colorText", + padding: "space40", }, }} > @@ -32,11 +32,11 @@ export const CustomDisplayPillGroup = (): JSX.Element => { data-testid="display-pill-anchor" onFocus={() => { // eslint-disable-next-line no-console - console.log('Focused Tennis!'); + console.log("Focused Tennis!"); }} onBlur={() => { // eslint-disable-next-line no-console - console.log('Blurred Tennis!'); + console.log("Blurred Tennis!"); }} href="https://google.com" > @@ -54,7 +54,7 @@ export const CustomDisplayPillGroup = (): JSX.Element => { // eslint-disable-next-line import/no-default-export export default { - title: 'Components/Display Pill Group/Customization', + title: "Components/Display Pill Group/Customization", component: DisplayPill, parameters: { a11y: { diff --git a/packages/paste-core/components/display-pill-group/stories/index.stories.tsx b/packages/paste-core/components/display-pill-group/stories/index.stories.tsx index e46eb417af..217f12e247 100644 --- a/packages/paste-core/components/display-pill-group/stories/index.stories.tsx +++ b/packages/paste-core/components/display-pill-group/stories/index.stories.tsx @@ -1,10 +1,10 @@ -import * as React from 'react'; -import {Box} from '@twilio-paste/box'; -import {CalendarIcon} from '@twilio-paste/icons/esm/CalendarIcon'; -import {Avatar} from '@twilio-paste/avatar'; +import { Avatar } from "@twilio-paste/avatar"; +import { Box } from "@twilio-paste/box"; +import { CalendarIcon } from "@twilio-paste/icons/esm/CalendarIcon"; +import * as React from "react"; -import {DisplayPillGroup} from '../src/DisplayPillGroup'; -import {DisplayPill} from '../src/DisplayPill'; +import { DisplayPill } from "../src/DisplayPill"; +import { DisplayPillGroup } from "../src/DisplayPillGroup"; export const Basic = (): JSX.Element => { return ( @@ -13,11 +13,11 @@ export const Basic = (): JSX.Element => { data-testid="display-pill-anchor" onFocus={() => { // eslint-disable-next-line no-console - console.log('Focused Tennis!'); + console.log("Focused Tennis!"); }} onBlur={() => { // eslint-disable-next-line no-console - console.log('Blurred Tennis!'); + console.log("Blurred Tennis!"); }} href="https://google.com" > @@ -47,11 +47,11 @@ export const OverflowWrapping = (): JSX.Element => { data-testid="display-pill-anchor" onFocus={() => { // eslint-disable-next-line no-console - console.log('Focused Tennis!'); + console.log("Focused Tennis!"); }} onBlur={() => { // eslint-disable-next-line no-console - console.log('Blurred Tennis!'); + console.log("Blurred Tennis!"); }} href="https://google.com" > @@ -73,6 +73,6 @@ export const OverflowWrapping = (): JSX.Element => { // eslint-disable-next-line import/no-default-export export default { - title: 'Components/Display Pill Group', + title: "Components/Display Pill Group", component: DisplayPill, }; diff --git a/packages/paste-core/components/editable-code-block/build.js b/packages/paste-core/components/editable-code-block/build.js index a4edeab49b..27dd98f98e 100644 --- a/packages/paste-core/components/editable-code-block/build.js +++ b/packages/paste-core/components/editable-code-block/build.js @@ -1,3 +1,3 @@ -const {build} = require('../../../../tools/build/esbuild'); +const { build } = require("../../../../tools/build/esbuild"); -build(require('./package.json')); +build(require("./package.json")); diff --git a/packages/paste-core/components/editable-code-block/src/EditableCodeBlock.tsx b/packages/paste-core/components/editable-code-block/src/EditableCodeBlock.tsx index e1a920e692..d9e4a7cd9d 100644 --- a/packages/paste-core/components/editable-code-block/src/EditableCodeBlock.tsx +++ b/packages/paste-core/components/editable-code-block/src/EditableCodeBlock.tsx @@ -1,55 +1,55 @@ -import * as React from 'react'; -import {Box, type BoxProps} from '@twilio-paste/box'; -import {useTheme} from '@twilio-paste/theme'; +import { Box, type BoxProps } from "@twilio-paste/box"; import { CodeEditor, CodeEditorPasteTheme, type CodeEditorProps, type Editor, - type Monaco, - type IRange, type IMarkdownString, -} from '@twilio-paste/code-editor-library'; -import {ScreenReaderOnly} from '@twilio-paste/screen-reader-only'; -import {Spinner} from '@twilio-paste/spinner'; -import {StylingGlobals} from '@twilio-paste/styling-library'; + type IRange, + type Monaco, +} from "@twilio-paste/code-editor-library"; +import { ScreenReaderOnly } from "@twilio-paste/screen-reader-only"; +import { Spinner } from "@twilio-paste/spinner"; +import { StylingGlobals } from "@twilio-paste/styling-library"; +import { useTheme } from "@twilio-paste/theme"; +import * as React from "react"; -const EditableCodeblockLoadingMessage: React.FC<{i18nLoadingLabel: string}> = ({i18nLoadingLabel}) => ( +const EditableCodeblockLoadingMessage: React.FC<{ i18nLoadingLabel: string }> = ({ i18nLoadingLabel }) => ( <> {i18nLoadingLabel} ); -EditableCodeblockLoadingMessage.displayName = 'EditableCodeblockLoadingMessage'; +EditableCodeblockLoadingMessage.displayName = "EditableCodeblockLoadingMessage"; -const InlineErrorStyles: {[key: string]: any} = { - '.paste-editable-code-editor-margin-error': { - ':before': { +const InlineErrorStyles: { [key: string]: any } = { + ".paste-editable-code-editor-margin-error": { + ":before": { content: '""', - display: 'inline-block', - position: 'relative', - left: '2px', - width: '16px', - height: '16px', + display: "inline-block", + position: "relative", + left: "2px", + width: "16px", + height: "16px", background: `url(https://assets.twilio.com/public_assets/paste-assets/1.0.0/icons/editable-codeblock-error.svg) no-repeat center center`, }, }, - '.paste-editable-code-editor-row-error': { - backgroundColor: 'rgba(255, 0, 0, 0.3)', + ".paste-editable-code-editor-row-error": { + backgroundColor: "rgba(255, 0, 0, 0.3)", }, }; export interface EditableCodeBlockProps - extends Omit { + extends Omit { children?: never; /* * NOTE: I leave these commented out because I'm not sure whether we want to allow users to override these options. * If we do, we can uncomment these easily in the future since the work is already done. */ // monacoOptions?: CodeEditorProps['options']; - element?: BoxProps['element']; + element?: BoxProps["element"]; minimap?: boolean; - lineNumbers?: 'on' | 'off'; + lineNumbers?: "on" | "off"; folding?: boolean; readOnly?: boolean; indentationGuide?: boolean; @@ -63,9 +63,9 @@ export interface EditableCodeBlockProps export const EditableCodeBlock: React.FC = ({ onMount, - element = 'EDITABLE_CODE_BLOCK', + element = "EDITABLE_CODE_BLOCK", // monacoOptions = {}, - lineNumbers = 'on', + lineNumbers = "on", readOnly = false, folding = true, indentationGuide = true, @@ -74,7 +74,7 @@ export const EditableCodeBlock: React.FC = ({ inlineErrorRange, inlineErrorHoverMessage, inlineErrorIsWholeLine = true, - i18nLoadingLabel = 'Loading code...', + i18nLoadingLabel = "Loading code...", ...props }) => { const theme = useTheme(); @@ -96,7 +96,7 @@ export const EditableCodeBlock: React.FC = ({ indentation: indentationGuide, // ...monacoOptions.guides, }, - } as CodeEditorProps['options']; + } as CodeEditorProps["options"]; }, [ // monacoOptions, readOnly, @@ -111,7 +111,7 @@ export const EditableCodeBlock: React.FC = ({ const globalStyles = React.useMemo(() => { return { - '.monaco-hover-content': { + ".monaco-hover-content": { fontFamily: theme.fonts.fontFamilyText, }, ...(inlineErrorRange ? InlineErrorStyles : {}), @@ -121,8 +121,8 @@ export const EditableCodeBlock: React.FC = ({ const handleEditorDidMount = React.useCallback( (editor: Editor.IStandaloneCodeEditor, monaco: Monaco): void => { // Sets the Paste theme for the editor - monaco.editor.defineTheme('paste', CodeEditorPasteTheme); - monaco.editor.setTheme('paste'); + monaco.editor.defineTheme("paste", CodeEditorPasteTheme); + monaco.editor.setTheme("paste"); if (inlineErrorRange) { editor.createDecorationsCollection([ @@ -132,19 +132,19 @@ export const EditableCodeBlock: React.FC = ({ inlineErrorRange.startLineNumber, inlineErrorRange.startColumn, inlineErrorRange.endLineNumber, - inlineErrorRange.endColumn + inlineErrorRange.endColumn, ), // https://microsoft.github.io/monaco-editor/docs.html#interfaces/editor.IModelDecorationOptions.html options: { isWholeLine: inlineErrorIsWholeLine, - className: '.paste-editable-code-editor-row-error', + className: ".paste-editable-code-editor-row-error", hoverMessage: inlineErrorHoverMessage, - glyphMarginClassName: '.paste-editable-code-editor-margin-error', + glyphMarginClassName: ".paste-editable-code-editor-margin-error", glyphMarginHoverMessage: inlineErrorHoverMessage, // Adds the red error line in the scrollbar canvas overviewRuler: { - color: '#b82430', - darkColor: '#b82430', + color: "#b82430", + darkColor: "#b82430", position: monaco.editor.OverviewRulerLane.Right, }, }, @@ -159,7 +159,7 @@ export const EditableCodeBlock: React.FC = ({ */ onMount?.(editor, monaco); }, - [onMount, inlineErrorHoverMessage, inlineErrorRange, inlineErrorIsWholeLine] + [onMount, inlineErrorHoverMessage, inlineErrorRange, inlineErrorIsWholeLine], ); return ( @@ -175,4 +175,4 @@ export const EditableCodeBlock: React.FC = ({ ); }; -EditableCodeBlock.displayName = 'EditableCodeBlock'; +EditableCodeBlock.displayName = "EditableCodeBlock"; diff --git a/packages/paste-core/components/editable-code-block/src/EditableCodeBlockHeader.tsx b/packages/paste-core/components/editable-code-block/src/EditableCodeBlockHeader.tsx index 93630ce30f..6aaf7a25a0 100644 --- a/packages/paste-core/components/editable-code-block/src/EditableCodeBlockHeader.tsx +++ b/packages/paste-core/components/editable-code-block/src/EditableCodeBlockHeader.tsx @@ -1,15 +1,15 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps, type BoxProps} from '@twilio-paste/box'; -import type {asTags} from '@twilio-paste/heading'; +import { Box, type BoxProps, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { asTags } from "@twilio-paste/heading"; +import * as React from "react"; -export interface EditableCodeBlockHeaderProps extends Partial> { +export interface EditableCodeBlockHeaderProps extends Partial> { children: string; - element?: BoxProps['element']; + element?: BoxProps["element"]; as?: asTags; } export const EditableCodeBlockHeader = React.forwardRef( - ({children, element = 'EDITABLE_CODE_BLOCK_HEADER', as = 'h3', ...props}, ref) => ( + ({ children, element = "EDITABLE_CODE_BLOCK_HEADER", as = "h3", ...props }, ref) => ( {children} - ) + ), ); -EditableCodeBlockHeader.displayName = 'EditableCodeBlockHeader'; +EditableCodeBlockHeader.displayName = "EditableCodeBlockHeader"; diff --git a/packages/paste-core/components/editable-code-block/src/EditableCodeBlockWrapper.tsx b/packages/paste-core/components/editable-code-block/src/EditableCodeBlockWrapper.tsx index 975f993d1b..222ff547f4 100644 --- a/packages/paste-core/components/editable-code-block/src/EditableCodeBlockWrapper.tsx +++ b/packages/paste-core/components/editable-code-block/src/EditableCodeBlockWrapper.tsx @@ -1,29 +1,29 @@ -import * as React from 'react'; -import {Box} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; -import {styled, css} from '@twilio-paste/styling-library'; +import { Box } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import { css, styled } from "@twilio-paste/styling-library"; +import * as React from "react"; const StyledEditableCodeBlockWrapper = styled(Box)( css({ - backgroundColor: 'rgb(1, 22, 39)', // Matches the Night Owl background theme - borderRadius: 'borderRadius20', - overflow: 'hidden', - }) + backgroundColor: "rgb(1, 22, 39)", // Matches the Night Owl background theme + borderRadius: "borderRadius20", + overflow: "hidden", + }), ); export interface EditableCodeBlockWrapperProps { children?: React.ReactNode; - element?: BoxProps['element']; + element?: BoxProps["element"]; } export const EditableCodeBlockWrapper = React.forwardRef( - ({children, element = 'EDITABLE_CODE_BLOCK_WRAPPER'}, ref) => { + ({ children, element = "EDITABLE_CODE_BLOCK_WRAPPER" }, ref) => { return ( {children} ); - } + }, ); -EditableCodeBlockWrapper.displayName = 'EditableCodeBlockWrapper'; +EditableCodeBlockWrapper.displayName = "EditableCodeBlockWrapper"; diff --git a/packages/paste-core/components/editable-code-block/src/index.tsx b/packages/paste-core/components/editable-code-block/src/index.tsx index 8989ca05eb..ab68db04e9 100644 --- a/packages/paste-core/components/editable-code-block/src/index.tsx +++ b/packages/paste-core/components/editable-code-block/src/index.tsx @@ -1,3 +1,3 @@ -export * from './EditableCodeBlockWrapper'; -export * from './EditableCodeBlockHeader'; -export * from './EditableCodeBlock'; +export * from "./EditableCodeBlockWrapper"; +export * from "./EditableCodeBlockHeader"; +export * from "./EditableCodeBlock"; diff --git a/packages/paste-core/components/editable-code-block/stories/index.stories.tsx b/packages/paste-core/components/editable-code-block/stories/index.stories.tsx index 37a4de2eb8..d5b2aabe0d 100644 --- a/packages/paste-core/components/editable-code-block/stories/index.stories.tsx +++ b/packages/paste-core/components/editable-code-block/stories/index.stories.tsx @@ -1,13 +1,13 @@ -import * as React from 'react'; -import {Stack} from '@twilio-paste/stack'; -import {Callout, CalloutHeading, CalloutText} from '@twilio-paste/callout'; -import {RadioButtonGroup, RadioButton} from '@twilio-paste/radio-button-group'; +import { Callout, CalloutHeading, CalloutText } from "@twilio-paste/callout"; +import { RadioButton, RadioButtonGroup } from "@twilio-paste/radio-button-group"; +import { Stack } from "@twilio-paste/stack"; +import * as React from "react"; -import {EditableCodeBlockHeader, EditableCodeBlockWrapper, EditableCodeBlock} from '../src'; +import { EditableCodeBlock, EditableCodeBlockHeader, EditableCodeBlockWrapper } from "../src"; // eslint-disable-next-line import/no-default-export export default { - title: 'Components/Editable Code Block', + title: "Components/Editable Code Block", }; const TypeScriptExample = `interface User { @@ -95,8 +95,8 @@ export const ReadOnly = (): React.ReactNode => { const Files: any = { JS: { - name: 'script.js', - language: 'javascript', + name: "script.js", + language: "javascript", value: `// program that checks if the number is positive, negative or zero // input from the user const number = parseInt(prompt("Enter a number: ")); @@ -117,8 +117,8 @@ else { }`, }, CSS: { - name: 'style.css', - language: 'css', + name: "style.css", + language: "css", value: `.content-area { background-color: #fff; border: 1px solid #e5e5e5; @@ -128,8 +128,8 @@ else { }`, }, HTML: { - name: 'index.html', - language: 'html', + name: "index.html", + language: "html", value: ` @@ -144,7 +144,7 @@ else { }; export const MultiFileEditor = (): React.ReactNode => { - const [fileKey, setFileKey] = React.useState('JS'); + const [fileKey, setFileKey] = React.useState("JS"); return ( { endColumn: 13, }} inlineErrorIsWholeLine={false} - inlineErrorHoverMessage={{value: '"id" can only be a string type.'}} + inlineErrorHoverMessage={{ value: '"id" can only be a string type.' }} defaultLanguage="typescript" defaultValue={TypeScriptExample} /> diff --git a/packages/paste-core/components/file-picker/__tests__/index.spec.tsx b/packages/paste-core/components/file-picker/__tests__/index.spec.tsx index 5947c06193..3e2f924839 100644 --- a/packages/paste-core/components/file-picker/__tests__/index.spec.tsx +++ b/packages/paste-core/components/file-picker/__tests__/index.spec.tsx @@ -1,90 +1,90 @@ -import * as React from 'react'; -import {fireEvent, render, screen} from '@testing-library/react'; -import type {RenderOptions} from '@testing-library/react'; -import {Theme} from '@twilio-paste/theme'; +import { fireEvent, render, screen } from "@testing-library/react"; +import type { RenderOptions } from "@testing-library/react"; +import { Theme } from "@twilio-paste/theme"; +import * as React from "react"; -import {Default, Disabled, Required, Customized} from '../stories/index.stories'; +import { Customized, Default, Disabled, Required } from "../stories/index.stories"; -const ThemeWrapper: RenderOptions['wrapper'] = ({children}) => ( +const ThemeWrapper: RenderOptions["wrapper"] = ({ children }) => ( {children} ); -describe('FilePicker', () => { - it('should render', () => { - const {getByText} = render(); - expect(getByText('Select file')).toBeDefined(); - expect(screen.getByTestId('test-file-picker')).toHaveAttribute('type', 'file'); +describe("FilePicker", () => { + it("should render", () => { + const { getByText } = render(); + expect(getByText("Select file")).toBeDefined(); + expect(screen.getByTestId("test-file-picker")).toHaveAttribute("type", "file"); }); - it('should render as disabled', () => { + it("should render as disabled", () => { render(); - expect(screen.getByTestId('test-file-picker').getAttribute('aria-disabled')).toBe('true'); + expect(screen.getByTestId("test-file-picker").getAttribute("aria-disabled")).toBe("true"); }); - it('should render as required', () => { + it("should render as required", () => { render(); - expect(screen.getByTestId('test-file-picker').getAttribute('aria-required')).toBe('true'); + expect(screen.getByTestId("test-file-picker").getAttribute("aria-required")).toBe("true"); }); - it('should set aria-describedby on the file description text', () => { + it("should set aria-describedby on the file description text", () => { render(); - const textId = screen.getByText('No file uploaded').getAttribute('id'); - expect(screen.getByTestId('test-file-picker')).toHaveAttribute('aria-describedby', textId); + const textId = screen.getByText("No file uploaded").getAttribute("id"); + expect(screen.getByTestId("test-file-picker")).toHaveAttribute("aria-describedby", textId); }); - it('should run the passed onChange function', () => { + it("should run the passed onChange function", () => { const MockOnChange = jest.fn(); render(); - fireEvent.change(screen.getByTestId('test-file-picker'), { + fireEvent.change(screen.getByTestId("test-file-picker"), { target: { - files: [new File([], 'file.png', {type: 'image/png'})], + files: [new File([], "file.png", { type: "image/png" })], }, }); expect(MockOnChange).toHaveBeenCalledTimes(1); }); - it('should correctly pass the name prop', () => { + it("should correctly pass the name prop", () => { render(); - expect(screen.getByTestId('test-file-picker').getAttribute('name')).toEqual('imAFilePicker'); + expect(screen.getByTestId("test-file-picker").getAttribute("name")).toEqual("imAFilePicker"); }); }); -describe('FilePicker customization', () => { - it('should set an element data attribute on File Picker', () => { - const {container} = render(); +describe("FilePicker customization", () => { + it("should set an element data attribute on File Picker", () => { + const { container } = render(); expect(container.querySelector('[data-paste-element="FILEPICKER"]')).toBeInTheDocument(); expect(container.querySelector('[data-paste-element="FILEPICKER_BUTTON"]')).toBeInTheDocument(); expect(container.querySelector('[data-paste-element="FILEPICKER_TEXT"]')).toBeInTheDocument(); }); - it('should set a custom element data attribute on File Picker', () => { - const {container} = render(); + it("should set a custom element data attribute on File Picker", () => { + const { container } = render(); expect(container.querySelector('[data-paste-element="MY_FILEPICKER"]')).toBeInTheDocument(); expect(container.querySelector('[data-paste-element="MY_FILEPICKER_BUTTON"]')).toBeInTheDocument(); expect(container.querySelector('[data-paste-element="MY_FILEPICKER_TEXT"]')).toBeInTheDocument(); }); - it('should add custom styling to File Picker', () => { - const {container} = render(, {wrapper: ThemeWrapper}); + it("should add custom styling to File Picker", () => { + const { container } = render(, { wrapper: ThemeWrapper }); expect(container.querySelector('[data-paste-element="FILEPICKER"]')).toHaveStyleRule( - 'font-family', - "'TwilioSansMono',Courier,monospace" + "font-family", + "'TwilioSansMono',Courier,monospace", ); expect(container.querySelector('[data-paste-element="FILEPICKER_BUTTON"]')).toHaveStyleRule( - 'background-color', - 'rgba(242, 47, 70, 0.1)' + "background-color", + "rgba(242, 47, 70, 0.1)", ); expect(container.querySelector('[data-paste-element="FILEPICKER_TEXT"]')).toHaveStyleRule( - 'margin-left', - '0.125rem' + "margin-left", + "0.125rem", ); }); - it('should add custom styling to a custom named File Picker', () => { - const {container} = render(); + it("should add custom styling to a custom named File Picker", () => { + const { container } = render(); expect(container.querySelector('[data-paste-element="MY_FILEPICKER"]')).toHaveStyleRule( - 'font-family', - "'TwilioSansMono',Courier,monospace" + "font-family", + "'TwilioSansMono',Courier,monospace", ); expect(container.querySelector('[data-paste-element="MY_FILEPICKER_BUTTON"]')).toHaveStyleRule( - 'background-color', - 'rgba(242, 47, 70, 0.1)' + "background-color", + "rgba(242, 47, 70, 0.1)", ); expect(container.querySelector('[data-paste-element="MY_FILEPICKER_TEXT"]')).toHaveStyleRule( - 'margin-left', - '0.125rem' + "margin-left", + "0.125rem", ); }); }); diff --git a/packages/paste-core/components/file-picker/build.js b/packages/paste-core/components/file-picker/build.js index a4edeab49b..27dd98f98e 100644 --- a/packages/paste-core/components/file-picker/build.js +++ b/packages/paste-core/components/file-picker/build.js @@ -1,3 +1,3 @@ -const {build} = require('../../../../tools/build/esbuild'); +const { build } = require("../../../../tools/build/esbuild"); -build(require('./package.json')); +build(require("./package.json")); diff --git a/packages/paste-core/components/file-picker/src/FilePicker.tsx b/packages/paste-core/components/file-picker/src/FilePicker.tsx index bcd582d33c..7b76cc1271 100644 --- a/packages/paste-core/components/file-picker/src/FilePicker.tsx +++ b/packages/paste-core/components/file-picker/src/FilePicker.tsx @@ -1,13 +1,13 @@ -import * as React from 'react'; -import {Text} from '@twilio-paste/text'; -import {useUID} from '@twilio-paste/uid-library'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; -import {SiblingBox} from '@twilio-paste/sibling-box'; -import type {TextColor} from '@twilio-paste/style-props'; -import type {HTMLPasteProps} from '@twilio-paste/types'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import { SiblingBox } from "@twilio-paste/sibling-box"; +import type { TextColor } from "@twilio-paste/style-props"; +import { Text } from "@twilio-paste/text"; +import type { HTMLPasteProps } from "@twilio-paste/types"; +import { useUID } from "@twilio-paste/uid-library"; +import * as React from "react"; -export interface FilePickerProps extends HTMLPasteProps<'input'>, Pick { +export interface FilePickerProps extends HTMLPasteProps<"input">, Pick { accept?: string; children: React.ReactElement; disabled?: boolean; @@ -19,25 +19,25 @@ export interface FilePickerProps extends HTMLPasteProps<'input'>, Pick { const noFileUploaded = fileDescription === i18nNoSelectionText; - if (disabled) return 'colorTextWeaker'; - if (noFileUploaded) return 'colorTextWeak'; - return 'colorText'; + if (disabled) return "colorTextWeaker"; + if (noFileUploaded) return "colorTextWeak"; + return "colorText"; }; const FilePicker = React.forwardRef( ( { - element = 'FILEPICKER', + element = "FILEPICKER", accept, id = useUID(), children, disabled = false, - i18nNoSelectionText = 'No file uploaded', + i18nNoSelectionText = "No file uploaded", required = false, onChange, ...props }, - ref + ref, ) => { const [fileDescription, setFileDescription] = React.useState(i18nNoSelectionText); @@ -91,24 +91,24 @@ const FilePicker = React.forwardRef( boxShadow="shadowBorder" backgroundColor="colorBackgroundBody" _focusSibling={{ - borderRadius: 'borderRadius30', - padding: 'space20', - boxShadow: 'shadowFocus', - backgroundColor: 'colorBackgroundBody', + borderRadius: "borderRadius30", + padding: "space20", + boxShadow: "shadowFocus", + backgroundColor: "colorBackgroundBody", }} _disabledSibling={{ - backgroundColor: 'colorBackground', - boxShadow: 'shadowBorderWeaker', + backgroundColor: "colorBackground", + boxShadow: "shadowBorderWeaker", }} > - {React.cloneElement(children, {disabled, element: `${element}_BUTTON`})} + {React.cloneElement(children, { disabled, element: `${element}_BUTTON` })} {fileDescription} @@ -117,9 +117,9 @@ const FilePicker = React.forwardRef( ); - } + }, ); -FilePicker.displayName = 'FilePicker'; +FilePicker.displayName = "FilePicker"; -export {FilePicker}; +export { FilePicker }; diff --git a/packages/paste-core/components/file-picker/src/FilePickerButton.tsx b/packages/paste-core/components/file-picker/src/FilePickerButton.tsx index 8297a8b8d7..7bd4cc3eb3 100644 --- a/packages/paste-core/components/file-picker/src/FilePickerButton.tsx +++ b/packages/paste-core/components/file-picker/src/FilePickerButton.tsx @@ -1,10 +1,10 @@ -import * as React from 'react'; -import type {ButtonProps} from '@twilio-paste/button'; -import {Button} from '@twilio-paste/button'; -import {Box} from '@twilio-paste/box'; +import { Box } from "@twilio-paste/box"; +import type { ButtonProps } from "@twilio-paste/button"; +import { Button } from "@twilio-paste/button"; +import * as React from "react"; const FilePickerButton = React.forwardRef( - ({children, element, disabled, ...props}, ref) => { + ({ children, element, disabled, ...props }, ref) => { return ( ); - } + }, ); -FilePickerButton.displayName = 'FilePickerButton'; +FilePickerButton.displayName = "FilePickerButton"; -export {FilePickerButton}; +export { FilePickerButton }; diff --git a/packages/paste-core/components/file-picker/src/index.tsx b/packages/paste-core/components/file-picker/src/index.tsx index cc7cb09fa1..2df7a3a518 100644 --- a/packages/paste-core/components/file-picker/src/index.tsx +++ b/packages/paste-core/components/file-picker/src/index.tsx @@ -1,2 +1,2 @@ -export * from './FilePicker'; -export * from './FilePickerButton'; +export * from "./FilePicker"; +export * from "./FilePickerButton"; diff --git a/packages/paste-core/components/file-picker/stories/index.stories.tsx b/packages/paste-core/components/file-picker/stories/index.stories.tsx index c3df3b2c78..32c85a13d0 100644 --- a/packages/paste-core/components/file-picker/stories/index.stories.tsx +++ b/packages/paste-core/components/file-picker/stories/index.stories.tsx @@ -1,21 +1,21 @@ -import * as React from 'react'; -import type {StoryFn} from '@storybook/react'; -import {useUID} from '@twilio-paste/uid-library'; -import {Label} from '@twilio-paste/label'; -import {HelpText} from '@twilio-paste/help-text'; -import {useTheme} from '@twilio-paste/theme'; -import {CustomizationProvider} from '@twilio-paste/customization'; -import {Box} from '@twilio-paste/box'; +import type { StoryFn } from "@storybook/react"; +import { Box } from "@twilio-paste/box"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import { HelpText } from "@twilio-paste/help-text"; +import { Label } from "@twilio-paste/label"; +import { useTheme } from "@twilio-paste/theme"; +import { useUID } from "@twilio-paste/uid-library"; +import * as React from "react"; -import {FilePicker, FilePickerButton} from '../src'; +import { FilePicker, FilePickerButton } from "../src"; // eslint-disable-next-line import/no-default-export export default { - title: 'Components/File Picker', + title: "Components/File Picker", component: FilePicker, }; -export const Default: StoryFn = ({...props}) => { +export const Default: StoryFn = ({ ...props }) => { const id = useUID(); const helpText = useUID(); return ( @@ -29,7 +29,7 @@ export const Default: StoryFn = ({...props}) => { ); }; -export const Required: StoryFn = ({...props}) => { +export const Required: StoryFn = ({ ...props }) => { const id = useUID(); return ( <> @@ -83,7 +83,7 @@ export const ContainedWidth: StoryFn = () => { export const OnChange: StoryFn = () => { const id = useUID(); - const [uploadedFileName, setUploadedFileName] = React.useState('Select file to see the onChange run'); + const [uploadedFileName, setUploadedFileName] = React.useState("Select file to see the onChange run"); return ( <> @@ -100,7 +100,7 @@ export const OnChange: StoryFn = () => { ); }; -export const Customized: StoryFn = ({element = 'FILEPICKER', ...props}) => { +export const Customized: StoryFn = ({ element = "FILEPICKER", ...props }) => { const id = useUID(); const helpText = useUID(); const theme = useTheme(); @@ -108,9 +108,9 @@ export const Customized: StoryFn = ({element = 'FILEPICKER', ...props}) => { diff --git a/packages/paste-core/components/file-uploader/__tests__/customization.spec.tsx b/packages/paste-core/components/file-uploader/__tests__/customization.spec.tsx index f1ca7f58c3..96e176fdbc 100644 --- a/packages/paste-core/components/file-uploader/__tests__/customization.spec.tsx +++ b/packages/paste-core/components/file-uploader/__tests__/customization.spec.tsx @@ -1,45 +1,45 @@ -import * as React from 'react'; -import {render, screen} from '@testing-library/react'; -import {Theme} from '@twilio-paste/theme'; -import type {PasteCustomCSS} from '@twilio-paste/customization'; -import {CustomizationProvider} from '@twilio-paste/customization'; +import { render, screen } from "@testing-library/react"; +import type { PasteCustomCSS } from "@twilio-paste/customization"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import { Theme } from "@twilio-paste/theme"; +import * as React from "react"; import { FileUploader, + FileUploaderDropzone, + FileUploaderDropzoneText, + FileUploaderErrorText, + FileUploaderHelpText, FileUploaderItem, - FileUploaderItemsList, FileUploaderItemDescription, FileUploaderItemTitle, - FileUploaderDropzone, - FileUploaderDropzoneText, + FileUploaderItemsList, FileUploaderLabel, - FileUploaderHelpText, - FileUploaderErrorText, -} from '../src'; +} from "../src"; -const getCustomizationStyles = (element = 'FILE_UPLOADER'): {[key: string]: PasteCustomCSS} => ({ - [`${element}`]: {maxWidth: 'size30'}, - [`${element}_DROPZONE_TEXT`]: {fontFamily: 'fontFamilyCode'}, - [`${element}_DROPZONE`]: {borderRadius: 'borderRadius0'}, - [`${element}_HELP_TEXT`]: {marginBottom: 'space10'}, - [`${element}_ERROR_TEXT`]: {marginBottom: 'space10'}, - [`${element}_ITEM_CONTENT`]: {rowGap: 'space30'}, - [`${element}_ITEM_DESCRIPTION`]: {fontSize: 'fontSize40'}, - [`${element}_ITEM_TITLE`]: {fontSize: 'fontSize40'}, - [`${element}_ITEM_BUTTON`]: {padding: 'space10'}, - [`${element}_ITEM`]: {padding: 'space10'}, - [`${element}_ITEMS_LIST`]: {rowGap: 'space10'}, - [`${element}_LABEL`]: {fontWeight: 'fontWeightNormal'}, +const getCustomizationStyles = (element = "FILE_UPLOADER"): { [key: string]: PasteCustomCSS } => ({ + [`${element}`]: { maxWidth: "size30" }, + [`${element}_DROPZONE_TEXT`]: { fontFamily: "fontFamilyCode" }, + [`${element}_DROPZONE`]: { borderRadius: "borderRadius0" }, + [`${element}_HELP_TEXT`]: { marginBottom: "space10" }, + [`${element}_ERROR_TEXT`]: { marginBottom: "space10" }, + [`${element}_ITEM_CONTENT`]: { rowGap: "space30" }, + [`${element}_ITEM_DESCRIPTION`]: { fontSize: "fontSize40" }, + [`${element}_ITEM_TITLE`]: { fontSize: "fontSize40" }, + [`${element}_ITEM_BUTTON`]: { padding: "space10" }, + [`${element}_ITEM`]: { padding: "space10" }, + [`${element}_ITEMS_LIST`]: { rowGap: "space10" }, + [`${element}_LABEL`]: { fontWeight: "fontWeightNormal" }, }); -describe('FileUploader customization', () => { - it('should set an element data attribute on File Uploader', () => { +describe("FileUploader customization", () => { + it("should set an element data attribute on File Uploader", () => { render( Upload files Files can be up to 50 MB. - + Click to browse or drag files here. @@ -52,37 +52,37 @@ describe('FileUploader customization', () => { - + , ); - const uploader = screen.getByTestId('my-uploader'); - const label = screen.getByTestId('my-label'); - const helpText = screen.getByTestId('my-help-text'); - const errorText = screen.getByTestId('my-error-text'); - const dropzone = screen.getByLabelText('Upload files').parentElement; - const dropzoneText = screen.getByText('Click to browse or drag files here.'); - const itemsList = screen.getByRole('list'); - const item = screen.getAllByRole('listitem')[0]; - const itemTitle = screen.getByText('File1.png'); + const uploader = screen.getByTestId("my-uploader"); + const label = screen.getByTestId("my-label"); + const helpText = screen.getByTestId("my-help-text"); + const errorText = screen.getByTestId("my-error-text"); + const dropzone = screen.getByLabelText("Upload files").parentElement; + const dropzoneText = screen.getByText("Click to browse or drag files here."); + const itemsList = screen.getByRole("list"); + const item = screen.getAllByRole("listitem")[0]; + const itemTitle = screen.getByText("File1.png"); const itemContent = itemTitle.parentElement; - const itemDescription = screen.getByText('Uploading...'); - const itemButton = screen.getAllByRole('button', {name: 'Remove file'})[0]; + const itemDescription = screen.getByText("Uploading..."); + const itemButton = screen.getAllByRole("button", { name: "Remove file" })[0]; - expect(uploader.dataset.pasteElement).toBe('FILE_UPLOADER'); - expect(label.dataset.pasteElement).toBe('FILE_UPLOADER_LABEL'); - expect(helpText.dataset.pasteElement).toBe('FILE_UPLOADER_HELP_TEXT'); - expect(errorText.dataset.pasteElement).toBe('FILE_UPLOADER_ERROR_TEXT'); - expect(dropzone?.dataset.pasteElement).toBe('FILE_UPLOADER_DROPZONE'); - expect(dropzoneText.dataset.pasteElement).toBe('FILE_UPLOADER_DROPZONE_TEXT'); - expect(itemsList.dataset.pasteElement).toBe('FILE_UPLOADER_ITEMS_LIST'); - expect(item.dataset.pasteElement).toBe('FILE_UPLOADER_ITEM'); - expect(itemTitle.dataset.pasteElement).toBe('FILE_UPLOADER_ITEM_TITLE'); - expect(itemContent?.dataset.pasteElement).toBe('FILE_UPLOADER_ITEM_CONTENT'); - expect(itemDescription.dataset.pasteElement).toBe('FILE_UPLOADER_ITEM_DESCRIPTION'); - expect(itemButton.dataset.pasteElement).toBe('FILE_UPLOADER_ITEM_BUTTON'); + expect(uploader.dataset.pasteElement).toBe("FILE_UPLOADER"); + expect(label.dataset.pasteElement).toBe("FILE_UPLOADER_LABEL"); + expect(helpText.dataset.pasteElement).toBe("FILE_UPLOADER_HELP_TEXT"); + expect(errorText.dataset.pasteElement).toBe("FILE_UPLOADER_ERROR_TEXT"); + expect(dropzone?.dataset.pasteElement).toBe("FILE_UPLOADER_DROPZONE"); + expect(dropzoneText.dataset.pasteElement).toBe("FILE_UPLOADER_DROPZONE_TEXT"); + expect(itemsList.dataset.pasteElement).toBe("FILE_UPLOADER_ITEMS_LIST"); + expect(item.dataset.pasteElement).toBe("FILE_UPLOADER_ITEM"); + expect(itemTitle.dataset.pasteElement).toBe("FILE_UPLOADER_ITEM_TITLE"); + expect(itemContent?.dataset.pasteElement).toBe("FILE_UPLOADER_ITEM_CONTENT"); + expect(itemDescription.dataset.pasteElement).toBe("FILE_UPLOADER_ITEM_DESCRIPTION"); + expect(itemButton.dataset.pasteElement).toBe("FILE_UPLOADER_ITEM_BUTTON"); }); - it('should set a custom element data attribute on File Uploader', () => { + it("should set a custom element data attribute on File Uploader", () => { render( @@ -93,7 +93,7 @@ describe('FileUploader customization', () => { Files can be up to 50 MB. @@ -112,43 +112,43 @@ describe('FileUploader customization', () => { - + , ); - const uploader = screen.getByTestId('my-uploader'); - const label = screen.getByTestId('my-label'); - const helpText = screen.getByTestId('my-help-text'); - const errorText = screen.getByTestId('my-error-text'); - const dropzone = screen.getByLabelText('Upload files').parentElement; - const dropzoneText = screen.getByText('Click to browse or drag files here.'); - const itemsList = screen.getByRole('list'); - const item = screen.getAllByRole('listitem')[0]; - const itemTitle = screen.getByText('File1.png'); + const uploader = screen.getByTestId("my-uploader"); + const label = screen.getByTestId("my-label"); + const helpText = screen.getByTestId("my-help-text"); + const errorText = screen.getByTestId("my-error-text"); + const dropzone = screen.getByLabelText("Upload files").parentElement; + const dropzoneText = screen.getByText("Click to browse or drag files here."); + const itemsList = screen.getByRole("list"); + const item = screen.getAllByRole("listitem")[0]; + const itemTitle = screen.getByText("File1.png"); const itemContent = itemTitle.parentElement; - const itemDescription = screen.getByText('Uploading...'); - const itemButton = screen.getAllByRole('button', {name: 'Remove file'})[0]; + const itemDescription = screen.getByText("Uploading..."); + const itemButton = screen.getAllByRole("button", { name: "Remove file" })[0]; - expect(uploader.dataset.pasteElement).toBe('MY_UPLOADER'); - expect(label.dataset.pasteElement).toBe('MY_UPLOADER_LABEL'); - expect(helpText.dataset.pasteElement).toBe('MY_UPLOADER_HELP_TEXT'); - expect(errorText.dataset.pasteElement).toBe('MY_UPLOADER_ERROR_TEXT'); - expect(dropzone?.dataset.pasteElement).toBe('MY_UPLOADER_DROPZONE'); - expect(dropzoneText.dataset.pasteElement).toBe('MY_UPLOADER_DROPZONE_TEXT'); - expect(itemsList.dataset.pasteElement).toBe('MY_UPLOADER_ITEMS_LIST'); - expect(item.dataset.pasteElement).toBe('MY_UPLOADER_ITEM'); - expect(itemTitle.dataset.pasteElement).toBe('MY_UPLOADER_ITEM_TITLE'); - expect(itemContent?.dataset.pasteElement).toBe('MY_UPLOADER_ITEM_CONTENT'); - expect(itemDescription.dataset.pasteElement).toBe('MY_UPLOADER_ITEM_DESCRIPTION'); - expect(itemButton.dataset.pasteElement).toBe('MY_UPLOADER_ITEM_BUTTON'); + expect(uploader.dataset.pasteElement).toBe("MY_UPLOADER"); + expect(label.dataset.pasteElement).toBe("MY_UPLOADER_LABEL"); + expect(helpText.dataset.pasteElement).toBe("MY_UPLOADER_HELP_TEXT"); + expect(errorText.dataset.pasteElement).toBe("MY_UPLOADER_ERROR_TEXT"); + expect(dropzone?.dataset.pasteElement).toBe("MY_UPLOADER_DROPZONE"); + expect(dropzoneText.dataset.pasteElement).toBe("MY_UPLOADER_DROPZONE_TEXT"); + expect(itemsList.dataset.pasteElement).toBe("MY_UPLOADER_ITEMS_LIST"); + expect(item.dataset.pasteElement).toBe("MY_UPLOADER_ITEM"); + expect(itemTitle.dataset.pasteElement).toBe("MY_UPLOADER_ITEM_TITLE"); + expect(itemContent?.dataset.pasteElement).toBe("MY_UPLOADER_ITEM_CONTENT"); + expect(itemDescription.dataset.pasteElement).toBe("MY_UPLOADER_ITEM_DESCRIPTION"); + expect(itemButton.dataset.pasteElement).toBe("MY_UPLOADER_ITEM_BUTTON"); }); - it('should add custom styling to File Uploader', () => { + it("should add custom styling to File Uploader", () => { render( Upload files Files can be up to 50 MB. - + Click to browse or drag files here. @@ -161,39 +161,39 @@ describe('FileUploader customization', () => { - + , ); - const uploader = screen.getByTestId('my-uploader'); - const label = screen.getByTestId('my-label'); - const helpText = screen.getByTestId('my-help-text'); - const errorText = screen.getByTestId('my-error-text'); - const dropzone = screen.getByLabelText('Upload files').parentElement; - const dropzoneText = screen.getByText('Click to browse or drag files here.'); - const itemsList = screen.getByRole('list'); - const item = screen.getAllByRole('listitem')[0]; - const itemTitle = screen.getByText('File1.png'); + const uploader = screen.getByTestId("my-uploader"); + const label = screen.getByTestId("my-label"); + const helpText = screen.getByTestId("my-help-text"); + const errorText = screen.getByTestId("my-error-text"); + const dropzone = screen.getByLabelText("Upload files").parentElement; + const dropzoneText = screen.getByText("Click to browse or drag files here."); + const itemsList = screen.getByRole("list"); + const item = screen.getAllByRole("listitem")[0]; + const itemTitle = screen.getByText("File1.png"); const itemContent = itemTitle.parentElement; - const itemDescription = screen.getByText('Uploading...'); - const itemButton = screen.getAllByRole('button', {name: 'Remove file'})[0]; + const itemDescription = screen.getByText("Uploading..."); + const itemButton = screen.getAllByRole("button", { name: "Remove file" })[0]; - expect(uploader).toHaveStyleRule('max-width', '18.5rem'); - expect(label).toHaveStyleRule('font-weight', '400'); - expect(helpText).toHaveStyleRule('margin-bottom', '0.125rem'); - expect(errorText).toHaveStyleRule('margin-bottom', '0.125rem'); - expect(dropzone).toHaveStyleRule('border-radius', '0'); - expect(dropzoneText).toHaveStyleRule('font-family', "'TwilioSansMono',Courier,monospace"); - expect(itemsList).toHaveStyleRule('row-gap', '0.125rem'); - expect(item).toHaveStyleRule('padding', '0.125rem'); - expect(itemTitle).toHaveStyleRule('font-size', '1rem'); - expect(itemContent).toHaveStyleRule('row-gap', '0.5rem'); - expect(itemDescription).toHaveStyleRule('font-size', '1rem'); - expect(itemButton).toHaveStyleRule('padding', '0.125rem'); + expect(uploader).toHaveStyleRule("max-width", "18.5rem"); + expect(label).toHaveStyleRule("font-weight", "400"); + expect(helpText).toHaveStyleRule("margin-bottom", "0.125rem"); + expect(errorText).toHaveStyleRule("margin-bottom", "0.125rem"); + expect(dropzone).toHaveStyleRule("border-radius", "0"); + expect(dropzoneText).toHaveStyleRule("font-family", "'TwilioSansMono',Courier,monospace"); + expect(itemsList).toHaveStyleRule("row-gap", "0.125rem"); + expect(item).toHaveStyleRule("padding", "0.125rem"); + expect(itemTitle).toHaveStyleRule("font-size", "1rem"); + expect(itemContent).toHaveStyleRule("row-gap", "0.5rem"); + expect(itemDescription).toHaveStyleRule("font-size", "1rem"); + expect(itemButton).toHaveStyleRule("padding", "0.125rem"); }); - it('should add custom styling to a custom named File Uploader', () => { + it("should add custom styling to a custom named File Uploader", () => { render( - + Upload files @@ -202,7 +202,7 @@ describe('FileUploader customization', () => { Files can be up to 50 MB. @@ -221,33 +221,33 @@ describe('FileUploader customization', () => { - + , ); - const uploader = screen.getByTestId('my-uploader'); - const label = screen.getByTestId('my-label'); - const helpText = screen.getByTestId('my-help-text'); - const errorText = screen.getByTestId('my-error-text'); - const dropzone = screen.getByLabelText('Upload files').parentElement; - const dropzoneText = screen.getByText('Click to browse or drag files here.'); - const itemsList = screen.getByRole('list'); - const item = screen.getAllByRole('listitem')[0]; - const itemTitle = screen.getByText('File1.png'); + const uploader = screen.getByTestId("my-uploader"); + const label = screen.getByTestId("my-label"); + const helpText = screen.getByTestId("my-help-text"); + const errorText = screen.getByTestId("my-error-text"); + const dropzone = screen.getByLabelText("Upload files").parentElement; + const dropzoneText = screen.getByText("Click to browse or drag files here."); + const itemsList = screen.getByRole("list"); + const item = screen.getAllByRole("listitem")[0]; + const itemTitle = screen.getByText("File1.png"); const itemContent = itemTitle.parentElement; - const itemDescription = screen.getByText('Uploading...'); - const itemButton = screen.getAllByRole('button', {name: 'Remove file'})[0]; + const itemDescription = screen.getByText("Uploading..."); + const itemButton = screen.getAllByRole("button", { name: "Remove file" })[0]; - expect(uploader).toHaveStyleRule('max-width', '18.5rem'); - expect(label).toHaveStyleRule('font-weight', '400'); - expect(helpText).toHaveStyleRule('margin-bottom', '0.125rem'); - expect(errorText).toHaveStyleRule('margin-bottom', '0.125rem'); - expect(dropzone).toHaveStyleRule('border-radius', '0'); - expect(dropzoneText).toHaveStyleRule('font-family', "'TwilioSansMono',Courier,monospace"); - expect(itemsList).toHaveStyleRule('row-gap', '0.125rem'); - expect(item).toHaveStyleRule('padding', '0.125rem'); - expect(itemTitle).toHaveStyleRule('font-size', '1rem'); - expect(itemContent).toHaveStyleRule('row-gap', '0.5rem'); - expect(itemDescription).toHaveStyleRule('font-size', '1rem'); - expect(itemButton).toHaveStyleRule('padding', '0.125rem'); + expect(uploader).toHaveStyleRule("max-width", "18.5rem"); + expect(label).toHaveStyleRule("font-weight", "400"); + expect(helpText).toHaveStyleRule("margin-bottom", "0.125rem"); + expect(errorText).toHaveStyleRule("margin-bottom", "0.125rem"); + expect(dropzone).toHaveStyleRule("border-radius", "0"); + expect(dropzoneText).toHaveStyleRule("font-family", "'TwilioSansMono',Courier,monospace"); + expect(itemsList).toHaveStyleRule("row-gap", "0.125rem"); + expect(item).toHaveStyleRule("padding", "0.125rem"); + expect(itemTitle).toHaveStyleRule("font-size", "1rem"); + expect(itemContent).toHaveStyleRule("row-gap", "0.5rem"); + expect(itemDescription).toHaveStyleRule("font-size", "1rem"); + expect(itemButton).toHaveStyleRule("padding", "0.125rem"); }); }); diff --git a/packages/paste-core/components/file-uploader/__tests__/index.spec.tsx b/packages/paste-core/components/file-uploader/__tests__/index.spec.tsx index de792fe57e..1f5200e649 100644 --- a/packages/paste-core/components/file-uploader/__tests__/index.spec.tsx +++ b/packages/paste-core/components/file-uploader/__tests__/index.spec.tsx @@ -1,31 +1,31 @@ -import * as React from 'react'; -import {render, screen, fireEvent} from '@testing-library/react'; -import {Theme} from '@twilio-paste/theme'; +import { fireEvent, render, screen } from "@testing-library/react"; +import { Theme } from "@twilio-paste/theme"; +import * as React from "react"; import { FileUploader, + FileUploaderDropzone, + FileUploaderDropzoneText, + FileUploaderErrorText, + FileUploaderHelpText, FileUploaderItem, - FileUploaderItemsList, FileUploaderItemDescription, FileUploaderItemTitle, - FileUploaderDropzone, - FileUploaderDropzoneText, + FileUploaderItemsList, FileUploaderLabel, - FileUploaderHelpText, - FileUploaderErrorText, -} from '../src'; -import {arrayToCsv} from '../src/utils'; +} from "../src"; +import { arrayToCsv } from "../src/utils"; -const sampleMimeTypes = ['text/css', 'image/jpeg', 'image/png', 'application/pdf']; +const sampleMimeTypes = ["text/css", "image/jpeg", "image/png", "application/pdf"]; -describe('arrayToCsv', () => { - it('should convert an array of strings to CSV', () => { - expect(arrayToCsv(['foo', 'bar', 'baz'])).toBe('foo,bar,baz'); +describe("arrayToCsv", () => { + it("should convert an array of strings to CSV", () => { + expect(arrayToCsv(["foo", "bar", "baz"])).toBe("foo,bar,baz"); }); }); -describe('FileUploader', () => { - it('should render the proper HTML', () => { +describe("FileUploader", () => { + it("should render the proper HTML", () => { render( @@ -44,28 +44,28 @@ describe('FileUploader', () => { - + , ); - const input = screen.getByLabelText('Upload files'); - const helpTextId = screen.getByTestId('my-help-text').id; - const errorTextId = screen.getByTestId('my-error-text').id; - const dropzoneTextId = screen.getByText('Click to browse or drag files here.').id; + const input = screen.getByLabelText("Upload files"); + const helpTextId = screen.getByTestId("my-help-text").id; + const errorTextId = screen.getByTestId("my-error-text").id; + const dropzoneTextId = screen.getByText("Click to browse or drag files here.").id; expect(input).toBeDefined(); expect(input).not.toBeRequired(); expect(input).not.toBeDisabled(); - expect(input.getAttribute('aria-describedby')).toBe(`${errorTextId} ${helpTextId} ${dropzoneTextId}`); - expect(input.getAttribute('name')).toBe('Default File Uploader'); - expect(input.getAttribute('accept')).toBe('text/css,image/jpeg,image/png,application/pdf'); - expect(input.getAttribute('type')).toBe('file'); - - expect(screen.getByRole('list')).toBeDefined(); - expect(screen.getAllByRole('listitem')).toHaveLength(1); - expect(screen.getByRole('button', {name: 'Remove file'})).toBeDefined(); + expect(input.getAttribute("aria-describedby")).toBe(`${errorTextId} ${helpTextId} ${dropzoneTextId}`); + expect(input.getAttribute("name")).toBe("Default File Uploader"); + expect(input.getAttribute("accept")).toBe("text/css,image/jpeg,image/png,application/pdf"); + expect(input.getAttribute("type")).toBe("file"); + + expect(screen.getByRole("list")).toBeDefined(); + expect(screen.getAllByRole("listitem")).toHaveLength(1); + expect(screen.getByRole("button", { name: "Remove file" })).toBeDefined(); }); - it('should render as required when pass the required prop', () => { + it("should render as required when pass the required prop", () => { render( @@ -74,18 +74,18 @@ describe('FileUploader', () => { Click to browse or drag files here. - + , ); const requiredDot = screen - .getByTestId('my-label') + .getByTestId("my-label") .querySelector('[data-paste-element="FILE_UPLOADER_LABEL_REQUIRED_DOT"]'); expect(requiredDot).toBeInTheDocument(); - expect(screen.getByLabelText('Upload files')).toBeRequired(); + expect(screen.getByLabelText("Upload files")).toBeRequired(); }); - it('should render as disabled when pass the disabled prop', () => { + it("should render as disabled when pass the disabled prop", () => { render( @@ -94,13 +94,13 @@ describe('FileUploader', () => { Click to browse or drag files here. - + , ); - expect(screen.getByLabelText('Upload files')).toBeDisabled(); + expect(screen.getByLabelText("Upload files")).toBeDisabled(); }); - it('should call appropriate event handlers', () => { + it("should call appropriate event handlers", () => { const onInputChangeMock: jest.Mock = jest.fn(); const onDragOverMock: jest.Mock = jest.fn(); const onDragLeaveMock: jest.Mock = jest.fn(); @@ -125,21 +125,21 @@ describe('FileUploader', () => { File1.png - + , ); - fireEvent.change(screen.getByLabelText('Upload files'), { + fireEvent.change(screen.getByLabelText("Upload files"), { target: { - files: [new File([], 'file.png', {type: 'image/png'})], + files: [new File([], "file.png", { type: "image/png" })], }, }); expect(onInputChangeMock).toBeCalledTimes(1); - const dropzone = screen.getByTestId('my-dropzone'); + const dropzone = screen.getByTestId("my-dropzone"); fireEvent.dragOver(dropzone, { dataTransfer: { - dropEffect: 'copy', + dropEffect: "copy", }, }); expect(onDragOverMock).toBeCalledTimes(1); @@ -150,11 +150,11 @@ describe('FileUploader', () => { fireEvent.drop(dropzone); expect(onDragLeaveMock).toBeCalledTimes(1); - fireEvent.click(screen.getByRole('button', {name: 'Remove file'})); + fireEvent.click(screen.getByRole("button", { name: "Remove file" })); expect(onButtonClickMock).toBeCalledTimes(1); }); - it('should not call drag event handlers when disabled', () => { + it("should not call drag event handlers when disabled", () => { const onDragOverMock: jest.Mock = jest.fn(); const onDragLeaveMock: jest.Mock = jest.fn(); const onDropMock: jest.Mock = jest.fn(); @@ -173,14 +173,14 @@ describe('FileUploader', () => { Click to browse or drag files here. - + , ); - const dropzone = screen.getByTestId('my-dropzone'); + const dropzone = screen.getByTestId("my-dropzone"); fireEvent.dragOver(dropzone, { dataTransfer: { - dropEffect: 'copy', + dropEffect: "copy", }, }); expect(onDragOverMock).toBeCalledTimes(0); @@ -193,8 +193,8 @@ describe('FileUploader', () => { }); }); -describe('i18n', () => { - it('should have default strings', () => { +describe("i18n", () => { + it("should have default strings", () => { render( @@ -202,14 +202,14 @@ describe('i18n', () => { File1.png File1.png - + , ); - expect(screen.getAllByRole('button', {name: 'Remove file'})).toHaveLength(3); - expect(screen.getByText('(error)')).toBeDefined(); - expect(screen.getByText('(uploading file)')).toBeDefined(); + expect(screen.getAllByRole("button", { name: "Remove file" })).toHaveLength(3); + expect(screen.getByText("(error)")).toBeDefined(); + expect(screen.getByText("(uploading file)")).toBeDefined(); }); - it('should use the i18n props to change the strings', () => { + it("should use the i18n props to change the strings", () => { render( @@ -221,11 +221,11 @@ describe('i18n', () => { File1.png - + , ); - expect(screen.getByRole('button', {name: 'foo button'})).toBeDefined(); - expect(screen.getByText('foo error')).toBeDefined(); - expect(screen.getByText('foo loading')).toBeDefined(); + expect(screen.getByRole("button", { name: "foo button" })).toBeDefined(); + expect(screen.getByText("foo error")).toBeDefined(); + expect(screen.getByText("foo loading")).toBeDefined(); }); }); diff --git a/packages/paste-core/components/file-uploader/build.js b/packages/paste-core/components/file-uploader/build.js index a4edeab49b..27dd98f98e 100644 --- a/packages/paste-core/components/file-uploader/build.js +++ b/packages/paste-core/components/file-uploader/build.js @@ -1,3 +1,3 @@ -const {build} = require('../../../../tools/build/esbuild'); +const { build } = require("../../../../tools/build/esbuild"); -build(require('./package.json')); +build(require("./package.json")); diff --git a/packages/paste-core/components/file-uploader/src/FileUploader.tsx b/packages/paste-core/components/file-uploader/src/FileUploader.tsx index 4995e98ec9..7b759dc6cb 100644 --- a/packages/paste-core/components/file-uploader/src/FileUploader.tsx +++ b/packages/paste-core/components/file-uploader/src/FileUploader.tsx @@ -1,13 +1,13 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; -import {useUID} from '@twilio-paste/uid-library'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import { useUID } from "@twilio-paste/uid-library"; +import * as React from "react"; -import {FileUploaderContext} from './FileUploaderContext'; +import { FileUploaderContext } from "./FileUploaderContext"; -export interface FileUploaderProps extends Omit, 'children' | 'onChange'> { +export interface FileUploaderProps extends Omit, "children" | "onChange"> { children?: React.ReactNode; - element?: BoxProps['element']; + element?: BoxProps["element"]; disabled?: boolean; id?: string; name: string; @@ -15,17 +15,17 @@ export interface FileUploaderProps extends Omit( - ({element = 'FILE_UPLOADER', disabled, id: idProp, name, required = false, ...props}, ref) => { + ({ element = "FILE_UPLOADER", disabled, id: idProp, name, required = false, ...props }, ref) => { const id = idProp ? idProp : useUID(); return ( - + {props.children} ); - } + }, ); -FileUploader.displayName = 'FileUploader'; +FileUploader.displayName = "FileUploader"; diff --git a/packages/paste-core/components/file-uploader/src/FileUploaderContext.tsx b/packages/paste-core/components/file-uploader/src/FileUploaderContext.tsx index 2a072aea46..3d0ed643ef 100644 --- a/packages/paste-core/components/file-uploader/src/FileUploaderContext.tsx +++ b/packages/paste-core/components/file-uploader/src/FileUploaderContext.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import * as React from "react"; interface FileUploaderContextProps { disabled?: boolean; diff --git a/packages/paste-core/components/file-uploader/src/FileUploaderDropzone.tsx b/packages/paste-core/components/file-uploader/src/FileUploaderDropzone.tsx index e1d29df587..0f7f29c2be 100644 --- a/packages/paste-core/components/file-uploader/src/FileUploaderDropzone.tsx +++ b/packages/paste-core/components/file-uploader/src/FileUploaderDropzone.tsx @@ -1,18 +1,18 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxProps, BoxStyleProps} from '@twilio-paste/box'; -import {UploadToCloudIcon} from '@twilio-paste/icons/esm/UploadToCloudIcon'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps, BoxStyleProps } from "@twilio-paste/box"; +import { UploadToCloudIcon } from "@twilio-paste/icons/esm/UploadToCloudIcon"; +import * as React from "react"; -import {FileUploaderContext} from './FileUploaderContext'; -import {arrayToCsv} from './utils'; +import { FileUploaderContext } from "./FileUploaderContext"; +import { arrayToCsv } from "./utils"; export interface FileUploaderDropzoneProps extends Omit< - React.ComponentPropsWithRef<'input'>, - 'children' | 'onChange' | 'onDragEnter' | 'onDragLeave' | 'onDrop' | 'onDragStart' | 'onDragEnd' | 'onDragOver' + React.ComponentPropsWithRef<"input">, + "children" | "onChange" | "onDragEnter" | "onDragLeave" | "onDrop" | "onDragStart" | "onDragEnd" | "onDragOver" > { acceptedMimeTypes: string[]; - element?: BoxProps['element']; + element?: BoxProps["element"]; children?: React.ReactNode; onInputChange?: (event: React.ChangeEvent) => void; onDragEnd?: (event: React.DragEvent) => void; @@ -24,31 +24,31 @@ export interface FileUploaderDropzoneProps } const hoverDragStyles: BoxStyleProps = { - borderColor: 'colorBorderPrimaryStrong', - backgroundColor: 'colorBackgroundPrimaryWeakest', + borderColor: "colorBorderPrimaryStrong", + backgroundColor: "colorBackgroundPrimaryWeakest", }; const baseStyles: BoxStyleProps = { - borderColor: 'colorBorderWeak', - borderStyle: 'dashed', - backgroundColor: 'colorBackgroundWeak', - cursor: 'pointer', - color: 'colorText', + borderColor: "colorBorderWeak", + borderStyle: "dashed", + backgroundColor: "colorBackgroundWeak", + cursor: "pointer", + color: "colorText", _hover: hoverDragStyles, }; const disabledStyles: BoxStyleProps = { - backgroundColor: 'colorBackgroundStrong', - borderStyle: 'solid', - borderColor: 'colorBorderWeaker', - cursor: 'not-allowed', - color: 'colorTextWeaker', + backgroundColor: "colorBackgroundStrong", + borderStyle: "solid", + borderColor: "colorBorderWeaker", + cursor: "not-allowed", + color: "colorTextWeaker", }; export const FileUploaderDropzone = React.forwardRef( ( { - element = 'FILE_UPLOADER_DROPZONE', + element = "FILE_UPLOADER_DROPZONE", children, acceptedMimeTypes, onInputChange, @@ -60,9 +60,9 @@ export const FileUploaderDropzone = React.forwardRef { - const {id, disabled, required, name} = React.useContext(FileUploaderContext); + const { id, disabled, required, name } = React.useContext(FileUploaderContext); /** * The underlying DOM element won't accept the same file after it has been @@ -75,7 +75,7 @@ export const FileUploaderDropzone = React.forwardRef): void => { setFileInputKey((prev) => prev + 1); @@ -87,7 +87,7 @@ export const FileUploaderDropzone = React.forwardRef): void => { event.preventDefault(); event.stopPropagation(); - event.dataTransfer.dropEffect = 'copy'; + event.dataTransfer.dropEffect = "copy"; if (disabled) return; @@ -99,7 +99,7 @@ export const FileUploaderDropzone = React.forwardRef): void => { event.preventDefault(); event.stopPropagation(); - event.dataTransfer.dropEffect = 'copy'; + event.dataTransfer.dropEffect = "copy"; if (disabled) return; @@ -156,8 +156,8 @@ export const FileUploaderDropzone = React.forwardRef - + <>{children} ); - } + }, ); -FileUploaderDropzone.displayName = 'FileUploaderDropzone'; +FileUploaderDropzone.displayName = "FileUploaderDropzone"; diff --git a/packages/paste-core/components/file-uploader/src/FileUploaderDropzoneText.tsx b/packages/paste-core/components/file-uploader/src/FileUploaderDropzoneText.tsx index a5514d777d..2cc0d6ab84 100644 --- a/packages/paste-core/components/file-uploader/src/FileUploaderDropzoneText.tsx +++ b/packages/paste-core/components/file-uploader/src/FileUploaderDropzoneText.tsx @@ -1,17 +1,17 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import * as React from "react"; -import {FileUploaderContext} from './FileUploaderContext'; +import { FileUploaderContext } from "./FileUploaderContext"; -export interface FileUploaderDropzoneTextProps extends Omit, 'children'> { +export interface FileUploaderDropzoneTextProps extends Omit, "children"> { children?: React.ReactNode; - element?: BoxProps['element']; + element?: BoxProps["element"]; } export const FileUploaderDropzoneText = React.forwardRef( - ({children, element = 'FILE_UPLOADER_DROPZONE_TEXT', ...props}, ref) => { - const {id} = React.useContext(FileUploaderContext); + ({ children, element = "FILE_UPLOADER_DROPZONE_TEXT", ...props }, ref) => { + const { id } = React.useContext(FileUploaderContext); return ( ); - } + }, ); -FileUploaderDropzoneText.displayName = 'FileUploaderDropzoneText'; +FileUploaderDropzoneText.displayName = "FileUploaderDropzoneText"; diff --git a/packages/paste-core/components/file-uploader/src/FileUploaderErrorText.tsx b/packages/paste-core/components/file-uploader/src/FileUploaderErrorText.tsx index 82be9eca74..6326df0c97 100644 --- a/packages/paste-core/components/file-uploader/src/FileUploaderErrorText.tsx +++ b/packages/paste-core/components/file-uploader/src/FileUploaderErrorText.tsx @@ -1,18 +1,18 @@ -import * as React from 'react'; -import {HelpText} from '@twilio-paste/help-text'; -import type {HelpTextProps} from '@twilio-paste/help-text'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import { HelpText } from "@twilio-paste/help-text"; +import type { HelpTextProps } from "@twilio-paste/help-text"; +import * as React from "react"; -import {FileUploaderContext} from './FileUploaderContext'; +import { FileUploaderContext } from "./FileUploaderContext"; -export interface FileUploaderErrorTextProps extends Omit, 'children'> { - children?: HelpTextProps['children']; - element?: HelpTextProps['element']; +export interface FileUploaderErrorTextProps extends Omit, "children"> { + children?: HelpTextProps["children"]; + element?: HelpTextProps["element"]; } export const FileUploaderErrorText = React.forwardRef( - ({children, element = 'FILE_UPLOADER_ERROR_TEXT', ...props}, ref) => { - const {id} = React.useContext(FileUploaderContext); + ({ children, element = "FILE_UPLOADER_ERROR_TEXT", ...props }, ref) => { + const { id } = React.useContext(FileUploaderContext); return ( @@ -21,7 +21,7 @@ export const FileUploaderErrorText = React.forwardRef ); - } + }, ); -FileUploaderErrorText.displayName = 'FileUploaderErrorText'; +FileUploaderErrorText.displayName = "FileUploaderErrorText"; diff --git a/packages/paste-core/components/file-uploader/src/FileUploaderHelpText.tsx b/packages/paste-core/components/file-uploader/src/FileUploaderHelpText.tsx index bec8f23674..911f28a4a5 100644 --- a/packages/paste-core/components/file-uploader/src/FileUploaderHelpText.tsx +++ b/packages/paste-core/components/file-uploader/src/FileUploaderHelpText.tsx @@ -1,25 +1,25 @@ -import * as React from 'react'; -import {HelpText} from '@twilio-paste/help-text'; -import type {HelpTextProps} from '@twilio-paste/help-text'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import { HelpText } from "@twilio-paste/help-text"; +import type { HelpTextProps } from "@twilio-paste/help-text"; +import * as React from "react"; -import {FileUploaderContext} from './FileUploaderContext'; +import { FileUploaderContext } from "./FileUploaderContext"; -export interface FileUploaderHelpTextProps extends Omit, 'children'> { - children?: HelpTextProps['children']; - element?: HelpTextProps['element']; +export interface FileUploaderHelpTextProps extends Omit, "children"> { + children?: HelpTextProps["children"]; + element?: HelpTextProps["element"]; } export const FileUploaderHelpText = React.forwardRef( - ({children, element = 'FILE_UPLOADER_HELP_TEXT', ...props}, ref) => { - const {id} = React.useContext(FileUploaderContext); + ({ children, element = "FILE_UPLOADER_HELP_TEXT", ...props }, ref) => { + const { id } = React.useContext(FileUploaderContext); return ( {children} ); - } + }, ); -FileUploaderHelpText.displayName = 'FileUploaderHelpText'; +FileUploaderHelpText.displayName = "FileUploaderHelpText"; diff --git a/packages/paste-core/components/file-uploader/src/FileUploaderItem.tsx b/packages/paste-core/components/file-uploader/src/FileUploaderItem.tsx index 54feaf6bff..0ad5e3f828 100644 --- a/packages/paste-core/components/file-uploader/src/FileUploaderItem.tsx +++ b/packages/paste-core/components/file-uploader/src/FileUploaderItem.tsx @@ -1,19 +1,19 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxProps, BoxStyleProps} from '@twilio-paste/box'; -import {Button} from '@twilio-paste/button'; -import {Spinner} from '@twilio-paste/spinner'; -import {ErrorIcon} from '@twilio-paste/icons/esm/ErrorIcon'; -import {DeleteIcon} from '@twilio-paste/icons/esm/DeleteIcon'; -import {CloseIcon} from '@twilio-paste/icons/esm/CloseIcon'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps, BoxStyleProps } from "@twilio-paste/box"; +import { Button } from "@twilio-paste/button"; +import { CloseIcon } from "@twilio-paste/icons/esm/CloseIcon"; +import { DeleteIcon } from "@twilio-paste/icons/esm/DeleteIcon"; +import { ErrorIcon } from "@twilio-paste/icons/esm/ErrorIcon"; +import { Spinner } from "@twilio-paste/spinner"; +import * as React from "react"; -import {FileUploaderItemContext} from './FileUploaderItemContext'; -import type {FileUploaderItemContextProps} from './FileUploaderItemContext'; +import { FileUploaderItemContext } from "./FileUploaderItemContext"; +import type { FileUploaderItemContextProps } from "./FileUploaderItemContext"; -export interface FileUploaderItemProps extends Omit, 'children'> { - children?: BoxProps['children']; - element?: BoxProps['element']; - variant?: FileUploaderItemContextProps['variant']; +export interface FileUploaderItemProps extends Omit, "children"> { + children?: BoxProps["children"]; + element?: BoxProps["element"]; + variant?: FileUploaderItemContextProps["variant"]; fileIcon?: NonNullable; onButtonClick?: () => void; i18nErrorText?: string; @@ -21,30 +21,30 @@ export interface FileUploaderItemProps extends Omit = { +const variantStyles: Record = { default: { - borderColor: 'colorBorderWeaker', - backgroundColor: 'colorBackgroundBody', + borderColor: "colorBorderWeaker", + backgroundColor: "colorBackgroundBody", }, loading: { - borderColor: 'colorBorderWeaker', - backgroundColor: 'colorBackgroundBody', + borderColor: "colorBorderWeaker", + backgroundColor: "colorBackgroundBody", }, error: { - borderColor: 'colorBorderError', - backgroundColor: 'colorBackgroundErrorWeakest', + borderColor: "colorBorderError", + backgroundColor: "colorBackgroundErrorWeakest", }, }; -const iconStyles: Record = { +const iconStyles: Record = { default: { - color: 'colorTextIcon', + color: "colorTextIcon", }, loading: { - color: 'colorTextIcon', + color: "colorTextIcon", }, error: { - color: 'colorTextIconError', + color: "colorTextIconError", }, }; @@ -53,29 +53,29 @@ export const FileUploaderItem = React.forwardRef { let icon = fileIcon; - if (variant === 'error') + if (variant === "error") icon = ; - if (variant === 'loading') + if (variant === "loading") icon = ; let buttonIcon = ; - if (variant === 'loading' || variant === 'error') { + if (variant === "loading" || variant === "error") { buttonIcon = ; } return ( - + ); - } + }, ); -FileUploaderItem.displayName = 'FileUploaderItem'; +FileUploaderItem.displayName = "FileUploaderItem"; diff --git a/packages/paste-core/components/file-uploader/src/FileUploaderItemContext.tsx b/packages/paste-core/components/file-uploader/src/FileUploaderItemContext.tsx index f230bd0058..a652f9b237 100644 --- a/packages/paste-core/components/file-uploader/src/FileUploaderItemContext.tsx +++ b/packages/paste-core/components/file-uploader/src/FileUploaderItemContext.tsx @@ -1,9 +1,9 @@ -import * as React from 'react'; +import * as React from "react"; export interface FileUploaderItemContextProps { - variant: 'default' | 'error' | 'loading'; + variant: "default" | "error" | "loading"; } export const FileUploaderItemContext = React.createContext({ - variant: 'default', + variant: "default", }); diff --git a/packages/paste-core/components/file-uploader/src/FileUploaderItemDescription.tsx b/packages/paste-core/components/file-uploader/src/FileUploaderItemDescription.tsx index 72654d8193..aa390ebe42 100644 --- a/packages/paste-core/components/file-uploader/src/FileUploaderItemDescription.tsx +++ b/packages/paste-core/components/file-uploader/src/FileUploaderItemDescription.tsx @@ -1,31 +1,31 @@ -import * as React from 'react'; -import type {BoxElementProps} from '@twilio-paste/box'; -import {Text, safelySpreadTextProps} from '@twilio-paste/text'; -import type {TextStyleProps} from '@twilio-paste/text'; +import type { BoxElementProps } from "@twilio-paste/box"; +import { Text, safelySpreadTextProps } from "@twilio-paste/text"; +import type { TextStyleProps } from "@twilio-paste/text"; +import * as React from "react"; -import {FileUploaderItemContext} from './FileUploaderItemContext'; -import type {FileUploaderItemContextProps} from './FileUploaderItemContext'; +import { FileUploaderItemContext } from "./FileUploaderItemContext"; +import type { FileUploaderItemContextProps } from "./FileUploaderItemContext"; -export interface FileUploaderItemDescriptionProps extends Omit, 'children'> { +export interface FileUploaderItemDescriptionProps extends Omit, "children"> { children: string; - element?: BoxElementProps['element']; + element?: BoxElementProps["element"]; } -const variantStyles: Record = { +const variantStyles: Record = { default: { - color: 'colorTextWeak', + color: "colorTextWeak", }, loading: { - color: 'colorTextWeak', + color: "colorTextWeak", }, error: { - color: 'colorTextError', + color: "colorTextError", }, }; export const FileUploaderItemDescription = React.forwardRef( - ({children, element = 'FILE_UPLOADER_ITEM_DESCRIPTION', ...props}, ref) => { - const {variant} = React.useContext(FileUploaderItemContext); + ({ children, element = "FILE_UPLOADER_ITEM_DESCRIPTION", ...props }, ref) => { + const { variant } = React.useContext(FileUploaderItemContext); return ( ); - } + }, ); -FileUploaderItemDescription.displayName = 'FileUploaderItemDescription'; +FileUploaderItemDescription.displayName = "FileUploaderItemDescription"; diff --git a/packages/paste-core/components/file-uploader/src/FileUploaderItemTitle.tsx b/packages/paste-core/components/file-uploader/src/FileUploaderItemTitle.tsx index 2eefc91034..8d5517c9b9 100644 --- a/packages/paste-core/components/file-uploader/src/FileUploaderItemTitle.tsx +++ b/packages/paste-core/components/file-uploader/src/FileUploaderItemTitle.tsx @@ -1,14 +1,14 @@ -import * as React from 'react'; -import type {BoxElementProps} from '@twilio-paste/box'; -import {Text, safelySpreadTextProps} from '@twilio-paste/text'; +import type { BoxElementProps } from "@twilio-paste/box"; +import { Text, safelySpreadTextProps } from "@twilio-paste/text"; +import * as React from "react"; -export interface FileUploaderItemTitleProps extends Omit, 'children'> { +export interface FileUploaderItemTitleProps extends Omit, "children"> { children: string; - element?: BoxElementProps['element']; + element?: BoxElementProps["element"]; } export const FileUploaderItemTitle = React.forwardRef( - ({children, element = 'FILE_UPLOADER_ITEM_TITLE', ...props}, ref) => { + ({ children, element = "FILE_UPLOADER_ITEM_TITLE", ...props }, ref) => { return ( ); - } + }, ); -FileUploaderItemTitle.displayName = 'FileUploaderItemTitle'; +FileUploaderItemTitle.displayName = "FileUploaderItemTitle"; diff --git a/packages/paste-core/components/file-uploader/src/FileUploaderItemsList.tsx b/packages/paste-core/components/file-uploader/src/FileUploaderItemsList.tsx index d03708d547..f8c93e06ff 100644 --- a/packages/paste-core/components/file-uploader/src/FileUploaderItemsList.tsx +++ b/packages/paste-core/components/file-uploader/src/FileUploaderItemsList.tsx @@ -1,14 +1,14 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import * as React from "react"; -export interface FileUploaderItemsListProps extends Omit, 'children'> { +export interface FileUploaderItemsListProps extends Omit, "children"> { children?: React.ReactNode; - element?: BoxProps['element']; + element?: BoxProps["element"]; } export const FileUploaderItemsList = React.forwardRef( - ({children, element = 'FILE_UPLOADER_ITEMS_LIST', ...props}, ref) => { + ({ children, element = "FILE_UPLOADER_ITEMS_LIST", ...props }, ref) => { return ( ); - } + }, ); -FileUploaderItemsList.displayName = 'FileUploaderItemsList'; +FileUploaderItemsList.displayName = "FileUploaderItemsList"; diff --git a/packages/paste-core/components/file-uploader/src/FileUploaderLabel.tsx b/packages/paste-core/components/file-uploader/src/FileUploaderLabel.tsx index 26a973daf2..dc76253f4c 100644 --- a/packages/paste-core/components/file-uploader/src/FileUploaderLabel.tsx +++ b/packages/paste-core/components/file-uploader/src/FileUploaderLabel.tsx @@ -1,24 +1,24 @@ -import * as React from 'react'; -import {Label} from '@twilio-paste/label'; -import type {LabelProps} from '@twilio-paste/label'; +import { Label } from "@twilio-paste/label"; +import type { LabelProps } from "@twilio-paste/label"; +import * as React from "react"; -import {FileUploaderContext} from './FileUploaderContext'; +import { FileUploaderContext } from "./FileUploaderContext"; -export type FileUploaderLabelProps = Omit, 'children'> & { - children: LabelProps['children']; - element?: LabelProps['element']; +export type FileUploaderLabelProps = Omit, "children"> & { + children: LabelProps["children"]; + element?: LabelProps["element"]; }; export const FileUploaderLabel = React.forwardRef( - ({children, element = 'FILE_UPLOADER_LABEL', ...props}, ref) => { - const {id, disabled, required} = React.useContext(FileUploaderContext); + ({ children, element = "FILE_UPLOADER_LABEL", ...props }, ref) => { + const { id, disabled, required } = React.useContext(FileUploaderContext); return ( ); - } + }, ); -FileUploaderLabel.displayName = 'FileUploaderLabel'; +FileUploaderLabel.displayName = "FileUploaderLabel"; diff --git a/packages/paste-core/components/file-uploader/src/index.tsx b/packages/paste-core/components/file-uploader/src/index.tsx index 009c97767e..9754b23822 100644 --- a/packages/paste-core/components/file-uploader/src/index.tsx +++ b/packages/paste-core/components/file-uploader/src/index.tsx @@ -1,10 +1,10 @@ -export * from './FileUploader'; -export * from './FileUploaderHelpText'; -export * from './FileUploaderLabel'; -export * from './FileUploaderItem'; -export * from './FileUploaderItemsList'; -export * from './FileUploaderItemDescription'; -export * from './FileUploaderItemTitle'; -export * from './FileUploaderDropzone'; -export * from './FileUploaderDropzoneText'; -export * from './FileUploaderErrorText'; +export * from "./FileUploader"; +export * from "./FileUploaderHelpText"; +export * from "./FileUploaderLabel"; +export * from "./FileUploaderItem"; +export * from "./FileUploaderItemsList"; +export * from "./FileUploaderItemDescription"; +export * from "./FileUploaderItemTitle"; +export * from "./FileUploaderDropzone"; +export * from "./FileUploaderDropzoneText"; +export * from "./FileUploaderErrorText"; diff --git a/packages/paste-core/components/file-uploader/src/utils.ts b/packages/paste-core/components/file-uploader/src/utils.ts index 0cae70ff89..fb27126a22 100644 --- a/packages/paste-core/components/file-uploader/src/utils.ts +++ b/packages/paste-core/components/file-uploader/src/utils.ts @@ -1,4 +1,4 @@ -import isEmpty from 'lodash/isEmpty'; +import isEmpty from "lodash/isEmpty"; /** * Converts an array to a comma separated string @@ -11,8 +11,8 @@ export const arrayToCsv = (value: string[]): string => { * there's nothing to join */ if (!Array.isArray(value) || isEmpty(value)) { - return ''; + return ""; } - return value.join(','); + return value.join(","); }; diff --git a/packages/paste-core/components/file-uploader/stories/index.stories.tsx b/packages/paste-core/components/file-uploader/stories/index.stories.tsx index 0e0ca64b43..8c46a20b3c 100644 --- a/packages/paste-core/components/file-uploader/stories/index.stories.tsx +++ b/packages/paste-core/components/file-uploader/stories/index.stories.tsx @@ -1,28 +1,28 @@ -import * as React from 'react'; -import {DownloadIcon} from '@twilio-paste/icons/esm/DownloadIcon'; -import {CustomizationProvider} from '@twilio-paste/customization'; -import {useTheme} from '@twilio-paste/theme'; -import {ScreenReaderOnly} from '@twilio-paste/screen-reader-only'; -import type {StoryFn} from '@storybook/react'; -import snakeCase from 'lodash/snakeCase'; +import type { StoryFn } from "@storybook/react"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import { DownloadIcon } from "@twilio-paste/icons/esm/DownloadIcon"; +import { ScreenReaderOnly } from "@twilio-paste/screen-reader-only"; +import { useTheme } from "@twilio-paste/theme"; +import snakeCase from "lodash/snakeCase"; +import * as React from "react"; import { FileUploader, + FileUploaderDropzone, + FileUploaderDropzoneText, + FileUploaderErrorText, + FileUploaderHelpText, FileUploaderItem, - FileUploaderItemsList, FileUploaderItemDescription, FileUploaderItemTitle, - FileUploaderDropzone, - FileUploaderDropzoneText, + FileUploaderItemsList, FileUploaderLabel, - FileUploaderHelpText, - FileUploaderErrorText, -} from '../src'; -import type {FileUploaderItemProps} from '../src'; +} from "../src"; +import type { FileUploaderItemProps } from "../src"; // eslint-disable-next-line import/no-default-export export default { - title: 'Components/File Uploader', + title: "Components/File Uploader", component: FileUploader, }; @@ -31,7 +31,7 @@ export const Default: StoryFn = () => { Upload files Files can be up to 50 MB. - + Browse files or drag them here @@ -53,7 +53,7 @@ export const Error: StoryFn = () => { Upload files Files can be up to 50 MB. - + Browse files or drag them here One of your files failed to upload. Please try again. @@ -82,7 +82,7 @@ export const Disabled: StoryFn = () => { Upload files Files can be up to 50 MB. - + Browse files or drag them here @@ -94,7 +94,7 @@ export const Required: StoryFn = () => { Upload files Files can be up to 50 MB. - + Browse files or drag them here @@ -102,7 +102,7 @@ export const Required: StoryFn = () => { }; interface File { - variant: FileUploaderItemProps['variant']; + variant: FileUploaderItemProps["variant"]; title: string; description: string; id: string; @@ -110,32 +110,32 @@ interface File { const sampleFiles: File[] = [ { - variant: 'default', - title: 'File1.png', - description: '9.2 MB', + variant: "default", + title: "File1.png", + description: "9.2 MB", id: `initial-file-0`, }, { - variant: 'loading', - title: 'File2.png', - description: 'Uploading...', + variant: "loading", + title: "File2.png", + description: "Uploading...", id: `initial-file-1`, }, ]; export const DragDropExample: StoryFn = () => { - const [screenReaderText, setScreenReaderText] = React.useState(''); + const [screenReaderText, setScreenReaderText] = React.useState(""); const [files, setFiles] = React.useState(sampleFiles); React.useEffect(() => { const timer = setTimeout(() => { - let finishedFiles = ''; + let finishedFiles = ""; setFiles((prev) => { const updatedFiles: File[] = []; prev.forEach((file) => { - if (file.variant === 'loading') { - file.variant = 'default'; + if (file.variant === "loading") { + file.variant = "default"; const size = Math.floor(Math.random() * (50 - 1 + 1) + 1); file.description = `${size} MB`; finishedFiles = `${finishedFiles} ${file.title}`; @@ -154,19 +154,19 @@ export const DragDropExample: StoryFn = () => { }, [files, setFiles]); const handleInputChange = (event: React.ChangeEvent): void => { - const {files: newFiles} = event.target; - let newFilesNames = ''; + const { files: newFiles } = event.target; + let newFilesNames = ""; if (newFiles !== null) { - Array.from(newFiles).forEach(({name}) => { + Array.from(newFiles).forEach(({ name }) => { newFilesNames = `${newFilesNames} ${name}`; setFiles((prev) => { return [ ...prev, { title: name, - description: 'Uploading...', - variant: 'loading', + description: "Uploading...", + variant: "loading", id: `${snakeCase(name)}`, }, ]; @@ -180,28 +180,28 @@ export const DragDropExample: StoryFn = () => { }; const handleDragEnter = (event: React.DragEvent): void => { - const {items} = event.dataTransfer; + const { items } = event.dataTransfer; setScreenReaderText(`Dragging ${items.length} files`); }; const handleDragLeave = (event: React.DragEvent): void => { - const {items} = event.dataTransfer; + const { items } = event.dataTransfer; setScreenReaderText(`Cancelled dragging ${items.length} files`); }; const handleDrop = (event: React.DragEvent): void => { - const {files: newFiles} = event.dataTransfer; + const { files: newFiles } = event.dataTransfer; setScreenReaderText(`Dropped ${newFiles.length} files`); if (newFiles !== null) { - Array.from(newFiles).forEach(({name}) => { + Array.from(newFiles).forEach(({ name }) => { setFiles((prev) => { return [ ...prev, { title: name, - description: 'Uploading...', - variant: 'loading', + description: "Uploading...", + variant: "loading", id: `${snakeCase(name)}`, }, ]; @@ -217,7 +217,7 @@ export const DragDropExample: StoryFn = () => { Files can be up to 50 MB. { Browse files or drag them here - {files.map(({variant, title, description, id}) => ( + {files.map(({ variant, title, description, id }) => ( { }; DragDropExample.parameters = { - chromatic: {disableSnapshot: true}, + chromatic: { disableSnapshot: true }, }; export const ReallyLongText: StoryFn = () => { @@ -265,7 +265,7 @@ export const ReallyLongText: StoryFn = () => { magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. - + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. @@ -287,29 +287,29 @@ export const ReallyLongText: StoryFn = () => { ); }; -export const Customized: StoryFn = ({element = 'FILE_UPLOADER', ...props}) => { +export const Customized: StoryFn = ({ element = "FILE_UPLOADER", ...props }) => { const theme = useTheme(); return ( Upload files Files can be up to 50 MB. - + Browse files or drag them here diff --git a/packages/paste-core/components/form-pill-group/__tests__/index.spec.tsx b/packages/paste-core/components/form-pill-group/__tests__/index.spec.tsx index 227f388103..c685d7c9dc 100644 --- a/packages/paste-core/components/form-pill-group/__tests__/index.spec.tsx +++ b/packages/paste-core/components/form-pill-group/__tests__/index.spec.tsx @@ -1,10 +1,10 @@ -import * as React from 'react'; -import {render, fireEvent, screen} from '@testing-library/react'; -import {CustomizationProvider} from '@twilio-paste/customization'; +import { fireEvent, render, screen } from "@testing-library/react"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import * as React from "react"; -import {useFormPillState, FormPillGroup, FormPill} from '../src'; -import {Basic, SelectableAndDismissable} from '../stories/index.stories'; -import {CustomFormPillGroup} from '../stories/customization.stories'; +import { FormPill, FormPillGroup, useFormPillState } from "../src"; +import { CustomFormPillGroup } from "../stories/customization.stories"; +import { Basic, SelectableAndDismissable } from "../stories/index.stories"; const CustomElementFormPillGroup = (): JSX.Element => { const pillState = useFormPillState(); @@ -44,169 +44,169 @@ const I18nProp = (): JSX.Element => { ); }; -describe('FormPillGroup', () => { - describe('Rendered shape', () => { - it('has the correct aria attributes and semantic HTML', () => { +describe("FormPillGroup", () => { + describe("Rendered shape", () => { + it("has the correct aria attributes and semantic HTML", () => { render(); - expect(screen.getByText('Default pill')).toBeDefined(); + expect(screen.getByText("Default pill")).toBeDefined(); - const group = screen.getByTestId('form-pill-group'); - expect(group.getAttribute('aria-label')).toBe('Basic pills:'); - expect(group.tagName).toBe('DIV'); - expect(group.getAttribute('role')).toBe('listbox'); + const group = screen.getByTestId("form-pill-group"); + expect(group.getAttribute("aria-label")).toBe("Basic pills:"); + expect(group.tagName).toBe("DIV"); + expect(group.getAttribute("role")).toBe("listbox"); - const pill = screen.getByTestId('form-pill-0'); - expect(pill.tagName).toBe('BUTTON'); - expect(pill.getAttribute('role')).toBe('option'); - expect(pill.getAttribute('aria-selected')).toBe('false'); + const pill = screen.getByTestId("form-pill-0"); + expect(pill.tagName).toBe("BUTTON"); + expect(pill.getAttribute("role")).toBe("option"); + expect(pill.getAttribute("aria-selected")).toBe("false"); }); }); - describe('Selecting and Removing', () => { - it('can select and navigate pills', () => { + describe("Selecting and Removing", () => { + it("can select and navigate pills", () => { render(); // Get the first pill - const firstPill = screen.getByTestId('form-pill-0'); + const firstPill = screen.getByTestId("form-pill-0"); // Click it and make sure it selected fireEvent.click(firstPill); - expect(firstPill.getAttribute('aria-selected')).toBe('true'); + expect(firstPill.getAttribute("aria-selected")).toBe("true"); // Make sure it deselects on click fireEvent.click(firstPill); - expect(firstPill.getAttribute('aria-selected')).toBe('false'); + expect(firstPill.getAttribute("aria-selected")).toBe("false"); // Make sure it selects on Enter key - fireEvent.keyDown(firstPill, {key: 'Enter', code: 'Enter'}); - expect(firstPill.getAttribute('aria-selected')).toBe('true'); + fireEvent.keyDown(firstPill, { key: "Enter", code: "Enter" }); + expect(firstPill.getAttribute("aria-selected")).toBe("true"); // Make sure it deselects on Enter key - fireEvent.keyDown(firstPill, {key: 'Enter', code: 'Enter'}); - expect(firstPill.getAttribute('aria-selected')).toBe('false'); + fireEvent.keyDown(firstPill, { key: "Enter", code: "Enter" }); + expect(firstPill.getAttribute("aria-selected")).toBe("false"); // Make sure we can navigate with right arrow - fireEvent.keyDown(firstPill, {key: 'ArrowRight', code: 'ArrowRight'}); + fireEvent.keyDown(firstPill, { key: "ArrowRight", code: "ArrowRight" }); if (document.activeElement == null) { - throw new Error('document.activeElement is null'); + throw new Error("document.activeElement is null"); } - expect(document.activeElement.getAttribute('data-testid')).toBe('form-pill-1'); + expect(document.activeElement.getAttribute("data-testid")).toBe("form-pill-1"); // Move right again and check for selection - fireEvent.keyDown(document.activeElement, {key: 'ArrowRight', code: 'ArrowRight'}); - expect(document.activeElement.getAttribute('data-testid')).toBe('form-pill-2'); - fireEvent.keyDown(document.activeElement, {key: 'Enter', code: 'Enter'}); - expect(document.activeElement.getAttribute('aria-selected')).toBe('true'); + fireEvent.keyDown(document.activeElement, { key: "ArrowRight", code: "ArrowRight" }); + expect(document.activeElement.getAttribute("data-testid")).toBe("form-pill-2"); + fireEvent.keyDown(document.activeElement, { key: "Enter", code: "Enter" }); + expect(document.activeElement.getAttribute("aria-selected")).toBe("true"); // Try moving left this time - fireEvent.keyDown(document.activeElement, {key: 'ArrowLeft', code: 'ArrowLeft'}); - expect(document.activeElement.getAttribute('data-testid')).toBe('form-pill-1'); + fireEvent.keyDown(document.activeElement, { key: "ArrowLeft", code: "ArrowLeft" }); + expect(document.activeElement.getAttribute("data-testid")).toBe("form-pill-1"); // Loop movement - fireEvent.keyDown(document.activeElement, {key: 'ArrowLeft', code: 'ArrowLeft'}); - fireEvent.keyDown(document.activeElement, {key: 'ArrowLeft', code: 'ArrowLeft'}); - expect(document.activeElement.getAttribute('data-testid')).toBe('form-pill-5'); + fireEvent.keyDown(document.activeElement, { key: "ArrowLeft", code: "ArrowLeft" }); + fireEvent.keyDown(document.activeElement, { key: "ArrowLeft", code: "ArrowLeft" }); + expect(document.activeElement.getAttribute("data-testid")).toBe("form-pill-5"); }); - it('can remove pills', () => { + it("can remove pills", () => { render(); /* Test click to remove */ - const firstPill = screen.getByRole('option', {name: 'Default pill'}).parentElement; + const firstPill = screen.getByRole("option", { name: "Default pill" }).parentElement; const firstPillX = firstPill?.querySelector('[data-paste-element="FORM_PILL_CLOSE"]'); fireEvent.click(firstPillX as Element); expect(firstPill).not.toBeInTheDocument(); /* Test keyboard to remove */ - const secondPill = screen.getByRole('option', {name: 'Pill with icon'}); - fireEvent.keyDown(secondPill, {key: 'Delete', code: 'Delete'}); + const secondPill = screen.getByRole("option", { name: "Pill with icon" }); + fireEvent.keyDown(secondPill, { key: "Delete", code: "Delete" }); expect(secondPill).not.toBeInTheDocument(); - const thirdPill = screen.getByRole('option', {name: 'Pill with avatar'}); - fireEvent.keyDown(thirdPill, {key: 'Backspace', code: 'Backspace'}); + const thirdPill = screen.getByRole("option", { name: "Pill with avatar" }); + fireEvent.keyDown(thirdPill, { key: "Backspace", code: "Backspace" }); expect(thirdPill).not.toBeInTheDocument(); }); }); - describe('Customization', () => { - it('should set an element data attribute for FormPillGroup & FormPill', () => { + describe("Customization", () => { + it("should set an element data attribute for FormPillGroup & FormPill", () => { render(); - const group = screen.getByTestId('form-pill-group'); - expect(group.getAttribute('data-paste-element')).toEqual('FORM_PILL_GROUP'); + const group = screen.getByTestId("form-pill-group"); + expect(group.getAttribute("data-paste-element")).toEqual("FORM_PILL_GROUP"); - const pill = screen.getByTestId('form-pill-0'); - expect(pill.getAttribute('data-paste-element')).toEqual('FORM_PILL'); + const pill = screen.getByTestId("form-pill-0"); + expect(pill.getAttribute("data-paste-element")).toEqual("FORM_PILL"); }); - it('should set a custom element data attribute for FormPillGroup & FormPill', () => { + it("should set a custom element data attribute for FormPillGroup & FormPill", () => { render(); - const group = screen.getByTestId('form-pill-group'); - expect(group.getAttribute('data-paste-element')).toEqual('CUSTOM_PILL_GROUP'); - const pill = screen.getByTestId('form-pill'); - expect(pill.getAttribute('data-paste-element')).toEqual('CUSTOM_PILL'); + const group = screen.getByTestId("form-pill-group"); + expect(group.getAttribute("data-paste-element")).toEqual("CUSTOM_PILL_GROUP"); + const pill = screen.getByTestId("form-pill"); + expect(pill.getAttribute("data-paste-element")).toEqual("CUSTOM_PILL"); }); - it('should add custom styles to FormPillGroup & FormPill', () => { + it("should add custom styles to FormPillGroup & FormPill", () => { render(); - const group = screen.getByTestId('form-pill-group'); - expect(group).toHaveStyleRule('margin', '0.75rem'); + const group = screen.getByTestId("form-pill-group"); + expect(group).toHaveStyleRule("margin", "0.75rem"); - const pill = screen.getByTestId('form-pill'); - expect(pill).toHaveStyleRule('background-color', 'rgb(245, 240, 252)'); + const pill = screen.getByTestId("form-pill"); + expect(pill).toHaveStyleRule("background-color", "rgb(245, 240, 252)"); }); - it('should add custom styles to custom element FormPillGroup & FormPill', () => { + it("should add custom styles to custom element FormPillGroup & FormPill", () => { render( - + , ); - const group = screen.getByTestId('form-pill-group'); - expect(group).toHaveStyleRule('margin', '0.75rem'); + const group = screen.getByTestId("form-pill-group"); + expect(group).toHaveStyleRule("margin", "0.75rem"); - const pill = screen.getByTestId('form-pill'); - expect(pill).toHaveStyleRule('background-color', 'rgb(231, 220, 250)'); + const pill = screen.getByTestId("form-pill"); + expect(pill).toHaveStyleRule("background-color", "rgb(231, 220, 250)"); }); }); - describe('i18n', () => { - it('should have default keyboard controls text', () => { + describe("i18n", () => { + it("should have default keyboard controls text", () => { render(); const keyboardControlsText = screen.getByText( - 'Press Delete or Backspace to remove. Press Enter to toggle selection.' + "Press Delete or Backspace to remove. Press Enter to toggle selection.", ); expect(keyboardControlsText).toBeDefined(); }); - it('should use i18nKeyboardControls for keyboard controls text', () => { + it("should use i18nKeyboardControls for keyboard controls text", () => { render(); const keyboardControlsText = screen.getByText( - 'Appuyez sur Supprimer ou Retour arrière pour supprimer. Appuyez sur Entrée pour basculer la sélection.' + "Appuyez sur Supprimer ou Retour arrière pour supprimer. Appuyez sur Entrée pour basculer la sélection.", ); expect(keyboardControlsText).toBeDefined(); }); - it('should have default error text', () => { + it("should have default error text", () => { render(); - const errorLabel = screen.getAllByText('(error)'); + const errorLabel = screen.getAllByText("(error)"); expect(errorLabel).toBeDefined(); }); - it('should use i18nErrorLabel for error text', () => { + it("should use i18nErrorLabel for error text", () => { render(); - const errorLabel = screen.getByText('(erreur)'); + const errorLabel = screen.getByText("(erreur)"); expect(errorLabel).toBeDefined(); }); }); diff --git a/packages/paste-core/components/form-pill-group/build.js b/packages/paste-core/components/form-pill-group/build.js index a4edeab49b..27dd98f98e 100644 --- a/packages/paste-core/components/form-pill-group/build.js +++ b/packages/paste-core/components/form-pill-group/build.js @@ -1,3 +1,3 @@ -const {build} = require('../../../../tools/build/esbuild'); +const { build } = require("../../../../tools/build/esbuild"); -build(require('./package.json')); +build(require("./package.json")); diff --git a/packages/paste-core/components/form-pill-group/src/FormPill.styles.ts b/packages/paste-core/components/form-pill-group/src/FormPill.styles.ts index b13038273b..046054e027 100644 --- a/packages/paste-core/components/form-pill-group/src/FormPill.styles.ts +++ b/packages/paste-core/components/form-pill-group/src/FormPill.styles.ts @@ -1,6 +1,6 @@ -import type {BoxStyleProps} from '@twilio-paste/box'; +import type { BoxStyleProps } from "@twilio-paste/box"; -import type {VariantStyles} from './types'; +import type { VariantStyles } from "./types"; /** * Wrapper styles @@ -10,30 +10,30 @@ import type {VariantStyles} from './types'; export const wrapperStyles: VariantStyles = { default: { - color: 'colorTextIcon', + color: "colorTextIcon", _hover: { - color: 'colorTextLinkStronger', + color: "colorTextLinkStronger", }, }, error: { - color: 'colorTextIcon', + color: "colorTextIcon", _hover: { - color: 'colorTextErrorStronger', + color: "colorTextErrorStronger", }, }, }; export const selectedWrapperStyles: VariantStyles = { default: { - color: 'colorTextWeakest', + color: "colorTextWeakest", _hover: { - color: 'colorTextInverse', + color: "colorTextInverse", }, }, error: { - color: 'colorTextInverse', + color: "colorTextInverse", _hover: { - color: 'colorTextWeakest', + color: "colorTextWeakest", }, }, }; @@ -44,94 +44,94 @@ export const selectedWrapperStyles: VariantStyles = { export const pillStyles: VariantStyles = { default: { - color: 'colorText', - backgroundColor: 'colorBackgroundPrimaryWeakest', - boxShadow: 'shadowBorderPrimaryWeaker', + color: "colorText", + backgroundColor: "colorBackgroundPrimaryWeakest", + boxShadow: "shadowBorderPrimaryWeaker", _focus: { - boxShadow: 'shadowFocus', - color: 'colorText', + boxShadow: "shadowFocus", + color: "colorText", }, _selected: { - backgroundColor: 'colorBackgroundPrimaryStronger', - boxShadow: 'shadowBorderPrimaryStronger', - color: 'colorTextWeakest', + backgroundColor: "colorBackgroundPrimaryStronger", + boxShadow: "shadowBorderPrimaryStronger", + color: "colorTextWeakest", }, _selected_focus: { - boxShadow: 'shadowFocus', - color: 'colorTextWeakest', + boxShadow: "shadowFocus", + color: "colorTextWeakest", }, _disabled: { - backgroundColor: 'colorBackgroundStrong', - boxShadow: 'shadowBorderWeaker', - cursor: 'not-allowed', - color: 'colorText', + backgroundColor: "colorBackgroundStrong", + boxShadow: "shadowBorderWeaker", + cursor: "not-allowed", + color: "colorText", }, }, error: { - backgroundColor: 'colorBackgroundErrorWeakest', - boxShadow: 'shadowBorderErrorWeaker', - color: 'colorTextError', + backgroundColor: "colorBackgroundErrorWeakest", + boxShadow: "shadowBorderErrorWeaker", + color: "colorTextError", _focus: { - boxShadow: 'shadowFocus', - color: 'colorTextErrorStrong', + boxShadow: "shadowFocus", + color: "colorTextErrorStrong", }, _selected: { - backgroundColor: 'colorBackgroundError', - boxShadow: 'shadowBorderError', - color: 'colorTextInverse', + backgroundColor: "colorBackgroundError", + boxShadow: "shadowBorderError", + color: "colorTextInverse", }, _selected_focus: { - boxShadow: 'shadowFocus', - color: 'colorTextInverse', + boxShadow: "shadowFocus", + color: "colorTextInverse", }, _disabled: { - backgroundColor: 'colorBackgroundStrong', - boxShadow: 'shadowBorderWeaker', - cursor: 'not-allowed', - color: 'colorText', + backgroundColor: "colorBackgroundStrong", + boxShadow: "shadowBorderWeaker", + cursor: "not-allowed", + color: "colorText", }, }, }; export const hoverPillStyles: VariantStyles = { default: { - cursor: 'pointer', - color: 'colorText', - backgroundColor: 'colorBackgroundPrimaryWeakest', - boxShadow: 'shadowBorderPrimaryWeaker', + cursor: "pointer", + color: "colorText", + backgroundColor: "colorBackgroundPrimaryWeakest", + boxShadow: "shadowBorderPrimaryWeaker", _hover: { - boxShadow: 'shadowBorderPrimaryStronger', - color: 'colorTextPrimaryStronger', + boxShadow: "shadowBorderPrimaryStronger", + color: "colorTextPrimaryStronger", }, _selected_hover: { - backgroundColor: 'colorBackgroundPrimary', - boxShadow: 'shadowBorderPrimary', - color: 'colorTextInverse', + backgroundColor: "colorBackgroundPrimary", + boxShadow: "shadowBorderPrimary", + color: "colorTextInverse", }, _focus_hover: { - boxShadow: 'shadowFocus', + boxShadow: "shadowFocus", }, }, error: { - cursor: 'pointer', - backgroundColor: 'colorBackgroundErrorWeakest', - boxShadow: 'shadowBorderErrorWeaker', - color: 'colorTextError', + cursor: "pointer", + backgroundColor: "colorBackgroundErrorWeakest", + boxShadow: "shadowBorderErrorWeaker", + color: "colorTextError", _hover: { - boxShadow: 'shadowBorderErrorStronger', - color: 'colorTextErrorStronger', + boxShadow: "shadowBorderErrorStronger", + color: "colorTextErrorStronger", }, _selected_hover: { - backgroundColor: 'colorBackgroundErrorStrongest', - boxShadow: 'shadowBorderErrorStrongest', - color: 'colorTextWeakest', + backgroundColor: "colorBackgroundErrorStrongest", + boxShadow: "shadowBorderErrorStrongest", + color: "colorTextWeakest", }, _focus_hover: { - boxShadow: 'shadowFocus', + boxShadow: "shadowFocus", }, }, }; @@ -143,15 +143,15 @@ export const hoverPillStyles: VariantStyles = { export const baseCloseStyles: VariantStyles = { default: { _hover: { - cursor: 'pointer', - boxShadow: 'shadowBorderPrimaryStronger', + cursor: "pointer", + boxShadow: "shadowBorderPrimaryStronger", }, }, error: { _hover: { - backgroundColor: 'colorBackgroundErrorWeakest', - boxShadow: 'shadowBorderErrorStronger', - cursor: 'pointer', + backgroundColor: "colorBackgroundErrorWeakest", + boxShadow: "shadowBorderErrorStronger", + cursor: "pointer", }, }, }; @@ -159,53 +159,53 @@ export const baseCloseStyles: VariantStyles = { export const selectedBaseCloseStyles: VariantStyles = { default: { _hover: { - cursor: 'pointer', - backgroundColor: 'colorBackgroundPrimary', - boxShadow: 'shadowBorderPrimary', + cursor: "pointer", + backgroundColor: "colorBackgroundPrimary", + boxShadow: "shadowBorderPrimary", }, }, error: { _hover: { - cursor: 'pointer', - backgroundColor: 'colorBackgroundErrorStrongest', - boxShadow: 'shadowBorderErrorStrongest', + cursor: "pointer", + backgroundColor: "colorBackgroundErrorStrongest", + boxShadow: "shadowBorderErrorStrongest", }, }, }; export const closeInheritColorStyles: BoxStyleProps = { - color: 'inherit', + color: "inherit", _hover: { - color: 'inherit', + color: "inherit", }, }; export const closeColorStyles: VariantStyles = { default: { - color: 'colorTextIcon', + color: "colorTextIcon", _hover: { - color: 'colorTextPrimaryStronger', + color: "colorTextPrimaryStronger", }, }, error: { - color: 'colorTextIcon', + color: "colorTextIcon", _hover: { - color: 'colorTextErrorStronger', + color: "colorTextErrorStronger", }, }, }; export const selectedCloseColorStyles: VariantStyles = { default: { - color: 'colorTextWeakest', + color: "colorTextWeakest", _hover: { - color: 'colorTextInverse', + color: "colorTextInverse", }, }, error: { - color: 'colorTextInverse', + color: "colorTextInverse", _hover: { - color: 'colorTextWeakest', + color: "colorTextWeakest", }, }, }; diff --git a/packages/paste-core/components/form-pill-group/src/FormPill.tsx b/packages/paste-core/components/form-pill-group/src/FormPill.tsx index e76c4ca5b4..a65508e7b3 100644 --- a/packages/paste-core/components/form-pill-group/src/FormPill.tsx +++ b/packages/paste-core/components/form-pill-group/src/FormPill.tsx @@ -1,15 +1,15 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; -import {CompositeItem} from '@twilio-paste/reakit-library'; -import type {CompositeStateReturn} from '@twilio-paste/reakit-library'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import { CompositeItem } from "@twilio-paste/reakit-library"; +import type { CompositeStateReturn } from "@twilio-paste/reakit-library"; +import * as React from "react"; -import {PillCloseIcon} from './PillCloseIcon'; -import {FormPillButton} from './FormPillButton'; -import type {PillVariant} from './types'; -import {selectedWrapperStyles, wrapperStyles} from './FormPill.styles'; +import { selectedWrapperStyles, wrapperStyles } from "./FormPill.styles"; +import { FormPillButton } from "./FormPillButton"; +import { PillCloseIcon } from "./PillCloseIcon"; +import type { PillVariant } from "./types"; -interface FormPillProps extends CompositeStateReturn, Pick { +interface FormPillProps extends CompositeStateReturn, Pick { selected?: boolean; disabled?: boolean; children: React.ReactNode; @@ -45,20 +45,20 @@ interface FormPillProps extends CompositeStateReturn, Pick export const FormPill = React.forwardRef( ( { - element = 'FORM_PILL', + element = "FORM_PILL", onDismiss, onSelect, next, selected, - variant = 'default', + variant = "default", disabled = false, i18nErrorLabel, ...props }, - ref + ref, ) => { if (selected && disabled) { - throw new Error('[Paste FormPill] FormPills cannot be selected and disabled at the same time.'); + throw new Error("[Paste FormPill] FormPills cannot be selected and disabled at the same time."); } const isHoverable = onSelect != null; @@ -73,16 +73,16 @@ export const FormPill = React.forwardRef( // Handles delete and backspace keypresses const handleKeydown = React.useCallback( (event: React.KeyboardEvent) => { - if ((event.key === 'Backspace' || event.key === 'Delete') && typeof onDismiss === 'function') { + if ((event.key === "Backspace" || event.key === "Delete") && typeof onDismiss === "function") { onDismiss(event); // Focus the next pill upon removing the current one - if (typeof next === 'function') { + if (typeof next === "function") { next(); } } }, - [onDismiss, next] + [onDismiss, next], ); return ( ( ) : null} ); - } + }, ); -FormPill.displayName = 'FormPill'; +FormPill.displayName = "FormPill"; diff --git a/packages/paste-core/components/form-pill-group/src/FormPillButton.tsx b/packages/paste-core/components/form-pill-group/src/FormPillButton.tsx index 503b4e49ea..227f7aa763 100644 --- a/packages/paste-core/components/form-pill-group/src/FormPillButton.tsx +++ b/packages/paste-core/components/form-pill-group/src/FormPillButton.tsx @@ -1,16 +1,16 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxElementProps} from '@twilio-paste/box'; -import {ScreenReaderOnly} from '@twilio-paste/screen-reader-only'; -import {ErrorIcon} from '@twilio-paste/icons/esm/ErrorIcon'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxElementProps } from "@twilio-paste/box"; +import { ErrorIcon } from "@twilio-paste/icons/esm/ErrorIcon"; +import { ScreenReaderOnly } from "@twilio-paste/screen-reader-only"; +import * as React from "react"; -import {pillStyles, hoverPillStyles} from './FormPill.styles'; -import type {PillVariant} from './types'; +import { hoverPillStyles, pillStyles } from "./FormPill.styles"; +import type { PillVariant } from "./types"; interface FormPillStylesProps { variant?: PillVariant; selected?: boolean; - element?: BoxElementProps['element']; + element?: BoxElementProps["element"]; children: React.ReactNode; onKeyDown?: (event: React.KeyboardEvent) => void; onClick?: (event: React.MouseEvent) => void; @@ -24,20 +24,20 @@ interface FormPillStylesProps { export const FormPillButton = React.forwardRef( ( { - element = 'FORM_PILL', + element = "FORM_PILL", selected = false, - variant = 'default', + variant = "default", isHoverable = false, isDisabled = false, isDismissable = false, - i18nErrorLabel = '(error)', + i18nErrorLabel = "(error)", ...props }, - ref + ref, ) => { const computedStyles = React.useMemo(() => { const hasHoverStyles = isHoverable && !isDisabled; - return hasHoverStyles ? {...pillStyles[variant], ...hoverPillStyles[variant]} : pillStyles[variant]; + return hasHoverStyles ? { ...pillStyles[variant], ...hoverPillStyles[variant] } : pillStyles[variant]; }, [isHoverable, isDisabled, variant]); return ( @@ -61,12 +61,12 @@ export const FormPillButton = React.forwardRef fontWeight="fontWeightMedium" outline="none" paddingLeft="space30" - paddingRight={isDismissable ? 'space80' : 'space30'} + paddingRight={isDismissable ? "space80" : "space30"} transition="background-color 150ms ease-in, border-color 150ms ease-in, box-shadow 150ms ease-in, color 150ms ease-in" {...computedStyles} > - {variant === 'error' ? ( + {variant === "error" ? ( <> {i18nErrorLabel} @@ -76,7 +76,7 @@ export const FormPillButton = React.forwardRef ); - } + }, ); -FormPillButton.displayName = 'FormPillButton'; +FormPillButton.displayName = "FormPillButton"; diff --git a/packages/paste-core/components/form-pill-group/src/FormPillGroup.tsx b/packages/paste-core/components/form-pill-group/src/FormPillGroup.tsx index 843256e2ce..5376eb0cf2 100644 --- a/packages/paste-core/components/form-pill-group/src/FormPillGroup.tsx +++ b/packages/paste-core/components/form-pill-group/src/FormPillGroup.tsx @@ -1,22 +1,22 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxElementProps} from '@twilio-paste/box'; -import {ScreenReaderOnly} from '@twilio-paste/screen-reader-only'; -import {useUID} from '@twilio-paste/uid-library'; -import {Composite} from '@twilio-paste/reakit-library'; -import type {CompositeProps} from '@twilio-paste/reakit-library'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxElementProps } from "@twilio-paste/box"; +import { Composite } from "@twilio-paste/reakit-library"; +import type { CompositeProps } from "@twilio-paste/reakit-library"; +import { ScreenReaderOnly } from "@twilio-paste/screen-reader-only"; +import { useUID } from "@twilio-paste/uid-library"; +import * as React from "react"; export interface FormPillGroupProps - extends Omit { - 'aria-label': string; - element?: BoxElementProps['element']; + extends Omit { + "aria-label": string; + element?: BoxElementProps["element"]; children: React.ReactNode; i18nKeyboardControls?: string; - display?: 'flex' | 'inline-flex'; + display?: "flex" | "inline-flex"; } const FormPillGroupStyles = React.forwardRef( - ({element = 'FORM_PILL_GROUP', display = 'flex', ...props}, ref) => ( + ({ element = "FORM_PILL_GROUP", display = "flex", ...props }, ref) => ( {props.children} - ) + ), ); -FormPillGroupStyles.displayName = 'StyledFormPillGroup'; +FormPillGroupStyles.displayName = "StyledFormPillGroup"; /** * FormPillGroup should be used to wrap a collection of FormPills. It should be used in conjunction with @@ -48,7 +48,10 @@ FormPillGroupStyles.displayName = 'StyledFormPillGroup'; * @see http://paste.twilio.design/components/form-pill-group */ export const FormPillGroup = React.forwardRef( - ({i18nKeyboardControls = 'Press Delete or Backspace to remove. Press Enter to toggle selection.', ...props}, ref) => { + ( + { i18nKeyboardControls = "Press Delete or Backspace to remove. Press Enter to toggle selection.", ...props }, + ref, + ) => { const keyboardControlsId = useUID(); return ( <> @@ -58,7 +61,7 @@ export const FormPillGroup = React.forwardRef{i18nKeyboardControls} ); - } + }, ); -FormPillGroup.displayName = 'FormPillGroup'; +FormPillGroup.displayName = "FormPillGroup"; diff --git a/packages/paste-core/components/form-pill-group/src/PillCloseIcon.tsx b/packages/paste-core/components/form-pill-group/src/PillCloseIcon.tsx index c695e0efce..14594b2e60 100644 --- a/packages/paste-core/components/form-pill-group/src/PillCloseIcon.tsx +++ b/packages/paste-core/components/form-pill-group/src/PillCloseIcon.tsx @@ -1,8 +1,8 @@ -import * as React from 'react'; -import {Box} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; -import {CloseIcon} from '@twilio-paste/icons/esm/CloseIcon'; -import merge from 'deepmerge'; +import { Box } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import { CloseIcon } from "@twilio-paste/icons/esm/CloseIcon"; +import merge from "deepmerge"; +import * as React from "react"; import { baseCloseStyles, @@ -10,23 +10,23 @@ import { closeInheritColorStyles, selectedBaseCloseStyles, selectedCloseColorStyles, -} from './FormPill.styles'; -import type {PillVariant} from './types'; +} from "./FormPill.styles"; +import type { PillVariant } from "./types"; interface PillCloseIconProps { onClick?: (event: React.MouseEvent) => void; selected?: boolean; variant?: PillVariant; - element?: BoxProps['element']; + element?: BoxProps["element"]; pillIsHoverable?: boolean; } export const PillCloseIcon: React.FC> = ({ - element = 'FORM_PILL_CLOSE', + element = "FORM_PILL_CLOSE", // eslint-disable-next-line @typescript-eslint/no-empty-function onClick = () => {}, selected = false, - variant = 'default', + variant = "default", pillIsHoverable = false, }) => { const baseStyles = selected ? selectedBaseCloseStyles[variant] : baseCloseStyles[variant]; @@ -62,4 +62,4 @@ export const PillCloseIcon: React.FC ); }; -PillCloseIcon.displayName = 'PillCloseIcon'; +PillCloseIcon.displayName = "PillCloseIcon"; diff --git a/packages/paste-core/components/form-pill-group/src/index.tsx b/packages/paste-core/components/form-pill-group/src/index.tsx index b3c1ae2979..ab8e1dcb36 100644 --- a/packages/paste-core/components/form-pill-group/src/index.tsx +++ b/packages/paste-core/components/form-pill-group/src/index.tsx @@ -1,3 +1,3 @@ -export * from './FormPill'; -export * from './FormPillGroup'; -export * from './useFormPillState'; +export * from "./FormPill"; +export * from "./FormPillGroup"; +export * from "./useFormPillState"; diff --git a/packages/paste-core/components/form-pill-group/src/types.ts b/packages/paste-core/components/form-pill-group/src/types.ts index 80fa6704e5..d53e594ca5 100644 --- a/packages/paste-core/components/form-pill-group/src/types.ts +++ b/packages/paste-core/components/form-pill-group/src/types.ts @@ -1,4 +1,4 @@ -import type {BoxStyleProps} from '@twilio-paste/box'; +import type { BoxStyleProps } from "@twilio-paste/box"; -export type PillVariant = 'error' | 'default'; +export type PillVariant = "error" | "default"; export type VariantStyles = Record; diff --git a/packages/paste-core/components/form-pill-group/src/useFormPillState.tsx b/packages/paste-core/components/form-pill-group/src/useFormPillState.tsx index bf7d203385..54101b16f9 100644 --- a/packages/paste-core/components/form-pill-group/src/useFormPillState.tsx +++ b/packages/paste-core/components/form-pill-group/src/useFormPillState.tsx @@ -1,14 +1,14 @@ -import {useCompositeState} from '@twilio-paste/reakit-library'; -import type {CompositeInitialState, CompositeStateReturn as FormPillStateReturn} from '@twilio-paste/reakit-library'; +import { useCompositeState } from "@twilio-paste/reakit-library"; +import type { CompositeInitialState, CompositeStateReturn as FormPillStateReturn } from "@twilio-paste/reakit-library"; -export type {FormPillStateReturn}; -export type FormPillInitialState = Omit; +export type { FormPillStateReturn }; +export type FormPillInitialState = Omit; export const useFormPillState = (config: FormPillInitialState = {}): FormPillStateReturn => { return { ...useCompositeState({ ...config, - orientation: 'horizontal', // <- -> arrow keys + orientation: "horizontal", // <- -> arrow keys loop: true, // loops when reaches end of pill list }), }; diff --git a/packages/paste-core/components/form-pill-group/stories/customization.stories.tsx b/packages/paste-core/components/form-pill-group/stories/customization.stories.tsx index 3b077bce4b..1d6353433e 100644 --- a/packages/paste-core/components/form-pill-group/stories/customization.stories.tsx +++ b/packages/paste-core/components/form-pill-group/stories/customization.stories.tsx @@ -1,9 +1,9 @@ -import * as React from 'react'; -import {useTheme} from '@twilio-paste/theme'; -import {CustomizationProvider} from '@twilio-paste/customization'; -import {CalendarIcon} from '@twilio-paste/icons/esm/CalendarIcon'; +import { CustomizationProvider } from "@twilio-paste/customization"; +import { CalendarIcon } from "@twilio-paste/icons/esm/CalendarIcon"; +import { useTheme } from "@twilio-paste/theme"; +import * as React from "react"; -import {useFormPillState, FormPillGroup, FormPill} from '../src'; +import { FormPill, FormPillGroup, useFormPillState } from "../src"; export const CustomFormPillGroup = (): JSX.Element => { const currentTheme = useTheme(); @@ -15,21 +15,21 @@ export const CustomFormPillGroup = (): JSX.Element => { disableAnimations={true} theme={{ ...currentTheme, - fonts: {fontFamilyText: 'arial'}, + fonts: { fontFamilyText: "arial" }, }} elements={{ FORM_PILL_GROUP: { - margin: 'space40', + margin: "space40", }, FORM_PILL: { - backgroundColor: 'colorBackgroundNew', - color: 'colorText', - height: 'sizeIcon20', + backgroundColor: "colorBackgroundNew", + color: "colorText", + height: "sizeIcon20", }, FORM_PILL_CLOSE: { - color: 'colorText', - height: 'sizeIcon20', - width: 'sizeIcon20', + color: "colorText", + height: "sizeIcon20", + width: "sizeIcon20", }, }} > @@ -67,7 +67,7 @@ export const CustomFormPillGroup = (): JSX.Element => { // eslint-disable-next-line import/no-default-export export default { - title: 'Components/Form Pill Group/Customization', + title: "Components/Form Pill Group/Customization", component: FormPillGroup, parameters: { a11y: { diff --git a/packages/paste-core/components/form-pill-group/stories/index.stories.tsx b/packages/paste-core/components/form-pill-group/stories/index.stories.tsx index e3e0b20769..8a8b984ef2 100644 --- a/packages/paste-core/components/form-pill-group/stories/index.stories.tsx +++ b/packages/paste-core/components/form-pill-group/stories/index.stories.tsx @@ -1,22 +1,22 @@ -import * as React from 'react'; -import {Box} from '@twilio-paste/box'; -import {Avatar} from '@twilio-paste/avatar'; -import {CalendarIcon} from '@twilio-paste/icons/esm/CalendarIcon'; +import { Avatar } from "@twilio-paste/avatar"; +import { Box } from "@twilio-paste/box"; +import { CalendarIcon } from "@twilio-paste/icons/esm/CalendarIcon"; +import * as React from "react"; -import {useFormPillState, FormPillGroup, FormPill} from '../src'; +import { FormPill, FormPillGroup, useFormPillState } from "../src"; const PILL_NAMES = [ - 'Default pill', - 'Pill with icon', - 'Pill with avatar', - 'Error pill', - 'Error pill with icon', - 'Error pill with avatar', + "Default pill", + "Pill with icon", + "Pill with avatar", + "Error pill", + "Error pill with icon", + "Error pill with avatar", ]; export const Basic: React.FC< - React.PropsWithChildren<{selected?: boolean; dismissable?: boolean; disabled?: boolean; ariaLabel?: string}> -> = ({selected = false, dismissable = false, disabled = false, ariaLabel = 'Basic pills:'}) => { + React.PropsWithChildren<{ selected?: boolean; dismissable?: boolean; disabled?: boolean; ariaLabel?: string }> +> = ({ selected = false, dismissable = false, disabled = false, ariaLabel = "Basic pills:" }) => { const pillState = useFormPillState(); return (
    @@ -27,7 +27,7 @@ export const Basic: React.FC< data-testid={`form-pill-${index}`} {...pillState} selected={selected} - variant={index > 2 ? 'error' : 'default'} + variant={index > 2 ? "error" : "default"} onDismiss={dismissable ? () => {} : undefined} disabled={disabled} > @@ -65,7 +65,7 @@ export const SelectableAndDismissable = (): JSX.Element => { data-testid={`form-pill-${index}`} {...pillState} selected={selectedSet.has(pill)} - variant={index > 2 ? 'error' : 'default'} + variant={index > 2 ? "error" : "default"} onDismiss={() => { setPills(pills.filter((_, i) => i !== index)); }} @@ -89,7 +89,7 @@ export const SelectableAndDismissable = (): JSX.Element => { ); }; -const I18N_PILL_NAMES = ['Le tennis', 'Le football américain', 'Le ski', 'Le football']; +const I18N_PILL_NAMES = ["Le tennis", "Le football américain", "Le ski", "Le football"]; export const I18nProp = (): React.ReactNode => { const pillState = useFormPillState(); @@ -112,10 +112,10 @@ export const I18nProp = (): React.ReactNode => { ); }; -I18nProp.storyName = 'I18n Prop'; +I18nProp.storyName = "I18n Prop"; // eslint-disable-next-line import/no-default-export export default { - title: 'Components/Form Pill Group', + title: "Components/Form Pill Group", component: FormPillGroup, }; diff --git a/packages/paste-core/components/form/__tests__/index.spec.tsx b/packages/paste-core/components/form/__tests__/index.spec.tsx index f7895e5862..5b237db20d 100644 --- a/packages/paste-core/components/form/__tests__/index.spec.tsx +++ b/packages/paste-core/components/form/__tests__/index.spec.tsx @@ -1,6 +1,6 @@ -import * as React from 'react'; -import {render, screen} from '@testing-library/react'; -import {CustomizationProvider} from '@twilio-paste/customization'; +import { render, screen } from "@testing-library/react"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import * as React from "react"; import { Form, @@ -10,10 +10,10 @@ import { FormSection, FormSectionDescription, FormSectionHeading, -} from '../src'; +} from "../src"; -describe('Form', () => { - it('should render correctly', () => { +describe("Form", () => { + it("should render correctly", () => { render( @@ -23,43 +23,43 @@ describe('Form', () => { Two column content Control content Actions content - + , ); - const form = screen.getByRole('form'); + const form = screen.getByRole("form"); expect(form).toBeDefined(); - expect(form).toHaveAttribute('aria-label', 'My Form'); + expect(form).toHaveAttribute("aria-label", "My Form"); - const description = screen.getByTestId('section-desc'); - expect(description.id).toBe('foo-section-description'); + const description = screen.getByTestId("section-desc"); + expect(description.id).toBe("foo-section-description"); - const section = screen.getByRole('group', {name: 'Settings'}); + const section = screen.getByRole("group", { name: "Settings" }); expect(section).toBeDefined(); - expect(section).toHaveAttribute('aria-describedby', description.id); + expect(section).toHaveAttribute("aria-describedby", description.id); - expect(screen.getByTestId('section-heading').nodeName).toBe('LEGEND'); - expect(screen.getByText('Two column content')).toBeDefined(); - expect(screen.getByText('Control content')).toBeDefined(); - expect(screen.getByText('Actions content')).toBeDefined(); + expect(screen.getByTestId("section-heading").nodeName).toBe("LEGEND"); + expect(screen.getByText("Two column content")).toBeDefined(); + expect(screen.getByText("Control content")).toBeDefined(); + expect(screen.getByText("Actions content")).toBeDefined(); }); - it('should set the description id if no id prop is passed to the form section', () => { + it("should set the description id if no id prop is passed to the form section", () => { render( Section Description - +
    , ); - expect(screen.getByRole('group', {name: 'Section'})).toHaveAttribute( - 'aria-describedby', - screen.getByTestId('section-desc').id + expect(screen.getByRole("group", { name: "Section" })).toHaveAttribute( + "aria-describedby", + screen.getByTestId("section-desc").id, ); }); }); -describe('Form customization', () => { - it('should set an element data attribute', () => { +describe("Form customization", () => { + it("should set an element data attribute", () => { render(
    @@ -69,18 +69,18 @@ describe('Form customization', () => { Two column content Control content Actions content - + , ); - expect(screen.getByRole('form').dataset.pasteElement).toBe('FORM'); - expect(screen.getByRole('group', {name: 'Settings'}).dataset.pasteElement).toBe('FORM_SECTION'); - expect(screen.getByTestId('section-heading').dataset.pasteElement).toBe('FORM_SECTION_HEADING'); - expect(screen.getByText('Two column content').dataset.pasteElement).toBe('FORM_CONTROL_TWO_COLUMN'); - expect(screen.getByText('Control content').dataset.pasteElement).toBe('FORM_CONTROL'); - expect(screen.getByText('Actions content').dataset.pasteElement).toBe('FORM_ACTIONS'); + expect(screen.getByRole("form").dataset.pasteElement).toBe("FORM"); + expect(screen.getByRole("group", { name: "Settings" }).dataset.pasteElement).toBe("FORM_SECTION"); + expect(screen.getByTestId("section-heading").dataset.pasteElement).toBe("FORM_SECTION_HEADING"); + expect(screen.getByText("Two column content").dataset.pasteElement).toBe("FORM_CONTROL_TWO_COLUMN"); + expect(screen.getByText("Control content").dataset.pasteElement).toBe("FORM_CONTROL"); + expect(screen.getByText("Actions content").dataset.pasteElement).toBe("FORM_ACTIONS"); }); - it('should set a custom element data attribute', () => { + it("should set a custom element data attribute", () => { render(
    @@ -94,29 +94,29 @@ describe('Form customization', () => { Two column content Control content Actions content - + , ); - expect(screen.getByRole('form').dataset.pasteElement).toBe('MY_FORM'); - expect(screen.getByRole('group', {name: 'Settings'}).dataset.pasteElement).toBe('MY_FORM_SECTION'); - expect(screen.getByTestId('section-heading').dataset.pasteElement).toBe('MY_FORM_SECTION_HEADING'); - expect(screen.getByText('Two column content').dataset.pasteElement).toBe('MY_FORM_CONTROL_TWO_COLUMN'); - expect(screen.getByText('Control content').dataset.pasteElement).toBe('MY_FORM_CONTROL'); - expect(screen.getByText('Actions content').dataset.pasteElement).toBe('MY_FORM_ACTIONS'); + expect(screen.getByRole("form").dataset.pasteElement).toBe("MY_FORM"); + expect(screen.getByRole("group", { name: "Settings" }).dataset.pasteElement).toBe("MY_FORM_SECTION"); + expect(screen.getByTestId("section-heading").dataset.pasteElement).toBe("MY_FORM_SECTION_HEADING"); + expect(screen.getByText("Two column content").dataset.pasteElement).toBe("MY_FORM_CONTROL_TWO_COLUMN"); + expect(screen.getByText("Control content").dataset.pasteElement).toBe("MY_FORM_CONTROL"); + expect(screen.getByText("Actions content").dataset.pasteElement).toBe("MY_FORM_ACTIONS"); }); - it('should add custom styling', () => { + it("should add custom styling", () => { render(
    @@ -128,29 +128,29 @@ describe('Form customization', () => { Control content Actions content
    -
    +
    , ); - expect(screen.getByRole('form')).toHaveStyleRule('row-gap', '0.25rem'); - expect(screen.getByRole('group', {name: 'Settings'})).toHaveStyleRule('border-style', 'solid'); - expect(screen.getByTestId('section-heading')).toHaveStyleRule('background-color', 'rgb(254, 236, 236)'); - expect(screen.getByText('Two column content')).toHaveStyleRule('column-gap', '0.25rem'); - expect(screen.getByText('Control content')).toHaveStyleRule('flex-grow', 'unset'); - expect(screen.getByText('Actions content')).toHaveStyleRule('justify-content', 'center'); + expect(screen.getByRole("form")).toHaveStyleRule("row-gap", "0.25rem"); + expect(screen.getByRole("group", { name: "Settings" })).toHaveStyleRule("border-style", "solid"); + expect(screen.getByTestId("section-heading")).toHaveStyleRule("background-color", "rgb(254, 236, 236)"); + expect(screen.getByText("Two column content")).toHaveStyleRule("column-gap", "0.25rem"); + expect(screen.getByText("Control content")).toHaveStyleRule("flex-grow", "unset"); + expect(screen.getByText("Actions content")).toHaveStyleRule("justify-content", "center"); }); - it('should add custom styling to a custom named form', () => { + it("should add custom styling to a custom named form", () => { render(
    @@ -166,14 +166,14 @@ describe('Form customization', () => { Control content Actions content
    -
    + , ); - expect(screen.getByRole('form')).toHaveStyleRule('row-gap', '0.25rem'); - expect(screen.getByRole('group', {name: 'Settings'})).toHaveStyleRule('border-style', 'solid'); - expect(screen.getByTestId('section-heading')).toHaveStyleRule('background-color', 'rgb(254, 236, 236)'); - expect(screen.getByText('Two column content')).toHaveStyleRule('column-gap', '0.25rem'); - expect(screen.getByText('Control content')).toHaveStyleRule('flex-grow', 'unset'); - expect(screen.getByText('Actions content')).toHaveStyleRule('justify-content', 'center'); + expect(screen.getByRole("form")).toHaveStyleRule("row-gap", "0.25rem"); + expect(screen.getByRole("group", { name: "Settings" })).toHaveStyleRule("border-style", "solid"); + expect(screen.getByTestId("section-heading")).toHaveStyleRule("background-color", "rgb(254, 236, 236)"); + expect(screen.getByText("Two column content")).toHaveStyleRule("column-gap", "0.25rem"); + expect(screen.getByText("Control content")).toHaveStyleRule("flex-grow", "unset"); + expect(screen.getByText("Actions content")).toHaveStyleRule("justify-content", "center"); }); }); diff --git a/packages/paste-core/components/form/build.js b/packages/paste-core/components/form/build.js index a4edeab49b..27dd98f98e 100644 --- a/packages/paste-core/components/form/build.js +++ b/packages/paste-core/components/form/build.js @@ -1,3 +1,3 @@ -const {build} = require('../../../../tools/build/esbuild'); +const { build } = require("../../../../tools/build/esbuild"); -build(require('./package.json')); +build(require("./package.json")); diff --git a/packages/paste-core/components/form/src/Form.tsx b/packages/paste-core/components/form/src/Form.tsx index 62bce7cca4..e25fbbd4f9 100644 --- a/packages/paste-core/components/form/src/Form.tsx +++ b/packages/paste-core/components/form/src/Form.tsx @@ -1,15 +1,15 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxProps, BoxStyleProps} from '@twilio-paste/box'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps, BoxStyleProps } from "@twilio-paste/box"; +import * as React from "react"; -export interface FormProps extends Omit, 'children'> { - element?: BoxProps['element']; +export interface FormProps extends Omit, "children"> { + element?: BoxProps["element"]; children: React.ReactNode; - maxWidth?: BoxStyleProps['maxWidth']; + maxWidth?: BoxStyleProps["maxWidth"]; } export const Form = React.forwardRef( - ({element = 'FORM', maxWidth, children, ...props}, ref) => ( + ({ element = "FORM", maxWidth, children, ...props }, ref) => ( ( > {children} - ) + ), ); -Form.displayName = 'Form'; +Form.displayName = "Form"; diff --git a/packages/paste-core/components/form/src/FormActions.tsx b/packages/paste-core/components/form/src/FormActions.tsx index 4f645cff06..fd70d79d1e 100644 --- a/packages/paste-core/components/form/src/FormActions.tsx +++ b/packages/paste-core/components/form/src/FormActions.tsx @@ -1,14 +1,14 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import * as React from "react"; -export interface FormActionsProps extends Omit, 'children'> { - element?: BoxProps['element']; +export interface FormActionsProps extends Omit, "children"> { + element?: BoxProps["element"]; children: React.ReactNode; } export const FormActions = React.forwardRef( - ({children, element = 'FORM_ACTIONS', ...props}, ref) => ( + ({ children, element = "FORM_ACTIONS", ...props }, ref) => ( ( > {children} - ) + ), ); -FormActions.displayName = 'FormActions'; +FormActions.displayName = "FormActions"; diff --git a/packages/paste-core/components/form/src/FormControl.tsx b/packages/paste-core/components/form/src/FormControl.tsx index e3b4589c79..886574087c 100644 --- a/packages/paste-core/components/form/src/FormControl.tsx +++ b/packages/paste-core/components/form/src/FormControl.tsx @@ -1,18 +1,18 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import * as React from "react"; -export interface FormControlProps extends Omit, 'children'> { - element?: BoxProps['element']; +export interface FormControlProps extends Omit, "children"> { + element?: BoxProps["element"]; children: React.ReactNode; } export const FormControl = React.forwardRef( - ({children, element = 'FORM_CONTROL', ...props}, ref) => ( + ({ children, element = "FORM_CONTROL", ...props }, ref) => ( {children} - ) + ), ); -FormControl.displayName = 'FormControl'; +FormControl.displayName = "FormControl"; diff --git a/packages/paste-core/components/form/src/FormControlTwoColumn.tsx b/packages/paste-core/components/form/src/FormControlTwoColumn.tsx index 08b0b2ffa2..f454373150 100644 --- a/packages/paste-core/components/form/src/FormControlTwoColumn.tsx +++ b/packages/paste-core/components/form/src/FormControlTwoColumn.tsx @@ -1,14 +1,14 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import * as React from "react"; -export interface FormControlTwoColumnProps extends Omit, 'children'> { - element?: BoxProps['element']; +export interface FormControlTwoColumnProps extends Omit, "children"> { + element?: BoxProps["element"]; children: React.ReactNode; } export const FormControlTwoColumn = React.forwardRef( - ({children, element = 'FORM_CONTROL_TWO_COLUMN', ...props}, ref) => ( + ({ children, element = "FORM_CONTROL_TWO_COLUMN", ...props }, ref) => ( {children} - ) + ), ); -FormControlTwoColumn.displayName = 'FormControlTwoColumn'; +FormControlTwoColumn.displayName = "FormControlTwoColumn"; diff --git a/packages/paste-core/components/form/src/FormSection.tsx b/packages/paste-core/components/form/src/FormSection.tsx index 37bafa2d8c..79dd2b0da1 100644 --- a/packages/paste-core/components/form/src/FormSection.tsx +++ b/packages/paste-core/components/form/src/FormSection.tsx @@ -1,21 +1,21 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; -import {useUID} from '@twilio-paste/uid-library'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import { useUID } from "@twilio-paste/uid-library"; +import * as React from "react"; -import {FormSectionContext} from './FormSectionContext'; +import { FormSectionContext } from "./FormSectionContext"; -export interface FormSectionProps extends Omit, 'children'> { - element?: BoxProps['element']; +export interface FormSectionProps extends Omit, "children"> { + element?: BoxProps["element"]; children: React.ReactNode; } export const FormSection = React.forwardRef( - ({children, element = 'FORM_SECTION', id: idProp, ...props}, ref) => { + ({ children, element = "FORM_SECTION", id: idProp, ...props }, ref) => { const id = idProp ? idProp : useUID(); return ( - + ); - } + }, ); -FormSection.displayName = 'FormSection'; +FormSection.displayName = "FormSection"; diff --git a/packages/paste-core/components/form/src/FormSectionContext.tsx b/packages/paste-core/components/form/src/FormSectionContext.tsx index 6bf36e1350..44ac84fae2 100644 --- a/packages/paste-core/components/form/src/FormSectionContext.tsx +++ b/packages/paste-core/components/form/src/FormSectionContext.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import * as React from "react"; interface FormSectionContextProps { id?: string; diff --git a/packages/paste-core/components/form/src/FormSectionDescription.tsx b/packages/paste-core/components/form/src/FormSectionDescription.tsx index b7b67be56f..434ec26260 100644 --- a/packages/paste-core/components/form/src/FormSectionDescription.tsx +++ b/packages/paste-core/components/form/src/FormSectionDescription.tsx @@ -1,17 +1,17 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import * as React from "react"; -import {FormSectionContext} from './FormSectionContext'; +import { FormSectionContext } from "./FormSectionContext"; -export interface FormSectionDescriptionProps extends Omit, 'children' | 'id'> { - element?: BoxProps['element']; +export interface FormSectionDescriptionProps extends Omit, "children" | "id"> { + element?: BoxProps["element"]; children: React.ReactNode; } export const FormSectionDescription = React.forwardRef( - ({children, element = 'FORM_SECTION_DESCRIPTION', ...props}, ref) => { - const {id: sectionId} = React.useContext(FormSectionContext); + ({ children, element = "FORM_SECTION_DESCRIPTION", ...props }, ref) => { + const { id: sectionId } = React.useContext(FormSectionContext); return ( ); - } + }, ); -FormSectionDescription.displayName = 'FormSectionDescription'; +FormSectionDescription.displayName = "FormSectionDescription"; diff --git a/packages/paste-core/components/form/src/FormSectionHeading.tsx b/packages/paste-core/components/form/src/FormSectionHeading.tsx index 1c4aaf54c2..4b4d4c34fa 100644 --- a/packages/paste-core/components/form/src/FormSectionHeading.tsx +++ b/packages/paste-core/components/form/src/FormSectionHeading.tsx @@ -1,23 +1,23 @@ -import * as React from 'react'; -import {Heading} from '@twilio-paste/heading'; -import type {HeadingProps} from '@twilio-paste/heading'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import { Heading } from "@twilio-paste/heading"; +import type { HeadingProps } from "@twilio-paste/heading"; +import * as React from "react"; -export interface FormSectionHeadingProps extends Omit, 'children'> { - element?: BoxProps['element']; +export interface FormSectionHeadingProps extends Omit, "children"> { + element?: BoxProps["element"]; children: React.ReactNode; - variant?: HeadingProps['variant']; + variant?: HeadingProps["variant"]; } export const FormSectionHeading = React.forwardRef( - ({children, element = 'FORM_SECTION_HEADING', variant = 'heading40', ...props}, ref) => ( + ({ children, element = "FORM_SECTION_HEADING", variant = "heading40", ...props }, ref) => ( {children} - ) + ), ); -FormSectionHeading.displayName = 'FormSectionHeading'; +FormSectionHeading.displayName = "FormSectionHeading"; diff --git a/packages/paste-core/components/form/src/index.tsx b/packages/paste-core/components/form/src/index.tsx index 88bf5434fe..1a62c7465c 100644 --- a/packages/paste-core/components/form/src/index.tsx +++ b/packages/paste-core/components/form/src/index.tsx @@ -1,7 +1,7 @@ -export * from './Form'; -export * from './FormActions'; -export * from './FormControl'; -export * from './FormControlTwoColumn'; -export * from './FormSection'; -export * from './FormSectionDescription'; -export * from './FormSectionHeading'; +export * from "./Form"; +export * from "./FormActions"; +export * from "./FormControl"; +export * from "./FormControlTwoColumn"; +export * from "./FormSection"; +export * from "./FormSectionDescription"; +export * from "./FormSectionHeading"; diff --git a/packages/paste-core/components/form/stories/index.stories.tsx b/packages/paste-core/components/form/stories/index.stories.tsx index 3e5d46fc9c..a65e2a27ec 100644 --- a/packages/paste-core/components/form/stories/index.stories.tsx +++ b/packages/paste-core/components/form/stories/index.stories.tsx @@ -1,23 +1,23 @@ -import * as React from 'react'; -import type {StoryFn} from '@storybook/types'; -import {CustomizationProvider} from '@twilio-paste/customization'; -import {Box} from '@twilio-paste/box'; -import {Button} from '@twilio-paste/button'; -import {Callout, CalloutHeading, CalloutList, CalloutListItem} from '@twilio-paste/callout'; -import {CheckboxGroup, Checkbox} from '@twilio-paste/checkbox'; -import {Combobox, MultiselectCombobox} from '@twilio-paste/combobox'; -import {Heading} from '@twilio-paste/heading'; -import {HelpText} from '@twilio-paste/help-text'; -import {InformationIcon} from '@twilio-paste/icons/esm/InformationIcon'; -import {Input} from '@twilio-paste/input'; -import {Label} from '@twilio-paste/label'; -import {Paragraph} from '@twilio-paste/paragraph'; -import {RadioGroup, Radio} from '@twilio-paste/radio-group'; -import {ScreenReaderOnly} from '@twilio-paste/screen-reader-only'; -import {Select, Option} from '@twilio-paste/select'; -import {Separator} from '@twilio-paste/separator'; -import {useTheme} from '@twilio-paste/theme'; -import {useUIDSeed, useUID} from '@twilio-paste/uid-library'; +import type { StoryFn } from "@storybook/types"; +import { Box } from "@twilio-paste/box"; +import { Button } from "@twilio-paste/button"; +import { Callout, CalloutHeading, CalloutList, CalloutListItem } from "@twilio-paste/callout"; +import { Checkbox, CheckboxGroup } from "@twilio-paste/checkbox"; +import { Combobox, MultiselectCombobox } from "@twilio-paste/combobox"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import { Heading } from "@twilio-paste/heading"; +import { HelpText } from "@twilio-paste/help-text"; +import { InformationIcon } from "@twilio-paste/icons/esm/InformationIcon"; +import { Input } from "@twilio-paste/input"; +import { Label } from "@twilio-paste/label"; +import { Paragraph } from "@twilio-paste/paragraph"; +import { Radio, RadioGroup } from "@twilio-paste/radio-group"; +import { ScreenReaderOnly } from "@twilio-paste/screen-reader-only"; +import { Option, Select } from "@twilio-paste/select"; +import { Separator } from "@twilio-paste/separator"; +import { useTheme } from "@twilio-paste/theme"; +import { useUID, useUIDSeed } from "@twilio-paste/uid-library"; +import * as React from "react"; import { Form, @@ -27,11 +27,11 @@ import { FormSection, FormSectionDescription, FormSectionHeading, -} from '../src'; +} from "../src"; // eslint-disable-next-line import/no-default-export export default { - title: 'Components/Form', + title: "Components/Form", component: Form, subcomponents: { FormActions, @@ -44,50 +44,50 @@ export default { }; const countriesList = [ - 'Bangladesh', - 'Brazil', - 'China', - 'Ethiopia', - 'India', - 'Indonesia', - 'Japan', - 'Mexico', - 'Nigeria', - 'Pakistan', - 'Philippines', - 'United States', + "Bangladesh", + "Brazil", + "China", + "Ethiopia", + "India", + "Indonesia", + "Japan", + "Mexico", + "Nigeria", + "Pakistan", + "Philippines", + "United States", ]; const statesList = [ - {value: 'AK', name: 'Alaska'}, - {value: 'AL', name: 'Alabama'}, - {value: 'AZ', name: 'Arizona'}, - {value: 'CA', name: 'California'}, - {value: 'CO', name: 'Colorado'}, - {value: 'CT', name: 'Connecticut'}, - {value: 'ID', name: 'Idaho'}, - {value: 'IL', name: 'Illinois'}, - {value: 'IN', name: 'Indiana'}, - {value: 'KS', name: 'Kansas'}, - {value: 'KY', name: 'Kentucky'}, - {value: 'LA', name: 'Louisiana'}, - {value: 'MN', name: 'Minnesota'}, - {value: 'MO', name: 'Missouri'}, - {value: 'MS', name: 'Mississippi'}, - {value: 'MT', name: 'Montana'}, + { value: "AK", name: "Alaska" }, + { value: "AL", name: "Alabama" }, + { value: "AZ", name: "Arizona" }, + { value: "CA", name: "California" }, + { value: "CO", name: "Colorado" }, + { value: "CT", name: "Connecticut" }, + { value: "ID", name: "Idaho" }, + { value: "IL", name: "Illinois" }, + { value: "IN", name: "Indiana" }, + { value: "KS", name: "Kansas" }, + { value: "KY", name: "Kentucky" }, + { value: "LA", name: "Louisiana" }, + { value: "MN", name: "Minnesota" }, + { value: "MO", name: "Missouri" }, + { value: "MS", name: "Mississippi" }, + { value: "MT", name: "Montana" }, ]; const componentsList = [ - 'Alert', - 'Anchor', - 'Button', - 'Card', - 'Heading', - 'List', - 'Modal', - 'Paragraph', - 'Popover', - 'Tooltip', + "Alert", + "Anchor", + "Button", + "Card", + "Heading", + "List", + "Modal", + "Paragraph", + "Popover", + "Tooltip", ]; function getMultiselectComboboxFilteredItems(inputValue: string): string[] { @@ -100,15 +100,15 @@ function getMultiselectComboboxFilteredItems(inputValue: string): string[] { export const Default: StoryFn = () => { const seed = useUIDSeed(); - const [comboboxInputValue, setComboboxInputValue] = React.useState(''); + const [comboboxInputValue, setComboboxInputValue] = React.useState(""); const filteredItems = React.useMemo( () => getMultiselectComboboxFilteredItems(comboboxInputValue), - [comboboxInputValue] + [comboboxInputValue], ); return ( -
    - + + Profile settings {/* Added UID to the heading because forms are HTML Landmarks. Axe was failing because in the stacked view, there were 4 forms with the same name and landmarks have to have unique names. */} {useUID()} @@ -118,16 +118,16 @@ export const Default: StoryFn = () => { Contact information Please add the details of your contact information. - + } /> - - + + { helpText="Paste components are the building blocks of your product UI." items={filteredItems} initialSelectedItems={componentsList.slice(1, 3)} - onInputValueChange={({inputValue: newInputValue = ''}) => { + onInputValueChange={({ inputValue: newInputValue = "" }) => { setComboboxInputValue(newInputValue); }} /> @@ -147,34 +147,34 @@ export const Default: StoryFn = () => { Shipping address - - + + - - + + - - + + - - + + - - + + - - + {statesList.map(({ value, name }) => ( @@ -182,8 +182,8 @@ export const Default: StoryFn = () => { - - + + @@ -198,8 +198,8 @@ export const Default: StoryFn = () => { export const HorizontalForm: StoryFn = () => { const seed = useUIDSeed(); return ( - - + + Choose Network Access Profile {/* Added UID to the heading because forms are HTML Landmarks. Axe was failing because in the stacked view, there were 4 forms with the same name and landmarks have to have unique names. */} {useUID()} @@ -233,8 +233,8 @@ export const ErrorForm: StoryFn = () => { const seed = useUIDSeed(); return ( - - + + Settings {/* Added UID to the heading because forms are HTML Landmarks. Axe was failing because in the stacked view, there were 4 forms with the same name and landmarks have to have unique names. */} {useUID()} @@ -248,25 +248,25 @@ export const ErrorForm: StoryFn = () => { - - - + {statesList.map(({ value, name }) => ( @@ -274,21 +274,21 @@ export const ErrorForm: StoryFn = () => { - - @@ -304,8 +304,8 @@ export const FixedWidthForm: StoryFn = () => { const seed = useUIDSeed(); return ( - - + + Profile settings {/* Added UID to the heading because forms are HTML Landmarks. Axe was failing because in the stacked view, there were 4 forms with the same name and landmarks have to have unique names. */} {useUID()} @@ -315,16 +315,16 @@ export const FixedWidthForm: StoryFn = () => { Contact information Please add the details of your contact information. - + } /> - - + + @@ -332,34 +332,34 @@ export const FixedWidthForm: StoryFn = () => { Shipping address - - + + - - + + - - + + - - + + - - + + - - + {statesList.map(({ value, name }) => ( @@ -367,8 +367,8 @@ export const FixedWidthForm: StoryFn = () => { - - + + @@ -398,13 +398,13 @@ export const CustomizedForm: StoryFn = () => { {/* Added UID to the heading because forms are HTML Landmarks. Axe was failing because in the stacked view, there were 4 forms with the same name and landmarks have to have unique names. */} @@ -413,34 +413,34 @@ export const CustomizedForm: StoryFn = () => { Shipping address - - + + - - + + - - + + - - + + - - + + - - + {statesList.map(({ value, name }) => ( @@ -448,8 +448,8 @@ export const CustomizedForm: StoryFn = () => { - - + + diff --git a/packages/paste-core/components/heading/__tests__/heading.test.tsx b/packages/paste-core/components/heading/__tests__/heading.test.tsx index f748ca2187..71c4496e10 100644 --- a/packages/paste-core/components/heading/__tests__/heading.test.tsx +++ b/packages/paste-core/components/heading/__tests__/heading.test.tsx @@ -1,190 +1,190 @@ -import * as React from 'react'; -import {render, screen} from '@testing-library/react'; -import {Theme} from '@twilio-paste/theme'; -import {CustomizationProvider} from '@twilio-paste/customization'; +import { render, screen } from "@testing-library/react"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import { Theme } from "@twilio-paste/theme"; +import * as React from "react"; -import {Heading} from '../src'; +import { Heading } from "../src"; -describe('Heading', () => { - describe('Render', () => { - it('should render an H1 at fontSize90', (): void => { +describe("Heading", () => { + describe("Render", () => { + it("should render an H1 at fontSize90", (): void => { render( This is an H1 - + , ); - const renderedHeading = screen.getByRole('heading', {level: 1}); + const renderedHeading = screen.getByRole("heading", { level: 1 }); expect(renderedHeading).not.toBeNull(); - expect(renderedHeading).toHaveStyleRule('margin-bottom', '1.5rem'); - expect(renderedHeading).toHaveStyleRule('font-size', '2rem'); - expect(renderedHeading).toHaveStyleRule('font-weight', '600'); - expect(renderedHeading).toHaveStyleRule('line-height', '2.75rem'); + expect(renderedHeading).toHaveStyleRule("margin-bottom", "1.5rem"); + expect(renderedHeading).toHaveStyleRule("font-size", "2rem"); + expect(renderedHeading).toHaveStyleRule("font-weight", "600"); + expect(renderedHeading).toHaveStyleRule("line-height", "2.75rem"); }); - it('should render an H2 at fontSize70', (): void => { + it("should render an H2 at fontSize70", (): void => { render( This is an H2 - + , ); - const renderedHeading = screen.getByRole('heading', {level: 2}); + const renderedHeading = screen.getByRole("heading", { level: 2 }); expect(renderedHeading).not.toBeNull(); - expect(renderedHeading).toHaveStyleRule('margin-bottom', '1.25rem'); - expect(renderedHeading).toHaveStyleRule('font-size', '1.5rem'); - expect(renderedHeading).toHaveStyleRule('font-weight', '600'); - expect(renderedHeading).toHaveStyleRule('line-height', '2rem'); + expect(renderedHeading).toHaveStyleRule("margin-bottom", "1.25rem"); + expect(renderedHeading).toHaveStyleRule("font-size", "1.5rem"); + expect(renderedHeading).toHaveStyleRule("font-weight", "600"); + expect(renderedHeading).toHaveStyleRule("line-height", "2rem"); }); - it('should render an H3 at fontSize60', (): void => { + it("should render an H3 at fontSize60", (): void => { render( This is an H3 - + , ); - const renderedHeading = screen.getByRole('heading', {level: 3}); + const renderedHeading = screen.getByRole("heading", { level: 3 }); expect(renderedHeading).not.toBeNull(); - expect(renderedHeading).toHaveStyleRule('margin-bottom', '1rem'); - expect(renderedHeading).toHaveStyleRule('font-size', '1.25rem'); - expect(renderedHeading).toHaveStyleRule('font-weight', '600'); - expect(renderedHeading).toHaveStyleRule('line-height', '1.75rem'); + expect(renderedHeading).toHaveStyleRule("margin-bottom", "1rem"); + expect(renderedHeading).toHaveStyleRule("font-size", "1.25rem"); + expect(renderedHeading).toHaveStyleRule("font-weight", "600"); + expect(renderedHeading).toHaveStyleRule("line-height", "1.75rem"); }); - it('should render an H4 at fontSize40', (): void => { + it("should render an H4 at fontSize40", (): void => { render( This is an H4 - + , ); - const renderedHeading = screen.getByRole('heading', {level: 4}); + const renderedHeading = screen.getByRole("heading", { level: 4 }); expect(renderedHeading).not.toBeNull(); - expect(renderedHeading).toHaveStyleRule('margin-bottom', '0.75rem'); - expect(renderedHeading).toHaveStyleRule('font-size', '1rem'); - expect(renderedHeading).toHaveStyleRule('font-weight', '600'); - expect(renderedHeading).toHaveStyleRule('line-height', '1.5rem'); + expect(renderedHeading).toHaveStyleRule("margin-bottom", "0.75rem"); + expect(renderedHeading).toHaveStyleRule("font-size", "1rem"); + expect(renderedHeading).toHaveStyleRule("font-weight", "600"); + expect(renderedHeading).toHaveStyleRule("line-height", "1.5rem"); }); - it('should render an H5 at fontSize30', (): void => { + it("should render an H5 at fontSize30", (): void => { render( This is an H5 - + , ); - const renderedHeading = screen.getByRole('heading', {level: 5}); + const renderedHeading = screen.getByRole("heading", { level: 5 }); expect(renderedHeading).not.toBeNull(); - expect(renderedHeading).toHaveStyleRule('margin-bottom', '0.5rem'); - expect(renderedHeading).toHaveStyleRule('font-size', '0.875rem'); - expect(renderedHeading).toHaveStyleRule('font-weight', '600'); - expect(renderedHeading).toHaveStyleRule('line-height', '1.25rem'); + expect(renderedHeading).toHaveStyleRule("margin-bottom", "0.5rem"); + expect(renderedHeading).toHaveStyleRule("font-size", "0.875rem"); + expect(renderedHeading).toHaveStyleRule("font-weight", "600"); + expect(renderedHeading).toHaveStyleRule("line-height", "1.25rem"); }); - it('should render an H6 at fontSize20', (): void => { + it("should render an H6 at fontSize20", (): void => { render( This is an H6 - + , ); - const renderedHeading = screen.getByRole('heading', {level: 6}); + const renderedHeading = screen.getByRole("heading", { level: 6 }); expect(renderedHeading).not.toBeNull(); - expect(renderedHeading).toHaveStyleRule('margin-bottom', '0.5rem'); - expect(renderedHeading).toHaveStyleRule('font-size', '0.75rem'); - expect(renderedHeading).toHaveStyleRule('font-weight', '600'); - expect(renderedHeading).toHaveStyleRule('line-height', '1.25rem'); + expect(renderedHeading).toHaveStyleRule("margin-bottom", "0.5rem"); + expect(renderedHeading).toHaveStyleRule("font-size", "0.75rem"); + expect(renderedHeading).toHaveStyleRule("font-weight", "600"); + expect(renderedHeading).toHaveStyleRule("line-height", "1.25rem"); }); - it('should render an italic H2 at fontSize50', (): void => { + it("should render an italic H2 at fontSize50", (): void => { render( This is an italic H2 - + , ); - const renderedHeading = screen.getByRole('heading', {level: 2}); - const renderedHeadingIdiomatic = screen.getByText('This is an italic H2').closest('i'); + const renderedHeading = screen.getByRole("heading", { level: 2 }); + const renderedHeadingIdiomatic = screen.getByText("This is an italic H2").closest("i"); expect(renderedHeading).not.toBeNull(); expect(renderedHeadingIdiomatic).not.toBeNull(); - expect(renderedHeading).toHaveStyleRule('margin-bottom', '1.25rem'); - expect(renderedHeading).toHaveStyleRule('font-size', '1.5rem'); - expect(renderedHeading).toHaveStyleRule('font-weight', '600'); - expect(renderedHeading).toHaveStyleRule('line-height', '2rem'); + expect(renderedHeading).toHaveStyleRule("margin-bottom", "1.25rem"); + expect(renderedHeading).toHaveStyleRule("font-size", "1.5rem"); + expect(renderedHeading).toHaveStyleRule("font-weight", "600"); + expect(renderedHeading).toHaveStyleRule("line-height", "2rem"); }); - it('should render with no margin', (): void => { + it("should render with no margin", (): void => { render( no margin heading - + , ); - const renderedHeading = screen.getByRole('heading', {level: 2}); + const renderedHeading = screen.getByRole("heading", { level: 2 }); expect(renderedHeading).not.toBeNull(); - expect(renderedHeading).toHaveStyleRule('margin-bottom', '0'); + expect(renderedHeading).toHaveStyleRule("margin-bottom", "0"); }); }); - describe('HTML attributes', () => { - it('should set a element data attribute for Heading', () => { + describe("HTML attributes", () => { + it("should set a element data attribute for Heading", () => { render( heading - + , ); - expect(screen.getByRole('heading').getAttribute('data-paste-element')).toEqual('HEADING'); + expect(screen.getByRole("heading").getAttribute("data-paste-element")).toEqual("HEADING"); }); - it('should set a custom element data attribute for Heading', () => { + it("should set a custom element data attribute for Heading", () => { render( heading - + , ); - expect(screen.getByRole('heading').getAttribute('data-paste-element')).toEqual('foo'); + expect(screen.getByRole("heading").getAttribute("data-paste-element")).toEqual("foo"); }); }); - describe('Customization', () => { - it('should add custom styles to Heading', (): void => { + describe("Customization", () => { + it("should add custom styles to Heading", (): void => { render( Custom heading - + , ); - const renderedHeading = screen.getByRole('heading'); - expect(renderedHeading).toHaveStyleRule('background-color', 'rgb(244, 244, 246)'); - expect(renderedHeading).toHaveStyleRule('color', 'rgb(96, 107, 133)'); + const renderedHeading = screen.getByRole("heading"); + expect(renderedHeading).toHaveStyleRule("background-color", "rgb(244, 244, 246)"); + expect(renderedHeading).toHaveStyleRule("color", "rgb(96, 107, 133)"); }); - it('should add custom styles to a Heading variant', (): void => { + it("should add custom styles to a Heading variant", (): void => { render( { Custom heading - + , ); - const renderedHeading = screen.getByRole('heading'); - expect(renderedHeading).toHaveStyleRule('background-color', 'rgb(244, 244, 246)'); - expect(renderedHeading).toHaveStyleRule('color', 'rgb(2, 99, 224)'); - expect(renderedHeading).toHaveStyleRule('text-decoration', 'underline'); + const renderedHeading = screen.getByRole("heading"); + expect(renderedHeading).toHaveStyleRule("background-color", "rgb(244, 244, 246)"); + expect(renderedHeading).toHaveStyleRule("color", "rgb(2, 99, 224)"); + expect(renderedHeading).toHaveStyleRule("text-decoration", "underline"); }); - it('should add custom styles to Heading with a custom element data attribute', (): void => { + it("should add custom styles to Heading with a custom element data attribute", (): void => { render( Custom heading - + , ); - const renderedHeading = screen.getByRole('heading'); - expect(renderedHeading).toHaveStyleRule('background-color', 'rgb(244, 244, 246)'); - expect(renderedHeading).toHaveStyleRule('color', 'rgb(96, 107, 133)'); + const renderedHeading = screen.getByRole("heading"); + expect(renderedHeading).toHaveStyleRule("background-color", "rgb(244, 244, 246)"); + expect(renderedHeading).toHaveStyleRule("color", "rgb(96, 107, 133)"); }); - it('should add custom styles to a Heading variant with a custom element data attribute', (): void => { + it("should add custom styles to a Heading variant with a custom element data attribute", (): void => { render( { Custom heading - + , ); - const renderedHeading = screen.getByRole('heading'); - expect(renderedHeading).toHaveStyleRule('background-color', 'rgb(244, 244, 246)'); - expect(renderedHeading).toHaveStyleRule('color', 'rgb(2, 99, 224)'); - expect(renderedHeading).toHaveStyleRule('text-decoration', 'underline'); + const renderedHeading = screen.getByRole("heading"); + expect(renderedHeading).toHaveStyleRule("background-color", "rgb(244, 244, 246)"); + expect(renderedHeading).toHaveStyleRule("color", "rgb(2, 99, 224)"); + expect(renderedHeading).toHaveStyleRule("text-decoration", "underline"); }); }); }); diff --git a/packages/paste-core/components/heading/build.js b/packages/paste-core/components/heading/build.js index a4edeab49b..27dd98f98e 100644 --- a/packages/paste-core/components/heading/build.js +++ b/packages/paste-core/components/heading/build.js @@ -1,3 +1,3 @@ -const {build} = require('../../../../tools/build/esbuild'); +const { build } = require("../../../../tools/build/esbuild"); -build(require('./package.json')); +build(require("./package.json")); diff --git a/packages/paste-core/components/heading/src/index.tsx b/packages/paste-core/components/heading/src/index.tsx index baf0f9865a..323a90ab0c 100644 --- a/packages/paste-core/components/heading/src/index.tsx +++ b/packages/paste-core/components/heading/src/index.tsx @@ -1,69 +1,69 @@ -import * as React from 'react'; -import type {TextStyleProps} from '@twilio-paste/text'; -import {Text, safelySpreadTextProps} from '@twilio-paste/text'; +import type { TextStyleProps } from "@twilio-paste/text"; +import { Text, safelySpreadTextProps } from "@twilio-paste/text"; +import * as React from "react"; -import type {HeadingVariants, HeadingProps, AsTags} from './types'; +import type { AsTags, HeadingProps, HeadingVariants } from "./types"; -function getHeadingProps(headingVariant?: HeadingVariants, marginBottom?: 'space0'): TextStyleProps { +function getHeadingProps(headingVariant?: HeadingVariants, marginBottom?: "space0"): TextStyleProps { switch (headingVariant) { - case 'heading10': + case "heading10": return { - marginBottom: marginBottom || 'space70', - fontSize: 'fontSize90', - fontWeight: 'fontWeightSemibold', - lineHeight: 'lineHeight90', - letterSpacing: '-.02em', + marginBottom: marginBottom || "space70", + fontSize: "fontSize90", + fontWeight: "fontWeightSemibold", + lineHeight: "lineHeight90", + letterSpacing: "-.02em", }; - case 'heading30': + case "heading30": return { - marginBottom: marginBottom || 'space50', - fontSize: 'fontSize60', - fontWeight: 'fontWeightSemibold', - lineHeight: 'lineHeight60', - letterSpacing: '-.02em', + marginBottom: marginBottom || "space50", + fontSize: "fontSize60", + fontWeight: "fontWeightSemibold", + lineHeight: "lineHeight60", + letterSpacing: "-.02em", }; - case 'heading40': + case "heading40": return { - marginBottom: marginBottom || 'space40', - fontSize: 'fontSize40', - fontWeight: 'fontWeightSemibold', - lineHeight: 'lineHeight40', - letterSpacing: '-.02em', + marginBottom: marginBottom || "space40", + fontSize: "fontSize40", + fontWeight: "fontWeightSemibold", + lineHeight: "lineHeight40", + letterSpacing: "-.02em", }; - case 'heading50': + case "heading50": return { - marginBottom: marginBottom || 'space30', - fontSize: 'fontSize30', - fontWeight: 'fontWeightSemibold', - lineHeight: 'lineHeight30', - letterSpacing: '-.02em', + marginBottom: marginBottom || "space30", + fontSize: "fontSize30", + fontWeight: "fontWeightSemibold", + lineHeight: "lineHeight30", + letterSpacing: "-.02em", }; - case 'heading60': + case "heading60": return { - marginBottom: marginBottom || 'space30', - fontSize: 'fontSize20', - fontWeight: 'fontWeightSemibold', - lineHeight: 'lineHeight20', - letterSpacing: '-.02em', + marginBottom: marginBottom || "space30", + fontSize: "fontSize20", + fontWeight: "fontWeightSemibold", + lineHeight: "lineHeight20", + letterSpacing: "-.02em", }; /** * heading20 is out of order because its also default. * Default is at the bottom of switch statement for readability. */ - case 'heading20': + case "heading20": default: return { - marginBottom: marginBottom || 'space60', - fontSize: 'fontSize70', - fontWeight: 'fontWeightSemibold', - lineHeight: 'lineHeight70', - letterSpacing: '-.02em', + marginBottom: marginBottom || "space60", + fontSize: "fontSize70", + fontWeight: "fontWeightSemibold", + lineHeight: "lineHeight70", + letterSpacing: "-.02em", }; } } const Heading = React.forwardRef( - ({as, children, display = 'block', element = 'HEADING', id, marginBottom, variant, ...props}, ref) => { + ({ as, children, display = "block", element = "HEADING", id, marginBottom, variant, ...props }, ref) => { return ( ( {children} ); - } + }, ); -Heading.displayName = 'Heading'; +Heading.displayName = "Heading"; -export type {HeadingProps, HeadingVariants, AsTags as asTags}; -export {Heading}; +export type { HeadingProps, HeadingVariants, AsTags as asTags }; +export { Heading }; diff --git a/packages/paste-core/components/heading/src/types.ts b/packages/paste-core/components/heading/src/types.ts index bddac3a58e..fa77f6cb1a 100644 --- a/packages/paste-core/components/heading/src/types.ts +++ b/packages/paste-core/components/heading/src/types.ts @@ -1,12 +1,12 @@ -import type {TextProps} from '@twilio-paste/text'; -import type {HTMLPasteProps} from '@twilio-paste/types'; +import type { TextProps } from "@twilio-paste/text"; +import type { HTMLPasteProps } from "@twilio-paste/types"; -export type AsTags = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'div' | 'label' | 'span' | 'header'; -export type HeadingVariants = 'heading10' | 'heading20' | 'heading30' | 'heading40' | 'heading50' | 'heading60'; +export type AsTags = "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "div" | "label" | "span" | "header"; +export type HeadingVariants = "heading10" | "heading20" | "heading30" | "heading40" | "heading50" | "heading60"; -export interface HeadingProps extends HTMLPasteProps, Pick { +export interface HeadingProps extends HTMLPasteProps, Pick { as: AsTags; id?: string; - marginBottom?: 'space0'; + marginBottom?: "space0"; variant: HeadingVariants; } diff --git a/packages/paste-core/components/heading/stories/index.stories.tsx b/packages/paste-core/components/heading/stories/index.stories.tsx index a2d4cc5452..366e21f508 100644 --- a/packages/paste-core/components/heading/stories/index.stories.tsx +++ b/packages/paste-core/components/heading/stories/index.stories.tsx @@ -1,15 +1,15 @@ -import * as React from 'react'; -import type {StoryFn} from '@storybook/react'; -import {useTheme} from '@twilio-paste/theme'; -import {CustomizationProvider} from '@twilio-paste/customization'; -import {Card} from '@twilio-paste/card'; -import {Stack} from '@twilio-paste/stack'; +import type { StoryFn } from "@storybook/react"; +import { Card } from "@twilio-paste/card"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import { Stack } from "@twilio-paste/stack"; +import { useTheme } from "@twilio-paste/theme"; +import * as React from "react"; -import {Heading} from '../src'; +import { Heading } from "../src"; // eslint-disable-next-line import/no-default-export export default { - title: 'Components/Heading', + title: "Components/Heading", component: Heading, }; @@ -21,7 +21,7 @@ export const Heading10 = (): React.ReactNode => { ); }; -Heading10.storyName = 'heading10'; +Heading10.storyName = "heading10"; export const Heading20 = (): React.ReactNode => { return ( @@ -31,7 +31,7 @@ export const Heading20 = (): React.ReactNode => { ); }; -Heading20.storyName = 'heading20'; +Heading20.storyName = "heading20"; export const Heading30 = (): React.ReactNode => { return ( @@ -41,7 +41,7 @@ export const Heading30 = (): React.ReactNode => { ); }; -Heading30.storyName = 'heading30'; +Heading30.storyName = "heading30"; export const Heading40 = (): React.ReactNode => { return ( @@ -51,7 +51,7 @@ export const Heading40 = (): React.ReactNode => { ); }; -Heading40.storyName = 'heading40'; +Heading40.storyName = "heading40"; export const Heading50 = (): React.ReactNode => { return ( @@ -61,7 +61,7 @@ export const Heading50 = (): React.ReactNode => { ); }; -Heading50.storyName = 'heading50'; +Heading50.storyName = "heading50"; export const Heading60 = (): React.ReactNode => { return ( @@ -71,7 +71,7 @@ export const Heading60 = (): React.ReactNode => { ); }; -Heading60.storyName = 'heading60'; +Heading60.storyName = "heading60"; export const Heading10NoMargin = (): React.ReactNode => { return ( @@ -83,7 +83,7 @@ export const Heading10NoMargin = (): React.ReactNode => { ); }; -Heading10NoMargin.storyName = 'heading10 no margin'; +Heading10NoMargin.storyName = "heading10 no margin"; export const Heading20NoMargin = (): React.ReactNode => { return ( @@ -95,7 +95,7 @@ export const Heading20NoMargin = (): React.ReactNode => { ); }; -Heading20NoMargin.storyName = 'heading20 no margin'; +Heading20NoMargin.storyName = "heading20 no margin"; export const Heading30NoMargin = (): React.ReactNode => { return ( @@ -107,7 +107,7 @@ export const Heading30NoMargin = (): React.ReactNode => { ); }; -Heading30NoMargin.storyName = 'heading30 no margin'; +Heading30NoMargin.storyName = "heading30 no margin"; export const Heading40NoMargin = (): React.ReactNode => { return ( @@ -119,7 +119,7 @@ export const Heading40NoMargin = (): React.ReactNode => { ); }; -Heading40NoMargin.storyName = 'heading40 no margin'; +Heading40NoMargin.storyName = "heading40 no margin"; export const Heading50NoMargin = (): React.ReactNode => { return ( @@ -131,7 +131,7 @@ export const Heading50NoMargin = (): React.ReactNode => { ); }; -Heading50NoMargin.storyName = 'heading50 no margin'; +Heading50NoMargin.storyName = "heading50 no margin"; export const Heading60NoMargin = (): React.ReactNode => { return ( @@ -143,9 +143,9 @@ export const Heading60NoMargin = (): React.ReactNode => { ); }; -Heading60NoMargin.storyName = 'heading60 no margin'; +Heading60NoMargin.storyName = "heading60 no margin"; -export const CustomHeading: StoryFn = (_args, {parameters: {isTestEnvironment}}) => { +export const CustomHeading: StoryFn = (_args, { parameters: { isTestEnvironment } }) => { const currentTheme = useTheme(); return ( @@ -157,17 +157,17 @@ export const CustomHeading: StoryFn = (_args, {parameters: {isTestEnvironment}}) theme={currentTheme} elements={{ HEADING: { - backgroundColor: 'colorBackgroundPrimaryWeaker', - color: 'colorTextError', - padding: 'space40', - textDecoration: 'underline', + backgroundColor: "colorBackgroundPrimaryWeaker", + color: "colorTextError", + padding: "space40", + textDecoration: "underline", variants: { heading10: { - color: 'colorTextError', + color: "colorTextError", }, heading20: { - color: 'colorTextLink', - textDecoration: 'none', + color: "colorTextLink", + textDecoration: "none", }, }, }, @@ -185,16 +185,16 @@ export const CustomHeading: StoryFn = (_args, {parameters: {isTestEnvironment}}) theme={currentTheme} elements={{ NEW_HEADING: { - backgroundColor: 'colorBackgroundTrial', - color: 'colorTextLink', - padding: 'space60', + backgroundColor: "colorBackgroundTrial", + color: "colorTextLink", + padding: "space60", variants: { heading10: { - color: 'colorTextLink', + color: "colorTextLink", }, heading20: { - color: 'colorTextError', - textDecoration: 'underline', + color: "colorTextError", + textDecoration: "underline", }, }, }, diff --git a/packages/paste-core/components/help-text/__tests__/helptext.test.tsx b/packages/paste-core/components/help-text/__tests__/helptext.test.tsx index 786dd7801d..95037ec85e 100644 --- a/packages/paste-core/components/help-text/__tests__/helptext.test.tsx +++ b/packages/paste-core/components/help-text/__tests__/helptext.test.tsx @@ -1,48 +1,48 @@ -import * as React from 'react'; -import {CustomizationProvider} from '@twilio-paste/customization'; -import {render, screen} from '@testing-library/react'; +import { render, screen } from "@testing-library/react"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import * as React from "react"; -import {HelpText} from '../src'; +import { HelpText } from "../src"; -describe('HelpText marginTop prop', () => { +describe("HelpText marginTop prop", () => { render(); - it('should have marginTop: space0', () => { - expect(screen.getByTestId('help_text')).toHaveStyleRule('margin-top', 'space0'); + it("should have marginTop: space0", () => { + expect(screen.getByTestId("help_text")).toHaveStyleRule("margin-top", "space0"); }); }); -describe('HelpText HTML attributes', () => { - it('should set element data attribute for help text', (): void => { - const {container} = render(This is help text.); +describe("HelpText HTML attributes", () => { + it("should set element data attribute for help text", (): void => { + const { container } = render(This is help text.); expect(container.querySelector('[data-paste-element="HELP_TEXT"]')).toBeInTheDocument(); - expect(screen.getByTestId('help_text').getAttribute('data-paste-element')).toEqual('HELP_TEXT'); + expect(screen.getByTestId("help_text").getAttribute("data-paste-element")).toEqual("HELP_TEXT"); }); - it('should set custom element data attribute for flex wrapper and help text', (): void => { - const {container} = render( + it("should set custom element data attribute for flex wrapper and help text", (): void => { + const { container } = render( This is help text. - + , ); expect(container.querySelector('[data-paste-element="foo"]')).toBeInTheDocument(); - expect(screen.getByTestId('help_text').getAttribute('data-paste-element')).toEqual('foo'); + expect(screen.getByTestId("help_text").getAttribute("data-paste-element")).toEqual("foo"); }); }); -describe('Customization', () => { - it('should customize help text default and error variant', (): void => { +describe("Customization", () => { + it("should customize help text default and error variant", (): void => { render( @@ -50,23 +50,23 @@ describe('Customization', () => { This is error help text. - + , ); - expect(screen.getByTestId('help_text')).toHaveStyleRule('font-weight', '700'); - expect(screen.getByTestId('help_text')).toHaveStyleRule('color', 'rgb(14, 124, 58)'); - expect(screen.getByTestId('help_text_error')).toHaveStyleRule('color', 'rgb(141, 49, 24)'); + expect(screen.getByTestId("help_text")).toHaveStyleRule("font-weight", "700"); + expect(screen.getByTestId("help_text")).toHaveStyleRule("color", "rgb(14, 124, 58)"); + expect(screen.getByTestId("help_text_error")).toHaveStyleRule("color", "rgb(141, 49, 24)"); }); - it('should customize help text default and error variant with custom element name', (): void => { + it("should customize help text default and error variant with custom element name", (): void => { render( @@ -76,10 +76,10 @@ describe('Customization', () => { This is error help text. - + , ); - expect(screen.getByTestId('help_text')).toHaveStyleRule('font-weight', '700'); - expect(screen.getByTestId('help_text')).toHaveStyleRule('color', 'rgb(14, 124, 58)'); - expect(screen.getByTestId('help_text_error')).toHaveStyleRule('color', 'rgb(141, 49, 24)'); + expect(screen.getByTestId("help_text")).toHaveStyleRule("font-weight", "700"); + expect(screen.getByTestId("help_text")).toHaveStyleRule("color", "rgb(14, 124, 58)"); + expect(screen.getByTestId("help_text_error")).toHaveStyleRule("color", "rgb(141, 49, 24)"); }); }); diff --git a/packages/paste-core/components/help-text/build.js b/packages/paste-core/components/help-text/build.js index a4edeab49b..27dd98f98e 100644 --- a/packages/paste-core/components/help-text/build.js +++ b/packages/paste-core/components/help-text/build.js @@ -1,3 +1,3 @@ -const {build} = require('../../../../tools/build/esbuild'); +const { build } = require("../../../../tools/build/esbuild"); -build(require('./package.json')); +build(require("./package.json")); diff --git a/packages/paste-core/components/help-text/src/HelpText.tsx b/packages/paste-core/components/help-text/src/HelpText.tsx index 9ffc5fe5b4..d505dda5bd 100644 --- a/packages/paste-core/components/help-text/src/HelpText.tsx +++ b/packages/paste-core/components/help-text/src/HelpText.tsx @@ -1,26 +1,26 @@ -import * as React from 'react'; -import type {HTMLPasteProps, ValueOf} from '@twilio-paste/types'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; -import type {TextColor} from '@twilio-paste/style-props'; -import {ErrorIcon} from '@twilio-paste/icons/esm/ErrorIcon'; -import {SuccessIcon} from '@twilio-paste/icons/esm/SuccessIcon'; -import {WarningIcon} from '@twilio-paste/icons/esm/WarningIcon'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import { ErrorIcon } from "@twilio-paste/icons/esm/ErrorIcon"; +import { SuccessIcon } from "@twilio-paste/icons/esm/SuccessIcon"; +import { WarningIcon } from "@twilio-paste/icons/esm/WarningIcon"; +import type { TextColor } from "@twilio-paste/style-props"; +import type { HTMLPasteProps, ValueOf } from "@twilio-paste/types"; +import * as React from "react"; export const HelpTextVariants = { - DEFAULT: 'default', - ERROR: 'error', - ERROR_INVERSE: 'error_inverse', - INVERSE: 'inverse', - SUCCESS: 'success', - WARNING: 'warning', + DEFAULT: "default", + ERROR: "error", + ERROR_INVERSE: "error_inverse", + INVERSE: "inverse", + SUCCESS: "success", + WARNING: "warning", } as const; // eslint-disable-next-line @typescript-eslint/no-redeclare export type HelpTextVariants = ValueOf; -export interface HelpTextProps extends HTMLPasteProps<'div'>, Pick { - marginTop?: 'space0'; +export interface HelpTextProps extends HTMLPasteProps<"div">, Pick { + marginTop?: "space0"; variant?: HelpTextVariants; } @@ -32,15 +32,15 @@ type VariantOptionsProps = { }; const VariantOptions: VariantOptionsProps = { [HelpTextVariants.DEFAULT]: { - textColor: 'colorTextWeak', + textColor: "colorTextWeak", icon: null, }, [HelpTextVariants.INVERSE]: { - textColor: 'colorTextInverseWeaker', + textColor: "colorTextInverseWeaker", icon: null, }, [HelpTextVariants.ERROR]: { - textColor: 'colorTextError', + textColor: "colorTextError", icon: ( @@ -48,7 +48,7 @@ const VariantOptions: VariantOptionsProps = { ), }, [HelpTextVariants.ERROR_INVERSE]: { - textColor: 'colorTextErrorWeak', + textColor: "colorTextErrorWeak", icon: ( @@ -56,7 +56,7 @@ const VariantOptions: VariantOptionsProps = { ), }, [HelpTextVariants.SUCCESS]: { - textColor: 'colorTextSuccess', + textColor: "colorTextSuccess", icon: ( @@ -64,7 +64,7 @@ const VariantOptions: VariantOptionsProps = { ), }, [HelpTextVariants.WARNING]: { - textColor: 'colorTextWarning', + textColor: "colorTextWarning", icon: ( @@ -74,15 +74,15 @@ const VariantOptions: VariantOptionsProps = { }; const HelpText = React.forwardRef( - ({marginTop, children, variant = 'default', element = 'HELP_TEXT', ...props}, ref) => { - const {textColor, icon} = VariantOptions[variant]; + ({ marginTop, children, variant = "default", element = "HELP_TEXT", ...props }, ref) => { + const { textColor, icon } = VariantOptions[variant]; return ( ( {children} ); - } + }, ); -HelpText.displayName = 'HelpText'; +HelpText.displayName = "HelpText"; -export {HelpText}; +export { HelpText }; diff --git a/packages/paste-core/components/help-text/src/index.tsx b/packages/paste-core/components/help-text/src/index.tsx index 45df2b3798..2cc13d2186 100644 --- a/packages/paste-core/components/help-text/src/index.tsx +++ b/packages/paste-core/components/help-text/src/index.tsx @@ -1 +1 @@ -export * from './HelpText'; +export * from "./HelpText"; diff --git a/packages/paste-core/components/help-text/stories/input.stories.tsx b/packages/paste-core/components/help-text/stories/input.stories.tsx index 7c433e4b39..5134a8c2cc 100644 --- a/packages/paste-core/components/help-text/stories/input.stories.tsx +++ b/packages/paste-core/components/help-text/stories/input.stories.tsx @@ -1,17 +1,17 @@ -import * as React from 'react'; -import type {StoryFn} from '@storybook/react'; -import {Box} from '@twilio-paste/box'; -import {Paragraph} from '@twilio-paste/paragraph'; -import {CustomizationProvider} from '@twilio-paste/customization'; -import {Stack} from '@twilio-paste/stack'; -import {Card} from '@twilio-paste/card'; -import {useTheme} from '@twilio-paste/theme'; +import type { StoryFn } from "@storybook/react"; +import { Box } from "@twilio-paste/box"; +import { Card } from "@twilio-paste/card"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import { Paragraph } from "@twilio-paste/paragraph"; +import { Stack } from "@twilio-paste/stack"; +import { useTheme } from "@twilio-paste/theme"; +import * as React from "react"; -import {HelpText} from '../src'; +import { HelpText } from "../src"; // eslint-disable-next-line import/no-default-export export default { - title: 'Components/Help Text', + title: "Components/Help Text", component: HelpText, }; @@ -29,7 +29,7 @@ export const Default = (): React.ReactNode => { ); }; -Default.storyName = 'Default'; +Default.storyName = "Default"; export const Inverse = (): React.ReactNode => { return ( @@ -40,9 +40,9 @@ export const Inverse = (): React.ReactNode => { ); }; -Inverse.storyName = 'Inverse'; +Inverse.storyName = "Inverse"; -export const Customized: StoryFn = (_args, {parameters: {isTestEnvironment}}) => { +export const Customized: StoryFn = (_args, { parameters: { isTestEnvironment } }) => { const currentTheme = useTheme(); return ( <> @@ -64,12 +64,12 @@ export const Customized: StoryFn = (_args, {parameters: {isTestEnvironment}}) => theme={currentTheme} elements={{ HELP_TEXT: { - color: 'colorTextSuccess', - fontWeight: 'fontWeightBold', + color: "colorTextSuccess", + fontWeight: "fontWeightBold", variants: { - error: {color: 'colorTextWarningStrong'}, - success: {color: 'colorTextLinkStrong'}, - warning: {color: 'colorTextErrorStronger'}, + error: { color: "colorTextWarningStrong" }, + success: { color: "colorTextLinkStrong" }, + warning: { color: "colorTextErrorStronger" }, }, }, }} @@ -89,12 +89,12 @@ export const Customized: StoryFn = (_args, {parameters: {isTestEnvironment}}) => theme={currentTheme} elements={{ foo: { - color: 'colorTextSuccess', - fontWeight: 'fontWeightBold', + color: "colorTextSuccess", + fontWeight: "fontWeightBold", variants: { - error: {color: 'colorTextWarningStrong'}, - success: {color: 'colorTextLinkStrong'}, - warning: {color: 'colorTextErrorStronger'}, + error: { color: "colorTextWarningStrong" }, + success: { color: "colorTextLinkStrong" }, + warning: { color: "colorTextErrorStronger" }, }, }, }} diff --git a/packages/paste-core/components/in-page-navigation/__tests__/index.spec.tsx b/packages/paste-core/components/in-page-navigation/__tests__/index.spec.tsx index ddc8c9b8b5..af1a878194 100644 --- a/packages/paste-core/components/in-page-navigation/__tests__/index.spec.tsx +++ b/packages/paste-core/components/in-page-navigation/__tests__/index.spec.tsx @@ -1,49 +1,49 @@ -import * as React from 'react'; -import {render} from '@testing-library/react'; -import {CustomizationProvider} from '@twilio-paste/customization'; +import { render } from "@testing-library/react"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import * as React from "react"; -import {InPageNavigation, InPageNavigationItem} from '../src'; +import { InPageNavigation, InPageNavigationItem } from "../src"; -describe('InPageNavigation', () => { - it('should render a nav with correct aria-label', () => { - const {getByRole} = render( +describe("InPageNavigation", () => { + it("should render a nav with correct aria-label", () => { + const { getByRole } = render( page 1 page 2 - + , ); - expect(getByRole('navigation')).toHaveAttribute('aria-label', 'my-nav'); + expect(getByRole("navigation")).toHaveAttribute("aria-label", "my-nav"); }); - it('should render a list with list items and links', () => { - const {getAllByRole} = render( + it("should render a list with list items and links", () => { + const { getAllByRole } = render( page 1 page 2 - + , ); - expect(getAllByRole('list')).toHaveLength(1); - expect(getAllByRole('listitem')).toHaveLength(2); - expect(getAllByRole('link')).toHaveLength(2); + expect(getAllByRole("list")).toHaveLength(1); + expect(getAllByRole("listitem")).toHaveLength(2); + expect(getAllByRole("link")).toHaveLength(2); }); - it('should use the currentPage prop to apply aria-current', () => { - const {getByText} = render( + it("should use the currentPage prop to apply aria-current", () => { + const { getByText } = render( page 1 page 2 - + , ); - expect(getByText('page 2')).toHaveAttribute('aria-current', 'page'); + expect(getByText("page 2")).toHaveAttribute("aria-current", "page"); }); - it('should pass props given to InPageNavigationItem onto its child', () => { - const {getByText} = render( + it("should pass props given to InPageNavigationItem onto its child", () => { + const { getByText } = render( page 1 @@ -51,76 +51,76 @@ describe('InPageNavigation', () => { page 2 - + , ); - expect(getByText('page 1')).toHaveAttribute('data-test-id', 'page-1'); + expect(getByText("page 1")).toHaveAttribute("data-test-id", "page-1"); }); }); -describe('Customization', () => { - it('should set a default element name', () => { - const {getByRole} = render( +describe("Customization", () => { + it("should set a default element name", () => { + const { getByRole } = render( page 1 - + , ); - expect(getByRole('navigation')).toHaveAttribute('data-paste-element', 'IN_PAGE_NAVIGATION'); - expect(getByRole('list')).toHaveAttribute('data-paste-element', 'IN_PAGE_NAVIGATION_ITEMS'); - expect(getByRole('listitem')).toHaveAttribute('data-paste-element', 'IN_PAGE_NAVIGATION_ITEM'); - expect(getByRole('link')).toHaveAttribute('data-paste-element', 'IN_PAGE_NAVIGATION_ITEM_ANCHOR'); + expect(getByRole("navigation")).toHaveAttribute("data-paste-element", "IN_PAGE_NAVIGATION"); + expect(getByRole("list")).toHaveAttribute("data-paste-element", "IN_PAGE_NAVIGATION_ITEMS"); + expect(getByRole("listitem")).toHaveAttribute("data-paste-element", "IN_PAGE_NAVIGATION_ITEM"); + expect(getByRole("link")).toHaveAttribute("data-paste-element", "IN_PAGE_NAVIGATION_ITEM_ANCHOR"); }); - it('should set a custom element name when provided', () => { - const {getByRole} = render( + it("should set a custom element name when provided", () => { + const { getByRole } = render( page 1 - + , ); - expect(getByRole('navigation')).toHaveAttribute('data-paste-element', 'MY_IN_PAGE_NAVIGATION'); - expect(getByRole('list')).toHaveAttribute('data-paste-element', 'MY_IN_PAGE_NAVIGATION_ITEMS'); - expect(getByRole('listitem')).toHaveAttribute('data-paste-element', 'MY_IN_PAGE_NAVIGATION_ITEM'); - expect(getByRole('link')).toHaveAttribute('data-paste-element', 'MY_IN_PAGE_NAVIGATION_ITEM_ANCHOR'); + expect(getByRole("navigation")).toHaveAttribute("data-paste-element", "MY_IN_PAGE_NAVIGATION"); + expect(getByRole("list")).toHaveAttribute("data-paste-element", "MY_IN_PAGE_NAVIGATION_ITEMS"); + expect(getByRole("listitem")).toHaveAttribute("data-paste-element", "MY_IN_PAGE_NAVIGATION_ITEM"); + expect(getByRole("link")).toHaveAttribute("data-paste-element", "MY_IN_PAGE_NAVIGATION_ITEM_ANCHOR"); }); - it('should add custom styles to default element names', () => { - const {getByRole} = render( + it("should add custom styles to default element names", () => { + const { getByRole } = render( page 1 - + , ); - expect(getByRole('navigation')).toHaveStyleRule('font-weight', '400'); - expect(getByRole('list')).toHaveStyleRule('padding', '0.75rem'); - expect(getByRole('listitem')).toHaveStyleRule('margin', '0.75rem'); - expect(getByRole('link')).toHaveStyleRule('font-size', '1rem'); + expect(getByRole("navigation")).toHaveStyleRule("font-weight", "400"); + expect(getByRole("list")).toHaveStyleRule("padding", "0.75rem"); + expect(getByRole("listitem")).toHaveStyleRule("margin", "0.75rem"); + expect(getByRole("link")).toHaveStyleRule("font-size", "1rem"); }); - it('should add custom styles to custom element names', () => { - const {getByRole} = render( + it("should add custom styles to custom element names", () => { + const { getByRole } = render( @@ -128,12 +128,12 @@ describe('Customization', () => { page 1 - + , ); - expect(getByRole('navigation')).toHaveStyleRule('font-weight', '400'); - expect(getByRole('list')).toHaveStyleRule('padding', '0.75rem'); - expect(getByRole('listitem')).toHaveStyleRule('margin', '0.75rem'); - expect(getByRole('link')).toHaveStyleRule('font-size', '1rem'); + expect(getByRole("navigation")).toHaveStyleRule("font-weight", "400"); + expect(getByRole("list")).toHaveStyleRule("padding", "0.75rem"); + expect(getByRole("listitem")).toHaveStyleRule("margin", "0.75rem"); + expect(getByRole("link")).toHaveStyleRule("font-size", "1rem"); }); }); diff --git a/packages/paste-core/components/in-page-navigation/build.js b/packages/paste-core/components/in-page-navigation/build.js index a4edeab49b..27dd98f98e 100644 --- a/packages/paste-core/components/in-page-navigation/build.js +++ b/packages/paste-core/components/in-page-navigation/build.js @@ -1,3 +1,3 @@ -const {build} = require('../../../../tools/build/esbuild'); +const { build } = require("../../../../tools/build/esbuild"); -build(require('./package.json')); +build(require("./package.json")); diff --git a/packages/paste-core/components/in-page-navigation/src/InPageNavigation.tsx b/packages/paste-core/components/in-page-navigation/src/InPageNavigation.tsx index 2d68f383e9..95ede5438d 100644 --- a/packages/paste-core/components/in-page-navigation/src/InPageNavigation.tsx +++ b/packages/paste-core/components/in-page-navigation/src/InPageNavigation.tsx @@ -1,44 +1,44 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import * as React from "react"; -import type {Variants} from './types'; -import {InPageNavigationContext} from './InPageNavigationContext'; +import { InPageNavigationContext } from "./InPageNavigationContext"; +import type { Variants } from "./types"; -export interface InPageNavigationProps extends Omit, 'children'> { +export interface InPageNavigationProps extends Omit, "children"> { children?: React.ReactNode; - element?: BoxProps['element']; - marginBottom?: 'space0'; - 'aria-label': string; + element?: BoxProps["element"]; + marginBottom?: "space0"; + "aria-label": string; variant?: Variants; } const InPageNavigation = React.forwardRef( - ({element = 'IN_PAGE_NAVIGATION', variant = 'default', marginBottom, children, ...props}, ref) => { - const isFullWidth = variant === 'fullWidth' || variant === 'inverse_fullWidth'; + ({ element = "IN_PAGE_NAVIGATION", variant = "default", marginBottom, children, ...props }, ref) => { + const isFullWidth = variant === "fullWidth" || variant === "inverse_fullWidth"; return ( - + {children} ); - } + }, ); -InPageNavigation.displayName = 'InPageNavigation'; +InPageNavigation.displayName = "InPageNavigation"; -export {InPageNavigation}; +export { InPageNavigation }; diff --git a/packages/paste-core/components/in-page-navigation/src/InPageNavigationContext.tsx b/packages/paste-core/components/in-page-navigation/src/InPageNavigationContext.tsx index 6b48a7412d..77045358c3 100644 --- a/packages/paste-core/components/in-page-navigation/src/InPageNavigationContext.tsx +++ b/packages/paste-core/components/in-page-navigation/src/InPageNavigationContext.tsx @@ -1,13 +1,13 @@ -import * as React from 'react'; +import * as React from "react"; -import type {Variants} from './types'; +import type { Variants } from "./types"; interface InPageNavigationContextValue { variant?: Variants; } const InPageNavigationContext = React.createContext({ - variant: 'default', + variant: "default", }); -export {InPageNavigationContext}; +export { InPageNavigationContext }; diff --git a/packages/paste-core/components/in-page-navigation/src/InPageNavigationItem.tsx b/packages/paste-core/components/in-page-navigation/src/InPageNavigationItem.tsx index e0a0736b96..97d171f35b 100644 --- a/packages/paste-core/components/in-page-navigation/src/InPageNavigationItem.tsx +++ b/packages/paste-core/components/in-page-navigation/src/InPageNavigationItem.tsx @@ -1,78 +1,78 @@ -import * as React from 'react'; -import type {BoxStyleProps, BoxProps} from '@twilio-paste/box'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import {secureExternalLink} from '@twilio-paste/anchor'; -import type {HTMLPasteProps} from '@twilio-paste/types'; +import { secureExternalLink } from "@twilio-paste/anchor"; +import type { BoxProps, BoxStyleProps } from "@twilio-paste/box"; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { HTMLPasteProps } from "@twilio-paste/types"; +import * as React from "react"; -import {InPageNavigationContext} from './InPageNavigationContext'; +import { InPageNavigationContext } from "./InPageNavigationContext"; const BASE_STYLES: BoxStyleProps = { - borderBottomColor: 'transparent', - borderBottomStyle: 'solid', - borderBottomWidth: 'borderWidth10', - color: 'colorTextWeak', - minWidth: 'sizeSquare130', - paddingBottom: 'space40', - paddingLeft: 'space20', - paddingRight: 'space20', - paddingTop: 'space40', - textAlign: 'center', - fontSize: 'fontSize30', - fontWeight: 'fontWeightMedium', - overflow: 'hidden', - position: 'relative', - textOverflow: 'ellipsis', - transition: 'border-color 100ms ease, color 100ms ease', - whiteSpace: 'nowrap', - display: 'block', - width: '100%', - textDecoration: 'none', + borderBottomColor: "transparent", + borderBottomStyle: "solid", + borderBottomWidth: "borderWidth10", + color: "colorTextWeak", + minWidth: "sizeSquare130", + paddingBottom: "space40", + paddingLeft: "space20", + paddingRight: "space20", + paddingTop: "space40", + textAlign: "center", + fontSize: "fontSize30", + fontWeight: "fontWeightMedium", + overflow: "hidden", + position: "relative", + textOverflow: "ellipsis", + transition: "border-color 100ms ease, color 100ms ease", + whiteSpace: "nowrap", + display: "block", + width: "100%", + textDecoration: "none", _hover: { - borderBottomColor: 'colorBorderPrimaryStronger', - color: 'colorTextLinkStronger', + borderBottomColor: "colorBorderPrimaryStronger", + color: "colorTextLinkStronger", }, _focus: { - boxShadow: 'shadowFocus', - outline: 'none', - borderRadius: 'borderRadius20', + boxShadow: "shadowFocus", + outline: "none", + borderRadius: "borderRadius20", }, }; const CURRENT_PAGE_STYLES: BoxStyleProps = { - borderBottomColor: 'colorBorderPrimary', - color: 'colorTextLink', + borderBottomColor: "colorBorderPrimary", + color: "colorTextLink", }; const INVERSE_STYLES: BoxStyleProps = { - color: 'colorTextInverseWeaker', + color: "colorTextInverseWeaker", _focus: { - boxShadow: 'shadowFocusInverse', - outline: 'none', - borderRadius: 'borderRadius20', + boxShadow: "shadowFocusInverse", + outline: "none", + borderRadius: "borderRadius20", }, _hover: { - borderBottomColor: 'colorBorderInverse', - color: 'colorTextInverseWeaker', + borderBottomColor: "colorBorderInverse", + color: "colorTextInverseWeaker", }, }; const INVERSE_CURRENT_PAGE_STYLES: BoxStyleProps = { - borderBottomColor: 'colorBorderInverseStrong', - color: 'colorTextInverse', + borderBottomColor: "colorBorderInverseStrong", + color: "colorTextInverse", }; -export interface InPageNavigationItemProps extends HTMLPasteProps<'a'> { +export interface InPageNavigationItemProps extends HTMLPasteProps<"a"> { currentPage?: boolean; children: NonNullable; href: string; - element?: BoxProps['element']; + element?: BoxProps["element"]; } const InPageNavigationItem = React.forwardRef( - ({element = 'IN_PAGE_NAVIGATION_ITEM', currentPage = false, href, children, ...props}, ref) => { - const {variant} = React.useContext(InPageNavigationContext); - const isFullWidth = variant === 'fullWidth' || variant === 'inverse_fullWidth'; - const isInverse = variant === 'inverse' || variant === 'inverse_fullWidth'; + ({ element = "IN_PAGE_NAVIGATION_ITEM", currentPage = false, href, children, ...props }, ref) => { + const { variant } = React.useContext(InPageNavigationContext); + const isFullWidth = variant === "fullWidth" || variant === "inverse_fullWidth"; + const isInverse = variant === "inverse" || variant === "inverse_fullWidth"; let currentPageStyles = {}; if (currentPage) { @@ -86,7 +86,7 @@ const InPageNavigationItem = React.forwardRef {children} ); - } + }, ); -InPageNavigationItem.displayName = 'InPageNavigationItem'; +InPageNavigationItem.displayName = "InPageNavigationItem"; -export {InPageNavigationItem}; +export { InPageNavigationItem }; diff --git a/packages/paste-core/components/in-page-navigation/src/index.tsx b/packages/paste-core/components/in-page-navigation/src/index.tsx index d1c50c8b2d..9d4e2130df 100644 --- a/packages/paste-core/components/in-page-navigation/src/index.tsx +++ b/packages/paste-core/components/in-page-navigation/src/index.tsx @@ -1,2 +1,2 @@ -export * from './InPageNavigation'; -export * from './InPageNavigationItem'; +export * from "./InPageNavigation"; +export * from "./InPageNavigationItem"; diff --git a/packages/paste-core/components/in-page-navigation/src/types.ts b/packages/paste-core/components/in-page-navigation/src/types.ts index 26f771805d..f9b2bd8a8f 100644 --- a/packages/paste-core/components/in-page-navigation/src/types.ts +++ b/packages/paste-core/components/in-page-navigation/src/types.ts @@ -1 +1 @@ -export type Variants = 'fullWidth' | 'default' | 'inverse' | 'inverse_fullWidth'; +export type Variants = "fullWidth" | "default" | "inverse" | "inverse_fullWidth"; diff --git a/packages/paste-core/components/in-page-navigation/stories/index.stories.tsx b/packages/paste-core/components/in-page-navigation/stories/index.stories.tsx index e6379b04ee..c47815cfdd 100644 --- a/packages/paste-core/components/in-page-navigation/stories/index.stories.tsx +++ b/packages/paste-core/components/in-page-navigation/stories/index.stories.tsx @@ -1,15 +1,15 @@ -import * as React from 'react'; -import type {StoryFn} from '@storybook/react'; -import {CustomizationProvider} from '@twilio-paste/customization'; -import {useTheme} from '@twilio-paste/theme'; -import {useUID} from '@twilio-paste/uid-library'; -import {Box} from '@twilio-paste/box'; +import type { StoryFn } from "@storybook/react"; +import { Box } from "@twilio-paste/box"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import { useTheme } from "@twilio-paste/theme"; +import { useUID } from "@twilio-paste/uid-library"; +import * as React from "react"; -import {InPageNavigation, InPageNavigationItem} from '../src'; +import { InPageNavigation, InPageNavigationItem } from "../src"; // eslint-disable-next-line import/no-default-export export default { - title: 'Components/In Page Navigation', + title: "Components/In Page Navigation", component: InPageNavigation, }; @@ -92,10 +92,10 @@ export const Customized: StoryFn = () => { {/* using UID here to make unique labels for landmarks in Storybook for axe testing */} diff --git a/packages/paste-core/components/inline-code/__tests__/index.spec.tsx b/packages/paste-core/components/inline-code/__tests__/index.spec.tsx index beb135b369..a5b2cddd28 100644 --- a/packages/paste-core/components/inline-code/__tests__/index.spec.tsx +++ b/packages/paste-core/components/inline-code/__tests__/index.spec.tsx @@ -1,58 +1,58 @@ -import * as React from 'react'; -import {render} from '@testing-library/react'; -import {CustomizationProvider} from '@twilio-paste/customization'; -import {Box} from '@twilio-paste/box'; +import { render } from "@testing-library/react"; +import { Box } from "@twilio-paste/box"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import * as React from "react"; -import {InlineCode} from '../src'; +import { InlineCode } from "../src"; -describe('InlineCode', () => { - it('should render text in a tag', () => { - const {getByTestId} = render( +describe("InlineCode", () => { + it("should render text in a tag", () => { + const { getByTestId } = render( sid - + , ); - expect(getByTestId('inline-code').querySelector('code')).not.toBeNull(); + expect(getByTestId("inline-code").querySelector("code")).not.toBeNull(); }); - it('should have a default element attribute', () => { - const {getByText} = render(sid); - expect(getByText('sid').getAttribute('data-paste-element')).toEqual('INLINE_CODE'); + it("should have a default element attribute", () => { + const { getByText } = render(sid); + expect(getByText("sid").getAttribute("data-paste-element")).toEqual("INLINE_CODE"); }); - it('should have a custom element attribute when set', () => { - const {getByText} = render(sid); - expect(getByText('sid').getAttribute('data-paste-element')).toEqual('MY_INLINE_CODE'); + it("should have a custom element attribute when set", () => { + const { getByText } = render(sid); + expect(getByText("sid").getAttribute("data-paste-element")).toEqual("MY_INLINE_CODE"); }); - it('should set custom styles using the default element attribute', () => { - const {getByText} = render( + it("should set custom styles using the default element attribute", () => { + const { getByText } = render( sid - + , ); - expect(getByText('sid')).toHaveStyleRule('border-width', '2px'); + expect(getByText("sid")).toHaveStyleRule("border-width", "2px"); }); - it('should set custom styles using a custom element attribute', () => { - const {getByText} = render( + it("should set custom styles using a custom element attribute", () => { + const { getByText } = render( sid - + , ); - expect(getByText('sid')).toHaveStyleRule('border-width', '2px'); + expect(getByText("sid")).toHaveStyleRule("border-width", "2px"); }); }); diff --git a/packages/paste-core/components/inline-code/build.js b/packages/paste-core/components/inline-code/build.js index a4edeab49b..27dd98f98e 100644 --- a/packages/paste-core/components/inline-code/build.js +++ b/packages/paste-core/components/inline-code/build.js @@ -1,3 +1,3 @@ -const {build} = require('../../../../tools/build/esbuild'); +const { build } = require("../../../../tools/build/esbuild"); -build(require('./package.json')); +build(require("./package.json")); diff --git a/packages/paste-core/components/inline-code/src/index.tsx b/packages/paste-core/components/inline-code/src/index.tsx index 8e4eb49148..94c11e65f0 100644 --- a/packages/paste-core/components/inline-code/src/index.tsx +++ b/packages/paste-core/components/inline-code/src/index.tsx @@ -1,16 +1,16 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; +import { Box, safelySpreadBoxProps } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import * as React from "react"; /** * Inline Code style variants. * Minimal is a deprecated vairant that we now hide, but we can't remove as it's a breaking change */ -type InlineCodeVariants = 'default' | 'minimal'; +type InlineCodeVariants = "default" | "minimal"; -export interface InlineCodeProps extends Partial> { +export interface InlineCodeProps extends Partial> { children: string; - element?: BoxProps['element']; + element?: BoxProps["element"]; /** * Choose the badge variant you would like to use. @@ -23,7 +23,7 @@ export interface InlineCodeProps extends Partial( - ({children, element = 'INLINE_CODE', variant = 'default', ...props}, ref) => { + ({ children, element = "INLINE_CODE", variant = "default", ...props }, ref) => { return ( ( {children} ); - } + }, ); -InlineCode.displayName = 'InlineCode'; +InlineCode.displayName = "InlineCode"; -export {InlineCode}; +export { InlineCode }; diff --git a/packages/paste-core/components/inline-code/stories/index.stories.tsx b/packages/paste-core/components/inline-code/stories/index.stories.tsx index 030a5bb2c3..6ea2fe35e5 100644 --- a/packages/paste-core/components/inline-code/stories/index.stories.tsx +++ b/packages/paste-core/components/inline-code/stories/index.stories.tsx @@ -1,17 +1,17 @@ -import * as React from 'react'; -import type {StoryFn} from '@storybook/react'; -import {Text} from '@twilio-paste/text'; -import {Box} from '@twilio-paste/box'; -import {Stack} from '@twilio-paste/stack'; -import {useTheme} from '@twilio-paste/theme'; -import {CustomizationProvider} from '@twilio-paste/customization'; -import {Heading} from '@twilio-paste/heading'; +import type { StoryFn } from "@storybook/react"; +import { Box } from "@twilio-paste/box"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import { Heading } from "@twilio-paste/heading"; +import { Stack } from "@twilio-paste/stack"; +import { Text } from "@twilio-paste/text"; +import { useTheme } from "@twilio-paste/theme"; +import * as React from "react"; -import {InlineCode} from '../src'; +import { InlineCode } from "../src"; // eslint-disable-next-line import/no-default-export export default { - title: 'Components/Inline Code', + title: "Components/Inline Code", component: InlineCode, }; @@ -94,7 +94,7 @@ export const DisplayingAPIKey: StoryFn = () => { ); }; -export const Customization: StoryFn = (_args, {parameters: {isTestEnvironment}}) => { +export const Customization: StoryFn = (_args, { parameters: { isTestEnvironment } }) => { const currentTheme = useTheme(); return ( diff --git a/packages/paste-core/components/inline-control-group/__tests__/inlineControlGroup.test.tsx b/packages/paste-core/components/inline-control-group/__tests__/inlineControlGroup.test.tsx index 10145bb613..e112e9f7dd 100644 --- a/packages/paste-core/components/inline-control-group/__tests__/inlineControlGroup.test.tsx +++ b/packages/paste-core/components/inline-control-group/__tests__/inlineControlGroup.test.tsx @@ -1,85 +1,85 @@ -import * as React from 'react'; -import {render as testRender, screen} from '@testing-library/react'; -import {CustomizationProvider} from '@twilio-paste/customization'; +import { render as testRender, screen } from "@testing-library/react"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import * as React from "react"; -import {InlineControlGroup} from '../src'; +import { InlineControlGroup } from "../src"; const defaultGroupProps = { - legend: 'This is a group legend', - name: 'bar', - value: 'bar', + legend: "This is a group legend", + name: "bar", + value: "bar", }; -describe('InlineControlGroup', () => { - it('should render', () => { - const {container} = testRender( +describe("InlineControlGroup", () => { + it("should render", () => { + const { container } = testRender(
    - + , ); - expect(container.querySelector('fieldset')).not.toBeNull(); + expect(container.querySelector("fieldset")).not.toBeNull(); }); - it('should render a legend', () => { - const {getByText} = testRender( + it("should render a legend", () => { + const { getByText } = testRender(
    - + , ); - expect(getByText('This is a group legend')).not.toBeNull(); + expect(getByText("This is a group legend")).not.toBeNull(); }); - it('should have a required a required dot in the legend', () => { + it("should have a required a required dot in the legend", () => { testRender(
    - + , ); - const fieldset = screen.getByRole('group'); + const fieldset = screen.getByRole("group"); const requiredDot = fieldset.querySelector('[data-paste-element="LEGEND_REQUIRED_DOT"]'); expect(requiredDot).toBeDefined(); }); - it('renders a helpText message when helpText prop is present', () => { - const helpText = 'I am a helpText message'; - const {getByText} = testRender( + it("renders a helpText message when helpText prop is present", () => { + const helpText = "I am a helpText message"; + const { getByText } = testRender(
    - + , ); expect(getByText(helpText)).toBeDefined(); }); - it('renders an errorText message when errorText prop is present', () => { - const errorText = 'I am an errorText message'; - const {getByText} = testRender( + it("renders an errorText message when errorText prop is present", () => { + const errorText = "I am an errorText message"; + const { getByText } = testRender(
    - + , ); expect(getByText(errorText)).toBeDefined(); }); }); -describe('Customization', () => { - it('Should set a default element data attribute for Inline Control Group', (): void => { - const {container} = testRender( +describe("Customization", () => { + it("Should set a default element data attribute for Inline Control Group", (): void => { + const { container } = testRender(
    - + , ); - expect(screen.getByTestId('inline-control-group')).toHaveAttribute('data-paste-element', 'INLINE_CONTROL_GROUP'); + expect(screen.getByTestId("inline-control-group")).toHaveAttribute("data-paste-element", "INLINE_CONTROL_GROUP"); expect(container.querySelector('[data-paste-element="INLINE_CONTROL_GROUP_SET"]')).toBeInTheDocument(); expect(container.querySelector('[data-paste-element="INLINE_CONTROL_GROUP_FIELD"]')).toBeInTheDocument(); expect( - container.querySelector('[data-paste-element="INLINE_CONTROL_GROUP_ERROR_TEXT_WRAPPER"]') + container.querySelector('[data-paste-element="INLINE_CONTROL_GROUP_ERROR_TEXT_WRAPPER"]'), ).toBeInTheDocument(); }); - it('Should set a custom element data attribute for custom named Inline Control Group', (): void => { - const {container} = testRender( + it("Should set a custom element data attribute for custom named Inline Control Group", (): void => { + const { container } = testRender( { errorText="error" >
    - + , ); - expect(screen.getByTestId('inline-control-group')).toHaveAttribute('data-paste-element', 'MY_INLINE_CONTROL_GROUP'); + expect(screen.getByTestId("inline-control-group")).toHaveAttribute("data-paste-element", "MY_INLINE_CONTROL_GROUP"); expect(container.querySelector('[data-paste-element="MY_INLINE_CONTROL_GROUP_SET"]')).toBeInTheDocument(); expect(container.querySelector('[data-paste-element="MY_INLINE_CONTROL_GROUP_FIELD"]')).toBeInTheDocument(); expect( - container.querySelector('[data-paste-element="MY_INLINE_CONTROL_GROUP_ERROR_TEXT_WRAPPER"]') + container.querySelector('[data-paste-element="MY_INLINE_CONTROL_GROUP_ERROR_TEXT_WRAPPER"]'), ).toBeInTheDocument(); }); - it('Should add custom styling to default Inline Control Group', (): void => { - const {container} = testRender( + it("Should add custom styling to default Inline Control Group", (): void => { + const { container } = testRender(
    - + , ); - expect(screen.getByTestId('inline-control-group')).toHaveStyleRule('margin', '1.25rem'); + expect(screen.getByTestId("inline-control-group")).toHaveStyleRule("margin", "1.25rem"); expect(container.querySelector('[data-paste-element="INLINE_CONTROL_GROUP_SET"]')).toHaveStyleRule( - 'margin-left', - '1.25rem' + "margin-left", + "1.25rem", ); expect(container.querySelector('[data-paste-element="INLINE_CONTROL_GROUP_FIELD"]')).toHaveStyleRule( - 'color', - 'rgb(14, 124, 58)' + "color", + "rgb(14, 124, 58)", ); expect(container.querySelector('[data-paste-element="INLINE_CONTROL_GROUP_ERROR_TEXT_WRAPPER"]')).toHaveStyleRule( - 'margin-top', - '1.25rem' + "margin-top", + "1.25rem", ); }); - it('Should add custom styling to custom named Inline Control Group', (): void => { - const {container} = testRender( + it("Should add custom styling to custom named Inline Control Group", (): void => { + const { container } = testRender( { >
    - + , ); - expect(screen.getByTestId('inline-control-group')).toHaveStyleRule('margin', '1.25rem'); + expect(screen.getByTestId("inline-control-group")).toHaveStyleRule("margin", "1.25rem"); expect(container.querySelector('[data-paste-element="MY_INLINE_CONTROL_GROUP_SET"]')).toHaveStyleRule( - 'margin-left', - '1.25rem' + "margin-left", + "1.25rem", ); expect(container.querySelector('[data-paste-element="MY_INLINE_CONTROL_GROUP_FIELD"]')).toHaveStyleRule( - 'color', - 'rgb(14, 124, 58)' + "color", + "rgb(14, 124, 58)", ); expect( - container.querySelector('[data-paste-element="MY_INLINE_CONTROL_GROUP_ERROR_TEXT_WRAPPER"]') - ).toHaveStyleRule('margin-top', '1.25rem'); + container.querySelector('[data-paste-element="MY_INLINE_CONTROL_GROUP_ERROR_TEXT_WRAPPER"]'), + ).toHaveStyleRule("margin-top", "1.25rem"); }); }); diff --git a/packages/paste-core/components/inline-control-group/build.js b/packages/paste-core/components/inline-control-group/build.js index a4edeab49b..27dd98f98e 100644 --- a/packages/paste-core/components/inline-control-group/build.js +++ b/packages/paste-core/components/inline-control-group/build.js @@ -1,3 +1,3 @@ -const {build} = require('../../../../tools/build/esbuild'); +const { build } = require("../../../../tools/build/esbuild"); -build(require('./package.json')); +build(require("./package.json")); diff --git a/packages/paste-core/components/inline-control-group/src/InlineControlGroup.tsx b/packages/paste-core/components/inline-control-group/src/InlineControlGroup.tsx index 3bac2b93db..e139c0fe8a 100644 --- a/packages/paste-core/components/inline-control-group/src/InlineControlGroup.tsx +++ b/packages/paste-core/components/inline-control-group/src/InlineControlGroup.tsx @@ -1,18 +1,18 @@ -import * as React from 'react'; -import {Box, safelySpreadBoxProps, type BoxProps, type BoxStyleProps} from '@twilio-paste/box'; -import {Label} from '@twilio-paste/label'; -import {HelpText} from '@twilio-paste/help-text'; -import type {HTMLPasteProps} from '@twilio-paste/types'; +import { Box, type BoxProps, type BoxStyleProps, safelySpreadBoxProps } from "@twilio-paste/box"; +import { HelpText } from "@twilio-paste/help-text"; +import { Label } from "@twilio-paste/label"; +import type { HTMLPasteProps } from "@twilio-paste/types"; +import * as React from "react"; export interface InlineControlGroupProps - extends Pick, - Omit, 'onChange'> { + extends Pick, + Omit, "onChange"> { children: React.ReactNode; disabled?: boolean; errorText?: string | React.ReactNode; helpText?: string | React.ReactNode; legend: string | NonNullable; - orientation?: 'vertical' | 'horizontal'; + orientation?: "vertical" | "horizontal"; required?: boolean; i18nRequiredLabel?: string; fieldStyleProps?: BoxStyleProps; @@ -23,17 +23,17 @@ const InlineControlGroup = React.forwardRef { const isVisualPicker = Boolean(fieldStyleProps); // This prop is only used in Visual Picker @@ -60,28 +60,28 @@ const InlineControlGroup = React.forwardRef {helpText && {helpText}} - + {React.Children.map(children, (child, index) => { return ( {child} @@ -97,9 +97,9 @@ const InlineControlGroup = React.forwardRef ); - } + }, ); -InlineControlGroup.displayName = 'InlineControlGroup'; +InlineControlGroup.displayName = "InlineControlGroup"; -export {InlineControlGroup}; +export { InlineControlGroup }; diff --git a/packages/paste-core/components/inline-control-group/src/index.tsx b/packages/paste-core/components/inline-control-group/src/index.tsx index d820bd37de..61b5a62a25 100644 --- a/packages/paste-core/components/inline-control-group/src/index.tsx +++ b/packages/paste-core/components/inline-control-group/src/index.tsx @@ -1 +1 @@ -export * from './InlineControlGroup'; +export * from "./InlineControlGroup"; diff --git a/packages/paste-core/components/inline-control-group/stories/inline-control-group.stories.tsx b/packages/paste-core/components/inline-control-group/stories/inline-control-group.stories.tsx index 1ac6d402a9..cec2769d74 100644 --- a/packages/paste-core/components/inline-control-group/stories/inline-control-group.stories.tsx +++ b/packages/paste-core/components/inline-control-group/stories/inline-control-group.stories.tsx @@ -1,15 +1,15 @@ -import * as React from 'react'; -import type {StoryFn} from '@storybook/react'; -import {Box} from '@twilio-paste/box'; -import {Grid, Column} from '@twilio-paste/grid'; -import {Paragraph} from '@twilio-paste/paragraph'; -import {CustomizationProvider} from '@twilio-paste/customization'; -import {useTheme} from '@twilio-paste/theme'; - -import {InlineControlGroup} from '../src'; -import type {InlineControlGroupProps} from '../src'; - -const MockChild: React.FC = ({children}) => { +import type { StoryFn } from "@storybook/react"; +import { Box } from "@twilio-paste/box"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import { Column, Grid } from "@twilio-paste/grid"; +import { Paragraph } from "@twilio-paste/paragraph"; +import { useTheme } from "@twilio-paste/theme"; +import * as React from "react"; + +import { InlineControlGroup } from "../src"; +import type { InlineControlGroupProps } from "../src"; + +const MockChild: React.FC = ({ children }) => { return {children}; }; @@ -19,14 +19,14 @@ const MockControlGroup: React.FC< showHelpText?: boolean; showErrorText?: boolean; element?: string; - orientation?: InlineControlGroupProps['orientation']; + orientation?: InlineControlGroupProps["orientation"]; }> -> = ({showRequired, showHelpText, showErrorText, element, orientation = 'vertical'}) => { +> = ({ showRequired, showHelpText, showErrorText, element, orientation = "vertical" }) => { return ( { @@ -104,21 +104,21 @@ export const ControlSpacingTest = (): React.ReactNode => { ); }; -export const Customized: StoryFn = (_args, {parameters: {isTestEnvironment}}) => { +export const Customized: StoryFn = (_args, { parameters: { isTestEnvironment } }) => { const currentTheme = useTheme(); return ( Using default element name: diff --git a/packages/paste-core/components/input-box/__tests__/input-box.test.tsx b/packages/paste-core/components/input-box/__tests__/input-box.test.tsx index ff26dc30ca..af159e1833 100644 --- a/packages/paste-core/components/input-box/__tests__/input-box.test.tsx +++ b/packages/paste-core/components/input-box/__tests__/input-box.test.tsx @@ -1,47 +1,47 @@ -import * as React from 'react'; -import {render, screen} from '@testing-library/react'; -import {CustomizationProvider} from '@twilio-paste/customization'; +import { render, screen } from "@testing-library/react"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import * as React from "react"; -import {InputBox} from '../src'; +import { InputBox } from "../src"; -describe('HTML attributes', () => { - it('should set a element data attribute for InputBox', () => { +describe("HTML attributes", () => { + it("should set a element data attribute for InputBox", () => { render(input-box); - expect(screen.getByText('input-box').getAttribute('data-paste-element')).toEqual('INPUT_BOX'); + expect(screen.getByText("input-box").getAttribute("data-paste-element")).toEqual("INPUT_BOX"); }); - it('should set a custom element data attribute for InputBox', () => { + it("should set a custom element data attribute for InputBox", () => { render(input-box); - expect(screen.getByText('input-box').getAttribute('data-paste-element')).toEqual('foo'); + expect(screen.getByText("input-box").getAttribute("data-paste-element")).toEqual("foo"); }); }); -describe('Customization', () => { - it('should add custom styles to InputBox', (): void => { +describe("Customization", () => { + it("should add custom styles to InputBox", (): void => { render( input-box - + , ); - const renderedInputBox = screen.getByText('input-box'); - expect(renderedInputBox).toHaveStyleRule('background-color', 'rgb(244, 244, 246)'); + const renderedInputBox = screen.getByText("input-box"); + expect(renderedInputBox).toHaveStyleRule("background-color", "rgb(244, 244, 246)"); }); - it('should add custom styles to a InputBox variant', (): void => { + it("should add custom styles to a InputBox variant", (): void => { render( { input-box - + , ); - const renderedInputBox = screen.getByText('input-box'); - expect(renderedInputBox).toHaveStyleRule('background-color', 'rgb(0, 20, 137)'); + const renderedInputBox = screen.getByText("input-box"); + expect(renderedInputBox).toHaveStyleRule("background-color", "rgb(0, 20, 137)"); }); - it('should add custom styles to InputBox with a custom element data attribute', (): void => { + it("should add custom styles to InputBox with a custom element data attribute", (): void => { render( input-box - + , ); - const renderedInputBox = screen.getByText('input-box'); - expect(renderedInputBox).toHaveStyleRule('background-color', 'rgb(244, 244, 246)'); + const renderedInputBox = screen.getByText("input-box"); + expect(renderedInputBox).toHaveStyleRule("background-color", "rgb(244, 244, 246)"); }); - it('should add custom styles to a InputBox variant with a custom element data attribute', (): void => { + it("should add custom styles to a InputBox variant with a custom element data attribute", (): void => { render( { input-box - + , ); - const renderedInputBox = screen.getByText('input-box'); - expect(renderedInputBox).toHaveStyleRule('background-color', 'rgb(0, 20, 137)'); + const renderedInputBox = screen.getByText("input-box"); + expect(renderedInputBox).toHaveStyleRule("background-color", "rgb(0, 20, 137)"); }); }); diff --git a/packages/paste-core/components/input-box/__tests__/input-chevron-wrapper.test.tsx b/packages/paste-core/components/input-box/__tests__/input-chevron-wrapper.test.tsx index 6753d44225..7bbd14c446 100644 --- a/packages/paste-core/components/input-box/__tests__/input-chevron-wrapper.test.tsx +++ b/packages/paste-core/components/input-box/__tests__/input-chevron-wrapper.test.tsx @@ -1,80 +1,80 @@ -import * as React from 'react'; -import {render, screen} from '@testing-library/react'; -import {CustomizationProvider} from '@twilio-paste/customization'; +import { render, screen } from "@testing-library/react"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import * as React from "react"; -import {getInputChevronIconColor, InputChevronWrapper, InputBox} from '../src'; +import { InputBox, InputChevronWrapper, getInputChevronIconColor } from "../src"; -describe('HTML attributes', () => { - it('should set a element data attribute for InputChevronWrapper', () => { +describe("HTML attributes", () => { + it("should set a element data attribute for InputChevronWrapper", () => { render( input-chevron - + , ); - expect(screen.getByText('input-chevron').getAttribute('data-paste-element')).toEqual('INPUT_CHEVRON_WRAPPER'); + expect(screen.getByText("input-chevron").getAttribute("data-paste-element")).toEqual("INPUT_CHEVRON_WRAPPER"); }); - it('should set a custom element data attribute for InputChevronWrapper', () => { + it("should set a custom element data attribute for InputChevronWrapper", () => { render( input-chevron - + , ); - expect(screen.getByText('input-chevron').getAttribute('data-paste-element')).toEqual('FOO_CHEVRON_WRAPPER'); + expect(screen.getByText("input-chevron").getAttribute("data-paste-element")).toEqual("FOO_CHEVRON_WRAPPER"); }); }); -describe('getInputChevronIconColor util', () => { - it('returns an the correct icon color based on variant, disabled, and readonly arguments', () => { +describe("getInputChevronIconColor util", () => { + it("returns an the correct icon color based on variant, disabled, and readonly arguments", () => { // default - expect(getInputChevronIconColor('default', false, false)).toBe('colorTextIcon'); - expect(getInputChevronIconColor('default', true, false)).toBe('colorTextWeaker'); - expect(getInputChevronIconColor('default', false, true)).toBe('colorTextWeaker'); - expect(getInputChevronIconColor('default', true, true)).toBe('colorTextWeaker'); + expect(getInputChevronIconColor("default", false, false)).toBe("colorTextIcon"); + expect(getInputChevronIconColor("default", true, false)).toBe("colorTextWeaker"); + expect(getInputChevronIconColor("default", false, true)).toBe("colorTextWeaker"); + expect(getInputChevronIconColor("default", true, true)).toBe("colorTextWeaker"); // inverse - expect(getInputChevronIconColor('inverse', false, false)).toBe('colorTextIconInverse'); - expect(getInputChevronIconColor('inverse', true, false)).toBe('colorTextInverseWeakest'); - expect(getInputChevronIconColor('inverse', false, true)).toBe('colorTextInverseWeakest'); - expect(getInputChevronIconColor('inverse', true, true)).toBe('colorTextInverseWeakest'); + expect(getInputChevronIconColor("inverse", false, false)).toBe("colorTextIconInverse"); + expect(getInputChevronIconColor("inverse", true, false)).toBe("colorTextInverseWeakest"); + expect(getInputChevronIconColor("inverse", false, true)).toBe("colorTextInverseWeakest"); + expect(getInputChevronIconColor("inverse", true, true)).toBe("colorTextInverseWeakest"); // missing args defaults to normal color - expect(getInputChevronIconColor()).toBe('colorTextIcon'); - expect(getInputChevronIconColor('default')).toBe('colorTextIcon'); + expect(getInputChevronIconColor()).toBe("colorTextIcon"); + expect(getInputChevronIconColor("default")).toBe("colorTextIcon"); }); }); -describe('Customization', () => { - it('should add custom styles to InputChevronWrapper', (): void => { +describe("Customization", () => { + it("should add custom styles to InputChevronWrapper", (): void => { render( input-chevron - + , ); - const renderedInputChevronWrapper = screen.getByText('input-chevron'); - expect(renderedInputChevronWrapper).toHaveStyleRule('background-color', 'rgb(244, 244, 246)'); + const renderedInputChevronWrapper = screen.getByText("input-chevron"); + expect(renderedInputChevronWrapper).toHaveStyleRule("background-color", "rgb(244, 244, 246)"); }); - it('should add custom styles to InputChevronWrapper with a custom element data attribute', (): void => { + it("should add custom styles to InputChevronWrapper with a custom element data attribute", (): void => { render( input-chevron - + , ); - const renderedInputChevronWrapper = screen.getByText('input-chevron'); - expect(renderedInputChevronWrapper).toHaveStyleRule('background-color', 'rgb(244, 244, 246)'); + const renderedInputChevronWrapper = screen.getByText("input-chevron"); + expect(renderedInputChevronWrapper).toHaveStyleRule("background-color", "rgb(244, 244, 246)"); }); }); diff --git a/packages/paste-core/components/input-box/__tests__/prefix.test.tsx b/packages/paste-core/components/input-box/__tests__/prefix.test.tsx index f457b4bf0b..5ba0b8dbf7 100644 --- a/packages/paste-core/components/input-box/__tests__/prefix.test.tsx +++ b/packages/paste-core/components/input-box/__tests__/prefix.test.tsx @@ -1,47 +1,47 @@ -import * as React from 'react'; -import {render, screen} from '@testing-library/react'; -import {CustomizationProvider} from '@twilio-paste/customization'; +import { render, screen } from "@testing-library/react"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import * as React from "react"; -import {Prefix} from '../src'; +import { Prefix } from "../src"; -describe('HTML attributes', () => { - it('should set a element data attribute for Prefix', () => { +describe("HTML attributes", () => { + it("should set a element data attribute for Prefix", () => { render(prefix); - expect(screen.getByText('prefix').getAttribute('data-paste-element')).toEqual('INPUT_PREFIX'); + expect(screen.getByText("prefix").getAttribute("data-paste-element")).toEqual("INPUT_PREFIX"); }); - it('should set a custom element data attribute for Prefix', () => { + it("should set a custom element data attribute for Prefix", () => { render(prefix); - expect(screen.getByText('prefix').getAttribute('data-paste-element')).toEqual('foo_PREFIX'); + expect(screen.getByText("prefix").getAttribute("data-paste-element")).toEqual("foo_PREFIX"); }); }); -describe('Customization', () => { - it('should add custom styles to Prefix', (): void => { +describe("Customization", () => { + it("should add custom styles to Prefix", (): void => { render( prefix - + , ); - const renderedPrefix = screen.getByText('prefix'); - expect(renderedPrefix).toHaveStyleRule('background-color', 'rgb(244, 244, 246)'); + const renderedPrefix = screen.getByText("prefix"); + expect(renderedPrefix).toHaveStyleRule("background-color", "rgb(244, 244, 246)"); }); - it('should add custom styles to a Prefix variant', (): void => { + it("should add custom styles to a Prefix variant", (): void => { render( { prefix - + , ); - const renderedPrefix = screen.getByText('prefix'); - expect(renderedPrefix).toHaveStyleRule('background-color', 'rgb(0, 20, 137)'); + const renderedPrefix = screen.getByText("prefix"); + expect(renderedPrefix).toHaveStyleRule("background-color", "rgb(0, 20, 137)"); }); - it('should add custom styles to Prefix with a custom element data attribute', (): void => { + it("should add custom styles to Prefix with a custom element data attribute", (): void => { render( prefix - + , ); - const renderedPrefix = screen.getByText('prefix'); - expect(renderedPrefix).toHaveStyleRule('background-color', 'rgb(244, 244, 246)'); + const renderedPrefix = screen.getByText("prefix"); + expect(renderedPrefix).toHaveStyleRule("background-color", "rgb(244, 244, 246)"); }); - it('should add custom styles to a Prefix variant with a custom element data attribute', (): void => { + it("should add custom styles to a Prefix variant with a custom element data attribute", (): void => { render( { prefix - + , ); - const renderedPrefix = screen.getByText('prefix'); - expect(renderedPrefix).toHaveStyleRule('background-color', 'rgb(0, 20, 137)'); + const renderedPrefix = screen.getByText("prefix"); + expect(renderedPrefix).toHaveStyleRule("background-color", "rgb(0, 20, 137)"); }); }); diff --git a/packages/paste-core/components/input-box/__tests__/suffix.test.tsx b/packages/paste-core/components/input-box/__tests__/suffix.test.tsx index 1598a3990d..54b6b1a938 100644 --- a/packages/paste-core/components/input-box/__tests__/suffix.test.tsx +++ b/packages/paste-core/components/input-box/__tests__/suffix.test.tsx @@ -1,49 +1,49 @@ -import * as React from 'react'; -import {render, screen} from '@testing-library/react'; -import {CustomizationProvider} from '@twilio-paste/customization'; +import { render, screen } from "@testing-library/react"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import * as React from "react"; -import {Suffix} from '../src'; +import { Suffix } from "../src"; -describe('HTML attributes', () => { - it('should set a element data attribute for Suffix', () => { +describe("HTML attributes", () => { + it("should set a element data attribute for Suffix", () => { render(suffix); - expect(screen.getByText('suffix').getAttribute('data-paste-element')).toEqual('INPUT_SUFFIX'); + expect(screen.getByText("suffix").getAttribute("data-paste-element")).toEqual("INPUT_SUFFIX"); }); - it('should set a custom element data attribute for Prefix', () => { + it("should set a custom element data attribute for Prefix", () => { render(suffix); - expect(screen.getByText('suffix').getAttribute('data-paste-element')).toEqual('foo_SUFFIX'); + expect(screen.getByText("suffix").getAttribute("data-paste-element")).toEqual("foo_SUFFIX"); }); }); -describe('Customization', () => { - it('should add custom styles to Suffix', () => { +describe("Customization", () => { + it("should add custom styles to Suffix", () => { render( suffix - + , ); - const renderedSuffix = screen.getByText('suffix'); - expect(renderedSuffix).toHaveStyleRule('background-color', TestTheme.backgroundColors.colorBackground); + const renderedSuffix = screen.getByText("suffix"); + expect(renderedSuffix).toHaveStyleRule("background-color", TestTheme.backgroundColors.colorBackground); }); - it('should add custom styles to a Suffix variant', () => { + it("should add custom styles to a Suffix variant", () => { render( { suffix - + , ); - const renderedSuffix = screen.getByText('suffix'); - expect(renderedSuffix).toHaveStyleRule('background-color', TestTheme.backgroundColors.colorBackgroundBrand); + const renderedSuffix = screen.getByText("suffix"); + expect(renderedSuffix).toHaveStyleRule("background-color", TestTheme.backgroundColors.colorBackgroundBrand); }); - it('should add custom styles to Suffix with a custom element data attribute', () => { + it("should add custom styles to Suffix with a custom element data attribute", () => { render( suffix - + , ); - const renderedSuffix = screen.getByText('suffix'); - expect(renderedSuffix).toHaveStyleRule('background-color', TestTheme.backgroundColors.colorBackground); + const renderedSuffix = screen.getByText("suffix"); + expect(renderedSuffix).toHaveStyleRule("background-color", TestTheme.backgroundColors.colorBackground); }); - it('should add custom styles to a Suffix variant with a custom element data attribute', () => { + it("should add custom styles to a Suffix variant with a custom element data attribute", () => { render( { suffix - + , ); - const renderedSuffix = screen.getByText('suffix'); - expect(renderedSuffix).toHaveStyleRule('background-color', TestTheme.backgroundColors.colorBackgroundBrand); + const renderedSuffix = screen.getByText("suffix"); + expect(renderedSuffix).toHaveStyleRule("background-color", TestTheme.backgroundColors.colorBackgroundBrand); }); }); diff --git a/packages/paste-core/components/input-box/build.js b/packages/paste-core/components/input-box/build.js index a4edeab49b..27dd98f98e 100644 --- a/packages/paste-core/components/input-box/build.js +++ b/packages/paste-core/components/input-box/build.js @@ -1,3 +1,3 @@ -const {build} = require('../../../../tools/build/esbuild'); +const { build } = require("../../../../tools/build/esbuild"); -build(require('./package.json')); +build(require("./package.json")); diff --git a/packages/paste-core/components/input-box/src/FauxInput/DefaultFauxInput.tsx b/packages/paste-core/components/input-box/src/FauxInput/DefaultFauxInput.tsx index c4a271642e..6afef18a5d 100644 --- a/packages/paste-core/components/input-box/src/FauxInput/DefaultFauxInput.tsx +++ b/packages/paste-core/components/input-box/src/FauxInput/DefaultFauxInput.tsx @@ -1,27 +1,27 @@ -import * as React from 'react'; -import {Box} from '@twilio-paste/box'; -import type {BoxShadow, BackgroundColor} from '@twilio-paste/style-props'; +import { Box } from "@twilio-paste/box"; +import type { BackgroundColor, BoxShadow } from "@twilio-paste/style-props"; +import * as React from "react"; -import type {FauxInputProps} from '../types'; +import type { FauxInputProps } from "../types"; const DefaultFauxInput = React.forwardRef>( - ({disabled, element, hasError, readOnly, children, type, variant}, ref) => { - let backgroundColor = 'colorBackgroundBody' as BackgroundColor; - let boxShadow = 'shadowBorder' as BoxShadow; - let boxShadowHover = 'shadowBorderPrimary' as BoxShadow; - let boxShadowActive = 'shadowBorderPrimaryStronger' as BoxShadow; - if (disabled && type !== 'hidden') { - boxShadow = 'shadowBorderWeak'; - boxShadowHover = 'shadowBorderWeak'; - backgroundColor = 'colorBackground'; - boxShadowActive = 'shadowBorderWeak'; - } else if (readOnly && type !== 'hidden') { - boxShadowHover = 'shadowBorder'; - backgroundColor = 'colorBackground'; - } else if (hasError && type !== 'hidden') { - boxShadow = 'shadowBorderError'; - boxShadowHover = 'shadowBorderErrorStronger'; - } else if (type === 'hidden') { + ({ disabled, element, hasError, readOnly, children, type, variant }, ref) => { + let backgroundColor = "colorBackgroundBody" as BackgroundColor; + let boxShadow = "shadowBorder" as BoxShadow; + let boxShadowHover = "shadowBorderPrimary" as BoxShadow; + let boxShadowActive = "shadowBorderPrimaryStronger" as BoxShadow; + if (disabled && type !== "hidden") { + boxShadow = "shadowBorderWeak"; + boxShadowHover = "shadowBorderWeak"; + backgroundColor = "colorBackground"; + boxShadowActive = "shadowBorderWeak"; + } else if (readOnly && type !== "hidden") { + boxShadowHover = "shadowBorder"; + backgroundColor = "colorBackground"; + } else if (hasError && type !== "hidden") { + boxShadow = "shadowBorderError"; + boxShadowHover = "shadowBorderErrorStronger"; + } else if (type === "hidden") { boxShadow = null; boxShadowHover = null; backgroundColor = null; @@ -38,13 +38,13 @@ const DefaultFauxInput = React.forwardRef ); - } + }, ); -DefaultFauxInput.displayName = 'DefaultFauxInput'; +DefaultFauxInput.displayName = "DefaultFauxInput"; -export {DefaultFauxInput}; +export { DefaultFauxInput }; diff --git a/packages/paste-core/components/input-box/src/FauxInput/InverseFauxInput.tsx b/packages/paste-core/components/input-box/src/FauxInput/InverseFauxInput.tsx index f25d0a4a91..17042dbd77 100644 --- a/packages/paste-core/components/input-box/src/FauxInput/InverseFauxInput.tsx +++ b/packages/paste-core/components/input-box/src/FauxInput/InverseFauxInput.tsx @@ -1,24 +1,24 @@ -import * as React from 'react'; -import {Box} from '@twilio-paste/box'; -import type {BoxShadow, BackgroundColor} from '@twilio-paste/style-props'; +import { Box } from "@twilio-paste/box"; +import type { BackgroundColor, BoxShadow } from "@twilio-paste/style-props"; +import * as React from "react"; -import type {FauxInputProps} from '../types'; +import type { FauxInputProps } from "../types"; const InverseFauxInput = React.forwardRef( - ({disabled, element, hasError, readOnly, children, type, variant}, ref) => { - let backgroundColor = 'colorBackgroundInverse' as BackgroundColor; - let boxShadow = 'shadowBorderInverse' as BoxShadow; - let boxShadowHover = 'shadowBorderInverseStrongest' as BoxShadow; - if (disabled && type !== 'hidden') { - backgroundColor = 'colorBackgroundInverse'; - boxShadow = 'shadowBorderInverseWeaker'; - boxShadowHover = 'shadowBorderInverseWeaker'; - } else if (readOnly && type !== 'hidden') { - backgroundColor = 'colorBackgroundInverseStrong'; - boxShadowHover = 'shadowBorderInverse'; - } else if (hasError && type !== 'hidden') { - boxShadow = 'shadowBorderErrorWeak'; - } else if (type === 'hidden') { + ({ disabled, element, hasError, readOnly, children, type, variant }, ref) => { + let backgroundColor = "colorBackgroundInverse" as BackgroundColor; + let boxShadow = "shadowBorderInverse" as BoxShadow; + let boxShadowHover = "shadowBorderInverseStrongest" as BoxShadow; + if (disabled && type !== "hidden") { + backgroundColor = "colorBackgroundInverse"; + boxShadow = "shadowBorderInverseWeaker"; + boxShadowHover = "shadowBorderInverseWeaker"; + } else if (readOnly && type !== "hidden") { + backgroundColor = "colorBackgroundInverseStrong"; + boxShadowHover = "shadowBorderInverse"; + } else if (hasError && type !== "hidden") { + boxShadow = "shadowBorderErrorWeak"; + } else if (type === "hidden") { backgroundColor = null; boxShadow = null; boxShadowHover = null; @@ -35,14 +35,14 @@ const InverseFauxInput = React.forwardRef( borderRadius="borderRadius20" color="colorTextInverse" transition="box-shadow 100ms ease-in" - cursor={disabled ? 'not-allowed' : 'text'} + cursor={disabled ? "not-allowed" : "text"} variant={variant} _hover={{ boxShadow: boxShadowHover, }} _focusWithin={{ - backgroundColor: 'colorBackgroundInverse', - boxShadow: disabled ? boxShadow : 'shadowFocusInverse', + backgroundColor: "colorBackgroundInverse", + boxShadow: disabled ? boxShadow : "shadowFocusInverse", }} _active={{ boxShadow: boxShadowHover, @@ -51,9 +51,9 @@ const InverseFauxInput = React.forwardRef( {children} ); - } + }, ); -InverseFauxInput.displayName = 'InverseFauxInput'; +InverseFauxInput.displayName = "InverseFauxInput"; -export {InverseFauxInput}; +export { InverseFauxInput }; diff --git a/packages/paste-core/components/input-box/src/FauxInput/index.tsx b/packages/paste-core/components/input-box/src/FauxInput/index.tsx index 72a7ac322a..ca916fdbea 100644 --- a/packages/paste-core/components/input-box/src/FauxInput/index.tsx +++ b/packages/paste-core/components/input-box/src/FauxInput/index.tsx @@ -1,8 +1,8 @@ -import * as React from 'react'; +import * as React from "react"; -import {DefaultFauxInput} from './DefaultFauxInput'; -import {InverseFauxInput} from './InverseFauxInput'; -import type {FauxInputProps} from '../types'; +import type { FauxInputProps } from "../types"; +import { DefaultFauxInput } from "./DefaultFauxInput"; +import { InverseFauxInput } from "./InverseFauxInput"; const FauxInputVariants = { default: DefaultFauxInput, @@ -10,7 +10,7 @@ const FauxInputVariants = { }; const FieldWrapper = React.forwardRef( - ({children, disabled, element, hasError, readOnly, type, variant = 'default'}, ref) => { + ({ children, disabled, element, hasError, readOnly, type, variant = "default" }, ref) => { const FieldWrapperComponent = FauxInputVariants[variant]; return ( @@ -26,9 +26,9 @@ const FieldWrapper = React.forwardRef( {children} ); - } + }, ); -FieldWrapper.displayName = 'FieldWrapper'; +FieldWrapper.displayName = "FieldWrapper"; -export {FieldWrapper}; +export { FieldWrapper }; diff --git a/packages/paste-core/components/input-box/src/InputBox.tsx b/packages/paste-core/components/input-box/src/InputBox.tsx index c3612ae454..a384ccb1c7 100644 --- a/packages/paste-core/components/input-box/src/InputBox.tsx +++ b/packages/paste-core/components/input-box/src/InputBox.tsx @@ -1,11 +1,11 @@ -import * as React from 'react'; -import type {BoxProps} from '@twilio-paste/box'; +import type { BoxProps } from "@twilio-paste/box"; +import * as React from "react"; -import {FieldWrapper} from './FauxInput'; -import {Prefix} from './Prefix'; -import {Suffix} from './Suffix'; -import type {InputBoxTypes, Variants} from './types'; -import {InputBoxContext} from './InputBoxContext'; +import { FieldWrapper } from "./FauxInput"; +import { InputBoxContext } from "./InputBoxContext"; +import { Prefix } from "./Prefix"; +import { Suffix } from "./Suffix"; +import type { InputBoxTypes, Variants } from "./types"; export interface InputBoxProps { children: NonNullable; @@ -14,7 +14,7 @@ export interface InputBoxProps { * Requiring element here instead of extending directly from BoxProps. * This ensures an element prop is always passed on these composite components. */ - element: BoxProps['element']; + element: BoxProps["element"]; hasError?: boolean; insertAfter?: React.ReactNode; insertBefore?: React.ReactNode; @@ -29,17 +29,17 @@ const InputBox = React.forwardRef ( - + - ) + ), ); -InputBox.displayName = 'InputBox'; +InputBox.displayName = "InputBox"; -export {InputBox}; +export { InputBox }; diff --git a/packages/paste-core/components/input-box/src/InputBoxContext.tsx b/packages/paste-core/components/input-box/src/InputBoxContext.tsx index f4a725dc2d..7aa74e076b 100644 --- a/packages/paste-core/components/input-box/src/InputBoxContext.tsx +++ b/packages/paste-core/components/input-box/src/InputBoxContext.tsx @@ -1,6 +1,6 @@ -import * as React from 'react'; +import * as React from "react"; -import type {Variants} from './types'; +import type { Variants } from "./types"; interface InputBoxContextData { disabled: boolean; @@ -12,7 +12,7 @@ export const InputBoxContext = React.createContext(n export const useInputBoxContext = (): InputBoxContextData => { const context = React.useContext(InputBoxContext); if (!context) { - throw new Error('useInputBoxContext must be used within a component.'); + throw new Error("useInputBoxContext must be used within a component."); } return context; }; diff --git a/packages/paste-core/components/input-box/src/InputChevronWrapper.tsx b/packages/paste-core/components/input-box/src/InputChevronWrapper.tsx index 1ca113e19d..19b82e423e 100644 --- a/packages/paste-core/components/input-box/src/InputChevronWrapper.tsx +++ b/packages/paste-core/components/input-box/src/InputChevronWrapper.tsx @@ -1,27 +1,27 @@ -import * as React from 'react'; -import {Box} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; -import type {BackgroundColor, TextColor} from '@twilio-paste/style-props'; +import { Box } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import type { BackgroundColor, TextColor } from "@twilio-paste/style-props"; +import * as React from "react"; -import type {Variants} from './types'; -import {useInputBoxContext} from './InputBoxContext'; +import { useInputBoxContext } from "./InputBoxContext"; +import type { Variants } from "./types"; -type StateOptions = 'default' | 'disabled' | 'readOnly'; +type StateOptions = "default" | "disabled" | "readOnly"; const getChevronWrapperState = (disabled: boolean, readOnly: boolean): StateOptions => // eslint-disable-next-line unicorn/no-nested-ternary - disabled ? 'disabled' : readOnly ? 'readOnly' : 'default'; + disabled ? "disabled" : readOnly ? "readOnly" : "default"; -const IconColors: {[variant in Variants]: {[key in StateOptions]: TextColor}} = { +const IconColors: { [variant in Variants]: { [key in StateOptions]: TextColor } } = { default: { - default: 'colorTextIcon', - disabled: 'colorTextWeaker', - readOnly: 'colorTextWeaker', + default: "colorTextIcon", + disabled: "colorTextWeaker", + readOnly: "colorTextWeaker", }, inverse: { - default: 'colorTextIconInverse', - disabled: 'colorTextInverseWeakest', - readOnly: 'colorTextInverseWeakest', + default: "colorTextIconInverse", + disabled: "colorTextInverseWeakest", + readOnly: "colorTextInverseWeakest", }, }; @@ -34,23 +34,23 @@ const IconColors: {[variant in Variants]: {[key in StateOptions]: TextColor}} = * @returns {TextColor} the icon color */ const getInputChevronIconColor = ( - variant: Variants | undefined = 'default', + variant: Variants | undefined = "default", disabled: boolean | undefined = false, - readOnly: boolean | undefined = false + readOnly: boolean | undefined = false, ): TextColor => { return IconColors[variant][getChevronWrapperState(disabled, readOnly)]; }; -const BackgroundColorStyles: {[variant: string]: {[key: string]: BackgroundColor}} = { +const BackgroundColorStyles: { [variant: string]: { [key: string]: BackgroundColor } } = { default: { - default: 'colorBackground', - disabled: 'colorBackground', - readOnly: 'colorBackground', + default: "colorBackground", + disabled: "colorBackground", + readOnly: "colorBackground", }, inverse: { - default: 'colorBackgroundInverseStrong', - disabled: 'colorBackgroundInverse', - readOnly: 'colorBackgroundInverseStrong', + default: "colorBackgroundInverseStrong", + disabled: "colorBackgroundInverse", + readOnly: "colorBackgroundInverseStrong", }, }; @@ -60,12 +60,12 @@ export interface InputChevronWrapperProps { * Requiring element here instead of extending directly from BoxProps. * This ensures an element prop is always passed on these composite components. */ - element: BoxProps['element']; + element: BoxProps["element"]; } const InputChevronWrapper = React.forwardRef>( - ({children, element = 'CHEVRON_WRAPPER'}, ref) => { - const {disabled, readOnly, variant} = useInputBoxContext(); + ({ children, element = "CHEVRON_WRAPPER" }, ref) => { + const { disabled, readOnly, variant } = useInputBoxContext(); return ( ); - } + }, ); -InputChevronWrapper.displayName = 'InputChevronWrapper'; +InputChevronWrapper.displayName = "InputChevronWrapper"; -export {InputChevronWrapper, getInputChevronIconColor}; +export { InputChevronWrapper, getInputChevronIconColor }; diff --git a/packages/paste-core/components/input-box/src/Prefix.tsx b/packages/paste-core/components/input-box/src/Prefix.tsx index bd7c74944b..e794431f33 100644 --- a/packages/paste-core/components/input-box/src/Prefix.tsx +++ b/packages/paste-core/components/input-box/src/Prefix.tsx @@ -1,9 +1,9 @@ -import * as React from 'react'; -import {Box} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; -import type {BackgroundColor, BorderColor} from '@twilio-paste/style-props'; +import { Box } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import type { BackgroundColor, BorderColor } from "@twilio-paste/style-props"; +import * as React from "react"; -import type {Variants} from './types'; +import type { Variants } from "./types"; export interface PrefixProps { children: NonNullable; @@ -12,24 +12,24 @@ export interface PrefixProps { * Requiring element here instead of extending directly from BoxProps. * This ensures an element prop is always passed on these composite components. */ - element: BoxProps['element']; + element: BoxProps["element"]; variant?: Variants; } const Prefix = React.forwardRef( - ({children, disabled, element = 'PREFIX', variant}, ref) => { - let backgroundColor = 'colorBackgroundWeak' as BackgroundColor; - let borderColor = 'colorBorderWeaker' as BorderColor; + ({ children, disabled, element = "PREFIX", variant }, ref) => { + let backgroundColor = "colorBackgroundWeak" as BackgroundColor; + let borderColor = "colorBorderWeaker" as BorderColor; - if (disabled && variant === 'inverse') { - backgroundColor = 'none'; - borderColor = 'colorBorderInverseWeaker'; - } else if (variant === 'inverse') { - backgroundColor = 'colorBackgroundInverse'; - borderColor = 'colorBorderInverse'; + if (disabled && variant === "inverse") { + backgroundColor = "none"; + borderColor = "colorBorderInverseWeaker"; + } else if (variant === "inverse") { + backgroundColor = "colorBackgroundInverse"; + borderColor = "colorBorderInverse"; } else if (disabled) { - backgroundColor = 'none'; - borderColor = 'colorBorderWeaker'; + backgroundColor = "none"; + borderColor = "colorBorderWeaker"; } if (children == null) return null; @@ -52,9 +52,9 @@ const Prefix = React.forwardRef( {children} ); - } + }, ); -Prefix.displayName = 'Prefix'; +Prefix.displayName = "Prefix"; -export {Prefix}; +export { Prefix }; diff --git a/packages/paste-core/components/input-box/src/Suffix.tsx b/packages/paste-core/components/input-box/src/Suffix.tsx index 41350dc73b..6639efeb47 100644 --- a/packages/paste-core/components/input-box/src/Suffix.tsx +++ b/packages/paste-core/components/input-box/src/Suffix.tsx @@ -1,9 +1,9 @@ -import * as React from 'react'; -import {Box} from '@twilio-paste/box'; -import type {BoxProps} from '@twilio-paste/box'; -import type {BackgroundColor, BorderColor} from '@twilio-paste/style-props'; +import { Box } from "@twilio-paste/box"; +import type { BoxProps } from "@twilio-paste/box"; +import type { BackgroundColor, BorderColor } from "@twilio-paste/style-props"; +import * as React from "react"; -import type {Variants} from './types'; +import type { Variants } from "./types"; export interface SuffixProps { children: NonNullable; @@ -12,24 +12,24 @@ export interface SuffixProps { * Requiring element here instead of extending directly from BoxProps. * This ensures an element prop is always passed on these composite components. */ - element: BoxProps['element']; + element: BoxProps["element"]; variant?: Variants; } const Suffix = React.forwardRef( - ({children, disabled, element = 'SUFFIX', variant}, ref) => { - let backgroundColor = 'colorBackgroundWeak' as BackgroundColor; - let borderColor = 'colorBorderWeaker' as BorderColor; + ({ children, disabled, element = "SUFFIX", variant }, ref) => { + let backgroundColor = "colorBackgroundWeak" as BackgroundColor; + let borderColor = "colorBorderWeaker" as BorderColor; - if (disabled && variant === 'inverse') { - backgroundColor = 'none'; - borderColor = 'colorBorderInverseWeaker'; - } else if (variant === 'inverse') { - backgroundColor = 'colorBackgroundInverse'; - borderColor = 'colorBorderInverse'; + if (disabled && variant === "inverse") { + backgroundColor = "none"; + borderColor = "colorBorderInverseWeaker"; + } else if (variant === "inverse") { + backgroundColor = "colorBackgroundInverse"; + borderColor = "colorBorderInverse"; } else if (disabled) { - backgroundColor = 'none'; - borderColor = 'colorBorderWeaker'; + backgroundColor = "none"; + borderColor = "colorBorderWeaker"; } if (children == null) return null; @@ -52,9 +52,9 @@ const Suffix = React.forwardRef( {children} ); - } + }, ); -Suffix.displayName = 'Suffix'; +Suffix.displayName = "Suffix"; -export {Suffix}; +export { Suffix }; diff --git a/packages/paste-core/components/input-box/src/index.tsx b/packages/paste-core/components/input-box/src/index.tsx index 1b4ffdbaac..aecf58c32c 100644 --- a/packages/paste-core/components/input-box/src/index.tsx +++ b/packages/paste-core/components/input-box/src/index.tsx @@ -1,5 +1,5 @@ -export * from './InputBox'; -export * from './Suffix'; -export * from './Prefix'; -export * from './InputChevronWrapper'; -export type {InputBoxTypes} from './types'; +export * from "./InputBox"; +export * from "./Suffix"; +export * from "./Prefix"; +export * from "./InputChevronWrapper"; +export type { InputBoxTypes } from "./types"; diff --git a/packages/paste-core/components/input-box/src/types.ts b/packages/paste-core/components/input-box/src/types.ts index dd4b1cef4c..86594cf2e6 100644 --- a/packages/paste-core/components/input-box/src/types.ts +++ b/packages/paste-core/components/input-box/src/types.ts @@ -1,17 +1,17 @@ -import type {BoxProps} from '@twilio-paste/box'; +import type { BoxProps } from "@twilio-paste/box"; export type InputBoxTypes = - | 'text' - | 'email' - | 'hidden' - | 'number' - | 'password' - | 'search' - | 'tel' - | 'date' - | 'time' - | 'url'; -export type Variants = 'default' | 'inverse'; + | "text" + | "email" + | "hidden" + | "number" + | "password" + | "search" + | "tel" + | "date" + | "time" + | "url"; +export type Variants = "default" | "inverse"; export interface FauxInputProps { children: NonNullable; @@ -20,7 +20,7 @@ export interface FauxInputProps { * Requiring element here instead of extending directly from BoxProps. * This ensures an element prop is always passed on these composite components. */ - element: BoxProps['element']; + element: BoxProps["element"]; hasError?: boolean; readOnly?: boolean; type?: InputBoxTypes; diff --git a/packages/paste-core/components/input-box/stories/inputbox.stories.tsx b/packages/paste-core/components/input-box/stories/inputbox.stories.tsx index f8538deaa9..f39c2f7aef 100644 --- a/packages/paste-core/components/input-box/stories/inputbox.stories.tsx +++ b/packages/paste-core/components/input-box/stories/inputbox.stories.tsx @@ -1,10 +1,10 @@ -import * as React from 'react'; -import {Box} from '@twilio-paste/box'; -import {Stack} from '@twilio-paste/stack'; -import {ChevronDownIcon} from '@twilio-paste/icons/esm/ChevronDownIcon'; +import { Box } from "@twilio-paste/box"; +import { ChevronDownIcon } from "@twilio-paste/icons/esm/ChevronDownIcon"; +import { Stack } from "@twilio-paste/stack"; +import * as React from "react"; -import type {InputBoxProps} from '../src'; -import {InputBox, InputChevronWrapper, getInputChevronIconColor} from '../src'; +import type { InputBoxProps } from "../src"; +import { InputBox, InputChevronWrapper, getInputChevronIconColor } from "../src"; const Insert = (): JSX.Element => { return ; @@ -14,7 +14,7 @@ const Input = (): JSX.Element => { return ; }; -const CommonStories: React.FC>> = ({variant, ...props}) => { +const CommonStories: React.FC>> = ({ variant, ...props }) => { return ( @@ -46,7 +46,7 @@ const CommonStories: React.FC { return ; }; -Default.storyName = 'default'; +Default.storyName = "default"; export const Readonly = (): React.ReactNode => { return ; }; -Readonly.storyName = 'readonly'; +Readonly.storyName = "readonly"; export const Disabled = (): React.ReactNode => { return ; }; -Disabled.storyName = 'disabled'; +Disabled.storyName = "disabled"; export const Error = (): React.ReactNode => { return ; }; -Error.storyName = 'error'; +Error.storyName = "error"; export const Inverse = (): React.ReactNode => { return ( @@ -82,7 +82,7 @@ export const Inverse = (): React.ReactNode => { ); }; -Inverse.storyName = 'inverse'; +Inverse.storyName = "inverse"; export const InverseReadonly = (): React.ReactNode => { return ( @@ -92,7 +92,7 @@ export const InverseReadonly = (): React.ReactNode => { ); }; -InverseReadonly.storyName = 'inverse readonly'; +InverseReadonly.storyName = "inverse readonly"; export const InverseDisabled = (): React.ReactNode => { return ( @@ -102,7 +102,7 @@ export const InverseDisabled = (): React.ReactNode => { ); }; -InverseDisabled.storyName = 'inverse disabled'; +InverseDisabled.storyName = "inverse disabled"; export const InverseError = (): React.ReactNode => { return ( @@ -112,4 +112,4 @@ export const InverseError = (): React.ReactNode => { ); }; -InverseError.storyName = 'inverse error'; +InverseError.storyName = "inverse error"; diff --git a/packages/paste-core/components/input/__tests__/input.test.tsx b/packages/paste-core/components/input/__tests__/input.test.tsx index c2e2ffb717..5dcd8a8952 100644 --- a/packages/paste-core/components/input/__tests__/input.test.tsx +++ b/packages/paste-core/components/input/__tests__/input.test.tsx @@ -1,137 +1,137 @@ -import * as React from 'react'; -import {act, render, screen} from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import {CustomizationProvider} from '@twilio-paste/customization'; +import { act, render, screen } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import * as React from "react"; -import {Input} from '../src'; -import type {InputTypes} from '../src'; +import { Input } from "../src"; +import type { InputTypes } from "../src"; const NOOP = (): void => {}; const NumberInput: React.FC = () => { - const [value, setValue] = React.useState('0'); + const [value, setValue] = React.useState("0"); return setValue(e.currentTarget.value)} />; }; -describe('Input inner input props', () => { +describe("Input inner input props", () => { const initialProps = { - id: 'input', - name: 'cool', - type: 'password' as InputTypes, - value: 'value', + id: "input", + name: "cool", + type: "password" as InputTypes, + value: "value", onChange: NOOP, disabled: true, readOnly: true, hasError: true, - placeholder: 'Enter your name', + placeholder: "Enter your name", }; - const {getByPlaceholderText} = render(); + const { getByPlaceholderText } = render(); const InnerInput = getByPlaceholderText(initialProps.placeholder); - it('should render', () => { + it("should render", () => { expect(InnerInput).toBeDefined(); }); - it('should set disabled correctly', () => { - expect(InnerInput.getAttribute('disabled')).toEqual(''); - expect(InnerInput).toHaveStyleRule('-webkit-text-fill-color', 'colorTextWeaker', {target: ':disabled'}); + it("should set disabled correctly", () => { + expect(InnerInput.getAttribute("disabled")).toEqual(""); + expect(InnerInput).toHaveStyleRule("-webkit-text-fill-color", "colorTextWeaker", { target: ":disabled" }); }); - it('should set readOnly correctly', () => { - expect(InnerInput.getAttribute('aria-readonly')).toEqual('true'); - expect(InnerInput.getAttribute('readOnly')).toEqual(''); + it("should set readOnly correctly", () => { + expect(InnerInput.getAttribute("aria-readonly")).toEqual("true"); + expect(InnerInput.getAttribute("readOnly")).toEqual(""); }); - it('should set hasError correctly', () => { - expect(InnerInput.getAttribute('aria-invalid')).toEqual('true'); + it("should set hasError correctly", () => { + expect(InnerInput.getAttribute("aria-invalid")).toEqual("true"); }); - it('should set id correctly', () => { - expect(InnerInput.getAttribute('id')).toEqual(initialProps.id); + it("should set id correctly", () => { + expect(InnerInput.getAttribute("id")).toEqual(initialProps.id); }); - it('should set type correctly', () => { - expect(InnerInput.getAttribute('type')).toEqual(initialProps.type); + it("should set type correctly", () => { + expect(InnerInput.getAttribute("type")).toEqual(initialProps.type); }); - it('should set value correctly', () => { - expect(InnerInput.getAttribute('value')).toEqual(initialProps.value); + it("should set value correctly", () => { + expect(InnerInput.getAttribute("value")).toEqual(initialProps.value); }); - it('should set name correctly', () => { - expect(InnerInput.getAttribute('name')).toEqual(initialProps.name); + it("should set name correctly", () => { + expect(InnerInput.getAttribute("name")).toEqual(initialProps.name); }); - it('should set placeholder correctly', () => { - expect(InnerInput.getAttribute('placeholder')).toEqual(initialProps.placeholder); + it("should set placeholder correctly", () => { + expect(InnerInput.getAttribute("placeholder")).toEqual(initialProps.placeholder); }); - it('should render with margin: space0', () => { - expect(InnerInput).toHaveStyleRule('margin', 'space0'); + it("should render with margin: space0", () => { + expect(InnerInput).toHaveStyleRule("margin", "space0"); }); }); -describe('Input insertBefore prop', () => { +describe("Input insertBefore prop", () => { const initialProps = { - id: 'input', - type: 'text' as InputTypes, - value: 'value', + id: "input", + type: "text" as InputTypes, + value: "value", onChange: NOOP, - placeholder: 'placeholder', + placeholder: "placeholder", }; - it('should render a prefix', () => { - const {getByText} = render($10.99
    } />); - expect(getByText('$10.99')).toBeDefined(); + it("should render a prefix", () => { + const { getByText } = render($10.99
    } />); + expect(getByText("$10.99")).toBeDefined(); }); - it('should render a suffix', () => { - const {getByText} = render($11.99
    } />); - expect(getByText('$11.99')).toBeDefined(); + it("should render a suffix", () => { + const { getByText } = render($11.99
    } />); + expect(getByText("$11.99")).toBeDefined(); }); }); -describe('Input event handlers', () => { - it('Should call the appropriate event handlers', () => { +describe("Input event handlers", () => { + it("Should call the appropriate event handlers", () => { const onChangeMock: jest.Mock = jest.fn(); const onFocusMock: jest.Mock = jest.fn(); const onBlurMock: jest.Mock = jest.fn(); - const {getByRole} = render( - + const { getByRole } = render( + , ); - const RenderedInput = getByRole('textbox'); + const RenderedInput = getByRole("textbox"); RenderedInput.focus(); expect(onFocusMock).toHaveBeenCalledTimes(1); RenderedInput.blur(); expect(onBlurMock).toHaveBeenCalledTimes(1); act(() => { - userEvent.type(RenderedInput, 'foo'); + userEvent.type(RenderedInput, "foo"); }); expect(onChangeMock).toHaveBeenCalledTimes(3); }); }); -describe('Input block props', () => { +describe("Input block props", () => { const initialProps = { - id: 'input', - type: 'text' as InputTypes, - value: 'value', + id: "input", + type: "text" as InputTypes, + value: "value", onChange: NOOP, - className: 'foo', - width: '300px', + className: "foo", + width: "300px", }; - it('should not pass width and classname props', () => { + it("should not pass width and classname props", () => { // @ts-expect-error we are passing unexpected props on purpose render(); - const RenderedInput = screen.getByRole('textbox'); + const RenderedInput = screen.getByRole("textbox"); - expect(RenderedInput).toHaveStyleRule('width', '100%'); + expect(RenderedInput).toHaveStyleRule("width", "100%"); - const classNames = RenderedInput.getAttribute('class'); + const classNames = RenderedInput.getAttribute("class"); expect(classNames).toBeDefined(); if (classNames != null) { // eslint-disable-next-line jest/no-conditional-expect @@ -140,19 +140,19 @@ describe('Input block props', () => { }); }); -describe('HTML attributes', () => { - it('should set a element data attribute for Input', () => { +describe("HTML attributes", () => { + it("should set a element data attribute for Input", () => { render(); - expect(screen.getByRole('textbox').getAttribute('data-paste-element')).toEqual('INPUT_ELEMENT'); + expect(screen.getByRole("textbox").getAttribute("data-paste-element")).toEqual("INPUT_ELEMENT"); }); - it('should set a custom element data attribute for Input', () => { + it("should set a custom element data attribute for Input", () => { render(); - expect(screen.getByRole('textbox').getAttribute('data-paste-element')).toEqual('foo_ELEMENT'); + expect(screen.getByRole("textbox").getAttribute("data-paste-element")).toEqual("foo_ELEMENT"); }); - it('should set the data attribute for all Input nodes', (): void => { - const {container} = render( + it("should set the data attribute for all Input nodes", (): void => { + const { container } = render( { onChange={NOOP} insertBefore={<>test before} insertAfter={<>test after} - /> + />, ); expect(container.querySelector('[data-paste-element="INPUT"]')).toBeInTheDocument(); - expect(screen.getByRole('textbox').getAttribute('data-paste-element')).toEqual('INPUT_ELEMENT'); - expect(screen.getByText('test before').getAttribute('data-paste-element')).toEqual('INPUT_PREFIX'); - expect(screen.getByText('test after').getAttribute('data-paste-element')).toEqual('INPUT_SUFFIX'); + expect(screen.getByRole("textbox").getAttribute("data-paste-element")).toEqual("INPUT_ELEMENT"); + expect(screen.getByText("test before").getAttribute("data-paste-element")).toEqual("INPUT_PREFIX"); + expect(screen.getByText("test after").getAttribute("data-paste-element")).toEqual("INPUT_SUFFIX"); }); - it('should set the custom element data attribute for all Input nodes', (): void => { - const {container} = render( + it("should set the custom element data attribute for all Input nodes", (): void => { + const { container } = render( { element="foo" insertBefore={<>test before} insertAfter={<>test after} - /> + />, ); expect(container.querySelector('[data-paste-element="foo"]')).toBeInTheDocument(); - expect(screen.getByRole('textbox').getAttribute('data-paste-element')).toEqual('foo_ELEMENT'); - expect(screen.getByText('test before').getAttribute('data-paste-element')).toEqual('foo_PREFIX'); - expect(screen.getByText('test after').getAttribute('data-paste-element')).toEqual('foo_SUFFIX'); + expect(screen.getByRole("textbox").getAttribute("data-paste-element")).toEqual("foo_ELEMENT"); + expect(screen.getByText("test before").getAttribute("data-paste-element")).toEqual("foo_PREFIX"); + expect(screen.getByText("test after").getAttribute("data-paste-element")).toEqual("foo_SUFFIX"); }); }); -describe('Number Input', () => { - it('increases when step up clicked', () => { - const {getByRole} = render(); - userEvent.click(getByRole('button', {name: 'step value up'})); - expect(getByRole('spinbutton').value).toBe('2'); +describe("Number Input", () => { + it("increases when step up clicked", () => { + const { getByRole } = render(); + userEvent.click(getByRole("button", { name: "step value up" })); + expect(getByRole("spinbutton").value).toBe("2"); }); - it('decreases when step down clicked', () => { - const {getByRole} = render(); - userEvent.click(getByRole('button', {name: 'step value down'})); - expect(getByRole('spinbutton').value).toBe('2'); + it("decreases when step down clicked", () => { + const { getByRole } = render(); + userEvent.click(getByRole("button", { name: "step value down" })); + expect(getByRole("spinbutton").value).toBe("2"); }); - it('increases by step when step up clicked', () => { - const {getByRole} = render(); - userEvent.click(getByRole('button', {name: 'step value up'})); - expect(getByRole('spinbutton').value).toBe('3'); + it("increases by step when step up clicked", () => { + const { getByRole } = render(); + userEvent.click(getByRole("button", { name: "step value up" })); + expect(getByRole("spinbutton").value).toBe("3"); }); - it('decreases by step when step down clicked', () => { - const {getByRole} = render(); - userEvent.click(getByRole('button', {name: 'step value down'})); - expect(getByRole('spinbutton').value).toBe('1'); + it("decreases by step when step down clicked", () => { + const { getByRole } = render(); + userEvent.click(getByRole("button", { name: "step value down" })); + expect(getByRole("spinbutton").value).toBe("1"); }); - it('does not decrement below min value', () => { - const {getByRole} = render(); - userEvent.click(getByRole('button', {name: 'step value down'})); - expect(getByRole('spinbutton').value).toBe('1'); + it("does not decrement below min value", () => { + const { getByRole } = render(); + userEvent.click(getByRole("button", { name: "step value down" })); + expect(getByRole("spinbutton").value).toBe("1"); }); - it('does not increment above max value', () => { - const {getByRole} = render(); - userEvent.click(getByRole('button', {name: 'step value up'})); - expect(getByRole('spinbutton').value).toBe('5'); + it("does not increment above max value", () => { + const { getByRole } = render(); + userEvent.click(getByRole("button", { name: "step value up" })); + expect(getByRole("spinbutton").value).toBe("5"); }); - it('increase button hides when hit max', () => { - const {getByRole} = render(); - const IncreaseButton = getByRole('button', {name: 'step value up'}); + it("increase button hides when hit max", () => { + const { getByRole } = render(); + const IncreaseButton = getByRole("button", { name: "step value up" }); act(() => { userEvent.click(IncreaseButton); }); - expect(getByRole('spinbutton').value).toBe('1'); + expect(getByRole("spinbutton").value).toBe("1"); act(() => { userEvent.click(IncreaseButton); }); - expect(getByRole('spinbutton').value).toBe('2'); + expect(getByRole("spinbutton").value).toBe("2"); expect(IncreaseButton).not.toBeInTheDocument(); }); - it('decrease button hides when hit min', () => { - const {getByRole} = render(); - const DecreaseButton = getByRole('button', {name: 'step value down'}); + it("decrease button hides when hit min", () => { + const { getByRole } = render(); + const DecreaseButton = getByRole("button", { name: "step value down" }); act(() => { userEvent.click(DecreaseButton); }); - expect(getByRole('spinbutton').value).toBe('-1'); + expect(getByRole("spinbutton").value).toBe("-1"); expect(DecreaseButton).not.toBeInTheDocument(); }); }); -describe('Customization', () => { - it('should add custom styles to Input', (): void => { - const {container} = render( +describe("Customization", () => { + it("should add custom styles to Input", (): void => { + const { container } = render( { insertBefore={<>test before} insertAfter={<>test after} /> - + , ); const renderedInput = container.querySelector('[data-paste-element="INPUT"]'); - const renderedInputElement = screen.getByRole('textbox'); - const renderedInputPrefix = screen.getByText('test before'); - const renderedInputSuffix = screen.getByText('test after'); - expect(renderedInput).toHaveStyleRule('background-color', 'rgb(244, 244, 246)'); - expect(renderedInputElement).toHaveStyleRule('background-color', 'rgb(244, 244, 246)'); - expect(renderedInputPrefix).toHaveStyleRule('background-color', 'rgb(244, 244, 246)'); - expect(renderedInputSuffix).toHaveStyleRule('background-color', 'rgb(244, 244, 246)'); + const renderedInputElement = screen.getByRole("textbox"); + const renderedInputPrefix = screen.getByText("test before"); + const renderedInputSuffix = screen.getByText("test after"); + expect(renderedInput).toHaveStyleRule("background-color", "rgb(244, 244, 246)"); + expect(renderedInputElement).toHaveStyleRule("background-color", "rgb(244, 244, 246)"); + expect(renderedInputPrefix).toHaveStyleRule("background-color", "rgb(244, 244, 246)"); + expect(renderedInputSuffix).toHaveStyleRule("background-color", "rgb(244, 244, 246)"); }); - it('should add custom styles to a Input variant', (): void => { - const {container} = render( + it("should add custom styles to a Input variant", (): void => { + const { container } = render( @@ -333,36 +333,36 @@ describe('Customization', () => { insertBefore={<>test before} insertAfter={<>test after} /> - + , ); const renderedInput = container.querySelector('[data-paste-element="INPUT"]'); - const renderedInputElement = screen.getByRole('spinbutton'); - const renderedInputPrefix = screen.getByText('test before'); - const renderedInputSuffix = screen.getByText('test after'); - const renderedIncrement = screen.getByRole('button', {name: 'step value up'}); - const renderedDecrement = screen.getByRole('button', {name: 'step value down'}); - expect(renderedInput).toHaveStyleRule('background-color', 'rgb(0, 20, 137)'); - expect(renderedInputElement).toHaveStyleRule('background-color', 'rgb(0, 20, 137)'); - expect(renderedInputPrefix).toHaveStyleRule('background-color', 'rgb(0, 20, 137)'); - expect(renderedInputSuffix).toHaveStyleRule('background-color', 'rgb(0, 20, 137)'); - expect(renderedIncrement).toHaveStyleRule('background-color', 'rgb(245, 240, 252)'); - expect(renderedDecrement).toHaveStyleRule('background-color', 'rgb(214, 31, 31)'); + const renderedInputElement = screen.getByRole("spinbutton"); + const renderedInputPrefix = screen.getByText("test before"); + const renderedInputSuffix = screen.getByText("test after"); + const renderedIncrement = screen.getByRole("button", { name: "step value up" }); + const renderedDecrement = screen.getByRole("button", { name: "step value down" }); + expect(renderedInput).toHaveStyleRule("background-color", "rgb(0, 20, 137)"); + expect(renderedInputElement).toHaveStyleRule("background-color", "rgb(0, 20, 137)"); + expect(renderedInputPrefix).toHaveStyleRule("background-color", "rgb(0, 20, 137)"); + expect(renderedInputSuffix).toHaveStyleRule("background-color", "rgb(0, 20, 137)"); + expect(renderedIncrement).toHaveStyleRule("background-color", "rgb(245, 240, 252)"); + expect(renderedDecrement).toHaveStyleRule("background-color", "rgb(214, 31, 31)"); }); - it('should add custom styles to Input with a custom element data attribute', (): void => { - const {container} = render( + it("should add custom styles to Input with a custom element data attribute", (): void => { + const { container } = render( @@ -375,56 +375,56 @@ describe('Customization', () => { insertBefore={<>test before} insertAfter={<>test after} /> - + , ); const renderedInput = container.querySelector('[data-paste-element="FOO"]'); - const renderedInputElement = screen.getByRole('spinbutton'); - const renderedInputPrefix = screen.getByText('test before'); - const renderedInputSuffix = screen.getByText('test after'); - const renderedIncrement = screen.getByRole('button', {name: 'step value up'}); - const renderedDecrement = screen.getByRole('button', {name: 'step value down'}); - expect(renderedInput).toHaveStyleRule('background-color', 'rgb(244, 244, 246)'); - expect(renderedInputElement).toHaveStyleRule('background-color', 'rgb(244, 244, 246)'); - expect(renderedInputPrefix).toHaveStyleRule('background-color', 'rgb(244, 244, 246)'); - expect(renderedInputSuffix).toHaveStyleRule('background-color', 'rgb(244, 244, 246)'); - expect(renderedIncrement).toHaveStyleRule('background-color', 'rgb(245, 240, 252)'); - expect(renderedDecrement).toHaveStyleRule('background-color', 'rgb(214, 31, 31)'); + const renderedInputElement = screen.getByRole("spinbutton"); + const renderedInputPrefix = screen.getByText("test before"); + const renderedInputSuffix = screen.getByText("test after"); + const renderedIncrement = screen.getByRole("button", { name: "step value up" }); + const renderedDecrement = screen.getByRole("button", { name: "step value down" }); + expect(renderedInput).toHaveStyleRule("background-color", "rgb(244, 244, 246)"); + expect(renderedInputElement).toHaveStyleRule("background-color", "rgb(244, 244, 246)"); + expect(renderedInputPrefix).toHaveStyleRule("background-color", "rgb(244, 244, 246)"); + expect(renderedInputSuffix).toHaveStyleRule("background-color", "rgb(244, 244, 246)"); + expect(renderedIncrement).toHaveStyleRule("background-color", "rgb(245, 240, 252)"); + expect(renderedDecrement).toHaveStyleRule("background-color", "rgb(214, 31, 31)"); }); - it('should add custom styles to a Input variant with a custom element data attribute', (): void => { - const {container} = render( + it("should add custom styles to a Input variant with a custom element data attribute", (): void => { + const { container } = render( { insertBefore={<>test before} insertAfter={<>test after} /> - + , ); const renderedInput = container.querySelector('[data-paste-element="FOO"]'); - const renderedInputElement = screen.getByRole('textbox'); - const renderedInputPrefix = screen.getByText('test before'); - const renderedInputSuffix = screen.getByText('test after'); - expect(renderedInput).toHaveStyleRule('background-color', 'rgb(0, 20, 137)'); - expect(renderedInputElement).toHaveStyleRule('background-color', 'rgb(0, 20, 137)'); - expect(renderedInputPrefix).toHaveStyleRule('background-color', 'rgb(0, 20, 137)'); - expect(renderedInputSuffix).toHaveStyleRule('background-color', 'rgb(0, 20, 137)'); + const renderedInputElement = screen.getByRole("textbox"); + const renderedInputPrefix = screen.getByText("test before"); + const renderedInputSuffix = screen.getByText("test after"); + expect(renderedInput).toHaveStyleRule("background-color", "rgb(0, 20, 137)"); + expect(renderedInputElement).toHaveStyleRule("background-color", "rgb(0, 20, 137)"); + expect(renderedInputPrefix).toHaveStyleRule("background-color", "rgb(0, 20, 137)"); + expect(renderedInputSuffix).toHaveStyleRule("background-color", "rgb(0, 20, 137)"); }); }); diff --git a/packages/paste-core/components/input/build.js b/packages/paste-core/components/input/build.js index a4edeab49b..27dd98f98e 100644 --- a/packages/paste-core/components/input/build.js +++ b/packages/paste-core/components/input/build.js @@ -1,3 +1,3 @@ -const {build} = require('../../../../tools/build/esbuild'); +const { build } = require("../../../../tools/build/esbuild"); -build(require('./package.json')); +build(require("./package.json")); diff --git a/packages/paste-core/components/input/src/DecrementButton.tsx b/packages/paste-core/components/input/src/DecrementButton.tsx index 46f2c185aa..50b53e6e8c 100644 --- a/packages/paste-core/components/input/src/DecrementButton.tsx +++ b/packages/paste-core/components/input/src/DecrementButton.tsx @@ -1,18 +1,18 @@ -import * as React from 'react'; -import type {BoxProps} from '@twilio-paste/box'; -import {Button, type ButtonProps} from '@twilio-paste/button'; -import {ChevronDownIcon} from '@twilio-paste/icons/esm/ChevronDownIcon'; -import type {HTMLPasteProps} from '@twilio-paste/types'; +import type { BoxProps } from "@twilio-paste/box"; +import { Button, type ButtonProps } from "@twilio-paste/button"; +import { ChevronDownIcon } from "@twilio-paste/icons/esm/ChevronDownIcon"; +import type { HTMLPasteProps } from "@twilio-paste/types"; +import * as React from "react"; -export interface DecrementButtonProps extends HTMLPasteProps<'button'> { +export interface DecrementButtonProps extends HTMLPasteProps<"button"> { i18nStepDownLabel?: string; - element?: BoxProps['element']; + element?: BoxProps["element"]; // Button component restricts tabIndex values - tabIndex?: ButtonProps['tabIndex']; + tabIndex?: ButtonProps["tabIndex"]; } export const DecrementButton = React.forwardRef( - ({i18nStepDownLabel = 'step value down', element, ...props}, ref) => { + ({ i18nStepDownLabel = "step value down", element, ...props }, ref) => { return ( ); - } + }, ); -DecrementButton.displayName = 'Decrement'; +DecrementButton.displayName = "Decrement"; diff --git a/packages/paste-core/components/input/src/IncrementButton.tsx b/packages/paste-core/components/input/src/IncrementButton.tsx index e93e342da8..75d258fb43 100644 --- a/packages/paste-core/components/input/src/IncrementButton.tsx +++ b/packages/paste-core/components/input/src/IncrementButton.tsx @@ -1,18 +1,18 @@ -import * as React from 'react'; -import type {BoxProps} from '@twilio-paste/box'; -import {Button, type ButtonProps} from '@twilio-paste/button'; -import {ChevronUpIcon} from '@twilio-paste/icons/esm/ChevronUpIcon'; -import type {HTMLPasteProps} from '@twilio-paste/types'; +import type { BoxProps } from "@twilio-paste/box"; +import { Button, type ButtonProps } from "@twilio-paste/button"; +import { ChevronUpIcon } from "@twilio-paste/icons/esm/ChevronUpIcon"; +import type { HTMLPasteProps } from "@twilio-paste/types"; +import * as React from "react"; -export interface IncrementButtonProps extends HTMLPasteProps<'button'> { +export interface IncrementButtonProps extends HTMLPasteProps<"button"> { i18nStepUpLabel?: string; - element?: BoxProps['element']; + element?: BoxProps["element"]; // Button component restricts tabIndex values - tabIndex?: ButtonProps['tabIndex']; + tabIndex?: ButtonProps["tabIndex"]; } export const IncrementButton = React.forwardRef( - ({i18nStepUpLabel = 'step value up', element, ...props}, ref) => { + ({ i18nStepUpLabel = "step value up", element, ...props }, ref) => { return ( ); - } + }, ); -IncrementButton.displayName = 'Increment'; +IncrementButton.displayName = "Increment"; diff --git a/packages/paste-core/components/input/src/Input.tsx b/packages/paste-core/components/input/src/Input.tsx index 98bc562d4e..5db19912d3 100644 --- a/packages/paste-core/components/input/src/Input.tsx +++ b/packages/paste-core/components/input/src/Input.tsx @@ -1,18 +1,18 @@ -import * as React from 'react'; -import {useMergeRefs} from '@twilio-paste/utils'; -import {Box} from '@twilio-paste/box'; -import type {BoxProps, BoxStyleProps} from '@twilio-paste/box'; -import {InputBox} from '@twilio-paste/input-box'; -import type {InputBoxTypes} from '@twilio-paste/input-box'; -import type {HTMLPasteProps} from '@twilio-paste/types'; +import { Box } from "@twilio-paste/box"; +import type { BoxProps, BoxStyleProps } from "@twilio-paste/box"; +import { InputBox } from "@twilio-paste/input-box"; +import type { InputBoxTypes } from "@twilio-paste/input-box"; +import type { HTMLPasteProps } from "@twilio-paste/types"; +import { useMergeRefs } from "@twilio-paste/utils"; +import * as React from "react"; -import {safelySpreadFormControlProps} from './utils'; -import {DecrementButton} from './DecrementButton'; -import {IncrementButton} from './IncrementButton'; +import { DecrementButton } from "./DecrementButton"; +import { IncrementButton } from "./IncrementButton"; +import { safelySpreadFormControlProps } from "./utils"; -export type InputVariants = 'default' | 'inverse'; +export type InputVariants = "default" | "inverse"; -export interface InputProps extends HTMLPasteProps<'input'>, Pick { +export interface InputProps extends HTMLPasteProps<"input">, Pick { disabled?: boolean; hasError?: boolean; height?: never; @@ -29,9 +29,9 @@ export interface InputProps extends HTMLPasteProps<'input'>, Pick(({element, ...props}, ref) => { +export const InputElement = React.forwardRef(({ element, ...props }, ref) => { return ( (({ele borderRadius="borderRadius20" boxShadow="none" color="inherit" - cursor={(props.type === 'date' || props.type === 'time') && !props.readOnly && !props.disabled ? 'text' : 'auto'} + cursor={(props.type === "date" || props.type === "time") && !props.readOnly && !props.disabled ? "text" : "auto"} display="block" element={element} fontFamily="inherit" @@ -70,46 +70,46 @@ export const InputElement = React.forwardRef(({ele variant={props.variant} ref={ref} _placeholder={{ - color: props.variant === 'inverse' ? 'colorTextInverseWeaker' : 'colorTextWeak', - fontStyle: 'italic', + color: props.variant === "inverse" ? "colorTextInverseWeaker" : "colorTextWeak", + fontStyle: "italic", }} _focus_placeholder={{ - color: props.variant === 'inverse' ? 'colorTextInverseWeaker' : 'colorTextWeak', + color: props.variant === "inverse" ? "colorTextInverseWeaker" : "colorTextWeak", }} _disabled={{ - color: props.variant === 'inverse' ? 'colorTextInverseWeakest' : 'colorTextWeaker', - cursor: 'not-allowed', - '-webkit-text-fill-color': props.variant === 'inverse' ? 'colorTextInverseWeakest' : 'colorTextWeaker', - '-webkit-opacity': '1', + color: props.variant === "inverse" ? "colorTextInverseWeakest" : "colorTextWeaker", + cursor: "not-allowed", + "-webkit-text-fill-color": props.variant === "inverse" ? "colorTextInverseWeakest" : "colorTextWeaker", + "-webkit-opacity": "1", }} __webkit_datetime_edit={{ - display: 'flex', + display: "flex", }} __webkit_calendar_picker_indicator_hover={{ - cursor: props.readOnly || props.disabled ? 'default' : 'pointer', + cursor: props.readOnly || props.disabled ? "default" : "pointer", }} // Hide native number input stepper buttons __webkit_inner_spin_button={{ - display: 'none', - margin: 'space0', + display: "none", + margin: "space0", }} __webkit_outer_spin_button={{ - display: 'none', - margin: 'space0', + display: "none", + margin: "space0", }} - {...{'-moz-appearance': 'textfield'}} + {...{ "-moz-appearance": "textfield" }} {...props} /> ); }); -InputElement.displayName = 'InputElement'; +InputElement.displayName = "InputElement"; const Input = React.forwardRef( ( { disabled, - element = 'INPUT', + element = "INPUT", hasError, id, insertAfter, @@ -128,9 +128,9 @@ const Input = React.forwardRef( i18nStepDownLabel, ...props }, - ref + ref, ) => { - const typeProps: TypeProps = {type}; + const typeProps: TypeProps = { type }; const internalRef = React.useRef(); const mergedRef = useMergeRefs(internalRef, ref) as React.Ref; @@ -139,10 +139,10 @@ const Input = React.forwardRef( const [showDecrement, setShowDecrement] = React.useState(true); // used for number inputs to be able to track uncontrolled number inputs value being changed by a user and it not being tracked by an applications - const [internalValue, setInternalValue] = React.useState(props.defaultValue ? props.defaultValue : '0'); + const [internalValue, setInternalValue] = React.useState(props.defaultValue ? props.defaultValue : "0"); React.useEffect(() => { - if (type !== 'number') return; + if (type !== "number") return; if (disabled) { setShowDecrement(false); setShowIncrement(false); @@ -159,7 +159,7 @@ const Input = React.forwardRef( if ((numMax - numMin) % numStep !== 0) // eslint-disable-next-line no-console console.error( - '[Paste Input]: when using min/max, and step values with a Number Input, please make sure that the min and max are multiples of the step value.' + "[Paste Input]: when using min/max, and step values with a Number Input, please make sure that the min and max are multiples of the step value.", ); if (numVal < numMax && numVal + numStep <= numMax) { setShowIncrement(true); @@ -203,13 +203,13 @@ const Input = React.forwardRef( value={value} variant={variant} onChange={(event) => { - if (props.onChange != null && typeof props.onChange === 'function') { + if (props.onChange != null && typeof props.onChange === "function") { props.onChange(event); } setInternalValue(event.target.value); }} /> - {type === 'number' ? ( + {type === "number" ? ( ( element={element} onClick={() => { internalRef.current?.stepUp(); - const ev = new Event('change', {bubbles: true}); + const ev = new Event("change", { bubbles: true }); internalRef.current?.dispatchEvent(ev); internalRef.current?.focus(); }} @@ -236,7 +236,7 @@ const Input = React.forwardRef( element={element} onClick={() => { internalRef.current?.stepDown(); - const ev = new Event('change', {bubbles: true}); + const ev = new Event("change", { bubbles: true }); internalRef.current?.dispatchEvent(ev); internalRef.current?.focus(); }} @@ -251,10 +251,10 @@ const Input = React.forwardRef( )} ); - } + }, ); -Input.displayName = 'Input'; +Input.displayName = "Input"; -export {Input}; -export type {InputBoxTypes as InputTypes}; +export { Input }; +export type { InputBoxTypes as InputTypes }; diff --git a/packages/paste-core/components/input/src/index.tsx b/packages/paste-core/components/input/src/index.tsx index ba9fe7ebc6..be66d7661c 100644 --- a/packages/paste-core/components/input/src/index.tsx +++ b/packages/paste-core/components/input/src/index.tsx @@ -1 +1 @@ -export * from './Input'; +export * from "./Input"; diff --git a/packages/paste-core/components/input/src/utils.ts b/packages/paste-core/components/input/src/utils.ts index 631dbf16c0..6e4e5a6591 100644 --- a/packages/paste-core/components/input/src/utils.ts +++ b/packages/paste-core/components/input/src/utils.ts @@ -1,6 +1,6 @@ -export const PROPS_TO_BLOCK: string[] = ['className', 'style', 'size', 'height', 'width']; +export const PROPS_TO_BLOCK: string[] = ["className", "style", "size", "height", "width"]; -type Props = {[key: string]: any}; +type Props = { [key: string]: any }; export const safelySpreadFormControlProps = (props: Props): Props => { // https://www.measurethat.net/Benchmarks/Show/6642/0/for-in-vs-reduce-vs-pick#latest_results_block diff --git a/packages/paste-core/components/input/stories/input.stories.tsx b/packages/paste-core/components/input/stories/input.stories.tsx index 3a33def806..9bff54d6ba 100644 --- a/packages/paste-core/components/input/stories/input.stories.tsx +++ b/packages/paste-core/components/input/stories/input.stories.tsx @@ -1,30 +1,30 @@ -import * as React from 'react'; -import type {StoryFn} from '@storybook/react'; -import {useUID} from '@twilio-paste/uid-library'; -import {action} from '@storybook/addon-actions'; -import {Anchor} from '@twilio-paste/anchor'; -import {Form, FormControl} from '@twilio-paste/form'; -import {useTheme} from '@twilio-paste/theme'; -import {Box} from '@twilio-paste/box'; -import {Text} from '@twilio-paste/text'; -import {InformationIcon} from '@twilio-paste/icons/esm/InformationIcon'; -import {Label} from '@twilio-paste/label'; -import {HelpText} from '@twilio-paste/help-text'; -import {Stack} from '@twilio-paste/stack'; -import {CustomizationProvider} from '@twilio-paste/customization'; - -import {Input} from '../src'; +import { action } from "@storybook/addon-actions"; +import type { StoryFn } from "@storybook/react"; +import { Anchor } from "@twilio-paste/anchor"; +import { Box } from "@twilio-paste/box"; +import { CustomizationProvider } from "@twilio-paste/customization"; +import { Form, FormControl } from "@twilio-paste/form"; +import { HelpText } from "@twilio-paste/help-text"; +import { InformationIcon } from "@twilio-paste/icons/esm/InformationIcon"; +import { Label } from "@twilio-paste/label"; +import { Stack } from "@twilio-paste/stack"; +import { Text } from "@twilio-paste/text"; +import { useTheme } from "@twilio-paste/theme"; +import { useUID } from "@twilio-paste/uid-library"; +import * as React from "react"; + +import { Input } from "../src"; // eslint-disable-next-line import/no-default-export export default { - title: 'Components/Input', + title: "Components/Input", component: Input, }; export const DefaultInput = (): React.ReactNode => { const uid = useUID(); const helpTextUid = useUID(); - const [value, setValue] = React.useState(''); + const [value, setValue] = React.useState(""); return ( @@ -41,10 +41,10 @@ export const DefaultInput = (): React.ReactNode => { value={value} onChange={(event) => { setValue(event.target.value); - action('handleChange'); + action("handleChange"); }} - onFocus={action('handleFocus')} - onBlur={action('handleBlur')} + onFocus={action("handleFocus")} + onBlur={action("handleBlur")} /> The URL to your personal homepage. @@ -52,12 +52,12 @@ export const DefaultInput = (): React.ReactNode => { ); }; -DefaultInput.storyName = 'Input'; +DefaultInput.storyName = "Input"; export const InputInverse = (): React.ReactNode => { const uid = useUID(); const helpTextUid = useUID(); - const [value, setValue] = React.useState('Input'); + const [value, setValue] = React.useState("Input"); return (