@hbdlzy/ui-core 0.1.8 → 0.1.10

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.
Files changed (31) hide show
  1. package/components.manifest.json +4 -2
  2. package/dist/components/BaseCard/BaseCard.types.d.ts +1 -0
  3. package/dist/components/BaseCard/BaseCard.vue.d.ts +3 -0
  4. package/dist/components/BaseTable/BaseTable.types.d.ts +8 -1
  5. package/dist/components/BaseTable/BaseTable.vue.d.ts +4 -1
  6. package/dist/components/BaseTable/index.d.ts +1 -1
  7. package/dist/components/OutlinedCascader/OutlinedCascader.vue.d.ts +1 -1
  8. package/dist/components/OutlinedDatePicker/OutlinedDatePicker.vue.d.ts +3 -3
  9. package/dist/components/OutlinedSelect/OutlinedSelect.vue.d.ts +4 -4
  10. package/dist/components/OutlinedTimePicker/OutlinedTimePicker.vue.d.ts +6 -6
  11. package/dist/components/OutlinedTreeSelect/OutlinedTreeSelect.vue.d.ts +4 -4
  12. package/dist/index.cjs +5 -5
  13. package/dist/index.js +337 -136
  14. package/dist/style.css +1 -1
  15. package/package.json +1 -1
  16. package/src/components/BaseCard/BaseCard.types.ts +1 -0
  17. package/src/components/BaseCard/BaseCard.vue +3 -1
  18. package/src/components/BaseCard/README.md +1 -0
  19. package/src/components/BaseTable/BaseTable.types.d.ts +6 -1
  20. package/src/components/BaseTable/BaseTable.types.ts +18 -1
  21. package/src/components/BaseTable/BaseTable.vue +358 -100
  22. package/src/components/BaseTable/README.md +77 -2
  23. package/src/components/BaseTable/index.ts +1 -0
  24. package/src/components/OutlinedCascader/OutlinedCascader.vue.d.ts +2 -2
  25. package/src/components/OutlinedDatePicker/OutlinedDatePicker.vue.d.ts +3 -3
  26. package/src/components/OutlinedDateTimePicker/OutlinedDateTimePicker.vue.d.ts +1 -1
  27. package/src/components/OutlinedInput/OutlinedInput.vue.d.ts +1 -1
  28. package/src/components/OutlinedSelect/OutlinedSelect.vue.d.ts +5 -5
  29. package/src/components/OutlinedTimePicker/OutlinedTimePicker.vue.d.ts +7 -7
  30. package/src/components/OutlinedTreeSelect/OutlinedTreeSelect.vue.d.ts +5 -5
  31. package/src/index.d.ts +48 -12
@@ -37,7 +37,7 @@
37
37
  <div class="base-table__toolbar-left">
38
38
  <slot name="toolbar"></slot>
39
39
  </div>
40
- <div v-if="showPagination" class="base-table__toolbar-right">
40
+ <div v-if="shouldRenderTopPagination" class="base-table__toolbar-right">
41
41
  <el-config-provider :locale="zhCn">
42
42
  <el-pagination
43
43
  small
@@ -66,6 +66,8 @@
66
66
  :stripe="stripe"
67
67
  :default-sort="normalizedDefaultSort"
68
68
  highlight-current-row
69
+ @select="handleSelectionChange"
70
+ @select-all="handleSelectionChange"
69
71
  @selection-change="handleSelectionChange"
70
72
  @sort-change="handleSortChange"
71
73
  >
@@ -77,8 +79,9 @@
77
79
  v-if="hasSelection"
78
80
  type="selection"
79
81
  :width="selectionWidth"
82
+ fixed="left"
80
83
  align="center"
81
- :selectable="rowSelectable"
84
+ :selectable="resolveRowSelectable"
82
85
  />
83
86
 
84
87
  <el-table-column
@@ -141,6 +144,7 @@
141
144
  <button
142
145
  :ref="bindHeaderSearchTrigger(column)"
143
146
  class="base-table__header-icon"
147
+ :data-base-table-id="baseTableIconPrefix"
144
148
  :class="{ 'is-active': hasHeaderSearchValue(column) }"
145
149
  type="button"
146
150
  @click.stop="toggleHeaderSearch(column)"
@@ -155,8 +159,10 @@
155
159
  <teleport to="body">
156
160
  <div
157
161
  v-if="isHeaderSearchVisible(column)"
162
+ :ref="bindHeaderSearchPanel(column)"
158
163
  :key="getHeaderSearchStateKey(column)"
