zjk
2026-07-17 47f583f707d9177486af3ac5c3c7844513691ca1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
export type TableRowKey = string | number
export type TableRowProps = Record<string, any>
export type TableRowPropsGetter<T> = (row: T) => TableRowProps | undefined
 
const DEFAULT_IGNORE_ROW_CLICK_SELECTORS = [
  '.n-checkbox',
  '.n-checkbox-box',
  '.n-checkbox-input',
  'button',
  '.n-button',
  '[role="button"]',
  'a',
  'input',
  'textarea',
  '.n-base-selection',
  '.n-switch',
  '.n-tag',
  '.n-image',
  '.cursor-pointer-text',
]
 
export function shouldIgnoreTableRowClick(target: EventTarget | null, extraSelectors: string[] = []) {
  if (!(target instanceof Element))
    return false
 
  return [...DEFAULT_IGNORE_ROW_CLICK_SELECTORS, ...extraSelectors].some(selector => target.closest(selector))
}
 
export function toggleMultiSelectRowKey<T extends TableRowKey>(rowKeys: T[], rowKey: T) {
  if (rowKeys.includes(rowKey))
    return rowKeys.filter(key => key !== rowKey)
 
  return [...rowKeys, rowKey]
}
 
export function getMultiSelectRowClassName<T extends TableRowKey>(rowKey: T, rowKeys: T[], extraClassNames: string[] = []) {
  const classNames = [...extraClassNames]
 
  if (rowKeys.includes(rowKey))
    classNames.unshift('robotaxi-table-row--selected')
 
  return classNames.join(' ')
}
 
function mergeTableEventHandler(baseHandler: unknown, nextHandler: unknown) {
  if (typeof baseHandler !== 'function')
    return nextHandler
  if (typeof nextHandler !== 'function')
    return baseHandler
 
  return (...args: any[]) => {
    baseHandler(...args)
    nextHandler(...args)
  }
}
 
function mergeSingleTableRowProps(baseProps: TableRowProps, nextProps: TableRowProps) {
  const mergedProps: TableRowProps = { ...baseProps, ...nextProps }
 
  if (baseProps.class || nextProps.class)
    mergedProps.class = [baseProps.class, nextProps.class].filter(Boolean)
 
  if (baseProps.style || nextProps.style)
    mergedProps.style = [baseProps.style, nextProps.style].filter(Boolean)
 
  const eventKeys = new Set([
    ...Object.keys(baseProps).filter(key => /^on[A-Z]/.test(key)),
    ...Object.keys(nextProps).filter(key => /^on[A-Z]/.test(key)),
  ])
 
  eventKeys.forEach((key) => {
    mergedProps[key] = mergeTableEventHandler(baseProps[key], nextProps[key])
  })
 
  return mergedProps
}
 
export function mergeTableRowProps<T>(...getters: Array<TableRowPropsGetter<T> | undefined>) {
  return (row: T) => {
    return getters.reduce<TableRowProps>((result, getter) => {
      const nextProps = getter?.(row)
      if (!nextProps)
        return result
      return mergeSingleTableRowProps(result, nextProps)
    }, {})
  }
}