@geomak/ui 6.29.1 → 6.30.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/index.cjs +23 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +24 -17
- package/dist/index.js.map +1 -1
- package/dist/styles.css +36 -11
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1381,6 +1381,8 @@ interface ChatProps {
|
|
|
1381
1381
|
disabled?: boolean;
|
|
1382
1382
|
/** Hide the composer entirely (read-only transcript). */
|
|
1383
1383
|
hideComposer?: boolean;
|
|
1384
|
+
/** Shows a transcript skeleton (use while loading history, before messages arrive). */
|
|
1385
|
+
loading?: boolean;
|
|
1384
1386
|
/** Shown when there are no messages. */
|
|
1385
1387
|
emptyState?: React__default.ReactNode;
|
|
1386
1388
|
/** Overall height — the message list scrolls within it. Default `480`. */
|
|
@@ -1406,7 +1408,7 @@ interface ChatProps {
|
|
|
1406
1408
|
* onSend={(text) => send(text)}
|
|
1407
1409
|
* />
|
|
1408
1410
|
*/
|
|
1409
|
-
declare function Chat({ messages, currentUserId, onSend, typingNames, title, subtitle, avatar, headerActions, placeholder, disabled, hideComposer, emptyState, height, className, style, }: ChatProps): react_jsx_runtime.JSX.Element;
|
|
1411
|
+
declare function Chat({ messages, currentUserId, onSend, typingNames, title, subtitle, avatar, headerActions, placeholder, disabled, hideComposer, loading, emptyState, height, className, style, }: ChatProps): react_jsx_runtime.JSX.Element;
|
|
1410
1412
|
|
|
1411
1413
|
type StatisticSize = 'sm' | 'md' | 'lg';
|
|
1412
1414
|
type DeltaDirection = 'up' | 'down' | 'neutral';
|
package/dist/index.d.ts
CHANGED
|
@@ -1381,6 +1381,8 @@ interface ChatProps {
|
|
|
1381
1381
|
disabled?: boolean;
|
|
1382
1382
|
/** Hide the composer entirely (read-only transcript). */
|
|
1383
1383
|
hideComposer?: boolean;
|
|
1384
|
+
/** Shows a transcript skeleton (use while loading history, before messages arrive). */
|
|
1385
|
+
loading?: boolean;
|
|
1384
1386
|
/** Shown when there are no messages. */
|
|
1385
1387
|
emptyState?: React__default.ReactNode;
|
|
1386
1388
|
/** Overall height — the message list scrolls within it. Default `480`. */
|
|
@@ -1406,7 +1408,7 @@ interface ChatProps {
|
|
|
1406
1408
|
* onSend={(text) => send(text)}
|
|
1407
1409
|
* />
|
|
1408
1410
|
*/
|
|
1409
|
-
declare function Chat({ messages, currentUserId, onSend, typingNames, title, subtitle, avatar, headerActions, placeholder, disabled, hideComposer, emptyState, height, className, style, }: ChatProps): react_jsx_runtime.JSX.Element;
|
|
1411
|
+
declare function Chat({ messages, currentUserId, onSend, typingNames, title, subtitle, avatar, headerActions, placeholder, disabled, hideComposer, loading, emptyState, height, className, style, }: ChatProps): react_jsx_runtime.JSX.Element;
|
|
1410
1412
|
|
|
1411
1413
|
type StatisticSize = 'sm' | 'md' | 'lg';
|
|
1412
1414
|
type DeltaDirection = 'up' | 'down' | 'neutral';
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { colors_default } from './chunk-I2P4JJDB.js';
|
|
2
2
|
export { colors_default as COLORS, PALETTE as palette, semanticTokens, vars } from './chunk-I2P4JJDB.js';
|
|
3
3
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
4
|
-
import React28, { createContext, useState, useEffect, useMemo, useId, useCallback, useRef,
|
|
4
|
+
import React28, { createContext, useState, useEffect, useMemo, useId, useCallback, useRef, useContext, useSyncExternalStore, useLayoutEffect } from 'react';
|
|
5
5
|
import { createPortal } from 'react-dom';
|
|
6
6
|
import * as AvatarPrimitive from '@radix-ui/react-avatar';
|
|
7
7
|
import * as DropdownMenu from '@radix-ui/react-dropdown-menu';
|
|
@@ -2267,6 +2267,19 @@ var ArrowDown = () => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "
|
|
|
2267
2267
|
function TypingDots() {
|
|
2268
2268
|
return /* @__PURE__ */ jsx("span", { className: "inline-flex items-center gap-1", "aria-hidden": "true", children: [0, 1, 2].map((i) => /* @__PURE__ */ jsx("span", { className: "h-1.5 w-1.5 animate-bounce rounded-full bg-foreground-muted", style: { animationDelay: `${i * 0.15}s` } }, i)) });
|
|
2269
2269
|
}
|
|
2270
|
+
var SKELETON_ROWS = [
|
|
2271
|
+
{ own: false, w: 150 },
|
|
2272
|
+
{ own: false, w: 110 },
|
|
2273
|
+
{ own: true, w: 180 },
|
|
2274
|
+
{ own: false, w: 130 },
|
|
2275
|
+
{ own: true, w: 90 }
|
|
2276
|
+
];
|
|
2277
|
+
function ChatSkeleton() {
|
|
2278
|
+
return /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", "aria-hidden": "true", children: SKELETON_ROWS.map((r, i) => /* @__PURE__ */ jsxs("div", { className: ["flex items-end gap-2", r.own ? "flex-row-reverse" : ""].filter(Boolean).join(" "), children: [
|
|
2279
|
+
!r.own && /* @__PURE__ */ jsx("span", { className: "h-6 w-6 flex-shrink-0 animate-pulse rounded-full bg-surface" }),
|
|
2280
|
+
/* @__PURE__ */ jsx("span", { className: "h-8 animate-pulse rounded-2xl bg-surface", style: { width: r.w } })
|
|
2281
|
+
] }, i)) });
|
|
2282
|
+
}
|
|
2270
2283
|
function Chat({
|
|
2271
2284
|
messages,
|
|
2272
2285
|
currentUserId,
|
|
@@ -2279,6 +2292,7 @@ function Chat({
|
|
|
2279
2292
|
placeholder = "Write a message\u2026",
|
|
2280
2293
|
disabled = false,
|
|
2281
2294
|
hideComposer = false,
|
|
2295
|
+
loading = false,
|
|
2282
2296
|
emptyState,
|
|
2283
2297
|
height = 480,
|
|
2284
2298
|
className = "",
|
|
@@ -2288,7 +2302,6 @@ function Chat({
|
|
|
2288
2302
|
const atBottomRef = useRef(true);
|
|
2289
2303
|
const [showJump, setShowJump] = useState(false);
|
|
2290
2304
|
const [draft, setDraft] = useState("");
|
|
2291
|
-
const taRef = useRef(null);
|
|
2292
2305
|
const hasHeader = title != null || subtitle != null || avatar != null || headerActions != null;
|
|
2293
2306
|
const isTyping = typingNames.length > 0;
|
|
2294
2307
|
const scrollToBottom = useCallback((smooth = true) => {
|
|
@@ -2310,12 +2323,6 @@ function Chat({
|
|
|
2310
2323
|
useEffect(() => {
|
|
2311
2324
|
scrollToBottom(false);
|
|
2312
2325
|
}, [scrollToBottom]);
|
|
2313
|
-
useLayoutEffect(() => {
|
|
2314
|
-
const ta = taRef.current;
|
|
2315
|
-
if (!ta) return;
|
|
2316
|
-
ta.style.height = "auto";
|
|
2317
|
-
ta.style.height = `${Math.min(ta.scrollHeight, 120)}px`;
|
|
2318
|
-
}, [draft]);
|
|
2319
2326
|
const send = () => {
|
|
2320
2327
|
const text = draft.trim();
|
|
2321
2328
|
if (!text || disabled) return;
|
|
@@ -2344,7 +2351,7 @@ function Chat({
|
|
|
2344
2351
|
] }),
|
|
2345
2352
|
/* @__PURE__ */ jsxs("div", { className: "relative flex-1 overflow-hidden", children: [
|
|
2346
2353
|
/* @__PURE__ */ jsxs("div", { ref: listRef, onScroll, className: "flex h-full flex-col gap-1 overflow-y-auto bg-background px-4 py-3", children: [
|
|
2347
|
-
messages.length === 0 && !isTyping ? /* @__PURE__ */ jsx("div", { className: "flex flex-1 items-center justify-center text-center text-sm text-foreground-muted", children: emptyState ?? "No messages yet. Say hello \u{1F44B}" }) : messages.map((m, i) => {
|
|
2354
|
+
loading && messages.length === 0 ? /* @__PURE__ */ jsx(ChatSkeleton, {}) : messages.length === 0 && !isTyping ? /* @__PURE__ */ jsx("div", { className: "flex flex-1 items-center justify-center text-center text-sm text-foreground-muted", children: emptyState ?? "No messages yet. Say hello \u{1F44B}" }) : messages.map((m, i) => {
|
|
2348
2355
|
const own = m.authorId === currentUserId;
|
|
2349
2356
|
const prev = messages[i - 1];
|
|
2350
2357
|
const next = messages[i + 1];
|
|
@@ -2399,15 +2406,14 @@ function Chat({
|
|
|
2399
2406
|
/* @__PURE__ */ jsx(
|
|
2400
2407
|
"textarea",
|
|
2401
2408
|
{
|
|
2402
|
-
|
|
2403
|
-
rows: 1,
|
|
2409
|
+
rows: 2,
|
|
2404
2410
|
value: draft,
|
|
2405
2411
|
disabled,
|
|
2406
2412
|
placeholder,
|
|
2407
2413
|
onChange: (e) => setDraft(e.target.value),
|
|
2408
2414
|
onKeyDown,
|
|
2409
2415
|
"aria-label": "Message",
|
|
2410
|
-
className: `${fieldShell({ size: "md", hasError: false, disabled, sized: false })}
|
|
2416
|
+
className: `${fieldShell({ size: "md", hasError: false, disabled, sized: false })} h-[4.5rem] flex-1 resize-none px-3 py-2 leading-snug`
|
|
2411
2417
|
}
|
|
2412
2418
|
),
|
|
2413
2419
|
/* @__PURE__ */ jsx(
|
|
@@ -5525,9 +5531,10 @@ function Pagination({
|
|
|
5525
5531
|
}, [serverSide, options.perPage, picker]);
|
|
5526
5532
|
const currentOpt = picker.find((o) => o.key === displayPerPageKey);
|
|
5527
5533
|
const currentPerPageLabel = currentOpt?.label ?? currentOpt?.value ?? options.perPage ?? "";
|
|
5528
|
-
const
|
|
5529
|
-
const
|
|
5530
|
-
const
|
|
5534
|
+
const FOCUS = "focus-visible:!ring-0 focus-visible:!border-accent";
|
|
5535
|
+
const navBtn = (icon, disabled, onClick, title) => /* @__PURE__ */ jsx(Button_default, { variant: "outline", size: "sm", disabled, onClick, icon, className: `w-7 !px-0 ${FOCUS}`, "aria-label": title, title });
|
|
5536
|
+
const chevronRight = /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 6l6 6-6 6" }) });
|
|
5537
|
+
const doubleChevronRight = /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 6l6 6-6 6M12 6l6 6-6 6" }) });
|
|
5531
5538
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-end gap-x-4 gap-y-3", children: [
|
|
5532
5539
|
options.withPicker && /* @__PURE__ */ jsxs("div", { className: "mr-auto flex items-center gap-2", children: [
|
|
5533
5540
|
/* @__PURE__ */ jsx("span", { className: "whitespace-nowrap text-xs text-foreground-muted", children: "Rows per page" }),
|
|
@@ -5537,7 +5544,7 @@ function Pagination({
|
|
|
5537
5544
|
variant: "outline",
|
|
5538
5545
|
size: "sm",
|
|
5539
5546
|
side: "top",
|
|
5540
|
-
className:
|
|
5547
|
+
className: FOCUS,
|
|
5541
5548
|
label: String(currentPerPageLabel),
|
|
5542
5549
|
items: picker.map((o) => ({
|
|
5543
5550
|
key: o.key,
|
|
@@ -5553,7 +5560,7 @@ function Pagination({
|
|
|
5553
5560
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
5554
5561
|
navBtn(/* @__PURE__ */ jsx("span", { className: "inline-flex rotate-180", children: doubleChevronRight }), activePage === 0, () => onPageChange(0), "First page"),
|
|
5555
5562
|
navBtn(/* @__PURE__ */ jsx("span", { className: "inline-flex rotate-180", children: chevronRight }), activePage === 0, () => activePage > 0 && onPageChange(activePage - 1), "Previous page"),
|
|
5556
|
-
/* @__PURE__ */ jsxs("span", { className: "px-2 text-
|
|
5563
|
+
/* @__PURE__ */ jsxs("span", { className: "px-2 text-xs tabular-nums text-foreground-secondary select-none", children: [
|
|
5557
5564
|
activePage + 1,
|
|
5558
5565
|
" ",
|
|
5559
5566
|
/* @__PURE__ */ jsxs("span", { className: "text-foreground-muted", children: [
|