stk-table-vue 1.2.5 → 1.2.6

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 (65) hide show
  1. package/README.md +194 -194
  2. package/lib/{Dropdown-C4c7Nmgf.js → Dropdown-BAANgg_5.js} +2 -2
  3. package/lib/{StkTable-CzktjLlV.js → StkTable-CGcxwpdb.js} +2 -1
  4. package/lib/stk-table-vue.js +3 -3
  5. package/lib/style.css +1 -1
  6. package/package.json +93 -93
  7. package/src/StkTable/StkTable.vue +2362 -2359
  8. package/src/StkTable/components/DragHandle.vue +9 -9
  9. package/src/StkTable/components/SortIcon.vue +6 -6
  10. package/src/StkTable/components/TreeNodeCell.vue +19 -19
  11. package/src/StkTable/components/TriangleIcon.vue +3 -3
  12. package/src/StkTable/const.ts +50 -50
  13. package/src/StkTable/custom-cells/ChangeCell/ChangeCell.less +34 -34
  14. package/src/StkTable/custom-cells/ChangeCell/createChangeCell.ts +90 -90
  15. package/src/StkTable/custom-cells/ChangeCell/index.ts +4 -4
  16. package/src/StkTable/custom-cells/CheckboxCell/CheckboxCell.less +14 -14
  17. package/src/StkTable/custom-cells/CheckboxCell/CheckboxCell.vue +56 -56
  18. package/src/StkTable/custom-cells/CheckboxCell/createCheckboxCell.ts +146 -146
  19. package/src/StkTable/custom-cells/CheckboxCell/index.ts +5 -5
  20. package/src/StkTable/custom-cells/FilterCell/Dropdown/index.ts +16 -16
  21. package/src/StkTable/custom-cells/FilterCell/Dropdown/index.vue +186 -186
  22. package/src/StkTable/custom-cells/FilterCell/Filter.less +118 -118
  23. package/src/StkTable/custom-cells/FilterCell/Filter.vue +66 -66
  24. package/src/StkTable/custom-cells/FilterCell/createFilterCell.ts +120 -120
  25. package/src/StkTable/custom-cells/FilterCell/index.ts +6 -6
  26. package/src/StkTable/custom-cells/FilterCell/types.ts +43 -43
  27. package/src/StkTable/custom-cells/NumberCell/createNumberCell.ts +43 -43
  28. package/src/StkTable/custom-cells/NumberCell/index.ts +2 -2
  29. package/src/StkTable/custom-cells/utils/formatNumber.ts +137 -137
  30. package/src/StkTable/features/const.ts +1 -1
  31. package/src/StkTable/features/index.ts +1 -1
  32. package/src/StkTable/features/useAreaSelection.ts +1240 -1240
  33. package/src/StkTable/index.ts +20 -20
  34. package/src/StkTable/mergeCellsCache.ts +69 -69
  35. package/src/StkTable/registerFeature.ts +40 -40
  36. package/src/StkTable/style.less +791 -791
  37. package/src/StkTable/types/highlightDimOptions.ts +28 -28
  38. package/src/StkTable/types/index.ts +503 -503
  39. package/src/StkTable/useAutoResize.ts +87 -87
  40. package/src/StkTable/useColResize.ts +202 -202
  41. package/src/StkTable/useFixedCol.ts +168 -168
  42. package/src/StkTable/useFixedStyle.ts +75 -75
  43. package/src/StkTable/useGetFixedColPosition.ts +63 -63
  44. package/src/StkTable/useHighlight.ts +270 -270
  45. package/src/StkTable/useIndexResolver.ts +29 -29
  46. package/src/StkTable/useKeyboardArrowScroll.ts +114 -114
  47. package/src/StkTable/useMaxRowSpan.ts +60 -60
  48. package/src/StkTable/useMergeCells.ts +541 -541
  49. package/src/StkTable/useRowExpand.ts +81 -81
  50. package/src/StkTable/useScrollRowByRow.ts +96 -96
  51. package/src/StkTable/useScrollbar.ts +177 -177
  52. package/src/StkTable/useSorter.ts +267 -267
  53. package/src/StkTable/useTableColumns.ts +142 -142
  54. package/src/StkTable/useThDrag.ts +94 -94
  55. package/src/StkTable/useTrDrag.ts +100 -100
  56. package/src/StkTable/useTree.ts +253 -253
  57. package/src/StkTable/useVirtualScroll.ts +1032 -1032
  58. package/src/StkTable/useWheeling.ts +23 -23
  59. package/src/StkTable/utils/constRefUtils.ts +29 -29
  60. package/src/StkTable/utils/index.ts +331 -331
  61. package/src/StkTable/utils/rowHeightFenwickTree.ts +74 -74
  62. package/src/StkTable/utils/useTriggerRef.ts +33 -33
  63. package/src/VirtualTree.vue +622 -622
  64. package/src/VirtualTreeSelect.vue +367 -367
  65. package/src/vite-env.d.ts +10 -10
