@lindaui/blocks 0.3.0 → 0.4.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/dist/audio-player.d.ts +9 -0
- package/dist/audio-player.d.ts.map +1 -0
- package/dist/audio-player.js +73 -0
- package/dist/chat-avatar.d.ts +15 -0
- package/dist/chat-avatar.d.ts.map +1 -0
- package/dist/chat-avatar.js +42 -0
- package/dist/chat-date-divider.d.ts +6 -0
- package/dist/chat-date-divider.d.ts.map +1 -0
- package/dist/chat-date-divider.js +18 -0
- package/dist/chat-header.d.ts +9 -0
- package/dist/chat-header.d.ts.map +1 -0
- package/dist/chat-header.js +30 -0
- package/dist/chat-layout.d.ts +12 -0
- package/dist/chat-layout.d.ts.map +1 -0
- package/dist/chat-layout.js +24 -0
- package/dist/chat-time-divider.d.ts +6 -0
- package/dist/chat-time-divider.d.ts.map +1 -0
- package/dist/chat-time-divider.js +16 -0
- package/dist/chat-types.d.ts +37 -0
- package/dist/chat-types.d.ts.map +1 -0
- package/dist/chat-types.js +1 -0
- package/dist/chat-types.test.d.ts +2 -0
- package/dist/chat-types.test.d.ts.map +1 -0
- package/dist/conversation-list-item.d.ts +10 -0
- package/dist/conversation-list-item.d.ts.map +1 -0
- package/dist/conversation-list-item.js +53 -0
- package/dist/conversation-list.d.ts +16 -0
- package/dist/conversation-list.d.ts.map +1 -0
- package/dist/conversation-list.js +45 -0
- package/dist/conversation-thread.d.ts +11 -0
- package/dist/conversation-thread.d.ts.map +1 -0
- package/dist/conversation-thread.js +62 -0
- package/dist/empty-chat-view.d.ts +8 -0
- package/dist/empty-chat-view.d.ts.map +1 -0
- package/dist/empty-chat-view.js +28 -0
- package/dist/entity-health-card.d.ts +18 -0
- package/dist/entity-health-card.d.ts.map +1 -0
- package/dist/entity-health-card.js +47 -0
- package/dist/fetching-indicator.d.ts +6 -0
- package/dist/fetching-indicator.d.ts.map +1 -0
- package/dist/fetching-indicator.js +20 -0
- package/dist/message-bubble.d.ts +7 -0
- package/dist/message-bubble.d.ts.map +1 -0
- package/dist/message-bubble.js +83 -0
- package/dist/message-composer.d.ts +11 -0
- package/dist/message-composer.d.ts.map +1 -0
- package/dist/message-composer.js +41 -0
- package/dist/stat-card.d.ts +3 -1
- package/dist/stat-card.d.ts.map +1 -1
- package/dist/stat-card.js +20 -7
- package/dist/time-range-picker.d.ts +26 -0
- package/dist/time-range-picker.d.ts.map +1 -0
- package/dist/time-range-picker.js +86 -0
- package/llms.txt +62 -1
- package/package.json +73 -9
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface AudioPlayerProps {
|
|
2
|
+
src: string;
|
|
3
|
+
durationSeconds?: number;
|
|
4
|
+
playLabel?: string;
|
|
5
|
+
pauseLabel?: string;
|
|
6
|
+
}
|
|
7
|
+
/** Reproductor de nota de voz genérico: play/pause + waveform estática + duración. */
|
|
8
|
+
export declare function AudioPlayer({ src, durationSeconds, playLabel, pauseLabel, }: AudioPlayerProps): import("react").JSX.Element;
|
|
9
|
+
//# sourceMappingURL=audio-player.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audio-player.d.ts","sourceRoot":"","sources":["../src/audio-player.tsx"],"names":[],"mappings":"AAKA,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAeD,sFAAsF;AACtF,wBAAgB,WAAW,CAAC,EAC1B,GAAG,EACH,eAAe,EACf,SAAwB,EACxB,UAAqB,GACtB,EAAE,gBAAgB,+BA0ClB"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { useRef, useState } from 'react';
|
|
4
|
+
import { Pause, Play } from 'lucide-react';
|
|
5
|
+
import { IconButton } from '@lindaui/ui/icon-button';
|
|
6
|
+
|
|
7
|
+
function formatDuration(seconds) {
|
|
8
|
+
const m = Math.floor(seconds / 60);
|
|
9
|
+
const s = Math.floor(seconds % 60);
|
|
10
|
+
return `${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`;
|
|
11
|
+
}
|
|
12
|
+
// Alturas deterministas (mismo seed que recording-overlay) — barra estática,
|
|
13
|
+
// no una waveform real del audio.
|
|
14
|
+
const BAR_HEIGHTS = Array.from({
|
|
15
|
+
length: 24
|
|
16
|
+
}, (_, i)=>{
|
|
17
|
+
const seed = Math.abs(Math.sin(i * 12.9898) * 43758.5453) % 1;
|
|
18
|
+
return Math.max(20, Math.round((0.25 + seed * 0.75) * 100));
|
|
19
|
+
});
|
|
20
|
+
/** Reproductor de nota de voz genérico: play/pause + waveform estática + duración. */ function AudioPlayer({ src, durationSeconds, playLabel = "Reproducir", pauseLabel = "Pausar" }) {
|
|
21
|
+
const audioRef = useRef(null);
|
|
22
|
+
const [isPlaying, setIsPlaying] = useState(false);
|
|
23
|
+
const [currentTime, setCurrentTime] = useState(0);
|
|
24
|
+
const toggle = ()=>{
|
|
25
|
+
const audio = audioRef.current;
|
|
26
|
+
if (!audio) return;
|
|
27
|
+
if (isPlaying) audio.pause();
|
|
28
|
+
else void audio.play();
|
|
29
|
+
};
|
|
30
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
31
|
+
className: "flex items-center gap-2.5 rounded-full bg-secondary px-2 py-1.5",
|
|
32
|
+
children: [
|
|
33
|
+
/*#__PURE__*/ jsx("audio", {
|
|
34
|
+
ref: audioRef,
|
|
35
|
+
src: src,
|
|
36
|
+
onPlay: ()=>setIsPlaying(true),
|
|
37
|
+
onPause: ()=>setIsPlaying(false),
|
|
38
|
+
onEnded: ()=>setIsPlaying(false),
|
|
39
|
+
onTimeUpdate: (e)=>setCurrentTime(e.currentTarget.currentTime),
|
|
40
|
+
children: /*#__PURE__*/ jsx("track", {
|
|
41
|
+
kind: "captions"
|
|
42
|
+
})
|
|
43
|
+
}),
|
|
44
|
+
/*#__PURE__*/ jsx(IconButton, {
|
|
45
|
+
"aria-label": isPlaying ? pauseLabel : playLabel,
|
|
46
|
+
onPress: toggle,
|
|
47
|
+
variant: "ghost",
|
|
48
|
+
size: "sm",
|
|
49
|
+
children: isPlaying ? /*#__PURE__*/ jsx(Pause, {
|
|
50
|
+
className: "size-4"
|
|
51
|
+
}) : /*#__PURE__*/ jsx(Play, {
|
|
52
|
+
className: "size-4"
|
|
53
|
+
})
|
|
54
|
+
}),
|
|
55
|
+
/*#__PURE__*/ jsx("div", {
|
|
56
|
+
className: "flex h-6 flex-1 items-end gap-[2px]",
|
|
57
|
+
"aria-hidden": "true",
|
|
58
|
+
children: BAR_HEIGHTS.map((h, i)=>/*#__PURE__*/ jsx("span", {
|
|
59
|
+
className: "w-[2.5px] rounded-full bg-primary/60",
|
|
60
|
+
style: {
|
|
61
|
+
height: `${h}%`
|
|
62
|
+
}
|
|
63
|
+
}, i))
|
|
64
|
+
}),
|
|
65
|
+
/*#__PURE__*/ jsx("span", {
|
|
66
|
+
className: "font-mono text-[11px] tabular-nums text-muted-foreground",
|
|
67
|
+
children: formatDuration(durationSeconds ?? currentTime)
|
|
68
|
+
})
|
|
69
|
+
]
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export { AudioPlayer };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type ChatAvatarSize = "sm" | "md" | "lg";
|
|
2
|
+
export interface ChatAvatarProps {
|
|
3
|
+
src?: string;
|
|
4
|
+
name: string;
|
|
5
|
+
size?: ChatAvatarSize;
|
|
6
|
+
/** Se dispara cuando `src` falla en cargar (además del fallback automático a iniciales). */
|
|
7
|
+
onError?: () => void;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Avatar de chat con fallback a iniciales. Bespoke (no compone
|
|
11
|
+
* `@lindaui/ui/avatar`): ese wrapper solo expone el Root de HeroUI, sin
|
|
12
|
+
* `Avatar.Image`/`Avatar.Fallback` — no alcanza para un fallback-on-error real.
|
|
13
|
+
*/
|
|
14
|
+
export declare function ChatAvatar({ src, name, size, onError }: ChatAvatarProps): import("react").JSX.Element;
|
|
15
|
+
//# sourceMappingURL=chat-avatar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-avatar.d.ts","sourceRoot":"","sources":["../src/chat-avatar.tsx"],"names":[],"mappings":"AAGA,MAAM,MAAM,cAAc,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEhD,MAAM,WAAW,eAAe;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,4FAA4F;IAC5F,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAeD;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,IAAW,EAAE,OAAO,EAAE,EAAE,eAAe,+BAyB9E"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
|
|
5
|
+
const sizeClasses = {
|
|
6
|
+
sm: "size-8 text-xs",
|
|
7
|
+
md: "size-10 text-sm",
|
|
8
|
+
lg: "size-12 text-base"
|
|
9
|
+
};
|
|
10
|
+
function initials(name) {
|
|
11
|
+
const parts = name.trim().split(/\s+/).filter(Boolean);
|
|
12
|
+
if (parts.length === 0) return "?";
|
|
13
|
+
if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase();
|
|
14
|
+
return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Avatar de chat con fallback a iniciales. Bespoke (no compone
|
|
18
|
+
* `@lindaui/ui/avatar`): ese wrapper solo expone el Root de HeroUI, sin
|
|
19
|
+
* `Avatar.Image`/`Avatar.Fallback` — no alcanza para un fallback-on-error real.
|
|
20
|
+
*/ function ChatAvatar({ src, name, size = "md", onError }) {
|
|
21
|
+
const [broken, setBroken] = useState(false);
|
|
22
|
+
const showImage = src != null && !broken;
|
|
23
|
+
return /*#__PURE__*/ jsx("div", {
|
|
24
|
+
role: "img",
|
|
25
|
+
"aria-label": name,
|
|
26
|
+
className: `grid shrink-0 place-items-center overflow-hidden rounded-full bg-secondary font-medium text-secondary-foreground ${sizeClasses[size]}`,
|
|
27
|
+
children: showImage ? /*#__PURE__*/ jsx("img", {
|
|
28
|
+
src: src,
|
|
29
|
+
alt: "",
|
|
30
|
+
className: "h-full w-full object-cover",
|
|
31
|
+
onError: ()=>{
|
|
32
|
+
setBroken(true);
|
|
33
|
+
onError?.();
|
|
34
|
+
}
|
|
35
|
+
}) : /*#__PURE__*/ jsx("span", {
|
|
36
|
+
"aria-hidden": "true",
|
|
37
|
+
children: initials(name)
|
|
38
|
+
})
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export { ChatAvatar };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export interface ChatDateDividerProps {
|
|
2
|
+
date: Date | number | string;
|
|
3
|
+
}
|
|
4
|
+
/** Divider centrado de día ("Hoy"/"Ayer"/fecha corta) para timelines de chat. */
|
|
5
|
+
export declare function ChatDateDivider({ date }: ChatDateDividerProps): import("react").JSX.Element;
|
|
6
|
+
//# sourceMappingURL=chat-date-divider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-date-divider.d.ts","sourceRoot":"","sources":["../src/chat-date-divider.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;CAC9B;AAED,iFAAiF;AACjF,wBAAgB,eAAe,CAAC,EAAE,IAAI,EAAE,EAAE,oBAAoB,+BAS7D"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { formatRelativeTime } from '@lindaui/ui/date';
|
|
4
|
+
|
|
5
|
+
/** Divider centrado de día ("Hoy"/"Ayer"/fecha corta) para timelines de chat. */ function ChatDateDivider({ date }) {
|
|
6
|
+
const label = formatRelativeTime(date);
|
|
7
|
+
return /*#__PURE__*/ jsx("div", {
|
|
8
|
+
className: "my-3 flex items-center justify-center",
|
|
9
|
+
role: "separator",
|
|
10
|
+
"aria-label": label,
|
|
11
|
+
children: /*#__PURE__*/ jsx("span", {
|
|
12
|
+
className: "rounded-full bg-secondary px-3 py-1 text-xs font-medium text-secondary-foreground",
|
|
13
|
+
children: label
|
|
14
|
+
})
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { ChatDateDivider };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
export interface ChatHeaderProps {
|
|
3
|
+
avatar?: ReactNode;
|
|
4
|
+
title: ReactNode;
|
|
5
|
+
subtitle?: ReactNode;
|
|
6
|
+
actions?: ReactNode;
|
|
7
|
+
}
|
|
8
|
+
export declare function ChatHeader({ avatar, title, subtitle, actions }: ChatHeaderProps): import("react").JSX.Element;
|
|
9
|
+
//# sourceMappingURL=chat-header.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-header.d.ts","sourceRoot":"","sources":["../src/chat-header.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,KAAK,EAAE,SAAS,CAAC;IACjB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,OAAO,CAAC,EAAE,SAAS,CAAC;CACrB;AAED,wBAAgB,UAAU,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,eAAe,+BAa/E"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
|
|
4
|
+
function ChatHeader({ avatar, title, subtitle, actions }) {
|
|
5
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
6
|
+
className: "flex items-center gap-3 border-b border-border bg-card px-4 py-3",
|
|
7
|
+
children: [
|
|
8
|
+
avatar,
|
|
9
|
+
/*#__PURE__*/ jsxs("div", {
|
|
10
|
+
className: "min-w-0 flex-1",
|
|
11
|
+
children: [
|
|
12
|
+
/*#__PURE__*/ jsx("div", {
|
|
13
|
+
className: "truncate text-sm font-semibold",
|
|
14
|
+
children: title
|
|
15
|
+
}),
|
|
16
|
+
subtitle != null && /*#__PURE__*/ jsx("div", {
|
|
17
|
+
className: "truncate text-xs text-muted-foreground",
|
|
18
|
+
children: subtitle
|
|
19
|
+
})
|
|
20
|
+
]
|
|
21
|
+
}),
|
|
22
|
+
actions != null && /*#__PURE__*/ jsx("div", {
|
|
23
|
+
className: "flex shrink-0 items-center gap-1",
|
|
24
|
+
children: actions
|
|
25
|
+
})
|
|
26
|
+
]
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export { ChatHeader };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
export type ChatLayoutPanel = "sidebar" | "main" | "detail";
|
|
3
|
+
export interface ChatLayoutProps {
|
|
4
|
+
sidebar: ReactNode;
|
|
5
|
+
main: ReactNode;
|
|
6
|
+
detail?: ReactNode;
|
|
7
|
+
/** Panel visible en mobile (un solo panel a la vez). Default "sidebar". */
|
|
8
|
+
activePanel?: ChatLayoutPanel;
|
|
9
|
+
}
|
|
10
|
+
/** Shell responsive de 3 columnas (sidebar/main/detail); mobile-first, un panel a la vez. */
|
|
11
|
+
export declare function ChatLayout({ sidebar, main, detail, activePanel }: ChatLayoutProps): import("react").JSX.Element;
|
|
12
|
+
//# sourceMappingURL=chat-layout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-layout.d.ts","sourceRoot":"","sources":["../src/chat-layout.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE5D,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,SAAS,CAAC;IACnB,IAAI,EAAE,SAAS,CAAC;IAChB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,2EAA2E;IAC3E,WAAW,CAAC,EAAE,eAAe,CAAC;CAC/B;AAED,6FAA6F;AAC7F,wBAAgB,UAAU,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,WAAuB,EAAE,EAAE,eAAe,+BA0B7F"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
|
|
4
|
+
/** Shell responsive de 3 columnas (sidebar/main/detail); mobile-first, un panel a la vez. */ function ChatLayout({ sidebar, main, detail, activePanel = "sidebar" }) {
|
|
5
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
6
|
+
className: "flex h-full min-h-0 w-full overflow-hidden",
|
|
7
|
+
children: [
|
|
8
|
+
/*#__PURE__*/ jsx("div", {
|
|
9
|
+
className: `w-full shrink-0 border-r border-border sm:block sm:w-80 ${activePanel === "sidebar" ? "block" : "hidden sm:block"}`,
|
|
10
|
+
children: sidebar
|
|
11
|
+
}),
|
|
12
|
+
/*#__PURE__*/ jsx("div", {
|
|
13
|
+
className: `min-w-0 flex-1 sm:block ${activePanel === "main" ? "block" : "hidden sm:block"}`,
|
|
14
|
+
children: main
|
|
15
|
+
}),
|
|
16
|
+
detail != null && /*#__PURE__*/ jsx("div", {
|
|
17
|
+
className: `w-full shrink-0 border-l border-border lg:block lg:w-96 ${activePanel === "detail" ? "block" : "hidden lg:block"}`,
|
|
18
|
+
children: detail
|
|
19
|
+
})
|
|
20
|
+
]
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export { ChatLayout };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export interface ChatTimeDividerProps {
|
|
2
|
+
label: string;
|
|
3
|
+
}
|
|
4
|
+
/** Header sticky de grupo horario (variante más chica que {@link ChatDateDivider}). */
|
|
5
|
+
export declare function ChatTimeDivider({ label }: ChatTimeDividerProps): import("react").JSX.Element;
|
|
6
|
+
//# sourceMappingURL=chat-time-divider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-time-divider.d.ts","sourceRoot":"","sources":["../src/chat-time-divider.tsx"],"names":[],"mappings":"AAEA,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;CACf;AAED,uFAAuF;AACvF,wBAAgB,eAAe,CAAC,EAAE,KAAK,EAAE,EAAE,oBAAoB,+BAY9D"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx } from 'react/jsx-runtime';
|
|
3
|
+
|
|
4
|
+
/** Header sticky de grupo horario (variante más chica que {@link ChatDateDivider}). */ function ChatTimeDivider({ label }) {
|
|
5
|
+
return /*#__PURE__*/ jsx("div", {
|
|
6
|
+
className: "sticky top-0 z-10 flex justify-center bg-card/80 py-1.5 backdrop-blur",
|
|
7
|
+
role: "separator",
|
|
8
|
+
"aria-label": label,
|
|
9
|
+
children: /*#__PURE__*/ jsx("span", {
|
|
10
|
+
className: "rounded-full bg-secondary px-2.5 py-0.5 text-[11px] font-medium text-secondary-foreground",
|
|
11
|
+
children: label
|
|
12
|
+
})
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export { ChatTimeDivider };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tipos compartidos por la familia `chat-*`. Agnósticos de dominio — el
|
|
3
|
+
* consumidor mapea su shape real (mensajes de WhatsApp, tickets, etc.) a
|
|
4
|
+
* estos antes de pasarlos a los blocks.
|
|
5
|
+
*/
|
|
6
|
+
export type MessageSide = "incoming" | "outgoing";
|
|
7
|
+
export type MessageStatus = "sending" | "sent" | "delivered" | "read" | "failed";
|
|
8
|
+
export type GenericMessageMedia = {
|
|
9
|
+
kind: "image";
|
|
10
|
+
url: string;
|
|
11
|
+
alt?: string;
|
|
12
|
+
} | {
|
|
13
|
+
kind: "audio";
|
|
14
|
+
url: string;
|
|
15
|
+
durationSeconds?: number;
|
|
16
|
+
} | {
|
|
17
|
+
kind: "pdf";
|
|
18
|
+
url: string;
|
|
19
|
+
name?: string;
|
|
20
|
+
};
|
|
21
|
+
export interface GenericMessage {
|
|
22
|
+
id: string;
|
|
23
|
+
side: MessageSide;
|
|
24
|
+
text?: string;
|
|
25
|
+
media?: GenericMessageMedia;
|
|
26
|
+
sentAt: Date | number | string;
|
|
27
|
+
status?: MessageStatus;
|
|
28
|
+
}
|
|
29
|
+
export interface ConversationSummary {
|
|
30
|
+
id: string;
|
|
31
|
+
title: string;
|
|
32
|
+
subtitle?: string;
|
|
33
|
+
avatarUrl?: string;
|
|
34
|
+
lastMessageAt?: Date | number | string;
|
|
35
|
+
unreadCount?: number;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=chat-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-types.d.ts","sourceRoot":"","sources":["../src/chat-types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,UAAU,CAAC;AAElD,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEjF,MAAM,MAAM,mBAAmB,GAC3B;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5C;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,GACxD;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,mBAAmB,CAAC;IAC5B,MAAM,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;IAC/B,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-types.test.d.ts","sourceRoot":"","sources":["../src/chat-types.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { ConversationSummary } from "./chat-types.js";
|
|
3
|
+
export interface ConversationListItemProps {
|
|
4
|
+
conversation: ConversationSummary;
|
|
5
|
+
selected?: boolean;
|
|
6
|
+
onSelect?: () => void;
|
|
7
|
+
trailing?: ReactNode;
|
|
8
|
+
}
|
|
9
|
+
export declare function ConversationListItem({ conversation, selected, onSelect, trailing, }: ConversationListItemProps): import("react").JSX.Element;
|
|
10
|
+
//# sourceMappingURL=conversation-list-item.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversation-list-item.d.ts","sourceRoot":"","sources":["../src/conversation-list-item.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAE3D,MAAM,WAAW,yBAAyB;IACxC,YAAY,EAAE,mBAAmB,CAAC;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED,wBAAgB,oBAAoB,CAAC,EACnC,YAAY,EACZ,QAAgB,EAChB,QAAQ,EACR,QAAQ,GACT,EAAE,yBAAyB,+BAkC3B"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { formatRelativeTime } from '@lindaui/ui/date';
|
|
4
|
+
import { ChatAvatar } from './chat-avatar.js';
|
|
5
|
+
|
|
6
|
+
function ConversationListItem({ conversation, selected = false, onSelect, trailing }) {
|
|
7
|
+
return /*#__PURE__*/ jsxs("button", {
|
|
8
|
+
type: "button",
|
|
9
|
+
"aria-pressed": selected,
|
|
10
|
+
onClick: onSelect,
|
|
11
|
+
className: `flex w-full items-center gap-3 border-b border-border px-3 py-3 text-left font-[inherit] text-[inherit] transition-colors ${selected ? "bg-primary/5" : "bg-card hover:bg-accent/50"}`,
|
|
12
|
+
children: [
|
|
13
|
+
/*#__PURE__*/ jsx(ChatAvatar, {
|
|
14
|
+
name: conversation.title,
|
|
15
|
+
src: conversation.avatarUrl
|
|
16
|
+
}),
|
|
17
|
+
/*#__PURE__*/ jsxs("div", {
|
|
18
|
+
className: "min-w-0 flex-1",
|
|
19
|
+
children: [
|
|
20
|
+
/*#__PURE__*/ jsxs("div", {
|
|
21
|
+
className: "flex items-center justify-between gap-2",
|
|
22
|
+
children: [
|
|
23
|
+
/*#__PURE__*/ jsx("span", {
|
|
24
|
+
className: "truncate text-sm font-semibold",
|
|
25
|
+
children: conversation.title
|
|
26
|
+
}),
|
|
27
|
+
conversation.lastMessageAt != null && /*#__PURE__*/ jsx("span", {
|
|
28
|
+
className: "shrink-0 text-[11px] text-muted-foreground",
|
|
29
|
+
children: formatRelativeTime(conversation.lastMessageAt)
|
|
30
|
+
})
|
|
31
|
+
]
|
|
32
|
+
}),
|
|
33
|
+
/*#__PURE__*/ jsxs("div", {
|
|
34
|
+
className: "flex items-center justify-between gap-2",
|
|
35
|
+
children: [
|
|
36
|
+
conversation.subtitle != null && /*#__PURE__*/ jsx("span", {
|
|
37
|
+
className: "truncate text-xs text-muted-foreground",
|
|
38
|
+
children: conversation.subtitle
|
|
39
|
+
}),
|
|
40
|
+
!!conversation.unreadCount && /*#__PURE__*/ jsx("span", {
|
|
41
|
+
className: "grid size-5 shrink-0 place-items-center rounded-full bg-primary text-[10px] font-semibold text-primary-foreground",
|
|
42
|
+
children: conversation.unreadCount
|
|
43
|
+
})
|
|
44
|
+
]
|
|
45
|
+
})
|
|
46
|
+
]
|
|
47
|
+
}),
|
|
48
|
+
trailing
|
|
49
|
+
]
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export { ConversationListItem };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { ConversationSummary } from "./chat-types.js";
|
|
3
|
+
export interface ConversationListProps {
|
|
4
|
+
conversations: ConversationSummary[];
|
|
5
|
+
selectedId?: string;
|
|
6
|
+
onSelect?: (id: string) => void;
|
|
7
|
+
searchValue?: string;
|
|
8
|
+
onSearchChange?: (value: string) => void;
|
|
9
|
+
searchLabel?: string;
|
|
10
|
+
searchPlaceholder?: string;
|
|
11
|
+
loading?: boolean;
|
|
12
|
+
emptyContent?: ReactNode;
|
|
13
|
+
filters?: ReactNode;
|
|
14
|
+
}
|
|
15
|
+
export declare function ConversationList({ conversations, selectedId, onSelect, searchValue, onSearchChange, searchLabel, searchPlaceholder, loading, emptyContent, filters, }: ConversationListProps): import("react").JSX.Element;
|
|
16
|
+
//# sourceMappingURL=conversation-list.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversation-list.d.ts","sourceRoot":"","sources":["../src/conversation-list.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAKvC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAE3D,MAAM,WAAW,qBAAqB;IACpC,aAAa,EAAE,mBAAmB,EAAE,CAAC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,OAAO,CAAC,EAAE,SAAS,CAAC;CACrB;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,aAAa,EACb,UAAU,EACV,QAAQ,EACR,WAAW,EACX,cAAc,EACd,WAAsB,EACtB,iBAA0C,EAC1C,OAAe,EACf,YAAY,EACZ,OAAO,GACR,EAAE,qBAAqB,+BAkCvB"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { SearchField } from '@lindaui/ui/search-field';
|
|
4
|
+
import { ScrollShadow } from '@lindaui/ui/scroll-shadow';
|
|
5
|
+
import { Spinner } from '@lindaui/ui/spinner';
|
|
6
|
+
import { ConversationListItem } from './conversation-list-item.js';
|
|
7
|
+
|
|
8
|
+
function ConversationList({ conversations, selectedId, onSelect, searchValue, onSearchChange, searchLabel = "Buscar", searchPlaceholder = "Buscar conversación…", loading = false, emptyContent, filters }) {
|
|
9
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
10
|
+
className: "flex h-full flex-col",
|
|
11
|
+
children: [
|
|
12
|
+
/*#__PURE__*/ jsx("div", {
|
|
13
|
+
className: "border-b border-border p-3",
|
|
14
|
+
children: /*#__PURE__*/ jsx(SearchField, {
|
|
15
|
+
"aria-label": searchLabel,
|
|
16
|
+
placeholder: searchPlaceholder,
|
|
17
|
+
value: searchValue,
|
|
18
|
+
onChange: onSearchChange
|
|
19
|
+
})
|
|
20
|
+
}),
|
|
21
|
+
filters != null && /*#__PURE__*/ jsx("div", {
|
|
22
|
+
className: "border-b border-border px-3 py-2",
|
|
23
|
+
children: filters
|
|
24
|
+
}),
|
|
25
|
+
/*#__PURE__*/ jsx(ScrollShadow, {
|
|
26
|
+
className: "flex-1",
|
|
27
|
+
children: loading ? /*#__PURE__*/ jsx("div", {
|
|
28
|
+
className: "flex items-center justify-center p-8",
|
|
29
|
+
children: /*#__PURE__*/ jsx(Spinner, {
|
|
30
|
+
"aria-label": "Cargando"
|
|
31
|
+
})
|
|
32
|
+
}) : conversations.length === 0 ? /*#__PURE__*/ jsx("div", {
|
|
33
|
+
className: "p-8 text-center text-sm text-muted-foreground",
|
|
34
|
+
children: emptyContent ?? "Sin conversaciones"
|
|
35
|
+
}) : conversations.map((c)=>/*#__PURE__*/ jsx(ConversationListItem, {
|
|
36
|
+
conversation: c,
|
|
37
|
+
selected: c.id === selectedId,
|
|
38
|
+
onSelect: ()=>onSelect?.(c.id)
|
|
39
|
+
}, c.id))
|
|
40
|
+
})
|
|
41
|
+
]
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export { ConversationList };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { GenericMessage } from "./chat-types.js";
|
|
2
|
+
export interface ConversationThreadProps {
|
|
3
|
+
messages: GenericMessage[];
|
|
4
|
+
loading?: boolean;
|
|
5
|
+
onImageClick?: (url: string) => void;
|
|
6
|
+
emptyTitle?: string;
|
|
7
|
+
emptyDescription?: string;
|
|
8
|
+
}
|
|
9
|
+
/** Timeline scrolleable con auto-scroll al último mensaje + agrupado por día. */
|
|
10
|
+
export declare function ConversationThread({ messages, loading, onImageClick, emptyTitle, emptyDescription, }: ConversationThreadProps): import("react").JSX.Element;
|
|
11
|
+
//# sourceMappingURL=conversation-thread.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversation-thread.d.ts","sourceRoot":"","sources":["../src/conversation-thread.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,iFAAiF;AACjF,wBAAgB,kBAAkB,CAAC,EACjC,QAAQ,EACR,OAAe,EACf,YAAY,EACZ,UAA2B,EAC3B,gBAAgB,GACjB,EAAE,uBAAuB,+BAsCzB"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
|
+
import { useRef, useEffect } from 'react';
|
|
4
|
+
import { ScrollShadow } from '@lindaui/ui/scroll-shadow';
|
|
5
|
+
import { Spinner } from '@lindaui/ui/spinner';
|
|
6
|
+
import { groupByDay } from '@lindaui/ui/time-grouping';
|
|
7
|
+
import { ChatDateDivider } from './chat-date-divider.js';
|
|
8
|
+
import { MessageBubble } from './message-bubble.js';
|
|
9
|
+
import { EmptyChatView } from './empty-chat-view.js';
|
|
10
|
+
|
|
11
|
+
/** Timeline scrolleable con auto-scroll al último mensaje + agrupado por día. */ function ConversationThread({ messages, loading = false, onImageClick, emptyTitle = "Sin mensajes", emptyDescription }) {
|
|
12
|
+
const bottomRef = useRef(null);
|
|
13
|
+
useEffect(()=>{
|
|
14
|
+
bottomRef.current?.scrollIntoView({
|
|
15
|
+
block: "end"
|
|
16
|
+
});
|
|
17
|
+
}, [
|
|
18
|
+
messages.length
|
|
19
|
+
]);
|
|
20
|
+
if (loading) {
|
|
21
|
+
return /*#__PURE__*/ jsx("div", {
|
|
22
|
+
className: "flex h-full items-center justify-center",
|
|
23
|
+
children: /*#__PURE__*/ jsx(Spinner, {
|
|
24
|
+
"aria-label": "Cargando mensajes"
|
|
25
|
+
})
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
if (messages.length === 0) {
|
|
29
|
+
return /*#__PURE__*/ jsx(EmptyChatView, {
|
|
30
|
+
title: emptyTitle,
|
|
31
|
+
description: emptyDescription
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
const groups = groupByDay(messages, (m)=>m.sentAt);
|
|
35
|
+
return /*#__PURE__*/ jsx(ScrollShadow, {
|
|
36
|
+
className: "h-full",
|
|
37
|
+
children: /*#__PURE__*/ jsxs("div", {
|
|
38
|
+
className: "flex flex-col gap-1 p-4",
|
|
39
|
+
children: [
|
|
40
|
+
groups.map((group)=>/*#__PURE__*/ jsxs("div", {
|
|
41
|
+
children: [
|
|
42
|
+
/*#__PURE__*/ jsx(ChatDateDivider, {
|
|
43
|
+
date: group.items[0].sentAt
|
|
44
|
+
}),
|
|
45
|
+
/*#__PURE__*/ jsx("div", {
|
|
46
|
+
className: "flex flex-col gap-1.5",
|
|
47
|
+
children: group.items.map((message)=>/*#__PURE__*/ jsx(MessageBubble, {
|
|
48
|
+
message: message,
|
|
49
|
+
onImageClick: onImageClick
|
|
50
|
+
}, message.id))
|
|
51
|
+
})
|
|
52
|
+
]
|
|
53
|
+
}, group.key)),
|
|
54
|
+
/*#__PURE__*/ jsx("div", {
|
|
55
|
+
ref: bottomRef
|
|
56
|
+
})
|
|
57
|
+
]
|
|
58
|
+
})
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export { ConversationThread };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
export interface EmptyChatViewProps {
|
|
3
|
+
title?: string;
|
|
4
|
+
description?: ReactNode;
|
|
5
|
+
icon?: ReactNode;
|
|
6
|
+
}
|
|
7
|
+
export declare function EmptyChatView({ title, description, icon, }: EmptyChatViewProps): import("react").JSX.Element;
|
|
8
|
+
//# sourceMappingURL=empty-chat-view.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"empty-chat-view.d.ts","sourceRoot":"","sources":["../src/empty-chat-view.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AAED,wBAAgB,aAAa,CAAC,EAC5B,KAAgC,EAChC,WAAW,EACX,IAAI,GACL,EAAE,kBAAkB,+BAUpB"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { MessageCircle } from 'lucide-react';
|
|
4
|
+
|
|
5
|
+
function EmptyChatView({ title = "Elegí una conversación", description, icon }) {
|
|
6
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
7
|
+
className: "flex h-full flex-col items-center justify-center gap-3 p-8 text-center text-muted-foreground",
|
|
8
|
+
children: [
|
|
9
|
+
/*#__PURE__*/ jsx("div", {
|
|
10
|
+
className: "grid size-14 place-items-center rounded-full bg-secondary",
|
|
11
|
+
children: icon ?? /*#__PURE__*/ jsx(MessageCircle, {
|
|
12
|
+
className: "size-6",
|
|
13
|
+
"aria-hidden": "true"
|
|
14
|
+
})
|
|
15
|
+
}),
|
|
16
|
+
/*#__PURE__*/ jsx("p", {
|
|
17
|
+
className: "text-sm font-medium text-foreground",
|
|
18
|
+
children: title
|
|
19
|
+
}),
|
|
20
|
+
description != null && /*#__PURE__*/ jsx("p", {
|
|
21
|
+
className: "max-w-xs text-xs",
|
|
22
|
+
children: description
|
|
23
|
+
})
|
|
24
|
+
]
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export { EmptyChatView };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
export type EntityHealthStatus = "default" | "success" | "warning" | "danger" | "info";
|
|
3
|
+
export interface EntityHealthItem {
|
|
4
|
+
id: string;
|
|
5
|
+
label: string;
|
|
6
|
+
value: ReactNode;
|
|
7
|
+
status?: EntityHealthStatus;
|
|
8
|
+
statusLabel?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface EntityHealthCardProps {
|
|
11
|
+
title: ReactNode;
|
|
12
|
+
description?: ReactNode;
|
|
13
|
+
items: EntityHealthItem[];
|
|
14
|
+
emptyLabel?: string;
|
|
15
|
+
}
|
|
16
|
+
/** Lista de salud de entidades genérica (ex-GymHealthCard, generalizado). */
|
|
17
|
+
export declare function EntityHealthCard({ title, description, items, emptyLabel, }: EntityHealthCardProps): import("react").JSX.Element;
|
|
18
|
+
//# sourceMappingURL=entity-health-card.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entity-health-card.d.ts","sourceRoot":"","sources":["../src/entity-health-card.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAKvC,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEvF,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,SAAS,CAAC;IACjB,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,6EAA6E;AAC7E,wBAAgB,gBAAgB,CAAC,EAC/B,KAAK,EACL,WAAW,EACX,KAAK,EACL,UAAwB,GACzB,EAAE,qBAAqB,+BAuBvB"}
|