niuma-ui 1.0.2 → 1.1.1
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 +37 -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/RsTableCellEditor.vue +13 -5
- 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/composables/useRsTableCore.ts +3 -1
- package/src/composables/useRsTableHeadless.ts +10 -2
- 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
|
@@ -4,8 +4,10 @@ import {
|
|
|
4
4
|
formatDateTimeDisplay,
|
|
5
5
|
formatDateTimeValue,
|
|
6
6
|
formatDateValue,
|
|
7
|
+
fromInternalPickerValue,
|
|
7
8
|
parseDateTimeValue,
|
|
8
9
|
parseDateValue,
|
|
10
|
+
toInternalPickerValue,
|
|
9
11
|
} from '../components/date-picker-utils'
|
|
10
12
|
import { RS_DATE_FORMAT, RS_DATETIME_FORMAT } from '../lib/rs-dayjs'
|
|
11
13
|
|
|
@@ -68,3 +70,50 @@ describe('date-picker-utils (dayjs)', () => {
|
|
|
68
70
|
expect(formatDateTimeValue('not-a-date')).toBe('not-a-date')
|
|
69
71
|
})
|
|
70
72
|
})
|
|
73
|
+
|
|
74
|
+
describe('date-picker valueFormat conversion', () => {
|
|
75
|
+
const datetimeOpts = { valueFormat: 'iso', withTime: true }
|
|
76
|
+
const dateOpts = { valueFormat: 'iso', withTime: false }
|
|
77
|
+
|
|
78
|
+
it('converts internal datetime to local-offset RFC3339', () => {
|
|
79
|
+
const iso = fromInternalPickerValue('2025-06-16 14:30:00', datetimeOpts)
|
|
80
|
+
expect(iso).toMatch(/^2025-06-16T14:30:00[+-]\d{2}:\d{2}$/)
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
it('converts internal date to RFC3339 at midnight local offset', () => {
|
|
84
|
+
const iso = fromInternalPickerValue('2025-06-16', dateOpts)
|
|
85
|
+
expect(iso).toMatch(/^2025-06-16T00:00:00[+-]\d{2}:\d{2}$/)
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
it('round-trips iso datetime as wall clock', () => {
|
|
89
|
+
const iso = fromInternalPickerValue('2025-06-16 14:30:00', datetimeOpts)
|
|
90
|
+
expect(toInternalPickerValue(iso, datetimeOpts)).toBe('2025-06-16 14:30:00')
|
|
91
|
+
expect(toInternalPickerValue('2026-07-01T14:49:43Z', datetimeOpts)).toBe('2026-07-01 14:49:43')
|
|
92
|
+
expect(toInternalPickerValue('2026-08-14T14:38:42+08:00', datetimeOpts)).toBe('2026-08-14 14:38:42')
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
it('keeps string format as internal wall clock', () => {
|
|
96
|
+
expect(fromInternalPickerValue('2025-06-16 14:30:00', { valueFormat: 'string', withTime: true }))
|
|
97
|
+
.toBe('2025-06-16 14:30:00')
|
|
98
|
+
expect(toInternalPickerValue('2025-06-16 14:30:00', { valueFormat: 'string', withTime: true }))
|
|
99
|
+
.toBe('2025-06-16 14:30:00')
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
it('converts timestamp format', () => {
|
|
103
|
+
const ms = fromInternalPickerValue('2025-06-16 14:30:00', { valueFormat: 'timestamp', withTime: true })
|
|
104
|
+
expect(typeof ms).toBe('number')
|
|
105
|
+
expect(toInternalPickerValue(ms, { valueFormat: 'timestamp', withTime: true })).toBe('2025-06-16 14:30:00')
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
it('supports custom dayjs value-format templates', () => {
|
|
109
|
+
const custom = { valueFormat: 'YYYY-MM-DDTHH:mm:ss', withTime: true }
|
|
110
|
+
expect(fromInternalPickerValue('2025-06-16 14:30:00', custom)).toBe('2025-06-16T14:30:00')
|
|
111
|
+
expect(toInternalPickerValue('2025-06-16T14:30:00', custom)).toBe('2025-06-16 14:30:00')
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
it('emits null for empty iso and timestamp', () => {
|
|
115
|
+
expect(fromInternalPickerValue('', datetimeOpts)).toBeNull()
|
|
116
|
+
expect(fromInternalPickerValue('', { valueFormat: 'timestamp', withTime: true })).toBeNull()
|
|
117
|
+
expect(fromInternalPickerValue('', { valueFormat: 'string', withTime: true })).toBe('')
|
|
118
|
+
})
|
|
119
|
+
})
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it } from 'vitest'
|
|
2
|
+
import { resolveRsDialogCssWidth, resolveRsDialogWidthPx } from '../components/dialog-utils'
|
|
3
|
+
|
|
4
|
+
describe('resolveRsDialogWidthPx', () => {
|
|
5
|
+
afterEach(() => {
|
|
6
|
+
document.documentElement.style.removeProperty('font-size')
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
it('returns undefined for presets', () => {
|
|
10
|
+
expect(resolveRsDialogWidthPx('sm')).toBeUndefined()
|
|
11
|
+
expect(resolveRsDialogWidthPx('md')).toBeUndefined()
|
|
12
|
+
expect(resolveRsDialogWidthPx('lg')).toBeUndefined()
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
it('keeps numeric and px widths', () => {
|
|
16
|
+
expect(resolveRsDialogWidthPx(1200)).toBe(1200)
|
|
17
|
+
expect(resolveRsDialogWidthPx('960px')).toBe(960)
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('converts rem using root font size', () => {
|
|
21
|
+
document.documentElement.style.fontSize = '16px'
|
|
22
|
+
expect(resolveRsDialogWidthPx('40rem')).toBe(640)
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
it('converts percent against the given viewport width', () => {
|
|
26
|
+
expect(resolveRsDialogWidthPx('90%', 1000)).toBe(900)
|
|
27
|
+
expect(resolveRsDialogWidthPx('80%', 800)).toBe(640)
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it('returns undefined for empty or unknown units', () => {
|
|
31
|
+
expect(resolveRsDialogWidthPx('')).toBeUndefined()
|
|
32
|
+
expect(resolveRsDialogWidthPx('min(90vw, 1200px)')).toBeUndefined()
|
|
33
|
+
expect(resolveRsDialogWidthPx(0)).toBeUndefined()
|
|
34
|
+
})
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
describe('resolveRsDialogCssWidth', () => {
|
|
38
|
+
it('maps number to px and keeps custom CSS strings', () => {
|
|
39
|
+
expect(resolveRsDialogCssWidth('md')).toBeUndefined()
|
|
40
|
+
expect(resolveRsDialogCssWidth(520)).toBe('520px')
|
|
41
|
+
expect(resolveRsDialogCssWidth('90%')).toBe('90%')
|
|
42
|
+
})
|
|
43
|
+
})
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import {
|
|
3
|
+
concatNamePath,
|
|
4
|
+
getByNamePath,
|
|
5
|
+
hasByNamePath,
|
|
6
|
+
namePathKey,
|
|
7
|
+
normalizeNamePath,
|
|
8
|
+
setByNamePath,
|
|
9
|
+
} from '../components/form-path'
|
|
10
|
+
|
|
11
|
+
describe('form-path', () => {
|
|
12
|
+
it('normalizes string and array name paths', () => {
|
|
13
|
+
expect(normalizeNamePath('user.email')).toEqual(['user', 'email'])
|
|
14
|
+
expect(normalizeNamePath(['user', 'email'])).toEqual(['user', 'email'])
|
|
15
|
+
expect(namePathKey(['a', 0, 'b'])).toBe('a.0.b')
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
it('gets and sets nested values', () => {
|
|
19
|
+
const model: Record<string, unknown> = {}
|
|
20
|
+
setByNamePath(model, 'user.email', 'a@b.com')
|
|
21
|
+
expect(model).toEqual({ user: { email: 'a@b.com' } })
|
|
22
|
+
expect(getByNamePath(model, ['user', 'email'])).toBe('a@b.com')
|
|
23
|
+
expect(hasByNamePath(model, 'user.email')).toBe(true)
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
it('walks multi-level JSON paths', () => {
|
|
27
|
+
const model: Record<string, unknown> = {}
|
|
28
|
+
setByNamePath(model, 'config.headerConfig.isRequestHeader', true)
|
|
29
|
+
expect(model).toEqual({
|
|
30
|
+
config: { headerConfig: { isRequestHeader: true } },
|
|
31
|
+
})
|
|
32
|
+
expect(getByNamePath(model, 'config.headerConfig.isRequestHeader')).toBe(true)
|
|
33
|
+
expect(hasByNamePath(model, 'config.headerConfig.headerName')).toBe(false)
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
it('preserves arrays when setting nested list fields', () => {
|
|
37
|
+
const model: Record<string, unknown> = { users: [{ name: 'A' }] }
|
|
38
|
+
setByNamePath(model, ['users', 0, 'name'], 'B')
|
|
39
|
+
expect(model.users).toEqual([{ name: 'B' }])
|
|
40
|
+
expect(Array.isArray(model.users)).toBe(true)
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
it('concatenates list prefix and item name', () => {
|
|
44
|
+
expect(concatNamePath('users', [0, 'name'])).toEqual(['users', 0, 'name'])
|
|
45
|
+
})
|
|
46
|
+
})
|
|
@@ -63,6 +63,11 @@ describe('form-rules', () => {
|
|
|
63
63
|
expect(rules[1]?.type).toBe('email')
|
|
64
64
|
})
|
|
65
65
|
|
|
66
|
+
it('interpolates required message with label', async () => {
|
|
67
|
+
const labeled = await runFormFieldRules('', [{ required: true }], { label: '邮箱' })
|
|
68
|
+
expect(labeled.message).toBe('请填写邮箱')
|
|
69
|
+
})
|
|
70
|
+
|
|
66
71
|
it('supports message as function', async () => {
|
|
67
72
|
const result = await runFormFieldRules('x', [
|
|
68
73
|
{
|
|
@@ -73,4 +78,62 @@ describe('form-rules', () => {
|
|
|
73
78
|
expect(result.valid).toBe(false)
|
|
74
79
|
expect(result.message).toBe('当前「x」太短')
|
|
75
80
|
})
|
|
81
|
+
|
|
82
|
+
it('validator can read other fields via context', async () => {
|
|
83
|
+
const result = await runFormFieldRules('two', [
|
|
84
|
+
{
|
|
85
|
+
validator(value, ctx) {
|
|
86
|
+
if (String(value) !== String(ctx.getFieldValue('a'))) return '不一致'
|
|
87
|
+
return true
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
], {
|
|
91
|
+
getFieldValue: (name) => (String(name) === 'a' ? 'one' : undefined),
|
|
92
|
+
})
|
|
93
|
+
expect(result).toEqual({ valid: false, message: '不一致' })
|
|
94
|
+
|
|
95
|
+
const ok = await runFormFieldRules('one', [
|
|
96
|
+
{
|
|
97
|
+
validator(value, ctx) {
|
|
98
|
+
if (String(value) !== String(ctx.getFieldValue('a'))) return '不一致'
|
|
99
|
+
return true
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
], {
|
|
103
|
+
getFieldValue: (name) => (String(name) === 'a' ? 'one' : undefined),
|
|
104
|
+
})
|
|
105
|
+
expect(ok.valid).toBe(true)
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
it('runs custom validator on empty value for cross-field required', async () => {
|
|
109
|
+
const result = await runFormFieldRules(
|
|
110
|
+
'',
|
|
111
|
+
[
|
|
112
|
+
{
|
|
113
|
+
validator(_value, ctx) {
|
|
114
|
+
if (ctx.getFieldValue('kind') === 'email') return '邮箱必填'
|
|
115
|
+
return true
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
],
|
|
119
|
+
{ getFieldValue: (name) => (String(name) === 'kind' ? 'email' : undefined) },
|
|
120
|
+
)
|
|
121
|
+
expect(result).toEqual({ valid: false, message: '邮箱必填' })
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
it('treats Error return and thrown errors as failure', async () => {
|
|
125
|
+
const returned = await runFormFieldRules('x', [
|
|
126
|
+
{ validator: () => new Error('返回错误') as unknown as string },
|
|
127
|
+
])
|
|
128
|
+
expect(returned).toEqual({ valid: false, message: '返回错误' })
|
|
129
|
+
|
|
130
|
+
const thrown = await runFormFieldRules('x', [
|
|
131
|
+
{
|
|
132
|
+
validator() {
|
|
133
|
+
throw new Error('抛出错误')
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
])
|
|
137
|
+
expect(thrown).toEqual({ valid: false, message: '抛出错误' })
|
|
138
|
+
})
|
|
76
139
|
})
|
|
@@ -17,6 +17,8 @@ describe('useRsConfig / theme', () => {
|
|
|
17
17
|
expect(en.t('select.placeholder')).toBe('Select')
|
|
18
18
|
expect(zh.t('input.required')).toBe('此项为必填')
|
|
19
19
|
expect(en.t('input.required')).toBe('This field is required')
|
|
20
|
+
expect(zh.t('form.validate.required', { label: '邮箱' })).toBe('请填写邮箱')
|
|
21
|
+
expect(en.t('form.validate.required', { label: 'Email' })).toBe('Please enter Email')
|
|
20
22
|
expect(en.t('breadcrumb.label')).toBe('Breadcrumb')
|
|
21
23
|
})
|
|
22
24
|
|
|
@@ -108,7 +108,7 @@ function onClose(event: MouseEvent): void {
|
|
|
108
108
|
|
|
109
109
|
.rs-alert__title {
|
|
110
110
|
font-size: var(--rs-font-size-sm);
|
|
111
|
-
font-weight:
|
|
111
|
+
font-weight: var(--rs-font-weight-semibold);
|
|
112
112
|
line-height: var(--rs-line-height-tight);
|
|
113
113
|
color: inherit;
|
|
114
114
|
}
|
|
@@ -90,7 +90,7 @@ const ariaLabel = computed(() => props.label ?? props.alt ?? props.name ?? undef
|
|
|
90
90
|
width: 100%;
|
|
91
91
|
height: 100%;
|
|
92
92
|
font-size: var(--rs-font-size-xs);
|
|
93
|
-
font-weight:
|
|
93
|
+
font-weight: var(--rs-font-weight-semibold);
|
|
94
94
|
}
|
|
95
95
|
.rs-avatar__fallback--default {
|
|
96
96
|
background: var(--rs-surface-hover);
|
|
@@ -22,7 +22,7 @@ withDefaults(
|
|
|
22
22
|
padding: 0.125rem 0.625rem;
|
|
23
23
|
border-radius: var(--rs-radius-full);
|
|
24
24
|
font-size: var(--rs-font-size-xs);
|
|
25
|
-
font-weight:
|
|
25
|
+
font-weight: var(--rs-font-weight-medium);
|
|
26
26
|
line-height: var(--rs-line-height-tight);
|
|
27
27
|
letter-spacing: 0.02em;
|
|
28
28
|
}
|
|
@@ -56,7 +56,7 @@ const renderItems = computed(() => buildBreadcrumbRenderItems(props.items))
|
|
|
56
56
|
}
|
|
57
57
|
.rs-breadcrumb__link--current {
|
|
58
58
|
color: var(--rs-text);
|
|
59
|
-
font-weight:
|
|
59
|
+
font-weight: var(--rs-font-weight-medium);
|
|
60
60
|
pointer-events: none;
|
|
61
61
|
}
|
|
62
62
|
.rs-breadcrumb__sep {
|
|
@@ -196,7 +196,7 @@ watch(
|
|
|
196
196
|
border-radius: var(--rs-btn-radius, var(--rs-radius-full));
|
|
197
197
|
border: 1px solid transparent;
|
|
198
198
|
font-size: var(--rs-font-size-sm);
|
|
199
|
-
font-weight:
|
|
199
|
+
font-weight: var(--rs-font-weight-medium);
|
|
200
200
|
letter-spacing: 0.01em;
|
|
201
201
|
line-height: 1;
|
|
202
202
|
white-space: nowrap;
|
|
@@ -329,7 +329,7 @@ watch(
|
|
|
329
329
|
background: transparent;
|
|
330
330
|
color: var(--rs-btn-tone, var(--rs-primary));
|
|
331
331
|
box-shadow: none;
|
|
332
|
-
font-weight:
|
|
332
|
+
font-weight: var(--rs-font-weight-medium);
|
|
333
333
|
}
|
|
334
334
|
.rs-btn--link:hover:not(:disabled) {
|
|
335
335
|
color: var(--rs-btn-tone-hover, var(--rs-primary-hover));
|
|
@@ -346,7 +346,7 @@ watch(
|
|
|
346
346
|
border-color: transparent;
|
|
347
347
|
background: transparent;
|
|
348
348
|
box-shadow: none;
|
|
349
|
-
font-weight:
|
|
349
|
+
font-weight: var(--rs-font-weight-regular);
|
|
350
350
|
color: var(--rs-btn-tone, var(--rs-text));
|
|
351
351
|
}
|
|
352
352
|
.rs-btn--text.rs-btn--ssm {
|
|
@@ -474,7 +474,7 @@ watch(
|
|
|
474
474
|
background: var(--rs-surface-elevated);
|
|
475
475
|
color: var(--rs-text);
|
|
476
476
|
font-size: var(--rs-font-size-xs);
|
|
477
|
-
font-weight:
|
|
477
|
+
font-weight: var(--rs-font-weight-medium);
|
|
478
478
|
line-height: 1.25rem;
|
|
479
479
|
white-space: nowrap;
|
|
480
480
|
box-shadow: var(--rs-shadow-sm);
|
|
@@ -204,7 +204,7 @@ function selectDate(cell: RsCalendarCell): void {
|
|
|
204
204
|
flex: 1;
|
|
205
205
|
text-align: center;
|
|
206
206
|
font-size: var(--rs-font-size-sm);
|
|
207
|
-
font-weight:
|
|
207
|
+
font-weight: var(--rs-font-weight-semibold);
|
|
208
208
|
color: var(--rs-text);
|
|
209
209
|
}
|
|
210
210
|
.rs-calendar-grid__nav {
|
|
@@ -233,8 +233,8 @@ function selectDate(cell: RsCalendarCell): void {
|
|
|
233
233
|
.rs-calendar-grid__weekday {
|
|
234
234
|
padding: 0.125rem 0;
|
|
235
235
|
text-align: center;
|
|
236
|
-
font-size:
|
|
237
|
-
font-weight:
|
|
236
|
+
font-size: var(--rs-font-size-xs);
|
|
237
|
+
font-weight: var(--rs-font-weight-medium);
|
|
238
238
|
color: var(--rs-muted);
|
|
239
239
|
}
|
|
240
240
|
.rs-calendar-grid__day {
|
|
@@ -232,7 +232,7 @@ const rootStyle = computed(() => ({
|
|
|
232
232
|
}
|
|
233
233
|
.rs-card--plain .rs-card__title {
|
|
234
234
|
font-size: var(--rs-font-size-xs);
|
|
235
|
-
font-weight:
|
|
235
|
+
font-weight: var(--rs-font-weight-medium);
|
|
236
236
|
color: var(--rs-card-description-fg);
|
|
237
237
|
letter-spacing: 0;
|
|
238
238
|
}
|
|
@@ -255,7 +255,7 @@ const rootStyle = computed(() => ({
|
|
|
255
255
|
box-shadow: none;
|
|
256
256
|
}
|
|
257
257
|
.rs-card--outlined .rs-card__title {
|
|
258
|
-
font-weight:
|
|
258
|
+
font-weight: var(--rs-font-weight-medium);
|
|
259
259
|
letter-spacing: 0;
|
|
260
260
|
}
|
|
261
261
|
.rs-card--outlined .rs-card__body {
|
|
@@ -277,7 +277,7 @@ const rootStyle = computed(() => ({
|
|
|
277
277
|
box-shadow: none;
|
|
278
278
|
}
|
|
279
279
|
.rs-card--filled .rs-card__title {
|
|
280
|
-
font-weight:
|
|
280
|
+
font-weight: var(--rs-font-weight-medium);
|
|
281
281
|
letter-spacing: 0;
|
|
282
282
|
}
|
|
283
283
|
.rs-card--filled .rs-card__body {
|
|
@@ -385,7 +385,7 @@ const rootStyle = computed(() => ({
|
|
|
385
385
|
.rs-card__title {
|
|
386
386
|
margin: 0;
|
|
387
387
|
font-size: var(--rs-card-title-size);
|
|
388
|
-
font-weight:
|
|
388
|
+
font-weight: var(--rs-font-weight-semibold);
|
|
389
389
|
letter-spacing: -0.01em;
|
|
390
390
|
color: var(--rs-card-title-fg);
|
|
391
391
|
}
|
|
@@ -192,7 +192,7 @@ function download() {
|
|
|
192
192
|
}
|
|
193
193
|
|
|
194
194
|
.rs-code-block__lang {
|
|
195
|
-
font-family:
|
|
195
|
+
font-family: var(--rs-code-font-family, var(--rs-font-mono));
|
|
196
196
|
font-size: var(--rs-font-size-xs);
|
|
197
197
|
color: var(--rs-muted);
|
|
198
198
|
text-transform: lowercase;
|
|
@@ -251,9 +251,9 @@ function download() {
|
|
|
251
251
|
}
|
|
252
252
|
|
|
253
253
|
.rs-code-block__editor :deep(.cm-scroller) {
|
|
254
|
-
font-family:
|
|
255
|
-
font-size: var(--rs-font-size-sm);
|
|
256
|
-
line-height:
|
|
254
|
+
font-family: var(--rs-code-font-family, var(--rs-font-mono));
|
|
255
|
+
font-size: var(--rs-code-font-size, var(--rs-font-size-sm));
|
|
256
|
+
line-height: var(--rs-code-line-height, var(--rs-line-height-relaxed));
|
|
257
257
|
}
|
|
258
258
|
|
|
259
259
|
/* 只读时隐藏光标,保持纯展示外观 */
|
|
@@ -445,14 +445,14 @@ defineExpose({
|
|
|
445
445
|
justify-content: space-between;
|
|
446
446
|
margin-bottom: 0.5rem;
|
|
447
447
|
font-size: var(--rs-font-size-xs);
|
|
448
|
-
font-weight:
|
|
448
|
+
font-weight: var(--rs-font-weight-semibold);
|
|
449
449
|
color: var(--rs-foreground);
|
|
450
450
|
}
|
|
451
451
|
.rs-code-editor__inline-edit-head kbd {
|
|
452
452
|
padding: 0.1rem 0.35rem;
|
|
453
453
|
border-radius: 4px;
|
|
454
454
|
border: 1px solid var(--rs-border-subtle);
|
|
455
|
-
font-size:
|
|
455
|
+
font-size: var(--rs-font-size-xs);
|
|
456
456
|
color: var(--rs-muted);
|
|
457
457
|
}
|
|
458
458
|
.rs-code-editor__inline-preview {
|
|
@@ -461,8 +461,8 @@ defineExpose({
|
|
|
461
461
|
border-radius: 4px;
|
|
462
462
|
background: color-mix(in srgb, var(--rs-muted) 8%, transparent);
|
|
463
463
|
color: var(--rs-muted);
|
|
464
|
-
font-family:
|
|
465
|
-
font-size:
|
|
464
|
+
font-family: var(--rs-code-font-family, var(--rs-font-mono));
|
|
465
|
+
font-size: var(--rs-font-size-xs);
|
|
466
466
|
line-height: 1.4;
|
|
467
467
|
white-space: pre-wrap;
|
|
468
468
|
max-height: 4.5rem;
|
|
@@ -520,9 +520,9 @@ defineExpose({
|
|
|
520
520
|
background: var(--rs-surface-elevated) !important;
|
|
521
521
|
}
|
|
522
522
|
.rs-code-editor__surface :deep(.cm-scroller) {
|
|
523
|
-
font-family:
|
|
524
|
-
font-size: var(--rs-font-size-sm);
|
|
525
|
-
line-height:
|
|
523
|
+
font-family: var(--rs-code-font-family, var(--rs-font-mono));
|
|
524
|
+
font-size: var(--rs-code-font-size, var(--rs-font-size-sm));
|
|
525
|
+
line-height: var(--rs-code-line-height, var(--rs-line-height-relaxed));
|
|
526
526
|
}
|
|
527
527
|
.rs-code-editor__surface :deep(.cm-gutters) {
|
|
528
528
|
background: color-mix(in srgb, var(--rs-surface-elevated) 85%, var(--rs-border) 15%) !important;
|
|
@@ -571,7 +571,7 @@ defineExpose({
|
|
|
571
571
|
border: 1px solid var(--rs-border);
|
|
572
572
|
background: var(--rs-surface-elevated);
|
|
573
573
|
color: var(--rs-foreground);
|
|
574
|
-
font-family:
|
|
574
|
+
font-family: var(--rs-code-font-family, var(--rs-font-mono));
|
|
575
575
|
font-size: var(--rs-font-size-xs);
|
|
576
576
|
line-height: 1.45;
|
|
577
577
|
white-space: pre-wrap;
|
|
@@ -297,7 +297,7 @@ defineExpose({
|
|
|
297
297
|
height: 2.5rem;
|
|
298
298
|
flex: 0 0 auto;
|
|
299
299
|
border-radius: var(--rs-radius);
|
|
300
|
-
font-weight:
|
|
300
|
+
font-weight: var(--rs-font-weight-bold);
|
|
301
301
|
}
|
|
302
302
|
.rs-confirm-dialog__icon-glyph {
|
|
303
303
|
width: 1.25rem;
|
|
@@ -328,7 +328,7 @@ defineExpose({
|
|
|
328
328
|
.rs-confirm-dialog__title {
|
|
329
329
|
margin: 0;
|
|
330
330
|
font-size: var(--rs-font-size-base);
|
|
331
|
-
font-weight:
|
|
331
|
+
font-weight: var(--rs-font-weight-semibold);
|
|
332
332
|
letter-spacing: -0.01em;
|
|
333
333
|
color: var(--rs-dialog-title-fg);
|
|
334
334
|
}
|
|
@@ -152,9 +152,10 @@ function onSelect(item: RsContextMenuItem) {
|
|
|
152
152
|
align-items: center;
|
|
153
153
|
gap: 0;
|
|
154
154
|
padding: 0 8px 0 0;
|
|
155
|
-
height:
|
|
155
|
+
height: 24px;
|
|
156
156
|
border-radius: 6px;
|
|
157
|
-
font-size:
|
|
157
|
+
font-size: var(--rs-font-size-xs);
|
|
158
|
+
font-weight: var(--rs-font-weight-regular);
|
|
158
159
|
line-height: 1;
|
|
159
160
|
color: var(--rs-text);
|
|
160
161
|
cursor: default;
|
|
@@ -185,10 +186,11 @@ function onSelect(item: RsContextMenuItem) {
|
|
|
185
186
|
.rs-context-menu__shortcut {
|
|
186
187
|
flex-shrink: 0;
|
|
187
188
|
margin-left: 16px;
|
|
188
|
-
font-size:
|
|
189
|
+
font-size: var(--rs-font-size-xs);
|
|
190
|
+
font-weight: var(--rs-font-weight-regular);
|
|
189
191
|
color: var(--rs-ctx-shortcut);
|
|
190
192
|
letter-spacing: 0.02em;
|
|
191
|
-
font-family: -
|
|
193
|
+
font-family: var(--rs-font-sans);
|
|
192
194
|
}
|
|
193
195
|
|
|
194
196
|
/* 子菜单展开箭头 */
|