dsh-side-chat-plus 0.3.2 → 0.3.3
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/README.md +326 -326
- package/README.zh.md +268 -268
- package/dsh.plugin.json +1 -1
- package/lib/client-registry.js +125 -125
- package/lib/client-registry.js.map +1 -1
- package/lib/client.js +125 -125
- package/lib/client.js.map +1 -1
- package/lib/index.js +7 -2
- package/package.json +1 -1
- package/src/client/attachments/AttachmentRail.module.css +89 -89
- package/src/client/attachments/AttachmentRail.tsx +173 -173
- package/src/client/attachments/DropOverlay.module.css +38 -38
- package/src/client/attachments/DropOverlay.tsx +62 -62
- package/src/client/attachments/ImageLightbox.module.css +44 -44
- package/src/client/attachments/ImageLightbox.tsx +58 -58
- package/src/client/attachments/MessageImage.module.css +61 -61
- package/src/client/attachments/MessageImage.tsx +120 -120
- package/src/client/attachments/index.ts +19 -19
- package/src/client/client.module.css +1032 -1032
- package/src/client/index.tsx +1966 -1966
- package/src/client/locales.ts +173 -173
- package/src/context-types.ts +384 -384
- package/src/index.ts +14 -6
|
@@ -1,62 +1,62 @@
|
|
|
1
|
-
import { createPortal } from 'react-dom'
|
|
2
|
-
import css from './DropOverlay.module.css'
|
|
3
|
-
|
|
4
|
-
/** Drop-overlay strings the owner resolves from its own locale namespace. */
|
|
5
|
-
export interface DropOverlayLabels {
|
|
6
|
-
/** Headline inviting the drop, or naming why it is unavailable. */
|
|
7
|
-
title: string
|
|
8
|
-
/** Limits line under the title; shown only while drops are accepted. */
|
|
9
|
-
desc?: string | undefined
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Full-viewport invitation shown while a file drag is over the page.
|
|
14
|
-
* Decoration only: `pointer-events: none` keeps drag targeting on the page
|
|
15
|
-
* below, so the owner's document-level listeners keep an accurate enter/leave
|
|
16
|
-
* count and own accept/reject. Rendered through a body portal for the same
|
|
17
|
-
* transformed-ancestor reason as the lightbox.
|
|
18
|
-
*/
|
|
19
|
-
export function DropOverlay({ disabled, labels }: {
|
|
20
|
-
disabled: boolean
|
|
21
|
-
labels: DropOverlayLabels
|
|
22
|
-
}) {
|
|
23
|
-
return createPortal(
|
|
24
|
-
<div className={css.mask} role="status">
|
|
25
|
-
<div className={css.wrap}>
|
|
26
|
-
<div className={css.illustration} aria-hidden="true">
|
|
27
|
-
{disabled ? <BlockedIllustration /> : <UploadIllustration />}
|
|
28
|
-
</div>
|
|
29
|
-
<div className={css.title}>{labels.title}</div>
|
|
30
|
-
{!disabled && labels.desc !== undefined && <div className={css.desc}>{labels.desc}</div>}
|
|
31
|
-
</div>
|
|
32
|
-
</div>,
|
|
33
|
-
document.body,
|
|
34
|
-
)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/** Tilted photo-and-note cards. */
|
|
38
|
-
const UploadIllustration = () => (
|
|
39
|
-
<svg width="96" height="72" viewBox="0 0 96 72" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
40
|
-
<rect y="14" width="38" height="38" rx="10" transform="rotate(-22 0 14)" fill="#9ce5ed" />
|
|
41
|
-
<rect x="62" y="7" width="37" height="43" rx="8" transform="rotate(17 62 7)" fill="#679efe" />
|
|
42
|
-
<rect x="26" y="30" width="38" height="38" rx="10" fill="#3964fe" />
|
|
43
|
-
<path
|
|
44
|
-
d="M33 62c1-2 4-8 7-14 1-2 5-2 6 1 2 5 5 9 7 10 3 1 7-9 17 2"
|
|
45
|
-
stroke="#fff"
|
|
46
|
-
strokeWidth="3"
|
|
47
|
-
fill="none"
|
|
48
|
-
/>
|
|
49
|
-
<circle cx="53" cy="43" r="4" fill="#fff" />
|
|
50
|
-
</svg>
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
/** Greyed cards with a blocked badge. */
|
|
54
|
-
const BlockedIllustration = () => (
|
|
55
|
-
<svg width="96" height="72" viewBox="0 0 96 72" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
56
|
-
<rect y="14" width="38" height="38" rx="10" transform="rotate(-22 0 14)" fill="#c4c9d0" />
|
|
57
|
-
<rect x="62" y="7" width="37" height="43" rx="8" transform="rotate(17 62 7)" fill="#b0b6be" />
|
|
58
|
-
<rect x="26" y="30" width="38" height="38" rx="10" fill="#d8dce1" />
|
|
59
|
-
<circle cx="45" cy="49" r="12" stroke="#fff" strokeWidth="3" fill="none" />
|
|
60
|
-
<path d="M36 40l18 18" stroke="#fff" strokeWidth="3" strokeLinecap="round" />
|
|
61
|
-
</svg>
|
|
62
|
-
)
|
|
1
|
+
import { createPortal } from 'react-dom'
|
|
2
|
+
import css from './DropOverlay.module.css'
|
|
3
|
+
|
|
4
|
+
/** Drop-overlay strings the owner resolves from its own locale namespace. */
|
|
5
|
+
export interface DropOverlayLabels {
|
|
6
|
+
/** Headline inviting the drop, or naming why it is unavailable. */
|
|
7
|
+
title: string
|
|
8
|
+
/** Limits line under the title; shown only while drops are accepted. */
|
|
9
|
+
desc?: string | undefined
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Full-viewport invitation shown while a file drag is over the page.
|
|
14
|
+
* Decoration only: `pointer-events: none` keeps drag targeting on the page
|
|
15
|
+
* below, so the owner's document-level listeners keep an accurate enter/leave
|
|
16
|
+
* count and own accept/reject. Rendered through a body portal for the same
|
|
17
|
+
* transformed-ancestor reason as the lightbox.
|
|
18
|
+
*/
|
|
19
|
+
export function DropOverlay({ disabled, labels }: {
|
|
20
|
+
disabled: boolean
|
|
21
|
+
labels: DropOverlayLabels
|
|
22
|
+
}) {
|
|
23
|
+
return createPortal(
|
|
24
|
+
<div className={css.mask} role="status">
|
|
25
|
+
<div className={css.wrap}>
|
|
26
|
+
<div className={css.illustration} aria-hidden="true">
|
|
27
|
+
{disabled ? <BlockedIllustration /> : <UploadIllustration />}
|
|
28
|
+
</div>
|
|
29
|
+
<div className={css.title}>{labels.title}</div>
|
|
30
|
+
{!disabled && labels.desc !== undefined && <div className={css.desc}>{labels.desc}</div>}
|
|
31
|
+
</div>
|
|
32
|
+
</div>,
|
|
33
|
+
document.body,
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Tilted photo-and-note cards. */
|
|
38
|
+
const UploadIllustration = () => (
|
|
39
|
+
<svg width="96" height="72" viewBox="0 0 96 72" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
40
|
+
<rect y="14" width="38" height="38" rx="10" transform="rotate(-22 0 14)" fill="#9ce5ed" />
|
|
41
|
+
<rect x="62" y="7" width="37" height="43" rx="8" transform="rotate(17 62 7)" fill="#679efe" />
|
|
42
|
+
<rect x="26" y="30" width="38" height="38" rx="10" fill="#3964fe" />
|
|
43
|
+
<path
|
|
44
|
+
d="M33 62c1-2 4-8 7-14 1-2 5-2 6 1 2 5 5 9 7 10 3 1 7-9 17 2"
|
|
45
|
+
stroke="#fff"
|
|
46
|
+
strokeWidth="3"
|
|
47
|
+
fill="none"
|
|
48
|
+
/>
|
|
49
|
+
<circle cx="53" cy="43" r="4" fill="#fff" />
|
|
50
|
+
</svg>
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
/** Greyed cards with a blocked badge. */
|
|
54
|
+
const BlockedIllustration = () => (
|
|
55
|
+
<svg width="96" height="72" viewBox="0 0 96 72" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
56
|
+
<rect y="14" width="38" height="38" rx="10" transform="rotate(-22 0 14)" fill="#c4c9d0" />
|
|
57
|
+
<rect x="62" y="7" width="37" height="43" rx="8" transform="rotate(17 62 7)" fill="#b0b6be" />
|
|
58
|
+
<rect x="26" y="30" width="38" height="38" rx="10" fill="#d8dce1" />
|
|
59
|
+
<circle cx="45" cy="49" r="12" stroke="#fff" strokeWidth="3" fill="none" />
|
|
60
|
+
<path d="M36 40l18 18" stroke="#fff" strokeWidth="3" strokeLinecap="round" />
|
|
61
|
+
</svg>
|
|
62
|
+
)
|
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
.backdrop {
|
|
2
|
-
position: fixed;
|
|
3
|
-
inset: 0;
|
|
4
|
-
z-index: 1000;
|
|
5
|
-
display: flex;
|
|
6
|
-
align-items: center;
|
|
7
|
-
justify-content: center;
|
|
8
|
-
padding: 32px;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
.mask {
|
|
12
|
-
position: absolute;
|
|
13
|
-
inset: 0;
|
|
14
|
-
background: rgba(0, 0, 0, 0.72);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
.image {
|
|
18
|
-
position: relative;
|
|
19
|
-
max-width: 100%;
|
|
20
|
-
max-height: 100%;
|
|
21
|
-
object-fit: contain;
|
|
22
|
-
border-radius: 8px;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
.close {
|
|
26
|
-
position: absolute;
|
|
27
|
-
top: 20px;
|
|
28
|
-
right: 20px;
|
|
29
|
-
display: flex;
|
|
30
|
-
align-items: center;
|
|
31
|
-
justify-content: center;
|
|
32
|
-
width: 32px;
|
|
33
|
-
height: 32px;
|
|
34
|
-
padding: 0;
|
|
35
|
-
border: none;
|
|
36
|
-
border-radius: 50%;
|
|
37
|
-
background: rgba(255, 255, 255, 0.16);
|
|
38
|
-
color: #fff;
|
|
39
|
-
cursor: pointer;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
.close:hover {
|
|
43
|
-
background: rgba(255, 255, 255, 0.28);
|
|
44
|
-
}
|
|
1
|
+
.backdrop {
|
|
2
|
+
position: fixed;
|
|
3
|
+
inset: 0;
|
|
4
|
+
z-index: 1000;
|
|
5
|
+
display: flex;
|
|
6
|
+
align-items: center;
|
|
7
|
+
justify-content: center;
|
|
8
|
+
padding: 32px;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.mask {
|
|
12
|
+
position: absolute;
|
|
13
|
+
inset: 0;
|
|
14
|
+
background: rgba(0, 0, 0, 0.72);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.image {
|
|
18
|
+
position: relative;
|
|
19
|
+
max-width: 100%;
|
|
20
|
+
max-height: 100%;
|
|
21
|
+
object-fit: contain;
|
|
22
|
+
border-radius: 8px;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.close {
|
|
26
|
+
position: absolute;
|
|
27
|
+
top: 20px;
|
|
28
|
+
right: 20px;
|
|
29
|
+
display: flex;
|
|
30
|
+
align-items: center;
|
|
31
|
+
justify-content: center;
|
|
32
|
+
width: 32px;
|
|
33
|
+
height: 32px;
|
|
34
|
+
padding: 0;
|
|
35
|
+
border: none;
|
|
36
|
+
border-radius: 50%;
|
|
37
|
+
background: rgba(255, 255, 255, 0.16);
|
|
38
|
+
color: #fff;
|
|
39
|
+
cursor: pointer;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.close:hover {
|
|
43
|
+
background: rgba(255, 255, 255, 0.28);
|
|
44
|
+
}
|
|
@@ -1,58 +1,58 @@
|
|
|
1
|
-
import { useEffect, useRef } from 'react'
|
|
2
|
-
import { createPortal } from 'react-dom'
|
|
3
|
-
import { IconCloseOutline16 } from '@deepseek-ai/dsh-client-ui-primitives'
|
|
4
|
-
import css from './ImageLightbox.module.css'
|
|
5
|
-
|
|
6
|
-
/** Preview strings the owner resolves from its own locale namespace. */
|
|
7
|
-
export interface ImageLightboxLabels {
|
|
8
|
-
/** Accessible name of the preview dialog. */
|
|
9
|
-
dialog: string
|
|
10
|
-
/** Accessible label of the close control. */
|
|
11
|
-
close: string
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Document-level original-image preview opened by clicking a thumbnail.
|
|
16
|
-
* Closes on Escape, backdrop press, or the close control, and restores focus
|
|
17
|
-
* to the opener on unmount. Rendered through a body portal: an opener inside
|
|
18
|
-
* a transformed or filtered ancestor would otherwise trap the fixed backdrop
|
|
19
|
-
* in that ancestor's box instead of covering the viewport.
|
|
20
|
-
*/
|
|
21
|
-
export function ImageLightbox({ src, alt, labels, onClose }: {
|
|
22
|
-
src: string
|
|
23
|
-
alt: string
|
|
24
|
-
labels: ImageLightboxLabels
|
|
25
|
-
onClose: () => void
|
|
26
|
-
}) {
|
|
27
|
-
const closeRef = useRef<HTMLButtonElement | null>(null)
|
|
28
|
-
const restoreRef = useRef<HTMLElement | null>(null)
|
|
29
|
-
|
|
30
|
-
useEffect(() => {
|
|
31
|
-
restoreRef.current = document.activeElement instanceof HTMLElement ? document.activeElement : null
|
|
32
|
-
closeRef.current?.focus()
|
|
33
|
-
const onKeyDown = (event: globalThis.KeyboardEvent): void => {
|
|
34
|
-
if (event.key === 'Escape') onClose()
|
|
35
|
-
}
|
|
36
|
-
window.addEventListener('keydown', onKeyDown)
|
|
37
|
-
return () => {
|
|
38
|
-
window.removeEventListener('keydown', onKeyDown)
|
|
39
|
-
restoreRef.current?.focus()
|
|
40
|
-
}
|
|
41
|
-
}, [onClose])
|
|
42
|
-
|
|
43
|
-
return createPortal(
|
|
44
|
-
<div
|
|
45
|
-
className={css.backdrop}
|
|
46
|
-
role="dialog"
|
|
47
|
-
aria-modal="true"
|
|
48
|
-
aria-label={labels.dialog}
|
|
49
|
-
>
|
|
50
|
-
<div className={css.mask} aria-hidden="true" onMouseDown={onClose} />
|
|
51
|
-
<img className={css.image} src={src} alt={alt} />
|
|
52
|
-
<button ref={closeRef} type="button" className={css.close} aria-label={labels.close} onClick={onClose}>
|
|
53
|
-
<IconCloseOutline16 size={16} />
|
|
54
|
-
</button>
|
|
55
|
-
</div>,
|
|
56
|
-
document.body,
|
|
57
|
-
)
|
|
58
|
-
}
|
|
1
|
+
import { useEffect, useRef } from 'react'
|
|
2
|
+
import { createPortal } from 'react-dom'
|
|
3
|
+
import { IconCloseOutline16 } from '@deepseek-ai/dsh-client-ui-primitives'
|
|
4
|
+
import css from './ImageLightbox.module.css'
|
|
5
|
+
|
|
6
|
+
/** Preview strings the owner resolves from its own locale namespace. */
|
|
7
|
+
export interface ImageLightboxLabels {
|
|
8
|
+
/** Accessible name of the preview dialog. */
|
|
9
|
+
dialog: string
|
|
10
|
+
/** Accessible label of the close control. */
|
|
11
|
+
close: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Document-level original-image preview opened by clicking a thumbnail.
|
|
16
|
+
* Closes on Escape, backdrop press, or the close control, and restores focus
|
|
17
|
+
* to the opener on unmount. Rendered through a body portal: an opener inside
|
|
18
|
+
* a transformed or filtered ancestor would otherwise trap the fixed backdrop
|
|
19
|
+
* in that ancestor's box instead of covering the viewport.
|
|
20
|
+
*/
|
|
21
|
+
export function ImageLightbox({ src, alt, labels, onClose }: {
|
|
22
|
+
src: string
|
|
23
|
+
alt: string
|
|
24
|
+
labels: ImageLightboxLabels
|
|
25
|
+
onClose: () => void
|
|
26
|
+
}) {
|
|
27
|
+
const closeRef = useRef<HTMLButtonElement | null>(null)
|
|
28
|
+
const restoreRef = useRef<HTMLElement | null>(null)
|
|
29
|
+
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
restoreRef.current = document.activeElement instanceof HTMLElement ? document.activeElement : null
|
|
32
|
+
closeRef.current?.focus()
|
|
33
|
+
const onKeyDown = (event: globalThis.KeyboardEvent): void => {
|
|
34
|
+
if (event.key === 'Escape') onClose()
|
|
35
|
+
}
|
|
36
|
+
window.addEventListener('keydown', onKeyDown)
|
|
37
|
+
return () => {
|
|
38
|
+
window.removeEventListener('keydown', onKeyDown)
|
|
39
|
+
restoreRef.current?.focus()
|
|
40
|
+
}
|
|
41
|
+
}, [onClose])
|
|
42
|
+
|
|
43
|
+
return createPortal(
|
|
44
|
+
<div
|
|
45
|
+
className={css.backdrop}
|
|
46
|
+
role="dialog"
|
|
47
|
+
aria-modal="true"
|
|
48
|
+
aria-label={labels.dialog}
|
|
49
|
+
>
|
|
50
|
+
<div className={css.mask} aria-hidden="true" onMouseDown={onClose} />
|
|
51
|
+
<img className={css.image} src={src} alt={alt} />
|
|
52
|
+
<button ref={closeRef} type="button" className={css.close} aria-label={labels.close} onClick={onClose}>
|
|
53
|
+
<IconCloseOutline16 size={16} />
|
|
54
|
+
</button>
|
|
55
|
+
</div>,
|
|
56
|
+
document.body,
|
|
57
|
+
)
|
|
58
|
+
}
|
|
@@ -1,61 +1,61 @@
|
|
|
1
|
-
.gallery {
|
|
2
|
-
display: flex;
|
|
3
|
-
flex-wrap: wrap;
|
|
4
|
-
gap: 8px;
|
|
5
|
-
max-width: 100%;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
.gallery[data-align='start'] {
|
|
9
|
-
justify-content: flex-start;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
.gallery[data-align='end'] {
|
|
13
|
-
justify-content: flex-end;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
.frame {
|
|
17
|
-
padding: 0;
|
|
18
|
-
overflow: hidden;
|
|
19
|
-
border: 1px solid var(--dsw-color-border, rgba(0, 0, 0, 0.08));
|
|
20
|
-
border-radius: 8px;
|
|
21
|
-
background: none;
|
|
22
|
-
cursor: pointer;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
.frame[data-variant='tile'] {
|
|
26
|
-
width: 64px;
|
|
27
|
-
height: 64px;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
.frame img {
|
|
31
|
-
width: 100%;
|
|
32
|
-
height: 100%;
|
|
33
|
-
object-fit: cover;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
.loading {
|
|
37
|
-
display: flex;
|
|
38
|
-
align-items: center;
|
|
39
|
-
justify-content: center;
|
|
40
|
-
width: 100%;
|
|
41
|
-
height: 100%;
|
|
42
|
-
min-width: 64px;
|
|
43
|
-
min-height: 64px;
|
|
44
|
-
font-size: 12px;
|
|
45
|
-
color: var(--dsw-color-text-secondary, #646a73);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
.error {
|
|
49
|
-
display: flex;
|
|
50
|
-
align-items: center;
|
|
51
|
-
justify-content: center;
|
|
52
|
-
min-width: 64px;
|
|
53
|
-
min-height: 64px;
|
|
54
|
-
padding: 0 8px;
|
|
55
|
-
border: 1px dashed var(--dsw-color-border, rgba(0, 0, 0, 0.16));
|
|
56
|
-
border-radius: 8px;
|
|
57
|
-
background: none;
|
|
58
|
-
font-size: 12px;
|
|
59
|
-
color: var(--dsw-color-text-secondary, #646a73);
|
|
60
|
-
cursor: pointer;
|
|
61
|
-
}
|
|
1
|
+
.gallery {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-wrap: wrap;
|
|
4
|
+
gap: 8px;
|
|
5
|
+
max-width: 100%;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.gallery[data-align='start'] {
|
|
9
|
+
justify-content: flex-start;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.gallery[data-align='end'] {
|
|
13
|
+
justify-content: flex-end;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.frame {
|
|
17
|
+
padding: 0;
|
|
18
|
+
overflow: hidden;
|
|
19
|
+
border: 1px solid var(--dsw-color-border, rgba(0, 0, 0, 0.08));
|
|
20
|
+
border-radius: 8px;
|
|
21
|
+
background: none;
|
|
22
|
+
cursor: pointer;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.frame[data-variant='tile'] {
|
|
26
|
+
width: 64px;
|
|
27
|
+
height: 64px;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.frame img {
|
|
31
|
+
width: 100%;
|
|
32
|
+
height: 100%;
|
|
33
|
+
object-fit: cover;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.loading {
|
|
37
|
+
display: flex;
|
|
38
|
+
align-items: center;
|
|
39
|
+
justify-content: center;
|
|
40
|
+
width: 100%;
|
|
41
|
+
height: 100%;
|
|
42
|
+
min-width: 64px;
|
|
43
|
+
min-height: 64px;
|
|
44
|
+
font-size: 12px;
|
|
45
|
+
color: var(--dsw-color-text-secondary, #646a73);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.error {
|
|
49
|
+
display: flex;
|
|
50
|
+
align-items: center;
|
|
51
|
+
justify-content: center;
|
|
52
|
+
min-width: 64px;
|
|
53
|
+
min-height: 64px;
|
|
54
|
+
padding: 0 8px;
|
|
55
|
+
border: 1px dashed var(--dsw-color-border, rgba(0, 0, 0, 0.16));
|
|
56
|
+
border-radius: 8px;
|
|
57
|
+
background: none;
|
|
58
|
+
font-size: 12px;
|
|
59
|
+
color: var(--dsw-color-text-secondary, #646a73);
|
|
60
|
+
cursor: pointer;
|
|
61
|
+
}
|