@astryxdesign/core 0.6.2 → 0.6.3-canary.0788c49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +81 -0
- package/dist/BottomSheet/BottomSheet.d.ts +1 -1
- package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheet.js +3 -1
- package/dist/BottomSheet/BottomSheetPanel.d.ts +7 -5
- package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheetPanel.js +56 -19
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +13 -28
- package/dist/Chat/ChatComposer.d.ts.map +1 -1
- package/dist/Chat/ChatComposer.js +10 -5
- package/dist/Chat/ChatComposerDrawer.d.ts +19 -5
- package/dist/Chat/ChatComposerDrawer.d.ts.map +1 -1
- package/dist/Chat/ChatComposerDrawer.js +48 -23
- package/dist/Chat/ChatComposerInput.d.ts +11 -3
- package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
- package/dist/Chat/ChatComposerInput.js +63 -16
- package/dist/Chat/ChatDictationButton.d.ts +3 -2
- package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
- package/dist/Chat/ChatDictationButton.js +6 -4
- package/dist/Chat/ChatLayout.d.ts +19 -0
- package/dist/Chat/ChatLayout.d.ts.map +1 -1
- package/dist/Chat/ChatLayout.js +19 -0
- package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
- package/dist/Chat/ChatLayoutScrollButton.js +44 -34
- package/dist/Chat/ChatMessageBubble.d.ts +2 -0
- package/dist/Chat/ChatMessageBubble.d.ts.map +1 -1
- package/dist/Chat/ChatMessageBubble.js +5 -3
- package/dist/Chat/ChatMessageList.d.ts +2 -1
- package/dist/Chat/ChatMessageList.d.ts.map +1 -1
- package/dist/Chat/ChatMessageList.js +4 -3
- package/dist/Chat/ChatMessageMetadata.d.ts +5 -4
- package/dist/Chat/ChatMessageMetadata.d.ts.map +1 -1
- package/dist/Chat/ChatMessageMetadata.js +12 -9
- package/dist/Chat/ChatSendButton.d.ts +2 -1
- package/dist/Chat/ChatSendButton.d.ts.map +1 -1
- package/dist/Chat/ChatSendButton.js +6 -4
- package/dist/Chat/index.d.ts +1 -1
- package/dist/Chat/index.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +12 -2
- package/dist/Citation/Citation.d.ts +1 -1
- package/dist/Citation/Citation.d.ts.map +1 -1
- package/dist/Citation/Citation.js +3 -2
- package/dist/CodeBlock/highlightRanges.d.ts.map +1 -1
- package/dist/CodeBlock/highlightRanges.js +14 -3
- package/dist/Collapsible/Collapsible.d.ts.map +1 -1
- package/dist/Collapsible/Collapsible.js +6 -1
- package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteInput.js +1 -1
- package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
- package/dist/ComplexSelector/ComplexSelector.js +1 -1
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +4 -4
- package/dist/DateInput/NativeDateField.d.ts.map +1 -1
- package/dist/DateInput/NativeDateField.js +16 -16
- package/dist/DateInput/TouchDateField.d.ts.map +1 -1
- package/dist/DateInput/TouchDateField.js +2 -2
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +4 -4
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +8 -8
- package/dist/DateTimeInput/TouchDateTimeField.d.ts.map +1 -1
- package/dist/DateTimeInput/TouchDateTimeField.js +4 -4
- package/dist/DateTimeInput/nativePickerSegmentStyles.d.ts +9 -3
- package/dist/DateTimeInput/nativePickerSegmentStyles.d.ts.map +1 -1
- package/dist/DateTimeInput/nativePickerSegmentStyles.js +3 -3
- package/dist/Dialog/DialogHeader.d.ts +8 -1
- package/dist/Dialog/DialogHeader.d.ts.map +1 -1
- package/dist/Dialog/DialogHeader.js +13 -4
- package/dist/Field/InputClearButton.d.ts +4 -2
- package/dist/Field/InputClearButton.d.ts.map +1 -1
- package/dist/Field/InputClearButton.js +4 -2
- package/dist/Field/PanelSearchInput.d.ts.map +1 -1
- package/dist/Field/PanelSearchInput.js +1 -1
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +7 -7
- package/dist/Icon/Icon.d.ts +6 -31
- package/dist/Icon/Icon.d.ts.map +1 -1
- package/dist/Icon/Icon.js +8 -71
- package/dist/Icon/IconDefaultSizeContext.d.ts +4 -0
- package/dist/Icon/IconDefaultSizeContext.d.ts.map +1 -0
- package/dist/Icon/IconDefaultSizeContext.js +18 -0
- package/dist/Icon/IconSize.stylex.d.ts +65 -0
- package/dist/Icon/IconSize.stylex.d.ts.map +1 -0
- package/dist/Icon/IconSize.stylex.js +75 -0
- package/dist/Item/Item.d.ts +1 -1
- package/dist/Item/Item.d.ts.map +1 -1
- package/dist/Item/Item.js +4 -3
- package/dist/Kbd/Kbd.d.ts +5 -3
- package/dist/Kbd/Kbd.d.ts.map +1 -1
- package/dist/Kbd/Kbd.js +36 -42
- package/dist/Link/Link.d.ts.map +1 -1
- package/dist/Link/Link.js +6 -2
- package/dist/Link/useLinkComponent.d.ts +5 -15
- package/dist/Link/useLinkComponent.d.ts.map +1 -1
- package/dist/Link/useLinkComponent.js +34 -51
- package/dist/List/List.d.ts +19 -1
- package/dist/List/List.d.ts.map +1 -1
- package/dist/List/List.js +9 -2
- package/dist/List/ListContext.d.ts +1 -0
- package/dist/List/ListContext.d.ts.map +1 -1
- package/dist/List/ListContext.js +2 -1
- package/dist/List/ListItem.d.ts +1 -1
- package/dist/List/ListItem.d.ts.map +1 -1
- package/dist/List/ListItem.js +9 -2
- package/dist/Markdown/Markdown.d.ts +8 -2
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.fr23.bench.d.ts +2 -0
- package/dist/Markdown/Markdown.fr23.bench.d.ts.map +1 -0
- package/dist/Markdown/Markdown.fr23.bench.js +150 -0
- package/dist/Markdown/Markdown.fr23.sampling.d.ts +2 -0
- package/dist/Markdown/Markdown.fr23.sampling.d.ts.map +1 -0
- package/dist/Markdown/Markdown.fr23.sampling.js +43 -0
- package/dist/Markdown/Markdown.js +262 -109
- package/dist/Markdown/ast.d.ts +162 -0
- package/dist/Markdown/ast.d.ts.map +1 -0
- package/dist/Markdown/ast.js +74 -0
- package/dist/Markdown/index.d.ts +5 -3
- package/dist/Markdown/index.d.ts.map +1 -1
- package/dist/Markdown/index.js +3 -2
- package/dist/Markdown/parser/index.d.ts +10 -0
- package/dist/Markdown/parser/index.d.ts.map +1 -0
- package/dist/Markdown/parser/index.js +10 -0
- package/dist/Markdown/parser.d.ts +126 -58
- package/dist/Markdown/parser.d.ts.map +1 -1
- package/dist/Markdown/parser.js +726 -177
- package/dist/Markdown/plugins/frontmatter.d.ts +32 -0
- package/dist/Markdown/plugins/frontmatter.d.ts.map +1 -0
- package/dist/Markdown/plugins/frontmatter.js +132 -0
- package/dist/Markdown/plugins/index.d.ts +17 -0
- package/dist/Markdown/plugins/index.d.ts.map +1 -0
- package/dist/Markdown/plugins/index.js +14 -0
- package/dist/Markdown/plugins/protocol.d.ts +191 -0
- package/dist/Markdown/plugins/protocol.d.ts.map +1 -0
- package/dist/Markdown/plugins/protocol.js +957 -0
- package/dist/Markdown/plugins/semanticFence.d.ts +36 -0
- package/dist/Markdown/plugins/semanticFence.d.ts.map +1 -0
- package/dist/Markdown/plugins/semanticFence.js +213 -0
- package/dist/Markdown/plugins/softBreaks.d.ts +3 -0
- package/dist/Markdown/plugins/softBreaks.d.ts.map +1 -0
- package/dist/Markdown/plugins/softBreaks.js +172 -0
- package/dist/Markdown/plugins/sourceDecoration.d.ts +76 -0
- package/dist/Markdown/plugins/sourceDecoration.d.ts.map +1 -0
- package/dist/Markdown/plugins/sourceDecoration.js +393 -0
- package/dist/Markdown/plugins/textTransform.d.ts +30 -0
- package/dist/Markdown/plugins/textTransform.d.ts.map +1 -0
- package/dist/Markdown/plugins/textTransform.js +374 -0
- package/dist/Markdown/remark.d.ts +196 -0
- package/dist/Markdown/remark.d.ts.map +1 -0
- package/dist/Markdown/remark.js +1062 -0
- package/dist/Markdown/url.d.ts +6 -0
- package/dist/Markdown/url.d.ts.map +1 -0
- package/dist/Markdown/url.js +31 -0
- package/dist/Markdown/utils.d.ts +4 -2
- package/dist/Markdown/utils.d.ts.map +1 -1
- package/dist/Markdown/utils.js +2 -1
- package/dist/MetadataList/MetadataList.js +3 -3
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +4 -4
- package/dist/Outline/index.d.ts +1 -0
- package/dist/Outline/index.d.ts.map +1 -1
- package/dist/Outline/parseOutlineFromMarkdown.d.ts +7 -1
- package/dist/Outline/parseOutlineFromMarkdown.d.ts.map +1 -1
- package/dist/Outline/parseOutlineFromMarkdown.js +14 -8
- package/dist/Outline/useOutlineFromMarkdown.d.ts +3 -1
- package/dist/Outline/useOutlineFromMarkdown.d.ts.map +1 -1
- package/dist/Outline/useOutlineFromMarkdown.js +8 -3
- package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchEditPopover.js +46 -30
- package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchValueEditor.js +5 -0
- package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
- package/dist/ProgressBar/ProgressBar.js +36 -31
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +13 -1
- package/dist/ScrollableArea/ScrollableArea.d.ts +1 -0
- package/dist/ScrollableArea/ScrollableArea.d.ts.map +1 -1
- package/dist/ScrollableArea/ScrollableArea.js +1 -0
- package/dist/SegmentedControl/SegmentedControl.d.ts +1 -1
- package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControl.js +1 -0
- package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.js +5 -5
- package/dist/Selector/Selector.d.ts +9 -7
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +16 -7
- package/dist/SideNav/SideNav.d.ts +2 -1
- package/dist/SideNav/SideNav.d.ts.map +1 -1
- package/dist/SideNav/SideNav.js +9 -3
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +28 -12
- package/dist/Spinner/Spinner.d.ts.map +1 -1
- package/dist/Spinner/Spinner.js +23 -7
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +11 -0
- package/dist/TabList/Tab.d.ts +1 -1
- package/dist/TabList/Tab.d.ts.map +1 -1
- package/dist/TabList/Tab.js +20 -7
- package/dist/Table/Table.d.ts +1 -0
- package/dist/Table/Table.d.ts.map +1 -1
- package/dist/Table/Table.js +29 -13
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +1 -1
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +2 -2
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +4 -4
- package/dist/Timer/Timer.d.ts +49 -0
- package/dist/Timer/Timer.d.ts.map +1 -0
- package/dist/Timer/Timer.js +158 -0
- package/dist/Timer/index.d.ts +9 -0
- package/dist/Timer/index.d.ts.map +1 -0
- package/dist/Timer/index.js +10 -0
- package/dist/ToggleButton/ToggleButton.d.ts +9 -6
- package/dist/ToggleButton/ToggleButton.d.ts.map +1 -1
- package/dist/ToggleButton/ToggleButton.js +15 -27
- package/dist/TopNav/TopNavMenu.d.ts +1 -1
- package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMenu.js +3 -2
- package/dist/TreeList/TreeList.d.ts.map +1 -1
- package/dist/TreeList/TreeList.js +3 -0
- package/dist/TreeList/TreeListItem.d.ts +6 -1
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +12 -2
- package/dist/TreeList/TreeListTypes.d.ts +8 -1
- package/dist/TreeList/TreeListTypes.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +16 -7
- package/dist/astryx.css +27 -11
- package/dist/hooks/scrollKeyboardDelegation.d.ts +3 -0
- package/dist/hooks/scrollKeyboardDelegation.d.ts.map +1 -0
- package/dist/hooks/scrollKeyboardDelegation.js +146 -0
- package/dist/hooks/useClickableContainer.d.ts +10 -1
- package/dist/hooks/useClickableContainer.d.ts.map +1 -1
- package/dist/hooks/useClickableContainer.js +15 -4
- package/dist/hooks/useScrollableArea.d.ts +6 -2
- package/dist/hooks/useScrollableArea.d.ts.map +1 -1
- package/dist/hooks/useScrollableArea.js +17 -5
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/theme/declarationBoundary.d.ts +17 -0
- package/dist/theme/declarationBoundary.d.ts.map +1 -0
- package/dist/theme/declarationBoundary.js +343 -0
- package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
- package/dist/theme/derivedVarRegistry.js +4 -0
- package/dist/theme/generateThemeRules.d.ts +13 -7
- package/dist/theme/generateThemeRules.d.ts.map +1 -1
- package/dist/theme/generateThemeRules.js +140 -34
- package/dist/utils/interactionOverlay.stylex.d.ts +8 -0
- package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -1
- package/dist/utils/interactionOverlay.stylex.js +9 -0
- package/dist/utils/safeUrl.d.ts +11 -0
- package/dist/utils/safeUrl.d.ts.map +1 -0
- package/dist/utils/safeUrl.js +78 -0
- package/locales/af-ZA.json +530 -1
- package/locales/ar-SA.json +490 -1
- package/locales/ca-ES.json +514 -1
- package/locales/cs-CZ.json +498 -1
- package/locales/da-DK.json +522 -1
- package/locales/de-DE.json +522 -1
- package/locales/el-GR.json +498 -1
- package/locales/es-ES.json +510 -1
- package/locales/fi-FI.json +498 -1
- package/locales/fr-FR.json +534 -1
- package/locales/he-IL.json +498 -1
- package/locales/hu-HU.json +498 -1
- package/locales/it-IT.json +510 -1
- package/locales/ja-JP.json +490 -1
- package/locales/ko-KR.json +498 -1
- package/locales/nl-NL.json +534 -1
- package/locales/no-NO.json +510 -1
- package/locales/pl-PL.json +506 -1
- package/locales/pt-BR.json +506 -1
- package/locales/pt-PT.json +506 -1
- package/locales/ro-RO.json +506 -1
- package/locales/ru-RU.json +498 -1
- package/locales/sr-SP.json +498 -1
- package/locales/sv-SE.json +502 -1
- package/locales/tr-TR.json +498 -1
- package/locales/uk-UA.json +498 -1
- package/locales/vi-VN.json +502 -1
- package/locales/zh-CN.json +490 -1
- package/locales/zh-TW.json +490 -1
- package/package.json +24 -4
- package/src/BottomSheet/BottomSheet.doc.mjs +8 -1
- package/src/BottomSheet/BottomSheet.spec.md +46 -20
- package/src/BottomSheet/BottomSheet.test.tsx +6 -3
- package/src/BottomSheet/BottomSheet.tsx +3 -1
- package/src/BottomSheet/BottomSheetKeyboard.test.tsx +195 -0
- package/src/BottomSheet/BottomSheetPanel.test.tsx +11 -1
- package/src/BottomSheet/BottomSheetPanel.tsx +49 -16
- package/src/BottomSheet/__tests__/BottomSheetKeyboard.a11y.browser.spec.ts +344 -0
- package/src/Button/Button.doc.mjs +5 -5
- package/src/Button/Button.tsx +15 -13
- package/src/Button/__tests__/Button.a11y.chromium.spec.ts +17 -1
- package/src/Button/__tests__/Button.a11y.known-failures.ts +0 -29
- package/src/Button/__tests__/Button.a11y.renders.tsx +9 -2
- package/src/Button/__tests__/Button.a11y.states.ts +9 -0
- package/src/Chat/ChatComposer.doc.mjs +14 -0
- package/src/Chat/ChatComposer.spec.md +230 -0
- package/src/Chat/ChatComposer.test.tsx +57 -0
- package/src/Chat/ChatComposer.tsx +21 -9
- package/src/Chat/ChatComposerDrawer.doc.mjs +63 -5
- package/src/Chat/ChatComposerDrawer.spec.md +267 -0
- package/src/Chat/ChatComposerDrawer.test.tsx +81 -12
- package/src/Chat/ChatComposerDrawer.tsx +38 -9
- package/src/Chat/ChatComposerInput.doc.mjs +114 -26
- package/src/Chat/ChatComposerInput.spec.md +185 -0
- package/src/Chat/ChatComposerInput.test.tsx +113 -3
- package/src/Chat/ChatComposerInput.tsx +78 -13
- package/src/Chat/ChatComposerTokenElement.spec.md +152 -0
- package/src/Chat/ChatComposerTokenElement.test.tsx +85 -0
- package/src/Chat/ChatDictationButton.doc.mjs +3 -3
- package/src/Chat/ChatDictationButton.spec.md +160 -0
- package/src/Chat/ChatDictationButton.test.tsx +92 -27
- package/src/Chat/ChatDictationButton.tsx +8 -6
- package/src/Chat/ChatLayout.doc.mjs +12 -4
- package/src/Chat/ChatLayout.spec.md +271 -0
- package/src/Chat/ChatLayout.test.tsx +28 -0
- package/src/Chat/ChatLayout.tsx +19 -0
- package/src/Chat/ChatLayoutScrollButton.spec.md +338 -0
- package/src/Chat/ChatLayoutScrollButton.test.tsx +31 -0
- package/src/Chat/ChatLayoutScrollButton.tsx +31 -14
- package/src/Chat/ChatMessageBubble.doc.mjs +28 -15
- package/src/Chat/ChatMessageBubble.spec.md +263 -0
- package/src/Chat/ChatMessageBubble.test.tsx +93 -0
- package/src/Chat/ChatMessageBubble.tsx +8 -3
- package/src/Chat/ChatMessageList.spec.md +222 -0
- package/src/Chat/ChatMessageList.test.tsx +64 -2
- package/src/Chat/ChatMessageList.tsx +4 -3
- package/src/Chat/ChatMessageMetadata.doc.mjs +57 -3
- package/src/Chat/ChatMessageMetadata.spec.md +220 -0
- package/src/Chat/ChatMessageMetadata.test.tsx +34 -0
- package/src/Chat/ChatMessageMetadata.tsx +13 -13
- package/src/Chat/ChatSendButton.doc.mjs +32 -0
- package/src/Chat/ChatSendButton.spec.md +227 -0
- package/src/Chat/ChatSendButton.test.tsx +128 -8
- package/src/Chat/ChatSendButton.tsx +6 -4
- package/src/Chat/__tests__/ChatLayoutScrollButton.a11y.chromium.spec.ts +514 -0
- package/src/Chat/__tests__/ChatLayoutScrollButtonSurface.a11y.chromium.spec.ts +740 -0
- package/src/Chat/__tests__/ChatMessageBubble.a11y.chromium.spec.ts +457 -0
- package/src/Chat/__tests__/ChatMessageBubble.auditProvenance.test.ts +91 -0
- package/src/Chat/__tests__/ChatMessageBubble.auditProvenance.ts +91 -0
- package/src/Chat/__tests__/ChatMessageList.a11y.chromium.spec.ts +456 -0
- package/src/Chat/__tests__/ChatMessageMetadata.a11y.chromium.spec.ts +413 -0
- package/src/Chat/__tests__/ChatSendButton.a11y.chromium.spec.ts +1522 -0
- package/src/Chat/index.ts +1 -0
- package/src/CheckboxInput/CheckboxInput.doc.mjs +11 -0
- package/src/CheckboxInput/CheckboxInput.test.tsx +34 -0
- package/src/CheckboxInput/CheckboxInput.tsx +21 -1
- package/src/Citation/Citation.doc.mjs +2 -2
- package/src/Citation/Citation.test.tsx +17 -0
- package/src/Citation/Citation.tsx +4 -2
- package/src/ClickableCard/ClickableCard.doc.mjs +2 -2
- package/src/ClickableCard/ClickableCard.test.tsx +102 -5
- package/src/CodeBlock/highlightRanges.test.ts +143 -1
- package/src/CodeBlock/highlightRanges.ts +15 -5
- package/src/Collapsible/Collapsible.doc.mjs +11 -0
- package/src/Collapsible/Collapsible.test.tsx +21 -0
- package/src/Collapsible/Collapsible.tsx +5 -0
- package/src/CommandPalette/CommandPaletteInput.tsx +6 -1
- package/src/ComplexSelector/ComplexSelector.tsx +6 -1
- package/src/DateInput/DateInput.tsx +6 -1
- package/src/DateInput/NativeDateField.tsx +24 -8
- package/src/DateInput/TouchDateField.tsx +6 -2
- package/src/DateRangeInput/DateRangeInput.tsx +6 -1
- package/src/DateTimeInput/DateTimeInput.tsx +6 -1
- package/src/DateTimeInput/TouchDateTimeField.tsx +6 -1
- package/src/DateTimeInput/nativePickerSegmentStyles.ts +24 -8
- package/src/Dialog/Dialog.doc.mjs +2 -0
- package/src/Dialog/DialogHeader.doc.mjs +22 -0
- package/src/Dialog/DialogHeader.test.tsx +167 -3
- package/src/Dialog/DialogHeader.tsx +37 -6
- package/src/Dialog/modules/DialogHeader.spec.md +101 -42
- package/src/DropdownMenu/DropdownMenu.test.tsx +5 -2
- package/src/Field/InputClearButton.test.tsx +17 -3
- package/src/Field/InputClearButton.tsx +5 -2
- package/src/Field/PanelSearchInput.tsx +5 -2
- package/src/FieldStatus/__tests__/StatusMessage.a11y.states.ts +1 -1
- package/src/FileInput/FileInput.tsx +11 -2
- package/src/Icon/Icon.doc.mjs +7 -5
- package/src/Icon/Icon.spec.md +81 -40
- package/src/Icon/Icon.test.tsx +6 -3
- package/src/Icon/Icon.tsx +20 -68
- package/src/Icon/IconDefaultSizeContext.ts +23 -0
- package/src/Icon/IconSize.stylex.ts +70 -0
- package/src/IconButton/IconButton.doc.mjs +3 -3
- package/src/IconButton/IconButton.test.tsx +40 -0
- package/src/Item/Item.doc.mjs +6 -2
- package/src/Item/Item.tsx +9 -3
- package/src/Kbd/Kbd.doc.mjs +3 -3
- package/src/Kbd/Kbd.test.tsx +57 -1
- package/src/Kbd/Kbd.tsx +57 -37
- package/src/Layout/LayoutFooter.doc.mjs +17 -0
- package/src/Link/Link.doc.mjs +17 -4
- package/src/Link/Link.test.tsx +24 -0
- package/src/Link/Link.tsx +5 -0
- package/src/Link/LinkProvider.doc.mjs +2 -2
- package/src/Link/__tests__/Link.navigation.a11y.chromium.spec.ts +261 -0
- package/src/Link/useLinkComponent.test.tsx +333 -0
- package/src/Link/useLinkComponent.ts +29 -57
- package/src/List/List.doc.mjs +6 -0
- package/src/List/List.spec.md +200 -0
- package/src/List/List.test.tsx +117 -1
- package/src/List/List.tsx +22 -2
- package/src/List/ListContext.tsx +3 -1
- package/src/List/ListItem.doc.mjs +2 -2
- package/src/List/ListItem.source-build.test.mjs +41 -0
- package/src/List/ListItem.tsx +26 -2
- package/src/Markdown/Markdown.doc.mjs +300 -2
- package/src/Markdown/Markdown.fr23.bench.ts +174 -0
- package/src/Markdown/Markdown.fr23.perf.test.ts +249 -0
- package/src/Markdown/Markdown.fr23.sampling.ts +49 -0
- package/src/Markdown/Markdown.helpers.perf.test.ts +489 -0
- package/src/Markdown/Markdown.public.test.ts +130 -3
- package/src/Markdown/Markdown.renderBoundary.test.tsx +72 -0
- package/src/Markdown/Markdown.spec.md +210 -45
- package/src/Markdown/Markdown.test.tsx +87 -3
- package/src/Markdown/Markdown.tsx +414 -135
- package/src/Markdown/ast.test.ts +307 -0
- package/src/Markdown/ast.ts +337 -0
- package/src/Markdown/incremental.test.ts +43 -0
- package/src/Markdown/index.ts +37 -1
- package/src/Markdown/modules/remark.spec.md +269 -0
- package/src/Markdown/modules/softBreaks.spec.md +137 -0
- package/src/Markdown/parser/index.ts +64 -0
- package/src/Markdown/parser.public.test.ts +103 -0
- package/src/Markdown/parser.test.ts +38 -6
- package/src/Markdown/parser.ts +1221 -242
- package/src/Markdown/plugins/frontmatter.test.tsx +125 -0
- package/src/Markdown/plugins/frontmatter.ts +198 -0
- package/src/Markdown/plugins/index.ts +54 -0
- package/src/Markdown/plugins/protocol.test.tsx +1022 -0
- package/src/Markdown/plugins/protocol.ts +1618 -0
- package/src/Markdown/plugins/semanticFence.test.tsx +546 -0
- package/src/Markdown/plugins/semanticFence.ts +424 -0
- package/src/Markdown/plugins/softBreaks.test.tsx +172 -0
- package/src/Markdown/plugins/softBreaks.ts +169 -0
- package/src/Markdown/plugins/sourceDecoration.test.tsx +799 -0
- package/src/Markdown/plugins/sourceDecoration.ts +539 -0
- package/src/Markdown/plugins/textTransform.test.ts +467 -0
- package/src/Markdown/plugins/textTransform.ts +554 -0
- package/src/Markdown/remark.test.tsx +1877 -0
- package/src/Markdown/remark.ts +1574 -0
- package/src/Markdown/url.ts +36 -0
- package/src/Markdown/utils.ts +13 -1
- package/src/MetadataList/MetadataList.test.tsx +4 -2
- package/src/MetadataList/MetadataList.tsx +3 -3
- package/src/MultiSelector/MultiSelector.test.tsx +1 -35
- package/src/MultiSelector/__tests__/MultiSelector.listbox.a11y.test.tsx +128 -0
- package/src/NumberInput/NumberInput.tsx +6 -1
- package/src/Outline/Outline.doc.mjs +7 -5
- package/src/Outline/Outline.spec.md +1 -1
- package/src/Outline/index.ts +1 -0
- package/src/Outline/modules/parseOutlineFromMarkdown.spec.md +142 -0
- package/src/Outline/parseOutlineFromMarkdown.ts +40 -10
- package/src/Outline/useOutlineFromMarkdown.ts +15 -3
- package/src/PowerSearch/PowerSearch.doc.mjs +2 -2
- package/src/PowerSearch/PowerSearchEditPopover.test.tsx +150 -1
- package/src/PowerSearch/PowerSearchEditPopover.tsx +51 -28
- package/src/PowerSearch/PowerSearchValueEditor.test.tsx +51 -0
- package/src/PowerSearch/PowerSearchValueEditor.tsx +4 -0
- package/src/ProgressBar/ProgressBar.test.tsx +29 -11
- package/src/ProgressBar/ProgressBar.tsx +59 -72
- package/src/RadioList/RadioList.doc.mjs +11 -0
- package/src/RadioList/RadioList.test.tsx +32 -0
- package/src/RadioList/RadioListItem.tsx +25 -1
- package/src/ScrollableArea/ScrollableArea.tsx +1 -0
- package/src/ScrollableArea/modules/useScrollableArea.spec.md +50 -22
- package/src/SegmentedControl/SegmentedControl.doc.mjs +2 -2
- package/src/SegmentedControl/SegmentedControl.test.tsx +61 -0
- package/src/SegmentedControl/SegmentedControl.tsx +2 -1
- package/src/SegmentedControl/SegmentedControlItem.tsx +6 -9
- package/src/Selector/Selector.doc.mjs +3 -3
- package/src/Selector/Selector.spec.md +51 -49
- package/src/Selector/Selector.test.tsx +61 -55
- package/src/Selector/Selector.tsx +34 -15
- package/src/Selector/__tests__/Listbox.a11y.chromium.spec.ts +130 -0
- package/src/Selector/__tests__/Listbox.a11y.dom.ts +38 -0
- package/src/Selector/__tests__/Listbox.a11y.inventory.test.ts +63 -0
- package/src/Selector/__tests__/Listbox.a11y.known-failures.ts +37 -0
- package/src/Selector/__tests__/Listbox.a11y.states.ts +232 -0
- package/src/Selector/__tests__/Selector.a11y.chromium.spec.ts +45 -0
- package/src/Selector/__tests__/Selector.listbox.a11y.test.tsx +121 -0
- package/src/SideNav/SideNav.doc.mjs +1 -1
- package/src/SideNav/SideNav.test.tsx +10 -0
- package/src/SideNav/SideNav.tsx +14 -2
- package/src/Slider/Slider.doc.mjs +17 -3
- package/src/Slider/Slider.test.tsx +221 -0
- package/src/Slider/Slider.tsx +40 -9
- package/src/Spinner/Spinner.test.tsx +4 -0
- package/src/Spinner/Spinner.tsx +31 -18
- package/src/Switch/Switch.doc.mjs +11 -0
- package/src/Switch/Switch.test.tsx +16 -0
- package/src/Switch/Switch.tsx +28 -0
- package/src/TabList/Tab.tsx +35 -7
- package/src/TabList/TabList.doc.mjs +11 -0
- package/src/TabList/TabList.spec.md +204 -0
- package/src/TabList/TabList.test.tsx +66 -0
- package/src/TabList/__tests__/Tabs.a11y.known-failures.ts +1 -34
- package/src/Table/Table.doc.mjs +1 -1
- package/src/Table/Table.spec.md +54 -40
- package/src/Table/Table.test.tsx +83 -10
- package/src/Table/Table.tsx +30 -22
- package/src/Table/__tests__/TableScroll.a11y.chromium.spec.ts +137 -0
- package/src/TextArea/TextArea.tsx +6 -1
- package/src/TextInput/TextInput.test.tsx +20 -1
- package/src/TextInput/TextInput.tsx +6 -1
- package/src/TimeInput/TimeInput.tsx +6 -1
- package/src/Timer/Timer.doc.mjs +183 -0
- package/src/Timer/Timer.spec.md +215 -0
- package/src/Timer/Timer.test.tsx +302 -0
- package/src/Timer/Timer.tsx +258 -0
- package/src/Timer/index.ts +11 -0
- package/src/ToggleButton/ToggleButton.doc.mjs +3 -3
- package/src/ToggleButton/ToggleButton.test.tsx +299 -4
- package/src/ToggleButton/ToggleButton.tsx +26 -33
- package/src/ToggleButton/ToggleButtonGroup.doc.mjs +3 -3
- package/src/ToggleButton/__tests__/ToggleButton.a11y.chromium.spec.ts +209 -0
- package/src/Token/Token.doc.mjs +2 -2
- package/src/Tokenizer/Tokenizer.spec.md +142 -75
- package/src/TopNav/TopNavMenu.doc.mjs +2 -2
- package/src/TopNav/TopNavMenu.test.tsx +30 -0
- package/src/TopNav/TopNavMenu.tsx +7 -2
- package/src/TreeList/TreeList.doc.mjs +3 -3
- package/src/TreeList/TreeList.spec.md +123 -75
- package/src/TreeList/TreeList.test.tsx +29 -0
- package/src/TreeList/TreeList.tsx +3 -0
- package/src/TreeList/TreeListItem.tsx +15 -1
- package/src/TreeList/TreeListTypes.ts +11 -1
- package/src/Typeahead/BaseTypeahead.spec.md +4 -3
- package/src/Typeahead/BaseTypeahead.tsx +21 -7
- package/src/Typeahead/Typeahead.test.tsx +53 -0
- package/src/__tests__/PressedState.a11y.chromium.spec.ts +813 -0
- package/src/__tests__/pressState.ts +93 -0
- package/src/hooks/scrollKeyboardDelegation.test.ts +155 -0
- package/src/hooks/scrollKeyboardDelegation.ts +233 -0
- package/src/hooks/useClickableContainer.test.tsx +236 -0
- package/src/hooks/useClickableContainer.ts +20 -4
- package/src/hooks/useScrollableArea.doc.mjs +15 -3
- package/src/hooks/useScrollableArea.test.tsx +59 -1
- package/src/hooks/useScrollableArea.ts +34 -10
- package/src/index.ts +3 -0
- package/src/inputFontFloor.test.ts +106 -0
- package/src/tailwind-theme.css +0 -6
- package/src/theme/Theme.test.tsx +32 -0
- package/src/theme/declarationBoundary.test.ts +126 -0
- package/src/theme/declarationBoundary.ts +347 -0
- package/src/theme/derivedVarRegistry.test.ts +7 -0
- package/src/theme/derivedVarRegistry.ts +1 -0
- package/src/theme/generateThemeRules.test.ts +526 -1
- package/src/theme/generateThemeRules.ts +228 -50
- package/src/theme/tokenValueCompat.test.ts +4 -1
- package/src/utils/interactionOverlay.stylex.ts +20 -0
- package/src/utils/safeUrl.test.ts +88 -0
- package/src/utils/safeUrl.ts +85 -0
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
'use client';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @file Timer.tsx
|
|
7
|
+
* @input Uses an optional start time, standardized format, Timestamp typography, BaseProps, and React ref
|
|
8
|
+
* @output Exports Timer, TimerProps, and TimerFormat with non-rendering elapsed-time updates
|
|
9
|
+
* @position Core content primitive for elapsed duration in active operations
|
|
10
|
+
*
|
|
11
|
+
* SYNC: When modified, update these files to stay in sync:
|
|
12
|
+
* - /packages/core/src/Timer/Timer.spec.md
|
|
13
|
+
* - /packages/core/src/Timer/Timer.doc.mjs
|
|
14
|
+
* - /packages/core/src/Timer/Timer.test.tsx
|
|
15
|
+
* - /packages/core/src/Timer/index.ts
|
|
16
|
+
* - /apps/storybook/stories/Timer.stories.tsx
|
|
17
|
+
* - /packages/cli/assets/templates/blocks/components/Timer/
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import {useEffect, useRef, useState} from 'react';
|
|
21
|
+
import * as stylex from '@stylexjs/stylex';
|
|
22
|
+
import type {BaseProps} from '../BaseProps';
|
|
23
|
+
import {useMergedRefs} from '../hooks/useMergedRefs';
|
|
24
|
+
import {Text} from '../Text';
|
|
25
|
+
import type {TextColor, TextSize, TextType, TextWeight} from '../theme/types';
|
|
26
|
+
import {mergeProps} from '../utils';
|
|
27
|
+
import {themeProps} from '../utils/themeProps';
|
|
28
|
+
|
|
29
|
+
const ONE_SECOND_MS = 1000;
|
|
30
|
+
const ONE_MINUTE_MS = 60 * ONE_SECOND_MS;
|
|
31
|
+
const ONE_HOUR_SECONDS = 60 * 60;
|
|
32
|
+
const MAX_TIMEOUT_MS = 2_147_483_647;
|
|
33
|
+
|
|
34
|
+
const styles = stylex.create({
|
|
35
|
+
time: {
|
|
36
|
+
color: 'inherit',
|
|
37
|
+
display: 'inline',
|
|
38
|
+
fontFamily: 'inherit',
|
|
39
|
+
fontSize: 'inherit',
|
|
40
|
+
fontStyle: 'normal',
|
|
41
|
+
fontVariantNumeric: 'tabular-nums',
|
|
42
|
+
fontWeight: 'inherit',
|
|
43
|
+
lineHeight: 'inherit',
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
export type TimerFormat = 'elapsed' | 'clock';
|
|
48
|
+
|
|
49
|
+
type TimerPresentation = {
|
|
50
|
+
dateTime: string;
|
|
51
|
+
text: string;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
function pad(value: number): string {
|
|
55
|
+
return String(value).padStart(2, '0');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function resolveFormat(format: TimerFormat): TimerFormat {
|
|
59
|
+
return format === 'clock' ? 'clock' : 'elapsed';
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function getElapsedMilliseconds(now: number, startTime: number): number {
|
|
63
|
+
return Math.max(0, now - startTime);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function getPresentation(
|
|
67
|
+
elapsedMilliseconds: number,
|
|
68
|
+
format: TimerFormat,
|
|
69
|
+
): TimerPresentation {
|
|
70
|
+
const elapsedSeconds = Math.floor(elapsedMilliseconds / ONE_SECOND_MS);
|
|
71
|
+
|
|
72
|
+
if (format === 'clock') {
|
|
73
|
+
const hours = Math.floor(elapsedSeconds / ONE_HOUR_SECONDS);
|
|
74
|
+
const minutes = Math.floor((elapsedSeconds % ONE_HOUR_SECONDS) / 60);
|
|
75
|
+
const seconds = elapsedSeconds % 60;
|
|
76
|
+
return {
|
|
77
|
+
dateTime: `PT${elapsedSeconds}S`,
|
|
78
|
+
text:
|
|
79
|
+
hours > 0
|
|
80
|
+
? `${String(hours)}:${pad(minutes)}:${pad(seconds)}`
|
|
81
|
+
: `${String(minutes)}:${pad(seconds)}`,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (elapsedSeconds < 60) {
|
|
86
|
+
return {
|
|
87
|
+
dateTime: `PT${elapsedSeconds}S`,
|
|
88
|
+
text: `${String(elapsedSeconds)}s`,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const totalMinutes = Math.floor(elapsedSeconds / 60);
|
|
93
|
+
if (totalMinutes < 60) {
|
|
94
|
+
return {
|
|
95
|
+
dateTime: `PT${elapsedSeconds}S`,
|
|
96
|
+
text: `${String(totalMinutes)}m ${pad(elapsedSeconds % 60)}s`,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const representedSeconds = totalMinutes * 60;
|
|
101
|
+
return {
|
|
102
|
+
dateTime: `PT${representedSeconds}S`,
|
|
103
|
+
text: `${String(Math.floor(totalMinutes / 60))}h ${pad(totalMinutes % 60)}m`,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function getMillisecondsUntilNextChange(
|
|
108
|
+
now: number,
|
|
109
|
+
startTime: number,
|
|
110
|
+
elapsedMilliseconds: number,
|
|
111
|
+
format: TimerFormat,
|
|
112
|
+
): number {
|
|
113
|
+
if (now < startTime) {
|
|
114
|
+
return Math.min(startTime - now + ONE_SECOND_MS, MAX_TIMEOUT_MS);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const precision =
|
|
118
|
+
format === 'elapsed' &&
|
|
119
|
+
elapsedMilliseconds >= ONE_HOUR_SECONDS * ONE_SECOND_MS
|
|
120
|
+
? ONE_MINUTE_MS
|
|
121
|
+
: ONE_SECOND_MS;
|
|
122
|
+
return precision - (elapsedMilliseconds % precision);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export interface TimerProps extends Omit<
|
|
126
|
+
BaseProps<HTMLTimeElement>,
|
|
127
|
+
'dateTime'
|
|
128
|
+
> {
|
|
129
|
+
/** Ref forwarded to the rendered `<time>` element. */
|
|
130
|
+
ref?: React.Ref<HTMLTimeElement>;
|
|
131
|
+
/**
|
|
132
|
+
* Unix time in milliseconds when the measured operation began. Omit it to
|
|
133
|
+
* start counting from this Timer's mount.
|
|
134
|
+
*/
|
|
135
|
+
startTime?: number;
|
|
136
|
+
/**
|
|
137
|
+
* Standard duration representation.
|
|
138
|
+
* @default 'elapsed'
|
|
139
|
+
*/
|
|
140
|
+
format?: TimerFormat;
|
|
141
|
+
/**
|
|
142
|
+
* Semantic text type. Matches Timestamp typography behavior.
|
|
143
|
+
* @default 'supporting'
|
|
144
|
+
*/
|
|
145
|
+
type?: TextType;
|
|
146
|
+
/** Explicit font size override. Overrides the size from `type`. */
|
|
147
|
+
size?: TextSize;
|
|
148
|
+
/**
|
|
149
|
+
* Text color.
|
|
150
|
+
* @default 'secondary'
|
|
151
|
+
*/
|
|
152
|
+
color?: TextColor;
|
|
153
|
+
/** Font weight override. */
|
|
154
|
+
weight?: TextWeight;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Displays a standardized elapsed duration without scheduling React tick renders.
|
|
159
|
+
*
|
|
160
|
+
* Timer writes changing text and its ISO 8601 duration directly to the owned
|
|
161
|
+
* `<time>` node. Use `elapsed` for compact duration text or `clock` for a
|
|
162
|
+
* stopwatch-like reading.
|
|
163
|
+
*
|
|
164
|
+
* @example
|
|
165
|
+
* ```
|
|
166
|
+
* <Timer />
|
|
167
|
+
* <Timer format="clock" />
|
|
168
|
+
* ```
|
|
169
|
+
*/
|
|
170
|
+
export function Timer({
|
|
171
|
+
startTime,
|
|
172
|
+
format = 'elapsed',
|
|
173
|
+
type = 'supporting',
|
|
174
|
+
size,
|
|
175
|
+
color = 'secondary',
|
|
176
|
+
weight,
|
|
177
|
+
ref,
|
|
178
|
+
xstyle,
|
|
179
|
+
className,
|
|
180
|
+
style,
|
|
181
|
+
...rest
|
|
182
|
+
}: TimerProps) {
|
|
183
|
+
const [mountTime] = useState(() => Date.now());
|
|
184
|
+
const timerRef = useRef<HTMLTimeElement>(null);
|
|
185
|
+
const mergedRef = useMergedRefs(ref, timerRef);
|
|
186
|
+
const resolvedFormat = resolveFormat(format);
|
|
187
|
+
const initialPresentation = getPresentation(0, resolvedFormat);
|
|
188
|
+
|
|
189
|
+
useEffect(() => {
|
|
190
|
+
const resolvedStartTime =
|
|
191
|
+
startTime !== undefined && Number.isFinite(startTime)
|
|
192
|
+
? startTime
|
|
193
|
+
: mountTime;
|
|
194
|
+
let timeoutID: ReturnType<typeof setTimeout> | undefined;
|
|
195
|
+
let previousDateTime: string | undefined;
|
|
196
|
+
let previousText: string | undefined;
|
|
197
|
+
|
|
198
|
+
const tick = () => {
|
|
199
|
+
const now = Date.now();
|
|
200
|
+
const elapsedMilliseconds = getElapsedMilliseconds(
|
|
201
|
+
now,
|
|
202
|
+
resolvedStartTime,
|
|
203
|
+
);
|
|
204
|
+
const presentation = getPresentation(elapsedMilliseconds, resolvedFormat);
|
|
205
|
+
const node = timerRef.current;
|
|
206
|
+
|
|
207
|
+
if (node != null) {
|
|
208
|
+
if (presentation.text !== previousText) {
|
|
209
|
+
node.textContent = presentation.text;
|
|
210
|
+
previousText = presentation.text;
|
|
211
|
+
}
|
|
212
|
+
if (presentation.dateTime !== previousDateTime) {
|
|
213
|
+
node.dateTime = presentation.dateTime;
|
|
214
|
+
previousDateTime = presentation.dateTime;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
timeoutID = setTimeout(
|
|
219
|
+
tick,
|
|
220
|
+
getMillisecondsUntilNextChange(
|
|
221
|
+
now,
|
|
222
|
+
resolvedStartTime,
|
|
223
|
+
elapsedMilliseconds,
|
|
224
|
+
resolvedFormat,
|
|
225
|
+
),
|
|
226
|
+
);
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
tick();
|
|
230
|
+
return () => {
|
|
231
|
+
if (timeoutID !== undefined) {
|
|
232
|
+
clearTimeout(timeoutID);
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
}, [mountTime, resolvedFormat, startTime]);
|
|
236
|
+
|
|
237
|
+
const timerProps = mergeProps(themeProps('timer'), {className, style});
|
|
238
|
+
|
|
239
|
+
return (
|
|
240
|
+
<Text
|
|
241
|
+
type={type}
|
|
242
|
+
size={size}
|
|
243
|
+
color={color}
|
|
244
|
+
weight={weight}
|
|
245
|
+
xstyle={xstyle}
|
|
246
|
+
{...timerProps}>
|
|
247
|
+
<time
|
|
248
|
+
{...rest}
|
|
249
|
+
ref={mergedRef}
|
|
250
|
+
dateTime="PT0S"
|
|
251
|
+
{...stylex.props(styles.time)}>
|
|
252
|
+
{initialPresentation.text}
|
|
253
|
+
</time>
|
|
254
|
+
</Text>
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
Timer.displayName = 'Timer';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file index.ts
|
|
5
|
+
* @input Imports Timer, TimerProps, and TimerFormat
|
|
6
|
+
* @output Public Timer component barrel
|
|
7
|
+
* @position Component subpath entry point for @astryxdesign/core/Timer
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export {Timer} from './Timer';
|
|
11
|
+
export type {TimerFormat, TimerProps} from './Timer';
|
|
@@ -31,17 +31,17 @@ export const docs = {
|
|
|
31
31
|
{
|
|
32
32
|
name: 'isPressed',
|
|
33
33
|
type: 'boolean',
|
|
34
|
-
description: 'Whether the button is currently pressed. Ignored
|
|
34
|
+
description: 'Whether the button is currently pressed. Ignored for a ToggleButtonGroup member with a value.',
|
|
35
35
|
},
|
|
36
36
|
{
|
|
37
37
|
name: 'onPressedChange',
|
|
38
38
|
type: '(isPressed: boolean, event: MouseEvent) => void',
|
|
39
|
-
description: 'Called when pressed state should change. Receives the next state and the click event; call event.preventDefault() to skip pressedChangeAction. Ignored
|
|
39
|
+
description: 'Called synchronously when pressed state should change. Receives the next state and the click event; call event.preventDefault() to skip pressedChangeAction. Without an Action, the callback produces no Action-pending feedback. Ignored for a ToggleButtonGroup member with a value.',
|
|
40
40
|
},
|
|
41
41
|
{
|
|
42
42
|
name: 'pressedChangeAction',
|
|
43
43
|
type: '(isPressed: boolean) => void | Promise<void>',
|
|
44
|
-
description: 'Action handler for API- or navigation-backed toggles, run in a transition. Shows an optimistic pressed state
|
|
44
|
+
description: 'Action handler for API- or navigation-backed toggles, run in a transition after the synchronous onPressedChange callback unless that callback calls event.preventDefault(). Works without onPressedChange. Shows an optimistic pressed state and a spinner while pending, and remains interruptible by re-clicks. Omit it for callback-only toggles with no Action-pending feedback. Ignored for a ToggleButtonGroup member with a value.',
|
|
45
45
|
},
|
|
46
46
|
{
|
|
47
47
|
name: 'size',
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* @file ToggleButton.test.tsx
|
|
5
5
|
* @input Uses vitest, @testing-library/react, ToggleButton, ToggleButtonGroup
|
|
6
|
-
* @output Unit tests for ToggleButton
|
|
6
|
+
* @output Unit tests for ToggleButton callback/Action order, pending state,
|
|
7
|
+
* group-owned selection, and ToggleButtonGroup
|
|
7
8
|
*
|
|
8
9
|
* SYNC: When ToggleButton.tsx or ToggleButtonGroup.tsx changes, update tests
|
|
9
10
|
*/
|
|
@@ -388,8 +389,94 @@ describe('ToggleButton', () => {
|
|
|
388
389
|
expect(pressedChangeAction).toHaveBeenCalledWith(true);
|
|
389
390
|
});
|
|
390
391
|
|
|
392
|
+
it('runs the synchronous callback before the Action with the same next state', async () => {
|
|
393
|
+
const calls: string[] = [];
|
|
394
|
+
const pressedChangeAction = vi.fn(() => {
|
|
395
|
+
calls.push('action');
|
|
396
|
+
});
|
|
397
|
+
const onPressedChange = vi.fn(() => {
|
|
398
|
+
expect(pressedChangeAction).not.toHaveBeenCalled();
|
|
399
|
+
calls.push('change');
|
|
400
|
+
});
|
|
401
|
+
render(
|
|
402
|
+
<ToggleButton
|
|
403
|
+
label="Favorite"
|
|
404
|
+
isPressed={false}
|
|
405
|
+
onPressedChange={onPressedChange}
|
|
406
|
+
pressedChangeAction={pressedChangeAction}
|
|
407
|
+
/>,
|
|
408
|
+
);
|
|
409
|
+
|
|
410
|
+
await userEvent.setup().click(screen.getByRole('button'));
|
|
411
|
+
|
|
412
|
+
expect(calls).toEqual(['change', 'action']);
|
|
413
|
+
expect(onPressedChange).toHaveBeenCalledExactlyOnceWith(
|
|
414
|
+
true,
|
|
415
|
+
expect.anything(),
|
|
416
|
+
);
|
|
417
|
+
expect(pressedChangeAction).toHaveBeenCalledExactlyOnceWith(true);
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
it('keeps callback-only controlled toggles synchronous without pending feedback', async () => {
|
|
421
|
+
function LegacyToggle() {
|
|
422
|
+
const [isPressed, setIsPressed] = useState(false);
|
|
423
|
+
return (
|
|
424
|
+
<ToggleButton
|
|
425
|
+
label="Bold"
|
|
426
|
+
isPressed={isPressed}
|
|
427
|
+
onPressedChange={setIsPressed}
|
|
428
|
+
/>
|
|
429
|
+
);
|
|
430
|
+
}
|
|
431
|
+
render(<LegacyToggle />);
|
|
432
|
+
const button = screen.getByRole('button');
|
|
433
|
+
|
|
434
|
+
fireEvent.click(button);
|
|
435
|
+
expect(button).toHaveAttribute('aria-pressed', 'true');
|
|
436
|
+
expect(button).not.toHaveAttribute('aria-busy', 'true');
|
|
437
|
+
fireEvent.click(button);
|
|
438
|
+
expect(button).toHaveAttribute('aria-pressed', 'false');
|
|
439
|
+
expect(button).not.toHaveAttribute('aria-busy', 'true');
|
|
440
|
+
await act(async () => {});
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
it('runs an Action without onPressedChange and settles to the controlled value', async () => {
|
|
444
|
+
let resolveAction: (() => void) | undefined;
|
|
445
|
+
const pressedChangeAction = vi.fn(
|
|
446
|
+
async () =>
|
|
447
|
+
new Promise<void>(resolve => {
|
|
448
|
+
resolveAction = resolve;
|
|
449
|
+
}),
|
|
450
|
+
);
|
|
451
|
+
const {rerender} = render(
|
|
452
|
+
<ToggleButton
|
|
453
|
+
label="Favorite"
|
|
454
|
+
isPressed={false}
|
|
455
|
+
pressedChangeAction={pressedChangeAction}
|
|
456
|
+
/>,
|
|
457
|
+
);
|
|
458
|
+
const button = screen.getByRole('button');
|
|
459
|
+
|
|
460
|
+
await userEvent.setup().click(button);
|
|
461
|
+
expect(pressedChangeAction).toHaveBeenCalledExactlyOnceWith(true);
|
|
462
|
+
expect(button).toHaveAttribute('aria-pressed', 'true');
|
|
463
|
+
expect(button).toHaveAttribute('aria-busy', 'true');
|
|
464
|
+
await act(async () => resolveAction?.());
|
|
465
|
+
expect(button).toHaveAttribute('aria-pressed', 'false');
|
|
466
|
+
expect(button).not.toHaveAttribute('aria-busy', 'true');
|
|
467
|
+
|
|
468
|
+
rerender(
|
|
469
|
+
<ToggleButton
|
|
470
|
+
label="Favorite"
|
|
471
|
+
isPressed
|
|
472
|
+
pressedChangeAction={pressedChangeAction}
|
|
473
|
+
/>,
|
|
474
|
+
);
|
|
475
|
+
expect(button).toHaveAttribute('aria-pressed', 'true');
|
|
476
|
+
expect(pressedChangeAction).toHaveBeenCalledTimes(1);
|
|
477
|
+
});
|
|
478
|
+
|
|
391
479
|
it('skips pressedChangeAction when onPressedChange calls preventDefault', async () => {
|
|
392
|
-
const user = userEvent.setup();
|
|
393
480
|
const pressedChangeAction = vi.fn();
|
|
394
481
|
const onPressedChange = vi.fn(
|
|
395
482
|
(_next: boolean, event: MouseEvent<HTMLButtonElement>) => {
|
|
@@ -406,10 +493,17 @@ describe('ToggleButton', () => {
|
|
|
406
493
|
/>,
|
|
407
494
|
);
|
|
408
495
|
|
|
409
|
-
|
|
496
|
+
const button = screen.getByRole('button', {name: 'Favorite'});
|
|
497
|
+
fireEvent.click(button);
|
|
410
498
|
|
|
411
|
-
expect(onPressedChange).
|
|
499
|
+
expect(onPressedChange).toHaveBeenCalledExactlyOnceWith(
|
|
500
|
+
true,
|
|
501
|
+
expect.anything(),
|
|
502
|
+
);
|
|
412
503
|
expect(pressedChangeAction).not.toHaveBeenCalled();
|
|
504
|
+
expect(button).toHaveAttribute('aria-pressed', 'false');
|
|
505
|
+
expect(button).not.toHaveAttribute('aria-busy', 'true');
|
|
506
|
+
await act(async () => {});
|
|
413
507
|
});
|
|
414
508
|
});
|
|
415
509
|
|
|
@@ -570,6 +664,207 @@ describe('ToggleButtonGroup (multiple)', () => {
|
|
|
570
664
|
});
|
|
571
665
|
});
|
|
572
666
|
|
|
667
|
+
// =============================================================================
|
|
668
|
+
// Group ownership — member Actions must not compete with controlled selection
|
|
669
|
+
// =============================================================================
|
|
670
|
+
|
|
671
|
+
describe.each(['single', 'multiple'] as const)(
|
|
672
|
+
'ToggleButtonGroup (%s) ownership',
|
|
673
|
+
type => {
|
|
674
|
+
it('keeps selection group-owned even when a member has standalone handlers', async () => {
|
|
675
|
+
const onChange = vi.fn();
|
|
676
|
+
const onPressedChange = vi.fn();
|
|
677
|
+
const pressedChangeAction = vi.fn();
|
|
678
|
+
const groupProps =
|
|
679
|
+
type === 'single'
|
|
680
|
+
? {type, value: 'list', onChange}
|
|
681
|
+
: {type, value: ['list'], onChange};
|
|
682
|
+
const children = (
|
|
683
|
+
<>
|
|
684
|
+
<ToggleButton value="list" label="List" isPressed={false} />
|
|
685
|
+
<ToggleButton
|
|
686
|
+
value="grid"
|
|
687
|
+
label="Grid"
|
|
688
|
+
isPressed
|
|
689
|
+
onPressedChange={onPressedChange}
|
|
690
|
+
pressedChangeAction={pressedChangeAction}
|
|
691
|
+
/>
|
|
692
|
+
</>
|
|
693
|
+
);
|
|
694
|
+
const {rerender} = render(
|
|
695
|
+
<ToggleButtonGroup {...groupProps} label="View">
|
|
696
|
+
{children}
|
|
697
|
+
</ToggleButtonGroup>,
|
|
698
|
+
);
|
|
699
|
+
const grid = screen.getByRole('button', {name: 'Grid'});
|
|
700
|
+
expect(grid).toHaveAttribute('aria-pressed', 'false');
|
|
701
|
+
expect(screen.getByRole('button', {name: 'List'})).toHaveAttribute(
|
|
702
|
+
'aria-pressed',
|
|
703
|
+
'true',
|
|
704
|
+
);
|
|
705
|
+
|
|
706
|
+
await userEvent.setup().click(grid);
|
|
707
|
+
expect(onChange).toHaveBeenCalledExactlyOnceWith(
|
|
708
|
+
type === 'single' ? 'grid' : ['list', 'grid'],
|
|
709
|
+
);
|
|
710
|
+
expect(onPressedChange).not.toHaveBeenCalled();
|
|
711
|
+
expect(pressedChangeAction).not.toHaveBeenCalled();
|
|
712
|
+
expect(grid).toHaveAttribute('aria-pressed', 'false');
|
|
713
|
+
expect(grid).not.toHaveAttribute('aria-busy', 'true');
|
|
714
|
+
|
|
715
|
+
const acceptedProps =
|
|
716
|
+
type === 'single'
|
|
717
|
+
? {type, value: 'grid', onChange}
|
|
718
|
+
: {type, value: ['list', 'grid'], onChange};
|
|
719
|
+
rerender(
|
|
720
|
+
<ToggleButtonGroup {...acceptedProps} label="View">
|
|
721
|
+
{children}
|
|
722
|
+
</ToggleButtonGroup>,
|
|
723
|
+
);
|
|
724
|
+
expect(grid).toHaveAttribute('aria-pressed', 'true');
|
|
725
|
+
await userEvent.setup().click(grid);
|
|
726
|
+
expect(onChange).toHaveBeenLastCalledWith(
|
|
727
|
+
type === 'single' ? null : ['list'],
|
|
728
|
+
);
|
|
729
|
+
expect(onPressedChange).not.toHaveBeenCalled();
|
|
730
|
+
expect(pressedChangeAction).not.toHaveBeenCalled();
|
|
731
|
+
});
|
|
732
|
+
},
|
|
733
|
+
);
|
|
734
|
+
|
|
735
|
+
// =============================================================================
|
|
736
|
+
// Disabled state — family:buttons FR3 (disabled means non-operable)
|
|
737
|
+
// =============================================================================
|
|
738
|
+
|
|
739
|
+
/**
|
|
740
|
+
* Two ways a ToggleButton becomes unavailable, and the rule that binds them:
|
|
741
|
+
* a group disables everything it contains, and a member can disable itself
|
|
742
|
+
* while the group stays enabled. Neither source may cancel the other out.
|
|
743
|
+
*
|
|
744
|
+
* The tooltip cases are here at the attribute and callback level only. A
|
|
745
|
+
* tooltip'd disabled toggle carries `aria-disabled` instead of the native
|
|
746
|
+
* `disabled` attribute, so whether a REAL mouse press is refused is an engine
|
|
747
|
+
* fact that jsdom's synthetic click cannot settle — that half lives in
|
|
748
|
+
* ./__tests__/ToggleButton.a11y.chromium.spec.ts.
|
|
749
|
+
*/
|
|
750
|
+
describe('disabled state', () => {
|
|
751
|
+
it('keeps a member disabled when the group disables nothing', async () => {
|
|
752
|
+
const user = userEvent.setup();
|
|
753
|
+
const handleChange = vi.fn();
|
|
754
|
+
render(
|
|
755
|
+
<ToggleButtonGroup value={null} onChange={handleChange} label="View mode">
|
|
756
|
+
<ToggleButton value="list" label="List" isDisabled />
|
|
757
|
+
<ToggleButton value="grid" label="Grid" />
|
|
758
|
+
</ToggleButtonGroup>,
|
|
759
|
+
);
|
|
760
|
+
|
|
761
|
+
expect(screen.getByRole('button', {name: 'List'})).toBeDisabled();
|
|
762
|
+
|
|
763
|
+
await user.click(screen.getByRole('button', {name: 'List'}));
|
|
764
|
+
expect(handleChange).not.toHaveBeenCalled();
|
|
765
|
+
});
|
|
766
|
+
|
|
767
|
+
it('leaves the rest of an enabled group selectable', async () => {
|
|
768
|
+
const user = userEvent.setup();
|
|
769
|
+
const handleChange = vi.fn();
|
|
770
|
+
render(
|
|
771
|
+
<ToggleButtonGroup value={null} onChange={handleChange} label="View mode">
|
|
772
|
+
<ToggleButton value="list" label="List" isDisabled />
|
|
773
|
+
<ToggleButton value="grid" label="Grid" />
|
|
774
|
+
</ToggleButtonGroup>,
|
|
775
|
+
);
|
|
776
|
+
|
|
777
|
+
expect(screen.getByRole('button', {name: 'Grid'})).toBeEnabled();
|
|
778
|
+
|
|
779
|
+
await user.click(screen.getByRole('button', {name: 'Grid'}));
|
|
780
|
+
expect(handleChange).toHaveBeenCalledWith('grid');
|
|
781
|
+
});
|
|
782
|
+
|
|
783
|
+
it('still disables a member that says nothing when the group is disabled', async () => {
|
|
784
|
+
const user = userEvent.setup();
|
|
785
|
+
const handleChange = vi.fn();
|
|
786
|
+
render(
|
|
787
|
+
<ToggleButtonGroup
|
|
788
|
+
value={null}
|
|
789
|
+
onChange={handleChange}
|
|
790
|
+
label="View mode"
|
|
791
|
+
isDisabled>
|
|
792
|
+
<ToggleButton value="list" label="List" />
|
|
793
|
+
</ToggleButtonGroup>,
|
|
794
|
+
);
|
|
795
|
+
|
|
796
|
+
expect(screen.getByRole('button', {name: 'List'})).toBeDisabled();
|
|
797
|
+
|
|
798
|
+
await user.click(screen.getByRole('button', {name: 'List'}));
|
|
799
|
+
expect(handleChange).not.toHaveBeenCalled();
|
|
800
|
+
});
|
|
801
|
+
|
|
802
|
+
it('keeps a tooltip-bearing disabled member focusable but inert', async () => {
|
|
803
|
+
const user = userEvent.setup();
|
|
804
|
+
const handleChange = vi.fn();
|
|
805
|
+
render(
|
|
806
|
+
<ToggleButtonGroup value={null} onChange={handleChange} label="View mode">
|
|
807
|
+
<ToggleButton
|
|
808
|
+
value="list"
|
|
809
|
+
label="List"
|
|
810
|
+
tooltip="List view is unavailable for this dataset"
|
|
811
|
+
isDisabled
|
|
812
|
+
/>
|
|
813
|
+
</ToggleButtonGroup>,
|
|
814
|
+
);
|
|
815
|
+
|
|
816
|
+
const member = screen.getByRole('button', {name: 'List'});
|
|
817
|
+
// The tooltip is the disabled reason, so the control stays reachable to
|
|
818
|
+
// read it: aria-disabled rather than the native attribute, which would
|
|
819
|
+
// take it out of the tab order along with its own explanation.
|
|
820
|
+
expect(member).toHaveAttribute('aria-disabled', 'true');
|
|
821
|
+
expect(member).not.toBeDisabled();
|
|
822
|
+
|
|
823
|
+
await user.click(member);
|
|
824
|
+
expect(handleChange).not.toHaveBeenCalled();
|
|
825
|
+
});
|
|
826
|
+
|
|
827
|
+
it('does not toggle a standalone disabled toggle that carries a tooltip', async () => {
|
|
828
|
+
const user = userEvent.setup();
|
|
829
|
+
const handleChange = vi.fn();
|
|
830
|
+
render(
|
|
831
|
+
<ToggleButton
|
|
832
|
+
label="Bold"
|
|
833
|
+
tooltip="Formatting is locked for this document"
|
|
834
|
+
isPressed={false}
|
|
835
|
+
onPressedChange={handleChange}
|
|
836
|
+
isDisabled
|
|
837
|
+
/>,
|
|
838
|
+
);
|
|
839
|
+
|
|
840
|
+
const toggle = screen.getByRole('button', {name: 'Bold'});
|
|
841
|
+
expect(toggle).toHaveAttribute('aria-disabled', 'true');
|
|
842
|
+
|
|
843
|
+
await user.click(toggle);
|
|
844
|
+
expect(handleChange).not.toHaveBeenCalled();
|
|
845
|
+
expect(toggle).toHaveAttribute('aria-pressed', 'false');
|
|
846
|
+
});
|
|
847
|
+
|
|
848
|
+
it('still toggles an enabled toggle that carries the same tooltip', async () => {
|
|
849
|
+
const user = userEvent.setup();
|
|
850
|
+
const handleChange = vi.fn();
|
|
851
|
+
render(
|
|
852
|
+
<ToggleButton
|
|
853
|
+
label="Bold"
|
|
854
|
+
tooltip="Bold the selected text"
|
|
855
|
+
isPressed={false}
|
|
856
|
+
onPressedChange={handleChange}
|
|
857
|
+
/>,
|
|
858
|
+
);
|
|
859
|
+
|
|
860
|
+
const toggle = screen.getByRole('button', {name: 'Bold'});
|
|
861
|
+
expect(toggle).not.toHaveAttribute('aria-disabled');
|
|
862
|
+
|
|
863
|
+
await user.click(toggle);
|
|
864
|
+
expect(handleChange).toHaveBeenCalledWith(true, expect.anything());
|
|
865
|
+
});
|
|
866
|
+
});
|
|
867
|
+
|
|
573
868
|
// jsdom cannot emulate forced-colors rendering, so these assert that the
|
|
574
869
|
// compiled output includes the forced-colors rules; visual behavior needs
|
|
575
870
|
// manual verification under Windows High Contrast.
|