@citizenplane/pimp 9.10.0 → 9.11.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/pimp.es.js +5220 -5080
- package/dist/pimp.umd.js +25 -25
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/assets/styles/helpers/_mixins.scss +21 -0
- package/src/components/CpTable.vue +40 -23
- package/src/components/CpTableColumnEditor.vue +208 -0
- package/src/components/index.ts +2 -0
- package/src/constants/CpTableColumn.ts +9 -0
- package/src/helpers/dom.ts +15 -0
- package/src/stories/CpTable.stories.ts +13 -0
package/package.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
@use '../variables/colors' as colors;
|
|
2
2
|
@use '../helpers/functions' as fn;
|
|
3
|
+
@use '../variables/easings' as easings;
|
|
3
4
|
|
|
4
5
|
// Popover
|
|
5
6
|
@mixin popover-desktop($transitionName) {
|
|
@@ -34,6 +35,26 @@
|
|
|
34
35
|
aspect-ratio: 1 / 1;
|
|
35
36
|
}
|
|
36
37
|
|
|
38
|
+
// Floating Vue
|
|
39
|
+
@mixin hide-tooltip-arrow() {
|
|
40
|
+
.v-popper__arrow-container {
|
|
41
|
+
display: none;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@mixin v-dropdown-transition() {
|
|
46
|
+
.v-popper__wrapper {
|
|
47
|
+
transition:
|
|
48
|
+
scale 200ms easings.$easing-elastic,
|
|
49
|
+
opacity 200ms ease;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.v-popper__popper--hidden .v-popper__wrapper {
|
|
53
|
+
opacity: 0;
|
|
54
|
+
scale: 0.9;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
37
58
|
// Media queries
|
|
38
59
|
@mixin media-query-min($breakpoint) {
|
|
39
60
|
@media (min-width: $breakpoint) {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
<thead class="cpTable__header">
|
|
18
18
|
<tr class="cpTable__row cpTable__row--header">
|
|
19
19
|
<th
|
|
20
|
-
v-for="column in
|
|
20
|
+
v-for="column in visibleColumns"
|
|
21
21
|
:key="column.id"
|
|
22
22
|
class="cpTable__column"
|
|
23
23
|
:style="getColumnStyle(column)"
|
|
@@ -26,7 +26,10 @@
|
|
|
26
26
|
{{ column.name }}
|
|
27
27
|
</slot>
|
|
28
28
|
</th>
|
|
29
|
-
<th v-show="
|
|
29
|
+
<th v-show="displayOptionsColumn" class="cpTable__column cpTable__column--isOptions">
|
|
30
|
+
<cp-table-column-editor v-if="enableColumnEdition" v-model="columnsModel" :columns="normalizedColumns" />
|
|
31
|
+
<span v-show="enableRowOptions" />
|
|
32
|
+
</th>
|
|
30
33
|
</tr>
|
|
31
34
|
</thead>
|
|
32
35
|
<tbody class="cpTable__body">
|
|
@@ -54,8 +57,8 @@
|
|
|
54
57
|
<template v-else>{{ cellValue }}</template>
|
|
55
58
|
</slot>
|
|
56
59
|
</td>
|
|
57
|
-
<td v-show="
|
|
58
|
-
<div class="cpTable__actions">
|
|
60
|
+
<td v-show="displayOptionsCell(rowData)" class="cpTable__cell cpTable__cell--isOptions">
|
|
61
|
+
<div v-if="enableRowOptions" class="cpTable__actions">
|
|
59
62
|
<slot name="row-quick-actions" :row="rowData">
|
|
60
63
|
<button
|
|
61
64
|
v-for="option in quickOptions"
|
|
@@ -119,6 +122,8 @@
|
|
|
119
122
|
<script setup lang="ts">
|
|
120
123
|
import { ref, computed, useId } from 'vue'
|
|
121
124
|
|
|
125
|
+
import { CpTableColumnObject } from '@/constants/CpTableColumn'
|
|
126
|
+
|
|
122
127
|
import CpContextualMenu from '@/components/CpContextualMenu.vue'
|
|
123
128
|
import CpTableEmptyState from '@/components/CpTableEmptyState.vue'
|
|
124
129
|
|
|
@@ -132,13 +137,6 @@ interface Emits {
|
|
|
132
137
|
(e: 'onPreviousClick'): void
|
|
133
138
|
}
|
|
134
139
|
|
|
135
|
-
interface ColumnDefinition {
|
|
136
|
-
id: string
|
|
137
|
-
name: string
|
|
138
|
-
textAlign?: 'left' | 'center' | 'right'
|
|
139
|
-
width?: number
|
|
140
|
-
}
|
|
141
|
-
|
|
142
140
|
interface PaginationServer {
|
|
143
141
|
activePage: number
|
|
144
142
|
total: number
|
|
@@ -170,9 +168,10 @@ interface GroupByData {
|
|
|
170
168
|
interface Props {
|
|
171
169
|
areRowsClickable?: boolean
|
|
172
170
|
caption?: string
|
|
173
|
-
columns?: string[] |
|
|
171
|
+
columns?: string[] | CpTableColumnObject[]
|
|
174
172
|
data: (Record<string, unknown> | GroupByData)[]
|
|
175
173
|
emptyCellPlaceholder?: string
|
|
174
|
+
enableColumnEdition?: boolean
|
|
176
175
|
enableRowOptions?: boolean
|
|
177
176
|
isLoading?: boolean
|
|
178
177
|
noResultPlaceholder?: string
|
|
@@ -190,6 +189,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
190
189
|
noResultPlaceholder: 'No results found',
|
|
191
190
|
isLoading: false,
|
|
192
191
|
enableRowOptions: false,
|
|
192
|
+
enableColumnEdition: false,
|
|
193
193
|
quickOptionsLimit: 3,
|
|
194
194
|
rowOptions: () => [],
|
|
195
195
|
})
|
|
@@ -216,6 +216,8 @@ const quickOptions = computed(() => {
|
|
|
216
216
|
return props.rowOptions
|
|
217
217
|
})
|
|
218
218
|
|
|
219
|
+
const displayOptionsColumn = computed(() => props.enableRowOptions || props.enableColumnEdition)
|
|
220
|
+
|
|
219
221
|
const currentRowData = ref<Record<string, unknown>>({})
|
|
220
222
|
const contextualMenuItems = computed(() => {
|
|
221
223
|
return props.rowOptions.map((option) => ({
|
|
@@ -229,7 +231,7 @@ const containerDOMElement = computed(() => cpTableContainer.value)
|
|
|
229
231
|
const mainClasses = computed(() => ({ 'cpTable--isLoading': props.isLoading }))
|
|
230
232
|
const containerClasses = computed(() => ({ 'cpTable__container--hasPagination': hasPagination.value }))
|
|
231
233
|
|
|
232
|
-
const normalizedColumns = computed<
|
|
234
|
+
const normalizedColumns = computed<CpTableColumnObject[]>(() => {
|
|
233
235
|
if (!props.columns) return []
|
|
234
236
|
const columns = props.columns.length ? [...props.columns] : [...columnsFromRows.value]
|
|
235
237
|
|
|
@@ -248,7 +250,13 @@ const normalizedColumns = computed<ColumnDefinition[]>(() => {
|
|
|
248
250
|
})
|
|
249
251
|
})
|
|
250
252
|
|
|
251
|
-
const
|
|
253
|
+
const visibleColumns = computed(() => normalizedColumns.value.filter(({ id }) => columnsModel.value.includes(id)))
|
|
254
|
+
|
|
255
|
+
const getAllColumnIds = () => normalizedColumns.value.map(({ id }) => id)
|
|
256
|
+
|
|
257
|
+
const columnsModel = ref<string[]>(getAllColumnIds())
|
|
258
|
+
|
|
259
|
+
const numberOfColumns = computed(() => visibleColumns.value.length)
|
|
252
260
|
|
|
253
261
|
const hasGroupBy = computed(() => {
|
|
254
262
|
if (!props.data.length) return false
|
|
@@ -405,10 +413,10 @@ const handleNavigationClick = (isNext = true) => {
|
|
|
405
413
|
}
|
|
406
414
|
|
|
407
415
|
const normalizeRowData = ({
|
|
408
|
-
columns =
|
|
416
|
+
columns = visibleColumns.value,
|
|
409
417
|
rowPayload,
|
|
410
418
|
}: {
|
|
411
|
-
columns?:
|
|
419
|
+
columns?: CpTableColumnObject[]
|
|
412
420
|
rowPayload: Record<string, unknown>
|
|
413
421
|
}) => {
|
|
414
422
|
if (!Array.isArray(rowPayload)) {
|
|
@@ -426,10 +434,10 @@ const normalizeRowData = ({
|
|
|
426
434
|
}
|
|
427
435
|
|
|
428
436
|
const mapCellToColumn = ({
|
|
429
|
-
columns =
|
|
437
|
+
columns = visibleColumns.value,
|
|
430
438
|
rowPayload,
|
|
431
439
|
}: {
|
|
432
|
-
columns?:
|
|
440
|
+
columns?: CpTableColumnObject[]
|
|
433
441
|
rowPayload: Record<string, unknown>
|
|
434
442
|
}) => {
|
|
435
443
|
if (isFullWidthRow(rowPayload)) return rowPayload
|
|
@@ -458,7 +466,7 @@ const resetScrollPosition = () => {
|
|
|
458
466
|
}
|
|
459
467
|
}
|
|
460
468
|
|
|
461
|
-
const getColumnStyle = (columnPayload:
|
|
469
|
+
const getColumnStyle = (columnPayload: CpTableColumnObject) => {
|
|
462
470
|
const formattedWidth = columnPayload?.width && `${columnPayload.width}px`
|
|
463
471
|
|
|
464
472
|
return {
|
|
@@ -470,7 +478,7 @@ const getColumnStyle = (columnPayload: ColumnDefinition) => {
|
|
|
470
478
|
const getCellStyle = (cellKey: RESERVED_KEYS, cellIndex: number) => {
|
|
471
479
|
if (isFullWidthCell(cellKey)) return null
|
|
472
480
|
return {
|
|
473
|
-
textAlign:
|
|
481
|
+
textAlign: visibleColumns.value[cellIndex]?.textAlign,
|
|
474
482
|
}
|
|
475
483
|
}
|
|
476
484
|
|
|
@@ -487,7 +495,7 @@ const getCellClasses = (cellKey: RESERVED_KEYS) => {
|
|
|
487
495
|
}
|
|
488
496
|
|
|
489
497
|
const getColspan = (cellKey: RESERVED_KEYS) => {
|
|
490
|
-
const numberOfColumnsValue =
|
|
498
|
+
const numberOfColumnsValue = displayOptionsColumn.value ? numberOfColumns.value + 1 : numberOfColumns.value
|
|
491
499
|
return isFullWidthCell(cellKey) ? numberOfColumnsValue : undefined
|
|
492
500
|
}
|
|
493
501
|
|
|
@@ -501,7 +509,11 @@ const isRowSelected = (rowIndex: number) => {
|
|
|
501
509
|
const row = rawVisibleRows.value[rowIndex] as Record<string, unknown>
|
|
502
510
|
return row?.[RESERVED_KEYS.IS_SELECTED] || false
|
|
503
511
|
}
|
|
504
|
-
|
|
512
|
+
|
|
513
|
+
const displayOptionsCell = (rowData: Record<string, unknown>) => {
|
|
514
|
+
if (isFullWidthRow(rowData)) return false
|
|
515
|
+
return props.enableColumnEdition || props.enableRowOptions
|
|
516
|
+
}
|
|
505
517
|
|
|
506
518
|
const resetPagination = () => (pageNumber.value = 0)
|
|
507
519
|
|
|
@@ -619,11 +631,11 @@ defineExpose({ hideContextualMenu, resetPagination, currentRowData })
|
|
|
619
631
|
position: sticky;
|
|
620
632
|
top: 0;
|
|
621
633
|
z-index: 3;
|
|
622
|
-
background-color: colors.$neutral-light;
|
|
623
634
|
padding: sp.$space sp.$space-md;
|
|
624
635
|
text-align: left;
|
|
625
636
|
white-space: nowrap;
|
|
626
637
|
font-size: fn.px-to-em(12);
|
|
638
|
+
line-height: fn.px-to-rem(16);
|
|
627
639
|
font-weight: normal;
|
|
628
640
|
color: colors.$neutral-dark-1;
|
|
629
641
|
|
|
@@ -641,6 +653,11 @@ defineExpose({ hideContextualMenu, resetPagination, currentRowData })
|
|
|
641
653
|
height: fn.px-to-rem(1);
|
|
642
654
|
background-color: colors.$border-color;
|
|
643
655
|
}
|
|
656
|
+
|
|
657
|
+
&--isOptions {
|
|
658
|
+
right: 0;
|
|
659
|
+
padding: 0;
|
|
660
|
+
}
|
|
644
661
|
}
|
|
645
662
|
|
|
646
663
|
&__body {
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="cpTableColumnEditor">
|
|
3
|
+
<v-dropdown
|
|
4
|
+
v-model:shown="isDropdownVisible"
|
|
5
|
+
:delay="0"
|
|
6
|
+
placement="bottom-end"
|
|
7
|
+
popper-class="cpTableColumnEditor__dropdown"
|
|
8
|
+
@apply-show="handleDropdownShown"
|
|
9
|
+
>
|
|
10
|
+
<cp-button
|
|
11
|
+
appearance="minimal"
|
|
12
|
+
class="cpTableColumnEditor__trigger"
|
|
13
|
+
:class="triggerDynamicClass"
|
|
14
|
+
is-square
|
|
15
|
+
size="xs"
|
|
16
|
+
>
|
|
17
|
+
<template #leading-icon>
|
|
18
|
+
<cp-icon size="16" type="more-vertical" />
|
|
19
|
+
</template>
|
|
20
|
+
</cp-button>
|
|
21
|
+
<template #popper>
|
|
22
|
+
<div class="cpTableColumnEditor__inner">
|
|
23
|
+
<div class="cpTableColumnEditor__header">
|
|
24
|
+
<cp-input
|
|
25
|
+
ref="searchInputRef"
|
|
26
|
+
v-model="searchQuery"
|
|
27
|
+
class="cpTableColumnEditor__search"
|
|
28
|
+
is-search
|
|
29
|
+
placeholder="Search for a column..."
|
|
30
|
+
size="sm"
|
|
31
|
+
/>
|
|
32
|
+
</div>
|
|
33
|
+
<div v-if="hasProtectedColumns" class="cpTableColumnEditor__row">
|
|
34
|
+
<div class="cpTableColumnEditor__heading">Fixed columns</div>
|
|
35
|
+
<div v-for="column in protectedColumns" :key="column.id" class="cpTableColumnEditor__column">
|
|
36
|
+
<span>{{ column.name }}</span>
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
<div class="cpTableColumnEditor__divider" />
|
|
40
|
+
<div class="cpTableColumnEditor__row">
|
|
41
|
+
<div class="cpTableColumnEditor__heading">Shown in table</div>
|
|
42
|
+
<div class="cpTableColumnEditor__column">
|
|
43
|
+
<template v-if="hasFilteredVisibleColumns">
|
|
44
|
+
<cp-checkbox
|
|
45
|
+
v-for="column in filteredVisibleColumns"
|
|
46
|
+
:key="column.id"
|
|
47
|
+
v-model="selectedColumnIds"
|
|
48
|
+
:checkbox-label="column.name"
|
|
49
|
+
:checkbox-value="column.id"
|
|
50
|
+
class="cpTableColumnEditor__checkbox"
|
|
51
|
+
color="purple"
|
|
52
|
+
:value="column.id"
|
|
53
|
+
/>
|
|
54
|
+
</template>
|
|
55
|
+
<span v-else class="cpTableColumnEditor__empty">No columns found</span>
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
<template v-if="hasHiddenColumns">
|
|
59
|
+
<div class="cpTableColumnEditor__divider" />
|
|
60
|
+
<div class="cpTableColumnEditor__row">
|
|
61
|
+
<div class="cpTableColumnEditor__heading">Hidden in table</div>
|
|
62
|
+
<div class="cpTableColumnEditor__column">
|
|
63
|
+
<cp-checkbox
|
|
64
|
+
v-for="column in hiddenColumns"
|
|
65
|
+
:key="column.id"
|
|
66
|
+
v-model="selectedColumnIds"
|
|
67
|
+
:checkbox-label="column.name"
|
|
68
|
+
:checkbox-value="column.id"
|
|
69
|
+
class="cpTableColumnEditor__checkbox"
|
|
70
|
+
color="purple"
|
|
71
|
+
:value="column.id"
|
|
72
|
+
/>
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
</template>
|
|
76
|
+
</div>
|
|
77
|
+
</template>
|
|
78
|
+
</v-dropdown>
|
|
79
|
+
</div>
|
|
80
|
+
</template>
|
|
81
|
+
|
|
82
|
+
<script setup lang="ts">
|
|
83
|
+
import { computed, ref, useTemplateRef } from 'vue'
|
|
84
|
+
|
|
85
|
+
import { CpTableColumnObject } from '@/constants/CpTableColumn'
|
|
86
|
+
|
|
87
|
+
import { focusOnDOMElement } from '@/helpers/dom'
|
|
88
|
+
|
|
89
|
+
interface Props {
|
|
90
|
+
columns: CpTableColumnObject[]
|
|
91
|
+
modelValue: string[]
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const props = defineProps<Props>()
|
|
95
|
+
|
|
96
|
+
const isDropdownVisible = ref(false)
|
|
97
|
+
const selectedColumnIds = defineModel<string[]>()
|
|
98
|
+
|
|
99
|
+
const searchQuery = ref('')
|
|
100
|
+
const searchInputRef = useTemplateRef('searchInputRef')
|
|
101
|
+
|
|
102
|
+
const triggerDynamicClass = computed(() => {
|
|
103
|
+
return {
|
|
104
|
+
'cpTableColumnEditor__trigger--isOpen': isDropdownVisible.value,
|
|
105
|
+
}
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
const protectedColumns = computed(() => {
|
|
109
|
+
const filteredProtectedColumns = props.columns.filter((column) => isColumnProtected(column))
|
|
110
|
+
if (filteredProtectedColumns.length) return filteredProtectedColumns
|
|
111
|
+
|
|
112
|
+
const firstColumn = props.columns[0]
|
|
113
|
+
return [firstColumn]
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
const hasProtectedColumns = computed(() => !!protectedColumns.value.length)
|
|
117
|
+
|
|
118
|
+
const filteredVisibleColumns = computed(() => {
|
|
119
|
+
return props.columns.filter((column) => {
|
|
120
|
+
const isMatchingSearch = column.name.toLowerCase().includes(searchQuery.value.toLowerCase())
|
|
121
|
+
const isProtected = protectedColumns.value.some(({ id }) => id === column.id)
|
|
122
|
+
|
|
123
|
+
const conditions = [isMatchingSearch, isColumnSelected(column), !isProtected]
|
|
124
|
+
return conditions.every((condition) => condition)
|
|
125
|
+
})
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
const hasFilteredVisibleColumns = computed(() => !!filteredVisibleColumns.value.length)
|
|
129
|
+
|
|
130
|
+
const hiddenColumns = computed(() => props.columns.filter((column) => !isColumnSelected(column)))
|
|
131
|
+
const hasHiddenColumns = computed(() => !!hiddenColumns.value.length)
|
|
132
|
+
|
|
133
|
+
const isColumnProtected = (column) => column.isProtected || false
|
|
134
|
+
const isColumnSelected = (column) => selectedColumnIds.value?.includes(column.id)
|
|
135
|
+
|
|
136
|
+
const handleDropdownShown = () => {
|
|
137
|
+
if (!searchInputRef.value?.$el) return
|
|
138
|
+
setTimeout(() => focusOnDOMElement(searchInputRef.value?.$el), 50)
|
|
139
|
+
}
|
|
140
|
+
</script>
|
|
141
|
+
|
|
142
|
+
<style lang="scss">
|
|
143
|
+
.cpTableColumnEditor {
|
|
144
|
+
text-align: right;
|
|
145
|
+
|
|
146
|
+
&__trigger {
|
|
147
|
+
@extend %u-focus-outline;
|
|
148
|
+
|
|
149
|
+
border-radius: fn.px-to-rem(8);
|
|
150
|
+
|
|
151
|
+
&--isOpen,
|
|
152
|
+
&:hover,
|
|
153
|
+
&:focus-within {
|
|
154
|
+
background-color: colors.$neutral-dark-5;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
&__dropdown {
|
|
159
|
+
@include mx.hide-tooltip-arrow;
|
|
160
|
+
@include mx.v-dropdown-transition;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
&__inner {
|
|
164
|
+
display: flex;
|
|
165
|
+
flex-direction: column;
|
|
166
|
+
gap: sp.$space;
|
|
167
|
+
padding-block: sp.$space;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
&__header {
|
|
171
|
+
padding-inline: sp.$space-md;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
&__heading,
|
|
175
|
+
&__column:not(:has(.cpTableColumnEditor__checkbox)) {
|
|
176
|
+
padding: sp.$space-sm sp.$space-md;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
&__heading {
|
|
180
|
+
font-size: fn.px-to-rem(12);
|
|
181
|
+
line-height: fn.px-to-rem(24);
|
|
182
|
+
color: colors.$neutral-dark-1;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
&__column,
|
|
186
|
+
&__empty {
|
|
187
|
+
font-size: fn.px-to-rem(14);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
&__column {
|
|
191
|
+
text-transform: capitalize;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
&__empty {
|
|
195
|
+
text-transform: initial;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
&__divider {
|
|
199
|
+
height: fn.px-to-rem(1);
|
|
200
|
+
background-color: colors.$neutral-dark-5;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
&__checkbox {
|
|
204
|
+
color: colors.$neutral-dark;
|
|
205
|
+
padding: sp.$space-sm sp.$space;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
</style>
|
package/src/components/index.ts
CHANGED
|
@@ -33,6 +33,7 @@ import CpSelect from './CpSelect.vue'
|
|
|
33
33
|
import CpSelectMenu from './CpSelectMenu.vue'
|
|
34
34
|
import CpSwitch from './CpSwitch.vue'
|
|
35
35
|
import CpTable from './CpTable.vue'
|
|
36
|
+
import CpTableColumnEditor from './CpTableColumnEditor.vue'
|
|
36
37
|
import CpTelInput from './CpTelInput.vue'
|
|
37
38
|
import CpTextarea from './CpTextarea.vue'
|
|
38
39
|
import CpToaster from './CpToaster.vue'
|
|
@@ -75,6 +76,7 @@ const Components = {
|
|
|
75
76
|
CpRadio,
|
|
76
77
|
CpSwitch,
|
|
77
78
|
CpTable,
|
|
79
|
+
CpTableColumnEditor,
|
|
78
80
|
CpIcon,
|
|
79
81
|
CpTelInput,
|
|
80
82
|
CpTooltip,
|
package/src/helpers/dom.ts
CHANGED
|
@@ -43,3 +43,18 @@ export const handleTrapFocus = (event: KeyboardEvent, DOMElement?: HTMLElement |
|
|
|
43
43
|
lastElement?.focus()
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
|
+
|
|
47
|
+
export const focusOnDOMElement = (DOMElement: Document | HTMLElement | null, inputTag = 'input'): void => {
|
|
48
|
+
if (!DOMElement) return
|
|
49
|
+
|
|
50
|
+
if (DOMElement instanceof HTMLInputElement) {
|
|
51
|
+
DOMElement.focus()
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const inputElement = DOMElement.querySelector(inputTag) as HTMLInputElement | null
|
|
56
|
+
|
|
57
|
+
if (!inputElement) return
|
|
58
|
+
|
|
59
|
+
inputElement.focus()
|
|
60
|
+
}
|
|
@@ -110,6 +110,19 @@ export const Default: Story = {
|
|
|
110
110
|
}),
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
+
export const EnableColumnEdition: Story = {
|
|
114
|
+
args: {
|
|
115
|
+
...Default.args,
|
|
116
|
+
columns: [
|
|
117
|
+
{ id: 'name', name: 'Name' },
|
|
118
|
+
{ id: 'age', name: 'Age' },
|
|
119
|
+
{ id: 'email', name: 'Email' },
|
|
120
|
+
{ id: 'status', name: 'Status' },
|
|
121
|
+
],
|
|
122
|
+
enableColumnEdition: true,
|
|
123
|
+
},
|
|
124
|
+
}
|
|
125
|
+
|
|
113
126
|
export const ClickableRows: Story = {
|
|
114
127
|
args: {
|
|
115
128
|
...Default.args,
|