@sipesistemas/polaris 1.2.4 → 1.4.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 (57) hide show
  1. package/build/cjs/components/ActionList/ActionList.js +1 -1
  2. package/build/cjs/components/DropDown/DropDown.css.js +9 -0
  3. package/build/cjs/components/DropDown/DropDown.js +293 -0
  4. package/build/cjs/components/DropDown/DropDownField.js +33 -0
  5. package/build/cjs/components/Filters/components/FiltersBar/FiltersBar.js +11 -5
  6. package/build/cjs/components/IndexTable/IndexTable.css.js +8 -1
  7. package/build/cjs/components/IndexTable/IndexTable.js +59 -11
  8. package/build/cjs/components/IndexTable/components/Row/Row.js +69 -6
  9. package/build/cjs/components/Pagination/Pagination.js +6 -3
  10. package/build/cjs/index.js +2 -0
  11. package/build/cjs/utilities/index-table/context.js +2 -0
  12. package/build/esm/components/ActionList/ActionList.js +1 -1
  13. package/build/esm/components/DropDown/DropDown.css.js +5 -0
  14. package/build/esm/components/DropDown/DropDown.js +290 -0
  15. package/build/esm/components/DropDown/DropDownField.js +31 -0
  16. package/build/esm/components/Filters/components/FiltersBar/FiltersBar.js +11 -5
  17. package/build/esm/components/IndexTable/IndexTable.css.js +8 -1
  18. package/build/esm/components/IndexTable/IndexTable.js +60 -12
  19. package/build/esm/components/IndexTable/components/Row/Row.js +68 -5
  20. package/build/esm/components/Pagination/Pagination.js +7 -4
  21. package/build/esm/index.js +1 -0
  22. package/build/esm/styles.css +61 -1
  23. package/build/esm/utilities/index-table/context.js +2 -1
  24. package/build/esnext/components/ActionList/ActionList.esnext +1 -1
  25. package/build/esnext/components/AppProvider/global.out.css +1 -1
  26. package/build/esnext/components/DropDown/DropDown.css.esnext +7 -0
  27. package/build/esnext/components/DropDown/DropDown.esnext +290 -0
  28. package/build/esnext/components/DropDown/DropDown.out.css +16 -0
  29. package/build/esnext/components/DropDown/DropDownField.esnext +31 -0
  30. package/build/esnext/components/Filters/components/FiltersBar/FiltersBar.esnext +11 -5
  31. package/build/esnext/components/IndexTable/IndexTable.css.esnext +8 -1
  32. package/build/esnext/components/IndexTable/IndexTable.esnext +60 -12
  33. package/build/esnext/components/IndexTable/IndexTable.out.css +42 -0
  34. package/build/esnext/components/IndexTable/components/Row/Row.esnext +68 -5
  35. package/build/esnext/components/Pagination/Pagination.esnext +7 -4
  36. package/build/esnext/index.esnext +1 -0
  37. package/build/esnext/utilities/index-table/context.esnext +2 -1
  38. package/build/ts/.storybook/main.d.ts.map +1 -1
  39. package/build/ts/src/components/DropDown/DropDown.d.ts +101 -0
  40. package/build/ts/src/components/DropDown/DropDown.d.ts.map +1 -0
  41. package/build/ts/src/components/DropDown/DropDownField.d.ts +8 -0
  42. package/build/ts/src/components/DropDown/DropDownField.d.ts.map +1 -0
  43. package/build/ts/src/components/DropDown/index.d.ts +2 -0
  44. package/build/ts/src/components/DropDown/index.d.ts.map +1 -0
  45. package/build/ts/src/components/Filters/components/FiltersBar/FiltersBar.d.ts.map +1 -1
  46. package/build/ts/src/components/IndexTable/IndexTable.d.ts +7 -0
  47. package/build/ts/src/components/IndexTable/IndexTable.d.ts.map +1 -1
  48. package/build/ts/src/components/IndexTable/components/Row/Row.d.ts.map +1 -1
  49. package/build/ts/src/components/Pagination/Pagination.d.ts +3 -1
  50. package/build/ts/src/components/Pagination/Pagination.d.ts.map +1 -1
  51. package/build/ts/src/index.d.ts +2 -0
  52. package/build/ts/src/index.d.ts.map +1 -1
  53. package/build/ts/src/utilities/index-table/context.d.ts +10 -0
  54. package/build/ts/src/utilities/index-table/context.d.ts.map +1 -1
  55. package/locales/en.json +10 -1
  56. package/locales/pt-BR.json +10 -1
  57. package/package.json +16 -6
@@ -52,7 +52,7 @@ function ActionList({
52
52
  actionRole: actionRole,
53
53
  onActionAnyItem: onActionAnyItem,
54
54
  isFirst: index === 0
55
- }, typeof section.title === 'string' ? section.title : index) : null;
55
+ }, typeof section.title === 'string' && section.title ? section.title : index) : null;
56
56
  });
