Skip to content

Commit

Permalink
feat(table): enhance table with generics (#919)
Browse files Browse the repository at this point in the history
* feat(table): enhance a11y

* feat(table): add generics

* feat(table): refactoring

* feat(table): fix table pagination

* docs(table): update docs

* docs(table): update example
  • Loading branch information
mlmoravek committed Jun 7, 2024
1 parent 8f64934 commit c85bee6
Show file tree
Hide file tree
Showing 26 changed files with 1,103 additions and 1,202 deletions.
4 changes: 2 additions & 2 deletions packages/docs/components/Pagination.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ title: Pagination
| perPage | Items count for each page | number\|string | - | <div><small>From <b>config</b>:</small></div><code style='white-space: nowrap; padding: 0;'>pagination: {<br>&nbsp;&nbsp;perPage: 20<br>}</code> |
| rangeAfter | Number of pagination items to show after current page. | number | - | <code style='white-space: nowrap; padding: 0;'>1</code> |
| rangeBefore | Number of pagination items to show before current page. | number | - | <code style='white-space: nowrap; padding: 0;'>1</code> |
| rounded | Rounded button style | boolean | - | <div><small>From <b>config</b>:</small></div><code style='white-space: nowrap; padding: 0;'>pagination: {<br>&nbsp;&nbsp;rounded: false<br>}</code> |
| simple | Simple style | boolean | - | <div><small>From <b>config</b>:</small></div><code style='white-space: nowrap; padding: 0;'>pagination: {<br>&nbsp;&nbsp;simple: false<br>}</code> |
| rounded | Enable rounded button style | boolean | - | <div><small>From <b>config</b>:</small></div><code style='white-space: nowrap; padding: 0;'>pagination: {<br>&nbsp;&nbsp;rounded: false<br>}</code> |
| simple | Enable simple style | boolean | - | <div><small>From <b>config</b>:</small></div><code style='white-space: nowrap; padding: 0;'>pagination: {<br>&nbsp;&nbsp;simple: false<br>}</code> |
| size | Pagination size | string | `small`, `medium`, `large` | <div><small>From <b>config</b>:</small></div><code style='white-space: nowrap; padding: 0;'>pagination: {<br>&nbsp;&nbsp;size: undefined<br>}</code> |
| total | Total count of items | number | - | |

Expand Down
247 changes: 125 additions & 122 deletions packages/docs/components/Table.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions packages/oruga/src/components/pagination/Pagination.vue
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ const props = defineProps({
type: String,
default: () => getOption("pagination.size"),
},
/** Simple style */
/** Enable simple style */
simple: {
type: Boolean,
default: () => getOption("pagination.simple", false),
},
/** Rounded button style */
/** Enable rounded button style */
rounded: {
type: Boolean,
default: () => getOption("pagination.rounded", false),
Expand Down
1,189 changes: 573 additions & 616 deletions packages/oruga/src/components/table/Table.vue

Large diffs are not rendered by default.

38 changes: 17 additions & 21 deletions packages/oruga/src/components/table/TableColumn.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup lang="ts" generic="T">
import { toRaw, computed, getCurrentInstance, type PropType } from "vue";
import { useProviderChild } from "@/composables";
Expand All @@ -22,7 +22,7 @@ const props = defineProps({
field: { type: String, default: undefined },
/** Provide a display function to edit the output */
display: {
type: Function as PropType<(value: unknown, row: unknown) => string>,
type: Function as PropType<(value: unknown, row: T) => string>,
default: undefined,
},
/** Define a column sub heading */
Expand Down Expand Up @@ -52,22 +52,20 @@ const props = defineProps({
sortable: { type: Boolean, default: false },
/** Define whether the column is visible or not */
visible: { type: Boolean, default: true },
/** Whether the column is sticky or not */
sticky: { type: Boolean, default: false },
/** Make header selectable */
headerSelectable: { type: Boolean, default: false },
/** Define a custom sort function */
customSort: {
type: Function as PropType<
(a: unknown, b: unknown, isAsc: boolean) => number
>,
type: Function as PropType<(a: T, b: T, isAsc: boolean) => number>,
default: undefined,
},
/** Define a custom funtion for the filter search */
/** Define a custom filter funtion for the search */
customSearch: {
type: Function as PropType<(row: unknown, filter: string) => boolean>,
type: Function as PropType<(row: T, filter: string) => boolean>,
default: undefined,
},
/** Whether the column is sticky or not */
sticky: { type: Boolean, default: false },
/** Make header selectable */
headerSelectable: { type: Boolean, default: false },
/**
* Adds native attributes to th
* @deprecated will be moved to table component in v0.9
Expand All @@ -81,9 +79,7 @@ const props = defineProps({
* @deprecated will be moved to table component in v0.9
*/
tdAttrs: {
type: Function as PropType<
(row: unknown, column: typeof props) => object
>,
type: Function as PropType<(row: T, column: typeof props) => object>,
default: () => ({}),
},
});
Expand Down Expand Up @@ -135,11 +131,11 @@ const { item } = useProviderChild({ data: providedData });
<template v-if="false">
<!--
@slot Default Slot
@binding {unknown} row - row data
@binding {Column} column - column definition
@binding {T} row - row data
@binding {TableColumn} column - column definition
@binding {number} index - row index
@binding {number} colindex - column index
@binding {(row): void} toggle-details - toggle details function
@binding {(): void} toggle-details - toggle details function
-->
<slot
:row="null"
Expand All @@ -149,22 +145,22 @@ const { item } = useProviderChild({ data: providedData });
:toggle-details="null" />
<!--
@slot Override header label
@binding {Column} column - column definition
@binding {TableColumn} column - column definition
@binding {number} index - column index
-->
<slot name="header" :column="null" :index="null" />
<!--
@slot Override subheading label
@binding {Column} column - column definition
@binding {TableColumn} column - column definition
@binding {number} index - column index
-->
<slot name="subheading" :column="null" :index="null" />

<!--
@slot Override searchable input
@binding {Column} column - column definition
@binding {TableColumn} column - column definition
@binding {number} index - column index
@binding {Record<string,string>} filters - active filters object
@binding {object} filters - active filters object
-->
<slot
name="searchable"
Expand Down
25 changes: 13 additions & 12 deletions packages/oruga/src/components/table/TableMobileSort.vue
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
<script setup lang="ts">
<script setup lang="ts" generic="T">
import { computed, watch, ref, type PropType } from "vue";
import OButton from "../button/Button.vue";
import OSelect from "../select/Select.vue";
import OIcon from "../icon/Icon.vue";
import OField from "../field/Field.vue";
import OButton from "@/components/button/Button.vue";
import OSelect from "@/components/select/Select.vue";
import OIcon from "@/components/icon/Icon.vue";
import OField from "@/components/field/Field.vue";
import { getValueByPath } from "@/utils/helpers";
import type { TableColumn } from "./types";
import type { TableColumnItem } from "./types";
import type { ClassBind } from "@/types";
defineOptions({
Expand All @@ -19,11 +19,11 @@ defineOptions({
const props = defineProps({
currentSortColumn: {
type: Object as PropType<TableColumn>,
type: Object as PropType<TableColumnItem<T>>,
default: undefined,
},
columns: {
type: Array as PropType<TableColumn[]>,
type: Array as PropType<TableColumnItem<T>[]>,
default: undefined,
},
placeholder: { type: String, default: undefined },
Expand All @@ -35,7 +35,7 @@ const props = defineProps({
});
const emits = defineEmits<{
(e: "sort", column: TableColumn, event: Event);
(e: "sort", column: TableColumnItem<T>, event: Event);
}>();
const mobileSort = ref<string>(
Expand Down Expand Up @@ -74,9 +74,9 @@ watch(
);
function sort(event?: Event): void {
const column = sortableColumns.value.filter(
const column = sortableColumns.value.find(
(c) => getValueByPath(c, "identifier") === mobileSort.value,
)[0];
);
emits("sort", column, event);
}
</script>
Expand All @@ -97,11 +97,12 @@ function sort(event?: Event): void {
</template>
<option
v-for="(column, index) in sortableColumns"
:key="index"
:key="column.field || index"
:value="column.identifier">
{{ column.label }}
</option>
</o-select>

<o-button @click="sort($event)">
<o-icon
v-show="isCurrentSort"
Expand Down
10 changes: 4 additions & 6 deletions packages/oruga/src/components/table/TablePagination.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
<script setup lang="ts">
import type { PropType } from "vue";
import OPagination from "../pagination/Pagination.vue";
import { usePropBinding } from "@/composables";
import OPagination from "@/components/pagination/Pagination.vue";
import type { ComponentClass } from "@/types";
Expand All @@ -13,7 +11,7 @@ defineOptions({
configField: "table",
});
const props = defineProps({
defineProps({
current: { type: Number, default: undefined },
paginated: { type: Boolean, default: false },
rootClass: {
Expand All @@ -35,9 +33,9 @@ const emits = defineEmits<{
(e: "change", event: number): void;
}>();
const currentPage = usePropBinding("current", props, emits);
const currentPage = defineModel<number>("current");
/** Paginator change listener. */
/** paginator change listener */
function pageChanged(page: number): void {
const newPage = page > 0 ? page : 1;
currentPage.value = newPage;
Expand Down
24 changes: 12 additions & 12 deletions packages/oruga/src/components/table/examples/async-data.vue
Original file line number Diff line number Diff line change
Expand Up @@ -102,44 +102,44 @@ onMounted(() => {
@page-change="onPageChange"
@sort="onSort">
<o-table-column
v-slot="props"
v-slot="{ row }"
field="original_title"
label="Title"
sortable>
{{ props.row.original_title }}
{{ row.original_title }}
</o-table-column>
<o-table-column
v-slot="props"
v-slot="{ row }"
field="vote_average"
label="Vote Average"
numeric
sortable>
<span class="tag" :class="type(props.row.vote_average)">
{{ props.row.vote_average }}
<span class="tag" :class="type(row.vote_average)">
{{ row.vote_average }}
</span>
</o-table-column>
<o-table-column
v-slot="props"
v-slot="{ row }"
field="vote_count"
label="Vote Count"
numeric
sortable>
{{ props.row.vote_count }}
{{ row.vote_count }}
</o-table-column>
<o-table-column
v-slot="props"
v-slot="{ row }"
field="release_date"
label="Release Date"
sortable
centered>
{{
props.row.release_date
? new Date(props.row.release_date).toLocaleDateString()
row.release_date
? new Date(row.release_date).toLocaleDateString()
: "unknown"
}}
</o-table-column>
<o-table-column v-slot="props" label="Overview" width="500">
{{ props.row.overview }}
<o-table-column v-slot="{ row }" label="Overview" width="500">
{{ row.overview }}
</o-table-column>
</o-table>
</section>
Expand Down
67 changes: 32 additions & 35 deletions packages/oruga/src/components/table/examples/base.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,37 @@
<script setup>
import { ref } from "vue";
const columns = ref([
{
field: "id",
label: "ID",
width: "40",
numeric: true,
sortable: true,
},
{
field: "first_name",
label: "First Name",
sortable: true,
},
{
field: "last_name",
label: "Last Name",
sortable: true,
},
{
field: "date",
label: "Date",
position: "centered",
sortable: true,
},
{
field: "gender",
label: "Gender",
sortable: true,
},
]);
const data = ref([
{
id: 1,
Expand Down Expand Up @@ -38,44 +69,10 @@ const data = ref([
gender: "Female",
},
]);
const columns = ref([
{
field: "id",
label: "ID",
width: "40",
numeric: true,
},
{
field: "first_name",
label: "First Name",
},
{
field: "last_name",
label: "Last Name",
},
{
field: "date",
label: "Date",
position: "centered",
},
{
field: "gender",
label: "Gender",
},
]);
</script>

<template>
<section>
<o-table :data="data">
<o-table-column
v-for="(column, idx) in columns"
:key="idx"
v-slot="{ row }"
v-bind="column">
{{ row[column.field] }}
</o-table-column>
</o-table>
<o-table :data="data" :columns="columns" />
</section>
</template>
Loading

0 comments on commit c85bee6

Please sign in to comment.