@primer/components 30.3.0-rc.2010c7d4 → 31.0.0-rc.15aa0a10
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/.eslintrc.json +2 -1
- package/.storybook/preview.js +4 -4
- package/CHANGELOG.md +12 -2
- package/codemods/deprecateUtilityComponents.js +1 -1
- package/contributor-docs/adrs/adr-003-prop-norms.md +72 -0
- package/dist/browser.esm.js +798 -794
- package/dist/browser.esm.js.map +1 -1
- package/dist/browser.umd.js +801 -797
- package/dist/browser.umd.js.map +1 -1
- package/docs/content/Autocomplete.mdx +627 -0
- package/docs/content/TextInputTokens.mdx +89 -0
- package/docs/content/getting-started.md +1 -1
- package/docs/content/overriding-styles.mdx +7 -6
- package/docs/content/theming.md +5 -5
- package/docs/package-lock.json +288 -511
- package/docs/package.json +1 -1
- package/docs/src/@primer/gatsby-theme-doctocat/components/hero.js +14 -12
- package/docs/src/@primer/gatsby-theme-doctocat/nav.yml +2 -0
- package/docs/src/@primer/gatsby-theme-doctocat/primer-components-hero.svg +7 -7
- package/lib/ActionList/Item.js +1 -1
- package/lib/AnchoredOverlay/AnchoredOverlay.d.ts +2 -1
- package/lib/AnchoredOverlay/AnchoredOverlay.js +11 -3
- package/lib/Autocomplete/Autocomplete.d.ts +304 -0
- package/lib/Autocomplete/Autocomplete.js +145 -0
- package/lib/Autocomplete/AutocompleteContext.d.ts +17 -0
- package/lib/Autocomplete/AutocompleteContext.js +11 -0
- package/lib/Autocomplete/AutocompleteInput.d.ts +292 -0
- package/lib/Autocomplete/AutocompleteInput.js +157 -0
- package/lib/Autocomplete/AutocompleteMenu.d.ts +72 -0
- package/lib/Autocomplete/AutocompleteMenu.js +224 -0
- package/lib/Autocomplete/AutocompleteOverlay.d.ts +20 -0
- package/lib/Autocomplete/AutocompleteOverlay.js +80 -0
- package/lib/Autocomplete/index.d.ts +2 -0
- package/lib/Autocomplete/index.js +15 -0
- package/lib/BaseStyles.js +1 -1
- package/lib/BorderBox.js +1 -1
- package/lib/Button/ButtonInvisible.js +1 -1
- package/lib/Caret.js +2 -2
- package/lib/Dialog.js +1 -1
- package/lib/FilteredActionList/FilteredActionList.js +5 -31
- package/lib/Flash.js +16 -16
- package/lib/Label.js +1 -1
- package/lib/Overlay.d.ts +1 -0
- package/lib/Overlay.js +3 -1
- package/lib/ProgressBar.js +1 -1
- package/lib/StateLabel.js +13 -19
- package/lib/Token/_RemoveTokenButton.js +1 -1
- package/lib/__tests__/Autocomplete.test.d.ts +1 -0
- package/lib/__tests__/Autocomplete.test.js +528 -0
- package/lib/__tests__/BorderBox.test.js +1 -1
- package/lib/__tests__/CircleOcticon.test.js +1 -1
- package/lib/__tests__/CounterLabel.test.js +4 -4
- package/lib/__tests__/Flash.test.js +4 -4
- package/lib/__tests__/Link.test.js +1 -1
- package/lib/__tests__/behaviors/scrollIntoViewingArea.test.d.ts +1 -0
- package/lib/__tests__/behaviors/scrollIntoViewingArea.test.js +226 -0
- package/lib/behaviors/scrollIntoViewingArea.d.ts +1 -0
- package/lib/behaviors/scrollIntoViewingArea.js +39 -0
- package/lib/hooks/useOpenAndCloseFocus.d.ts +2 -1
- package/lib/hooks/useOpenAndCloseFocus.js +7 -2
- package/lib/hooks/useOverlay.d.ts +2 -1
- package/lib/hooks/useOverlay.js +4 -2
- package/lib/index.d.ts +2 -0
- package/lib/index.js +8 -0
- package/lib/stories/Autocomplete.stories.js +608 -0
- package/lib/stories/Dialog.stories.js +3 -3
- package/lib/stories/IssueLabelToken.stories.js +1 -1
- package/lib/stories/ProfileToken.stories.js +1 -1
- package/lib/theme-preval.js +370 -3100
- package/lib/utils/testing.d.ts +50 -493
- package/lib/utils/types/MandateProps.d.ts +3 -0
- package/lib/utils/types/MandateProps.js +1 -0
- package/lib/utils/types/index.d.ts +1 -0
- package/lib/utils/types/index.js +13 -0
- package/lib-esm/ActionList/Item.js +1 -1
- package/lib-esm/AnchoredOverlay/AnchoredOverlay.d.ts +2 -1
- package/lib-esm/AnchoredOverlay/AnchoredOverlay.js +11 -3
- package/lib-esm/Autocomplete/Autocomplete.d.ts +304 -0
- package/lib-esm/Autocomplete/Autocomplete.js +123 -0
- package/lib-esm/Autocomplete/AutocompleteContext.d.ts +17 -0
- package/lib-esm/Autocomplete/AutocompleteContext.js +2 -0
- package/lib-esm/Autocomplete/AutocompleteInput.d.ts +292 -0
- package/lib-esm/Autocomplete/AutocompleteInput.js +138 -0
- package/lib-esm/Autocomplete/AutocompleteMenu.d.ts +72 -0
- package/lib-esm/Autocomplete/AutocompleteMenu.js +205 -0
- package/lib-esm/Autocomplete/AutocompleteOverlay.d.ts +20 -0
- package/lib-esm/Autocomplete/AutocompleteOverlay.js +62 -0
- package/lib-esm/Autocomplete/index.d.ts +2 -0
- package/lib-esm/Autocomplete/index.js +1 -0
- package/lib-esm/BaseStyles.js +1 -1
- package/lib-esm/BorderBox.js +1 -1
- package/lib-esm/Button/ButtonInvisible.js +1 -1
- package/lib-esm/Caret.js +2 -2
- package/lib-esm/Dialog.js +1 -1
- package/lib-esm/FilteredActionList/FilteredActionList.js +3 -31
- package/lib-esm/Flash.js +16 -16
- package/lib-esm/Label.js +1 -1
- package/lib-esm/Overlay.d.ts +1 -0
- package/lib-esm/Overlay.js +3 -1
- package/lib-esm/ProgressBar.js +1 -1
- package/lib-esm/StateLabel.js +13 -19
- package/lib-esm/Token/_RemoveTokenButton.js +1 -1
- package/lib-esm/__tests__/Autocomplete.test.d.ts +1 -0
- package/lib-esm/__tests__/Autocomplete.test.js +494 -0
- package/lib-esm/__tests__/BorderBox.test.js +1 -1
- package/lib-esm/__tests__/CircleOcticon.test.js +1 -1
- package/lib-esm/__tests__/CounterLabel.test.js +4 -4
- package/lib-esm/__tests__/Flash.test.js +4 -4
- package/lib-esm/__tests__/Link.test.js +1 -1
- package/lib-esm/__tests__/behaviors/scrollIntoViewingArea.test.d.ts +1 -0
- package/lib-esm/__tests__/behaviors/scrollIntoViewingArea.test.js +224 -0
- package/lib-esm/behaviors/scrollIntoViewingArea.d.ts +1 -0
- package/lib-esm/behaviors/scrollIntoViewingArea.js +30 -0
- package/lib-esm/hooks/useOpenAndCloseFocus.d.ts +2 -1
- package/lib-esm/hooks/useOpenAndCloseFocus.js +7 -2
- package/lib-esm/hooks/useOverlay.d.ts +2 -1
- package/lib-esm/hooks/useOverlay.js +4 -2
- package/lib-esm/index.d.ts +2 -0
- package/lib-esm/index.js +1 -0
- package/lib-esm/stories/Autocomplete.stories.js +549 -0
- package/lib-esm/stories/Dialog.stories.js +3 -3
- package/lib-esm/stories/IssueLabelToken.stories.js +1 -1
- package/lib-esm/stories/ProfileToken.stories.js +1 -1
- package/lib-esm/theme-preval.js +370 -3100
- package/lib-esm/utils/testing.d.ts +50 -493
- package/lib-esm/utils/types/MandateProps.d.ts +3 -0
- package/lib-esm/utils/types/MandateProps.js +1 -0
- package/lib-esm/utils/types/index.d.ts +1 -0
- package/lib-esm/utils/types/index.js +2 -1
- package/package-lock.json +11 -8
- package/package.json +3 -3
- package/src/ActionList/Item.tsx +1 -1
- package/src/AnchoredOverlay/AnchoredOverlay.tsx +14 -3
- package/src/Autocomplete/Autocomplete.tsx +103 -0
- package/src/Autocomplete/AutocompleteContext.tsx +19 -0
- package/src/Autocomplete/AutocompleteInput.tsx +179 -0
- package/src/Autocomplete/AutocompleteMenu.tsx +341 -0
- package/src/Autocomplete/AutocompleteOverlay.tsx +68 -0
- package/src/Autocomplete/index.ts +2 -0
- package/src/BaseStyles.tsx +1 -1
- package/src/BorderBox.tsx +1 -1
- package/src/Button/ButtonInvisible.tsx +7 -2
- package/src/Caret.tsx +2 -2
- package/src/Dialog.tsx +1 -1
- package/src/FilteredActionList/FilteredActionList.tsx +10 -25
- package/src/Flash.tsx +16 -16
- package/src/Label.tsx +1 -1
- package/src/Overlay.tsx +4 -1
- package/src/ProgressBar.tsx +1 -1
- package/src/StateLabel.tsx +12 -20
- package/src/Token/_RemoveTokenButton.tsx +4 -2
- package/src/__tests__/Autocomplete.test.tsx +444 -0
- package/src/__tests__/BorderBox.test.tsx +1 -1
- package/src/__tests__/CircleOcticon.test.tsx +1 -1
- package/src/__tests__/CounterLabel.test.tsx +4 -4
- package/src/__tests__/Flash.test.tsx +4 -4
- package/src/__tests__/Link.test.tsx +1 -1
- package/src/__tests__/__snapshots__/AnchoredOverlay.test.tsx.snap +3 -3
- package/src/__tests__/__snapshots__/Autocomplete.test.tsx.snap +3414 -0
- package/src/__tests__/__snapshots__/Button.test.tsx.snap +9 -1
- package/src/__tests__/__snapshots__/ConfirmationDialog.test.tsx.snap +1 -1
- package/src/__tests__/__snapshots__/SelectPanel.test.tsx.snap +1 -1
- package/src/__tests__/__snapshots__/StateLabel.test.tsx.snap +0 -21
- package/src/__tests__/__snapshots__/TextInputWithTokens.test.tsx.snap +16 -16
- package/src/__tests__/__snapshots__/Token.test.tsx.snap +34 -34
- package/src/__tests__/behaviors/scrollIntoViewingArea.test.ts +195 -0
- package/src/behaviors/scrollIntoViewingArea.ts +27 -0
- package/src/hooks/useOpenAndCloseFocus.ts +7 -2
- package/src/hooks/useOverlay.tsx +4 -2
- package/src/index.ts +2 -0
- package/src/stories/Autocomplete.stories.tsx +572 -0
- package/src/stories/Dialog.stories.tsx +3 -3
- package/src/stories/IssueLabelToken.stories.tsx +1 -1
- package/src/stories/ProfileToken.stories.tsx +1 -1
- package/src/utils/types/MandateProps.ts +19 -0
- package/src/utils/types/index.ts +1 -0
- package/stats.html +1 -1
- package/docs/src/@primer/gatsby-theme-doctocat/components/live-code.js +0 -84
- package/docs/src/@primer/gatsby-theme-doctocat/components/nav-dropdown.js +0 -48
- package/docs/src/@primer/gatsby-theme-doctocat/components/wrap-page-element.js +0 -25
@@ -0,0 +1,205 @@
|
|
1
|
+
import React, { useContext, useEffect, useMemo, useRef, useState } from 'react';
|
2
|
+
import { ActionList } from '../ActionList';
|
3
|
+
import { useFocusZone } from '../hooks/useFocusZone';
|
4
|
+
import { Box, Spinner } from '../';
|
5
|
+
import { AutocompleteContext } from './AutocompleteContext';
|
6
|
+
import { PlusIcon } from '@primer/octicons-react';
|
7
|
+
import { uniqueId } from '../utils/uniqueId';
|
8
|
+
import { scrollIntoViewingArea } from '../behaviors/scrollIntoViewingArea';
|
9
|
+
|
10
|
+
const getDefaultSortFn = isItemSelectedFn => (itemIdA, itemIdB) => isItemSelectedFn(itemIdA) === isItemSelectedFn(itemIdB) ? 0 : isItemSelectedFn(itemIdA) ? -1 : 1;
|
11
|
+
|
12
|
+
function getDefaultItemFilter(filterValue) {
|
13
|
+
return function (item, _i) {
|
14
|
+
var _item$text;
|
15
|
+
|
16
|
+
return Boolean((_item$text = item.text) === null || _item$text === void 0 ? void 0 : _item$text.toLowerCase().startsWith(filterValue.toLowerCase()));
|
17
|
+
};
|
18
|
+
}
|
19
|
+
|
20
|
+
function getDefaultOnSelectionChange(setInputValueFn) {
|
21
|
+
return function (itemOrItems) {
|
22
|
+
const {
|
23
|
+
text = ''
|
24
|
+
} = Array.isArray(itemOrItems) ? itemOrItems.slice(-1)[0] : itemOrItems;
|
25
|
+
setInputValueFn(text);
|
26
|
+
};
|
27
|
+
}
|
28
|
+
|
29
|
+
const isItemSelected = (itemId, selectedItemIds) => selectedItemIds.includes(itemId);
|
30
|
+
|
31
|
+
function getItemById(itemId, items) {
|
32
|
+
return items.find(item => item.id === itemId);
|
33
|
+
} // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
34
|
+
|
35
|
+
|
36
|
+
function AutocompleteMenu(props) {
|
37
|
+
const autocompleteContext = useContext(AutocompleteContext);
|
38
|
+
|
39
|
+
if (autocompleteContext === null) {
|
40
|
+
throw new Error('AutocompleteContext returned null values');
|
41
|
+
}
|
42
|
+
|
43
|
+
const {
|
44
|
+
activeDescendantRef,
|
45
|
+
id,
|
46
|
+
inputRef,
|
47
|
+
inputValue = '',
|
48
|
+
scrollContainerRef,
|
49
|
+
setAutocompleteSuggestion,
|
50
|
+
setShowMenu,
|
51
|
+
setInputValue,
|
52
|
+
setIsMenuDirectlyActivated,
|
53
|
+
setSelectedItemLength,
|
54
|
+
showMenu
|
55
|
+
} = autocompleteContext;
|
56
|
+
const {
|
57
|
+
items,
|
58
|
+
selectedItemIds,
|
59
|
+
sortOnCloseFn,
|
60
|
+
emptyStateText,
|
61
|
+
addNewItem,
|
62
|
+
loading,
|
63
|
+
selectionVariant,
|
64
|
+
filterFn,
|
65
|
+
'aria-labelledby': ariaLabelledBy,
|
66
|
+
onOpenChange,
|
67
|
+
onSelectedChange,
|
68
|
+
customScrollContainerRef
|
69
|
+
} = props;
|
70
|
+
const listContainerRef = useRef(null);
|
71
|
+
const [highlightedItem, setHighlightedItem] = useState();
|
72
|
+
const [sortedItemIds, setSortedItemIds] = useState(items.map(({
|
73
|
+
id: itemId
|
74
|
+
}) => itemId));
|
75
|
+
const selectableItems = useMemo(() => items.map(selectableItem => {
|
76
|
+
return { ...selectableItem,
|
77
|
+
role: 'option',
|
78
|
+
id: selectableItem.id,
|
79
|
+
selected: selectionVariant === 'multiple' ? selectedItemIds.includes(selectableItem.id) : undefined,
|
80
|
+
onAction: item => {
|
81
|
+
const otherSelectedItemIds = selectedItemIds.filter(selectedItemId => selectedItemId !== item.id);
|
82
|
+
const newSelectedItemIds = selectedItemIds.includes(item.id) ? otherSelectedItemIds : [...otherSelectedItemIds, item.id];
|
83
|
+
const onSelectedChangeFn = onSelectedChange ? onSelectedChange : getDefaultOnSelectionChange(setInputValue);
|
84
|
+
onSelectedChangeFn(newSelectedItemIds.map(newSelectedItemId => getItemById(newSelectedItemId, items)));
|
85
|
+
|
86
|
+
if (selectionVariant === 'multiple') {
|
87
|
+
setInputValue('');
|
88
|
+
setAutocompleteSuggestion('');
|
89
|
+
} else {
|
90
|
+
var _inputRef$current;
|
91
|
+
|
92
|
+
setShowMenu(false);
|
93
|
+
(_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 ? void 0 : _inputRef$current.setSelectionRange(inputRef.current.value.length, inputRef.current.value.length);
|
94
|
+
}
|
95
|
+
}
|
96
|
+
};
|
97
|
+
}), [items, selectedItemIds, inputRef, onSelectedChange, selectionVariant, setAutocompleteSuggestion, setInputValue, setShowMenu]);
|
98
|
+
const itemSortOrderData = useMemo(() => sortedItemIds.reduce((acc, curr, i) => {
|
99
|
+
acc[curr] = i;
|
100
|
+
return acc;
|
101
|
+
}, {}), [sortedItemIds]);
|
102
|
+
const sortedAndFilteredItemsToRender = useMemo(() => selectableItems.filter(filterFn ? filterFn : getDefaultItemFilter(inputValue)).sort((a, b) => itemSortOrderData[a.id] - itemSortOrderData[b.id]), [selectableItems, itemSortOrderData, filterFn, inputValue]);
|
103
|
+
const allItemsToRender = useMemo(() => [// sorted and filtered selectable items
|
104
|
+
...sortedAndFilteredItemsToRender, // menu item used for creating a token from whatever is in the text input
|
105
|
+
...(addNewItem ? [{ ...addNewItem,
|
106
|
+
leadingVisual: () => /*#__PURE__*/React.createElement(PlusIcon, null),
|
107
|
+
onAction: item => {
|
108
|
+
// TODO: make it possible to pass a leadingVisual when using `addNewItem`
|
109
|
+
addNewItem.handleAddItem({ ...item,
|
110
|
+
id: item.id || uniqueId(),
|
111
|
+
leadingVisual: undefined
|
112
|
+
});
|
113
|
+
|
114
|
+
if (selectionVariant === 'multiple') {
|
115
|
+
setInputValue('');
|
116
|
+
setAutocompleteSuggestion('');
|
117
|
+
}
|
118
|
+
}
|
119
|
+
}] : [])], [sortedAndFilteredItemsToRender, addNewItem, setAutocompleteSuggestion, selectionVariant, setInputValue]);
|
120
|
+
useFocusZone({
|
121
|
+
containerRef: listContainerRef,
|
122
|
+
focusOutBehavior: 'wrap',
|
123
|
+
focusableElementFilter: element => {
|
124
|
+
return !(element instanceof HTMLInputElement);
|
125
|
+
},
|
126
|
+
activeDescendantFocus: inputRef,
|
127
|
+
onActiveDescendantChanged: (current, _previous, directlyActivated) => {
|
128
|
+
activeDescendantRef.current = current || null;
|
129
|
+
|
130
|
+
if (current) {
|
131
|
+
const selectedItem = selectableItems.find(item => item.id.toString() === current.getAttribute('data-id'));
|
132
|
+
setHighlightedItem(selectedItem);
|
133
|
+
setIsMenuDirectlyActivated(directlyActivated);
|
134
|
+
}
|
135
|
+
|
136
|
+
if (current && customScrollContainerRef && customScrollContainerRef.current && directlyActivated) {
|
137
|
+
scrollIntoViewingArea(current, customScrollContainerRef.current);
|
138
|
+
} else if (current && scrollContainerRef.current && directlyActivated) {
|
139
|
+
scrollIntoViewingArea(current, scrollContainerRef.current);
|
140
|
+
}
|
141
|
+
}
|
142
|
+
}, [loading]);
|
143
|
+
useEffect(() => {
|
144
|
+
var _highlightedItem$text;
|
145
|
+
|
146
|
+
if (highlightedItem !== null && highlightedItem !== void 0 && (_highlightedItem$text = highlightedItem.text) !== null && _highlightedItem$text !== void 0 && _highlightedItem$text.startsWith(inputValue) && !selectedItemIds.includes(highlightedItem.id)) {
|
147
|
+
setAutocompleteSuggestion(highlightedItem.text);
|
148
|
+
} else {
|
149
|
+
setAutocompleteSuggestion('');
|
150
|
+
}
|
151
|
+
}, [highlightedItem, inputValue, selectedItemIds, setAutocompleteSuggestion]);
|
152
|
+
useEffect(() => {
|
153
|
+
const itemIdSortResult = [...sortedItemIds].sort(sortOnCloseFn ? sortOnCloseFn : getDefaultSortFn(itemId => isItemSelected(itemId, selectedItemIds)));
|
154
|
+
const sortResultMatchesState = itemIdSortResult.length === sortedItemIds.length && itemIdSortResult.every((element, index) => element === sortedItemIds[index]);
|
155
|
+
|
156
|
+
if (showMenu === false && !sortResultMatchesState) {
|
157
|
+
setSortedItemIds(itemIdSortResult);
|
158
|
+
}
|
159
|
+
|
160
|
+
onOpenChange && onOpenChange(Boolean(showMenu));
|
161
|
+
}, [showMenu, onOpenChange, selectedItemIds, sortOnCloseFn, sortedItemIds]);
|
162
|
+
useEffect(() => {
|
163
|
+
if (selectedItemIds.length) {
|
164
|
+
setSelectedItemLength(selectedItemIds.length);
|
165
|
+
}
|
166
|
+
}, [selectedItemIds, setSelectedItemLength]);
|
167
|
+
return /*#__PURE__*/React.createElement(Box, {
|
168
|
+
sx: !showMenu ? {
|
169
|
+
// visually hides this label for sighted users
|
170
|
+
position: 'absolute',
|
171
|
+
width: '1px',
|
172
|
+
height: '1px',
|
173
|
+
padding: '0',
|
174
|
+
margin: '-1px',
|
175
|
+
overflow: 'hidden',
|
176
|
+
clip: 'rect(0, 0, 0, 0)',
|
177
|
+
whiteSpace: 'nowrap',
|
178
|
+
borderWidth: '0'
|
179
|
+
} : {}
|
180
|
+
}, loading ? /*#__PURE__*/React.createElement(Box, {
|
181
|
+
p: 3,
|
182
|
+
display: "flex",
|
183
|
+
justifyContent: "center"
|
184
|
+
}, /*#__PURE__*/React.createElement(Spinner, null)) : /*#__PURE__*/React.createElement("div", {
|
185
|
+
ref: listContainerRef
|
186
|
+
}, allItemsToRender.length ? /*#__PURE__*/React.createElement(ActionList, {
|
187
|
+
selectionVariant: "multiple" // have to typecast to `ItemProps` because we have an extra property
|
188
|
+
// on `items` for Autocomplete: `metadata`
|
189
|
+
,
|
190
|
+
items: allItemsToRender,
|
191
|
+
role: "listbox",
|
192
|
+
id: `${id}-listbox`,
|
193
|
+
"aria-labelledby": ariaLabelledBy
|
194
|
+
}) : /*#__PURE__*/React.createElement(Box, {
|
195
|
+
p: 3
|
196
|
+
}, emptyStateText)));
|
197
|
+
}
|
198
|
+
|
199
|
+
AutocompleteMenu.displayName = "AutocompleteMenu";
|
200
|
+
AutocompleteMenu.defaultProps = {
|
201
|
+
emptyStateText: 'No selectable options',
|
202
|
+
selectionVariant: 'single'
|
203
|
+
};
|
204
|
+
AutocompleteMenu.displayName = 'AutocompleteMenu';
|
205
|
+
export default AutocompleteMenu;
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { OverlayProps } from '../Overlay';
|
3
|
+
import { ComponentProps } from '../utils/types';
|
4
|
+
declare type AutocompleteOverlayInternalProps = {
|
5
|
+
/**
|
6
|
+
* The ref of the element that the position of the menu is based on. By default, the menu is positioned based on the text input
|
7
|
+
*/
|
8
|
+
menuAnchorRef?: React.RefObject<HTMLElement>;
|
9
|
+
/**
|
10
|
+
* Props to be spread on the internal `Overlay` component.
|
11
|
+
*/
|
12
|
+
overlayProps?: Partial<OverlayProps>;
|
13
|
+
children?: React.ReactNode;
|
14
|
+
} & Pick<React.AriaAttributes, 'aria-labelledby'>;
|
15
|
+
declare function AutocompleteOverlay({ menuAnchorRef, overlayProps, children }: AutocompleteOverlayInternalProps): JSX.Element | null;
|
16
|
+
declare namespace AutocompleteOverlay {
|
17
|
+
var displayName: string;
|
18
|
+
}
|
19
|
+
export declare type AutocompleteOverlayProps = ComponentProps<typeof AutocompleteOverlay>;
|
20
|
+
export default AutocompleteOverlay;
|
@@ -0,0 +1,62 @@
|
|
1
|
+
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
2
|
+
|
3
|
+
import React, { useCallback, useContext } from 'react';
|
4
|
+
import { useAnchoredPosition } from '../hooks';
|
5
|
+
import Overlay from '../Overlay';
|
6
|
+
import { AutocompleteContext } from './AutocompleteContext';
|
7
|
+
import { useCombinedRefs } from '../hooks/useCombinedRefs';
|
8
|
+
|
9
|
+
// TODO: consider making 'aria-labelledby' required
|
10
|
+
function AutocompleteOverlay({
|
11
|
+
menuAnchorRef,
|
12
|
+
overlayProps,
|
13
|
+
children
|
14
|
+
}) {
|
15
|
+
const autocompleteContext = useContext(AutocompleteContext);
|
16
|
+
|
17
|
+
if (autocompleteContext === null) {
|
18
|
+
throw new Error('AutocompleteContext returned null values');
|
19
|
+
}
|
20
|
+
|
21
|
+
const {
|
22
|
+
inputRef,
|
23
|
+
scrollContainerRef,
|
24
|
+
selectedItemLength,
|
25
|
+
setShowMenu,
|
26
|
+
showMenu = false
|
27
|
+
} = autocompleteContext;
|
28
|
+
const {
|
29
|
+
floatingElementRef,
|
30
|
+
position
|
31
|
+
} = useAnchoredPosition({
|
32
|
+
side: 'outside-bottom',
|
33
|
+
align: 'start',
|
34
|
+
anchorElementRef: menuAnchorRef ? menuAnchorRef : inputRef
|
35
|
+
}, [showMenu, selectedItemLength]);
|
36
|
+
const combinedOverlayRef = useCombinedRefs(scrollContainerRef, floatingElementRef);
|
37
|
+
const closeOptionList = useCallback(() => {
|
38
|
+
setShowMenu(false);
|
39
|
+
}, [setShowMenu]);
|
40
|
+
|
41
|
+
if (typeof window === 'undefined') {
|
42
|
+
return null;
|
43
|
+
}
|
44
|
+
|
45
|
+
return /*#__PURE__*/React.createElement(Overlay, _extends({
|
46
|
+
returnFocusRef: inputRef,
|
47
|
+
preventFocusOnOpen: true,
|
48
|
+
onClickOutside: closeOptionList,
|
49
|
+
onEscape: closeOptionList,
|
50
|
+
ref: combinedOverlayRef,
|
51
|
+
top: position === null || position === void 0 ? void 0 : position.top,
|
52
|
+
left: position === null || position === void 0 ? void 0 : position.left,
|
53
|
+
visibility: showMenu ? 'visible' : 'hidden',
|
54
|
+
sx: {
|
55
|
+
overflow: 'auto'
|
56
|
+
}
|
57
|
+
}, overlayProps), children);
|
58
|
+
}
|
59
|
+
|
60
|
+
AutocompleteOverlay.displayName = "AutocompleteOverlay";
|
61
|
+
AutocompleteOverlay.displayName = 'AutocompleteOverlay';
|
62
|
+
export default AutocompleteOverlay;
|
@@ -0,0 +1 @@
|
|
1
|
+
export { default } from './Autocomplete';
|
package/lib-esm/BaseStyles.js
CHANGED
package/lib-esm/BorderBox.js
CHANGED
@@ -5,5 +5,5 @@ import ButtonBase, { buttonSystemProps } from './ButtonBase';
|
|
5
5
|
const ButtonInvisible = styled(ButtonBase).withConfig({
|
6
6
|
displayName: "ButtonInvisible",
|
7
7
|
componentId: "sc-1195tpn-0"
|
8
|
-
})(["color:", ";background-color:transparent;border:0;border-radius:", ";box-shadow:none;&:disabled{color:", ";}&:focus{box-shadow:", ";}", ";", ""], get('colors.accent.fg'), get('radii.2'), get('colors.fg.
|
8
|
+
})(["color:", ";background-color:transparent;border:0;border-radius:", ";box-shadow:none;&:disabled{color:", ";}&:focus{box-shadow:", ";}&:hover{background-color:", ";}&:active{background-color:", ";}", ";", ""], get('colors.accent.fg'), get('radii.2'), get('colors.primer.fg.disabled'), get('shadows.btn.focusShadow'), get('colors.btn.hoverBg'), get('colors.btn.selectedBg'), buttonSystemProps, sx);
|
9
9
|
export default ButtonInvisible;
|
package/lib-esm/Caret.js
CHANGED
@@ -106,8 +106,8 @@ function Caret(props) {
|
|
106
106
|
Caret.displayName = "Caret";
|
107
107
|
Caret.locations = ['top', 'top-left', 'top-right', 'right', 'right-top', 'right-bottom', 'bottom', 'bottom-left', 'bottom-right', 'left', 'left-top', 'left-bottom'];
|
108
108
|
Caret.defaultProps = {
|
109
|
-
bg: '
|
110
|
-
borderColor: 'border.
|
109
|
+
bg: 'canvas.default',
|
110
|
+
borderColor: 'border.default',
|
111
111
|
borderWidth: 1
|
112
112
|
};
|
113
113
|
export default Caret;
|
package/lib-esm/Dialog.js
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
2
2
|
|
3
3
|
import React, { useCallback, useEffect, useRef } from 'react';
|
4
|
+
import { useSSRSafeId } from '@react-aria/ssr';
|
4
5
|
import TextInput from '../TextInput';
|
5
6
|
import Box from '../Box';
|
6
7
|
import { ActionList } from '../ActionList';
|
@@ -11,36 +12,7 @@ import styled from 'styled-components';
|
|
11
12
|
import { get } from '../constants';
|
12
13
|
import { useProvidedRefOrCreate } from '../hooks/useProvidedRefOrCreate';
|
13
14
|
import useScrollFlash from '../hooks/useScrollFlash';
|
14
|
-
import {
|
15
|
-
|
16
|
-
function scrollIntoViewingArea(child, container, margin = 8, behavior = 'smooth') {
|
17
|
-
const {
|
18
|
-
top: childTop,
|
19
|
-
bottom: childBottom
|
20
|
-
} = child.getBoundingClientRect();
|
21
|
-
const {
|
22
|
-
top: containerTop,
|
23
|
-
bottom: containerBottom
|
24
|
-
} = container.getBoundingClientRect();
|
25
|
-
const isChildTopAboveViewingArea = childTop < containerTop + margin;
|
26
|
-
const isChildBottomBelowViewingArea = childBottom > containerBottom - margin;
|
27
|
-
|
28
|
-
if (isChildTopAboveViewingArea) {
|
29
|
-
const scrollHeightToChildTop = childTop - containerTop + container.scrollTop;
|
30
|
-
container.scrollTo({
|
31
|
-
behavior,
|
32
|
-
top: scrollHeightToChildTop - margin
|
33
|
-
});
|
34
|
-
} else if (isChildBottomBelowViewingArea) {
|
35
|
-
const scrollHeightToChildBottom = childBottom - containerBottom + container.scrollTop;
|
36
|
-
container.scrollTo({
|
37
|
-
behavior,
|
38
|
-
top: scrollHeightToChildBottom + margin
|
39
|
-
});
|
40
|
-
} // either completely in view or outside viewing area on both ends, don't scroll
|
41
|
-
|
42
|
-
}
|
43
|
-
|
15
|
+
import { scrollIntoViewingArea } from '../behaviors/scrollIntoViewingArea';
|
44
16
|
const StyledHeader = styled.div.withConfig({
|
45
17
|
displayName: "FilteredActionList__StyledHeader",
|
46
18
|
componentId: "yg3jkv-0"
|
@@ -95,7 +67,7 @@ export function FilteredActionList({
|
|
95
67
|
useEffect(() => {
|
96
68
|
// if items changed, we want to instantly move active descendant into view
|
97
69
|
if (activeDescendantRef.current && scrollContainerRef.current) {
|
98
|
-
scrollIntoViewingArea(activeDescendantRef.current, scrollContainerRef.current, undefined, 'auto');
|
70
|
+
scrollIntoViewingArea(activeDescendantRef.current, scrollContainerRef.current, 'vertical', undefined, undefined, 'auto');
|
99
71
|
}
|
100
72
|
}, [items]);
|
101
73
|
useScrollFlash(scrollContainerRef);
|
package/lib-esm/Flash.js
CHANGED
@@ -5,35 +5,35 @@ import sx from './sx';
|
|
5
5
|
const variants = variant({
|
6
6
|
variants: {
|
7
7
|
default: {
|
8
|
-
color: '
|
9
|
-
backgroundColor: '
|
10
|
-
borderColor: '
|
8
|
+
color: 'fg.default',
|
9
|
+
backgroundColor: 'accent.subtle',
|
10
|
+
borderColor: 'accent.muted',
|
11
11
|
svg: {
|
12
|
-
color: '
|
12
|
+
color: 'accent.fg'
|
13
13
|
}
|
14
14
|
},
|
15
15
|
success: {
|
16
|
-
color: '
|
17
|
-
backgroundColor: '
|
18
|
-
borderColor: '
|
16
|
+
color: 'fg.default',
|
17
|
+
backgroundColor: 'success.subtle',
|
18
|
+
borderColor: 'success.muted',
|
19
19
|
svg: {
|
20
|
-
color: '
|
20
|
+
color: 'success.fg'
|
21
21
|
}
|
22
22
|
},
|
23
23
|
danger: {
|
24
|
-
color: '
|
25
|
-
backgroundColor: '
|
26
|
-
borderColor: '
|
24
|
+
color: 'fg.default',
|
25
|
+
backgroundColor: 'danger.subtle',
|
26
|
+
borderColor: 'danger.muted',
|
27
27
|
svg: {
|
28
|
-
color: '
|
28
|
+
color: 'danger.fg'
|
29
29
|
}
|
30
30
|
},
|
31
31
|
warning: {
|
32
|
-
color: '
|
33
|
-
backgroundColor: '
|
34
|
-
borderColor: '
|
32
|
+
color: 'fg.default',
|
33
|
+
backgroundColor: 'attention.subtle',
|
34
|
+
borderColor: 'attention.muted',
|
35
35
|
svg: {
|
36
|
-
color: '
|
36
|
+
color: 'attention.fg'
|
37
37
|
}
|
38
38
|
}
|
39
39
|
}
|
package/lib-esm/Label.js
CHANGED
@@ -33,7 +33,7 @@ const Label = styled.span.withConfig({
|
|
33
33
|
componentId: "sc-1t3ykp0-0"
|
34
34
|
})(["display:inline-block;font-weight:", ";color:", ";border-radius:", ";&:hover{text-decoration:none;}", " ", " ", " ", " ", ""], get('fontWeights.semibold'), get('colors.fg.onEmphasis'), get('radii.3'), sizeVariant, COMMON, props => props.dropshadow ? 'box-shadow: inset 0 -1px 0 rgba(27, 31, 35, 0.12)' : '', props => props.outline ? outlineStyles : '', sx);
|
35
35
|
Label.defaultProps = {
|
36
|
-
bg: '
|
36
|
+
bg: 'neutral.emphasis',
|
37
37
|
variant: 'medium'
|
38
38
|
};
|
39
39
|
export default Label;
|
package/lib-esm/Overlay.d.ts
CHANGED
@@ -40,6 +40,7 @@ export declare type OverlayProps = {
|
|
40
40
|
top: number;
|
41
41
|
left: number;
|
42
42
|
portalContainerName?: string;
|
43
|
+
preventFocusOnOpen?: boolean;
|
43
44
|
} & Omit<ComponentProps<typeof StyledOverlay>, 'visibility' | keyof SystemPositionProps>;
|
44
45
|
/**
|
45
46
|
* An `Overlay` is a flexible floating surface, used to display transient content such as menus,
|
package/lib-esm/Overlay.js
CHANGED
@@ -92,6 +92,7 @@ const Overlay = /*#__PURE__*/React.forwardRef(({
|
|
92
92
|
left,
|
93
93
|
anchorSide,
|
94
94
|
portalContainerName,
|
95
|
+
preventFocusOnOpen,
|
95
96
|
...rest
|
96
97
|
}, forwardedRef) => {
|
97
98
|
const overlayRef = useRef(null);
|
@@ -107,7 +108,8 @@ const Overlay = /*#__PURE__*/React.forwardRef(({
|
|
107
108
|
onEscape,
|
108
109
|
ignoreClickRefs,
|
109
110
|
onClickOutside,
|
110
|
-
initialFocusRef
|
111
|
+
initialFocusRef,
|
112
|
+
preventFocusOnOpen
|
111
113
|
});
|
112
114
|
useEffect(() => {
|
113
115
|
var _combinedRef$current;
|
package/lib-esm/ProgressBar.js
CHANGED
package/lib-esm/StateLabel.js
CHANGED
@@ -19,34 +19,28 @@ const colorVariants = variant({
|
|
19
19
|
prop: 'status',
|
20
20
|
variants: {
|
21
21
|
issueClosed: {
|
22
|
-
backgroundColor: '
|
23
|
-
color: '
|
24
|
-
borderColor: 'prState.closed.border'
|
22
|
+
backgroundColor: 'danger.emphasis',
|
23
|
+
color: 'fg.onEmphasis'
|
25
24
|
},
|
26
25
|
pullClosed: {
|
27
|
-
backgroundColor: '
|
28
|
-
color: '
|
29
|
-
borderColor: 'prState.closed.border'
|
26
|
+
backgroundColor: 'danger.emphasis',
|
27
|
+
color: 'fg.onEmphasis'
|
30
28
|
},
|
31
29
|
pullMerged: {
|
32
|
-
backgroundColor: '
|
33
|
-
color: '
|
34
|
-
borderColor: 'prState.merged.border'
|
30
|
+
backgroundColor: 'done.emphasis',
|
31
|
+
color: 'fg.onEmphasis'
|
35
32
|
},
|
36
33
|
issueOpened: {
|
37
|
-
backgroundColor: '
|
38
|
-
color: '
|
39
|
-
borderColor: 'prState.open.border'
|
34
|
+
backgroundColor: 'success.emphasis',
|
35
|
+
color: 'fg.onEmphasis'
|
40
36
|
},
|
41
37
|
pullOpened: {
|
42
|
-
backgroundColor: '
|
43
|
-
color: '
|
44
|
-
borderColor: 'prState.open.border'
|
38
|
+
backgroundColor: 'success.emphasis',
|
39
|
+
color: 'fg.onEmphasis'
|
45
40
|
},
|
46
41
|
draft: {
|
47
|
-
backgroundColor: '
|
48
|
-
color: '
|
49
|
-
borderColor: 'prState.draft.border'
|
42
|
+
backgroundColor: 'neutral.emphasis',
|
43
|
+
color: 'fg.onEmphasis'
|
50
44
|
}
|
51
45
|
}
|
52
46
|
});
|
@@ -68,7 +62,7 @@ const sizeVariants = variant({
|
|
68
62
|
const StateLabelBase = styled.span.withConfig({
|
69
63
|
displayName: "StateLabel__StateLabelBase",
|
70
64
|
componentId: "k4pd9e-0"
|
71
|
-
})(["display:inline-flex;align-items:center;font-weight:", ";line-height:16px;color:", ";text-align:center;border-radius:", ";
|
65
|
+
})(["display:inline-flex;align-items:center;font-weight:", ";line-height:16px;color:", ";text-align:center;border-radius:", ";", ";", ";", ";", ";"], get('fontWeights.bold'), get('colors.canvas.default'), get('radii.3'), colorVariants, sizeVariants, COMMON, sx);
|
72
66
|
|
73
67
|
function StateLabel({
|
74
68
|
children,
|
@@ -34,7 +34,7 @@ const getTokenButtonIconSize = size => parseInt(tokenSizes[size || defaultTokenS
|
|
34
34
|
const StyledTokenButton = styled.span.withConfig({
|
35
35
|
displayName: "_RemoveTokenButton__StyledTokenButton",
|
36
36
|
componentId: "sc-14lvcw1-0"
|
37
|
-
})(["background-color:transparent;font-family:inherit;color:currentColor;cursor:pointer;display:inline-flex;justify-content:center;align-items:center;user-select:none;appearance:none;text-decoration:none;padding:0;transform:", ";align-self:baseline;border:0;border-radius:999px;&:hover,&:focus{background-color:", ";}&:active{background-color:", ";}", " ", ""], props => `translate(${props.borderOffset}px, -${props.borderOffset}px)`, get('colors.
|
37
|
+
})(["background-color:transparent;font-family:inherit;color:currentColor;cursor:pointer;display:inline-flex;justify-content:center;align-items:center;user-select:none;appearance:none;text-decoration:none;padding:0;transform:", ";align-self:baseline;border:0;border-radius:999px;&:hover,&:focus{background-color:", ";}&:active{background-color:", ";}", " ", ""], props => `translate(${props.borderOffset}px, -${props.borderOffset}px)`, get('colors.neutral.muted'), get('colors.neutral.subtle'), variants, sx);
|
38
38
|
|
39
39
|
const RemoveTokenButton = ({
|
40
40
|
'aria-label': ariaLabel,
|
@@ -0,0 +1 @@
|
|
1
|
+
import 'babel-polyfill';
|