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.
@@ -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
+ }