useyuva 0.0.0-stage → 0.0.4
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/LICENSE +22 -0
- package/README.md +120 -2
- package/dist/esm/api.js +1 -0
- package/dist/esm/chat.js +109 -0
- package/dist/esm/index-feftwnsj.js +12 -0
- package/dist/esm/index-r5vcg0sx.js +2 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/react.js +1 -0
- package/dist/esm/yuva-chat-2482m97r.js +183 -0
- package/dist/types/api.d.ts +9 -0
- package/dist/types/chat.d.ts +3 -0
- package/dist/types/client/api.d.ts +32 -0
- package/dist/types/client/client.d.ts +82 -0
- package/dist/types/client/realtime.d.ts +19 -0
- package/dist/types/element.d.ts +23 -0
- package/dist/types/i18n.d.ts +6 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/locales/en/loader.d.ts +2 -0
- package/dist/types/locales/en/panel.d.ts +2 -0
- package/dist/types/locales/tr/loader.d.ts +2 -0
- package/dist/types/locales/tr/panel.d.ts +2 -0
- package/dist/types/panel/chat.d.ts +12 -0
- package/dist/types/panel/styles.d.ts +1 -0
- package/dist/types/panel/text.d.ts +2 -0
- package/dist/types/react.d.ts +29 -0
- package/dist/types/schema.gen.d.ts +9207 -0
- package/dist/types/types.d.ts +48 -0
- package/dist/types/yuva-chat.d.ts +1 -0
- package/dist/yuva-chat.js +201 -0
- package/dist/yuva.js +109 -0
- package/package.json +84 -4
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { components } from "../schema.gen.js";
|
|
2
|
+
type Schemas = components["schemas"];
|
|
3
|
+
export type ClientSession = Schemas["ClientSession"];
|
|
4
|
+
export type ClientSessionInfo = Schemas["ClientSessionInfo"];
|
|
5
|
+
export type ClientInbox = Schemas["ClientInbox"];
|
|
6
|
+
export type ClientContact = Schemas["ClientContact"];
|
|
7
|
+
export type ClientPresence = Schemas["ClientPresence"];
|
|
8
|
+
export type ClientConversation = Schemas["ClientConversation"];
|
|
9
|
+
export type ClientConversationPage = Schemas["ClientConversationPage"];
|
|
10
|
+
export type ClientConversationCreated = Schemas["ClientConversationCreated"];
|
|
11
|
+
export type ClientMessage = Schemas["ClientMessage"];
|
|
12
|
+
export type ClientMessagePage = Schemas["ClientMessagePage"];
|
|
13
|
+
export type ClientAttachment = Schemas["ClientAttachment"];
|
|
14
|
+
export type ClientReadState = Schemas["ClientReadState"];
|
|
15
|
+
export type ClientRealtimeMessage = Schemas["ClientRealtimeMessage"];
|
|
16
|
+
export type Problem = Schemas["Problem"];
|
|
17
|
+
export type Fetch = (url: string, init: RequestInit) => Promise<Response>;
|
|
18
|
+
export declare class ApiError extends Error {
|
|
19
|
+
readonly status: number;
|
|
20
|
+
readonly code: string;
|
|
21
|
+
constructor(status: number, code: string);
|
|
22
|
+
}
|
|
23
|
+
export interface Request {
|
|
24
|
+
method?: string;
|
|
25
|
+
json?: unknown;
|
|
26
|
+
body?: Blob;
|
|
27
|
+
headers?: Record<string, string>;
|
|
28
|
+
token?: string | null;
|
|
29
|
+
blob?: boolean;
|
|
30
|
+
}
|
|
31
|
+
export declare function call<T>(fetcher: Fetch, server: string, path: string, { method, json, body, headers, token, blob }?: Request): Promise<T>;
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { type Fetch, type ClientContact, type ClientConversation, type ClientConversationCreated, type ClientConversationPage, type ClientInbox, type ClientMessage, type ClientMessagePage, type ClientReadState, type ClientRealtimeMessage, type ClientSessionInfo } from "./api.js";
|
|
2
|
+
export type IdentityTokenSource = () => string | null | undefined | Promise<string | null | undefined>;
|
|
3
|
+
export interface YuvaStorage {
|
|
4
|
+
getItem(key: string): string | null;
|
|
5
|
+
setItem(key: string, value: string): void;
|
|
6
|
+
}
|
|
7
|
+
export interface YuvaClientOptions {
|
|
8
|
+
server: string;
|
|
9
|
+
channel: string;
|
|
10
|
+
identityToken?: IdentityTokenSource | null;
|
|
11
|
+
storage?: YuvaStorage | null;
|
|
12
|
+
fetch?: Fetch;
|
|
13
|
+
WebSocket?: typeof WebSocket;
|
|
14
|
+
idempotencyKeys?: boolean;
|
|
15
|
+
}
|
|
16
|
+
export interface StoredState {
|
|
17
|
+
visitor_id?: string;
|
|
18
|
+
session?: {
|
|
19
|
+
token: string;
|
|
20
|
+
expires_at: string;
|
|
21
|
+
sub: string | null;
|
|
22
|
+
};
|
|
23
|
+
[key: string]: unknown;
|
|
24
|
+
}
|
|
25
|
+
export interface ConnectionState {
|
|
26
|
+
state: "connecting" | "open" | "reconnecting" | "closed";
|
|
27
|
+
attempt: number;
|
|
28
|
+
}
|
|
29
|
+
export interface YuvaClientEvents {
|
|
30
|
+
event: ClientRealtimeMessage;
|
|
31
|
+
connection: ConnectionState;
|
|
32
|
+
session: {
|
|
33
|
+
session: ClientSessionInfo;
|
|
34
|
+
renewed: boolean;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export interface MessageInput {
|
|
38
|
+
body?: string;
|
|
39
|
+
files?: Blob[];
|
|
40
|
+
client_id?: string;
|
|
41
|
+
}
|
|
42
|
+
export interface ConversationInput extends MessageInput {
|
|
43
|
+
subject?: string;
|
|
44
|
+
}
|
|
45
|
+
export interface Page {
|
|
46
|
+
cursor?: string;
|
|
47
|
+
limit?: number;
|
|
48
|
+
}
|
|
49
|
+
export declare function storageKey(channel: string): string;
|
|
50
|
+
export declare function randomId(): string;
|
|
51
|
+
export declare class YuvaClient {
|
|
52
|
+
#private;
|
|
53
|
+
readonly server: string;
|
|
54
|
+
readonly channel: string;
|
|
55
|
+
constructor(options: YuvaClientOptions);
|
|
56
|
+
get session(): ClientSessionInfo | null;
|
|
57
|
+
get token(): string | null;
|
|
58
|
+
get connected(): boolean;
|
|
59
|
+
on<K extends keyof YuvaClientEvents>(type: K, handler: (value: YuvaClientEvents[K]) => void): () => void;
|
|
60
|
+
stored(): StoredState;
|
|
61
|
+
channelSettings(): Promise<ClientInbox>;
|
|
62
|
+
setIdentityToken(source: IdentityTokenSource | null): void;
|
|
63
|
+
start(): Promise<ClientSessionInfo>;
|
|
64
|
+
refresh(): Promise<ClientSessionInfo>;
|
|
65
|
+
reset(): void;
|
|
66
|
+
signOut(): Promise<void>;
|
|
67
|
+
connect(): Promise<void>;
|
|
68
|
+
disconnect(): void;
|
|
69
|
+
reconnect(): void;
|
|
70
|
+
listConversations(page?: Page): Promise<ClientConversationPage>;
|
|
71
|
+
getConversation(id: string): Promise<ClientConversation>;
|
|
72
|
+
startConversation(input: ConversationInput): Promise<ClientConversationCreated>;
|
|
73
|
+
listMessages(conversationId: string, page?: Page & {
|
|
74
|
+
order?: "asc" | "desc";
|
|
75
|
+
}): Promise<ClientMessagePage>;
|
|
76
|
+
sendMessage(conversationId: string, input: MessageInput): Promise<ClientMessage>;
|
|
77
|
+
markRead(conversationId: string, messageId?: string): Promise<ClientReadState>;
|
|
78
|
+
setTyping(conversationId: string, typing: boolean): Promise<void>;
|
|
79
|
+
setEmail(email: string): Promise<ClientContact>;
|
|
80
|
+
attachment(id: string): Promise<Blob>;
|
|
81
|
+
}
|
|
82
|
+
export declare function createYuvaClient(options: YuvaClientOptions): YuvaClient;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ClientRealtimeMessage } from "./api.js";
|
|
2
|
+
export interface RealtimeHandlers {
|
|
3
|
+
token(): string | null;
|
|
4
|
+
event(message: ClientRealtimeMessage): void;
|
|
5
|
+
sessionEnded(): void;
|
|
6
|
+
reconnecting(attempt: number): void;
|
|
7
|
+
}
|
|
8
|
+
export declare class Realtime {
|
|
9
|
+
#private;
|
|
10
|
+
readonly server: string;
|
|
11
|
+
readonly socketClass: typeof WebSocket;
|
|
12
|
+
readonly handlers: RealtimeHandlers;
|
|
13
|
+
constructor(server: string, socketClass: typeof WebSocket, handlers: RealtimeHandlers);
|
|
14
|
+
get connected(): boolean;
|
|
15
|
+
start(): void;
|
|
16
|
+
stop(): void;
|
|
17
|
+
reset(): void;
|
|
18
|
+
nudge(): void;
|
|
19
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type IdentityTokenSource, type Layout, type PanelModule } from "./types.js";
|
|
2
|
+
export declare function contrastOn(color: string): string;
|
|
3
|
+
export declare class YuvaChatElement extends HTMLElement {
|
|
4
|
+
#private;
|
|
5
|
+
static observedAttributes: string[];
|
|
6
|
+
static loadPanel: () => Promise<PanelModule>;
|
|
7
|
+
constructor();
|
|
8
|
+
get layout(): Layout;
|
|
9
|
+
get channel(): string | null;
|
|
10
|
+
get server(): string;
|
|
11
|
+
get locale(): string;
|
|
12
|
+
get isOpen(): boolean;
|
|
13
|
+
get unread(): number;
|
|
14
|
+
setIdentityToken(source: IdentityTokenSource | null): void;
|
|
15
|
+
signOut(): Promise<void>;
|
|
16
|
+
connectedCallback(): void;
|
|
17
|
+
disconnectedCallback(): void;
|
|
18
|
+
attributeChangedCallback(name: string, previous: string | null, value: string | null): void;
|
|
19
|
+
open(): Promise<void>;
|
|
20
|
+
close(): void;
|
|
21
|
+
toggle(): Promise<void> | void;
|
|
22
|
+
}
|
|
23
|
+
export declare function define(): void;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { MessageDescriptor, Messages } from "@lingui/core";
|
|
2
|
+
export declare const sourceLocale = "en";
|
|
3
|
+
export declare function resolveLocale(...candidates: (string | null | undefined)[]): string;
|
|
4
|
+
export declare function directionOf(locale: string): "ltr" | "rtl";
|
|
5
|
+
export declare function catalogFor(locale: string): Messages;
|
|
6
|
+
export declare function translatePlain(messages: Messages, descriptor: MessageDescriptor): string;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { createYuvaClient, YuvaClient, type ConnectionState, type ConversationInput, type IdentityTokenSource, type MessageInput, type Page, type StoredState, type YuvaClientEvents, type YuvaClientOptions, type YuvaStorage, } from "./client/client.js";
|
|
2
|
+
export { ApiError, type Fetch, type ClientAttachment, type ClientContact, type ClientConversation, type ClientConversationCreated, type ClientConversationPage, type ClientInbox, type ClientMessage, type ClientMessagePage, type ClientPresence, type ClientReadState, type ClientRealtimeMessage, type ClientSession, type ClientSessionInfo, type Problem, } from "./client/api.js";
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type PanelController, type PanelHost } from "../types.js";
|
|
2
|
+
export declare class Chat implements PanelController {
|
|
3
|
+
#private;
|
|
4
|
+
constructor(host: PanelHost);
|
|
5
|
+
update(): void;
|
|
6
|
+
opened(): void;
|
|
7
|
+
closed(): void;
|
|
8
|
+
identityChanged(): void;
|
|
9
|
+
signOut(): Promise<void>;
|
|
10
|
+
destroy(): void;
|
|
11
|
+
}
|
|
12
|
+
export declare function mount(host: PanelHost): PanelController;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const styles = "\n[hidden] { display: none !important; }\n.header {\n display: flex;\n align-items: center;\n gap: 10px;\n padding-block: 12px;\n padding-inline: 14px 10px;\n background: var(--yuva-accent);\n color: var(--yuva-on-accent);\n}\n.heading { flex: 1; min-inline-size: 0; }\n.title {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.status { display: flex; align-items: center; gap: 6px; font-size: 13px; opacity: 0.9; }\n.dot { inline-size: 8px; block-size: 8px; border-radius: 50%; background: #22c55e; box-shadow: 0 0 0 2px rgb(255 255 255 / 0.6); }\n.dot.away { background: #9ca3af; }\n.avatars { display: flex; }\n.avatars .avatar { margin-inline-start: -8px; box-shadow: 0 0 0 2px var(--yuva-accent); }\n.avatars .avatar:first-child { margin-inline-start: 0; }\n.avatar {\n display: grid;\n place-items: center;\n flex: none;\n inline-size: 28px;\n block-size: 28px;\n border-radius: 50%;\n background: var(--yuva-soft);\n color: var(--yuva-fg);\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n}\n.icon {\n display: grid;\n place-items: center;\n flex: none;\n inline-size: 32px;\n block-size: 32px;\n padding: 0;\n border: 0;\n border-radius: 8px;\n background: transparent;\n color: inherit;\n cursor: pointer;\n}\n.icon:hover { background: rgb(127 127 127 / 0.18); }\n.icon:focus-visible { outline: 2px solid currentColor; outline-offset: -4px; }\n[dir=\"rtl\"] .flip { transform: scaleX(-1); }\n.body { position: relative; flex: 1; min-block-size: 0; display: flex; flex-direction: column; }\n.scroll { flex: 1; overflow-y: auto; overscroll-behavior: contain; padding: 14px; display: flex; flex-direction: column; gap: 4px; }\n.center { flex: 1; display: grid; place-content: center; gap: 6px; padding: 24px; text-align: center; }\n.empty { margin: 0; font-weight: 600; }\n.hint { margin: 0; color: var(--yuva-muted); font-size: 14px; }\n.list { list-style: none; margin: 0; padding: 6px; overflow-y: auto; flex: 1; }\n.item {\n display: flex;\n gap: 10px;\n align-items: center;\n inline-size: 100%;\n padding: 10px;\n border: 0;\n border-radius: 10px;\n background: transparent;\n color: inherit;\n font: inherit;\n text-align: start;\n cursor: pointer;\n}\n.item:hover, .item:focus-visible { background: var(--yuva-soft); outline: none; }\n.item-main { flex: 1; min-inline-size: 0; }\n.item-top { display: flex; gap: 8px; justify-content: space-between; }\n.item-subject, .item-preview { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.item-subject { font-weight: 600; }\n.item-preview { color: var(--yuva-muted); font-size: 14px; }\n.item.unread .item-preview { color: var(--yuva-fg); font-weight: 600; }\n.item-time { flex: none; color: var(--yuva-muted); font-size: 12px; }\n.unread-dot { flex: none; inline-size: 9px; block-size: 9px; border-radius: 50%; background: var(--yuva-accent); }\n.primary {\n margin: 10px;\n padding: 10px 14px;\n border: 0;\n border-radius: 10px;\n background: var(--yuva-accent);\n color: var(--yuva-on-accent);\n font: inherit;\n font-weight: 600;\n cursor: pointer;\n}\n.row { display: flex; gap: 8px; align-items: flex-end; max-inline-size: 85%; }\n.row.mine { align-self: flex-end; }\n.row.theirs .avatar { margin-block-end: 2px; }\n.avatar img { inline-size: 100%; block-size: 100%; border-radius: 50%; object-fit: cover; }\n.group-gap { margin-block-start: 8px; }\n.author { margin: 6px 0 2px; margin-inline-start: 36px; color: var(--yuva-muted); font-size: 12px; }\n.bubble {\n padding: 8px 12px;\n border-radius: 16px;\n background: var(--yuva-soft);\n overflow-wrap: anywhere;\n white-space: normal;\n}\n.mine .bubble { background: var(--yuva-accent); color: var(--yuva-on-accent); border-end-end-radius: 4px; }\n.theirs .bubble { border-end-start-radius: 4px; }\n.bubble a { color: inherit; text-decoration: underline; }\n.bubble code { font-family: ui-monospace, Menlo, monospace; font-size: 13px; padding: 1px 4px; border-radius: 4px; background: rgb(127 127 127 / 0.2); }\n.bubble pre { margin: 4px 0; padding: 8px; border-radius: 8px; background: rgb(127 127 127 / 0.2); font-family: ui-monospace, Menlo, monospace; font-size: 13px; white-space: pre-wrap; }\n.greeting { align-self: flex-start; max-inline-size: 85%; }\n.files { display: flex; flex-direction: column; gap: 4px; margin-block-start: 4px; }\n.files img { display: block; max-inline-size: 100%; max-block-size: 220px; border-radius: 10px; cursor: zoom-in; }\n.file {\n display: inline-flex;\n gap: 6px;\n align-items: center;\n padding: 6px 10px;\n border: 1px solid currentColor;\n border-radius: 8px;\n background: transparent;\n color: inherit;\n font: inherit;\n font-size: 13px;\n cursor: pointer;\n}\n.meta { align-self: flex-end; color: var(--yuva-muted); font-size: 12px; margin-block-start: 2px; }\n.meta.failed { color: var(--yuva-danger); }\n.link { padding: 0; border: 0; background: none; color: inherit; font: inherit; text-decoration: underline; cursor: pointer; }\n.typing { display: flex; gap: 6px; align-items: center; color: var(--yuva-muted); font-size: 13px; margin-block-start: 6px; }\n.typing i { display: inline-block; inline-size: 6px; block-size: 6px; border-radius: 50%; background: currentColor; animation: blink 1.2s infinite both; }\n.typing i:nth-child(2) { animation-delay: 0.2s; }\n.typing i:nth-child(3) { animation-delay: 0.4s; }\n@keyframes blink { 0%, 80%, 100% { opacity: 0.25; } 40% { opacity: 1; } }\n@media (prefers-reduced-motion: reduce) { .typing i { animation: none; } }\n.card { margin-block-start: 10px; padding: 12px; border: 1px solid var(--yuva-border); border-radius: 12px; font-size: 14px; }\n.card p { margin: 0 0 8px; }\n.card form { display: flex; gap: 6px; }\n.card input {\n flex: 1;\n min-inline-size: 0;\n padding: 8px 10px;\n border: 1px solid var(--yuva-border);\n border-radius: 8px;\n background: var(--yuva-bg);\n color: inherit;\n font: inherit;\n}\n.card button { padding: 8px 12px; border: 0; border-radius: 8px; background: var(--yuva-accent); color: var(--yuva-on-accent); font: inherit; font-weight: 600; cursor: pointer; }\n.card .error { margin: 6px 0 0; color: var(--yuva-danger); }\n.composer { border-block-start: 1px solid var(--yuva-border); padding: 8px; }\n.composer form { display: flex; gap: 4px; align-items: flex-end; }\n.composer textarea {\n flex: 1;\n min-inline-size: 0;\n box-sizing: border-box;\n block-size: 38px;\n max-block-size: 140px;\n padding: 8px 10px;\n border: 0;\n border-radius: 10px;\n background: transparent;\n color: inherit;\n font: inherit;\n resize: none;\n outline: none;\n}\n.composer .icon { color: var(--yuva-muted); }\n.composer .send { color: var(--yuva-accent); }\n.composer .send:disabled { opacity: 0.4; cursor: default; }\n.chips { display: flex; flex-wrap: wrap; gap: 6px; padding: 0 6px 6px; }\n.chip { display: inline-flex; gap: 4px; align-items: center; max-inline-size: 100%; padding: 2px 4px 2px 10px; border-radius: 999px; background: var(--yuva-soft); font-size: 13px; }\n.chip span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-inline-size: 180px; }\n.chip .icon { inline-size: 22px; block-size: 22px; }\n.banner { padding: 6px 12px; background: var(--yuva-soft); color: var(--yuva-muted); font-size: 13px; text-align: center; }\n@media (max-width: 480px) { .composer textarea, .card input { font-size: 16px; } }\n.sr { position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }\n";
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type ReactElement, type ReactNode } from "react";
|
|
2
|
+
import type { ClientConversation, ClientMessage } from "./client/api.js";
|
|
3
|
+
import type { MessageInput, YuvaClient } from "./client/client.js";
|
|
4
|
+
export interface YuvaProviderProps {
|
|
5
|
+
client: YuvaClient;
|
|
6
|
+
connect?: boolean;
|
|
7
|
+
children?: ReactNode;
|
|
8
|
+
}
|
|
9
|
+
export declare function YuvaProvider({ client, connect, children }: YuvaProviderProps): ReactElement;
|
|
10
|
+
export declare function useYuva(): YuvaClient;
|
|
11
|
+
export interface ConversationsResult {
|
|
12
|
+
conversations: ClientConversation[];
|
|
13
|
+
loading: boolean;
|
|
14
|
+
error: unknown;
|
|
15
|
+
hasMore: boolean;
|
|
16
|
+
loadMore(): Promise<void>;
|
|
17
|
+
reload(): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
export declare function useConversations(): ConversationsResult;
|
|
20
|
+
export interface MessagesResult {
|
|
21
|
+
messages: ClientMessage[];
|
|
22
|
+
loading: boolean;
|
|
23
|
+
error: unknown;
|
|
24
|
+
hasMore: boolean;
|
|
25
|
+
loadOlder(): Promise<void>;
|
|
26
|
+
send(input: MessageInput | string): Promise<ClientMessage>;
|
|
27
|
+
markRead(): Promise<void>;
|
|
28
|
+
}
|
|
29
|
+
export declare function useMessages(conversationId: string | null | undefined): MessagesResult;
|