@planningcenter/tapestry 4.12.0 → 4.13.0-rc.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.
- package/dist/componentRegistrars.d.ts +1 -0
- package/dist/componentRegistrars.d.ts.map +1 -1
- package/dist/componentRegistrars.js +6 -2
- package/dist/componentRegistrars.js.map +1 -1
- package/dist/components/DataTable/ActiveFilters.d.ts +23 -1
- package/dist/components/DataTable/ActiveFilters.d.ts.map +1 -1
- package/dist/components/DataTable/ActiveFilters.js +49 -4
- package/dist/components/DataTable/ActiveFilters.js.map +1 -1
- package/dist/components/DataTable/CollectionEditorsLazy.d.ts.map +1 -1
- package/dist/components/DataTable/CollectionEditorsLazy.js +20 -18
- package/dist/components/DataTable/CollectionEditorsLazy.js.map +1 -1
- package/dist/components/DataTable/DataTable.d.ts +66 -50
- package/dist/components/DataTable/DataTable.d.ts.map +1 -1
- package/dist/components/DataTable/DataTable.js +78 -17
- package/dist/components/DataTable/DataTable.js.map +1 -1
- package/dist/components/DataTable/ManageSavedViewsModal.d.ts +18 -7
- package/dist/components/DataTable/ManageSavedViewsModal.d.ts.map +1 -1
- package/dist/components/DataTable/ManageSavedViewsModal.js +120 -104
- package/dist/components/DataTable/ManageSavedViewsModal.js.map +1 -1
- package/dist/components/DataTable/ManageSavedViewsModal.module.css.js +1 -1
- package/dist/components/DataTable/NewSavedViewButton.d.ts.map +1 -1
- package/dist/components/DataTable/NewSavedViewButton.js +1 -1
- package/dist/components/DataTable/NewSavedViewButton.js.map +1 -1
- package/dist/components/DataTable/SavedViewActions.d.ts +19 -0
- package/dist/components/DataTable/SavedViewActions.d.ts.map +1 -0
- package/dist/components/DataTable/SavedViewActions.js +34 -0
- package/dist/components/DataTable/SavedViewActions.js.map +1 -0
- package/dist/components/DataTable/SavedViewMenu.d.ts +18 -0
- package/dist/components/DataTable/SavedViewMenu.d.ts.map +1 -0
- package/dist/components/DataTable/SavedViewMenu.js +25 -0
- package/dist/components/DataTable/SavedViewMenu.js.map +1 -0
- package/dist/components/DataTable/SavedViewsBar.d.ts +25 -13
- package/dist/components/DataTable/SavedViewsBar.d.ts.map +1 -1
- package/dist/components/DataTable/SavedViewsBar.js +43 -83
- package/dist/components/DataTable/SavedViewsBar.js.map +1 -1
- package/dist/components/DataTable/TableActions.d.ts +4 -2
- package/dist/components/DataTable/TableActions.d.ts.map +1 -1
- package/dist/components/DataTable/TableActions.js +11 -14
- package/dist/components/DataTable/TableActions.js.map +1 -1
- package/dist/components/DataTable/index.d.ts +2 -0
- package/dist/components/DataTable/index.d.ts.map +1 -1
- package/dist/components/DataTable/saveErrorMessage.d.ts +3 -0
- package/dist/components/DataTable/saveErrorMessage.d.ts.map +1 -0
- package/dist/components/DataTable/saveErrorMessage.js +9 -0
- package/dist/components/DataTable/saveErrorMessage.js.map +1 -0
- package/dist/components/DataTable/savedViews.d.ts +15 -30
- package/dist/components/DataTable/savedViews.d.ts.map +1 -1
- package/dist/components/DataTable/savedViews.js +51 -98
- package/dist/components/DataTable/savedViews.js.map +1 -1
- package/dist/components/DataTable/useActiveSavedView.d.ts +1 -1
- package/dist/components/DataTable/useActiveSavedView.d.ts.map +1 -1
- package/dist/components/DataTable/useActiveSavedView.js +5 -4
- package/dist/components/DataTable/useActiveSavedView.js.map +1 -1
- package/dist/components/DataTable/useColumnVisibility.d.ts +7 -7
- package/dist/components/DataTable/useColumnVisibility.d.ts.map +1 -1
- package/dist/components/DataTable/useColumnVisibility.js +14 -14
- package/dist/components/DataTable/useColumnVisibility.js.map +1 -1
- package/dist/components/DataTable/useResultsAnnouncement.d.ts +26 -0
- package/dist/components/DataTable/useResultsAnnouncement.d.ts.map +1 -0
- package/dist/components/DataTable/{useFilterAnnouncement.js → useResultsAnnouncement.js} +16 -12
- package/dist/components/DataTable/useResultsAnnouncement.js.map +1 -0
- package/dist/components/DataTable/useSaveStatus.d.ts +32 -0
- package/dist/components/DataTable/useSaveStatus.d.ts.map +1 -0
- package/dist/components/DataTable/useSaveStatus.js +80 -0
- package/dist/components/DataTable/useSaveStatus.js.map +1 -0
- package/dist/components/DataTable/useSavedViewNameModal.d.ts +14 -0
- package/dist/components/DataTable/useSavedViewNameModal.d.ts.map +1 -0
- package/dist/components/DataTable/useSavedViewNameModal.js +43 -0
- package/dist/components/DataTable/useSavedViewNameModal.js.map +1 -0
- package/dist/components/DataTable/useSavedViewsClient.d.ts +58 -0
- package/dist/components/DataTable/useSavedViewsClient.d.ts.map +1 -0
- package/dist/components/DataTable/useSavedViewsClient.js +87 -0
- package/dist/components/DataTable/useSavedViewsClient.js.map +1 -0
- package/dist/components/DataTable/useSavedViewsState.d.ts +35 -0
- package/dist/components/DataTable/useSavedViewsState.d.ts.map +1 -0
- package/dist/components/DataTable/useSavedViewsState.js +192 -0
- package/dist/components/DataTable/useSavedViewsState.js.map +1 -0
- package/dist/components/DataTable/useUpdateSavedViewName.d.ts +2 -3
- package/dist/components/DataTable/useUpdateSavedViewName.d.ts.map +1 -1
- package/dist/components/DataTable/useUpdateSavedViewName.js +1 -2
- package/dist/components/DataTable/useUpdateSavedViewName.js.map +1 -1
- package/dist/components/button/BaseButton.d.ts +2 -0
- package/dist/components/button/BaseButton.d.ts.map +1 -1
- package/dist/components/button/BaseButton.js +8 -17
- package/dist/components/button/BaseButton.js.map +1 -1
- package/dist/components/internal/LoadingAnnouncement.d.ts +6 -0
- package/dist/components/internal/LoadingAnnouncement.d.ts.map +1 -1
- package/dist/components/internal/LoadingAnnouncement.js +12 -3
- package/dist/components/internal/LoadingAnnouncement.js.map +1 -1
- package/dist/components/internal/index.d.ts +1 -1
- package/dist/components/internal/index.d.ts.map +1 -1
- package/dist/components/internal/tooltip/useTooltipTriggerProps.d.ts +13 -0
- package/dist/components/internal/tooltip/useTooltipTriggerProps.d.ts.map +1 -0
- package/dist/components/internal/tooltip/useTooltipTriggerProps.js +24 -0
- package/dist/components/internal/tooltip/useTooltipTriggerProps.js.map +1 -0
- package/dist/components/link/BaseLink.d.ts.map +1 -1
- package/dist/components/link/BaseLink.js +3 -13
- package/dist/components/link/BaseLink.js.map +1 -1
- package/dist/components/segmented-control/IconSegment.d.ts +30 -8
- package/dist/components/segmented-control/IconSegment.d.ts.map +1 -1
- package/dist/components/segmented-control/IconSegment.js +10 -3
- package/dist/components/segmented-control/IconSegment.js.map +1 -1
- package/dist/components/segmented-control/SegmentBase.d.ts.map +1 -1
- package/dist/components/segmented-control/SegmentBase.js +4 -2
- package/dist/components/segmented-control/SegmentBase.js.map +1 -1
- package/dist/components/segmented-control/SegmentedControl.d.ts.map +1 -1
- package/dist/components/segmented-control/SegmentedControl.js +10 -3
- package/dist/components/segmented-control/SegmentedControl.js.map +1 -1
- package/dist/index.css +20 -5
- package/dist/index.css.map +1 -1
- package/dist/reactRender.css +1409 -1319
- package/dist/reactRender.css.map +1 -1
- package/dist/reactRender.js +1 -1
- package/dist/reactRenderLegacy.css +1409 -1319
- package/dist/reactRenderLegacy.css.map +1 -1
- package/dist/reactRenderLegacy.js +1 -1
- package/dist/tapestryMount.css +1409 -1319
- package/dist/tapestryMount.css.map +1 -1
- package/dist/tapestryMount.js +1 -1
- package/dist/tapestryMountLegacy.css +1409 -1319
- package/dist/tapestryMountLegacy.css.map +1 -1
- package/dist/tapestryMountLegacy.js +1 -1
- package/dist/tokens-dark.css +2 -2
- package/dist/tokens-dark.css.map +1 -1
- package/dist/tokens.css +3 -3
- package/dist/tokens.css.map +1 -1
- package/dist/unstable.css +385 -295
- package/dist/unstable.css.map +1 -1
- package/dist/unstable.js +1 -0
- package/dist/unstable.js.map +1 -1
- package/package.json +6 -7
- package/dist/components/DataTable/useFilterAnnouncement.d.ts +0 -24
- package/dist/components/DataTable/useFilterAnnouncement.d.ts.map +0 -1
- package/dist/components/DataTable/useFilterAnnouncement.js.map +0 -1
|
@@ -1,18 +1,19 @@
|
|
|
1
|
-
import '../button/ActionsDropdownIconButton.js';
|
|
1
|
+
import { ActionsDropdownIconButton } from '../button/ActionsDropdownIconButton.js';
|
|
2
2
|
import { Button } from '../button/Button.js';
|
|
3
3
|
import '../button/DropdownButton.js';
|
|
4
4
|
import '../button/DropdownIconButton.js';
|
|
5
5
|
import { IconButton } from '../button/IconButton.js';
|
|
6
6
|
import '../button/LoadingButton.js';
|
|
7
7
|
import '../button/PageHeaderActionsDropdownButton.js';
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
8
|
+
import { Dropdown, DropdownTrigger } from '../dropdown/Dropdown.js';
|
|
9
|
+
import { Tooltip } from '../internal/tooltip/Tooltip.js';
|
|
10
|
+
import { TooltipTriggerContext } from '../internal/tooltip/TooltipTriggerContext.js';
|
|
10
11
|
import { Modal } from '../modal/Modal.js';
|
|
11
12
|
import { ModalBody } from '../modal/ModalBody.js';
|
|
12
13
|
import { ModalFooter } from '../modal/ModalFooter.js';
|
|
13
14
|
import { ModalHeader } from '../modal/ModalHeader.js';
|
|
14
15
|
import Icon from '../../utilities/Icon.js';
|
|
15
|
-
import React__default, { useState, useRef, useEffect } from 'react';
|
|
16
|
+
import React__default, { useState, useRef, useEffect, useContext } from 'react';
|
|
16
17
|
import { ListDropTargetDelegate } from 'react-aria/ListDropTargetDelegate';
|
|
17
18
|
import { ListKeyboardDelegate } from 'react-aria/ListKeyboardDelegate';
|
|
18
19
|
import { mergeProps } from 'react-aria/mergeProps';
|
|
@@ -26,48 +27,75 @@ import { useDroppableCollectionState } from 'react-stately/useDroppableCollectio
|
|
|
26
27
|
import { useListState } from 'react-stately/useListState';
|
|
27
28
|
import { DeleteSavedViewAlertDialog } from './DeleteSavedViewAlertDialog.js';
|
|
28
29
|
import styles from './ManageSavedViewsModal.module.css.js';
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
30
|
+
import { NewSavedViewModal } from './NewSavedViewModal.js';
|
|
31
|
+
import { hasSavedViewMenuActions, SavedViewMenu } from './SavedViewMenu.js';
|
|
32
|
+
import { useSavedViewNameModal } from './useSavedViewNameModal.js';
|
|
33
|
+
import { useSaveStatus, SaveStatusIcon } from './useSaveStatus.js';
|
|
31
34
|
|
|
32
|
-
function ManageSavedViewsModal({ defaultViewId, onClose, onDelete, onSetDefault, onUpdate, open, savedViews, staticViews, }) {
|
|
33
|
-
const updateSavedViewName = useUpdateSavedViewName(onUpdate);
|
|
35
|
+
function ManageSavedViewsModal({ defaultViewId, isReordering = false, onClose, onCreate, onDelete, onReorder, onSetDefault, onUpdate, open, savedViews, staticViews, }) {
|
|
34
36
|
// Kept after the alert closes, so its text holds during the exit animation.
|
|
35
37
|
const [viewToDelete, setViewToDelete] = useState(null);
|
|
36
38
|
const [isDeleteAlertOpen, setIsDeleteAlertOpen] = useState(false);
|
|
37
39
|
// Without this, focus would go to the modal's close button, since the
|
|
38
|
-
// alert returns it to the
|
|
40
|
+
// alert returns it to the actions button, which is gone with its row.
|
|
39
41
|
const { doneButtonRef, focusAfterDelete, listRef } = useFocusAfterDelete(savedViews, isDeleteAlertOpen);
|
|
42
|
+
const nameModal = useSavedViewNameModal(onUpdate);
|
|
43
|
+
const saveStatus = useSaveStatus();
|
|
44
|
+
// Listed after the other saved views. Managing views leaves the selection
|
|
45
|
+
// alone, so unlike the context menu's Duplicate, it doesn't select the
|
|
46
|
+
// duplicate. Its status shows on the view it was duplicated from, since
|
|
47
|
+
// it isn't listed until it saves.
|
|
48
|
+
const createDuplicate = (view, duplicate) => {
|
|
49
|
+
if (onCreate)
|
|
50
|
+
saveStatus.track(view.id, onCreate(duplicate), duplicate.name);
|
|
51
|
+
};
|
|
40
52
|
const requestDelete = (view) => {
|
|
41
53
|
setViewToDelete(view);
|
|
42
54
|
setIsDeleteAlertOpen(true);
|
|
43
55
|
};
|
|
44
|
-
// Deleting the default view hands the default back to "initial".
|
|
45
56
|
const confirmDelete = () => {
|
|
46
|
-
if (viewToDelete) {
|
|
57
|
+
if (viewToDelete && onDelete) {
|
|
47
58
|
focusAfterDelete(viewToDelete);
|
|
48
|
-
onDelete
|
|
49
|
-
if (viewToDelete.id === defaultViewId)
|
|
50
|
-
onSetDefault?.("initial");
|
|
59
|
+
saveStatus.track(viewToDelete.id, onDelete(viewToDelete), viewToDelete.name);
|
|
51
60
|
}
|
|
52
61
|
setIsDeleteAlertOpen(false);
|
|
53
62
|
};
|
|
54
|
-
//
|
|
55
|
-
//
|
|
56
|
-
const
|
|
57
|
-
|
|
63
|
+
// Every row gets an actions button, disabled without actions, so the
|
|
64
|
+
// buttons line up.
|
|
65
|
+
const hasViewActions = Boolean(onCreate || onDelete || onSetDefault || onUpdate);
|
|
66
|
+
// The actions static views share with saved views. The default is matched
|
|
67
|
+
// by id, so an unsaved view can't be made the default.
|
|
68
|
+
const viewActions = (view) => {
|
|
69
|
+
const { id } = view;
|
|
70
|
+
return {
|
|
71
|
+
isDefault: id === defaultViewId,
|
|
72
|
+
onDuplicate: onCreate
|
|
73
|
+
? () => nameModal.openDuplicate(view, (duplicate) => createDuplicate(view, duplicate))
|
|
74
|
+
: undefined,
|
|
75
|
+
onSetDefault: onSetDefault && id !== undefined
|
|
76
|
+
? () => saveStatus.track(id, onSetDefault(id), view.name)
|
|
77
|
+
: undefined,
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
return (React__default.createElement(Modal, { dismissible: true, open: open, size: "sm", onClose: onClose },
|
|
58
81
|
React__default.createElement(ModalHeader, { title: "Manage views" }),
|
|
59
82
|
React__default.createElement(ModalBody, null,
|
|
60
|
-
React__default.createElement(SavedViewsList, { listRef: listRef, renderStaticViewActions: (view) => (React__default.createElement(React__default.Fragment, null,
|
|
61
|
-
|
|
62
|
-
|
|
83
|
+
React__default.createElement(SavedViewsList, { isReordering: isReordering, listRef: listRef, renderStaticViewActions: (view) => (React__default.createElement(React__default.Fragment, null,
|
|
84
|
+
React__default.createElement(SaveStatusIcon, { status: saveStatus.statusFor(view.id) }),
|
|
85
|
+
view.id === defaultViewId && React__default.createElement(DefaultViewIcon, null),
|
|
86
|
+
hasViewActions && (React__default.createElement(ViewActionsMenu, { name: view.name, ...viewActions(view) })))), savedViews: savedViews, staticViews: staticViews, onReorder: onReorder &&
|
|
87
|
+
((view, target) => saveStatus.track(view.id, onReorder(view, target), view.name)) }, (view) => (React__default.createElement(SavedViewRow, { hasActionsMenu: hasViewActions, view: view, ...viewActions(view), saveStatus: React__default.createElement(SaveStatusIcon, { status: saveStatus.statusFor(view.id) }),
|
|
63
88
|
// Updates and deletes are matched by id, so an unsaved view
|
|
64
89
|
// can't be renamed or deleted.
|
|
65
|
-
|
|
66
|
-
? (
|
|
67
|
-
: undefined, onRename:
|
|
90
|
+
onDelete: onDelete && view.id !== undefined
|
|
91
|
+
? () => requestDelete(view)
|
|
92
|
+
: undefined, onRename: onUpdate && view.id !== undefined
|
|
93
|
+
? () => nameModal.openRename(view, (saving) => saveStatus.track(view.id, saving, view.name))
|
|
94
|
+
: undefined })))),
|
|
68
95
|
React__default.createElement(ModalFooter, null,
|
|
69
96
|
React__default.createElement(Button, { ref: doneButtonRef, kind: "primary", label: "Done", onClick: onClose })),
|
|
70
|
-
onDelete && (React__default.createElement(DeleteSavedViewAlertDialog, { open: isDeleteAlertOpen, view: viewToDelete, onCancel: () => setIsDeleteAlertOpen(false), onConfirm: confirmDelete }))
|
|
97
|
+
onDelete && (React__default.createElement(DeleteSavedViewAlertDialog, { open: isDeleteAlertOpen, view: viewToDelete, onCancel: () => setIsDeleteAlertOpen(false), onConfirm: confirmDelete })),
|
|
98
|
+
(onCreate || onUpdate) && (React__default.createElement(NewSavedViewModal, { ...nameModal.modalProps }))));
|
|
71
99
|
}
|
|
72
100
|
ManageSavedViewsModal.displayName = "ManageSavedViewsModal";
|
|
73
101
|
/**
|
|
@@ -75,17 +103,17 @@ ManageSavedViewsModal.displayName = "ManageSavedViewsModal";
|
|
|
75
103
|
* modal's content, since React Aria registers the list as a drop target when
|
|
76
104
|
* its hooks mount, and the modal stays mounted while closed.
|
|
77
105
|
*/
|
|
78
|
-
function SavedViewsList({ children, listRef,
|
|
79
|
-
const { collectionProps, dragState, dropState } = useSavedViewsDragAndDrop(savedViews, listRef,
|
|
106
|
+
function SavedViewsList({ children, isReordering, listRef, onReorder, renderStaticViewActions, savedViews, staticViews, }) {
|
|
107
|
+
const { collectionProps, dragState, dropState } = useSavedViewsDragAndDrop(savedViews, listRef, isReordering, onReorder);
|
|
80
108
|
return (React__default.createElement("ol", { ref: listRef, ...collectionProps, className: styles["views-list"] },
|
|
81
109
|
staticViews.map((view) => (React__default.createElement("li", { key: view.id, className: styles["views-list-item--static"] },
|
|
82
|
-
React__default.createElement("span", { className: styles["view-list-item-
|
|
110
|
+
React__default.createElement("span", { className: styles["view-list-item-name"] }, view.name),
|
|
83
111
|
renderStaticViewActions(view)))),
|
|
84
112
|
savedViews.map((view, index) => {
|
|
85
113
|
const key = savedViewKey(view, index);
|
|
86
114
|
return (React__default.createElement("li", { key: key, className: styles["views-list-item"], "data-dragging": dragState.isDragging(key) || undefined, "data-key": key },
|
|
87
115
|
React__default.createElement(SavedViewDropIndicator, { dropState: dropState, target: { dropPosition: "before", key, type: "item" } }),
|
|
88
|
-
savedViews.length > 1 &&
|
|
116
|
+
savedViews.length > 1 && onReorder && view.id !== undefined && (React__default.createElement(SavedViewDragHandle, { dragState: dragState, itemKey: key, name: view.name })),
|
|
89
117
|
children(view),
|
|
90
118
|
index === savedViews.length - 1 && (React__default.createElement(SavedViewDropIndicator, { dropState: dropState, target: { dropPosition: "after", key, type: "item" } }))));
|
|
91
119
|
})));
|
|
@@ -96,22 +124,27 @@ function savedViewKey(view, index) {
|
|
|
96
124
|
}
|
|
97
125
|
/**
|
|
98
126
|
* Drag and drop for the saved views' rows, which React Aria finds by their
|
|
99
|
-
* `data-key`. A drop sends the
|
|
100
|
-
*
|
|
127
|
+
* `data-key`. A drop sends the dragged view and where it landed to
|
|
128
|
+
* `onReorder`.
|
|
101
129
|
*/
|
|
102
|
-
function useSavedViewsDragAndDrop(savedViews, listRef,
|
|
130
|
+
function useSavedViewsDragAndDrop(savedViews, listRef, isReordering, onReorder) {
|
|
103
131
|
const { collection, selectionManager } = useListState({
|
|
104
132
|
children: savedViews.map((view, index) => (React__default.createElement(Item, { key: savedViewKey(view, index), textValue: view.name }, view.name))),
|
|
105
133
|
selectionMode: "none",
|
|
106
134
|
});
|
|
135
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
107
136
|
const dragState = useDraggableCollectionState({
|
|
108
137
|
collection,
|
|
109
138
|
getItems: (keys) => [...keys].map((key) => ({
|
|
110
139
|
"text/plain": collection.getItem(key)?.textValue ?? String(key),
|
|
111
140
|
})),
|
|
141
|
+
// Reorders save one at a time. A pointer drop starts the save before the
|
|
142
|
+
// drag ends, and a disabled handle drops the listener that ends it.
|
|
143
|
+
isDisabled: isReordering && !isDragging,
|
|
112
144
|
// A drop removes the drop target that had focus, and rows can't take
|
|
113
145
|
// focus, so it goes back to the handle that started the drag.
|
|
114
146
|
onDragEnd: ({ keys }) => {
|
|
147
|
+
setIsDragging(false);
|
|
115
148
|
const [key] = keys;
|
|
116
149
|
listRef.current
|
|
117
150
|
?.querySelector(`[data-key="${CSS.escape(String(key))}"] .${styles["view-list-item-drag-handle"]}`)
|
|
@@ -120,36 +153,37 @@ function useSavedViewsDragAndDrop(savedViews, listRef, onUpdate) {
|
|
|
120
153
|
// A keyboard drag starts after the focused row, which the rows can't
|
|
121
154
|
// set themselves, since they can't take focus.
|
|
122
155
|
onDragStart: ({ keys }) => {
|
|
156
|
+
setIsDragging(true);
|
|
123
157
|
const [key] = keys;
|
|
124
158
|
selectionManager.setFocusedKey(key);
|
|
125
159
|
},
|
|
126
160
|
selectionManager,
|
|
127
161
|
});
|
|
128
162
|
useDraggableCollection({}, dragState, listRef);
|
|
129
|
-
const
|
|
130
|
-
const
|
|
163
|
+
const reorder = ({ keys, target }) => {
|
|
164
|
+
const viewFor = (key) => savedViews.find((view, index) => savedViewKey(view, index) === key);
|
|
131
165
|
// Rows only offer drop targets between them, not on them.
|
|
132
166
|
if (target.dropPosition === "on")
|
|
133
167
|
return;
|
|
134
168
|
const [key] = keys;
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
169
|
+
const view = viewFor(key);
|
|
170
|
+
const targetView = viewFor(target.key);
|
|
171
|
+
if (view && targetView) {
|
|
172
|
+
onReorder?.(view, {
|
|
173
|
+
dropPosition: target.dropPosition,
|
|
174
|
+
view: targetView,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
143
177
|
};
|
|
144
178
|
const dropState = useDroppableCollectionState({
|
|
145
179
|
collection,
|
|
146
|
-
onReorder,
|
|
180
|
+
onReorder: reorder,
|
|
147
181
|
selectionManager,
|
|
148
182
|
});
|
|
149
183
|
const { collectionProps } = useDroppableCollection({
|
|
150
184
|
dropTargetDelegate: new ListDropTargetDelegate(collection, listRef),
|
|
151
185
|
keyboardDelegate: new ListKeyboardDelegate({ collection, ref: listRef }),
|
|
152
|
-
onReorder,
|
|
186
|
+
onReorder: reorder,
|
|
153
187
|
}, dropState, listRef);
|
|
154
188
|
return { collectionProps, dragState, dropState };
|
|
155
189
|
}
|
|
@@ -174,7 +208,9 @@ function SavedViewDragHandle({ dragState, itemKey, name, }) {
|
|
|
174
208
|
requestAnimationFrame(() => row.classList.remove(className));
|
|
175
209
|
event.dataTransfer.setDragImage(row, event.clientX - left, event.clientY - top);
|
|
176
210
|
},
|
|
177
|
-
}), "aria-label": `Reorder ${name}`, className: styles["view-list-item-drag-handle"],
|
|
211
|
+
}), "aria-label": `Reorder ${name}`, className: styles["view-list-item-drag-handle"],
|
|
212
|
+
// Stays focusable, since focus returns here after a keyboard drop.
|
|
213
|
+
disabled: dragState.isDisabled, focusableWhenDisabled: true, icon: React__default.createElement(Icon, { "aria-hidden": true, symbol: "general#drag-handle" }), kind: "ghost" }));
|
|
178
214
|
}
|
|
179
215
|
/**
|
|
180
216
|
* A line at a row's edge while dragging. Screen readers reach the hidden
|
|
@@ -198,17 +234,15 @@ function useFocusAfterDelete(savedViews, isDeleteAlertOpen) {
|
|
|
198
234
|
const listRef = useRef(null);
|
|
199
235
|
const doneButtonRef = useRef(null);
|
|
200
236
|
const focusTargetRef = useRef(null);
|
|
201
|
-
// Step 1: the next view's row, or the previous one's
|
|
202
|
-
// last, or Done if
|
|
237
|
+
// Step 1: the actions button on the next view's row, or the previous one's
|
|
238
|
+
// if the deleted view is last, or Done if that row's actions are disabled or
|
|
239
|
+
// it's the only one.
|
|
203
240
|
const focusAfterDelete = (view) => {
|
|
204
241
|
const rows = listRef.current?.querySelectorAll(`.${styles["views-list-item"]}`) ?? [];
|
|
205
242
|
const index = savedViews.findIndex(({ id }) => id === view.id);
|
|
206
243
|
const row = rows[index + 1] ?? rows[index - 1];
|
|
207
|
-
// The row's last enabled button is its delete button, when it has one.
|
|
208
|
-
const buttons = row?.querySelectorAll(`button:not(.${styles["view-list-item-drag-handle"]}, :disabled)`);
|
|
209
244
|
focusTargetRef.current =
|
|
210
|
-
|
|
211
|
-
row?.querySelector("input") ??
|
|
245
|
+
row?.querySelector("button[data-view-actions]:enabled") ??
|
|
212
246
|
doneButtonRef.current;
|
|
213
247
|
};
|
|
214
248
|
// Step 2: a closing alert no longer holds focus, and doesn't take it back
|
|
@@ -221,63 +255,45 @@ function useFocusAfterDelete(savedViews, isDeleteAlertOpen) {
|
|
|
221
255
|
}, [isDeleteAlertOpen]);
|
|
222
256
|
return { doneButtonRef, focusAfterDelete, listRef };
|
|
223
257
|
}
|
|
258
|
+
/** A saved view's name and actions menu. */
|
|
259
|
+
function SavedViewRow({ hasActionsMenu, saveStatus, view, ...menuProps }) {
|
|
260
|
+
return (React__default.createElement(React__default.Fragment, null,
|
|
261
|
+
React__default.createElement("span", { className: styles["view-list-item-name"] }, view.name),
|
|
262
|
+
saveStatus,
|
|
263
|
+
menuProps.isDefault && React__default.createElement(DefaultViewIcon, null),
|
|
264
|
+
hasActionsMenu && React__default.createElement(ViewActionsMenu, { name: view.name, ...menuProps })));
|
|
265
|
+
}
|
|
224
266
|
/**
|
|
225
|
-
*
|
|
226
|
-
*
|
|
227
|
-
*
|
|
228
|
-
* then passes along the name, so the alert shows what the field does.
|
|
267
|
+
* Marks the default view. Set the default from its actions menu. Its tooltip
|
|
268
|
+
* shows on hover only, since the icon can't take focus, and screen readers get
|
|
269
|
+
* the same text from the icon's name.
|
|
229
270
|
*/
|
|
230
|
-
function
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
// Picks up names changed outside this field, including once a rename saves,
|
|
234
|
-
// unless the field has newer edits, which its next blur or Enter sends.
|
|
235
|
-
useEffect(() => {
|
|
236
|
-
const previousName = committedName.current;
|
|
237
|
-
committedName.current = view.name;
|
|
238
|
-
setName((currentName) => currentName === previousName ? view.name : currentName);
|
|
239
|
-
}, [view.name]);
|
|
240
|
-
const commit = () => {
|
|
241
|
-
const trimmedName = name.trim();
|
|
242
|
-
if (!trimmedName) {
|
|
243
|
-
setName(committedName.current);
|
|
244
|
-
return;
|
|
245
|
-
}
|
|
246
|
-
setName(trimmedName);
|
|
247
|
-
if (trimmedName === committedName.current)
|
|
248
|
-
return;
|
|
249
|
-
committedName.current = trimmedName;
|
|
250
|
-
onRename(trimmedName);
|
|
251
|
-
};
|
|
252
|
-
return (React__default.createElement(React__default.Fragment, null,
|
|
253
|
-
React__default.createElement(Input, { autoComplete: "off", className: styles["view-list-item-input"], hideLabel: true, label: `Name for ${view.name}`, readOnly: readOnly, required: !readOnly, value: name, onBlur: readOnly ? undefined : commit, onChange: (event) => setName(event.target.value), onKeyDown: (event) => {
|
|
254
|
-
if (!readOnly &&
|
|
255
|
-
event.key === "Enter" &&
|
|
256
|
-
!event.repeat &&
|
|
257
|
-
!event.nativeEvent.isComposing) {
|
|
258
|
-
commit();
|
|
259
|
-
}
|
|
260
|
-
} }),
|
|
261
|
-
defaultViewToggle,
|
|
262
|
-
hasDeleteButton && (React__default.createElement(DeleteViewButton, { disabled: !onDelete, name: view.name, onClick: (event) => {
|
|
263
|
-
// Safari doesn't focus a button on click, and the alert returns
|
|
264
|
-
// focus to whatever had it when it opened. Focusing also blurs
|
|
265
|
-
// the field, which sends a pending rename.
|
|
266
|
-
event.currentTarget.focus();
|
|
267
|
-
onDelete?.(committedName.current);
|
|
268
|
-
} }))));
|
|
271
|
+
function DefaultViewIcon() {
|
|
272
|
+
return (React__default.createElement(Tooltip, { content: "Default view", placement: "bottom", visualOnly: true },
|
|
273
|
+
React__default.createElement(DefaultViewIconTrigger, null)));
|
|
269
274
|
}
|
|
270
|
-
|
|
271
|
-
|
|
275
|
+
/** Takes the tooltip's trigger wiring, which only buttons and links read. */
|
|
276
|
+
function DefaultViewIconTrigger() {
|
|
277
|
+
const tooltip = useContext(TooltipTriggerContext);
|
|
278
|
+
return (React__default.createElement("span", { ref: tooltip?.ref, ...tooltip?.triggerProps, className: styles["view-list-item-default-icon"] },
|
|
279
|
+
React__default.createElement(Icon, { "aria-label": "Default view", role: "img", symbol: "general#pin" })));
|
|
272
280
|
}
|
|
273
|
-
/**
|
|
274
|
-
function
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
// name to
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
+
/** A view's actions menu. Disabled without any actions. */
|
|
282
|
+
function ViewActionsMenu({ name, ...menuProps }) {
|
|
283
|
+
const triggerRef = useRef(null);
|
|
284
|
+
const { onDelete, onDuplicate, onRename } = menuProps;
|
|
285
|
+
// The name modal and alert return focus to whatever had it when they
|
|
286
|
+
// opened. The menu hasn't returned focus to its button yet by then, so
|
|
287
|
+
// this does it first.
|
|
288
|
+
const withFocusOnTrigger = (open) => open &&
|
|
289
|
+
(() => queueMicrotask(() => {
|
|
290
|
+
triggerRef.current?.focus();
|
|
291
|
+
open();
|
|
292
|
+
}));
|
|
293
|
+
return (React__default.createElement(Dropdown, null,
|
|
294
|
+
React__default.createElement(DropdownTrigger, { disabled: !hasSavedViewMenuActions(menuProps) },
|
|
295
|
+
React__default.createElement(ActionsDropdownIconButton, { ref: triggerRef, "aria-label": `Actions for ${name}`, className: styles["view-list-item-actions"], "data-view-actions": true })),
|
|
296
|
+
React__default.createElement(SavedViewMenu, { ...menuProps, placement: "bottom end", onDelete: withFocusOnTrigger(onDelete), onDuplicate: withFocusOnTrigger(onDuplicate), onRename: withFocusOnTrigger(onRename) })));
|
|
281
297
|
}
|
|
282
298
|
|
|
283
299
|
export { ManageSavedViewsModal };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ManageSavedViewsModal.js","sources":["../../../src/components/DataTable/ManageSavedViewsModal.tsx"],"sourcesContent":["import { Button, IconButton } from \"@components/button\"\nimport { ToggleIconButton } from \"@components/button/ToggleIconButton\"\nimport { Input } from \"@components/input\"\nimport { Modal, ModalBody, ModalFooter, ModalHeader } from \"@components/modal\"\nimport Icon from \"@utilities/Icon\"\nimport React, { type ReactNode, useEffect, useRef, useState } from \"react\"\nimport { ListDropTargetDelegate } from \"react-aria/ListDropTargetDelegate\"\nimport { ListKeyboardDelegate } from \"react-aria/ListKeyboardDelegate\"\nimport { mergeProps } from \"react-aria/mergeProps\"\nimport { useButton } from \"react-aria/useButton\"\nimport {\n useDraggableCollection,\n useDraggableItem,\n} from \"react-aria/useDraggableCollection\"\nimport {\n type DroppableCollectionReorderEvent,\n type DropTarget,\n useDropIndicator,\n useDroppableCollection,\n} from \"react-aria/useDroppableCollection\"\nimport { useVisuallyHidden } from \"react-aria/VisuallyHidden\"\nimport type { Key } from \"react-aria-components/ListBox\"\nimport { Item } from \"react-stately/Item\"\nimport {\n type DraggableCollectionState,\n useDraggableCollectionState,\n} from \"react-stately/useDraggableCollectionState\"\nimport {\n type DroppableCollectionState,\n useDroppableCollectionState,\n} from \"react-stately/useDroppableCollectionState\"\nimport { useListState } from \"react-stately/useListState\"\n\nimport { DeleteSavedViewAlertDialog } from \"./DeleteSavedViewAlertDialog\"\nimport styles from \"./ManageSavedViewsModal.module.css\"\nimport {\n type SavedView,\n savedViewUpdatesForReorder,\n type StaticView,\n} from \"./savedViews\"\nimport { useUpdateSavedViewName } from \"./useUpdateSavedViewName\"\n\nexport interface ManageSavedViewsModalProps {\n defaultViewId: NonNullable<SavedView[\"id\"]>\n onClose: () => void\n /** Called once the user confirms. Omit to leave out the delete buttons. */\n onDelete?: (savedView: SavedView) => void\n /** Omit to leave out the default view buttons. */\n onSetDefault?: (id: NonNullable<SavedView[\"id\"]>) => void\n onUpdate?: (savedView: SavedView) => Promise<SavedView> | SavedView\n open: boolean\n savedViews: SavedView[]\n /** Listed by name before `savedViews`, since they can't be renamed. */\n staticViews: StaticView[]\n}\n\nexport function ManageSavedViewsModal({\n defaultViewId,\n onClose,\n onDelete,\n onSetDefault,\n onUpdate,\n open,\n savedViews,\n staticViews,\n}: ManageSavedViewsModalProps) {\n const updateSavedViewName = useUpdateSavedViewName(onUpdate)\n // Kept after the alert closes, so its text holds during the exit animation.\n const [viewToDelete, setViewToDelete] = useState<SavedView | null>(null)\n const [isDeleteAlertOpen, setIsDeleteAlertOpen] = useState(false)\n // Without this, focus would go to the modal's close button, since the\n // alert returns it to the delete button, which is gone with its row.\n const { doneButtonRef, focusAfterDelete, listRef } = useFocusAfterDelete(\n savedViews,\n isDeleteAlertOpen\n )\n\n const requestDelete = (view: SavedView) => {\n setViewToDelete(view)\n setIsDeleteAlertOpen(true)\n }\n\n // Deleting the default view hands the default back to \"initial\".\n const confirmDelete = () => {\n if (viewToDelete) {\n focusAfterDelete(viewToDelete)\n onDelete?.(viewToDelete)\n if (viewToDelete.id === defaultViewId) onSetDefault?.(\"initial\")\n }\n setIsDeleteAlertOpen(false)\n }\n\n // The default is matched by id, so an unsaved view can't be made the\n // default. Unsetting the default hands it back to \"initial\".\n const renderDefaultViewToggle = ({ id, name }: SavedView) =>\n onSetDefault && id !== undefined ? (\n <DefaultViewToggle\n isDefault={id === defaultViewId}\n name={name}\n onChange={(isDefault) => onSetDefault(isDefault ? id : \"initial\")}\n />\n ) : null\n\n return (\n <Modal dismissible open={open} onClose={onClose}>\n <ModalHeader title=\"Manage views\" />\n <ModalBody>\n <SavedViewsList\n listRef={listRef}\n renderStaticViewActions={(view) => (\n <>\n {renderDefaultViewToggle(view)}\n {/* Static views can't be deleted, but keep the column lined up. */}\n {onDelete && <DeleteViewButton disabled name={view.name} />}\n </>\n )}\n savedViews={savedViews}\n staticViews={staticViews}\n onUpdate={onUpdate}\n >\n {(view) => (\n <SavedViewRow\n defaultViewToggle={renderDefaultViewToggle(view)}\n hasDeleteButton={Boolean(onDelete)}\n // Updates and deletes are matched by id, so an unsaved view\n // can't be renamed or deleted.\n readOnly={!onUpdate || view.id === undefined}\n view={view}\n onDelete={\n onDelete && view.id !== undefined\n ? (name) => requestDelete({ ...view, name })\n : undefined\n }\n onRename={(name) => updateSavedViewName(view, name)}\n />\n )}\n </SavedViewsList>\n </ModalBody>\n <ModalFooter>\n <Button\n ref={doneButtonRef}\n kind=\"primary\"\n label=\"Done\"\n onClick={onClose}\n />\n </ModalFooter>\n {onDelete && (\n <DeleteSavedViewAlertDialog\n open={isDeleteAlertOpen}\n view={viewToDelete}\n onCancel={() => setIsDeleteAlertOpen(false)}\n onConfirm={confirmDelete}\n />\n )}\n </Modal>\n )\n}\n\nManageSavedViewsModal.displayName = \"ManageSavedViewsModal\"\n\n/**\n * The static views, then the saved views with drag handles. Mounts with the\n * modal's content, since React Aria registers the list as a drop target when\n * its hooks mount, and the modal stays mounted while closed.\n */\nfunction SavedViewsList({\n children,\n listRef,\n onUpdate,\n renderStaticViewActions,\n savedViews,\n staticViews,\n}: {\n children: (view: SavedView) => ReactNode\n listRef: React.RefObject<HTMLOListElement>\n onUpdate?: ManageSavedViewsModalProps[\"onUpdate\"]\n renderStaticViewActions: (view: StaticView) => ReactNode\n savedViews: SavedView[]\n staticViews: StaticView[]\n}) {\n const { collectionProps, dragState, dropState } = useSavedViewsDragAndDrop(\n savedViews,\n listRef,\n onUpdate\n )\n\n return (\n <ol ref={listRef} {...collectionProps} className={styles[\"views-list\"]}>\n {staticViews.map((view) => (\n <li key={view.id} className={styles[\"views-list-item--static\"]}>\n <span className={styles[\"view-list-item-static-name\"]}>\n {view.name}\n </span>\n {renderStaticViewActions(view)}\n </li>\n ))}\n {savedViews.map((view, index) => {\n const key = savedViewKey(view, index)\n return (\n <li\n key={key}\n className={styles[\"views-list-item\"]}\n data-dragging={dragState.isDragging(key) || undefined}\n data-key={key}\n >\n <SavedViewDropIndicator\n dropState={dropState}\n target={{ dropPosition: \"before\", key, type: \"item\" }}\n />\n {/* A single view has no order to change, and updates are matched\n by id, so an unsaved view can't be reordered. */}\n {savedViews.length > 1 && onUpdate && view.id !== undefined && (\n <SavedViewDragHandle\n dragState={dragState}\n itemKey={key}\n name={view.name}\n />\n )}\n {children(view)}\n {index === savedViews.length - 1 && (\n <SavedViewDropIndicator\n dropState={dropState}\n target={{ dropPosition: \"after\", key, type: \"item\" }}\n />\n )}\n </li>\n )\n })}\n </ol>\n )\n}\n\n/** A string, since React Aria's collection keys an `Item` by its React key. */\nfunction savedViewKey(view: SavedView, index: number): Key {\n return String(view.id ?? `unsaved-view-${index}`)\n}\n\n/**\n * Drag and drop for the saved views' rows, which React Aria finds by their\n * `data-key`. A drop sends the views with new sort keys to `onUpdate`, and\n * the row moves once they're passed back in.\n */\nfunction useSavedViewsDragAndDrop(\n savedViews: SavedView[],\n listRef: React.RefObject<HTMLOListElement | null>,\n onUpdate?: ManageSavedViewsModalProps[\"onUpdate\"]\n) {\n const { collection, selectionManager } = useListState({\n children: savedViews.map((view, index) => (\n <Item key={savedViewKey(view, index)} textValue={view.name}>\n {view.name}\n </Item>\n )),\n selectionMode: \"none\",\n })\n\n const dragState = useDraggableCollectionState({\n collection,\n getItems: (keys) =>\n [...keys].map((key) => ({\n \"text/plain\": collection.getItem(key)?.textValue ?? String(key),\n })),\n\n // A drop removes the drop target that had focus, and rows can't take\n // focus, so it goes back to the handle that started the drag.\n onDragEnd: ({ keys }) => {\n const [key] = keys\n listRef.current\n ?.querySelector<HTMLElement>(\n `[data-key=\"${CSS.escape(String(key))}\"] .${styles[\"view-list-item-drag-handle\"]}`\n )\n ?.focus()\n },\n\n // A keyboard drag starts after the focused row, which the rows can't\n // set themselves, since they can't take focus.\n onDragStart: ({ keys }) => {\n const [key] = keys\n selectionManager.setFocusedKey(key)\n },\n selectionManager,\n })\n useDraggableCollection({}, dragState, listRef)\n\n const onReorder = ({ keys, target }: DroppableCollectionReorderEvent) => {\n const indexOf = (key: Key) =>\n savedViews.findIndex((view, index) => savedViewKey(view, index) === key)\n // Rows only offer drop targets between them, not on them.\n if (target.dropPosition === \"on\") return\n const [key] = keys\n const updates = savedViewUpdatesForReorder(\n savedViews,\n indexOf(key),\n indexOf(target.key),\n target.dropPosition\n )\n // Updates are matched by id, so a reorder that needs to update an unsaved\n // view can't be saved in full. Saving part of it would leave the order\n // unchanged anyway.\n if (updates.some((view) => view.id === undefined)) return\n for (const view of updates) onUpdate?.(view)\n }\n const dropState = useDroppableCollectionState({\n collection,\n onReorder,\n selectionManager,\n })\n const { collectionProps } = useDroppableCollection(\n {\n dropTargetDelegate: new ListDropTargetDelegate(collection, listRef),\n keyboardDelegate: new ListKeyboardDelegate({ collection, ref: listRef }),\n onReorder,\n },\n dropState,\n listRef\n )\n\n return { collectionProps, dragState, dropState }\n}\n\n/**\n * Starts a drag with a pointer, or with Enter or Space. A pointer drag shows\n * the whole row, held where the pointer grabbed it, rather than the handle.\n */\nfunction SavedViewDragHandle({\n dragState,\n itemKey,\n name,\n}: {\n dragState: DraggableCollectionState\n itemKey: Key\n name: string\n}) {\n const ref = useRef<HTMLButtonElement>(null)\n const { dragButtonProps, dragProps } = useDraggableItem(\n { hasDragButton: true, key: itemKey },\n dragState\n )\n const { buttonProps } = useButton(dragButtonProps, ref)\n\n return (\n <IconButton\n ref={ref}\n {...mergeProps(buttonProps, dragProps, {\n onDragStart: (event: React.DragEvent<HTMLButtonElement>) => {\n const row = event.currentTarget.closest(\"li\")\n if (!row) return\n const { left, top } = row.getBoundingClientRect()\n // The browser snapshots the row once this handler returns, so the\n // ghost styles apply only to the snapshot.\n const className = styles[\"views-list-item--drag-ghost\"]\n row.classList.add(className)\n requestAnimationFrame(() => row.classList.remove(className))\n event.dataTransfer.setDragImage(\n row,\n event.clientX - left,\n event.clientY - top\n )\n },\n })}\n aria-label={`Reorder ${name}`}\n className={styles[\"view-list-item-drag-handle\"]}\n icon={<Icon aria-hidden symbol=\"general#drag-handle\" />}\n kind=\"ghost\"\n />\n )\n}\n\n/**\n * A line at a row's edge while dragging. Screen readers reach the hidden\n * button inside it as a drop target.\n */\nfunction SavedViewDropIndicator({\n dropState,\n target,\n}: {\n dropState: DroppableCollectionState\n target: DropTarget\n}) {\n const ref = useRef<HTMLDivElement>(null)\n const { dropIndicatorProps, isDropTarget, isHidden } = useDropIndicator(\n { target },\n dropState,\n ref\n )\n const { visuallyHiddenProps } = useVisuallyHidden()\n if (isHidden) return null\n\n return (\n <div\n className={styles[\"view-list-drop-indicator\"]}\n data-drop-position={\n target.type === \"item\" ? target.dropPosition : undefined\n }\n data-drop-target={isDropTarget || undefined}\n >\n <div\n {...visuallyHiddenProps}\n role=\"button\"\n {...dropIndicatorProps}\n ref={ref}\n />\n </div>\n )\n}\n\n/**\n * Moves focus off a deleted view's row in two steps: `focusAfterDelete` picks\n * the target while the row is still there, and focus moves to it once the\n * alert starts closing.\n */\nfunction useFocusAfterDelete(\n savedViews: SavedView[],\n isDeleteAlertOpen: boolean\n) {\n const listRef = useRef<HTMLOListElement>(null)\n const doneButtonRef = useRef<HTMLButtonElement>(null)\n const focusTargetRef = useRef<HTMLElement | null>(null)\n\n // Step 1: the next view's row, or the previous one's if the deleted view is\n // last, or Done if it's the only one.\n const focusAfterDelete = (view: SavedView) => {\n const rows =\n listRef.current?.querySelectorAll(`.${styles[\"views-list-item\"]}`) ?? []\n const index = savedViews.findIndex(({ id }) => id === view.id)\n const row = rows[index + 1] ?? rows[index - 1]\n // The row's last enabled button is its delete button, when it has one.\n const buttons = row?.querySelectorAll<HTMLElement>(\n `button:not(.${styles[\"view-list-item-drag-handle\"]}, :disabled)`\n )\n focusTargetRef.current =\n buttons?.[buttons.length - 1] ??\n row?.querySelector(\"input\") ??\n doneButtonRef.current\n }\n\n // Step 2: a closing alert no longer holds focus, and doesn't take it back\n // once focus is outside it.\n useEffect(() => {\n if (isDeleteAlertOpen) return\n focusTargetRef.current?.focus()\n focusTargetRef.current = null\n }, [isDeleteAlertOpen])\n\n return { doneButtonRef, focusAfterDelete, listRef }\n}\n\n/**\n * A saved view's name field, default view toggle, and delete button. Renames on blur or Enter. An\n * empty name reverts to the current one. Tracks the last name it sent, so\n * Enter followed by blur renames once. Deleting sends a pending rename first,\n * then passes along the name, so the alert shows what the field does.\n */\nfunction SavedViewRow({\n defaultViewToggle,\n hasDeleteButton,\n onDelete,\n onRename,\n readOnly,\n view,\n}: {\n defaultViewToggle: ReactNode\n /** Shows the delete button, disabled without `onDelete`. */\n hasDeleteButton: boolean\n onDelete?: (name: string) => void\n onRename: (name: string) => void\n readOnly: boolean\n view: SavedView\n}) {\n const [name, setName] = useState(view.name)\n const committedName = useRef(view.name)\n\n // Picks up names changed outside this field, including once a rename saves,\n // unless the field has newer edits, which its next blur or Enter sends.\n useEffect(() => {\n const previousName = committedName.current\n committedName.current = view.name\n setName((currentName) =>\n currentName === previousName ? view.name : currentName\n )\n }, [view.name])\n\n const commit = () => {\n const trimmedName = name.trim()\n if (!trimmedName) {\n setName(committedName.current)\n return\n }\n setName(trimmedName)\n if (trimmedName === committedName.current) return\n committedName.current = trimmedName\n onRename(trimmedName)\n }\n\n return (\n <>\n <Input\n autoComplete=\"off\"\n className={styles[\"view-list-item-input\"]}\n hideLabel\n label={`Name for ${view.name}`}\n readOnly={readOnly}\n required={!readOnly}\n value={name}\n onBlur={readOnly ? undefined : commit}\n onChange={(event) => setName(event.target.value)}\n onKeyDown={(event) => {\n if (\n !readOnly &&\n event.key === \"Enter\" &&\n !event.repeat &&\n !event.nativeEvent.isComposing\n ) {\n commit()\n }\n }}\n />\n {defaultViewToggle}\n {hasDeleteButton && (\n <DeleteViewButton\n disabled={!onDelete}\n name={view.name}\n onClick={(event) => {\n // Safari doesn't focus a button on click, and the alert returns\n // focus to whatever had it when it opened. Focusing also blurs\n // the field, which sends a pending rename.\n event.currentTarget.focus()\n onDelete?.(committedName.current)\n }}\n />\n )}\n </>\n )\n}\n\nfunction DeleteViewButton({\n disabled,\n name,\n onClick,\n}: {\n disabled?: boolean\n name: string\n onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void\n}) {\n return (\n <IconButton\n aria-label={`Delete ${name}`}\n disabled={disabled}\n icon={<Icon aria-hidden symbol=\"general#trash\" />}\n kind=\"ghost\"\n tooltip=\"Delete\"\n onClick={onClick}\n />\n )\n}\n\n/** Makes a view the default, or hands the default back to \"initial\". */\nfunction DefaultViewToggle({\n isDefault,\n name,\n onChange,\n}: {\n isDefault: boolean\n name: string\n onChange: (isDefault: boolean) => void\n}) {\n return (\n <ToggleIconButton\n // Only one view is the default, so its label doesn't need the view's\n // name to be unique.\n aria-label={isDefault ? \"Default view\" : `Set ${name} as default`}\n icon={\n <Icon\n aria-hidden\n symbol={isDefault ? \"general#pin\" : \"general#outlined-pin\"}\n />\n }\n // Only the default's pin is blue.\n kind={isDefault ? \"ghost-interaction\" : \"ghost\"}\n pressed={isDefault}\n tooltip={isDefault ? \"Default view\" : \"Set as default\"}\n onChange={onChange}\n />\n )\n}\n"],"names":["React"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ManageSavedViewsModal.js","sources":["../../../src/components/DataTable/ManageSavedViewsModal.tsx"],"sourcesContent":["import {\n ActionsDropdownIconButton,\n Button,\n IconButton,\n} from \"@components/button\"\nimport { Dropdown, DropdownTrigger } from \"@components/dropdown\"\nimport { Tooltip } from \"@components/internal/tooltip\"\nimport { TooltipTriggerContext } from \"@components/internal/tooltip/TooltipTriggerContext\"\nimport { Modal, ModalBody, ModalFooter, ModalHeader } from \"@components/modal\"\nimport Icon from \"@utilities/Icon\"\nimport React, {\n type ReactNode,\n useContext,\n useEffect,\n useRef,\n useState,\n} from \"react\"\nimport { ListDropTargetDelegate } from \"react-aria/ListDropTargetDelegate\"\nimport { ListKeyboardDelegate } from \"react-aria/ListKeyboardDelegate\"\nimport { mergeProps } from \"react-aria/mergeProps\"\nimport { useButton } from \"react-aria/useButton\"\nimport {\n useDraggableCollection,\n useDraggableItem,\n} from \"react-aria/useDraggableCollection\"\nimport {\n type DroppableCollectionReorderEvent,\n type DropTarget,\n useDropIndicator,\n useDroppableCollection,\n} from \"react-aria/useDroppableCollection\"\nimport { useVisuallyHidden } from \"react-aria/VisuallyHidden\"\nimport type { Key } from \"react-aria-components/ListBox\"\nimport { Item } from \"react-stately/Item\"\nimport {\n type DraggableCollectionState,\n useDraggableCollectionState,\n} from \"react-stately/useDraggableCollectionState\"\nimport {\n type DroppableCollectionState,\n useDroppableCollectionState,\n} from \"react-stately/useDroppableCollectionState\"\nimport { useListState } from \"react-stately/useListState\"\n\nimport { DeleteSavedViewAlertDialog } from \"./DeleteSavedViewAlertDialog\"\nimport styles from \"./ManageSavedViewsModal.module.css\"\nimport { NewSavedViewModal } from \"./NewSavedViewModal\"\nimport {\n hasSavedViewMenuActions,\n SavedViewMenu,\n type SavedViewMenuProps,\n} from \"./SavedViewMenu\"\nimport { type SavedView, type StaticView } from \"./savedViews\"\nimport { useSavedViewNameModal } from \"./useSavedViewNameModal\"\nimport type { ReorderTarget } from \"./useSavedViewsState\"\nimport { SaveStatusIcon, useSaveStatus } from \"./useSaveStatus\"\n\nexport interface ManageSavedViewsModalProps {\n defaultViewId: NonNullable<SavedView[\"id\"]>\n /** Disables the drag handles while a reorder saves. */\n isReordering?: boolean\n onClose: () => void\n /**\n * Called with a view's duplicate once the user names it. Omit to leave out\n * the Duplicate actions.\n */\n onCreate?: (\n savedView: Omit<SavedView, \"id\">\n ) => Promise<SavedView | undefined> | SavedView\n /** Called once the user confirms. Omit to leave out the Delete actions. */\n onDelete?: (savedView: SavedView) => Promise<void>\n /** Omit to leave out the drag handles. */\n onReorder?: (savedView: SavedView, target: ReorderTarget) => Promise<void>\n /** Omit to leave out the Set as default actions. */\n onSetDefault?: (id: NonNullable<SavedView[\"id\"]>) => Promise<void>\n /** Omit to leave out the Rename actions. */\n onUpdate?: (\n savedView: SavedView\n ) => Promise<SavedView | undefined> | SavedView\n open: boolean\n savedViews: SavedView[]\n /** Listed before `savedViews`, and can't be renamed, reordered, or deleted. */\n staticViews: StaticView[]\n}\n\nexport function ManageSavedViewsModal({\n defaultViewId,\n isReordering = false,\n onClose,\n onCreate,\n onDelete,\n onReorder,\n onSetDefault,\n onUpdate,\n open,\n savedViews,\n staticViews,\n}: ManageSavedViewsModalProps) {\n // Kept after the alert closes, so its text holds during the exit animation.\n const [viewToDelete, setViewToDelete] = useState<SavedView | null>(null)\n const [isDeleteAlertOpen, setIsDeleteAlertOpen] = useState(false)\n // Without this, focus would go to the modal's close button, since the\n // alert returns it to the actions button, which is gone with its row.\n const { doneButtonRef, focusAfterDelete, listRef } = useFocusAfterDelete(\n savedViews,\n isDeleteAlertOpen\n )\n const nameModal = useSavedViewNameModal(onUpdate)\n const saveStatus = useSaveStatus()\n\n // Listed after the other saved views. Managing views leaves the selection\n // alone, so unlike the context menu's Duplicate, it doesn't select the\n // duplicate. Its status shows on the view it was duplicated from, since\n // it isn't listed until it saves.\n const createDuplicate = (\n view: SavedView,\n duplicate: Omit<SavedView, \"id\">\n ) => {\n if (onCreate) saveStatus.track(view.id, onCreate(duplicate), duplicate.name)\n }\n\n const requestDelete = (view: SavedView) => {\n setViewToDelete(view)\n setIsDeleteAlertOpen(true)\n }\n\n const confirmDelete = () => {\n if (viewToDelete && onDelete) {\n focusAfterDelete(viewToDelete)\n saveStatus.track(\n viewToDelete.id,\n onDelete(viewToDelete),\n viewToDelete.name\n )\n }\n setIsDeleteAlertOpen(false)\n }\n\n // Every row gets an actions button, disabled without actions, so the\n // buttons line up.\n const hasViewActions = Boolean(\n onCreate || onDelete || onSetDefault || onUpdate\n )\n\n // The actions static views share with saved views. The default is matched\n // by id, so an unsaved view can't be made the default.\n const viewActions = (view: SavedView) => {\n const { id } = view\n return {\n isDefault: id === defaultViewId,\n onDuplicate: onCreate\n ? () =>\n nameModal.openDuplicate(view, (duplicate) =>\n createDuplicate(view, duplicate)\n )\n : undefined,\n onSetDefault:\n onSetDefault && id !== undefined\n ? () => saveStatus.track(id, onSetDefault(id), view.name)\n : undefined,\n }\n }\n\n return (\n <Modal dismissible open={open} size=\"sm\" onClose={onClose}>\n <ModalHeader title=\"Manage views\" />\n <ModalBody>\n <SavedViewsList\n isReordering={isReordering}\n listRef={listRef}\n renderStaticViewActions={(view) => (\n <>\n <SaveStatusIcon status={saveStatus.statusFor(view.id)} />\n {view.id === defaultViewId && <DefaultViewIcon />}\n {hasViewActions && (\n <ViewActionsMenu name={view.name} {...viewActions(view)} />\n )}\n </>\n )}\n savedViews={savedViews}\n staticViews={staticViews}\n onReorder={\n onReorder &&\n ((view, target) =>\n saveStatus.track(view.id, onReorder(view, target), view.name))\n }\n >\n {(view) => (\n <SavedViewRow\n hasActionsMenu={hasViewActions}\n view={view}\n {...viewActions(view)}\n saveStatus={\n <SaveStatusIcon status={saveStatus.statusFor(view.id)} />\n }\n // Updates and deletes are matched by id, so an unsaved view\n // can't be renamed or deleted.\n onDelete={\n onDelete && view.id !== undefined\n ? () => requestDelete(view)\n : undefined\n }\n onRename={\n onUpdate && view.id !== undefined\n ? () =>\n nameModal.openRename(view, (saving) =>\n saveStatus.track(view.id, saving, view.name)\n )\n : undefined\n }\n />\n )}\n </SavedViewsList>\n </ModalBody>\n <ModalFooter>\n <Button\n ref={doneButtonRef}\n kind=\"primary\"\n label=\"Done\"\n onClick={onClose}\n />\n </ModalFooter>\n {onDelete && (\n <DeleteSavedViewAlertDialog\n open={isDeleteAlertOpen}\n view={viewToDelete}\n onCancel={() => setIsDeleteAlertOpen(false)}\n onConfirm={confirmDelete}\n />\n )}\n {(onCreate || onUpdate) && (\n <NewSavedViewModal {...nameModal.modalProps} />\n )}\n </Modal>\n )\n}\n\nManageSavedViewsModal.displayName = \"ManageSavedViewsModal\"\n\n/**\n * The static views, then the saved views with drag handles. Mounts with the\n * modal's content, since React Aria registers the list as a drop target when\n * its hooks mount, and the modal stays mounted while closed.\n */\nfunction SavedViewsList({\n children,\n isReordering,\n listRef,\n onReorder,\n renderStaticViewActions,\n savedViews,\n staticViews,\n}: {\n children: (view: SavedView) => ReactNode\n isReordering: boolean\n listRef: React.RefObject<HTMLOListElement>\n onReorder?: ManageSavedViewsModalProps[\"onReorder\"]\n renderStaticViewActions: (view: StaticView) => ReactNode\n savedViews: SavedView[]\n staticViews: StaticView[]\n}) {\n const { collectionProps, dragState, dropState } = useSavedViewsDragAndDrop(\n savedViews,\n listRef,\n isReordering,\n onReorder\n )\n\n return (\n <ol ref={listRef} {...collectionProps} className={styles[\"views-list\"]}>\n {staticViews.map((view) => (\n <li key={view.id} className={styles[\"views-list-item--static\"]}>\n <span className={styles[\"view-list-item-name\"]}>{view.name}</span>\n {renderStaticViewActions(view)}\n </li>\n ))}\n {savedViews.map((view, index) => {\n const key = savedViewKey(view, index)\n return (\n <li\n key={key}\n className={styles[\"views-list-item\"]}\n data-dragging={dragState.isDragging(key) || undefined}\n data-key={key}\n >\n <SavedViewDropIndicator\n dropState={dropState}\n target={{ dropPosition: \"before\", key, type: \"item\" }}\n />\n {/* A single view has no order to change, and the new position is\n saved by id, so an unsaved view can't be reordered. */}\n {savedViews.length > 1 && onReorder && view.id !== undefined && (\n <SavedViewDragHandle\n dragState={dragState}\n itemKey={key}\n name={view.name}\n />\n )}\n {children(view)}\n {index === savedViews.length - 1 && (\n <SavedViewDropIndicator\n dropState={dropState}\n target={{ dropPosition: \"after\", key, type: \"item\" }}\n />\n )}\n </li>\n )\n })}\n </ol>\n )\n}\n\n/** A string, since React Aria's collection keys an `Item` by its React key. */\nfunction savedViewKey(view: SavedView, index: number): Key {\n return String(view.id ?? `unsaved-view-${index}`)\n}\n\n/**\n * Drag and drop for the saved views' rows, which React Aria finds by their\n * `data-key`. A drop sends the dragged view and where it landed to\n * `onReorder`.\n */\nfunction useSavedViewsDragAndDrop(\n savedViews: SavedView[],\n listRef: React.RefObject<HTMLOListElement | null>,\n isReordering: boolean,\n onReorder?: ManageSavedViewsModalProps[\"onReorder\"]\n) {\n const { collection, selectionManager } = useListState({\n children: savedViews.map((view, index) => (\n <Item key={savedViewKey(view, index)} textValue={view.name}>\n {view.name}\n </Item>\n )),\n selectionMode: \"none\",\n })\n const [isDragging, setIsDragging] = useState(false)\n\n const dragState = useDraggableCollectionState({\n collection,\n getItems: (keys) =>\n [...keys].map((key) => ({\n \"text/plain\": collection.getItem(key)?.textValue ?? String(key),\n })),\n\n // Reorders save one at a time. A pointer drop starts the save before the\n // drag ends, and a disabled handle drops the listener that ends it.\n isDisabled: isReordering && !isDragging,\n\n // A drop removes the drop target that had focus, and rows can't take\n // focus, so it goes back to the handle that started the drag.\n onDragEnd: ({ keys }) => {\n setIsDragging(false)\n const [key] = keys\n listRef.current\n ?.querySelector<HTMLElement>(\n `[data-key=\"${CSS.escape(String(key))}\"] .${styles[\"view-list-item-drag-handle\"]}`\n )\n ?.focus()\n },\n\n // A keyboard drag starts after the focused row, which the rows can't\n // set themselves, since they can't take focus.\n onDragStart: ({ keys }) => {\n setIsDragging(true)\n const [key] = keys\n selectionManager.setFocusedKey(key)\n },\n selectionManager,\n })\n useDraggableCollection({}, dragState, listRef)\n\n const reorder = ({ keys, target }: DroppableCollectionReorderEvent) => {\n const viewFor = (key: Key) =>\n savedViews.find((view, index) => savedViewKey(view, index) === key)\n // Rows only offer drop targets between them, not on them.\n if (target.dropPosition === \"on\") return\n const [key] = keys\n const view = viewFor(key)\n const targetView = viewFor(target.key)\n if (view && targetView) {\n onReorder?.(view, {\n dropPosition: target.dropPosition,\n view: targetView,\n })\n }\n }\n const dropState = useDroppableCollectionState({\n collection,\n onReorder: reorder,\n selectionManager,\n })\n const { collectionProps } = useDroppableCollection(\n {\n dropTargetDelegate: new ListDropTargetDelegate(collection, listRef),\n keyboardDelegate: new ListKeyboardDelegate({ collection, ref: listRef }),\n onReorder: reorder,\n },\n dropState,\n listRef\n )\n\n return { collectionProps, dragState, dropState }\n}\n\n/**\n * Starts a drag with a pointer, or with Enter or Space. A pointer drag shows\n * the whole row, held where the pointer grabbed it, rather than the handle.\n */\nfunction SavedViewDragHandle({\n dragState,\n itemKey,\n name,\n}: {\n dragState: DraggableCollectionState\n itemKey: Key\n name: string\n}) {\n const ref = useRef<HTMLButtonElement>(null)\n const { dragButtonProps, dragProps } = useDraggableItem(\n { hasDragButton: true, key: itemKey },\n dragState\n )\n const { buttonProps } = useButton(dragButtonProps, ref)\n\n return (\n <IconButton\n ref={ref}\n {...mergeProps(buttonProps, dragProps, {\n onDragStart: (event: React.DragEvent<HTMLButtonElement>) => {\n const row = event.currentTarget.closest(\"li\")\n if (!row) return\n const { left, top } = row.getBoundingClientRect()\n // The browser snapshots the row once this handler returns, so the\n // ghost styles apply only to the snapshot.\n const className = styles[\"views-list-item--drag-ghost\"]\n row.classList.add(className)\n requestAnimationFrame(() => row.classList.remove(className))\n event.dataTransfer.setDragImage(\n row,\n event.clientX - left,\n event.clientY - top\n )\n },\n })}\n aria-label={`Reorder ${name}`}\n className={styles[\"view-list-item-drag-handle\"]}\n // Stays focusable, since focus returns here after a keyboard drop.\n disabled={dragState.isDisabled}\n focusableWhenDisabled\n icon={<Icon aria-hidden symbol=\"general#drag-handle\" />}\n kind=\"ghost\"\n />\n )\n}\n\n/**\n * A line at a row's edge while dragging. Screen readers reach the hidden\n * button inside it as a drop target.\n */\nfunction SavedViewDropIndicator({\n dropState,\n target,\n}: {\n dropState: DroppableCollectionState\n target: DropTarget\n}) {\n const ref = useRef<HTMLDivElement>(null)\n const { dropIndicatorProps, isDropTarget, isHidden } = useDropIndicator(\n { target },\n dropState,\n ref\n )\n const { visuallyHiddenProps } = useVisuallyHidden()\n if (isHidden) return null\n\n return (\n <div\n className={styles[\"view-list-drop-indicator\"]}\n data-drop-position={\n target.type === \"item\" ? target.dropPosition : undefined\n }\n data-drop-target={isDropTarget || undefined}\n >\n <div\n {...visuallyHiddenProps}\n role=\"button\"\n {...dropIndicatorProps}\n ref={ref}\n />\n </div>\n )\n}\n\n/**\n * Moves focus off a deleted view's row in two steps: `focusAfterDelete` picks\n * the target while the row is still there, and focus moves to it once the\n * alert starts closing.\n */\nfunction useFocusAfterDelete(\n savedViews: SavedView[],\n isDeleteAlertOpen: boolean\n) {\n const listRef = useRef<HTMLOListElement>(null)\n const doneButtonRef = useRef<HTMLButtonElement>(null)\n const focusTargetRef = useRef<HTMLElement | null>(null)\n\n // Step 1: the actions button on the next view's row, or the previous one's\n // if the deleted view is last, or Done if that row's actions are disabled or\n // it's the only one.\n const focusAfterDelete = (view: SavedView) => {\n const rows =\n listRef.current?.querySelectorAll(`.${styles[\"views-list-item\"]}`) ?? []\n const index = savedViews.findIndex(({ id }) => id === view.id)\n const row = rows[index + 1] ?? rows[index - 1]\n focusTargetRef.current =\n row?.querySelector<HTMLElement>(\"button[data-view-actions]:enabled\") ??\n doneButtonRef.current\n }\n\n // Step 2: a closing alert no longer holds focus, and doesn't take it back\n // once focus is outside it.\n useEffect(() => {\n if (isDeleteAlertOpen) return\n focusTargetRef.current?.focus()\n focusTargetRef.current = null\n }, [isDeleteAlertOpen])\n\n return { doneButtonRef, focusAfterDelete, listRef }\n}\n\n/** A saved view's name and actions menu. */\nfunction SavedViewRow({\n hasActionsMenu,\n saveStatus,\n view,\n ...menuProps\n}: SavedViewMenuProps & {\n /** Shows the actions menu, disabled without any actions. */\n hasActionsMenu: boolean\n saveStatus: ReactNode\n view: SavedView\n}) {\n return (\n <>\n <span className={styles[\"view-list-item-name\"]}>{view.name}</span>\n {saveStatus}\n {menuProps.isDefault && <DefaultViewIcon />}\n {hasActionsMenu && <ViewActionsMenu name={view.name} {...menuProps} />}\n </>\n )\n}\n\n/**\n * Marks the default view. Set the default from its actions menu. Its tooltip\n * shows on hover only, since the icon can't take focus, and screen readers get\n * the same text from the icon's name.\n */\nfunction DefaultViewIcon() {\n return (\n <Tooltip content=\"Default view\" placement=\"bottom\" visualOnly>\n <DefaultViewIconTrigger />\n </Tooltip>\n )\n}\n\n/** Takes the tooltip's trigger wiring, which only buttons and links read. */\nfunction DefaultViewIconTrigger() {\n const tooltip = useContext(TooltipTriggerContext)\n\n return (\n <span\n ref={tooltip?.ref}\n {...tooltip?.triggerProps}\n className={styles[\"view-list-item-default-icon\"]}\n >\n <Icon aria-label=\"Default view\" role=\"img\" symbol=\"general#pin\" />\n </span>\n )\n}\n\n/** A view's actions menu. Disabled without any actions. */\nfunction ViewActionsMenu({\n name,\n ...menuProps\n}: SavedViewMenuProps & { name: string }) {\n const triggerRef = useRef<HTMLButtonElement>(null)\n const { onDelete, onDuplicate, onRename } = menuProps\n\n // The name modal and alert return focus to whatever had it when they\n // opened. The menu hasn't returned focus to its button yet by then, so\n // this does it first.\n const withFocusOnTrigger = (open?: () => void) =>\n open &&\n (() =>\n queueMicrotask(() => {\n triggerRef.current?.focus()\n open()\n }))\n\n return (\n <Dropdown>\n <DropdownTrigger disabled={!hasSavedViewMenuActions(menuProps)}>\n <ActionsDropdownIconButton\n ref={triggerRef}\n aria-label={`Actions for ${name}`}\n className={styles[\"view-list-item-actions\"]}\n // Lets `useFocusAfterDelete` find a neighboring row's actions.\n data-view-actions\n />\n </DropdownTrigger>\n <SavedViewMenu\n {...menuProps}\n placement=\"bottom end\"\n onDelete={withFocusOnTrigger(onDelete)}\n onDuplicate={withFocusOnTrigger(onDuplicate)}\n onRename={withFocusOnTrigger(onRename)}\n />\n </Dropdown>\n )\n}\n"],"names":["React"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var styles = {"views-list":"views-list-3AMVI","views-list-item":"views-list-item-cWGsC","view-list-drop-indicator":"view-list-drop-indicator-zyDIt","view-list-item-
|
|
1
|
+
var styles = {"views-list":"views-list-3AMVI","views-list-item":"views-list-item-cWGsC","views-list-item--static":"views-list-item--static-9zGpJ","view-list-drop-indicator":"view-list-drop-indicator-zyDIt","view-list-item-default-icon":"view-list-item-default-icon-d-QS1","view-list-item-actions":"view-list-item-actions-NFBUU","view-list-item-drag-handle":"view-list-item-drag-handle-fiO5Z","views-list-item--drag-ghost":"views-list-item--drag-ghost-zEVbL","view-list-item-name":"view-list-item-name-VRsyM"};
|
|
2
2
|
|
|
3
3
|
export { styles as default };
|
|
4
4
|
//# sourceMappingURL=ManageSavedViewsModal.module.css.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NewSavedViewButton.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/NewSavedViewButton.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB;AAED,wBAAgB,kBAAkB,CAAC,EAAE,OAAO,EAAE,EAAE,uBAAuB,
|
|
1
|
+
{"version":3,"file":"NewSavedViewButton.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/NewSavedViewButton.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB;AAED,wBAAgB,kBAAkB,CAAC,EAAE,OAAO,EAAE,EAAE,uBAAuB,qBAUtE;yBAVe,kBAAkB"}
|
|
@@ -9,7 +9,7 @@ import Icon from '../../utilities/Icon.js';
|
|
|
9
9
|
import React__default from 'react';
|
|
10
10
|
|
|
11
11
|
function NewSavedViewButton({ onClick }) {
|
|
12
|
-
return (React__default.createElement(IconButton, {
|
|
12
|
+
return (React__default.createElement(IconButton, { className: "tds-btn--data-table-saved-views-new-view", icon: React__default.createElement(Icon, { "aria-hidden": true, symbol: "general#plus" }), kind: "pill", tooltip: "Add new view", onClick: onClick }));
|
|
13
13
|
}
|
|
14
14
|
NewSavedViewButton.displayName = "NewSavedViewButton";
|
|
15
15
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NewSavedViewButton.js","sources":["../../../src/components/DataTable/NewSavedViewButton.tsx"],"sourcesContent":["import { IconButton } from \"@components/button\"\nimport Icon from \"@utilities/Icon\"\nimport React from \"react\"\n\nexport interface NewSavedViewButtonProps {\n onClick: () => void\n}\n\nexport function NewSavedViewButton({ onClick }: NewSavedViewButtonProps) {\n return (\n <IconButton\n
|
|
1
|
+
{"version":3,"file":"NewSavedViewButton.js","sources":["../../../src/components/DataTable/NewSavedViewButton.tsx"],"sourcesContent":["import { IconButton } from \"@components/button\"\nimport Icon from \"@utilities/Icon\"\nimport React from \"react\"\n\nexport interface NewSavedViewButtonProps {\n onClick: () => void\n}\n\nexport function NewSavedViewButton({ onClick }: NewSavedViewButtonProps) {\n return (\n <IconButton\n className=\"tds-btn--data-table-saved-views-new-view\"\n icon={<Icon aria-hidden symbol=\"general#plus\" />}\n kind=\"pill\"\n tooltip=\"Add new view\"\n onClick={onClick}\n />\n )\n}\n\nNewSavedViewButton.displayName = \"NewSavedViewButton\"\n"],"names":["React"],"mappings":";;;;;;;;;;AAQM,SAAU,kBAAkB,CAAC,EAAE,OAAO,EAA2B,EAAA;AACrE,IAAA,QACEA,cAAA,CAAA,aAAA,CAAC,UAAU,EAAA,EACT,SAAS,EAAC,0CAA0C,EACpD,IAAI,EAAEA,cAAA,CAAA,aAAA,CAAC,IAAI,yBAAa,MAAM,EAAC,cAAc,EAAA,CAAG,EAChD,IAAI,EAAC,MAAM,EACX,OAAO,EAAC,cAAc,EACtB,OAAO,EAAE,OAAO,EAAA,CAChB;AAEN;AAEA,kBAAkB,CAAC,WAAW,GAAG,oBAAoB;;;;"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export interface SavedViewActionsProps {
|
|
3
|
+
onDiscard: () => void;
|
|
4
|
+
/** Omit to hide "Save as new view". */
|
|
5
|
+
onSaveAsNew?: (name: string) => void;
|
|
6
|
+
/** Omit to disable "Update view". */
|
|
7
|
+
onUpdate?: () => void;
|
|
8
|
+
/** The view whose filters have changed. */
|
|
9
|
+
savedViewName: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Actions for a modified saved view. The host owns focus afterward, since it
|
|
13
|
+
* decides whether these stay mounted.
|
|
14
|
+
*/
|
|
15
|
+
export declare function SavedViewActions({ onDiscard, onSaveAsNew, onUpdate, savedViewName, }: SavedViewActionsProps): React.JSX.Element;
|
|
16
|
+
export declare namespace SavedViewActions {
|
|
17
|
+
var displayName: string;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=SavedViewActions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SavedViewActions.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/SavedViewActions.tsx"],"names":[],"mappings":"AASA,OAAO,KAAmB,MAAM,OAAO,CAAA;AAIvC,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,IAAI,CAAA;IACrB,uCAAuC;IACvC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACpC,qCAAqC;IACrC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,2CAA2C;IAC3C,aAAa,EAAE,MAAM,CAAA;CACtB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,SAAS,EACT,WAAW,EACX,QAAQ,EACR,aAAa,GACd,EAAE,qBAAqB,qBAgDvB;yBArDe,gBAAgB"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import '../button/ActionsDropdownIconButton.js';
|
|
2
|
+
import { Button } from '../button/Button.js';
|
|
3
|
+
import '../button/DropdownButton.js';
|
|
4
|
+
import '../button/DropdownIconButton.js';
|
|
5
|
+
import { IconButton } from '../button/IconButton.js';
|
|
6
|
+
import '../button/LoadingButton.js';
|
|
7
|
+
import '../button/PageHeaderActionsDropdownButton.js';
|
|
8
|
+
import { ButtonGroup } from '../button-group/ButtonGroup.js';
|
|
9
|
+
import { Dropdown, DropdownTrigger, DropdownMenu, DropdownAction } from '../dropdown/Dropdown.js';
|
|
10
|
+
import Icon from '../../utilities/Icon.js';
|
|
11
|
+
import React__default, { useState } from 'react';
|
|
12
|
+
import { NewSavedViewModal } from './NewSavedViewModal.js';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Actions for a modified saved view. The host owns focus afterward, since it
|
|
16
|
+
* decides whether these stay mounted.
|
|
17
|
+
*/
|
|
18
|
+
function SavedViewActions({ onDiscard, onSaveAsNew, onUpdate, savedViewName, }) {
|
|
19
|
+
const [isNewViewModalOpen, setIsNewViewModalOpen] = useState(false);
|
|
20
|
+
return (React__default.createElement(React__default.Fragment, null,
|
|
21
|
+
React__default.createElement(ButtonGroup, { "aria-label": `Changes to ${savedViewName}` },
|
|
22
|
+
React__default.createElement(Button, { disabled: !onUpdate, kind: "secondary", label: "Update view", size: "sm", onClick: onUpdate }),
|
|
23
|
+
React__default.createElement(Dropdown, null,
|
|
24
|
+
React__default.createElement(DropdownTrigger, null,
|
|
25
|
+
React__default.createElement(IconButton, { "aria-label": "More view actions", icon: React__default.createElement(Icon, { "aria-hidden": true, symbol: "general#down-caret" }), kind: "secondary", size: "sm" })),
|
|
26
|
+
React__default.createElement(DropdownMenu, { placement: "bottom end" },
|
|
27
|
+
onSaveAsNew && (React__default.createElement(DropdownAction, { id: "save-as-new", onAction: () => queueMicrotask(() => setIsNewViewModalOpen(true)) }, "Save as new view")),
|
|
28
|
+
React__default.createElement(DropdownAction, { id: "discard", onAction: onDiscard }, "Discard changes")))),
|
|
29
|
+
onSaveAsNew && (React__default.createElement(NewSavedViewModal, { open: isNewViewModalOpen, onClose: () => setIsNewViewModalOpen(false), onSave: onSaveAsNew }))));
|
|
30
|
+
}
|
|
31
|
+
SavedViewActions.displayName = "SavedViewActions";
|
|
32
|
+
|
|
33
|
+
export { SavedViewActions };
|
|
34
|
+
//# sourceMappingURL=SavedViewActions.js.map
|