PluginProbe
Code Snippets / trunk
Code Snippets vtrunk
4.0.0-beta.2 3.10.2 3.10.1 3.10.0 3.10.0-beta.2 3.10.0-beta.1 4.0.0-beta.1 3.9.6 trunk 2.10.0 2.10.1 2.12.0 2.12.1 2.13.0 2.13.1 2.13.2 2.13.3 2.14.0 2.14.1 2.14.2 2.14.3 2.14.4 2.14.5 2.14.6 3.0.0 All 65 releases
← All changes | js/components/common/ListTable/TableNavigation.tsx +71 -11 4.0.0-beta.1 → trunk View file →
@@ -48,11 +48,18 @@
48 48 which: 'top' | 'bottom'
49 49 actions: ListTableAction<A>[]
50 50 selectedAction: A | undefined
51 51 setSelectedAction: Dispatch<SetStateAction<A | undefined>>
52 + label: string
52 53 }
53 54
54 -const BulkActionSelect = <A extends string>({ which, actions, selectedAction, setSelectedAction }: BulkActionSelectProps<A>) =>
55 +const BulkActionSelect = <A extends string>({
56 + which,
57 + actions,
58 + selectedAction,
59 + setSelectedAction,
60 + label
61 +}: BulkActionSelectProps<A>) =>
55 62 <select
56 63 name={`action${'bottom' === which ? '-2' : ''}`}
57 64 id={`bulk-action-selector-${which}`}
58 65 value={selectedAction}
@@ -63,16 +70,17 @@
63 70 setSelectedAction(value)
64 71 }
65 72 }}
66 73 >
67 - <option value="-1">{__('Bulk actions', 'code-snippets')}</option>
74 + <option value="-1">{label}</option>
68 75 <BulkActionSelectOptions actions={actions} />
69 76 </select>
70 77
71 78 interface BulkActionsProps<K extends Key, A extends string> extends Required<Pick<TableNavProps<K, A>, 'which' | 'actions' | 'doAction'>> {
72 - onActionSuccess?: () => void
79 + onActionSuccess?: VoidFunction
73 80 disabled?: boolean
74 81 selected: Set<K>
82 + selectLabel?: string
75 83 }
76 84
77 85 const BulkActions = function BulkActions<K extends Key, A extends string>({
78 86 which,
@@ -79,9 +87,10 @@
79 87 actions,
80 88 selected,
81 89 doAction,
82 90 onActionSuccess,
83 - disabled
91 + disabled,
92 + selectLabel
84 93 }: BulkActionsProps<K, A>) {
85 94 const [selectedAction, setSelectedAction] = useState<A>()
86 95 const [isPerformingAction, setIsPerformingAction] = useState(false)
87 96
@@ -105,9 +114,12 @@
105 114 {/* translators: Hidden accessibility text. */}
106 115 {__('Select bulk action', 'code-snippets')}
107 116 </label>
108 117
109 - <BulkActionSelect {...{ which, actions, selectedAction, setSelectedAction }} />
118 + <BulkActionSelect
119 + {...{ which, actions, selectedAction, setSelectedAction }}
120 + label={selectLabel ?? __('Bulk actions', 'code-snippets')}
121 + />
110 122
111 123 <SubmitButton
112 124 id={`doaction${'bottom' === which ? '-2' : ''}`}
113 125 name="bulk_action"
@@ -112,9 +124,9 @@
112 124 id={`doaction${'bottom' === which ? '-2' : ''}`}
113 125 name="bulk_action"
114 126 text={__('Apply', 'code-snippets')}
115 127 className="action"
116 - disabled={!!disabled || isPerformingAction || !selectedAction}
128 + disabled={!!disabled || isPerformingAction || !selectedAction || 0 === selected.size}
117 129 onClick={handleSubmit}
118 130 />
119 131
120 132 {isPerformingAction ? <Spinner /> : null}
@@ -121,8 +133,38 @@
121 133 </div>
122 134 )
123 135 }
124 136
137 +export interface SelectAllControlProps<K extends Key> {
138 + keys: K[]
139 + selected: Set<K>
140 + setSelected: Dispatch<SetStateAction<Set<K>>>
141 +}
142 +
143 +export const SelectAllControl = <K extends Key>({
144 + keys,
145 + selected,
146 + setSelected
147 +}: SelectAllControlProps<K>) =>
148 + <label className="tablenav-select-all">
149 + <input
150 + type="checkbox"
151 + checked={0 < keys.length && keys.every(key => selected.has(key))}
152 + disabled={0 === keys.length}
153 + aria-label={__('Select all items', 'code-snippets')}
154 + onChange={event => {
155 + const { checked } = event.target
156 +
157 + setSelected(previous => {
158 + const updated = new Set(previous)
159 + keys.forEach(key => checked ? updated.add(key) : updated.delete(key))
160 + return updated
161 + })
162 + }}
163 + />
164 + {__('Select all', 'code-snippets')}
165 + </label>
166 +
125 167 export interface TableNavProps<K extends Key, A extends string> extends TableNavigationProps<K, A> {
126 168 which: 'top' | 'bottom'
127 169 }
128 170
@@ -134,14 +176,19 @@
134 176 setSelected,
135 177 totalItems,
136 178 totalPages = 0,
137 179 extraTableNav,
180 + endTableNav,
181 + selectAllKeys,
138 182 ...paginationProps
139 -}: TableNavProps<K, A>) =>
140 - extraTableNav || 0 < totalItems && actions
183 +}: TableNavProps<K, A>) => {
184 + const isTop = 'top' === which
185 + const hasBulkActions = 0 < totalItems && Boolean(actions)
186 +
187 + return isTop && Boolean(extraTableNav ?? endTableNav) || hasBulkActions || 0 < totalPages
141 188 ? <div className={`tablenav ${which}`}>
142 189
143 - {0 < totalItems && actions && (
190 + {0 < totalItems && actions && doAction && (
144 191 <BulkActions
145 192 which={which}
146 193 actions={actions}
147 194 doAction={doAction}
@@ -149,14 +196,26 @@
149 196 selected={selected}
150 197 onActionSuccess={() => setSelected(new Set())}
151 198 />)}
152 199
153 - {extraTableNav?.(which)}
154 - {0 < totalPages && <TablePagination {...{ totalPages, totalItems, which, ...paginationProps }} />}
200 + {isTop && selectAllKeys
201 + ? <SelectAllControl keys={selectAllKeys} selected={selected} setSelected={setSelected} />
202 + : null}
155 203
204 + {isTop ? extraTableNav?.(which) : null}
205 +
206 + {0 < totalPages || isTop && endTableNav
207 + ? <div className="tablenav-end-group">
208 + {0 < totalPages &&
209 + <TablePagination {...{ totalPages, totalItems, which, ...paginationProps }} />}
210 + {isTop ? endTableNav?.(which) : null}
211 + </div>
212 + : null}
213 +
156 214 <br className="clear" />
157 215 </div>
158 216 : null
217 +}
159 218
160 219 export interface TableNavigationProps<K extends Key, A extends string> extends ListTableNavProps<K, A>,
161 220 Omit<TablePaginationProps, 'totalPages' | 'which'> {
162 221 selected: Set<K>
@@ -162,8 +221,9 @@
162 221 selected: Set<K>
163 222 setSelected: Dispatch<SetStateAction<Set<K>>>
164 223 totalItems: number
165 224 totalPages: number | undefined
225 + selectAllKeys?: K[]
166 226 }
167 227
168 228 export const TableNavigation = <K extends Key, A extends string>({
169 229 children,