@lindaui/blocks 0.5.1 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/analytics/types.d.ts +3 -3
- package/dist/analytics/types.d.ts.map +1 -1
- package/dist/app-shell/drawer-focus.d.ts.map +1 -1
- package/dist/app-shell.js +3 -2
- package/dist/chat.js +2 -2
- package/dist/compat-chat/conversation-thread.d.ts.map +1 -1
- package/dist/compat.js +1 -1
- package/dist/{conversation-thread-c60431oa.js → conversation-thread-f4ruu4kn.js} +6 -5
- package/dist/field-array-form.js +11 -16
- package/dist/{image-lightbox-ci3arb6z.js → image-lightbox-vtovz1gj.js} +1 -0
- package/dist/image-viewer.d.ts.map +1 -1
- package/dist/image-viewer.js +5 -4
- package/dist/{message-bubble-odjvhroq.js → message-bubble-ivgt1l7t.js} +1 -1
- package/dist/message-bubble.d.ts.map +1 -1
- package/dist/message-bubble.js +1 -0
- package/llms.txt +15 -1
- package/package.json +5 -3
- package/src/analytics/types.ts +1 -1
- package/src/app-shell/drawer-focus.ts +2 -1
- package/src/app-shell.tsx +1 -1
- package/src/compat-chat/conversation-thread.tsx +4 -3
- package/src/compat-chat/image-lightbox.tsx +1 -1
- package/src/field-array-form.tsx +1 -1
- package/src/image-viewer.tsx +5 -3
- package/src/message-bubble.tsx +1 -0
|
@@ -71,9 +71,9 @@ export interface AiVsHumanData {
|
|
|
71
71
|
humanRate: number;
|
|
72
72
|
}
|
|
73
73
|
export interface AiPerformanceCardProps {
|
|
74
|
-
aiVsHuman
|
|
75
|
-
avgResponseTimeMinutes
|
|
76
|
-
containmentRate
|
|
74
|
+
aiVsHuman?: AiVsHumanData;
|
|
75
|
+
avgResponseTimeMinutes?: number;
|
|
76
|
+
containmentRate?: number;
|
|
77
77
|
t: (key: string, opts?: Record<string, unknown>) => string;
|
|
78
78
|
}
|
|
79
79
|
export interface AiCostData {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/analytics/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,+EAA+E;AAC/E,MAAM,WAAW,WAAW;IAAG,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;CAAE;AAC1F,MAAM,WAAW,4BAA4B;IAAG,IAAI,EAAE,WAAW,EAAE,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;CAAE;AAC/H,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACzB,KAAK,CAAC,EAAE;QAAE,KAAK,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACzG,KAAK,EAAE,MAAM,CAAC;CACf;AACD,MAAM,WAAW,YAAY;IAAG,KAAK,EAAE,UAAU,EAAE,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;CAAE;AAChF,MAAM,WAAW,iBAAiB;IAAG,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;CAAE;AAC5F,MAAM,WAAW,qBAAqB;IAAG,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,YAAY,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAAE;AACtI,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;AAC9D,MAAM,WAAW,YAAY;IAAG,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,YAAY,CAAC;CAAE;AAChG,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACtC,WAAW,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,MAAM,CAAC;IAC9C,KAAK,EAAE,MAAM,CAAC;CACf;AACD,MAAM,WAAW,qBAAqB;IAAG,QAAQ,EAAE,YAAY,EAAE,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAC;IAAC,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,KAAK,SAAS,CAAC;CAAE;AAC3K,MAAM,WAAW,aAAa;IAAG,WAAW,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;CAAE;AACvJ,MAAM,WAAW,sBAAsB;IAAG,SAAS,EAAE,aAAa,CAAC;IAAC,sBAAsB,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAC;CAAE;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/analytics/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,+EAA+E;AAC/E,MAAM,WAAW,WAAW;IAAG,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;CAAE;AAC1F,MAAM,WAAW,4BAA4B;IAAG,IAAI,EAAE,WAAW,EAAE,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;CAAE;AAC/H,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACzB,KAAK,CAAC,EAAE;QAAE,KAAK,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACzG,KAAK,EAAE,MAAM,CAAC;CACf;AACD,MAAM,WAAW,YAAY;IAAG,KAAK,EAAE,UAAU,EAAE,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;CAAE;AAChF,MAAM,WAAW,iBAAiB;IAAG,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;CAAE;AAC5F,MAAM,WAAW,qBAAqB;IAAG,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,YAAY,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAAE;AACtI,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;AAC9D,MAAM,WAAW,YAAY;IAAG,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,YAAY,CAAC;CAAE;AAChG,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACtC,WAAW,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,MAAM,CAAC;IAC9C,KAAK,EAAE,MAAM,CAAC;CACf;AACD,MAAM,WAAW,qBAAqB;IAAG,QAAQ,EAAE,YAAY,EAAE,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAC;IAAC,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,KAAK,SAAS,CAAC;CAAE;AAC3K,MAAM,WAAW,aAAa;IAAG,WAAW,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;CAAE;AACvJ,MAAM,WAAW,sBAAsB;IAAG,SAAS,CAAC,EAAE,aAAa,CAAC;IAAC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAC;CAAE;AAC7L,MAAM,WAAW,UAAU;IAAG,SAAS,EAAE,OAAO,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;CAAE;AAC9H,MAAM,WAAW,eAAe;IAAG,MAAM,EAAE,UAAU,GAAG,SAAS,CAAC;IAAC,SAAS,EAAE,OAAO,CAAC;IAAC,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAC;CAAE;AACpJ,MAAM,MAAM,MAAM,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,GAAG,QAAQ,CAAC;AACrD,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,UAAU,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAC1C,mBAAmB,EAAE,CAAC,CAAC,EAAE,UAAU,CAAC,SAAS,CAAC,GAAG,IAAI,KAAK,IAAI,CAAC;IAC/D,cAAc,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;CAC5B;AACD,MAAM,WAAW,kBAAkB;IAAG,MAAM,CAAC,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;CAAE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drawer-focus.d.ts","sourceRoot":"","sources":["../../src/app-shell/drawer-focus.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C,4FAA4F;AAC5F,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI;;;uBAcvC,aAAa,CAAC,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"drawer-focus.d.ts","sourceRoot":"","sources":["../../src/app-shell/drawer-focus.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C,4FAA4F;AAC5F,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI;;;uBAcvC,aAAa,CAAC,WAAW,CAAC;EAwBrD"}
|
package/dist/app-shell.js
CHANGED
|
@@ -36,7 +36,8 @@ export { A as AppShellFooter } from './footer-f7r5e42b.js';
|
|
|
36
36
|
const activeElement = event.currentTarget.ownerDocument.activeElement;
|
|
37
37
|
if (event.shiftKey && activeElement === first || !event.shiftKey && activeElement === last) {
|
|
38
38
|
event.preventDefault();
|
|
39
|
-
|
|
39
|
+
// Matching a real activeElement to either boundary proves the list is nonempty.
|
|
40
|
+
(event.shiftKey ? last : first).focus();
|
|
40
41
|
}
|
|
41
42
|
};
|
|
42
43
|
return {
|
|
@@ -106,7 +107,7 @@ const defaultLabels = {
|
|
|
106
107
|
href: brand.href,
|
|
107
108
|
renderLink: renderLink,
|
|
108
109
|
children: [
|
|
109
|
-
logo(32,
|
|
110
|
+
logo(32, `rounded-lg ${isCollapsed ? "h-7 w-7" : "h-8 w-8"}`),
|
|
110
111
|
isCollapsed ? null : /*#__PURE__*/ jsx("span", {
|
|
111
112
|
className: "font-extrabold text-sm uppercase",
|
|
112
113
|
children: brand.label
|
package/dist/chat.js
CHANGED
|
@@ -3,9 +3,9 @@ import { jsxs, jsx } from 'react/jsx-runtime';
|
|
|
3
3
|
export { C as ChatLayout } from './chat-layout-fwx3x26g.js';
|
|
4
4
|
export { C as ConversationList } from './conversation-list-ekq2dzca.js';
|
|
5
5
|
export { C as ConversationListItem } from './conversation-list-item-fy6t5af2.js';
|
|
6
|
-
export { C as ConversationThread } from './conversation-thread-
|
|
6
|
+
export { C as ConversationThread } from './conversation-thread-f4ruu4kn.js';
|
|
7
7
|
import { MessageCircle } from 'lucide-react';
|
|
8
|
-
export { M as MessageBubble } from './message-bubble-
|
|
8
|
+
export { M as MessageBubble } from './message-bubble-ivgt1l7t.js';
|
|
9
9
|
export { M as MessageComposer } from './message-composer-m2n6soo7.js';
|
|
10
10
|
|
|
11
11
|
function ChatHeader({ title, subtitle, avatar, actions }) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation-thread.d.ts","sourceRoot":"","sources":["../../src/compat-chat/conversation-thread.tsx"],"names":[],"mappings":"AAMA,OAAO,EAA4D,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAGjG,OAAO,KAAK,EAAE,wBAAwB,EAAE,cAAc,EAAE,MAAM,YAAS,CAAC;AAExE,MAAM,WAAW,uBAAuB;IACtC,mFAAmF;IACnF,eAAe,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACzD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,wBAAwB,CAAC;IACjC,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,+EAA+E;IAC/E,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,cAAc,EAAE,EAAE,aAAa,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,SAAS,KAAK,SAAS,CAAC;CACnH;AAED,wBAAgB,kBAAkB,CAAC,EAAE,QAAQ,EAAE,SAAiB,EAAE,OAAe,EAAE,MAAM,EAAE,eAAe,EAAE,mBAA2B,EAAE,cAAc,EAAE,EAAE,uBAAuB,+
|
|
1
|
+
{"version":3,"file":"conversation-thread.d.ts","sourceRoot":"","sources":["../../src/compat-chat/conversation-thread.tsx"],"names":[],"mappings":"AAMA,OAAO,EAA4D,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAGjG,OAAO,KAAK,EAAE,wBAAwB,EAAE,cAAc,EAAE,MAAM,YAAS,CAAC;AAExE,MAAM,WAAW,uBAAuB;IACtC,mFAAmF;IACnF,eAAe,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACzD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,wBAAwB,CAAC;IACjC,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,+EAA+E;IAC/E,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,cAAc,EAAE,EAAE,aAAa,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,SAAS,KAAK,SAAS,CAAC;CACnH;AAED,wBAAgB,kBAAkB,CAAC,EAAE,QAAQ,EAAE,SAAiB,EAAE,OAAe,EAAE,MAAM,EAAE,eAAe,EAAE,mBAA2B,EAAE,cAAc,EAAE,EAAE,uBAAuB,+BAqEjL"}
|
package/dist/compat.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export * from '@lindaui/ui/compat';
|
|
2
2
|
export { K as KPICard } from './analytics-skeleton-imve37du.js';
|
|
3
3
|
export { StatusFilters } from './status-filters.js';
|
|
4
|
-
export { D as DateDivider } from './conversation-thread-
|
|
4
|
+
export { D as DateDivider } from './conversation-thread-f4ruu4kn.js';
|
|
@@ -6,7 +6,7 @@ import dayjs from 'dayjs';
|
|
|
6
6
|
import { AlertCircle } from 'lucide-react';
|
|
7
7
|
import { useRef, useMemo, useCallback, useLayoutEffect, useEffect } from 'react';
|
|
8
8
|
import { isToday, isYesterday } from '@lindaui/ui/compat';
|
|
9
|
-
import { M as MessageBubble } from './message-bubble-
|
|
9
|
+
import { M as MessageBubble } from './message-bubble-ivgt1l7t.js';
|
|
10
10
|
|
|
11
11
|
function DateDivider({ date }) {
|
|
12
12
|
return /*#__PURE__*/ jsx("div", {
|
|
@@ -71,12 +71,11 @@ function ConversationThread({ messages, isLoading = false, isError = false, labe
|
|
|
71
71
|
if (!el || !listEl) return;
|
|
72
72
|
let settleTimeout = null;
|
|
73
73
|
let settled = false;
|
|
74
|
-
const scrollNow = ()=>
|
|
75
|
-
el.scrollTop = el.scrollHeight;
|
|
76
|
-
};
|
|
74
|
+
const scrollNow = ()=>scrollToBottom("auto");
|
|
77
75
|
const scheduleSettle = ()=>{
|
|
78
76
|
if (settleTimeout) clearTimeout(settleTimeout);
|
|
79
77
|
settleTimeout = setTimeout(()=>{
|
|
78
|
+
settleTimeout = null;
|
|
80
79
|
settled = true;
|
|
81
80
|
hasScrolledOnLoad.current = true;
|
|
82
81
|
resizeObserver.disconnect();
|
|
@@ -103,6 +102,7 @@ function ConversationThread({ messages, isLoading = false, isError = false, labe
|
|
|
103
102
|
subtree: true
|
|
104
103
|
});
|
|
105
104
|
return ()=>{
|
|
105
|
+
settled = true;
|
|
106
106
|
if (settleTimeout) clearTimeout(settleTimeout);
|
|
107
107
|
resizeObserver.disconnect();
|
|
108
108
|
mutationObserver.disconnect();
|
|
@@ -110,7 +110,8 @@ function ConversationThread({ messages, isLoading = false, isError = false, labe
|
|
|
110
110
|
}, [
|
|
111
111
|
isLoading,
|
|
112
112
|
messages.length,
|
|
113
|
-
firstId
|
|
113
|
+
firstId,
|
|
114
|
+
scrollToBottom
|
|
114
115
|
]);
|
|
115
116
|
const messageCount = messages.length;
|
|
116
117
|
const prevMessageCount = useRef(messageCount);
|
package/dist/field-array-form.js
CHANGED
|
@@ -24,22 +24,17 @@ function FieldArrayForm({ onSubmit, options, categoryLabel = "Categoría", nameL
|
|
|
24
24
|
children: /*#__PURE__*/ jsxs("div", {
|
|
25
25
|
className: "flex flex-col gap-4 px-4 py-4 sm:px-6 sm:py-5",
|
|
26
26
|
children: [
|
|
27
|
-
/*#__PURE__*/
|
|
28
|
-
children:
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
value: field.value,
|
|
39
|
-
onChange: (val)=>field.onChange(val)
|
|
40
|
-
})
|
|
41
|
-
})
|
|
42
|
-
]
|
|
27
|
+
/*#__PURE__*/ jsx("div", {
|
|
28
|
+
children: /*#__PURE__*/ jsx(Controller, {
|
|
29
|
+
control: control,
|
|
30
|
+
name: "category",
|
|
31
|
+
render: ({ field })=>/*#__PURE__*/ jsx(Select, {
|
|
32
|
+
label: categoryLabel,
|
|
33
|
+
items: options,
|
|
34
|
+
value: field.value,
|
|
35
|
+
onChange: (val)=>field.onChange(val)
|
|
36
|
+
})
|
|
37
|
+
})
|
|
43
38
|
}),
|
|
44
39
|
/*#__PURE__*/ jsx(Controller, {
|
|
45
40
|
control: control,
|
|
@@ -36,6 +36,7 @@ function ImageLightbox({ src, alt = "Media", className }) {
|
|
|
36
36
|
className: "overflow-hidden",
|
|
37
37
|
size: "full",
|
|
38
38
|
children: /*#__PURE__*/ jsxs(Modal.Dialog, {
|
|
39
|
+
"aria-label": alt,
|
|
39
40
|
className: "m-0 rounded-none shadow-none",
|
|
40
41
|
children: [
|
|
41
42
|
/*#__PURE__*/ jsx(Modal.CloseTrigger, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image-viewer.d.ts","sourceRoot":"","sources":["../src/image-viewer.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,MAAM,WAAW,gBAAgB;IAC/B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,WAAW,CAAC,EAC1B,GAAG,EACH,GAAQ,EACR,WAAW,EACX,OAAO,EACP,gBAAgB,EAChB,GAAO,EACP,YAAoB,EACpB,OAAW,EACX,OAAa,GACd,EAAE,gBAAgB,+
|
|
1
|
+
{"version":3,"file":"image-viewer.d.ts","sourceRoot":"","sources":["../src/image-viewer.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,MAAM,WAAW,gBAAgB;IAC/B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,WAAW,CAAC,EAC1B,GAAG,EACH,GAAQ,EACR,WAAW,EACX,OAAO,EACP,gBAAgB,EAChB,GAAO,EACP,YAAoB,EACpB,OAAW,EACX,OAAa,GACd,EAAE,gBAAgB,+BAsGlB"}
|
package/dist/image-viewer.js
CHANGED
|
@@ -5,7 +5,8 @@ import { Scan, ZoomOut, ZoomIn, Frame } from 'lucide-react';
|
|
|
5
5
|
|
|
6
6
|
function ImageViewer({ src, alt = "", annotations, caption, placeholderLabel, dim = 0, showControls = false, minZoom = 1, maxZoom = 2.6 }) {
|
|
7
7
|
const [zoom, setZoom] = useState(1);
|
|
8
|
-
const [
|
|
8
|
+
const [loadedSrc, setLoadedSrc] = useState(null);
|
|
9
|
+
const imgOk = loadedSrc === src;
|
|
9
10
|
const showPlaceholder = !src || !imgOk;
|
|
10
11
|
return /*#__PURE__*/ jsxs("div", {
|
|
11
12
|
className: "absolute inset-0 overflow-hidden bg-viewer-bg text-viewer-foreground",
|
|
@@ -19,13 +20,13 @@ function ImageViewer({ src, alt = "", annotations, caption, placeholderLabel, di
|
|
|
19
20
|
src && /*#__PURE__*/ jsx("img", {
|
|
20
21
|
src: src,
|
|
21
22
|
alt: alt,
|
|
22
|
-
onLoad: ()=>
|
|
23
|
-
onError: ()=>
|
|
23
|
+
onLoad: ()=>setLoadedSrc(src),
|
|
24
|
+
onError: ()=>setLoadedSrc(null),
|
|
24
25
|
className: "max-h-full max-w-full object-contain",
|
|
25
26
|
style: {
|
|
26
27
|
display: imgOk ? "block" : "none"
|
|
27
28
|
}
|
|
28
|
-
}),
|
|
29
|
+
}, src),
|
|
29
30
|
showPlaceholder && /*#__PURE__*/ jsx("div", {
|
|
30
31
|
className: "grid place-items-center rounded-lg border border-dashed",
|
|
31
32
|
children: /*#__PURE__*/ jsxs("div", {
|
|
@@ -3,7 +3,7 @@ import { jsx, jsxs } from 'react/jsx-runtime';
|
|
|
3
3
|
import dayjs from 'dayjs';
|
|
4
4
|
import { motion } from 'framer-motion';
|
|
5
5
|
import { cn } from '@lindaui/ui/cn';
|
|
6
|
-
import { I as ImageLightbox } from './image-lightbox-
|
|
6
|
+
import { I as ImageLightbox } from './image-lightbox-vtovz1gj.js';
|
|
7
7
|
import { W as WhatsAppAudioPlayer } from './whatsapp-audio-player-nooty6jb.js';
|
|
8
8
|
|
|
9
9
|
function formatTime(date) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message-bubble.d.ts","sourceRoot":"","sources":["../src/message-bubble.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAiB,MAAM,iBAAiB,CAAC;AAErE,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,cAAc,CAAC;IACxB,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC;AAUD,wBAAgB,aAAa,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,EAAE,kBAAkB,+
|
|
1
|
+
{"version":3,"file":"message-bubble.d.ts","sourceRoot":"","sources":["../src/message-bubble.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAiB,MAAM,iBAAiB,CAAC;AAErE,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,cAAc,CAAC;IACxB,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC;AAUD,wBAAgB,aAAa,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,EAAE,kBAAkB,+BAmD1E"}
|
package/dist/message-bubble.js
CHANGED
|
@@ -37,6 +37,7 @@ function MessageBubble({ message, onImageClick }) {
|
|
|
37
37
|
children: [
|
|
38
38
|
message.media?.kind === "image" && /*#__PURE__*/ jsx("button", {
|
|
39
39
|
type: "button",
|
|
40
|
+
"aria-label": message.media.alt || "Abrir imagen",
|
|
40
41
|
onClick: ()=>onImageClick?.(message.media.url),
|
|
41
42
|
className: "-mx-1 -mt-1 mb-1 block overflow-hidden rounded-xl",
|
|
42
43
|
children: /*#__PURE__*/ jsx("img", {
|
package/llms.txt
CHANGED
|
@@ -97,7 +97,9 @@ StatusDatum: key/label/count/color. HealthEntity: id/name/score and status
|
|
|
97
97
|
TimeRangePicker uses preset `24h|7d|30d|custom`, customRange
|
|
98
98
|
`RangeValue<DateValue> | null`, onPresetChange/onCustomRangeChange and translation
|
|
99
99
|
function `t`. This is NOT the unchanged flat `/time-range-picker` documented below.
|
|
100
|
-
|
|
100
|
+
AiPerformanceCard accepts omitted metrics: containment/response time and AI-vs-human
|
|
101
|
+
values default to zero. SDK mapping, tenant policy, fetching and navigation stay
|
|
102
|
+
in the consumer.
|
|
101
103
|
|
|
102
104
|
Dayjs, @internationalized/date, @react-types/shared, motion and drag/drop are
|
|
103
105
|
runtime dependencies (including public date types), not workspace-only tooling.
|
|
@@ -215,6 +217,8 @@ emptyDescription />` — auto-scrolls to the last message; groups by calendar da
|
|
|
215
217
|
### @lindaui/blocks/message-bubble
|
|
216
218
|
Renders one `GenericMessage`: text, image (click → `onImageClick(url)`), audio (via
|
|
217
219
|
`audio-player`), or pdf (link). Side-aligned; outgoing messages show a status icon.
|
|
220
|
+
Image buttons use the media alt text as their accessible name, falling back to
|
|
221
|
+
"Abrir imagen" when it is omitted or empty.
|
|
218
222
|
|
|
219
223
|
### @lindaui/blocks/message-composer
|
|
220
224
|
`<MessageComposer value onValueChange onSend placeholder isSending isDisabled
|
|
@@ -287,3 +291,13 @@ API: doctor, api, setup, theme, scaffold, activate and check. Mutation commands
|
|
|
287
291
|
produce plans by default. Use activate when adopting LindaUI for all UI tasks.
|
|
288
292
|
Always prefer this installed package's exports, types and llms.txt over newer
|
|
289
293
|
unpublished GitHub APIs. See the skill for setup, recipes and verification.
|
|
294
|
+
|
|
295
|
+
## Consumer control policy
|
|
296
|
+
|
|
297
|
+
Use installed LindaUI entries for controls and canonical tokens for styling.
|
|
298
|
+
Semantic HTML containers, text, labels and graphics remain appropriate. Select
|
|
299
|
+
input, selection and expansion components by behavior, not only by tag name.
|
|
300
|
+
The lindaui skill check reports recognized native controls with installed
|
|
301
|
+
counterparts. Required native behavior needs an adjacent JSX comment with a
|
|
302
|
+
nonempty reason: {/* lindaui-allow-native: reason */}. Run check in consumer CI;
|
|
303
|
+
static findings do not prove browser behavior or exhaustive compliance.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lindaui/blocks",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"description": "Composed UI sections (auth, lists, master-detail, charts) built on @lindaui/ui — importable npm package, not a copy-paste registry.",
|
|
5
5
|
"author": "Franco Carballar <francocarballar@gmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -350,6 +350,7 @@
|
|
|
350
350
|
"framer-motion": "14.0.0"
|
|
351
351
|
},
|
|
352
352
|
"devDependencies": {
|
|
353
|
+
"@vitest/coverage-v8": "5.0.3",
|
|
353
354
|
"@hookform/resolvers": "^5.9.1",
|
|
354
355
|
"@testing-library/jest-dom": "^7.0.1",
|
|
355
356
|
"@testing-library/react": "^16.3.3",
|
|
@@ -369,14 +370,15 @@
|
|
|
369
370
|
"vite": "^8.3.4",
|
|
370
371
|
"vitest": "^5.0.3",
|
|
371
372
|
"zod": "^4.6.5",
|
|
372
|
-
"@lindaui/tokens": "0.4.
|
|
373
|
-
"@lindaui/ui": "0.5.
|
|
373
|
+
"@lindaui/tokens": "0.4.3",
|
|
374
|
+
"@lindaui/ui": "0.5.3"
|
|
374
375
|
},
|
|
375
376
|
"scripts": {
|
|
376
377
|
"build": "bunchee --no-dts && tsc -p tsconfig.build.json && node ../../scripts/normalize-declarations.mjs dist",
|
|
377
378
|
"dev": "bunchee --watch",
|
|
378
379
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
379
380
|
"test": "vitest run",
|
|
381
|
+
"test:coverage": "vitest run --coverage",
|
|
380
382
|
"test:watch": "vitest"
|
|
381
383
|
}
|
|
382
384
|
}
|
package/src/analytics/types.ts
CHANGED
|
@@ -29,7 +29,7 @@ export interface HealthCardLabels {
|
|
|
29
29
|
}
|
|
30
30
|
export interface EntityHealthCardProps { entities: HealthEntity[]; labels: HealthCardLabels; renderEntityLink?: (entity: HealthEntity, children: ReactNode) => ReactNode; }
|
|
31
31
|
export interface AiVsHumanData { aiConverted: number; aiLeads: number; aiRate: number; humanConverted: number; humanLeads: number; humanRate: number; }
|
|
32
|
-
export interface AiPerformanceCardProps { aiVsHuman
|
|
32
|
+
export interface AiPerformanceCardProps { aiVsHuman?: AiVsHumanData; avgResponseTimeMinutes?: number; containmentRate?: number; t: (key: string, opts?: Record<string, unknown>) => string; }
|
|
33
33
|
export interface AiCostData { available: boolean; conversionsCount: number; costPerConversion: number; totalCostUsd: number; }
|
|
34
34
|
export interface AiCostCardProps { aiCost: AiCostData | undefined; isLoading: boolean; t: (key: string, opts?: Record<string, unknown>) => string; }
|
|
35
35
|
export type Preset = "24h" | "7d" | "30d" | "custom";
|
|
@@ -35,7 +35,8 @@ export function useDrawerFocus(isOpen: boolean, onClose: () => void) {
|
|
|
35
35
|
if ((event.shiftKey && activeElement === first)
|
|
36
36
|
|| (!event.shiftKey && activeElement === last)) {
|
|
37
37
|
event.preventDefault();
|
|
38
|
-
|
|
38
|
+
// Matching a real activeElement to either boundary proves the list is nonempty.
|
|
39
|
+
(event.shiftKey ? last : first)!.focus();
|
|
39
40
|
}
|
|
40
41
|
};
|
|
41
42
|
return { drawerRef, triggerRef, onKeyDown };
|
package/src/app-shell.tsx
CHANGED
|
@@ -69,7 +69,7 @@ export function AppShell({
|
|
|
69
69
|
href={brand.href}
|
|
70
70
|
renderLink={renderLink}
|
|
71
71
|
>
|
|
72
|
-
{logo(32,
|
|
72
|
+
{logo(32, `rounded-lg ${isCollapsed ? "h-7 w-7" : "h-8 w-8"}`)}
|
|
73
73
|
{isCollapsed ? null : <span className="font-extrabold text-sm uppercase">{brand.label}</span>}
|
|
74
74
|
</ShellLink>
|
|
75
75
|
{isCollapsed ? null : (
|
|
@@ -51,10 +51,11 @@ export function ConversationThread({ messages, isLoading = false, isError = fals
|
|
|
51
51
|
if (!el || !listEl) return;
|
|
52
52
|
let settleTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
53
53
|
let settled = false;
|
|
54
|
-
const scrollNow = () =>
|
|
54
|
+
const scrollNow = () => scrollToBottom("auto");
|
|
55
55
|
const scheduleSettle = () => {
|
|
56
56
|
if (settleTimeout) clearTimeout(settleTimeout);
|
|
57
57
|
settleTimeout = setTimeout(() => {
|
|
58
|
+
settleTimeout = null;
|
|
58
59
|
settled = true;
|
|
59
60
|
hasScrolledOnLoad.current = true;
|
|
60
61
|
resizeObserver.disconnect();
|
|
@@ -67,8 +68,8 @@ export function ConversationThread({ messages, isLoading = false, isError = fals
|
|
|
67
68
|
const mutationObserver = new MutationObserver(() => { if (!settled) { scrollNow(); scheduleSettle(); } });
|
|
68
69
|
resizeObserver.observe(listEl);
|
|
69
70
|
mutationObserver.observe(listEl, { childList: true, subtree: true });
|
|
70
|
-
return () => { if (settleTimeout) clearTimeout(settleTimeout); resizeObserver.disconnect(); mutationObserver.disconnect(); };
|
|
71
|
-
}, [isLoading, messages.length, firstId]);
|
|
71
|
+
return () => { settled = true; if (settleTimeout) clearTimeout(settleTimeout); resizeObserver.disconnect(); mutationObserver.disconnect(); };
|
|
72
|
+
}, [isLoading, messages.length, firstId, scrollToBottom]);
|
|
72
73
|
const messageCount = messages.length;
|
|
73
74
|
const prevMessageCount = useRef(messageCount);
|
|
74
75
|
useEffect(() => {
|
|
@@ -13,7 +13,7 @@ export function ImageLightbox({ src, alt = "Media", className }: ImageLightboxPr
|
|
|
13
13
|
<img alt={alt} className="h-44 w-full max-w-[220px] rounded-lg object-cover" height={600} loading="lazy" src={src} width={800} />
|
|
14
14
|
</button>
|
|
15
15
|
<Modal.Backdrop className="bg-black/80" isOpen={isOpen} onOpenChange={handleOpenChange} variant="blur">
|
|
16
|
-
<Modal.Container className="overflow-hidden" size="full"><Modal.Dialog className="m-0 rounded-none shadow-none">
|
|
16
|
+
<Modal.Container className="overflow-hidden" size="full"><Modal.Dialog aria-label={alt} className="m-0 rounded-none shadow-none">
|
|
17
17
|
<Modal.CloseTrigger className="top-4 right-4 z-10 rounded-full bg-black/50 text-white hover:bg-black/70" />
|
|
18
18
|
<Modal.Body className="flex h-full items-center justify-center overflow-hidden p-4"><img alt={alt} className="max-h-full max-w-full rounded-lg object-contain" height={1080} src={src} width={1920} /></Modal.Body>
|
|
19
19
|
</Modal.Dialog></Modal.Container>
|
package/src/field-array-form.tsx
CHANGED
|
@@ -63,12 +63,12 @@ export function FieldArrayForm({
|
|
|
63
63
|
<div className="flex flex-col gap-4 px-4 py-4 sm:px-6 sm:py-5">
|
|
64
64
|
{/* Category Select via Controller */}
|
|
65
65
|
<div>
|
|
66
|
-
<label className="text-sm font-medium">{categoryLabel}</label>
|
|
67
66
|
<Controller
|
|
68
67
|
control={control}
|
|
69
68
|
name="category"
|
|
70
69
|
render={({ field }) => (
|
|
71
70
|
<Select
|
|
71
|
+
label={categoryLabel}
|
|
72
72
|
items={options}
|
|
73
73
|
value={field.value}
|
|
74
74
|
onChange={(val) => field.onChange(val)}
|
package/src/image-viewer.tsx
CHANGED
|
@@ -28,7 +28,8 @@ export function ImageViewer({
|
|
|
28
28
|
maxZoom = 2.6,
|
|
29
29
|
}: ImageViewerProps) {
|
|
30
30
|
const [zoom, setZoom] = useState(1);
|
|
31
|
-
const [
|
|
31
|
+
const [loadedSrc, setLoadedSrc] = useState<string | null>(null);
|
|
32
|
+
const imgOk = loadedSrc === src;
|
|
32
33
|
|
|
33
34
|
const showPlaceholder = !src || !imgOk;
|
|
34
35
|
|
|
@@ -40,10 +41,11 @@ export function ImageViewer({
|
|
|
40
41
|
>
|
|
41
42
|
{src && (
|
|
42
43
|
<img
|
|
44
|
+
key={src}
|
|
43
45
|
src={src}
|
|
44
46
|
alt={alt}
|
|
45
|
-
onLoad={() =>
|
|
46
|
-
onError={() =>
|
|
47
|
+
onLoad={() => setLoadedSrc(src)}
|
|
48
|
+
onError={() => setLoadedSrc(null)}
|
|
47
49
|
className="max-h-full max-w-full object-contain"
|
|
48
50
|
style={{ display: imgOk ? "block" : "none" }}
|
|
49
51
|
/>
|
package/src/message-bubble.tsx
CHANGED
|
@@ -32,6 +32,7 @@ export function MessageBubble({ message, onImageClick }: MessageBubbleProps) {
|
|
|
32
32
|
{message.media?.kind === "image" && (
|
|
33
33
|
<button
|
|
34
34
|
type="button"
|
|
35
|
+
aria-label={message.media.alt || "Abrir imagen"}
|
|
35
36
|
onClick={() => onImageClick?.(message.media!.url)}
|
|
36
37
|
className="-mx-1 -mt-1 mb-1 block overflow-hidden rounded-xl"
|
|
37
38
|
>
|