niuma-ui 1.0.2 → 1.1.0
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.
- package/CHANGELOG.md +28 -1
- package/package.json +1 -1
- package/src/__tests__/RsDatePicker.spec.ts +21 -0
- package/src/__tests__/RsDialog.spec.ts +61 -0
- package/src/__tests__/RsForm.spec.ts +5 -5
- package/src/__tests__/RsFormItem.spec.ts +478 -0
- package/src/__tests__/RsFormList.spec.ts +109 -0
- package/src/__tests__/RsInput.spec.ts +93 -0
- package/src/__tests__/RsInputNumber.spec.ts +33 -0
- package/src/__tests__/RsSelect.spec.ts +423 -1
- package/src/__tests__/RsSwitch.spec.ts +30 -0
- package/src/__tests__/RsTimePicker.spec.ts +9 -0
- package/src/__tests__/RsTooltip.spec.ts +43 -0
- package/src/__tests__/css-token.spec.ts +51 -0
- package/src/__tests__/date-picker-utils.spec.ts +49 -0
- package/src/__tests__/dialog-utils.spec.ts +43 -0
- package/src/__tests__/form-path.spec.ts +46 -0
- package/src/__tests__/form-rules.spec.ts +63 -0
- package/src/__tests__/theme.spec.ts +2 -0
- package/src/components/RsAlert.vue +1 -1
- package/src/components/RsAvatar.vue +1 -1
- package/src/components/RsBadge.vue +1 -1
- package/src/components/RsBreadcrumb.vue +1 -1
- package/src/components/RsButton.vue +4 -4
- package/src/components/RsCalendarGrid.vue +3 -3
- package/src/components/RsCard.vue +4 -4
- package/src/components/RsCodeBlock.vue +4 -4
- package/src/components/RsCodeEditor.vue +8 -8
- package/src/components/RsConfirmDialog.vue +2 -2
- package/src/components/RsContextMenu.vue +6 -4
- package/src/components/RsDatePicker.vue +75 -31
- package/src/components/RsDateTimePicker.vue +9 -1
- package/src/components/RsDescriptions.vue +2 -2
- package/src/components/RsDialog.vue +26 -16
- package/src/components/RsDrawer.vue +1 -1
- package/src/components/RsDropdown.vue +1 -1
- package/src/components/RsDynamicTags.vue +18 -4
- package/src/components/RsEmpty.vue +1 -1
- package/src/components/RsForm.vue +68 -1
- package/src/components/RsFormItem.vue +423 -0
- package/src/components/RsFormItemControl.vue +21 -0
- package/src/components/RsFormList.vue +117 -0
- package/src/components/RsInput.vue +411 -18
- package/src/components/RsInputNumber.vue +13 -4
- package/src/components/RsLink.vue +1 -1
- package/src/components/RsMarkdown.vue +5 -5
- package/src/components/RsMenu.vue +2 -2
- package/src/components/RsMonacoEditor.vue +9 -3
- package/src/components/RsPagination.vue +1 -1
- package/src/components/RsProseEditor.vue +3 -3
- package/src/components/RsSelect.vue +332 -611
- package/src/components/RsSidebarGroup.vue +1 -1
- package/src/components/RsSplitPane.vue +22 -1
- package/src/components/RsStatCard.vue +2 -2
- package/src/components/RsSteps.vue +2 -2
- package/src/components/RsSwitch.vue +20 -7
- package/src/components/RsTabs.vue +9 -9
- package/src/components/RsTag.vue +1 -1
- package/src/components/RsTerminal.vue +58 -19
- package/src/components/RsTimePicker.vue +28 -4
- package/src/components/RsTimePickerColumns.vue +4 -4
- package/src/components/RsToaster.vue +7 -7
- package/src/components/RsTooltip.vue +10 -1
- package/src/components/RsTooltipProvider.vue +11 -1
- package/src/components/RsTree.vue +6 -6
- package/src/components/RsUpload.vue +2 -2
- package/src/components/date-picker-utils.ts +113 -2
- package/src/components/dialog-utils.ts +37 -2
- package/src/components/form-item-control.ts +55 -0
- package/src/components/form-path.ts +92 -0
- package/src/components/form-rules.ts +64 -10
- package/src/components/form-utils.ts +94 -2
- package/src/components/select-utils.ts +272 -12
- package/src/components/table/RsTableHeaderFilter.vue +1 -1
- package/src/components/table/rs-table.css +1 -1
- package/src/components/use-rs-select.ts +436 -0
- package/src/composables/useRsConfig.ts +10 -3
- package/src/composables/useRsI18n.ts +16 -5
- package/src/index.ts +69 -1
- package/src/locale/interpolate.ts +32 -0
- package/src/locale/messages.ts +10 -0
- package/src/styles.css +68 -12
- package/src/theme/brand.example.css +4 -1
- package/src/theme/css-token.ts +107 -0
- package/src/theme/types.ts +1 -0
|
@@ -1,7 +1,24 @@
|
|
|
1
|
+
export type RsSelectValue = string | number
|
|
2
|
+
|
|
3
|
+
/** 过滤 / 回显比对字段名,默认 label;可传 value 或 fieldNames 映射后的键 */
|
|
4
|
+
export type RsSelectOptionFilterProp = string
|
|
5
|
+
|
|
6
|
+
export type RsSelectPlacement = 'top' | 'bottom' | 'left' | 'right'
|
|
7
|
+
|
|
8
|
+
export type RsSelectStatus = 'error' | 'warning' | ''
|
|
9
|
+
|
|
10
|
+
/** 自定义过滤(对齐 Ant Design filterOption)。返回 false 则隐藏该项。 */
|
|
11
|
+
export type RsSelectFilterOption = (query: string, option: RsSelectOption) => boolean
|
|
12
|
+
|
|
13
|
+
/** 过滤后排序(对齐 Ant Design filterSort) */
|
|
14
|
+
export type RsSelectFilterSort = (a: RsSelectOption, b: RsSelectOption) => number
|
|
15
|
+
|
|
1
16
|
export interface RsSelectOption {
|
|
2
17
|
label: string
|
|
3
|
-
value:
|
|
18
|
+
value: RsSelectValue
|
|
4
19
|
disabled?: boolean
|
|
20
|
+
/** 原生 title;悬停展示补充说明 */
|
|
21
|
+
title?: string
|
|
5
22
|
}
|
|
6
23
|
|
|
7
24
|
export interface RsSelectOptionGroup {
|
|
@@ -11,18 +28,47 @@ export interface RsSelectOptionGroup {
|
|
|
11
28
|
|
|
12
29
|
export type RsSelectOptions = ReadonlyArray<RsSelectOption | RsSelectOptionGroup>
|
|
13
30
|
|
|
31
|
+
/** 未正规化的选项(配合 fieldNames 可用 name/id/children 等业务字段) */
|
|
32
|
+
export type RsSelectOptionInput = RsSelectOption | RsSelectOptionGroup | Record<string, unknown>
|
|
33
|
+
|
|
34
|
+
export type RsSelectOptionsInput = ReadonlyArray<RsSelectOptionInput>
|
|
35
|
+
|
|
36
|
+
/** 对齐 Ant Design fieldNames */
|
|
37
|
+
export interface RsSelectFieldNames {
|
|
38
|
+
label?: string
|
|
39
|
+
value?: string
|
|
40
|
+
options?: string
|
|
41
|
+
disabled?: string
|
|
42
|
+
groupLabel?: string
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export type RsSelectGetPopupContainer = (triggerNode?: HTMLElement) => string | HTMLElement | undefined
|
|
46
|
+
|
|
47
|
+
/** labelInValue 时的 v-model 项(对齐 Ant Design) */
|
|
48
|
+
export interface RsSelectLabeledValue {
|
|
49
|
+
label: string
|
|
50
|
+
value: RsSelectValue
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export type RsSelectModelValue =
|
|
54
|
+
| RsSelectValue
|
|
55
|
+
| RsSelectValue[]
|
|
56
|
+
| RsSelectLabeledValue
|
|
57
|
+
| RsSelectLabeledValue[]
|
|
58
|
+
| ''
|
|
59
|
+
|
|
14
60
|
/**
|
|
15
61
|
* Reka ComboboxItem 禁止 value 为空串(空串表示未选中 / placeholder)。
|
|
16
62
|
* 选项若传入 value: '',对内映射为此哨兵,避免崩溃;对外读写仍为 ''。
|
|
17
63
|
*/
|
|
18
64
|
export const RS_SELECT_EMPTY_VALUE = '__rs_select_empty__'
|
|
19
65
|
|
|
20
|
-
/** 业务 value → ComboboxItem
|
|
21
|
-
export function toComboboxValue(value:
|
|
22
|
-
return value === '' ? RS_SELECT_EMPTY_VALUE : value
|
|
66
|
+
/** 业务 value → ComboboxItem token(空串走哨兵;数字转为十进制字符串) */
|
|
67
|
+
export function toComboboxValue(value: RsSelectValue): string {
|
|
68
|
+
return value === '' ? RS_SELECT_EMPTY_VALUE : String(value)
|
|
23
69
|
}
|
|
24
70
|
|
|
25
|
-
/** ComboboxItem
|
|
71
|
+
/** ComboboxItem token → 业务字符串(仅还原空串哨兵,不恢复 number) */
|
|
26
72
|
export function fromComboboxValue(value: string): string {
|
|
27
73
|
return value === RS_SELECT_EMPTY_VALUE ? '' : value
|
|
28
74
|
}
|
|
@@ -45,11 +91,40 @@ export function flattenSelectOptions(options: RsSelectOptions): RsSelectOption[]
|
|
|
45
91
|
return result
|
|
46
92
|
}
|
|
47
93
|
|
|
94
|
+
export function findSelectOption(
|
|
95
|
+
options: RsSelectOptions,
|
|
96
|
+
token: string,
|
|
97
|
+
): RsSelectOption | undefined {
|
|
98
|
+
const raw = fromComboboxValue(token)
|
|
99
|
+
return flattenSelectOptions(options).find((opt) => String(opt.value) === String(raw))
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Combobox token → 业务 value。
|
|
104
|
+
* 优先返回 options 里的原始类型(number 0 保持为 0);手输/未知项保持字符串。
|
|
105
|
+
*/
|
|
106
|
+
export function restoreSelectValue(
|
|
107
|
+
token: string,
|
|
108
|
+
options: RsSelectOptions,
|
|
109
|
+
): RsSelectValue {
|
|
110
|
+
const matched = findSelectOption(options, token)
|
|
111
|
+
if (matched) return matched.value
|
|
112
|
+
return fromComboboxValue(token)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export function restoreSelectValues(
|
|
116
|
+
tokens: string[],
|
|
117
|
+
options: RsSelectOptions,
|
|
118
|
+
): RsSelectValue[] {
|
|
119
|
+
return tokens.map((token) => restoreSelectValue(token, options))
|
|
120
|
+
}
|
|
121
|
+
|
|
48
122
|
export function buildOptionLabelMap(options: RsSelectOptions): Map<string, string> {
|
|
49
123
|
const map = new Map<string, string>()
|
|
50
124
|
for (const opt of flattenSelectOptions(options)) {
|
|
51
|
-
|
|
52
|
-
|
|
125
|
+
const key = toComboboxValue(opt.value)
|
|
126
|
+
map.set(key, opt.label)
|
|
127
|
+
if (opt.value === '') map.set('', opt.label)
|
|
53
128
|
}
|
|
54
129
|
return map
|
|
55
130
|
}
|
|
@@ -57,29 +132,130 @@ export function buildOptionLabelMap(options: RsSelectOptions): Map<string, strin
|
|
|
57
132
|
export function buildOptionDisabledMap(options: RsSelectOptions): Map<string, boolean> {
|
|
58
133
|
const map = new Map<string, boolean>()
|
|
59
134
|
for (const opt of flattenSelectOptions(options)) {
|
|
60
|
-
const
|
|
61
|
-
map.set(opt.
|
|
62
|
-
if (opt.value === '') map.set(RS_SELECT_EMPTY_VALUE, disabled)
|
|
135
|
+
const key = toComboboxValue(opt.value)
|
|
136
|
+
map.set(key, Boolean(opt.disabled))
|
|
63
137
|
}
|
|
64
138
|
return map
|
|
65
139
|
}
|
|
66
140
|
|
|
141
|
+
function optionFieldText(option: RsSelectOption, prop: string): string {
|
|
142
|
+
if (prop === 'value') return String(option.value)
|
|
143
|
+
if (prop === 'label' || !prop) return String(option.label)
|
|
144
|
+
const extra = Reflect.get(option, prop)
|
|
145
|
+
return extra == null ? String(option.label) : String(extra)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function defaultMatchOption(
|
|
149
|
+
option: RsSelectOption,
|
|
150
|
+
query: string,
|
|
151
|
+
contains: (text: string, search: string) => boolean,
|
|
152
|
+
optionFilterProp: RsSelectOptionFilterProp,
|
|
153
|
+
): boolean {
|
|
154
|
+
return contains(optionFieldText(option, optionFilterProp), query)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function coerceSelectValue(raw: unknown): RsSelectValue {
|
|
158
|
+
if (typeof raw === 'number' || typeof raw === 'string') return raw
|
|
159
|
+
if (raw == null) return ''
|
|
160
|
+
return String(raw)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function mapSelectOption(
|
|
164
|
+
raw: Record<string, unknown>,
|
|
165
|
+
names: Required<Pick<RsSelectFieldNames, 'label' | 'value' | 'disabled'>>,
|
|
166
|
+
): RsSelectOption {
|
|
167
|
+
const value = coerceSelectValue(raw[names.value])
|
|
168
|
+
const label = raw[names.label]
|
|
169
|
+
return {
|
|
170
|
+
...raw,
|
|
171
|
+
value,
|
|
172
|
+
label: label == null ? String(value) : String(label),
|
|
173
|
+
disabled: Boolean(raw[names.disabled]),
|
|
174
|
+
title: typeof raw.title === 'string' ? raw.title : undefined,
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* 按 fieldNames 把业务选项正规化为 { label, value, disabled }。
|
|
180
|
+
* 默认键即为 label / value / options,既有调用无需改。
|
|
181
|
+
*/
|
|
182
|
+
export function normalizeSelectOptions(
|
|
183
|
+
options: RsSelectOptionsInput,
|
|
184
|
+
fieldNames?: RsSelectFieldNames,
|
|
185
|
+
): RsSelectOptions {
|
|
186
|
+
const labelKey = fieldNames?.label ?? 'label'
|
|
187
|
+
const valueKey = fieldNames?.value ?? 'value'
|
|
188
|
+
const optionsKey = fieldNames?.options ?? 'options'
|
|
189
|
+
const disabledKey = fieldNames?.disabled ?? 'disabled'
|
|
190
|
+
const groupLabelKey = fieldNames?.groupLabel ?? labelKey
|
|
191
|
+
const result: Array<RsSelectOption | RsSelectOptionGroup> = []
|
|
192
|
+
|
|
193
|
+
for (const item of options) {
|
|
194
|
+
if (!item || typeof item !== 'object') continue
|
|
195
|
+
const raw = item as Record<string, unknown>
|
|
196
|
+
const nested = raw[optionsKey]
|
|
197
|
+
if (Array.isArray(nested)) {
|
|
198
|
+
const children: RsSelectOption[] = []
|
|
199
|
+
for (const child of nested) {
|
|
200
|
+
if (!child || typeof child !== 'object') continue
|
|
201
|
+
children.push(mapSelectOption(child as Record<string, unknown>, {
|
|
202
|
+
label: labelKey,
|
|
203
|
+
value: valueKey,
|
|
204
|
+
disabled: disabledKey,
|
|
205
|
+
}))
|
|
206
|
+
}
|
|
207
|
+
result.push({
|
|
208
|
+
label: String(raw[groupLabelKey] ?? ''),
|
|
209
|
+
options: children,
|
|
210
|
+
})
|
|
211
|
+
continue
|
|
212
|
+
}
|
|
213
|
+
result.push(mapSelectOption(raw, { label: labelKey, value: valueKey, disabled: disabledKey }))
|
|
214
|
+
}
|
|
215
|
+
return result
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/** 触发器 / tag 展示文案,对齐 Ant optionLabelProp */
|
|
219
|
+
export function optionDisplayLabel(option: RsSelectOption, prop = 'label'): string {
|
|
220
|
+
return optionFieldText(option, prop)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export function comboboxBindingToTokens(value: unknown, multiple: boolean): string[] {
|
|
224
|
+
if (multiple) return Array.isArray(value) ? value.map(String) : []
|
|
225
|
+
if (value == null || value === '') return []
|
|
226
|
+
return [String(value)]
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export function selectModelEntries(value: unknown): unknown[] {
|
|
230
|
+
if (Array.isArray(value)) return value
|
|
231
|
+
if (value === '' || value == null) return []
|
|
232
|
+
return [value]
|
|
233
|
+
}
|
|
234
|
+
|
|
67
235
|
export function filterSelectOptions(
|
|
68
236
|
options: RsSelectOptions,
|
|
69
237
|
query: string,
|
|
70
238
|
contains: (text: string, search: string) => boolean,
|
|
239
|
+
filterOption?: RsSelectFilterOption | boolean,
|
|
240
|
+
optionFilterProp: RsSelectOptionFilterProp = 'label',
|
|
71
241
|
): RsSelectOptions {
|
|
242
|
+
if (filterOption === false) return options
|
|
72
243
|
const trimmed = query.trim()
|
|
73
244
|
if (!trimmed) return options
|
|
74
245
|
|
|
246
|
+
const match =
|
|
247
|
+
typeof filterOption === 'function'
|
|
248
|
+
? (opt: RsSelectOption) => filterOption(trimmed, opt)
|
|
249
|
+
: (opt: RsSelectOption) => defaultMatchOption(opt, trimmed, contains, optionFilterProp)
|
|
250
|
+
|
|
75
251
|
const result: Array<RsSelectOption | RsSelectOptionGroup> = []
|
|
76
252
|
for (const item of options) {
|
|
77
253
|
if (isSelectOptionGroup(item)) {
|
|
78
|
-
const filtered = item.options.filter(
|
|
254
|
+
const filtered = item.options.filter(match)
|
|
79
255
|
if (filtered.length > 0) {
|
|
80
256
|
result.push({ label: item.label, options: filtered })
|
|
81
257
|
}
|
|
82
|
-
} else if (
|
|
258
|
+
} else if (match(item)) {
|
|
83
259
|
result.push(item)
|
|
84
260
|
}
|
|
85
261
|
}
|
|
@@ -89,3 +265,87 @@ export function filterSelectOptions(
|
|
|
89
265
|
export function flattenSelectValues(options: RsSelectOptions): string[] {
|
|
90
266
|
return flattenSelectOptions(options).map((opt) => toComboboxValue(opt.value))
|
|
91
267
|
}
|
|
268
|
+
|
|
269
|
+
export function toSelectedTokens(value: unknown, multiple: boolean): string[] {
|
|
270
|
+
const entries = multiple
|
|
271
|
+
? selectModelEntries(value)
|
|
272
|
+
: Array.isArray(value) || value === '' || value == null
|
|
273
|
+
? []
|
|
274
|
+
: [value]
|
|
275
|
+
const tokens: string[] = []
|
|
276
|
+
for (const entry of entries) {
|
|
277
|
+
const raw = unwrapSelectEntry(entry)
|
|
278
|
+
if (raw === null) continue
|
|
279
|
+
tokens.push(toComboboxValue(raw))
|
|
280
|
+
}
|
|
281
|
+
return tokens
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
export function isSelectLabeledValue(value: unknown): value is RsSelectLabeledValue {
|
|
285
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value) && 'value' in value
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
export function unwrapSelectEntry(item: unknown): RsSelectValue | null {
|
|
289
|
+
if (item == null || item === '') return null
|
|
290
|
+
if (isSelectLabeledValue(item)) return item.value
|
|
291
|
+
if (typeof item === 'string' || typeof item === 'number') return item
|
|
292
|
+
return null
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
export function toLabeledValue(
|
|
296
|
+
value: RsSelectValue,
|
|
297
|
+
options: RsSelectOptions,
|
|
298
|
+
): RsSelectLabeledValue {
|
|
299
|
+
const matched = flattenSelectOptions(options).find(
|
|
300
|
+
(opt) => String(opt.value) === String(value),
|
|
301
|
+
)
|
|
302
|
+
return {
|
|
303
|
+
value: matched ? matched.value : value,
|
|
304
|
+
label: matched?.label ?? String(value),
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
export function packSelectModel(
|
|
309
|
+
values: RsSelectValue[],
|
|
310
|
+
options: RsSelectOptions,
|
|
311
|
+
multiple: boolean,
|
|
312
|
+
labelInValue: boolean,
|
|
313
|
+
): RsSelectModelValue {
|
|
314
|
+
if (multiple) {
|
|
315
|
+
return labelInValue ? values.map((value) => toLabeledValue(value, options)) : values
|
|
316
|
+
}
|
|
317
|
+
const first = values[0]
|
|
318
|
+
if (first === undefined) return ''
|
|
319
|
+
return labelInValue ? toLabeledValue(first, options) : first
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
export function sortSelectOptions(
|
|
323
|
+
options: RsSelectOptions,
|
|
324
|
+
sort?: RsSelectFilterSort,
|
|
325
|
+
): RsSelectOptions {
|
|
326
|
+
if (!sort) return options
|
|
327
|
+
const next: Array<RsSelectOption | RsSelectOptionGroup> = []
|
|
328
|
+
const flats: RsSelectOption[] = []
|
|
329
|
+
const flushFlats = () => {
|
|
330
|
+
if (!flats.length) return
|
|
331
|
+
next.push(...[...flats].sort(sort))
|
|
332
|
+
flats.length = 0
|
|
333
|
+
}
|
|
334
|
+
for (const item of options) {
|
|
335
|
+
if (isSelectOptionGroup(item)) {
|
|
336
|
+
flushFlats()
|
|
337
|
+
next.push({ label: item.label, options: [...item.options].sort(sort) })
|
|
338
|
+
} else {
|
|
339
|
+
flats.push(item)
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
flushFlats()
|
|
343
|
+
return next as RsSelectOptions
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
export function splitByTokenSeparators(raw: string, separators: string[]): string[] | null {
|
|
347
|
+
if (!separators.length) return null
|
|
348
|
+
const found = separators.find((sep) => sep && raw.includes(sep))
|
|
349
|
+
if (!found) return null
|
|
350
|
+
return raw.split(found)
|
|
351
|
+
}
|
|
@@ -87,7 +87,7 @@ function onEditorEnter(): void {
|
|
|
87
87
|
.rs-table-header-filter__title {
|
|
88
88
|
margin: 0 0 0.5rem;
|
|
89
89
|
font-size: var(--rs-font-size-sm);
|
|
90
|
-
font-weight:
|
|
90
|
+
font-weight: var(--rs-font-weight-semibold);
|
|
91
91
|
color: var(--rs-fg);
|
|
92
92
|
}
|
|
93
93
|
.rs-table-header-filter__field {
|
|
@@ -778,7 +778,7 @@
|
|
|
778
778
|
padding: var(--rs-space-xs) var(--rs-space-md);
|
|
779
779
|
color: var(--rs-table-muted-fg);
|
|
780
780
|
font-size: var(--rs-font-size-xs);
|
|
781
|
-
font-weight:
|
|
781
|
+
font-weight: var(--rs-font-weight-semibold);
|
|
782
782
|
}
|
|
783
783
|
.rs-table__virtual-pad td {
|
|
784
784
|
padding: 0;
|