@teamturing/react-kit 2.12.0 → 2.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/dist/core/Overlay/index.d.ts +18 -0
  2. package/dist/core/OverlayPopper/index.d.ts +16 -0
  3. package/dist/core/Pagination/index.d.ts +327 -0
  4. package/dist/core/Pill/index.d.ts +47 -0
  5. package/dist/hook/useFocusTrap.d.ts +13 -0
  6. package/dist/hook/useFocusZone.d.ts +15 -0
  7. package/dist/index.d.ts +12 -0
  8. package/dist/index.js +3323 -581
  9. package/esm/core/Dialog/index.js +8 -36
  10. package/esm/core/Overlay/index.js +92 -0
  11. package/esm/core/OverlayPopper/index.js +69 -0
  12. package/esm/core/Pagination/index.js +273 -0
  13. package/esm/core/Pill/index.js +129 -0
  14. package/esm/hook/useFocusTrap.js +39 -0
  15. package/esm/hook/useFocusZone.js +35 -0
  16. package/esm/index.js +8 -0
  17. package/esm/node_modules/@floating-ui/core/dist/floating-ui.core.js +475 -0
  18. package/esm/node_modules/@floating-ui/dom/dist/floating-ui.dom.js +599 -0
  19. package/esm/node_modules/@floating-ui/react-dom/dist/floating-ui.react-dom.js +229 -0
  20. package/esm/node_modules/@floating-ui/utils/dist/floating-ui.utils.js +121 -0
  21. package/esm/node_modules/@floating-ui/utils/dom/dist/floating-ui.utils.dom.js +128 -0
  22. package/esm/node_modules/@primer/behaviors/dist/esm/focus-trap.js +105 -0
  23. package/esm/node_modules/@primer/behaviors/dist/esm/focus-zone.js +436 -0
  24. package/esm/node_modules/@primer/behaviors/dist/esm/polyfills/event-listener-signal.js +38 -0
  25. package/esm/node_modules/@primer/behaviors/dist/esm/utils/iterate-focusable-elements.js +65 -0
  26. package/esm/node_modules/@primer/behaviors/dist/esm/utils/unique-id.js +6 -0
  27. package/esm/node_modules/@primer/behaviors/dist/esm/utils/user-agent.js +9 -0
  28. package/esm/packages/utils/esm/noop.js +6 -0
  29. package/package.json +5 -2
@@ -6,19 +6,13 @@ import '../../packages/token-studio/esm/token/typography/index.js';
6
6
  import styled from 'styled-components';
7
7
  import IconButton from '../IconButton/index.js';
8
8
  import View from '../View/index.js';
9
+ import useFocusTrap from '../../hook/useFocusTrap.js';
9
10
  import { sx } from '../../utils/styled-system/index.js';
10
11
  import MotionView from '../MotionView/index.js';
11
12
  import { j as jsxRuntimeExports } from '../../node_modules/react/jsx-runtime.js';
12
13
  import { AnimatePresence } from '../../node_modules/framer-motion/dist/es/components/AnimatePresence/index.js';
13
14
  import { cubicBezier } from '../../node_modules/framer-motion/dist/es/easing/cubic-bezier.js';
14
15
 
