| 1 |
import { h, type VNode } from 'vue' |
| 2 |
import IvyButtonAction from '@/views/_components/button/IvyButtonAction.vue' |
| 3 |
import IvyTooltip from '@/views/_components/tooltip/IvyTooltip.vue' |
| 4 |
import type { CellRenderProps } from '@/views/_components/table/IvyCellRendererProps' |
| 5 |
|
| 6 |
export interface CellAction<Row> { |
| 7 |
icon: string | ((row: Row) => string) |
| 8 |
tooltip: string | ((row: Row) => string) |
| 9 |
onClick: (row: Row, e?: Event) => void | Promise<void> |
| 10 |
priority?: 'tertiary' | 'danger' | 'success' |
| 11 |
type?: 'ghost' | 'fill' |
| 12 |
iconStartType?: 'outline' | 'fill' |
| 13 |
visible?: (row: Row) => boolean |
| 14 |
refKey?: string |
| 15 |
} |
| 16 |
|
| 17 |
export interface ActionsCellOptions<Row> { |
| 18 |
actions: CellAction<Row>[] | ((row: Row) => CellAction<Row>[]) |
| 19 |
idKey?: keyof Row & string |
| 20 |
onButtonRef?: (id: unknown, el: HTMLElement | null) => void |
| 21 |
} |
| 22 |
|
| 23 |
const resolve = <Row, T>(value: T | ((row: Row) => T), row: Row): T => |
| 24 |
typeof value === 'function' ? (value as (row: Row) => T)(row) : value |
| 25 |
|
| 26 |
export function actionsCellRenderer<Row extends Record<string, unknown>>( |
| 27 |
options: ActionsCellOptions<Row>, |
| 28 |
) { |
| 29 |
const idKey = options.idKey ?? ('id' as keyof Row & string) |
| 30 |
|
| 31 |
return (props: CellRenderProps): VNode | null => { |
| 32 |
const row = props.rowData as unknown as Row |
| 33 |
if (!row) return null |
| 34 |
|
| 35 |
const actions = typeof options.actions === 'function' ? options.actions(row) : options.actions |
| 36 |
const visibleActions = actions |
| 37 |
.map((action, index) => ({ action, index })) |
| 38 |
.filter(({ action }) => (action.visible ? action.visible(row) : true)) |
| 39 |
const rowId = row[idKey] as unknown |
| 40 |
|
| 41 |
return h( |
| 42 |
'div', |
| 43 |
{ |
| 44 |
class: ['ivyforms-column-actions', { hovered: rowId === props.hoveredRowId }], |
| 45 |
}, |
| 46 |
visibleActions.map(({ action, index }) => |
| 47 |
h( |
| 48 |
IvyTooltip, |
| 49 |
{ |
| 50 |
key: `${String(rowId)}-${String(resolve(action.icon, row))}-${index}`, |
| 51 |
content: resolve(action.tooltip, row), |
| 52 |
placement: 'top', |
| 53 |
}, |
| 54 |
() => [ |
| 55 |
h(IvyButtonAction, { |
| 56 |
iconOnly: true, |
| 57 |
iconStart: resolve(action.icon, row), |
| 58 |
size: 's', |
| 59 |
type: action.type ?? 'ghost', |
| 60 |
priority: action.priority ?? 'tertiary', |
| 61 |
iconStartType: action.iconStartType ?? 'outline', |
| 62 |
ref: action.refKey |
| 63 |
? (el: unknown) => { |
| 64 |
if (!options.onButtonRef) return |
| 65 |
const node = |
| 66 |
el && |
| 67 |
typeof el === 'object' && |
| 68 |
'$el' in el && |
| 69 |
(el as { $el: unknown }).$el instanceof HTMLElement |
| 70 |
? (el as { $el: HTMLElement }).$el |
| 71 |
: null |
| 72 |
options.onButtonRef(rowId, node) |
| 73 |
} |
| 74 |
: undefined, |
| 75 |
onClick: (e: Event) => action.onClick(row, e), |
| 76 |
}), |
| 77 |
], |
| 78 |
), |
| 79 |
), |
| 80 |
) |
| 81 |
} |
| 82 |
} |
| 83 |
|