feat(data-table): support radio, selectable variants with batch actions

This commit is contained in:
Eric Liu 2020-10-24 13:37:00 -07:00
commit f43b132088
15 changed files with 662 additions and 156 deletions

View file

@ -0,0 +1,43 @@
<script>
/**
* Specify whether the checkbox is checked
* @type {boolean} [checked=false]
*/
export let checked = false;
/**
* Specify whether the checkbox is indeterminate
* @type {boolean} [indeterminate=false]
*/
export let indeterminate = false;
/**
* Specify the title attribute for the label element
* @type {string} [title]
*/
export let title = undefined;
/**
* Set an id for the input label
* @type {string} [id]
*/
export let id = "ccs-" + Math.random().toString(36);
</script>
<input
type="checkbox"
class:bx--checkbox="{true}"
checked="{indeterminate ? false : checked}"
indeterminate="{indeterminate}"
id="{id}"
{...$$restProps}
aria-label="{undefined}"
aria-checked="{indeterminate ? 'mixed' : checked}"
on:change
/>
<label
for="{id}"
title="{title}"
aria-label="{$$props['aria-label']}"
class:bx--checkbox-label="{true}"
></label>

View file

@ -1,2 +1,3 @@
export { default as Checkbox } from "./Checkbox.svelte";
export { default as CheckboxSkeleton } from "./Checkbox.Skeleton.svelte";
export { default as InlineCheckbox } from "./InlineCheckbox.svelte";

View file

@ -61,6 +61,31 @@
*/
export let expandedRowIds = [];
/**
* Set to `true` for the radio selection variant
* @type {boolean} [radio=false]
*/
export let radio = false;
/**
* Set to `true` for the selectable variant
* Automatically set to `true` if `radio` or `batchSelection` are `true`
* @type {boolean} [selectable=false]
*/
export let selectable = false;
/**
* Set to `true` to enable batch selection
* @type {boolean} [batchSelection=false]
*/
export let batchSelection = false;
/**
* Specify the row ids to be selected
* @type {string[]} [selectedRowIds=[]]
*/
export let selectedRowIds = [];
/**
* Set to `true` to enable a sticky header
* @type {boolean} [stickyHeader=false]
@ -70,6 +95,8 @@
import { createEventDispatcher, setContext } from "svelte";
import { writable, derived } from "svelte/store";
import ChevronRight16 from "carbon-icons-svelte/lib/ChevronRight16";
import { InlineCheckbox } from "../Checkbox";
import { RadioButton } from "../RadioButton";
import Table from "./Table.svelte";
import TableBody from "./TableBody.svelte";
import TableCell from "./TableCell.svelte";
@ -84,6 +111,7 @@
descending: "none",
};
const dispatch = createEventDispatcher();
const batchSelectedIds = writable(false);
const tableSortable = writable(sortable);
const sortHeader = writable({
id: null,
@ -101,6 +129,10 @@
setContext("DataTable", {
sortHeader,
tableSortable,
batchSelectedIds,
resetSelectedRowIds: () => {
selectedRowIds = [];
},
add: (id) => {
headerItems.update((_) => [..._, id]);
},
@ -113,7 +145,13 @@
(a, id) => ({ ...a, [id]: true }),
{}
);
let selectAll = false;
$: batchSelectedIds.set(selectedRowIds);
$: indeterminate =
selectedRowIds.length > 0 && selectedRowIds.length < rows.length;
$: if (batchExpansion) expandable = true;
$: if (radio || batchSelection) selectable = true;
$: tableSortable.set(sortable);
$: headerKeys = headers.map(({ key }) => key);
$: rows = rows.map((row) => ({
@ -180,6 +218,32 @@
{/if}
</th>
{/if}
{#if selectable && !batchSelection}
<th scope="col"></th>
{/if}
{#if batchSelection && !radio}
<th scope="col" class:bx--table-column-checkbox="{true}">
<InlineCheckbox
aria-label="Select all rows"
checked="{selectAll}"
indeterminate="{indeterminate}"
on:change="{(e) => {
if (indeterminate) {
e.target.checked = false;
selectAll = false;
selectedRowIds = [];
return;
}
if (e.target.checked) {
selectedRowIds = rows.map((row) => row.id);
} else {
selectedRowIds = [];
}
}}"
/>
</th>
{/if}
{#each headers as header, i (header.key)}
<TableHeader
on:click="{() => {
@ -235,6 +299,34 @@
</button>
</TableCell>
{/if}
{#if selectable}
<td
class:bx--table-column-checkbox="{true}"
class:bx--table-column-radio="{radio}"
>
{#if radio}
<RadioButton
name="select-row-{row.id}"
checked="{selectedRowIds.includes(row.id)}"
on:change="{() => {
selectedRowIds = [row.id];
}}"
/>
{:else}
<InlineCheckbox
name="select-row-{row.id}"
checked="{selectedRowIds.includes(row.id)}"
on:change="{() => {
if (selectedRowIds.includes(row.id)) {
selectedRowIds = selectedRowIds.filter((id) => id !== row.id);
} else {
selectedRowIds = [...selectedRowIds, row.id];
}
}}"
/>
{/if}
</td>
{/if}
{#each row.cells as cell, j (cell.key)}
<TableCell
on:click="{() => {

View file

@ -0,0 +1,44 @@
<script>
/**
* Override the total items selected text
* @type {(totalSelected: number) => string} [formatTotalSelected = (totalSelected: number) => string]
*/
export let formatTotalSelected = (totalSelected) =>
`${totalSelected} item${totalSelected === 1 ? "" : "s"} selected`;
import { onMount, getContext } from "svelte";
import { Button } from "../Button";
let batchSelectedIds = [];
$: showActions = batchSelectedIds.length > 0;
const ctx = getContext("DataTable");
const unsubscribe = ctx.batchSelectedIds.subscribe((value) => {
batchSelectedIds = value;
});
onMount(() => unsubscribe);
</script>
<div
class:bx--batch-actions="{true}"
class:bx--batch-actions--active="{showActions}"
{...$$restProps}
>
<div class:bx--batch-summary="{true}">
<p class:bx--batch-summary__para="{true}">
<span> {formatTotalSelected(batchSelectedIds.length)} </span>
</p>
</div>
<div class:bx--action-list="{true}">
<slot />
<Button
class="bx--batch-summary__cancel"
tabindex="{showActions ? '0' : '-1'}"
on:click="{ctx.resetSelectedRowIds}"
>
Cancel
</Button>
</div>
</div>

View file

@ -0,0 +1,3 @@
<div class:bx--toolbar-content="{true}">
<slot />
</div>

View file

@ -7,4 +7,6 @@ export { default as TableHead } from "./TableHead.svelte";
export { default as TableHeader } from "./TableHeader.svelte";
export { default as TableRow } from "./TableRow.svelte";
export { default as Toolbar } from "./Toolbar.svelte";
export { default as ToolbarContent } from "./ToolbarContent.svelte";
export { default as ToolbarSearch } from "./ToolbarSearch.svelte";
export { default as ToolbarBatchActions } from "./ToolbarBatchActions.svelte";

View file

@ -24,7 +24,9 @@ export {
TableHeader,
TableRow,
Toolbar,
ToolbarContent,
ToolbarSearch,
ToolbarBatchActions,
} from "./DataTable";
export { DataTableSkeleton } from "./DataTableSkeleton";
export { DatePicker, DatePickerInput, DatePickerSkeleton } from "./DatePicker";