57
57
  const handleFocusPreviousItem = evt => {
58
58
  evt.preventDefault();
@@ -0,0 +1,9 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var styles = {
6
+ "Activator": "Polaris-DropDown__Activator"
7
+ };
8
+
9
+ exports.default = styles;
@@ -0,0 +1,293 @@
1
+ 'use strict';
2
+
3
+ var polarisIcons = require('@shopify/polaris-icons');
4
+ var react = require('react');
5
+ var DropDown_module = require('./DropDown.css.js');
6
+ var jsxRuntime = require('react/jsx-runtime');
7
+ var EmptySearchResult = require('../EmptySearchResult/EmptySearchResult.js');
8
+ var hooks = require('../../utilities/i18n/hooks.js');
9
+ var TextField = require('../TextField/TextField.js');
10
+ var Icon = require('../Icon/Icon.js');
11
+ var utils = require('../Button/utils.js');
12
+ var Listbox = require('../Listbox/Listbox.js');
13
+ var Popover = require('../Popover/Popover.js');
14
+ var Box = require('../Box/Box.js');
15
+ var Scrollable = require('../Scrollable/Scrollable.js');
16
+
17
+ function getValueByPath(obj, path) {
18
+ return path.split('.').reduce((acc, part) => acc?.[part], obj);
19
+ }
20
+
21
+ /** Resolves the activator text for an option, falling back to its `label` when there is no `object` */
22
+ function resolveOptionLabel(option, selectedLabelKey) {
23
+ if (!option) return '';
24
+ if (selectedLabelKey && option.object !== undefined) {
25
+ const value = getValueByPath(option.object, selectedLabelKey);
26
+ if (typeof value === 'string') return value;
27
+ }
28
+ return typeof option.label === 'string' ? option.label : '';
29
+ }
30
+ const SCROLLABLE_HEIGHT = 292;
31
+ function DropDownBase({
32
+ loading,
33
+ loadingMore,
34
+ options,
35
+ value,
36
+ onChange,
37
+ onBlur,
38
+ emptyStateTitle = '',
39
+ emptyStateDescription,
40
+ onQueryChange,
41
+ selectedLabelKey,
42
+ label,
43
+ labelHidden,
44
+ searchable = true,
45
+ placeholder,
46
+ disabled,
47
+ requiredIndicator,
48
+ helpText,
49
+ error,
50
+ allowClear,
51
+ onScrolledToBottom,
52
+ suffixAction
53
+ }) {
54
+ const i18n = hooks.useI18n();
55
+ const [query, setQuery] = react.useState('');
56
+ const [popoverActive, setPopoverActive] = react.useState(false);
57
+ const [activeOptionId, setActiveOptionId] = react.useState();
58
+ // pagination/search can drop the selected option from `options`; the cache keeps its label visible
59
+ const [cachedSelection, setCachedSelection] = react.useState(null);
60
+ // clicking the clear button bubbles to TextField's container, which focuses the input
61
+ const skipNextFocusOpen = react.useRef(false);
62
+ const listboxId = react.useId();
63
+ const selectedValue = value ?? '';
64
+ const selected = selectedValue ? [selectedValue] : [];
65
+ // when the parent does not control filtering, narrow the options by the query ourselves
66
+ const filteredOptions = react.useMemo(() => {
67
+ if (onQueryChange || !query) return options;
68
+ const needle = query.toLowerCase();
69
+ return options.filter(option => resolveOptionLabel(option, selectedLabelKey).toLowerCase().includes(needle));
70
+ }, [options, query, onQueryChange, selectedLabelKey]);
71
+ const togglePopoverActive = react.useCallback(() => {
72
+ setPopoverActive(active => !active);
73
+ setQuery('');
74
+ onQueryChange?.('');
75
+ }, [onQueryChange]);
76
+ react.useEffect(() => {
77
+ function handleEsc(event) {
78
+ if (event.key === 'Escape') setPopoverActive(false);
79
+ }
80
+ document.addEventListener('keydown', handleEsc);
81
+ return () => document.removeEventListener('keydown', handleEsc);
82
+ }, []);
83
+
84
+ // keep the cache in sync while the selected option is loaded, so its label survives (and stays
85
+ // fresh) if pagination later drops the option from `options`
86
+ react.useEffect(() => {
87
+ if (!selectedValue) return;
88
+ const loadedOption = options.find(option => option.value === selectedValue);
89
+ if (!loadedOption) return;
90
+ const label = resolveOptionLabel(loadedOption, selectedLabelKey);
91
+ if (label && (cachedSelection?.value !== selectedValue || cachedSelection.label !== label)) {
92
+ setCachedSelection({
93
+ value: selectedValue,
94
+ label
95
+ });
96
+ }
97
+ }, [selectedValue, options, selectedLabelKey, cachedSelection]);
98
+ const textSelectedItem = react.useMemo(() => {
99
+ if (!selectedValue) return '';
100
+ const selectedItem = options.find(option => option.value === selectedValue);
101
+ const resolved = resolveOptionLabel(selectedItem, selectedLabelKey);
102
+ if (resolved) return resolved;
103
+ return cachedSelection?.value === selectedValue ? cachedSelection.label : '';
104
+ }, [selectedValue, options, selectedLabelKey, cachedSelection]);
105
+ const handleSelectionClear = react.useCallback(() => {
106
+ setCachedSelection(null);
107
+ onChange?.('');
108
+ if (requiredIndicator) {
109
+ setPopoverActive(true);
110
+ } else {
111
+ skipNextFocusOpen.current = true;
112
+ }
113
+ }, [onChange, requiredIndicator]);
114
+ const handleActivatorFocus = react.useCallback(() => {
115
+ if (disabled) return;
116
+ if (skipNextFocusOpen.current) {
117
+ skipNextFocusOpen.current = false;
118
+ return;
119
+ }
120
+ setPopoverActive(true);
121
+ }, [disabled]);
122
+
123
+ // when the clear button is visible it replaces the caret, so they don't pile up
124
+ const showClearButton = Boolean(allowClear) && textSelectedItem !== '';
125
+ const activator = /*#__PURE__*/jsxRuntime.jsx("div", {
126
+ className: DropDown_module.default.Activator,
127
+ children: /*#__PURE__*/jsxRuntime.jsx(TextField.TextField, {
128
+ label: label,
129
+ labelHidden: labelHidden,
130
+ placeholder: placeholder,
131
+ autoComplete: "off",
132
+ value: textSelectedItem,
133
+ disabled: disabled,
134
+ requiredIndicator: requiredIndicator,
135
+ helpText: helpText,
136
+ error: error,
137
+ clearButton: showClearButton,
138
+ onClearButtonClick: handleSelectionClear,
139
+ onFocus: handleActivatorFocus,
140
+ onBlur: onBlur,
141
+ suffix: showClearButton ? undefined : /*#__PURE__*/jsxRuntime.jsx(Icon.Icon, {
142
+ source: polarisIcons.CaretDownIcon
143
+ }),
144
+ connectedRight: suffixAction ? utils.buttonFrom(suffixAction) : undefined
145
+ })
146
+ });
147
+
148
+ // the selected option keeps its natural position in the list; if it is absent from the loaded
149
+ // `options` (e.g. pagination/search reset) it simply isn't listed, while the activator still
150
+ // shows its label via the cache
151
+ const optionsMarkup = react.useMemo(() => {
152
+ if (loading || filteredOptions.length === 0) return null;
153
+ return filteredOptions.map(option => {
154
+ const isSelected = selected.includes(option.value);
155
+ return /*#__PURE__*/jsxRuntime.jsx(Listbox.Listbox.Option, {
156
+ value: option.value,
157
+ selected: isSelected,
158
+ children: /*#__PURE__*/jsxRuntime.jsx(Listbox.Listbox.TextOption, {
159
+ selected: isSelected,
160
+ children: option.label
161
+ })
162
+ }, option.value);
163
+ });
164
+ }, [loading, filteredOptions, selected]);
165
+ const loadingMarkup = loading ? /*#__PURE__*/jsxRuntime.jsx(Listbox.Listbox.Loading, {
166
+ accessibilityLabel: i18n.translate('Polaris.DropDown.loadingAccessibilityLabel')
167
+ }) : null;
168
+ const loadingMoreMarkup = loadingMore ? /*#__PURE__*/jsxRuntime.jsx(Listbox.Listbox.Loading, {
169
+ accessibilityLabel: i18n.translate('Polaris.DropDown.loadingMoreAccessibilityLabel')
170
+ }) : null;
171
+ const noResultsMarkup = !loading && filteredOptions.length === 0 ? /*#__PURE__*/jsxRuntime.jsx(EmptySearchResult.EmptySearchResult, {
172
+ title: emptyStateTitle || (query ? i18n.translate('Polaris.DropDown.noResultsFoundFor', {
173
+ query
174
+ }) : i18n.translate('Polaris.DropDown.noResultsFound')),
175
+ description: emptyStateDescription
176
+ }) : null;
177
+ const updateSelection = react.useCallback(newSelection => {
178
+ const option = options.find(({
179
+ value: optionValue
180
+ }) => optionValue === newSelection);
181
+ const label = resolveOptionLabel(option, selectedLabelKey);
182
+ if (label) {
183
+ setCachedSelection({
184
+ value: newSelection,
185
+ label
186
+ });
187
+ } else if (cachedSelection?.value !== newSelection) {
188
+ // re-selecting the cached option (absent from `options`) must keep its cached label
189
+ setCachedSelection(null);
190
+ }
191
+ onChange?.(newSelection);
192
+ setQuery('');
193
+ onQueryChange?.('');
194
+ setPopoverActive(false);
195
+ }, [options, selectedLabelKey, cachedSelection, onChange, onQueryChange]);
196
+ const handleActiveOptionChange = react.useCallback((_value, domId) => {
197
+ setActiveOptionId(domId);
198
+ }, []);
199
+ const handleQueryClear = react.useCallback(() => {
200
+ setQuery('');
201
+ onQueryChange?.('');
202
+ }, [onQueryChange]);
203
+ return /*#__PURE__*/jsxRuntime.jsx(Popover.Popover, {
204
+ activator: activator,
205
+ active: popoverActive,
206
+ onClose: togglePopoverActive,
207
+ fullWidth: true,
208
+ autofocusTarget: "first-node",
209
+ preferInputActivator: false,
210
+ children: /*#__PURE__*/jsxRuntime.jsxs(Popover.Popover.Pane, {
211
+ fixed: true,
212
+ children: [searchable ? /*#__PURE__*/jsxRuntime.jsx(Box.Box, {
213
+ padding: "300",
214
+ children: /*#__PURE__*/jsxRuntime.jsx(TextField.TextField, {
215
+ prefix: /*#__PURE__*/jsxRuntime.jsx(Icon.Icon, {
216
+ source: polarisIcons.SearchIcon
217
+ }),
218
+ label: "",
219
+ labelHidden: true,
220
+ autoComplete: "off",
221
+ placeholder: i18n.translate('Polaris.DropDown.searchPlaceholder'),
222
+ clearButton: true,
223
+ ariaActiveDescendant: activeOptionId,
224
+ ariaControls: listboxId,
225
+ value: query,
226
+ onChange: value => {
227
+ onQueryChange?.(value);
228
+ setQuery(value);
229
+ },
230
+ onClearButtonClick: handleQueryClear
231
+ })
232
+ }) : null, /*#__PURE__*/jsxRuntime.jsx(Scrollable.Scrollable, {
233
+ style: {
234
+ position: 'relative',
235
+ maxHeight: SCROLLABLE_HEIGHT,
236
+ // without the search field above, the list needs its own top padding
237
+ padding: searchable ? '0 0 var(--p-space-200)' : 'var(--p-space-200) 0',
238
+ borderBottomLeftRadius: 'var(--p-border-radius-200)',
239
+ borderBottomRightRadius: 'var(--p-border-radius-200)'
240
+ },
241
+ horizontal: false,
242
+ onScrolledToBottom: onScrolledToBottom,
243
+ children: /*#__PURE__*/jsxRuntime.jsxs(Listbox.Listbox, {
244
+ enableKeyboardControl: true,
245
+ autoSelection: selected.length > 0 ? Listbox.AutoSelection.FirstSelected : Listbox.AutoSelection.None,
246
+ customListId: listboxId,
247
+ onSelect: updateSelection,
248
+ onActiveOptionChange: handleActiveOptionChange,
249
+ children: [optionsMarkup, loadingMarkup, loadingMoreMarkup, noResultsMarkup]
250
+ })
251
+ })]
252
+ })
253
+ });
254
+ }
255
+ // react-hook-form is an optional peer dependency: only pull it in when the form-aware mode is used
256
+ const LazyDropDownField = /*#__PURE__*/react.lazy(() => Promise.resolve().then(function () { return require('./DropDownField.js'); }).then(module => ({
257
+ default: module.DropDownField
258
+ })));
259
+
260
+ /**
261
+ * A searchable single-select dropdown. Works standalone via `value`/`onChange`, or as a form-aware
262
+ * field by passing `name` (and optionally `control`) to integrate with react-hook-form.
263
+ */
264
+ function DropDown(props) {
265
+ if (props.name != null) {
266
+ const {
267
+ name,
268
+ control,
269
+ rules,
270
+ defaultValue,
271
+ ...baseProps
272
+ } = props;
273
+ return /*#__PURE__*/jsxRuntime.jsx(react.Suspense, {
274
+ fallback: /*#__PURE__*/jsxRuntime.jsx(DropDownBase, {
275
+ ...baseProps,
276
+ disabled: true
277
+ }),
278
+ children: /*#__PURE__*/jsxRuntime.jsx(LazyDropDownField, {
279
+ name: name,
280
+ control: control,
281
+ rules: rules,
282
+ defaultValue: defaultValue,
283
+ ...baseProps
284
+ })
285
+ });
286
+ }
287
+ return /*#__PURE__*/jsxRuntime.jsx(DropDownBase, {
288
+ ...props
289
+ });
290
+ }
291
+
292
+ exports.DropDown = DropDown;
293
+ exports.DropDownBase = DropDownBase;
@@ -0,0 +1,33 @@
1
+ 'use strict';
2
+
3
+ var reactHookForm = require('react-hook-form');
4
+ var DropDown = require('./DropDown.js');
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+
7
+ function DropDownField({
8
+ name,
9
+ control,
10
+ rules,
11
+ defaultValue = '',
12
+ error,
13
+ ...rest
14
+ }) {
15
+ const {
16
+ field,
17
+ fieldState
18
+ } = reactHookForm.useController({
19
+ name,
20
+ control,
21
+ rules,
22
+ defaultValue
23
+ });
24
+ return /*#__PURE__*/jsxRuntime.jsx(DropDown.DropDownBase, {
25
+ ...rest,
26
+ value: field.value,
27
+ onChange: field.onChange,
28
+ onBlur: field.onBlur,
29
+ error: fieldState.error?.message ?? error
30
+ });
31
+ }
32
+
33
+ exports.DropDownField = DropDownField;
@@ -75,11 +75,17 @@ function FiltersBar({
75
75
  togglePopoverActive();
76
76
  }, 0);
77
77
  };