@@ -1,186 +1,186 @@
1
- <script setup lang="ts">
2
- import { StkTableColumn } from '@/StkTable/types';
3
- import { h, nextTick, onMounted, onUnmounted, reactive, ref } from 'vue';
4
- import StkTable from '../../../StkTable.vue';
5
- import type { FilterOption } from '../types.js';
6
-
7
- const theme = ref<'light' | 'dark'>('light');
8
- const checkedTempValueSet = reactive<Set<FilterOption['value']>>(new Set());
9
-
10
- const columns = ref<StkTableColumn<FilterOption>[]>([
11
- {
12
- title: '',
13
- dataIndex: 'value',
14
- width: 30,
15
- className: 'stk-filter-dropdown-checkbox',
16
- customCell: ({ row }) =>
17
- h('input', {
18
- type: 'checkbox',
19
- checked: checkedTempValueSet.has(row.value),
20
- }),
21
- },
22
- { title: '', dataIndex: 'label' },
23
- ]);
24
-
25
- const visible = ref(false);
26
- const position = ref<{ x: number; y: number }>({ x: 0, y: 0 });
27
- const options = ref<FilterOption[]>([]);
28
-
29
- const dropdownEl = ref<HTMLDivElement>();
30
-
31
- const DROPDOWN_DEFAULT_WIDTH = 300; // 默认宽度(用于首次计算)
32
- const DROPDOWN_DEFAULT_HEIGHT = 400; // 默认高度(用于首次计算)
33
- const PADDING = 6; // 与屏幕边缘的安全距离
34
-
35
- onMounted(() => {
36
- document.addEventListener('click', handleClickOutside);
37
- });
38
-
39
- onUnmounted(() => {
40
- document.removeEventListener('click', handleClickOutside);
41
- });
42
-
43
- let onConfirmFn: (values: FilterOption['value'][]) => void;
44
-
45
- function getDropdownSize() {
46
- if (!dropdownEl.value) {
47
- return [DROPDOWN_DEFAULT_WIDTH, DROPDOWN_DEFAULT_HEIGHT] as const;
48
- }
49
- const rect = dropdownEl.value.getBoundingClientRect();
50
- return [rect.width || DROPDOWN_DEFAULT_WIDTH, rect.height || DROPDOWN_DEFAULT_HEIGHT] as const;
51
- }
52
-
53
- function calculatePosition(docPos: { x: number; y: number; height?: number }) {
54
- // docPos 是相对于文档的坐标(已包含滚动偏移)
55
- const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
56
- const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
57
- const viewportWidth = document.documentElement.clientWidth;
58
- const viewportHeight = document.documentElement.clientHeight;
59
-
60
- const [dropdownWidth, dropdownHeight] = getDropdownSize();
61
-
62
- let finalX = docPos.x;
63
- let finalY = docPos.y;
64
-
65
- // 检测是否超出右边界(相对于视口)
66
- const relativeX = docPos.x - scrollLeft;
67
- if (relativeX + dropdownWidth > viewportWidth - PADDING) {
68
- finalX = viewportWidth - dropdownWidth - PADDING + scrollLeft;
69
- }
70
-
71
- // 检测是否超出下边界(相对于视口)
72
- const relativeY = docPos.y - scrollTop;
73
- if (relativeY + dropdownHeight > viewportHeight - PADDING) {
74
- // 如果下方空间不足,尝试在上方显示
75
- const triggerHeight = docPos.height || 30;
76
- if (relativeY - triggerHeight >= dropdownHeight + PADDING) {
77
- // 上方空间足够,在触发元素上方显示
78
- finalY = docPos.y - triggerHeight - dropdownHeight - PADDING;
79
- } else {
80
- // 上方空间也不足,使用最大可用空间(从视口顶部开始)
81
- finalY = PADDING + scrollTop;
82
- }
83
- }
84
-
85
- // 确保不会超出左边界和上边界
86
- finalX = Math.max(PADDING + scrollLeft, finalX);
87
- finalY = Math.max(PADDING + scrollTop, finalY);
88
-
89
- return { x: finalX, y: finalY };
90
- }
91
-
92
- async function show(pos: { x: number; y: number; height?: number }, opt: FilterOption[], onConfirm: (values: FilterOption['value'][]) => void) {
93
- if (dropdownEl.value) {
94
- dropdownEl.value.style.visibility = 'hidden';
95
- }
96
- visible.value = true;
97
- options.value = opt || [];
98
- initChecked();
99
- onConfirmFn = onConfirm;
100
- await nextTick();
101
- position.value = calculatePosition(pos);
102
- if (dropdownEl.value) {
103
- dropdownEl.value.style.visibility = 'visible';
104
- }
105
- }
106
-
107
- async function handleClickOutside(e: MouseEvent) {
108
- if (!visible.value || dropdownEl.value?.contains(e.target as Node)) return;
109
- hide();
110
- }
111
-
112
- function initChecked() {
113
- options.value.forEach(opt => {
114
- if (opt.selected) {
115
- checkedTempValueSet.add(opt.value);
116
- }
117
- });
118
- }
119
-
120
- function updateChecked(checked: boolean, row: FilterOption) {
121
- if (checked) {
122
- checkedTempValueSet.add(row.value);
123
- } else {
124
- checkedTempValueSet.delete(row.value);
125
- }
126
- }
127
-
128
- function confirm() {
129
- options.value.forEach(opt => (opt.selected = checkedTempValueSet.has(opt.value)));
130
- onConfirmFn(Array.from(checkedTempValueSet));
131
- hide();
132
- }
133
- function hide() {
134
- visible.value = false;
135
- options.value = [];
136
- checkedTempValueSet.clear();
137
- }
138
- function handleRowClick(e: MouseEvent, row: FilterOption) {
139
- const selected = checkedTempValueSet.has(row.value);
140
- updateChecked(!selected, row);
141
- }
142
-
143
- function setTheme(t: 'light' | 'dark') {
144
- theme.value = t;
145
- }
146
-
147
- function handleClear() {
148
- checkedTempValueSet.clear();
149
- options.value.forEach(opt => (opt.selected = false));
150
- onConfirmFn([]);
151
- hide();
152
- }
153
-
154
- defineExpose({ visible, show, hide, setTheme });
155
- </script>
156
- <template>
157
- <div
158
- ref="dropdownEl"
159
- class="stk-filter-dropdown"
160
- :class="[`stk-filter-dropdown--${theme}`]"
161
- :style="{
162
- top: position.y + 'px',
163
- left: position.x + 'px',
164
- display: visible ? void 0 : 'none',
165
- }"
166
- @click.stop
167
- >
168
- <StkTable
169
- row-key="id"
170
- headless
171
- virtual
172
- no-data-full
173
- :theme="theme"
174
- :row-active="false"
175
- :row-height="20"
176
- :bordered="false"
177
- :columns="columns"
178
- :data-source="options"
179
- @row-click="handleRowClick"
180
- />
181
- <footer>
182
- <button @click="handleClear">↺</button>
183
- <button @click="confirm">✓</button>
184
- </footer>
185
- </div>
186
- </template>
1
+ <script setup lang="ts">
2
+ import { StkTableColumn } from '@/StkTable/types';
3
+ import { h, nextTick, onMounted, onUnmounted, reactive, ref } from 'vue';
4
+ import StkTable from '../../../StkTable.vue';
5
+ import type { FilterOption } from '../types.js';
6
+
7
+ const theme = ref<'light' | 'dark'>('light');
8
+ const checkedTempValueSet = reactive<Set<FilterOption['value']>>(new Set());
9
+
10
+ const columns = ref<StkTableColumn<FilterOption>[]>([
11
+ {
12
+ title: '',
13
+ dataIndex: 'value',
14
+ width: 30,
15
+ className: 'stk-filter-dropdown-checkbox',
16
+ customCell: ({ row }) =>
17
+ h('input', {
18
+ type: 'checkbox',
19
+ checked: checkedTempValueSet.has(row.value),
20
+ }),
21
+ },
22
+ { title: '', dataIndex: 'label' },
23
+ ]);
24
+
25
+ const visible = ref(false);
26
+ const position = ref<{ x: number; y: number }>({ x: 0, y: 0 });
27
+ const options = ref<FilterOption[]>([]);
28
+
29
+ const dropdownEl = ref<HTMLDivElement>();
30
+
31
+ const DROPDOWN_DEFAULT_WIDTH = 300; // 默认宽度(用于首次计算)
32
+ const DROPDOWN_DEFAULT_HEIGHT = 400; // 默认高度(用于首次计算)
33
+ const PADDING = 6; // 与屏幕边缘的安全距离
34
+
35
+ onMounted(() => {
36
+ document.addEventListener('click', handleClickOutside);
37
+ });
38
+
39
+ onUnmounted(() => {
40
+ document.removeEventListener('click', handleClickOutside);
41
+ });
42
+
43
+ let onConfirmFn: (values: FilterOption['value'][]) => void;
44
+
45
+ function getDropdownSize() {
46
+ if (!dropdownEl.value) {
47
+ return [DROPDOWN_DEFAULT_WIDTH, DROPDOWN_DEFAULT_HEIGHT] as const;
48
+ }
49
+ const rect = dropdownEl.value.getBoundingClientRect();
50
+ return [rect.width || DROPDOWN_DEFAULT_WIDTH, rect.height || DROPDOWN_DEFAULT_HEIGHT] as const;
51
+ }
52
+
53
+ function calculatePosition(docPos: { x: number; y: number; height?: number }) {
54
+ // docPos 是相对于文档的坐标(已包含滚动偏移)
55
+ const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
56
+ const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
57
+ const viewportWidth = document.documentElement.clientWidth;
58
+ const viewportHeight = document.documentElement.clientHeight;
59
+
60
+ const [dropdownWidth, dropdownHeight] = getDropdownSize();
61
+
62
+ let finalX = docPos.x;
63
+ let finalY = docPos.y;
64
+
65
+ // 检测是否超出右边界(相对于视口)
66
+ const relativeX = docPos.x - scrollLeft;
67
+ if (relativeX + dropdownWidth > viewportWidth - PADDING) {
68
+ finalX = viewportWidth - dropdownWidth - PADDING + scrollLeft;
69
+ }
70
+
71
+ // 检测是否超出下边界(相对于视口)
72
+ const relativeY = docPos.y - scrollTop;
73
+ if (relativeY + dropdownHeight > viewportHeight - PADDING) {
74
+ // 如果下方空间不足,尝试在上方显示
75
+ const triggerHeight = docPos.height || 30;
76
+ if (relativeY - triggerHeight >= dropdownHeight + PADDING) {
77
+ // 上方空间足够,在触发元素上方显示
78
+ finalY = docPos.y - triggerHeight - dropdownHeight - PADDING;
79
+ } else {
80
+ // 上方空间也不足,使用最大可用空间(从视口顶部开始)
81
+ finalY = PADDING + scrollTop;
82
+ }
83
+ }
84
+
85
+ // 确保不会超出左边界和上边界
86
+ finalX = Math.max(PADDING + scrollLeft, finalX);
87
+ finalY = Math.max(PADDING + scrollTop, finalY);
88
+
89
+ return { x: finalX, y: finalY };
90
+ }
91
+
92
+ async function show(pos: { x: number; y: number; height?: number }, opt: FilterOption[], onConfirm: (values: FilterOption['value'][]) => void) {
93
+ if (dropdownEl.value) {
94
+ dropdownEl.value.style.visibility = 'hidden';
95
+ }
96
+ visible.value = true;
97
+ options.value = opt || [];
98
+ initChecked();
99
+ onConfirmFn = onConfirm;
100
+ await nextTick();
101
+ position.value = calculatePosition(pos);
102
+ if (dropdownEl.value) {
103
+ dropdownEl.value.style.visibility = 'visible';
104
+ }
105
+ }
106
+
107
+ async function handleClickOutside(e: MouseEvent) {
108
+ if (!visible.value || dropdownEl.value?.contains(e.target as Node)) return;
109
+ hide();
110
+ }
111
+
112
+ function initChecked() {
113
+ options.value.forEach(opt => {
114
+ if (opt.selected) {
115
+ checkedTempValueSet.add(opt.value);
116
+ }
117
+ });
118
+ }
119
+
120
+ function updateChecked(checked: boolean, row: FilterOption) {
121
+ if (checked) {
122
+ checkedTempValueSet.add(row.value);
123
+ } else {
124
+ checkedTempValueSet.delete(row.value);
125
+ }
126
+ }
127
+
128
+ function confirm() {
129
+ options.value.forEach(opt => (opt.selected = checkedTempValueSet.has(opt.value)));
130
+ onConfirmFn(Array.from(checkedTempValueSet));
131
+ hide();
132
+ }
133
+ function hide() {
134
+ visible.value = false;
135
+ options.value = [];
136
+ checkedTempValueSet.clear();
137
+ }
138
+ function handleRowClick(e: MouseEvent, row: FilterOption) {
139
+ const selected = checkedTempValueSet.has(row.value);
140
+ updateChecked(!selected, row);
141
+ }
142
+
143
+ function setTheme(t: 'light' | 'dark') {
144
+ theme.value = t;
145
+ }
146
+
147
+ function handleClear() {
148
+ checkedTempValueSet.clear();
149
+ options.value.forEach(opt => (opt.selected = false));
150
+ onConfirmFn([]);
151
+ hide();
152
+ }
153
+
154
+ defineExpose({ visible, show, hide, setTheme });
155
+ </script>
156
+ <template>
157
+ <div
158
+ ref="dropdownEl"
159
+ class="stk-filter-dropdown"
160
+ :class="[`stk-filter-dropdown--${theme}`]"
161
+ :style="{
162
+ top: position.y + 'px',
163
+ left: position.x + 'px',
164
+ display: visible ? void 0 : 'none',
165
+ }"
166
+ @click.stop
167
+ >
168
+ <StkTable
169
+ row-key="id"
170
+ headless
171
+ virtual
172
+ no-data-full
173
+ :theme="theme"
174
+ :row-active="false"
175
+ :row-height="20"
176
+ :bordered="false"
177
+ :columns="columns"
178
+ :data-source="options"
179
+ @row-click="handleRowClick"
180
+ />
181
+ <footer>
182
+ <button @click="handleClear">↺</button>
183
+ <button @click="confirm">✓</button>
184
+ </footer>
185
+ </div>
186
+ </template>
@@ -1,118 +1,118 @@
1
- .stk-table.header-text-overflow {
2
- .stk-filter >span {
3
- text-overflow: ellipsis;
4
- white-space: nowrap;
5
- }
6
- }
7
-
8
- .stk-filter {
9
- display: inline-flex;
10
- align-items: center;
11
- gap: 4px;
12
- cursor: pointer;
13
- flex: 1;
14
- min-width: 0;
15
- &--light {
16
- --icon-active-color: #1b63d9;
17
- --icon-hover-color: #1890ff;
18
- }
19
-
20
- &--dark {
21
- --icon-active-color: #1b63d9;
22
- --icon-hover-color: #4f8df4;
23
- }
24
-
25
- &.stk-filter--active {
26
- .stk-filter-icon {
27
- color: var(--icon-active-color);
28
- }
29
- }
30
- >span {
31
- flex: 1;
32
- min-width: 0;
33
- overflow: hidden;
34
- }
35
-
36
- .stk-filter-icon {
37
- display: inline-flex;
38
- width: 16px;
39
- height: 16px;
40
- cursor: pointer;
41
- opacity: 0.6;
42
- transition: opacity 0.2s;
43
- flex-shrink: 0;
44
- &:hover {
45
- opacity: 1;
46
- color: var(--icon-hover-color);
47
- }
48
- }
49
- }
50
-
51
- .stk-filter-dropdown {
52
- --border-color: #303439;
53
- --btn-hover-color: #2a2f34;
54
- --bg-color: #181c21;
55
- --text-color: rgba(255, 255, 255, 0.85);
56
- --cell-hover-color: #2a2f34;
57
-
58
- &--light {
59
- --border-color: #e8e8e8;
60
- --btn-hover-color: #f5f5f5;
61
- --bg-color: #ffffff;
62
- --text-color: rgba(0, 0, 0, 0.85);
63
- --cell-hover-color: #fafafa;
64
-
65
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
66
- }
67
-
68
- position: absolute;
69
- width: 120px;
70
- max-height: 200px;
71
- background-color: var(--bg-color);
72
- border: 1px solid var(--border-color);
73
- border-radius: 4px;
74
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
75
- z-index: 1000;
76
- display: flex;
77
- flex-direction: column;
78
- color: var(--text-color);
79
-
80
- > .stk-table {
81
- --cell-padding-x: 4px;
82
- padding: 8px 0;
83
- flex: 1;
84
- min-height: 0;
85
-
86
- tr {
87
- cursor: pointer;
88
- }
89
- }
90
-
91
- .stk-filter-dropdown-checkbox {
92
- text-align: center;
93
- > [type='checkbox'] {
94
- vertical-align: middle;
95
- }
96
- }
97
-
98
- footer {
99
- display: flex;
100
- border-top: 1px solid var(--border-color);
101
-
102
- button {
103
- flex: 1;
104
- cursor: pointer;
105
- background: transparent;
106
- border: none;
107
- color: var(--text-color);
108
-
109
- &:first-child {
110
- border-right: 1px solid var(--border-color);
111
- }
112
-
113
- &:hover {
114
- background-color: var(--btn-hover-color);
115
- }
116
- }
117
- }
118
- }
1
+ .stk-table.header-text-overflow {
2
+ .stk-filter >span {
3
+ text-overflow: ellipsis;
4
+ white-space: nowrap;
5
+ }
6
+ }
7
+
8
+ .stk-filter {
9
+ display: inline-flex;
10
+ align-items: center;
11
+ gap: 4px;
12
+ cursor: pointer;
13
+ flex: 1;
14
+ min-width: 0;
15
+ &--light {
16
+ --icon-active-color: #1b63d9;
17
+ --icon-hover-color: #1890ff;
18
+ }
19
+
20
+ &--dark {
21
+ --icon-active-color: #1b63d9;
22
+ --icon-hover-color: #4f8df4;
23
+ }
24
+
25
+ &.stk-filter--active {
26
+ .stk-filter-icon {
27
+ color: var(--icon-active-color);
28
+ }
29
+ }
30
+ >span {
31
+ flex: 1;
32
+ min-width: 0;
33
+ overflow: hidden;
34
+ }
35
+
36
+ .stk-filter-icon {
37
+ display: inline-flex;
38
+ width: 16px;
39
+ height: 16px;
40
+ cursor: pointer;
41
+ opacity: 0.6;
42
+ transition: opacity 0.2s;
43
+ flex-shrink: 0;
44
+ &:hover {
45
+ opacity: 1;
46
+ color: var(--icon-hover-color);
47
+ }
48
+ }
49
+ }
50
+
51
+ .stk-filter-dropdown {
52
+ --border-color: #303439;
53
+ --btn-hover-color: #2a2f34;
54
+ --bg-color: #181c21;
55
+ --text-color: rgba(255, 255, 255, 0.85);
56
+ --cell-hover-color: #2a2f34;
57
+
58
+ &--light {
59
+ --border-color: #e8e8e8;
60
+ --btn-hover-color: #f5f5f5;
61
+ --bg-color: #ffffff;
62
+ --text-color: rgba(0, 0, 0, 0.85);
63
+ --cell-hover-color: #fafafa;
64
+
65
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
66
+ }
67
+
68
+ position: absolute;
69
+ width: 120px;
70
+ max-height: 200px;
71
+ background-color: var(--bg-color);
72
+ border: 1px solid var(--border-color);
73
+ border-radius: 4px;
74
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
75
+ z-index: 1000;
76
+ display: flex;
77
+ flex-direction: column;
78
+ color: var(--text-color);
79
+
80
+ > .stk-table {
81
+ --cell-padding-x: 4px;
82
+ padding: 8px 0;
83
+ flex: 1;
84
+ min-height: 0;
85
+
86
+ tr {
87
+ cursor: pointer;
88
+ }
89
+ }
90
+
91
+ .stk-filter-dropdown-checkbox {
92
+ text-align: center;
93
+ > [type='checkbox'] {
94
+ vertical-align: middle;
95
+ }
96
+ }
97
+
98
+ footer {
99
+ display: flex;
100
+ border-top: 1px solid var(--border-color);
101
+
102
+ button {
103
+ flex: 1;
104
+ cursor: pointer;
105
+ background: transparent;
106
+ border: none;
107
+ color: var(--text-color);
108
+
109
+ &:first-child {
110
+ border-right: 1px solid var(--border-color);
111
+ }
112
+
113
+ &:hover {
114
+ background-color: var(--btn-hover-color);
115
+ }
116
+ }
117
+ }
118
+ }