15
- function visible(el) {
16
- return !el.hidden && (!el.type || el.type !== 'hidden') && (el.offsetWidth > 0 || el.offsetHeight > 0);
17
- }
18
- function focusable(el) {
19
- const inputEl = el;
20
- return inputEl.tabIndex >= 0 && !inputEl.disabled && visible(inputEl);
21
- }
22
16
  const Dialog = ({
23
17
  children,
24
18
  isOpen,
@@ -38,41 +32,19 @@ const Dialog = ({
38
32
  handleDismiss?.();
39
33
  }
40
34
  }, [handleDismiss, dialogRef, overlayRef]);
41
- const getFocusableItem = useCallback((e, movement) => {
42
- if (dialogRef.current) {
43
- const items = Array.from(dialogRef.current.querySelectorAll('*')).filter(focusable);
44
- if (items.length === 0) return;
45
- e.preventDefault();
46
- const focusedElement = document.activeElement;
47
- if (!focusedElement) {
48
- return;
49
- }
50
- const index = items.indexOf(focusedElement);
51
- const offsetIndex = index + movement;
52
- const fallbackIndex = movement === 1 ? 0 : items.length - 1;
53
- const focusableItem = items[offsetIndex] || items[fallbackIndex];
54
- return focusableItem;
55
- }
56
- }, [dialogRef]);
57
- const handleTab = useCallback(e => {
58
- const movement = e.shiftKey ? -1 : 1;
59
- const focusableItem = getFocusableItem(e, movement);
60
- if (!focusableItem) {
61
- return;
62
- }
63
- focusableItem.focus();
64
- }, [getFocusableItem]);
65
35
  const handleKeyDown = useCallback(event => {
66
36
  switch (event.key) {
67
- case 'Tab':
68
- handleTab(event);
69
- break;
70
37
  case 'Escape':
71
38
  handleDismiss?.();
72
39
  event.stopPropagation();
73
40
  break;
74
41
  }
75
42
  }, [handleDismiss]);
43
+ useFocusTrap({
44
+ containerRef: dialogRef,
45
+ initialFocusRef: closeButtonRef,
46
+ disabled: !isOpen
47
+ });
76
48
  useEffect(() => {
77
49
  if (isOpen) {
78
50
  document.addEventListener('click', handleOutsideClick);
@@ -118,7 +90,7 @@ const Dialog = ({
118
90
  height: '100%',
119
91
  zIndex: 9999
120
92
  },
121
- children: [/*#__PURE__*/jsxRuntimeExports.jsx(Overlay, {
93
+ children: [/*#__PURE__*/jsxRuntimeExports.jsx(Blanket, {
122
94
  ref: overlayRef
123
95
  }), /*#__PURE__*/jsxRuntimeExports.jsxs(BaseDialog, {
124
96
  ref: dialogRef,
@@ -162,7 +134,7 @@ const Dialog = ({
162
134
  }) : null
163
135
  });
164
136
  };
165
- const Overlay = styled.span`
137
+ const Blanket = styled.span`
166
138
  &:before {
167
139
  position: fixed;
168
140
  top: 0;
@@ -0,0 +1,92 @@
1
+ import { forwardRef, useRef, useImperativeHandle, useCallback, useEffect } from 'react';
2
+ import styled from 'styled-components';
3
+ import '../../node_modules/styled-system/dist/index.esm.js';
4
+ import { forcePixelValue } from '../../utils/forcePixelValue.js';
5
+ import { sx } from '../../utils/styled-system/index.js';
6
+ import { j as jsxRuntimeExports } from '../../node_modules/react/jsx-runtime.js';
7
+ import { variant } from '../../node_modules/@styled-system/variant/dist/index.esm.js';
8
+ import { iterateFocusableElements } from '../../node_modules/@primer/behaviors/dist/esm/utils/iterate-focusable-elements.js';
9
+
10
+ const Overlay = ({
11
+ children,
12
+ isOpen,
13
+ onDismiss,
14
+ size = 'm',
15
+ ignoreOutsideClickRefs = [],
16
+ ...props
17
+ }, ref) => {
18
+ const overlayRef = useRef(null);
19
+ useImperativeHandle(ref, () => overlayRef.current);
20
+ const handleDismiss = useCallback(() => onDismiss?.(), [onDismiss]);
21
+ const handleOutsideClick = useCallback(e => {
22
+ if (overlayRef.current && e.target instanceof Node && !overlayRef.current.contains(e.target) && ignoreOutsideClickRefs && !ignoreOutsideClickRefs.some(({
23
+ current
24
+ }) => current?.contains(e.target))) {
25
+ handleDismiss?.();
26
+ }
27
+ }, [handleDismiss, overlayRef]);
28
+ const handleKeyDown = useCallback(event => {
29
+ switch (event.key) {
30
+ case 'Escape':
31
+ handleDismiss?.();
32
+ event.stopPropagation();
33
+ break;
34
+ }
35
+ }, [handleDismiss]);
36
+ useEffect(() => {
37
+ if (overlayRef.current) {
38
+ const firstItem = iterateFocusableElements(overlayRef.current).next().value;
39
+ firstItem?.focus();
40
+ }
41
+ }, [isOpen]);
42
+ useEffect(() => {
43
+ if (isOpen) {
44
+ document.addEventListener('keydown', handleKeyDown);
45
+ return () => {
46
+ document.removeEventListener('keydown', handleKeyDown);
47
+ };
48
+ }
49
+ }, [isOpen, handleKeyDown]);
50
+ useEffect(() => {
51
+ if (isOpen) {
52
+ document.addEventListener('click', handleOutsideClick);
53
+ return () => {
54
+ document.removeEventListener('click', handleOutsideClick);
55
+ };
56
+ }
57
+ }, [isOpen, handleOutsideClick]);
58
+ return isOpen ? /*#__PURE__*/jsxRuntimeExports.jsx(BaseOverlay, {
59
+ ref: overlayRef,
60
+ size: size,
61
+ ...props,
62
+ children: children
63
+ }) : null;
64
+ };
65
+ const BaseOverlay = styled.div`
66
+ position: absolute;
67
+ box-shadow: ${({
68
+ theme
69
+ }) => theme.shadows['shadow/overlay']};
70
+ background-color: ${({
71
+ theme
72
+ }) => theme.colors['surface/overlay']};
73
+ border-radius: ${({
74
+ theme
75
+ }) => forcePixelValue(theme.radii.s)};
76
+ overflow: hidden;
77
+ margin: auto;
78
+ z-index: 99999;
79
+
80
+ ${variant({
81
+ prop: 'size',
82
+ variants: {
83
+ m: {
84
+ width: forcePixelValue(180)
85
+ }
86
+ }
87
+ })}
88
+ ${sx}
89
+ `;
90
+ var Overlay$1 = /*#__PURE__*/forwardRef(Overlay);
91
+
92
+ export { Overlay$1 as default };
@@ -0,0 +1,69 @@
1
+ import { useFloating } from '../../node_modules/@floating-ui/react-dom/dist/floating-ui.react-dom.js';
2
+ import space from '../../packages/token-studio/esm/token/space/index.js';
3
+ import '../../packages/token-studio/esm/token/typography/index.js';
4
+ import { Children, cloneElement } from 'react';
5
+ import useFocusTrap from '../../hook/useFocusTrap.js';
6
+ import useFocusZone from '../../hook/useFocusZone.js';
7
+ import useToggleHandler from '../../hook/useToggleHandler.js';
8
+ import Overlay from '../Overlay/index.js';
9
+ import { j as jsxRuntimeExports } from '../../node_modules/react/jsx-runtime.js';
10
+ import { autoUpdate } from '../../node_modules/@floating-ui/dom/dist/floating-ui.dom.js';
11
+ import { offset, flip, shift } from '../../node_modules/@floating-ui/core/dist/floating-ui.core.js';
12
+
13
+ const OverlayPopper = ({
14
+ children: propChildren,
15
+ renderOverlay,
16
+ placement = 'bottom-start',
17
+ focusZoneSettings,
18
+ focusTrapSettings
19
+ }) => {
20
+ const {
21
+ refs,
22
+ floatingStyles,
23
+ isPositioned
24
+ } = useFloating({
25
+ placement,
26
+ whileElementsMounted: autoUpdate,
27
+ middleware: [offset(space[1]), flip(), shift()],
28
+ strategy: 'fixed'
29
+ });
30
+ const {
31
+ state: isOpen,
32
+ toggle: toggleOverlay,
33
+ off: closeOverlay
34
+ } = useToggleHandler({
35
+ initialState: false
36
+ });
37
+ const children = Children.map(propChildren, child => /*#__PURE__*/cloneElement(child, {
38
+ onClick: toggleOverlay,
39
+ tabIndex: 0,
40
+ ...{
41
+ ref: refs.setReference
42
+ }
43
+ }));
44
+ useFocusZone({
45
+ containerRef: refs.floating,
46
+ disabled: !isOpen || !isPositioned,
47
+ ...focusZoneSettings
48
+ });
49
+ useFocusTrap({
50
+ containerRef: refs.floating,
51
+ disabled: !isOpen || !isPositioned,
52
+ ...focusTrapSettings
53
+ });
54
+ return /*#__PURE__*/jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, {
55
+ children: [children, /*#__PURE__*/jsxRuntimeExports.jsx(Overlay, {
56
+ ref: refs.setFloating,
57
+ isOpen: isOpen,
58
+ onDismiss: closeOverlay,
59
+ ignoreOutsideClickRefs: [refs.reference],
60
+ style: floatingStyles,
61
+ children: renderOverlay({
62
+ isOpen,
63
+ closeOverlay
64
+ })
65
+ })]
66
+ });
67
+ };
68
+
69
+ export { OverlayPopper as default };
@@ -0,0 +1,273 @@
1
+ import { useCallback, Fragment } from 'react';
2
+ import SvgChevronLeft from '../../packages/icons/esm/ChevronLeft.js';
3
+ import SvgChevronRight from '../../packages/icons/esm/ChevronRight.js';
4
+ import { noop } from '../../packages/utils/esm/noop.js';
5
+ import styled, { css } from 'styled-components';
6
+ import '../../node_modules/styled-system/dist/index.esm.js';
7
+ import { forcePixelValue } from '../../utils/forcePixelValue.js';
8
+ import { sx } from '../../utils/styled-system/index.js';
9
+ import UnstyledButton from '../_UnstyledButton.js';
10
+ import { j as jsxRuntimeExports } from '../../node_modules/react/jsx-runtime.js';
11
+ import { variant } from '../../node_modules/@styled-system/variant/dist/index.esm.js';
12
+
13
+ const Pagination = ({
14
+ pages: propPages,
15
+ currentPageIndex,
16
+ aroundPageCount = 1,
17
+ edgePageCount = 1,
18
+ type = 'default',
19
+ sx,
20
+ onPageClick = noop,
21
+ onPreviousClick = noop,
22
+ onNextClick = noop,
23
+ renderPage = (page, i) => /*#__PURE__*/jsxRuntimeExports.jsx(PaginationPage, {
24
+ onClick: () => onPageClick(page, i),
25
+ selected: i === currentPageIndex,
26
+ children: page.label
27
+ }),
28
+ renderPageWrapper = (children, {
29
+ label
30
+ }, i) => /*#__PURE__*/jsxRuntimeExports.jsx(Fragment, {
31
+ children: children
32
+ }, [label, i].join('-')),
33
+ renderPreviousPageDirection = ({
34
+ previousPageDirectionProps
35
+ }) => /*#__PURE__*/jsxRuntimeExports.jsxs(PaginationPageDirection, {
36
+ ...previousPageDirectionProps,
37
+ children: [/*#__PURE__*/jsxRuntimeExports.jsx(SvgChevronLeft, {}), "\uC774\uC804"]
38
+ }),
39
+ renderNextPageDirection = ({
40
+ nextPageDirectionProps
41
+ }) => /*#__PURE__*/jsxRuntimeExports.jsxs(PaginationPageDirection, {
42
+ ...nextPageDirectionProps,
43
+ children: ["\uB2E4\uC74C", /*#__PURE__*/jsxRuntimeExports.jsx(SvgChevronRight, {})]
44
+ }),
45
+ renderTruncationIndicator = () => /*#__PURE__*/jsxRuntimeExports.jsx(PaginationTruncationIndicator, {
46
+ children: "\u2026"
47
+ })
48
+ }) => {
49
+ const CURRENT_PAGE_COUNT = 1;
50
+ const totalVisiblePageCount = CURRENT_PAGE_COUNT + 2 * aroundPageCount + 2 * edgePageCount;
51
+ const pages = propPages.map((page, i) => ({
52
+ page,
53
+ originalIndex: i
54
+ }));
55
+ const totalPageCount = propPages.length;
56
+ const isCurrentPageCloseToBeginEdge = currentPageIndex < edgePageCount + aroundPageCount + CURRENT_PAGE_COUNT;
57
+ const isCurrentPageCloseToEndEdge = totalPageCount - (edgePageCount + aroundPageCount + CURRENT_PAGE_COUNT) < currentPageIndex + 1;
58
+ const isTruncationNeeded = totalVisiblePageCount < totalPageCount;
59
+ const renderPaginationPage = useCallback((page, i) => renderPageWrapper(renderPage(page, i), page, i), [currentPageIndex]);
60
+ return /*#__PURE__*/jsxRuntimeExports.jsxs(BasePagination, {
61
+ type: type,
62
+ sx: sx,
63
+ children: [renderPreviousPageDirection({
64
+ previousPageDirectionProps: {
65
+ onClick: () => onPreviousClick(currentPageIndex),
66
+ disabled: currentPageIndex === 0
67
+ }
68
+ }), !isTruncationNeeded ? pages.map(({
69
+ page,
70
+ originalIndex
71
+ }) => renderPaginationPage(page, originalIndex)) : isTruncationNeeded && isCurrentPageCloseToBeginEdge ? [pages.slice(0, edgePageCount + aroundPageCount * 2 + CURRENT_PAGE_COUNT).map(({
72
+ page,
73
+ originalIndex
74
+ }) => renderPaginationPage(page, originalIndex)), /*#__PURE__*/jsxRuntimeExports.jsx(Fragment, {
75
+ children: renderTruncationIndicator()
76
+ }, 'end_truncation_indicator'), pages.slice(edgePageCount * -1).map(({
77
+ page,
78
+ originalIndex
79
+ }) => renderPaginationPage(page, originalIndex))] : isTruncationNeeded && isCurrentPageCloseToEndEdge ? [pages.slice(0, edgePageCount).map(({
80
+ page,
81
+ originalIndex
82
+ }) => renderPaginationPage(page, originalIndex)), /*#__PURE__*/jsxRuntimeExports.jsx(Fragment, {
83
+ children: renderTruncationIndicator()
84
+ }, 'begin_truncation_indicator'), pages.slice(totalPageCount - (edgePageCount + aroundPageCount * 2 + CURRENT_PAGE_COUNT)).map(({
85
+ page,
86
+ originalIndex
87
+ }) => renderPaginationPage(page, originalIndex))] : [pages.slice(0, edgePageCount).map(({
88
+ page,
89
+ originalIndex
90
+ }) => renderPaginationPage(page, originalIndex)), /*#__PURE__*/jsxRuntimeExports.jsx(Fragment, {
91
+ children: renderTruncationIndicator()
92
+ }, 'begin_truncation_indicator'), pages.slice(currentPageIndex - aroundPageCount, currentPageIndex + aroundPageCount + CURRENT_PAGE_COUNT).map(({
93
+ page,
94
+ originalIndex
95
+ }) => renderPaginationPage(page, originalIndex)), /*#__PURE__*/jsxRuntimeExports.jsx(Fragment, {
96
+ children: renderTruncationIndicator()
97
+ }, 'end_truncation_indicator'), pages.slice(edgePageCount * -1).map(({
98
+ page,
99
+ originalIndex
100
+ }) => renderPaginationPage(page, originalIndex))], renderNextPageDirection({
101
+ nextPageDirectionProps: {
102
+ onClick: () => onNextClick(currentPageIndex),
103
+ disabled: currentPageIndex === totalPageCount - 1
104
+ }
105
+ })]
106
+ });
107
+ };
108
+ const BasePagination = styled.nav`
109
+ display: flex;
110
+ align-items: center;
111
+ justify-content: center;
112
+ flex-wrap: nowrap;
113
+ column-gap: ${({
114
+ theme
115
+ }) => forcePixelValue(theme.space[1])};
116
+
117
+ ${variant({
118
+ prop: 'type',
119
+ variants: {
120
+ default: {},
121
+ simple: {
122
+ '& > *:not(:first-child):not(:last-child)': {
123
+ display: 'none !important'
124
+ }
125
+ }
126
+ }
127
+ })}
128
+ ${sx}
129
+ `;
130
+ const PaginationPage = styled(UnstyledButton)`
131
+ transition: background-color 100ms;
132
+
133
+ height: ${forcePixelValue(32)};
134
+ min-width: ${forcePixelValue(32)};
135
+
136
+ border-radius: ${({
137
+ theme
138
+ }) => forcePixelValue(theme.radii.xs)};
139
+ padding: ${({
140
+ theme
141
+ }) => `${forcePixelValue(theme.space[0])} ${forcePixelValue(theme.space[3])}`};
142
+ background-color: ${({
143
+ theme
144
+ }) => theme.colors['bg/neutral/subtler']};
145
+
146
+ font-size: ${({
147
+ theme
148
+ }) => forcePixelValue(theme.fontSizes.xs)};
149
+ font-weight: ${({
150
+ theme
151
+ }) => theme.fontWeights.regular};
152
+ line-height: ${({
153
+ theme
154
+ }) => theme.lineHeights[2]};
155
+ color: ${({
156
+ theme
157
+ }) => theme.colors['text/neutral']};
158
+
159
+ ${({
160
+ selected
161
+ }) => selected ? css`
162
+ background-color: ${({
163
+ theme
164
+ }) => theme.colors['bg/neutral/bolder']};
165
+ color: ${({
166
+ theme
167
+ }) => theme.colors['text/inverse']};
168
+ ` : css`
169
+ &:hover {
170
+ background-color: ${({
171
+ theme
172
+ }) => theme.colors['bg/neutral/subtler/hovered']};
173
+ }
174
+ `}
175
+ `;
176
+ const PaginationPageDirection = styled(UnstyledButton)`
177
+ transition: background-color 100ms;
178
+
179
+ display: inline-flex;
180
+ align-items: center;
181
+ flex-wrap: nowrap;
182
+ column-gap: ${({
183
+ theme
184
+ }) => forcePixelValue(theme.space[1])};
185
+
186
+ height: ${forcePixelValue(32)};
187
+ min-width: ${forcePixelValue(32)};
188
+
189
+ border-radius: ${({
190
+ theme
191
+ }) => forcePixelValue(theme.radii.xs)};
192
+ padding: ${({
193
+ theme
194
+ }) => `${forcePixelValue(theme.space[0])} ${forcePixelValue(theme.space[3])}`};
195
+ background-color: ${({
196
+ theme
197
+ }) => theme.colors['bg/neutral/subtler']};
198
+
199
+ font-size: ${({
200
+ theme
201
+ }) => forcePixelValue(theme.fontSizes.xs)};
202
+ font-weight: ${({
203
+ theme
204
+ }) => theme.fontWeights.regular};
205
+ line-height: ${({
206
+ theme
207
+ }) => theme.lineHeights[2]};
208
+ color: ${({
209
+ theme
210
+ }) => theme.colors['text/neutral']};
211
+
212
+ & svg {
213
+ color: ${({
214
+ theme
215
+ }) => theme.colors['icon/accent/gray']};
216
+ width: ${forcePixelValue(16)};
217
+ height: ${forcePixelValue(16)};
218
+ }
219
+
220
+ &:hover:not(:disabled) {
221
+ background-color: ${({
222
+ theme
223
+ }) => theme.colors['bg/neutral/subtler/hovered']};
224
+ }
225
+ &:disabled {
226
+ cursor: not-allowed;
227
+ color: ${({
228
+ theme
229
+ }) => theme.colors['text/disabled']};
230
+ & > svg {
231
+ color: ${({
232
+ theme
233
+ }) => theme.colors['icon/disabled']};
234
+ }
235
+ }
236
+ `;
237
+ const PaginationTruncationIndicator = styled.div`
238
+ min-width: ${forcePixelValue(32)};
239
+
240
+ border-radius: ${({
241
+ theme
242
+ }) => forcePixelValue(theme.radii.xs)};
243
+ padding: ${({
244
+ theme
245
+ }) => `${forcePixelValue(theme.space[0])} ${forcePixelValue(theme.space[3])}`};
246
+ background-color: ${({
247
+ theme
248
+ }) => theme.colors['bg/neutral/subtler']};
249
+
250
+ font-size: ${({
251
+ theme
252
+ }) => forcePixelValue(theme.fontSizes.xs)};
253
+ font-weight: ${({
254
+ theme
255
+ }) => theme.fontWeights.regular};
256
+ line-height: ${({
257
+ theme
258
+ }) => theme.lineHeights[2]};
259
+ color: ${({
260
+ theme
261
+ }) => theme.colors['text/neutral']};
262
+
263
+ pointer-events: none;
264
+
265
+ ${sx}
266
+ `;
267
+ var index = Object.assign(Pagination, {
268
+ Page: PaginationPage,
269
+ PageDirection: PaginationPageDirection,
270
+ TruncationIndicator: PaginationTruncationIndicator
271
+ });
272
+
273
+ export { index as default };
@@ -0,0 +1,129 @@
1
+ import { forwardRef } from 'react';
2
+ import SvgClose from '../../packages/icons/esm/Close.js';
3
+ import { r as reactIsExports } from '../../node_modules/react-is/index.js';
4
+ import styled from 'styled-components';
5
+ import '../../node_modules/styled-system/dist/index.esm.js';
6
+ import { forcePixelValue } from '../../utils/forcePixelValue.js';
7
+ import { isNullable } from '../../utils/isNullable.js';
8
+ import { sx } from '../../utils/styled-system/index.js';
9
+ import UnstyledButton from '../_UnstyledButton.js';
10
+ import { j as jsxRuntimeExports } from '../../node_modules/react/jsx-runtime.js';
11
+ import { variant } from '../../node_modules/@styled-system/variant/dist/index.esm.js';
12
+
13
+ const Pill = ({
14
+ text,
15
+ size = 'm',
16
+ variant = 'secondary',
17
+ leadingVisual: LeadingVisual,
18
+ onRemove,
19
+ ...props
20
+ }, ref) => /*#__PURE__*/jsxRuntimeExports.jsxs(BasePill, {
21
+ ref: ref,
22
+ size: size,
23
+ variant: variant,
24
+ hasLeadingVisual: !isNullable(LeadingVisual),
25
+ hasRemoveButton: !isNullable(onRemove),
26
+ ...props,
27
+ children: [typeof LeadingVisual !== 'string' && reactIsExports.isValidElementType(LeadingVisual) ? /*#__PURE__*/jsxRuntimeExports.jsx(LeadingVisual, {}) : LeadingVisual, text, onRemove ? /*#__PURE__*/jsxRuntimeExports.jsx(UnstyledButton, {
28
+ type: 'button',
29
+ onClick: onRemove,
30
+ "aria-label": 'Remove Pill',
31
+ children: /*#__PURE__*/jsxRuntimeExports.jsx(SvgClose, {})
32
+ }) : null]
33
+ });
34
+ const BasePill = styled.span`
35
+ display: inline-flex;
36
+ align-items: center;
37
+ border-radius: ${({
38
+ theme
39
+ }) => forcePixelValue(theme.radii.xxs)};
40
+
41
+ & > button {
42
+ display: flex;
43
+ transition: background-color 100ms;
44
+ border-radius: ${({
45
+ theme
46
+ }) => forcePixelValue(theme.radii.full)};
47
+ }
48
+
49
+ ${({
50
+ theme,
51
+ hasLeadingVisual,
52
+ hasRemoveButton
53
+ }) => variant({
54
+ prop: 'size',
55
+ variants: {
56
+ l: {
57
+ 'pl': hasLeadingVisual || hasRemoveButton ? 2 : 3,
58
+ 'pr': hasRemoveButton ? 0.5 : hasLeadingVisual ? 2 : 3,
59
+ 'py': 1,
60
+ 'fontSize': theme.fontSizes.s,
61
+ 'fontWeight': theme.fontWeights.medium,
62
+ 'lineHeight': theme.lineHeights[2],
63
+ 'columnGap': 1,
64
+ '& svg': {
65
+ width: 16,
66
+ height: 16,
67
+ color: theme.colors['icon/primary']
68
+ },
69
+ '& button': {
70
+ p: 1
71
+ }
72
+ },
73
+ m: {
74
+ 'pl': hasLeadingVisual || hasRemoveButton ? 2 : 3,
75
+ 'pr': hasRemoveButton ? 1 : hasLeadingVisual ? 2 : 3,
76
+ 'py': 1,
77
+ 'fontSize': theme.fontSizes.xs,
78
+ 'fontWeight': theme.fontWeights.medium,
79
+ 'lineHeight': theme.lineHeights[2],
80
+ 'columnGap': 0.5,
81
+ '& svg': {
82
+ width: 16,
83
+ height: 16,
84
+ color: theme.colors['icon/primary']
85
+ },
86
+ '& button': {
87
+ p: 0.5
88
+ }
89
+ },
90
+ s: {
91
+ 'pl': 2,
92
+ 'pr': hasRemoveButton ? 1 : 2,
93
+ 'py': 0.5,
94
+ 'fontSize': theme.fontSizes.xxs,
95
+ 'fontWeight': theme.fontWeights.medium,
96
+ 'lineHeight': theme.lineHeights[2],
97
+ 'columnGap': 0.5,
98
+ '& svg': {
99
+ width: 12,
100
+ height: 12,
101
+ color: theme.colors['icon/primary']
102
+ },
103
+ '& button': {
104
+ p: 0.5
105
+ }
106
+ }
107
+ }
108
+ })}
109
+ ${({
110
+ theme
111
+ }) => variant({
112
+ prop: 'variant',
113
+ variants: {
114
+ secondary: {
115
+ 'color': theme.colors['text/primary'],
116
+ 'backgroundColor': theme.colors['bg/secondary'],
117
+ '& button': {
118
+ '&:hover': {
119
+ backgroundColor: theme.colors['bg/secondary/hovered']
120
+ }
121
+ }
122
+ }
123
+ }
124
+ })}
125
+ ${sx}
126
+ `;
127
+ var index = /*#__PURE__*/forwardRef(Pill);
128
+
129
+ export { index as default };
@@ -0,0 +1,39 @@
1
+ import React__default from 'react';
2
+ import useProvidedOrCreatedRef from './useProvidedOrCreatedRef.js';
3
+ import { focusTrap } from '../node_modules/@primer/behaviors/dist/esm/focus-trap.js';
4
+
5
+ const useFocusTrap = (settings, dependencies = []) => {
6
+ const containerRef = useProvidedOrCreatedRef(settings?.containerRef);
7
+ const initialFocusRef = useProvidedOrCreatedRef(settings?.initialFocusRef);
8
+ const disabled = settings?.disabled;
9
+ const abortController = React__default.useRef();
10
+ const previousFocusedElement = React__default.useRef(null);
11
+ if (!previousFocusedElement.current && !settings?.disabled) {
12
+ previousFocusedElement.current = document.activeElement;
13
+ }
14
+ const disableTrap = () => {
15
+ abortController.current?.abort();
16
+ if (settings?.restoreFocusOnCleanUp && previousFocusedElement.current instanceof HTMLElement) {
17
+ previousFocusedElement.current.focus();
18
+ previousFocusedElement.current = null;
19
+ }
20
+ };
21
+ React__default.useEffect(() => {
22
+ if (containerRef.current instanceof HTMLElement) {
23
+ if (!disabled) {
24
+ abortController.current = focusTrap(containerRef.current, initialFocusRef.current ?? undefined);
25
+ return () => {
26
+ disableTrap();
27
+ };
28
+ } else {
29
+ disableTrap();
30
+ }
31
+ }
32
+ }, [containerRef, initialFocusRef, disabled, ...dependencies]);
33
+ return {
34
+ containerRef,
35
+ initialFocusRef
36
+ };
37
+ };
38
+
39
+ export { useFocusTrap as default };