78
- const filterToActionItem = filter => ({
79
- ...filter,
80
- content: filter.label,
81
- onAction: onFilterClick(filter)
82
- });
78
+ const filterToActionItem = filter => {
79
+ const {
80
+ key: _filterKey,
81
+ ...rest
82
+ } = filter;
83
+ return {
84
+ ...rest,
85
+ content: filter.label,
86
+ onAction: onFilterClick(filter)
87
+ };
88
+ };
83
89
  const unpinnedFilters = filters.filter(filter => !pinnedFilters.some(({
84
90
  key
85
91
  }) => key === filter.key));
@@ -96,7 +96,14 @@ var styles = {
96
96
  "HeaderWrapper": "Polaris-IndexTable__HeaderWrapper",
97
97
  "StickyTable-condensed": "Polaris-IndexTable__StickyTable--condensed",
98
98
  "StickyTableHeader-condensed": "Polaris-IndexTable__StickyTableHeader--condensed",
99
- "ScrollBarContent": "Polaris-IndexTable__ScrollBarContent"
99
+ "ScrollBarContent": "Polaris-IndexTable__ScrollBarContent",
100
+ "TableHeading-reorder": "Polaris-IndexTable__TableHeading--reorder",
101
+ "TableCellDragHandle": "Polaris-IndexTable__TableCellDragHandle",
102
+ "DragHandle": "Polaris-IndexTable__DragHandle",
103
+ "DragHandleIcon": "Polaris-IndexTable__DragHandleIcon",
104
+ "TableRow-reorderable": "Polaris-IndexTable__TableRow--reorderable",
105
+ "TableRow-dragging": "Polaris-IndexTable__TableRow--dragging",
106
+ "TableRow-dropTarget": "Polaris-IndexTable__TableRow--dropTarget"
100
107
  };