159
164
  class="base-table__header-search-panel"
165
+ :data-base-table-id="baseTableIconPrefix"
160
166
  :style="getHeaderSearchPanelStyle(column)"
161
167
  @click.stop
162
168
  @mousedown.stop
@@ -165,70 +171,27 @@
165
171
  v-if="isHeaderSearchSelect(column)"
166
172
  class="base-table__header-select"
167
173
  >
168
- <button
169
- class="base-table__header-select-trigger"
170
- type="button"
171
- @click="toggleHeaderSearchSelect(column)"
174
+ <el-select
175
+ class="base-table__header-el-select"
176
+ :model-value="getHeaderSearchSelectModelValue(column)"
177
+ :placeholder="getHeaderSearchPlaceholder(column)"
178
+ :multiple="isHeaderSearchMultiple(column)"
179
+ :filterable="isHeaderSearchFilterable(column)"
180
+ :clearable="isHeaderSearchClearable(column)"
181
+ :collapse-tags="isHeaderSearchMultiple(column)"
182
+ :collapse-tags-tooltip="isHeaderSearchMultiple(column)"
183
+ :teleported="false"
184
+ @update:model-value="handleHeaderSearchSelectModelValue(column, $event)"
185
+ @clear="handleHeaderSearchSelectEmpty(column)"
172
186
  >
173
- <span
174
- v-if="isHeaderSearchMultiple(column) && getHeaderSearchSelectedLabels(column).length"
175
- class="base-table__header-select-tags"
176
- >
177
- <span
178
- v-for="label in getHeaderSearchSelectedLabels(column).slice(0, 2)"
179
- :key="label"
180
- class="base-table__header-select-tag"
181
- >
182
- {{ label }}
183
- </span>
184
- <span
185
- v-if="getHeaderSearchSelectedLabels(column).length > 2"
186
- class="base-table__header-select-tag base-table__header-select-tag--count"
187
- >
188
- +{{ getHeaderSearchSelectedLabels(column).length - 2 }}
189
- </span>
190
- </span>
191
- <span
192
- v-else
193
- class="base-table__header-select-text"
194
- :class="{ 'is-placeholder': !hasHeaderSearchValue(column) }"
195
- >
196
- {{ getHeaderSearchSelectLabel(column) }}
197
- </span>
198
- <span
199
- class="base-table__header-select-arrow"
200
- :class="{ 'is-open': isHeaderSearchSelectOpen(column) }"
201
- aria-hidden="true"
202
- ></span>
203
- </button>
204
-
205
- <div
206
- v-if="isHeaderSearchSelectOpen(column)"
207
- class="base-table__header-select-options"
208
- >
209
- <button
210
- v-if="!isHeaderSearchMultiple(column)"
211
- class="base-table__header-select-option"
212
- :class="{ 'is-selected': !hasHeaderSearchValue(column) }"
213
- type="button"
214
- @click="handleHeaderSearchSelectEmpty(column)"
215
- >
216
- {{ getHeaderSearchPlaceholder(column) }}
217
- </button>
218
- <button
187
+ <el-option
219
188
  v-for="option in getHeaderSearchOptions(column)"
220
189
  :key="String(getHeaderSearchOptionValue(option, column))"
221
- class="base-table__header-select-option"
222
- :class="{ 'is-selected': isHeaderSearchOptionSelected(option, column) }"
223
- type="button"
190
+ :label="getHeaderSearchOptionLabel(option, column)"
191
+ :value="getHeaderSearchOptionValue(option, column)"
224
192
  :disabled="isHeaderSearchOptionDisabled(option, column)"
225
- @click="handleHeaderSearchSelectValue(column, getHeaderSearchOptionValue(option, column))"
226
- >
227
- <span class="base-table__header-select-option-label">
228
- {{ getHeaderSearchOptionLabel(option, column) }}
229
- </span>
230
- </button>
231
- </div>
193
+ />
194
+ </el-select>
232
195
  </div>
233
196
 
234
197
  <div
@@ -287,6 +250,38 @@
287
250
  </div>
288
251
  </div>
289
252
 
