@xhub-short/ui 0.1.0-beta.1 → 0.1.0-beta.10
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/dist/CommentSheet.css-BeCrEaUG.d.ts +221 -0
- package/dist/{chunk-2PTMP65P.js → chunk-2FSDVYER.js} +8 -9
- package/dist/{chunk-WKX2WBVO.js → chunk-3XPJHUYL.js} +1 -39
- package/dist/{chunk-ANGBSV7L.js → chunk-AC2IFAJR.js} +10 -5
- package/dist/{chunk-4YDIRPIN.js → chunk-ANCP53F3.js} +3 -3
- package/dist/chunk-AQHD6LPS.js +430 -0
- package/dist/{chunk-HW4LXTFT.js → chunk-CL6BS7GB.js} +7 -5
- package/dist/{chunk-YW23IBKF.js → chunk-ECR42RKK.js} +46 -5
- package/dist/chunk-EDWS2IPH.js +1 -0
- package/dist/chunk-FNXTPQ6L.js +2573 -0
- package/dist/{chunk-DHQJBXQW.js → chunk-KWHMZ6H5.js} +1 -1
- package/dist/{chunk-UXMA4KJZ.js → chunk-RMLTPW5S.js} +3 -2
- package/dist/{chunk-SSJDO24Q.js → chunk-SZXFH334.js} +1 -1
- package/dist/{chunk-4MN72OZH.js → chunk-UNV3NWN6.js} +4 -4
- package/dist/{chunk-ZZDQKP4R.js → chunk-WCRDTBCZ.js} +94 -155
- package/dist/{chunk-XAOEHLOX.js → chunk-XDIH66C4.js} +245 -52
- package/dist/components/ActionBar/index.js +1 -1
- package/dist/components/AuthorInfo/index.d.ts +5 -1
- package/dist/components/AuthorInfo/index.js +1 -1
- package/dist/components/BlurhashPlaceholder/index.d.ts +67 -0
- package/dist/components/BlurhashPlaceholder/index.js +150 -0
- package/dist/components/CommentSheet/index.d.ts +164 -0
- package/dist/components/CommentSheet/index.js +1 -0
- package/dist/components/ErrorBoundary/index.js +1 -1
- package/dist/components/OfflineIndicator/index.d.ts +56 -0
- package/dist/components/OfflineIndicator/index.js +151 -0
- package/dist/components/ProgressBar/index.d.ts +30 -2
- package/dist/components/ProgressBar/index.js +1 -1
- package/dist/components/Skeleton/index.js +1 -1
- package/dist/components/SubtitleDisplay/index.d.ts +94 -0
- package/dist/components/SubtitleDisplay/index.js +165 -0
- package/dist/components/VideoFeed/index.d.ts +11 -0
- package/dist/components/VideoFeed/index.js +1 -1
- package/dist/components/VideoInfo/index.js +1 -1
- package/dist/components/VideoPlayer/index.d.ts +14 -41
- package/dist/components/VideoPlayer/index.js +1 -1
- package/dist/components/VideoSlot/index.d.ts +124 -64
- package/dist/components/VideoSlot/index.js +1 -1
- package/dist/components/VirtualSlider/index.d.ts +339 -0
- package/dist/components/VirtualSlider/index.js +1 -0
- package/dist/components/icons/index.js +1 -1
- package/dist/index.d.ts +76 -93
- package/dist/index.js +75 -27
- package/package.json +53 -8
- package/dist/use-gesture-react.esm-3SV4QLEJ.js +0 -1893
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { injectComponentCSS } from '../../chunk-RMLTPW5S.js';
|
|
2
|
+
import { clsx } from 'clsx';
|
|
3
|
+
import { useRef, useState, useInsertionEffect, useEffect } from 'react';
|
|
4
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
// src/components/BlurhashPlaceholder/BlurhashPlaceholder.css.ts
|
|
7
|
+
var BLURHASH_PLACEHOLDER_CSS = `
|
|
8
|
+
/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
9
|
+
* BLURHASH PLACEHOLDER
|
|
10
|
+
* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */
|
|
11
|
+
|
|
12
|
+
.sv-blurhash-placeholder {
|
|
13
|
+
position: absolute;
|
|
14
|
+
inset: 0;
|
|
15
|
+
z-index: var(--sv-z-placeholder, 1);
|
|
16
|
+
background-size: cover;
|
|
17
|
+
background-position: center;
|
|
18
|
+
background-repeat: no-repeat;
|
|
19
|
+
transition: opacity 200ms ease-out;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.sv-blurhash-placeholder--hidden {
|
|
23
|
+
opacity: 0;
|
|
24
|
+
pointer-events: none;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* Canvas used for decoding - always hidden */
|
|
28
|
+
.sv-blurhash-placeholder__canvas {
|
|
29
|
+
display: none !important;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
33
|
+
* REDUCE MOTION
|
|
34
|
+
* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */
|
|
35
|
+
|
|
36
|
+
@media (prefers-reduced-motion: reduce) {
|
|
37
|
+
.sv-blurhash-placeholder {
|
|
38
|
+
transition: none;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
`;
|
|
42
|
+
var imageCache = /* @__PURE__ */ new Map();
|
|
43
|
+
var decodePromise = null;
|
|
44
|
+
function getBlurhashDecoder() {
|
|
45
|
+
if (!decodePromise) {
|
|
46
|
+
decodePromise = import('blurhash').then((m) => ({ decode: m.decode }));
|
|
47
|
+
}
|
|
48
|
+
return decodePromise;
|
|
49
|
+
}
|
|
50
|
+
function getCacheKey(blurhash, width, height, punch) {
|
|
51
|
+
return `${blurhash}:${width}:${height}:${punch}`;
|
|
52
|
+
}
|
|
53
|
+
function BlurhashPlaceholderHeadless({
|
|
54
|
+
blurhash,
|
|
55
|
+
width = 32,
|
|
56
|
+
height = 32,
|
|
57
|
+
punch = 1,
|
|
58
|
+
isHidden = false,
|
|
59
|
+
className,
|
|
60
|
+
testId
|
|
61
|
+
}) {
|
|
62
|
+
const canvasRef = useRef(null);
|
|
63
|
+
const cacheKey = getCacheKey(blurhash, width, height, punch);
|
|
64
|
+
const [dataUrl, setDataUrl] = useState(() => {
|
|
65
|
+
return imageCache.get(cacheKey) ?? null;
|
|
66
|
+
});
|
|
67
|
+
useInsertionEffect(() => {
|
|
68
|
+
return injectComponentCSS("blurhash-placeholder", BLURHASH_PLACEHOLDER_CSS);
|
|
69
|
+
}, []);
|
|
70
|
+
useEffect(() => {
|
|
71
|
+
if (dataUrl) return void 0;
|
|
72
|
+
let cancelled = false;
|
|
73
|
+
async function decode() {
|
|
74
|
+
try {
|
|
75
|
+
const { decode: decodeBlurhash } = await getBlurhashDecoder();
|
|
76
|
+
if (cancelled) return;
|
|
77
|
+
const pixels = decodeBlurhash(blurhash, width, height, punch);
|
|
78
|
+
if (cancelled) return;
|
|
79
|
+
const canvas = canvasRef.current;
|
|
80
|
+
if (!canvas) return;
|
|
81
|
+
canvas.width = width;
|
|
82
|
+
canvas.height = height;
|
|
83
|
+
const ctx = canvas.getContext("2d");
|
|
84
|
+
if (!ctx) return;
|
|
85
|
+
const imageData = ctx.createImageData(width, height);
|
|
86
|
+
imageData.data.set(pixels);
|
|
87
|
+
ctx.putImageData(imageData, 0, 0);
|
|
88
|
+
const url = canvas.toDataURL();
|
|
89
|
+
imageCache.set(cacheKey, url);
|
|
90
|
+
if (!cancelled) {
|
|
91
|
+
setDataUrl(url);
|
|
92
|
+
}
|
|
93
|
+
} catch {
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
decode();
|
|
97
|
+
return () => {
|
|
98
|
+
cancelled = true;
|
|
99
|
+
};
|
|
100
|
+
}, [blurhash, width, height, punch, cacheKey, dataUrl]);
|
|
101
|
+
if (!dataUrl && !canvasRef.current) {
|
|
102
|
+
return /* @__PURE__ */ jsx("canvas", { ref: canvasRef, className: "sv-blurhash-placeholder__canvas" });
|
|
103
|
+
}
|
|
104
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
105
|
+
/* @__PURE__ */ jsx("canvas", { ref: canvasRef, className: "sv-blurhash-placeholder__canvas" }),
|
|
106
|
+
dataUrl && /* @__PURE__ */ jsx(
|
|
107
|
+
"div",
|
|
108
|
+
{
|
|
109
|
+
className: clsx(
|
|
110
|
+
"sv-blurhash-placeholder",
|
|
111
|
+
isHidden && "sv-blurhash-placeholder--hidden",
|
|
112
|
+
className
|
|
113
|
+
),
|
|
114
|
+
style: { backgroundImage: `url(${dataUrl})` },
|
|
115
|
+
"aria-hidden": "true",
|
|
116
|
+
"data-testid": testId
|
|
117
|
+
}
|
|
118
|
+
)
|
|
119
|
+
] });
|
|
120
|
+
}
|
|
121
|
+
function clearBlurhashCache() {
|
|
122
|
+
imageCache.clear();
|
|
123
|
+
}
|
|
124
|
+
function getBlurhashCacheSize() {
|
|
125
|
+
return imageCache.size;
|
|
126
|
+
}
|
|
127
|
+
async function preloadBlurhash(blurhash, width = 32, height = 32, punch = 1) {
|
|
128
|
+
const cacheKey = getCacheKey(blurhash, width, height, punch);
|
|
129
|
+
const cached = imageCache.get(cacheKey);
|
|
130
|
+
if (cached) return cached;
|
|
131
|
+
try {
|
|
132
|
+
const { decode } = await getBlurhashDecoder();
|
|
133
|
+
const pixels = decode(blurhash, width, height, punch);
|
|
134
|
+
const canvas = document.createElement("canvas");
|
|
135
|
+
canvas.width = width;
|
|
136
|
+
canvas.height = height;
|
|
137
|
+
const ctx = canvas.getContext("2d");
|
|
138
|
+
if (!ctx) return null;
|
|
139
|
+
const imageData = ctx.createImageData(width, height);
|
|
140
|
+
imageData.data.set(pixels);
|
|
141
|
+
ctx.putImageData(imageData, 0, 0);
|
|
142
|
+
const url = canvas.toDataURL();
|
|
143
|
+
imageCache.set(cacheKey, url);
|
|
144
|
+
return url;
|
|
145
|
+
} catch {
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export { BLURHASH_PLACEHOLDER_CSS, BlurhashPlaceholderHeadless, clearBlurhashCache, getBlurhashCacheSize, preloadBlurhash };
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
export { n as COMMENT_SHEET_CSS, f as CommentInput, g as CommentInputProps, h as CommentItemComponent, i as CommentItemProps, d as CommentList, e as CommentListProps, C as CommentSheet, j as CommentSheetContext, l as CommentSheetContextValue, a as CommentSheetHeadless, b as CommentSheetHeadlessProps, m as CommentSheetI18n, R as ReplyTarget, S as SheetHeader, c as SheetHeaderProps, u as useCommentSheetContext, k as useOptionalCommentSheetContext } from '../../CommentSheet.css-BeCrEaUG.js';
|
|
2
|
+
import * as react from 'react';
|
|
3
|
+
import { ReactNode, ReactElement } from 'react';
|
|
4
|
+
import { CommentItem, ReplyItem } from '@xhub-short/contracts';
|
|
5
|
+
|
|
6
|
+
interface CommentMenuContextValue {
|
|
7
|
+
/** Comment data */
|
|
8
|
+
comment: CommentItem | ReplyItem;
|
|
9
|
+
/** Whether this is a reply */
|
|
10
|
+
isReply: boolean;
|
|
11
|
+
/** Parent comment ID (for replies) */
|
|
12
|
+
parentId?: string;
|
|
13
|
+
/** Whether menu is open */
|
|
14
|
+
isOpen: boolean;
|
|
15
|
+
/** Open menu */
|
|
16
|
+
open: () => void;
|
|
17
|
+
/** Close menu */
|
|
18
|
+
close: () => void;
|
|
19
|
+
/** Toggle menu */
|
|
20
|
+
toggle: () => void;
|
|
21
|
+
/** Trigger button ref */
|
|
22
|
+
triggerRef: React.RefObject<HTMLButtonElement | null>;
|
|
23
|
+
/** Menu container ref */
|
|
24
|
+
menuRef: React.RefObject<HTMLDivElement | null>;
|
|
25
|
+
/** Show confirmation dialog */
|
|
26
|
+
showConfirm: (config: ConfirmDialogConfig) => void;
|
|
27
|
+
/** i18n strings */
|
|
28
|
+
i18n: CommentMenuI18n;
|
|
29
|
+
}
|
|
30
|
+
interface ConfirmDialogConfig {
|
|
31
|
+
title: string;
|
|
32
|
+
message: string;
|
|
33
|
+
confirmText: string;
|
|
34
|
+
cancelText: string;
|
|
35
|
+
danger?: boolean;
|
|
36
|
+
onConfirm: () => Promise<void> | void;
|
|
37
|
+
}
|
|
38
|
+
interface CommentMenuI18n {
|
|
39
|
+
deleteText: string;
|
|
40
|
+
editText: string;
|
|
41
|
+
reportText: string;
|
|
42
|
+
deleteConfirmTitle: string;
|
|
43
|
+
deleteConfirmMessage: string;
|
|
44
|
+
deleteConfirmButton: string;
|
|
45
|
+
cancelButton: string;
|
|
46
|
+
}
|
|
47
|
+
declare function useCommentMenuContext(): CommentMenuContextValue;
|
|
48
|
+
interface DeleteConfirmDialogProps {
|
|
49
|
+
isOpen: boolean;
|
|
50
|
+
onClose: () => void;
|
|
51
|
+
onConfirm: () => void;
|
|
52
|
+
isDeleting?: boolean;
|
|
53
|
+
title?: string;
|
|
54
|
+
message?: string;
|
|
55
|
+
confirmText?: string;
|
|
56
|
+
cancelText?: string;
|
|
57
|
+
danger?: boolean;
|
|
58
|
+
}
|
|
59
|
+
declare const DeleteConfirmDialog: react.NamedExoticComponent<DeleteConfirmDialogProps>;
|
|
60
|
+
interface CommentMenuProps {
|
|
61
|
+
/** Comment or Reply data */
|
|
62
|
+
comment: CommentItem | ReplyItem;
|
|
63
|
+
/** Whether this is a reply */
|
|
64
|
+
isReply?: boolean;
|
|
65
|
+
/** Parent comment ID (required for replies) */
|
|
66
|
+
parentId?: string;
|
|
67
|
+
/** Custom class */
|
|
68
|
+
className?: string;
|
|
69
|
+
/** Children (compound components) */
|
|
70
|
+
children: ReactNode;
|
|
71
|
+
}
|
|
72
|
+
declare function CommentMenuRoot({ comment, isReply, parentId, className, children, }: CommentMenuProps): ReactElement;
|
|
73
|
+
interface CommentMenuTriggerProps {
|
|
74
|
+
/** Custom class */
|
|
75
|
+
className?: string;
|
|
76
|
+
/** Custom icon */
|
|
77
|
+
icon?: ReactNode;
|
|
78
|
+
/** Aria label */
|
|
79
|
+
'aria-label'?: string;
|
|
80
|
+
}
|
|
81
|
+
declare function Trigger({ className, icon, 'aria-label': ariaLabel, }: CommentMenuTriggerProps): ReactElement;
|
|
82
|
+
interface CommentMenuDropdownProps {
|
|
83
|
+
/** Custom class */
|
|
84
|
+
className?: string;
|
|
85
|
+
/** Children (menu items) */
|
|
86
|
+
children: ReactNode;
|
|
87
|
+
}
|
|
88
|
+
declare function Dropdown({ className, children }: CommentMenuDropdownProps): ReactElement | null;
|
|
89
|
+
interface CommentMenuItemProps {
|
|
90
|
+
/** Icon element */
|
|
91
|
+
icon?: ReactNode;
|
|
92
|
+
/** Danger style (red) */
|
|
93
|
+
danger?: boolean;
|
|
94
|
+
/** Disabled state */
|
|
95
|
+
disabled?: boolean;
|
|
96
|
+
/** Custom class */
|
|
97
|
+
className?: string;
|
|
98
|
+
/** Click handler */
|
|
99
|
+
onClick?: () => void;
|
|
100
|
+
/** Children (label) */
|
|
101
|
+
children: ReactNode;
|
|
102
|
+
}
|
|
103
|
+
declare function Item({ icon, danger, disabled, className, onClick, children, }: CommentMenuItemProps): ReactElement;
|
|
104
|
+
interface DeleteItemProps {
|
|
105
|
+
/** Override confirm behavior (skip dialog if false) */
|
|
106
|
+
requireConfirm?: boolean;
|
|
107
|
+
/**
|
|
108
|
+
* Custom delete handler - overrides default context action
|
|
109
|
+
* @param id - Comment/Reply ID
|
|
110
|
+
* @param isReply - Whether this is a reply
|
|
111
|
+
* @param parentId - Parent comment ID (for replies)
|
|
112
|
+
*/
|
|
113
|
+
onDelete?: (id: string, isReply: boolean, parentId?: string) => Promise<void> | void;
|
|
114
|
+
/** Custom label text */
|
|
115
|
+
label?: string;
|
|
116
|
+
/** Custom class */
|
|
117
|
+
className?: string;
|
|
118
|
+
}
|
|
119
|
+
declare function DeleteItem({ requireConfirm, onDelete, label, className }: DeleteItemProps): ReactElement;
|
|
120
|
+
interface EditItemProps {
|
|
121
|
+
/**
|
|
122
|
+
* Edit handler - receives comment ID and current content
|
|
123
|
+
* If not provided, item will be disabled
|
|
124
|
+
*/
|
|
125
|
+
onEdit?: (id: string, content: string) => void;
|
|
126
|
+
/** Custom label text */
|
|
127
|
+
label?: string;
|
|
128
|
+
/** Custom class */
|
|
129
|
+
className?: string;
|
|
130
|
+
}
|
|
131
|
+
declare function EditItem({ onEdit, label, className }: EditItemProps): ReactElement;
|
|
132
|
+
interface ReportItemProps {
|
|
133
|
+
/**
|
|
134
|
+
* Custom report handler - overrides default context action
|
|
135
|
+
* @param id - Comment/Reply ID
|
|
136
|
+
*/
|
|
137
|
+
onReport?: (id: string) => void;
|
|
138
|
+
/** Default report reason (used when onReport not provided) */
|
|
139
|
+
reason?: string;
|
|
140
|
+
/** Custom label text */
|
|
141
|
+
label?: string;
|
|
142
|
+
/** Custom class */
|
|
143
|
+
className?: string;
|
|
144
|
+
}
|
|
145
|
+
declare function ReportItem({ onReport, reason, label, className, }: ReportItemProps): ReactElement;
|
|
146
|
+
declare const CommentMenu: react.NamedExoticComponent<CommentMenuProps> & {
|
|
147
|
+
readonly type: typeof CommentMenuRoot;
|
|
148
|
+
} & {
|
|
149
|
+
Trigger: react.MemoExoticComponent<typeof Trigger>;
|
|
150
|
+
Dropdown: react.MemoExoticComponent<typeof Dropdown>;
|
|
151
|
+
Item: react.MemoExoticComponent<typeof Item>;
|
|
152
|
+
DeleteItem: react.MemoExoticComponent<typeof DeleteItem>;
|
|
153
|
+
EditItem: react.MemoExoticComponent<typeof EditItem>;
|
|
154
|
+
ReportItem: react.MemoExoticComponent<typeof ReportItem>;
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
declare const CommentItemSkeleton: react.NamedExoticComponent<object>;
|
|
158
|
+
interface CommentListSkeletonProps {
|
|
159
|
+
/** Number of skeleton items to show (default: 5) */
|
|
160
|
+
count?: number;
|
|
161
|
+
}
|
|
162
|
+
declare const CommentListSkeleton: react.NamedExoticComponent<CommentListSkeletonProps>;
|
|
163
|
+
|
|
164
|
+
export { CommentItemSkeleton, CommentListSkeleton, type CommentListSkeletonProps, CommentMenu, type CommentMenuContextValue, type CommentMenuDropdownProps, type CommentMenuI18n, type CommentMenuItemProps, type CommentMenuProps, type CommentMenuTriggerProps, type ConfirmDialogConfig, DeleteConfirmDialog, type DeleteConfirmDialogProps, type DeleteItemProps, type EditItemProps, type ReportItemProps, useCommentMenuContext };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { COMMENT_SHEET_CSS, CommentInput, CommentItemComponent, CommentItemSkeleton, CommentList, CommentListSkeleton, CommentMenu, CommentSheet, CommentSheetContext, CommentSheetHeadless, DeleteConfirmDialog, SheetHeader, useCommentMenuContext, useCommentSheetContext, useOptionalCommentSheetContext } from '../../chunk-FNXTPQ6L.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { ErrorBoundary } from '../../chunk-
|
|
1
|
+
export { ErrorBoundary } from '../../chunk-SZXFH334.js';
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* OfflineIndicatorHeadless - Network status indicator
|
|
5
|
+
*
|
|
6
|
+
* Shows a banner when network is offline or poor.
|
|
7
|
+
*
|
|
8
|
+
* @packageDocumentation
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Indicator status type
|
|
13
|
+
*/
|
|
14
|
+
type IndicatorStatus = 'offline' | 'poor';
|
|
15
|
+
/**
|
|
16
|
+
* Props for OfflineIndicatorHeadless
|
|
17
|
+
*/
|
|
18
|
+
interface OfflineIndicatorHeadlessProps {
|
|
19
|
+
/** Current connection status */
|
|
20
|
+
status: IndicatorStatus;
|
|
21
|
+
/** Whether to show the indicator */
|
|
22
|
+
isVisible: boolean;
|
|
23
|
+
/** Custom offline message */
|
|
24
|
+
offlineMessage?: string;
|
|
25
|
+
/** Custom poor connection message */
|
|
26
|
+
poorMessage?: string;
|
|
27
|
+
/** Custom icon */
|
|
28
|
+
icon?: ReactNode;
|
|
29
|
+
/** Additional CSS class */
|
|
30
|
+
className?: string;
|
|
31
|
+
/** Test ID */
|
|
32
|
+
testId?: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* OfflineIndicatorHeadless - Network status indicator
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```tsx
|
|
39
|
+
* const { isOnline, status } = useOnlineStatus();
|
|
40
|
+
*
|
|
41
|
+
* <OfflineIndicatorHeadless
|
|
42
|
+
* status={status === 'offline' ? 'offline' : 'poor'}
|
|
43
|
+
* isVisible={!isOnline || status === 'poor'}
|
|
44
|
+
* />
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
declare function OfflineIndicatorHeadless({ status, isVisible, offlineMessage, poorMessage, icon, className, testId, }: OfflineIndicatorHeadlessProps): React.ReactElement | null;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* OfflineIndicator CSS
|
|
51
|
+
*
|
|
52
|
+
* Styles for network status indicator.
|
|
53
|
+
*/
|
|
54
|
+
declare const OFFLINE_INDICATOR_CSS = "\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n * OFFLINE INDICATOR\n * \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-offline-indicator {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 8px 16px;\n background: var(--sv-offline-bg, rgba(220, 53, 69, 0.95));\n color: var(--sv-offline-color, #fff);\n font-size: 14px;\n font-weight: 500;\n z-index: var(--sv-z-toast, 1200);\n animation: sv-offline-slide-down 200ms ease-out;\n}\n\n.sv-offline-indicator--poor {\n background: var(--sv-offline-poor-bg, rgba(255, 193, 7, 0.95));\n color: var(--sv-offline-poor-color, #000);\n}\n\n.sv-offline-indicator__icon {\n flex-shrink: 0;\n width: 16px;\n height: 16px;\n}\n\n.sv-offline-indicator__message {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n * ANIMATIONS\n * \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n@keyframes sv-offline-slide-down {\n from {\n transform: translateY(-100%);\n }\n to {\n transform: translateY(0);\n }\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n * REDUCE MOTION\n * \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n@media (prefers-reduced-motion: reduce) {\n .sv-offline-indicator {\n animation: none;\n }\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n * SAFE AREA (Notch devices)\n * \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n@supports (padding-top: env(safe-area-inset-top)) {\n .sv-offline-indicator {\n padding-top: calc(8px + env(safe-area-inset-top));\n }\n}\n";
|
|
55
|
+
|
|
56
|
+
export { type IndicatorStatus, OFFLINE_INDICATOR_CSS, OfflineIndicatorHeadless, type OfflineIndicatorHeadlessProps };
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { injectComponentCSS } from '../../chunk-RMLTPW5S.js';
|
|
2
|
+
import { clsx } from 'clsx';
|
|
3
|
+
import { useInsertionEffect } from 'react';
|
|
4
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
// src/components/OfflineIndicator/OfflineIndicator.css.ts
|
|
7
|
+
var OFFLINE_INDICATOR_CSS = `
|
|
8
|
+
/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
9
|
+
* OFFLINE INDICATOR
|
|
10
|
+
* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */
|
|
11
|
+
|
|
12
|
+
.sv-offline-indicator {
|
|
13
|
+
position: fixed;
|
|
14
|
+
top: 0;
|
|
15
|
+
left: 0;
|
|
16
|
+
right: 0;
|
|
17
|
+
display: flex;
|
|
18
|
+
align-items: center;
|
|
19
|
+
justify-content: center;
|
|
20
|
+
gap: 8px;
|
|
21
|
+
padding: 8px 16px;
|
|
22
|
+
background: var(--sv-offline-bg, rgba(220, 53, 69, 0.95));
|
|
23
|
+
color: var(--sv-offline-color, #fff);
|
|
24
|
+
font-size: 14px;
|
|
25
|
+
font-weight: 500;
|
|
26
|
+
z-index: var(--sv-z-toast, 1200);
|
|
27
|
+
animation: sv-offline-slide-down 200ms ease-out;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.sv-offline-indicator--poor {
|
|
31
|
+
background: var(--sv-offline-poor-bg, rgba(255, 193, 7, 0.95));
|
|
32
|
+
color: var(--sv-offline-poor-color, #000);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.sv-offline-indicator__icon {
|
|
36
|
+
flex-shrink: 0;
|
|
37
|
+
width: 16px;
|
|
38
|
+
height: 16px;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.sv-offline-indicator__message {
|
|
42
|
+
white-space: nowrap;
|
|
43
|
+
overflow: hidden;
|
|
44
|
+
text-overflow: ellipsis;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
48
|
+
* ANIMATIONS
|
|
49
|
+
* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */
|
|
50
|
+
|
|
51
|
+
@keyframes sv-offline-slide-down {
|
|
52
|
+
from {
|
|
53
|
+
transform: translateY(-100%);
|
|
54
|
+
}
|
|
55
|
+
to {
|
|
56
|
+
transform: translateY(0);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
61
|
+
* REDUCE MOTION
|
|
62
|
+
* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */
|
|
63
|
+
|
|
64
|
+
@media (prefers-reduced-motion: reduce) {
|
|
65
|
+
.sv-offline-indicator {
|
|
66
|
+
animation: none;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
71
|
+
* SAFE AREA (Notch devices)
|
|
72
|
+
* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */
|
|
73
|
+
|
|
74
|
+
@supports (padding-top: env(safe-area-inset-top)) {
|
|
75
|
+
.sv-offline-indicator {
|
|
76
|
+
padding-top: calc(8px + env(safe-area-inset-top));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
`;
|
|
80
|
+
var DEFAULT_MESSAGES = {
|
|
81
|
+
offline: "No internet connection",
|
|
82
|
+
poor: "Poor connection"
|
|
83
|
+
};
|
|
84
|
+
function OfflineIcon() {
|
|
85
|
+
return /* @__PURE__ */ jsx(
|
|
86
|
+
"svg",
|
|
87
|
+
{
|
|
88
|
+
className: "sv-offline-indicator__icon",
|
|
89
|
+
width: "16",
|
|
90
|
+
height: "16",
|
|
91
|
+
viewBox: "0 0 24 24",
|
|
92
|
+
fill: "currentColor",
|
|
93
|
+
"aria-hidden": "true",
|
|
94
|
+
children: /* @__PURE__ */ jsx("path", { d: "M23.64 7c-.45-.34-4.93-4-11.64-4-1.5 0-2.89.19-4.15.48L18.18 13.8 23.64 7zM17.04 15.22L3.27 1.44 2 2.72l2.05 2.06C1.91 5.76.59 6.82.36 7L12 21.5l3.07-4.21 4.54 4.54 1.27-1.27-3.84-3.85zM12 4c1.23 0 2.37.14 3.42.36l-3.45 4.74L12 4z" })
|
|
95
|
+
}
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
function PoorConnectionIcon() {
|
|
99
|
+
return /* @__PURE__ */ jsxs(
|
|
100
|
+
"svg",
|
|
101
|
+
{
|
|
102
|
+
className: "sv-offline-indicator__icon",
|
|
103
|
+
width: "16",
|
|
104
|
+
height: "16",
|
|
105
|
+
viewBox: "0 0 24 24",
|
|
106
|
+
fill: "currentColor",
|
|
107
|
+
"aria-hidden": "true",
|
|
108
|
+
children: [
|
|
109
|
+
/* @__PURE__ */ jsx(
|
|
110
|
+
"path",
|
|
111
|
+
{
|
|
112
|
+
d: "M12 3C7.46 3 3.34 4.78.29 7.67c-.18.18-.29.43-.29.71 0 .28.11.53.29.71l11 11c.18.18.43.29.71.29s.53-.11.71-.29l11-11c.18-.18.29-.43.29-.71 0-.28-.11-.53-.29-.71C20.66 4.78 16.54 3 12 3zM2.92 8.38C5.43 6.34 8.59 5 12 5s6.57 1.34 9.08 3.38L12 17.5 2.92 8.38z",
|
|
113
|
+
opacity: "0.5"
|
|
114
|
+
}
|
|
115
|
+
),
|
|
116
|
+
/* @__PURE__ */ jsx("path", { d: "M12 21.5l4.5-6.19c-.93-.76-2.14-1.31-3.5-1.31s-2.57.55-3.5 1.31L12 21.5z" })
|
|
117
|
+
]
|
|
118
|
+
}
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
function OfflineIndicatorHeadless({
|
|
122
|
+
status,
|
|
123
|
+
isVisible,
|
|
124
|
+
offlineMessage,
|
|
125
|
+
poorMessage,
|
|
126
|
+
icon,
|
|
127
|
+
className,
|
|
128
|
+
testId
|
|
129
|
+
}) {
|
|
130
|
+
useInsertionEffect(() => {
|
|
131
|
+
return injectComponentCSS("offline-indicator", OFFLINE_INDICATOR_CSS);
|
|
132
|
+
}, []);
|
|
133
|
+
if (!isVisible) return null;
|
|
134
|
+
const message = status === "offline" ? offlineMessage ?? DEFAULT_MESSAGES.offline : poorMessage ?? DEFAULT_MESSAGES.poor;
|
|
135
|
+
const defaultIcon = status === "offline" ? /* @__PURE__ */ jsx(OfflineIcon, {}) : /* @__PURE__ */ jsx(PoorConnectionIcon, {});
|
|
136
|
+
return /* @__PURE__ */ jsxs(
|
|
137
|
+
"div",
|
|
138
|
+
{
|
|
139
|
+
role: "alert",
|
|
140
|
+
"aria-live": "assertive",
|
|
141
|
+
className: clsx("sv-offline-indicator", `sv-offline-indicator--${status}`, className),
|
|
142
|
+
"data-testid": testId,
|
|
143
|
+
children: [
|
|
144
|
+
icon ?? defaultIcon,
|
|
145
|
+
/* @__PURE__ */ jsx("span", { className: "sv-offline-indicator__message", children: message })
|
|
146
|
+
]
|
|
147
|
+
}
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export { OFFLINE_INDICATOR_CSS, OfflineIndicatorHeadless };
|