101
108
 
102
109
  exports.default = styles;
@@ -12,7 +12,6 @@ var IndexProvider = require('../IndexProvider/IndexProvider.js');
12
12
  var Row = require('./components/Row/Row.js');
13
13
  var types = require('../../utilities/index-provider/types.js');
14
14
  var utilities = require('./utilities/utilities.js');
15
- var EmptySearchResult = require('../EmptySearchResult/EmptySearchResult.js');
16
15
  var ScrollContainer = require('./components/ScrollContainer/ScrollContainer.js');
17
16
  var BulkActions = require('../BulkActions/BulkActions.js');
18
17
  var Cell = require('./components/Cell/Cell.js');
@@ -20,9 +19,11 @@ var hooks = require('../../utilities/index-provider/hooks.js');
20
19
  var hooks$1 = require('../../utilities/i18n/hooks.js');
21
20
  var Spinner = require('../Spinner/Spinner.js');
22
21
  var AfterInitialMount = require('../AfterInitialMount/AfterInitialMount.js');
22
+ var EmptySearchResult = require('../EmptySearchResult/EmptySearchResult.js');
23
23
  var Pagination = require('../Pagination/Pagination.js');
24
- var Checkbox = require('../Checkbox/Checkbox.js');
24
+ var context = require('../../utilities/index-table/context.js');
25
25
  var Text = require('../Text/Text.js');