253
+ <el-date-picker
254
+ v-else-if="isHeaderSearchDatePicker(column)"
255
+ class="base-table__header-picker"
256
+ :model-value="getHeaderSearchPickerValue(column)"
257
+ :type="getHeaderSearchPickerType(column)"
258
+ :placeholder="getHeaderSearchPlaceholder(column)"
259
+ :start-placeholder="getHeaderSearchStartPlaceholder(column)"
260
+ :end-placeholder="getHeaderSearchEndPlaceholder(column)"
261
+ :range-separator="getHeaderSearchRangeSeparator(column)"
262
+ :format="getHeaderSearchDateFormat(column)"
263
+ :value-format="getHeaderSearchDateValueFormat(column)"
264
+ :clearable="isHeaderSearchClearable(column)"
265
+ :teleported="false"
266
+ @update:model-value="handleHeaderSearchPickerValue(column, $event)"
267
+ />
268
+
269
+ <el-time-picker
270
+ v-else-if="isHeaderSearchTimePicker(column)"
271
+ class="base-table__header-picker"
272
+ :model-value="getHeaderSearchPickerValue(column)"
273
+ :is-range="isHeaderSearchRange(column)"
274
+ :placeholder="getHeaderSearchPlaceholder(column)"
275
+ :start-placeholder="getHeaderSearchStartPlaceholder(column)"
276
+ :end-placeholder="getHeaderSearchEndPlaceholder(column)"
277
+ :range-separator="getHeaderSearchRangeSeparator(column)"
278
+ :format="getHeaderSearchTimeFormat(column)"
279
+ :value-format="getHeaderSearchTimeValueFormat(column)"
280
+ :clearable="isHeaderSearchClearable(column)"
281
+ :teleported="false"
282
+ @update:model-value="handleHeaderSearchPickerValue(column, $event)"
283
+ />
284
+
290
285
  <input
291
286
  v-else
292
287
  class="base-table__header-search-input"
@@ -387,6 +382,24 @@
387
382
  </template>
388
383
  </el-table-column>
389
384
  </el-table>
385
+
386
+ <div v-if="shouldRenderBottomPagination" class="base-table__pagination base-table__pagination--bottom">
387
+ <el-config-provider :locale="zhCn">
388
+ <el-pagination
389
+ small
390
+ background
391
+ layout="total, prev, pager, next, sizes, jumper"
392
+ :total="paginationState.total"
393
+ :current-page="paginationState.currentPage"
394
+ :page-size="paginationState.pageSize"
395
+ :page-sizes="paginationState.pageSizes"
396
+ :pager-count="5"
397
+ :popper-append-to-body="false"
398
+ @size-change="handleSizeChange"
399
+ @current-change="handleCurrentChange"
400
+ />
401
+ </el-config-provider>
402
+ </div>
390
403
  </div>
391
404
  </template>
392
405
 
