stk-table-vue 1.2.4 → 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 (68) hide show
  1. package/README.md +194 -194
  2. package/lib/{Dropdown-D_9cB0rD.js → Dropdown-BAANgg_5.js} +2 -2
  3. package/lib/{StkTable-CVcmlZi9.js → StkTable-CGcxwpdb.js} +22 -6
  4. package/lib/src/StkTable/StkTable.vue.d.ts +18 -4
  5. package/lib/src/StkTable/types/index.d.ts +4 -1
  6. package/lib/src/StkTable/useVirtualScroll.d.ts +6 -1
  7. package/lib/stk-table-vue.js +3 -3
  8. package/lib/style.css +1 -1
  9. package/package.json +93 -93
  10. package/src/StkTable/StkTable.vue +2362 -2338
  11. package/src/StkTable/components/DragHandle.vue +9 -9
  12. package/src/StkTable/components/SortIcon.vue +6 -6
  13. package/src/StkTable/components/TreeNodeCell.vue +19 -19
  14. package/src/StkTable/components/TriangleIcon.vue +3 -3
  15. package/src/StkTable/const.ts +50 -50
  16. package/src/StkTable/custom-cells/ChangeCell/ChangeCell.less +34 -34
  17. package/src/StkTable/custom-cells/ChangeCell/createChangeCell.ts +90 -90
  18. package/src/StkTable/custom-cells/ChangeCell/index.ts +4 -4
  19. package/src/StkTable/custom-cells/CheckboxCell/CheckboxCell.less +14 -14
  20. package/src/StkTable/custom-cells/CheckboxCell/CheckboxCell.vue +56 -56
  21. package/src/StkTable/custom-cells/CheckboxCell/createCheckboxCell.ts +146 -146
  22. package/src/StkTable/custom-cells/CheckboxCell/index.ts +5 -5
  23. package/src/StkTable/custom-cells/FilterCell/Dropdown/index.ts +16 -16
  24. package/src/StkTable/custom-cells/FilterCell/Dropdown/index.vue +186 -186
  25. package/src/StkTable/custom-cells/FilterCell/Filter.less +118 -118
  26. package/src/StkTable/custom-cells/FilterCell/Filter.vue +66 -66
  27. package/src/StkTable/custom-cells/FilterCell/createFilterCell.ts +120 -120
  28. package/src/StkTable/custom-cells/FilterCell/index.ts +6 -6
  29. package/src/StkTable/custom-cells/FilterCell/types.ts +43 -43
  30. package/src/StkTable/custom-cells/NumberCell/createNumberCell.ts +43 -43
  31. package/src/StkTable/custom-cells/NumberCell/index.ts +2 -2
  32. package/src/StkTable/custom-cells/utils/formatNumber.ts +137 -137
  33. package/src/StkTable/features/const.ts +1 -1
  34. package/src/StkTable/features/index.ts +1 -1
  35. package/src/StkTable/features/useAreaSelection.ts +1240 -1239
  36. package/src/StkTable/index.ts +20 -20
  37. package/src/StkTable/mergeCellsCache.ts +69 -69
  38. package/src/StkTable/registerFeature.ts +40 -40
  39. package/src/StkTable/style.less +791 -791
  40. package/src/StkTable/types/highlightDimOptions.ts +28 -28
  41. package/src/StkTable/types/index.ts +503 -500
  42. package/src/StkTable/useAutoResize.ts +87 -87
  43. package/src/StkTable/useColResize.ts +202 -202
  44. package/src/StkTable/useFixedCol.ts +168 -168
  45. package/src/StkTable/useFixedStyle.ts +75 -75
  46. package/src/StkTable/useGetFixedColPosition.ts +63 -63
  47. package/src/StkTable/useHighlight.ts +270 -270
  48. package/src/StkTable/useIndexResolver.ts +29 -29
  49. package/src/StkTable/useKeyboardArrowScroll.ts +114 -114
  50. package/src/StkTable/useMaxRowSpan.ts +60 -60
  51. package/src/StkTable/useMergeCells.ts +541 -541
  52. package/src/StkTable/useRowExpand.ts +81 -81
  53. package/src/StkTable/useScrollRowByRow.ts +96 -96
  54. package/src/StkTable/useScrollbar.ts +177 -177
  55. package/src/StkTable/useSorter.ts +267 -267
  56. package/src/StkTable/useTableColumns.ts +142 -142
  57. package/src/StkTable/useThDrag.ts +94 -94
  58. package/src/StkTable/useTrDrag.ts +100 -100
  59. package/src/StkTable/useTree.ts +253 -253
  60. package/src/StkTable/useVirtualScroll.ts +1032 -1025
  61. package/src/StkTable/useWheeling.ts +23 -23
  62. package/src/StkTable/utils/constRefUtils.ts +29 -29
  63. package/src/StkTable/utils/index.ts +331 -331
  64. package/src/StkTable/utils/rowHeightFenwickTree.ts +74 -74
  65. package/src/StkTable/utils/useTriggerRef.ts +33 -33
  66. package/src/VirtualTree.vue +622 -622
  67. package/src/VirtualTreeSelect.vue +367 -367
  68. 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
+ }