26
+ var Checkbox = require('../Checkbox/Checkbox.js');
26
27
  var LegacyStack = require('../LegacyStack/LegacyStack.js');
27
28
  var Badge = require('../Badge/Badge.js');
28
29
  var UnstyledButton = require('../UnstyledButton/UnstyledButton.js');
@@ -49,6 +50,7 @@ function IndexTableBase({
49
50
  sortToggleLabels,
50
51
  hasZebraStriping,
51
52
  pagination,
53
+ onReorder,
52
54
  ...restProps
53
55
  }) {
54
56
  const {
@@ -66,6 +68,34 @@ function IndexTableBase({
66
68
  } = hooks.useIndexValue();
67
69
  const handleSelectionChange = hooks.useIndexSelectionChange();
68
70
  const i18n = hooks$1.useI18n();
71
+ const reorderable = typeof onReorder === 'function';
72
+ const [draggingPosition, setDraggingPosition] = react.useState(null);
73
+ const [dropPosition, setDropPosition] = react.useState(null);
74
+ const handleReorderDragStart = react.useCallback(position => {
75
+ setDraggingPosition(position);
76
+ }, []);
77
+ const handleReorderDragEnter = react.useCallback(position => {
78
+ setDropPosition(position);
79
+ }, []);
80
+ const resetReorderState = react.useCallback(() => {
81
+ setDraggingPosition(null);
82
+ setDropPosition(null);
83
+ }, []);
84
+ const handleReorderDrop = react.useCallback(() => {
85
+ if (draggingPosition !== null && dropPosition !== null && draggingPosition !== dropPosition) {
86
+ onReorder?.(draggingPosition, dropPosition);
87
+ }
88
+ resetReorderState();
89
+ }, [draggingPosition, dropPosition, onReorder, resetReorderState]);
90
+ const reorderContextValue = react.useMemo(() => ({
91
+ reorderable,
92
+ draggingPosition,
93
+ dropPosition,
94
+ onDragStart: handleReorderDragStart,
95
+ onDragEnter: handleReorderDragEnter,
96
+ onDrop: handleReorderDrop,
97
+ onDragEnd: resetReorderState
98
+ }), [reorderable, draggingPosition, dropPosition, handleReorderDragStart, handleReorderDragEnter, handleReorderDrop, resetReorderState]);
69
99
  const {
70
100
  value: hasMoreLeftColumns,
71
101
  toggle: toggleHasMoreLeftColumns
@@ -391,7 +421,8 @@ function IndexTableBase({
391
421
  ...pagination
392
422
  })
393
423
  }) : null;
394
- return /*#__PURE__*/jsxRuntime.jsx(jsxRuntime.Fragment, {
424
+ return /*#__PURE__*/jsxRuntime.jsx(context.RowReorderContext.Provider, {
425
+ value: reorderContextValue,
395
426
  children: /*#__PURE__*/jsxRuntime.jsx("div", {
396
427
  className: IndexTable_module.default.IndexTable,
397
428
  children: /*#__PURE__*/jsxRuntime.jsxs("div", {
@@ -416,16 +447,33 @@ function IndexTableBase({
416
447
  ...tagProps,
417
448
  children: renderHeadingContent(heading, index)
418
449
  }, getHeadingKey(heading));
419
- if (index !== 0 || !selectable) {
450
+ if (index !== 0 || !selectable && !reorderable) {
420
451
  return headingContent;
421
452
  }
422
- const checkboxClassName = css.classNames(IndexTable_module.default.TableHeading, hasSortable && IndexTable_module.default['TableHeading-sortable'], index === 0 && IndexTable_module.default['TableHeading-first']);
423
- const checkboxContent = /*#__PURE__*/jsxRuntime.jsx(Tag, {
424
- className: checkboxClassName,
425
- ...tagProps,
426
- children: renderCheckboxContent()
427
- }, `${heading}-${index}`);
428
- return [checkboxContent, headingContent];
453
+ const leadingHeadings = [];
454
+
455
+ // Omits `data-index-table-heading` so this column is excluded from the
456
+ // column index math used by sticky columns and sort handling.
457
+ if (reorderable) {
458
+ leadingHeadings.push(/*#__PURE__*/jsxRuntime.jsx(Tag, {
459
+ className: css.classNames(IndexTable_module.default.TableHeading, IndexTable_module.default['TableHeading-reorder']),
460
+ children: /*#__PURE__*/jsxRuntime.jsx(Text.Text, {
461
+ as: "span",
462
+ variant: "bodySm",
463
+ visuallyHidden: true,
464
+ children: i18n.translate('Polaris.IndexTable.reorderColumnHeader')
465
+ })
466
+ }, "reorder-heading"));
467
+ }
468
+ if (selectable) {
469
+ const checkboxClassName = css.classNames(IndexTable_module.default.TableHeading, hasSortable && IndexTable_module.default['TableHeading-sortable'], index === 0 && IndexTable_module.default['TableHeading-first']);
470
+ leadingHeadings.push(/*#__PURE__*/jsxRuntime.jsx(Tag, {
471
+ className: checkboxClassName,
472
+ ...tagProps,
473
+ children: renderCheckboxContent()
474
+ }, `${heading}-${index}`));
475
+ }
476
+ return [...leadingHeadings, headingContent];
429
477
  }
430
478
  function renderCheckboxContent() {
431
479
  return /*#__PURE__*/jsxRuntime.jsx("div", {
@@ -1,15 +1,19 @@
1
1
  'use strict';
2
2
 
3
+ var polarisIcons = require('@shopify/polaris-icons');
3
4
  var react = require('react');
4
5
  var css = require('../../../../utilities/css.js');
5
6
  var useToggle = require('../../../../utilities/use-toggle.js');
6
7
  var IndexTable_module = require('../../IndexTable.css.js');
7
8
  var jsxRuntime = require('react/jsx-runtime');
8
- var hooks = require('../../../../utilities/index-provider/hooks.js');
9
- var types = require('../../../../utilities/index-provider/types.js');
9
+ var hooks$1 = require('../../../../utilities/index-provider/hooks.js');
10
10
  var context = require('../../../../utilities/index-table/context.js');
11
+ var types = require('../../../../utilities/index-provider/types.js');
11
12
  var Cell = require('../Cell/Cell.js');
12
13
  var Checkbox = require('../Checkbox/Checkbox.js');
14
+ var hooks = require('../../../../utilities/i18n/hooks.js');
15
+ var Icon = require('../../../Icon/Icon.js');
16
+ var Text = require('../../../Text/Text.js');
13
17
 
14
18
  const Row = /*#__PURE__*/react.memo(function Row({
15
19
  children,
@@ -25,18 +29,44 @@ const Row = /*#__PURE__*/react.memo(function Row({
25
29
  onNavigation,
26
30
  onClick
27
31
  }) {
32
+ const i18n = hooks.useI18n();
28
33
  const {
29
34
  selectable: tableIsSelectable,
30
35
  selectMode,
31
36
  condensed
32
- } = hooks.useIndexRow();
37
+ } = hooks$1.useIndexRow();
38
+ const {
39
+ resourceName
40
+ } = hooks$1.useIndexValue();
33
41
  const rowIsSelectable = tableIsSelectable && !hideSelectable;
34
- const onSelectionChange = hooks.useIndexSelectionChange();
42
+ const onSelectionChange = hooks$1.useIndexSelectionChange();
35
43
  const {
36
44
  value: hovered,
37
45
  setTrue: setHoverIn,
38
46
  setFalse: setHoverOut
39
47
  } = useToggle.useToggle(false);
48
+ const reorder = react.useContext(context.RowReorderContext);
49
+ const reorderable = Boolean(reorder?.reorderable) && rowType === 'data';
50
+ const isDragging = reorderable && reorder?.draggingPosition === position;
51
+ const isDropTarget = reorderable && reorder?.dropPosition === position && reorder?.draggingPosition !== position;
52
+ const handleDragStart = react.useCallback(event => {
53
+ event.dataTransfer.effectAllowed = 'move';
54
+ reorder?.onDragStart(position);
55
+ }, [reorder, position]);
56
+ const handleDragEnter = react.useCallback(() => {
57
+ reorder?.onDragEnter(position);
58
+ }, [reorder, position]);
59
+ const handleDragOver = react.useCallback(event => {
60
+ event.preventDefault();
61
+ event.dataTransfer.dropEffect = 'move';
62
+ }, []);
63
+ const handleDrop = react.useCallback(event => {
64
+ event.preventDefault();
65
+ reorder?.onDrop();
66
+ }, [reorder]);
67
+ const handleDragEnd = react.useCallback(() => {
68
+ reorder?.onDragEnd();
69
+ }, [reorder]);
40
70
  const handleInteraction = react.useCallback(event => {
41
71
  event.stopPropagation();
42
72
  let selectionType = types.SelectionType.Single;
@@ -66,7 +96,7 @@ const Row = /*#__PURE__*/react.memo(function Row({
66
96
  primaryLinkElement.current = el;
67
97
  }
68
98
  }, []);
69
- const rowClassName = css.classNames(IndexTable_module.default.TableRow, rowType === 'subheader' && IndexTable_module.default['TableRow-subheader'], rowType === 'child' && IndexTable_module.default['TableRow-child'], rowIsSelectable && condensed && IndexTable_module.default.condensedRow, selected && IndexTable_module.default['TableRow-selected'], hovered && !condensed && IndexTable_module.default['TableRow-hovered'], disabled && IndexTable_module.default['TableRow-disabled'], tone && IndexTable_module.default[css.variationName('tone', tone)], !rowIsSelectable && !onClick && !primaryLinkElement.current && IndexTable_module.default['TableRow-unclickable']);
99
+ const rowClassName = css.classNames(IndexTable_module.default.TableRow, rowType === 'subheader' && IndexTable_module.default['TableRow-subheader'], rowType === 'child' && IndexTable_module.default['TableRow-child'], rowIsSelectable && condensed && IndexTable_module.default.condensedRow, selected && IndexTable_module.default['TableRow-selected'], hovered && !condensed && IndexTable_module.default['TableRow-hovered'], disabled && IndexTable_module.default['TableRow-disabled'], tone && IndexTable_module.default[css.variationName('tone', tone)], reorderable && IndexTable_module.default['TableRow-reorderable'], isDragging && IndexTable_module.default['TableRow-dragging'], isDropTarget && IndexTable_module.default['TableRow-dropTarget'], !rowIsSelectable && !onClick && !primaryLinkElement.current && IndexTable_module.default['TableRow-unclickable']);
70
100
  let handleRowClick;
71
101
  if (!disabled && rowIsSelectable || onClick || primaryLinkElement.current) {
72
102
  handleRowClick = event => {
@@ -105,6 +135,35 @@ const Row = /*#__PURE__*/react.memo(function Row({
105
135
  const checkboxMarkup = hideSelectable ? /*#__PURE__*/jsxRuntime.jsx(Cell.Cell, {}) : /*#__PURE__*/jsxRuntime.jsx(Checkbox.Checkbox, {
106
136
  accessibilityLabel: accessibilityLabel
107
137
  });
138
+ const dragHandleMarkup = reorderable ? /*#__PURE__*/jsxRuntime.jsx("td", {
139
+ className: IndexTable_module.default.TableCellDragHandle,
140
+ onClick: stopPropagation,
141
+ children: /*#__PURE__*/jsxRuntime.jsxs("span", {
142
+ className: IndexTable_module.default.DragHandle,
143
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
144
+ className: IndexTable_module.default.DragHandleIcon,
145
+ "aria-hidden": "true",
146
+ children: /*#__PURE__*/jsxRuntime.jsx(Icon.Icon, {
147
+ source: polarisIcons.DragHandleIcon,
148
+ tone: "subdued"
149
+ })
150
+ }), /*#__PURE__*/jsxRuntime.jsx(Text.Text, {
151
+ as: "span",
152
+ visuallyHidden: true,
153
+ children: i18n.translate('Polaris.IndexTable.reorderAccessibilityLabel', {
154
+ resourceName: resourceName.singular
155
+ })
156
+ })]
157
+ })
158
+ }) : null;
159
+ const reorderProps = reorderable ? {
160
+ draggable: true,
161
+ onDragStart: handleDragStart,
162
+ onDragEnter: handleDragEnter,
163
+ onDragOver: handleDragOver,
164
+ onDrop: handleDrop,
165
+ onDragEnd: handleDragEnd
166
+ } : {};
108
167
  return /*#__PURE__*/jsxRuntime.jsx(context.RowContext.Provider, {
109
168
  value: contextValue,
110
169
  children: /*#__PURE__*/jsxRuntime.jsx(context.RowHoveredContext.Provider, {
@@ -116,10 +175,14 @@ const Row = /*#__PURE__*/react.memo(function Row({
116
175
  onMouseLeave: setHoverOut,
117
176
  onClick: handleRowClick,
118
177
  ref: tableRowCallbackRef,
119
- children: [tableIsSelectable ? checkboxMarkup : null, children]
178
+ ...reorderProps,
179
+ children: [dragHandleMarkup, tableIsSelectable ? checkboxMarkup : null, children]
120
180
  }, id)
121
181
  })
122
182
  });
123
183
  });
184
+ function stopPropagation(event) {
185
+ event.stopPropagation();
186
+ }
124
187
 
125
188
  exports.Row = Row;
@@ -29,15 +29,18 @@ function Pagination({
29
29
  accessibilityLabel,
30
30
  accessibilityLabels,
31
31
  label,
32
- type = 'page'
32
+ type = 'page',
33
+ direction = 'horizontal'
33
34
  }) {
34
35
  const i18n = hooks.useI18n();
35
36
  const node = /*#__PURE__*/react.createRef();
36
37
  const navLabel = accessibilityLabel || i18n.translate('Polaris.Pagination.pagination');
37
38
  const previousLabel = accessibilityLabels?.previous || i18n.translate('Polaris.Pagination.previous');
38
39
  const nextLabel = accessibilityLabels?.next || i18n.translate('Polaris.Pagination.next');
40
+ const previousIcon = direction === 'vertical' ? polarisIcons.ChevronUpIcon : polarisIcons.ChevronLeftIcon;
41
+ const nextIcon = direction === 'vertical' ? polarisIcons.ChevronDownIcon : polarisIcons.ChevronRightIcon;
39
42
  const prev = /*#__PURE__*/jsxRuntime.jsx(Button.Button, {
40
- icon: polarisIcons.ChevronLeftIcon,
43
+ icon: previousIcon,
41
44
  accessibilityLabel: previousLabel,
42
45
  url: previousURL,
43
46
  onClick: onPrevious,
@@ -51,7 +54,7 @@ function Pagination({
51
54
  children: prev
52
55
  }) : prev;
53
56
  const next = /*#__PURE__*/jsxRuntime.jsx(Button.Button, {
54
- icon: polarisIcons.ChevronRightIcon,
57
+ icon: nextIcon,
55
58
  accessibilityLabel: nextLabel,
56
59
  url: nextURL,
57
60
  onClick: onNext,