@@ -409,6 +422,7 @@ import type {
409
422
  BaseTableLoadedPayload,
410
423
  BaseTableOption,
411
424
  BaseTablePagination,
425
+ BaseTablePaginationPosition,
412
426
  BaseTableProps,
413
427
  BaseTableRequestParams,
414
428
  BaseTableRowActionPayload,
@@ -443,6 +457,7 @@ const props = withDefaults(defineProps<BaseTableProps>(), {
443
457
  indexWidth: 60,
444
458
  selectionWidth: 50,
445
459
  pagination: () => ({}),
460
+ paginationPosition: 'top-right' as BaseTablePaginationPosition,
446
461
  currentPageKey: 'pageNum',
447
462
  pageSizeKey: 'pageSize',
448
463
  defaultSort: () => ({
@@ -484,6 +499,8 @@ const headerSearchSelectOpen = reactive<Record<string, boolean>>({})
484
499
  const headerSearchCascaderActivePaths = reactive<Record<string, BaseTableHeaderSearchPrimitiveValue[]>>({})
485
500
  const headerSearchTriggerRects = reactive<Record<string, DOMRect>>({})
486
501
  const headerSearchTriggerRefs = ref<Record<string, HTMLElement>>({})
502
+ const headerSearchPanelRefs = ref<Record<string, HTMLElement>>({})
503
+ const headerSearchPositionTick = ref(0)
487
504
  const baseTableIconPrefix = `base-table-icon-${++baseTableIconSeed}`
488
505
  let headerSearchPositionFrame = 0
489
506
  const sortState = reactive({
@@ -500,7 +517,9 @@ const paginationState = reactive<BaseTablePagination>({
500
517
  syncPagination(props.pagination)
501
518
 
502
519
  const normalizedHeight = computed(() => toCssValue(props.height))
503
- const shouldRenderToolbar = computed(() => props.showToolbar && (Boolean(slots.toolbar) || props.showPagination))
520
+ const shouldRenderTopPagination = computed(() => props.showPagination && props.paginationPosition === 'top-right')
521
+ const shouldRenderBottomPagination = computed(() => props.showPagination && props.paginationPosition === 'bottom-right')
522
+ const shouldRenderToolbar = computed(() => props.showToolbar && (Boolean(slots.toolbar) || shouldRenderTopPagination.value))
504
523
  const normalizedDefaultSort = computed(() => {
505
524
  if (!sortState.prop || !sortState.order) {
506
525
  return undefined
@@ -551,6 +570,7 @@ watch(
551
570
  )
552
571
 
553
572
  onMounted(() => {
573
+ document.addEventListener('click', handleDocumentClick, true)
554
574
  window.addEventListener('scroll', scheduleHeaderSearchPositionUpdate, true)
555
575
  window.addEventListener('resize', scheduleHeaderSearchPositionUpdate)
556
576
 
@@ -565,6 +585,7 @@ onMounted(() => {
565
585
  })
566
586
 
567
587
  onBeforeUnmount(() => {
588
+ document.removeEventListener('click', handleDocumentClick, true)
568
589
  window.removeEventListener('scroll', scheduleHeaderSearchPositionUpdate, true)
569
590
  window.removeEventListener('resize', scheduleHeaderSearchPositionUpdate)
570
591
 
@@ -671,6 +692,10 @@ function handleSelectionChange(value: BaseTableRow[]) {
671
692
  emit('selection-change', value)
672
693
  }
673
694
 
695
+ function resolveRowSelectable(row: BaseTableRow, index: number) {
696
+ return props.rowSelectable ? props.rowSelectable(row, index) : true
697
+ }
698
+
674
699
  function handleSortChange(payload: { prop?: string; order: BaseTableSortOrder }) {
675
700
  const column = props.columns.find((item) => String(item.prop || '') === String(payload.prop || ''))
676
701
 
@@ -793,6 +818,26 @@ function bindHeaderSearchTrigger(column: BaseTableColumn<BaseTableRow>) {
793
818
  }
794
819
  }
795
820
 
821
+ function setHeaderSearchPanelRef(
822
+ instance: Element | ComponentPublicInstance | null,
823
+ column: BaseTableColumn<BaseTableRow>
824
+ ) {
825
+ const stateKey = getHeaderSearchStateKey(column)
826
+
827
+ if (!(instance instanceof HTMLElement)) {
828
+ delete headerSearchPanelRefs.value[stateKey]
829
+ return
830
+ }
831
+
832
+ headerSearchPanelRefs.value[stateKey] = instance
833
+ }
834
+
835
+ function bindHeaderSearchPanel(column: BaseTableColumn<BaseTableRow>) {
836
+ return (instance: Element | ComponentPublicInstance | null) => {
837
+ setHeaderSearchPanelRef(instance, column)
838
+ }
839
+ }
840
+
796
841
  function isHeaderSearchVisible(column: BaseTableColumn<BaseTableRow>) {
797
842
  return Boolean(headerSearchVisible[getHeaderSearchStateKey(column)])
798
843
  }
@@ -805,6 +850,7 @@ function toggleHeaderSearch(column: BaseTableColumn<BaseTableRow>) {
805
850
  closeAllHeaderSearch()
806
851
  updateHeaderSearchTriggerRect(column)
807
852
  syncHeaderSearchCascaderActivePath(column)
853
+ scheduleHeaderSearchPositionUpdate()
808
854
  }
809
855
 
810
856
  headerSearchVisible[stateKey] = nextVisible
@@ -818,6 +864,21 @@ function closeAllHeaderSearch() {
818
864
  })
819
865
  }
820
866
 
867
+ function handleDocumentClick(event: MouseEvent) {
868
+ const target = event.target
869
+
870
+ if (target instanceof Element) {
871
+ if (
872
+ target.closest(`[data-base-table-id="${baseTableIconPrefix}"].base-table__header-search-panel`) ||
873
+ target.closest(`[data-base-table-id="${baseTableIconPrefix}"].base-table__header-icon`)
874
+ ) {
875
+ return
876
+ }
877
+ }
878
+
879
+ closeAllHeaderSearch()
880
+ }
881
+
821
882
  function updateHeaderSearchTriggerRect(column: BaseTableColumn<BaseTableRow>) {
822
883
  const stateKey = getHeaderSearchStateKey(column)
823
884
  const rect = headerSearchTriggerRefs.value[stateKey]?.getBoundingClientRect()
@@ -842,33 +903,78 @@ function scheduleHeaderSearchPositionUpdate() {
842
903
 
843
904
  headerSearchPositionFrame = window.requestAnimationFrame(() => {
844
905
  headerSearchPositionFrame = 0
906
+ headerSearchPositionTick.value += 1
845
907
  updateVisibleHeaderSearchPosition()
846
908
  })
847
909
  }
848
910
 
849
911
  function getHeaderSearchPanelStyle(column: BaseTableColumn<BaseTableRow>) {
912
+ headerSearchPositionTick.value
850
913
  const stateKey = getHeaderSearchStateKey(column)
851
914
  const triggerRect = headerSearchTriggerRects[stateKey]
852
- const width = toCssValue(getHeaderSearchWidth(column)) || '280px'
915
+ const panelWidth = getHeaderSearchPanelWidth(column)
916
+ const style = {
917
+ width: panelWidth.width,
918
+ minWidth: panelWidth.minWidth,
919
+ maxWidth: panelWidth.maxWidth
920
+ }
853
921
 
854
922
  if (!triggerRect) {
855
- return {
856
- width
857
- }
923
+ return style
858
924
  }
859
925
 
860
- const panelWidth = Number.parseFloat(String(getHeaderSearchWidth(column))) || 280
861
- const maxLeft = Math.max(8, window.innerWidth - panelWidth - 8)
862
- const left = Math.min(maxLeft, Math.max(8, triggerRect.right - panelWidth))
926
+ const maxLeft = Math.max(8, window.innerWidth - panelWidth.positionWidth - 8)
927
+ const left = Math.min(maxLeft, Math.max(8, triggerRect.right - panelWidth.positionWidth))
863
928
  const top = triggerRect.bottom + 8
864
929
 
865
930
  return {
866
- width,
931
+ ...style,
867
932
  left: `${left}px`,
868
933
  top: `${top}px`
869
934
  }
870
935
  }
871
936
 
937
+ function getHeaderSearchPanelWidth(column: BaseTableColumn<BaseTableRow>) {
938
+ const rawWidth = getHeaderSearchWidth(column)
939
+ const viewportMaxWidth = Math.max(220, window.innerWidth - 16)
940
+ const renderedWidth = getRenderedHeaderSearchPanelWidth(column)
941
+
942
+ if (rawWidth === 'auto') {
943
+ const positionWidth = Math.min(renderedWidth || getHeaderSearchAutoWidth(column), viewportMaxWidth)
944
+ return {
945
+ width: 'max-content',
946
+ minWidth: '280px',
947
+ maxWidth: `${viewportMaxWidth}px`,
948
+ positionWidth
949
+ }
950
+ }
951
+
952
+ const width = toCssValue(rawWidth) || '280px'
953
+ const positionWidth = Math.min(Number.parseFloat(String(rawWidth)) || 280, viewportMaxWidth)
954
+
955
+ return {
956
+ width,
957
+ minWidth: width,
958
+ maxWidth: `${viewportMaxWidth}px`,
959
+ positionWidth
960
+ }
961
+ }
962
+
963
+ function getRenderedHeaderSearchPanelWidth(column: BaseTableColumn<BaseTableRow>) {
964
+ const stateKey = getHeaderSearchStateKey(column)
965
+ const panelElement = headerSearchPanelRefs.value[stateKey]
966
+ return panelElement ? panelElement.getBoundingClientRect().width : 0
967
+ }
968
+
969
+ function getHeaderSearchAutoWidth(column: BaseTableColumn<BaseTableRow>) {
970
+ if (isHeaderSearchRange(column)) {
971
+ const type = getHeaderSearchConfig(column)?.type
972
+ return type === 'daterange' || type === 'timerange' ? 420 : 560
973
+ }
974
+
975
+ return 280
976
+ }
977
+
872
978
  function getHeaderSearchValue(column: BaseTableColumn<BaseTableRow>): BaseTableHeaderSearchValue {
873
979
  const stateKey = getHeaderSearchStateKey(column)
874
980
  const value = headerSearchValues[stateKey]
@@ -905,6 +1011,25 @@ function isHeaderSearchCascader(column: BaseTableColumn<BaseTableRow>) {
905
1011
  return getHeaderSearchConfig(column)?.type === 'cascader'
906
1012
  }
907
1013
 
1014
+ function isHeaderSearchDatePicker(column: BaseTableColumn<BaseTableRow>) {
1015
+ const type = getHeaderSearchConfig(column)?.type
1016
+ return type === 'date' || type === 'daterange' || type === 'datetime' || type === 'datetimerange'
1017
+ }
1018
+
1019
+ function isHeaderSearchTimePicker(column: BaseTableColumn<BaseTableRow>) {
1020
+ const type = getHeaderSearchConfig(column)?.type
1021
+ return type === 'time' || type === 'timerange'
1022
+ }
1023
+
1024
+ function isHeaderSearchPicker(column: BaseTableColumn<BaseTableRow>) {
1025
+ return isHeaderSearchDatePicker(column) || isHeaderSearchTimePicker(column)
1026
+ }
1027
+
1028
+ function isHeaderSearchRange(column: BaseTableColumn<BaseTableRow>) {
1029
+ const type = getHeaderSearchConfig(column)?.type
1030
+ return type === 'daterange' || type === 'datetimerange' || type === 'timerange'
1031
+ }
1032
+
908
1033
  function isHeaderSearchChoice(column: BaseTableColumn<BaseTableRow>) {
909
1034
  return isHeaderSearchSelect(column) || isHeaderSearchCascader(column)
910
1035
  }
@@ -961,8 +1086,60 @@ function getHeaderSearchPlaceholder(column: BaseTableColumn<BaseTableRow>) {
961
1086
  return getHeaderSearchConfig(column)?.placeholder || (isHeaderSearchChoice(column) ? '请选择' : '请输入搜索内容')
962
1087
  }
963
1088
 
1089
+ function getHeaderSearchStartPlaceholder(column: BaseTableColumn<BaseTableRow>) {
1090
+ return getHeaderSearchConfig(column)?.startPlaceholder || '开始时间'
1091
+ }
1092
+
1093
+ function getHeaderSearchEndPlaceholder(column: BaseTableColumn<BaseTableRow>) {
1094
+ return getHeaderSearchConfig(column)?.endPlaceholder || '结束时间'
1095
+ }
1096
+
1097
+ function getHeaderSearchRangeSeparator(column: BaseTableColumn<BaseTableRow>) {
1098
+ return getHeaderSearchConfig(column)?.rangeSeparator || '至'
1099
+ }
1100
+
1101
+ function getHeaderSearchPickerType(column: BaseTableColumn<BaseTableRow>) {
1102
+ const type = getHeaderSearchConfig(column)?.type
1103
+
1104
+ if (type === 'datetime' || type === 'datetimerange') {
1105
+ return type
1106
+ }
1107
+
1108
+ return type === 'daterange' ? 'daterange' : 'date'
1109
+ }
1110
+
1111
+ function getHeaderSearchDateFormat(column: BaseTableColumn<BaseTableRow>) {
1112
+ const config = getHeaderSearchConfig(column)
1113
+
1114
+ if (config?.format) {
1115
+ return config.format
1116
+ }
1117
+
1118
+ return getHeaderSearchConfig(column)?.type === 'datetime' || getHeaderSearchConfig(column)?.type === 'datetimerange'
1119
+ ? 'YYYY-MM-DD HH:mm:ss'
1120
+ : 'YYYY-MM-DD'
1121
+ }
1122
+
1123
+ function getHeaderSearchDateValueFormat(column: BaseTableColumn<BaseTableRow>) {
1124
+ return getHeaderSearchConfig(column)?.valueFormat || getHeaderSearchDateFormat(column)
1125
+ }
1126
+
1127
+ function getHeaderSearchTimeFormat(column: BaseTableColumn<BaseTableRow>) {
1128
+ return getHeaderSearchConfig(column)?.format || 'HH:mm:ss'
1129
+ }
1130
+
1131
+ function getHeaderSearchTimeValueFormat(column: BaseTableColumn<BaseTableRow>) {
1132
+ return getHeaderSearchConfig(column)?.valueFormat || getHeaderSearchTimeFormat(column)
1133
+ }
1134
+
964
1135
  function getHeaderSearchWidth(column: BaseTableColumn<BaseTableRow>) {
965
- return getHeaderSearchConfig(column)?.width || 280
1136
+ const configuredWidth = getHeaderSearchConfig(column)?.width
1137
+
1138
+ if (configuredWidth !== undefined && configuredWidth !== null && configuredWidth !== '') {
1139
+ return configuredWidth
1140
+ }
1141
+
1142
+ return isHeaderSearchRange(column) ? 'auto' : 280
966
1143
  }
967
1144
 
968
1145
  function getHeaderSearchSearchText(column: BaseTableColumn<BaseTableRow>) {
@@ -1025,9 +1202,14 @@ function getHeaderSearchSelectedLabels(column: BaseTableColumn<BaseTableRow>) {
1025
1202
  })
1026
1203
  }
1027
1204
 
1028
- function isHeaderSearchOptionSelected(option: BaseTableOption, column: BaseTableColumn<BaseTableRow>) {
1029
- const optionValue = String(getHeaderSearchOptionValue(option, column))
1030
- return toComparableValues(getHeaderSearchValue(column)).includes(optionValue)
1205
+ function getHeaderSearchSelectModelValue(column: BaseTableColumn<BaseTableRow>) {
1206
+ const value = getHeaderSearchValue(column)
1207
+
1208
+ if (isHeaderSearchMultiple(column)) {
1209
+ return Array.isArray(value) ? value : []
1210
+ }
1211
+
1212
+ return Array.isArray(value) ? value[0] ?? '' : value
1031
1213
  }
1032
1214
 
1033
1215
  function handleHeaderSearchSelectEmpty(column: BaseTableColumn<BaseTableRow>) {
@@ -1035,33 +1217,17 @@ function handleHeaderSearchSelectEmpty(column: BaseTableColumn<BaseTableRow>) {
1035
1217
  headerSearchSelectOpen[getHeaderSearchStateKey(column)] = false
1036
1218
  }
1037
1219
 
1038
- function handleHeaderSearchSelectValue(
1039
- column: BaseTableColumn<BaseTableRow>,
1040
- optionValue: BaseTableHeaderSearchPrimitiveValue
1041
- ) {
1042
- if (!isHeaderSearchMultiple(column)) {
1043
- updateHeaderSearchValue(column, optionValue)
1044
- headerSearchSelectOpen[getHeaderSearchStateKey(column)] = false
1045
- return
1046
- }
1047
-
1048
- const currentValues = Array.isArray(getHeaderSearchValue(column))
1049
- ? [...getHeaderSearchValue(column) as BaseTableHeaderSearchPrimitiveValue[]]
1050
- : []
1051
- const comparableValue = String(optionValue)
1052
- const matchedIndex = currentValues.findIndex((item) => String(item) === comparableValue)
1053
-
1054
- if (matchedIndex >= 0) {
1055
- currentValues.splice(matchedIndex, 1)
1056
- } else {
1057
- currentValues.push(optionValue)
1058
- }
1220
+ function handleHeaderSearchSelectModelValue(column: BaseTableColumn<BaseTableRow>, value: unknown) {
1221
+ updateHeaderSearchValue(column, value)
1222
+ }
1059
1223
 
1060
- updateHeaderSearchValue(column, currentValues)
1224
+ function getHeaderSearchPickerValue(column: BaseTableColumn<BaseTableRow>) {
1225
+ const value = getHeaderSearchValue(column)
1226
+ return Array.isArray(value) ? [...value] : value
1061
1227
  }
1062
1228
 
1063
- function handleHeaderSearchSelectOption(column: BaseTableColumn<BaseTableRow>, option: BaseTableOption) {
1064
- handleHeaderSearchSelectValue(column, getHeaderSearchOptionValue(option, column))
1229
+ function handleHeaderSearchPickerValue(column: BaseTableColumn<BaseTableRow>, value: unknown) {
1230
+ updateHeaderSearchValue(column, value)
1065
1231
  }
1066
1232
 
1067
1233
  function getHeaderSearchCascaderValue(column: BaseTableColumn<BaseTableRow>) {
@@ -1271,13 +1437,17 @@ function filterLocalRows(data: BaseTableRow[]) {
1271
1437
  return matchesHeaderSearchCascaderValue(value, searchValue)
1272
1438
  }
1273
1439
 
1440
+ if (isHeaderSearchPicker(column)) {
1441
+ return matchesHeaderSearchPickerValue(value, searchValue, column)
1442
+ }
1443
+
1274
1444
  return toSearchableText(value).includes(toHeaderSearchKeyword(searchValue))
1275
1445
  })
1276
1446
  })
1277
1447
  }
1278
1448
 
1279
1449
  function getHeaderSearchEmptyValue(column: BaseTableColumn<BaseTableRow>): BaseTableHeaderSearchValue {
1280
- return isHeaderSearchMultiple(column) || isHeaderSearchCascader(column) ? [] : ''
1450
+ return isHeaderSearchMultiple(column) || isHeaderSearchCascader(column) || isHeaderSearchRange(column) ? [] : ''
1281
1451
  }
1282
1452
 
1283
1453
  function normalizeHeaderSearchValue(
@@ -1288,6 +1458,18 @@ function normalizeHeaderSearchValue(
1288
1458
  return normalizeHeaderSearchPathValue(value)
1289
1459
  }
1290
1460
 
1461
+ if (isHeaderSearchPicker(column)) {
1462
+ if (isHeaderSearchRange(column)) {
1463
+ return normalizeHeaderSearchPathValue(value)
1464
+ }
1465
+
1466
+ if (value === undefined || value === null) {
1467
+ return ''
1468
+ }
1469
+
1470
+ return normalizeHeaderSearchPrimitiveValue(value)
1471
+ }
1472
+
1291
1473
  if (!isHeaderSearchSelect(column)) {
1292
1474
  if (value === undefined || value === null) {
1293
1475
  return ''
@@ -1389,6 +1571,53 @@ function matchesHeaderSearchCascaderValue(rowValue: unknown, searchValue: BaseTa
1389
1571
  return selectedPath.every((item, index) => String(rowPath[index]) === String(item))
1390
1572
  }
1391
1573
 
1574
+ function matchesHeaderSearchPickerValue(
1575
+ rowValue: unknown,
1576
+ searchValue: BaseTableHeaderSearchValue,
1577
+ column: BaseTableColumn<BaseTableRow>
1578
+ ) {
1579
+ if (isHeaderSearchRange(column)) {
1580
+ const selectedRange = normalizeHeaderSearchPathValue(searchValue)
1581
+
1582
+ if (!selectedRange.length) {
1583
+ return true
1584
+ }
1585
+
1586
+ const rowTime = toComparableTime(rowValue)
1587
+ const startTime = toComparableTime(selectedRange[0])
1588
+ const endTime = toComparableTime(selectedRange[1])
1589
+
1590
+ if (rowTime === null) {
1591
+ return false
1592
+ }
1593
+
1594
+ return (startTime === null || rowTime >= startTime) && (endTime === null || rowTime <= endTime)
1595
+ }
1596
+
1597
+ return String(rowValue || '') === String(searchValue || '')
1598
+ }
1599
+
1600
+ function toComparableTime(value: unknown) {
1601
+ if (value === undefined || value === null || value === '') {
1602
+ return null
1603
+ }
1604
+
1605
+ if (value instanceof Date) {
1606
+ return value.getTime()
1607
+ }
1608
+
1609
+ const normalizedValue = String(value).trim()
1610
+ const parsedValue = Date.parse(normalizedValue)
1611
+
1612
+ if (!Number.isNaN(parsedValue)) {
1613
+ return parsedValue
1614
+ }
1615
+
1616
+ const today = new Date().toISOString().slice(0, 10)
1617
+ const parsedTime = Date.parse(`${today} ${normalizedValue}`)
1618
+ return Number.isNaN(parsedTime) ? null : parsedTime
1619
+ }
1620
+
1392
1621
  function toComparableValues(value: unknown) {
1393
1622
  const values = Array.isArray(value) ? value : [value]
1394
1623
  return values
@@ -1792,6 +2021,16 @@ defineExpose<BaseTableExpose>({
1792
2021
  flex: 0 1 auto;
1793
2022
  }
1794
2023
 
2024
+ .base-table__pagination {
2025
+ display: flex;
2026
+ justify-content: flex-end;
2027
+ flex: 0 0 auto;
2028
+ }
2029
+
2030
+ .base-table__pagination--bottom {
2031
+ margin-top: 16px;
2032
+ }
2033
+
1795
2034
  .base-table__actions {
1796
2035
  display: flex;
1797
2036
  align-items: center;
@@ -1956,6 +2195,25 @@ defineExpose<BaseTableExpose>({
1956
2195
  width: 100%;
1957
2196
  }
1958
2197
 
2198
+ .base-table__header-el-select {
2199
+ width: 100%;
2200
+ }
2201
+
2202
+ .base-table__header-el-select :deep(.el-select__wrapper) {
2203
+ min-height: 32px;
2204
+ }
2205
+
2206
+ .base-table__header-picker {
2207
+ width: 100%;
2208
+ }
2209
+
2210
+ .base-table__header-picker :deep(.el-input__wrapper),
2211
+ .base-table__header-picker :deep(.el-range-editor.el-input__wrapper) {
2212
+ width: 100%;
2213
+ min-height: 32px;
2214
+ box-sizing: border-box;
2215
+ }
2216
+
1959
2217
  .base-table__header-select-trigger {
1960
2218
  display: flex;
1961
2219
  align-items: center;