@omniloy/sofia-sdk 1.0.10 → 1.0.12
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/legacy/webcomponents.d.ts +155 -0
- package/dist/legacy/webcomponents.es.js +918 -327
- package/dist/legacy/webcomponents.umd.js +918 -327
- package/dist/react/index.css +59 -39
- package/dist/react/index.d.ts +155 -0
- package/dist/react/index.es.js +756 -133
- package/dist/webcomponents.d.ts +155 -0
- package/dist/webcomponents.es.js +634 -39
- package/dist/webcomponents.umd.js +634 -39
- package/package.json +1 -1
package/dist/react/index.css
CHANGED
|
@@ -230,6 +230,7 @@
|
|
|
230
230
|
--color-gray-200: oklch(92.8% 0.006 264.531);
|
|
231
231
|
--color-gray-500: oklch(55.1% 0.027 264.364);
|
|
232
232
|
--color-gray-900: oklch(21% 0.034 264.665);
|
|
233
|
+
--color-zinc-500: oklch(55.2% 0.016 285.938);
|
|
233
234
|
--color-zinc-900: oklch(21% 0.006 285.885);
|
|
234
235
|
--color-sidebar: var(--sidebar);
|
|
235
236
|
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
@@ -3321,85 +3322,104 @@
|
|
|
3321
3322
|
}
|
|
3322
3323
|
}
|
|
3323
3324
|
|
|
3325
|
+
/* Escala de encabezados calibrada al ancho del panel del chat (~380px) con
|
|
3326
|
+
cuerpo de 14px. La escala anterior (26/24/22/20/18px) venía de la tipografía
|
|
3327
|
+
por defecto de un documento a ancho completo: en el panel el encabezado
|
|
3328
|
+
dominaba el mensaje y los seis niveles quedaban a 2px unos de otros, sin
|
|
3329
|
+
jerarquía legible. Aquí h1-h3 bajan de tamaño y h4-h6 se diferencian por
|
|
3330
|
+
peso, no por tamaño. Los márgenes usan --spacing (rem): un host que altere
|
|
3331
|
+
el font-size de :root los escala, aunque los tamaños en px no se muevan. */
|
|
3332
|
+
|
|
3324
3333
|
.omniscribe_markdown-h1 {
|
|
3325
|
-
margin-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3334
|
+
margin-top: calc(var(--spacing) * 5) /* 20px */;
|
|
3335
|
+
margin-bottom: calc(var(--spacing) * 2) /* 8px */;
|
|
3336
|
+
scroll-margin: calc(var(--spacing) * 20) /* 80px */;
|
|
3337
|
+
font-size: var(--text-xl) /* 20px */;
|
|
3338
|
+
line-height: var(--text-xl--line-height);
|
|
3339
|
+
font-weight: var(--font-weight-bold) /* 700 */;
|
|
3330
3340
|
letter-spacing: var(--tracking-tight) /* -0.025em */;
|
|
3341
|
+
&:first-child {
|
|
3342
|
+
margin-top: calc(var(--spacing) * 0);
|
|
3343
|
+
}
|
|
3331
3344
|
&:last-child {
|
|
3332
|
-
margin-bottom: calc(var(--spacing) * 0)
|
|
3345
|
+
margin-bottom: calc(var(--spacing) * 0);
|
|
3333
3346
|
}
|
|
3334
3347
|
}
|
|
3335
3348
|
|
|
3336
3349
|
.omniscribe_markdown-h2 {
|
|
3337
|
-
margin-
|
|
3338
|
-
margin-
|
|
3339
|
-
scroll-margin: calc(var(--spacing) * 20)
|
|
3340
|
-
font-size: var(--text-
|
|
3341
|
-
line-height: var(--text-
|
|
3350
|
+
margin-top: calc(var(--spacing) * 4) /* 16px */;
|
|
3351
|
+
margin-bottom: calc(var(--spacing) * 2) /* 8px */;
|
|
3352
|
+
scroll-margin: calc(var(--spacing) * 20);
|
|
3353
|
+
font-size: var(--text-lg) /* 18px */;
|
|
3354
|
+
line-height: var(--text-lg--line-height);
|
|
3342
3355
|
font-weight: var(--font-weight-semibold) /* 600 */;
|
|
3343
|
-
letter-spacing: var(--tracking-tight)
|
|
3356
|
+
letter-spacing: var(--tracking-tight);
|
|
3344
3357
|
&:first-child {
|
|
3345
|
-
margin-top: calc(var(--spacing) * 0)
|
|
3358
|
+
margin-top: calc(var(--spacing) * 0);
|
|
3346
3359
|
}
|
|
3347
3360
|
&:last-child {
|
|
3348
|
-
margin-bottom: calc(var(--spacing) * 0)
|
|
3361
|
+
margin-bottom: calc(var(--spacing) * 0);
|
|
3349
3362
|
}
|
|
3350
3363
|
}
|
|
3364
|
+
|
|
3351
3365
|
.omniscribe_markdown-h3 {
|
|
3352
|
-
margin-
|
|
3353
|
-
margin-
|
|
3354
|
-
scroll-margin: calc(var(--spacing) * 20)
|
|
3355
|
-
font-size: var(--text-
|
|
3356
|
-
line-height: var(--text-
|
|
3366
|
+
margin-top: calc(var(--spacing) * 4) /* 16px */;
|
|
3367
|
+
margin-bottom: calc(var(--spacing) * 2) /* 8px */;
|
|
3368
|
+
scroll-margin: calc(var(--spacing) * 20);
|
|
3369
|
+
font-size: var(--text-base) /* 16px */;
|
|
3370
|
+
line-height: var(--text-base--line-height);
|
|
3357
3371
|
font-weight: var(--font-weight-semibold) /* 600 */;
|
|
3358
|
-
letter-spacing: var(--tracking-tight) /* -0.025em */;
|
|
3359
3372
|
&:first-child {
|
|
3360
|
-
margin-top: calc(var(--spacing) * 0)
|
|
3373
|
+
margin-top: calc(var(--spacing) * 0);
|
|
3361
3374
|
}
|
|
3362
3375
|
&:last-child {
|
|
3363
|
-
margin-bottom: calc(var(--spacing) * 0)
|
|
3376
|
+
margin-bottom: calc(var(--spacing) * 0);
|
|
3364
3377
|
}
|
|
3365
3378
|
}
|
|
3366
3379
|
|
|
3380
|
+
/* h4-h6 comparten el tamaño del cuerpo (14px) y se distinguen por peso.
|
|
3381
|
+
Bajar de 14px haría el encabezado menos legible que el texto que titula. */
|
|
3367
3382
|
.omniscribe_markdown-h4 {
|
|
3368
|
-
margin-
|
|
3369
|
-
margin-
|
|
3370
|
-
scroll-margin: calc(var(--spacing) * 20)
|
|
3371
|
-
font-size: var(--text-
|
|
3372
|
-
line-height: var(--text-
|
|
3373
|
-
font-weight: var(--font-weight-
|
|
3374
|
-
letter-spacing: var(--tracking-tight) /* -0.025em */;
|
|
3383
|
+
margin-top: calc(var(--spacing) * 3) /* 12px */;
|
|
3384
|
+
margin-bottom: calc(var(--spacing) * 1) /* 4px */;
|
|
3385
|
+
scroll-margin: calc(var(--spacing) * 20);
|
|
3386
|
+
font-size: var(--text-sm) /* 14px */;
|
|
3387
|
+
line-height: var(--text-sm--line-height);
|
|
3388
|
+
font-weight: var(--font-weight-bold) /* 700 */;
|
|
3375
3389
|
&:first-child {
|
|
3376
|
-
margin-top: calc(var(--spacing) * 0)
|
|
3390
|
+
margin-top: calc(var(--spacing) * 0);
|
|
3377
3391
|
}
|
|
3378
3392
|
&:last-child {
|
|
3379
|
-
margin-bottom: calc(var(--spacing) * 0)
|
|
3393
|
+
margin-bottom: calc(var(--spacing) * 0);
|
|
3380
3394
|
}
|
|
3381
3395
|
}
|
|
3396
|
+
|
|
3382
3397
|
.omniscribe_markdown-h5 {
|
|
3383
|
-
margin-
|
|
3384
|
-
|
|
3385
|
-
|
|
3398
|
+
margin-top: calc(var(--spacing) * 3) /* 12px */;
|
|
3399
|
+
margin-bottom: calc(var(--spacing) * 1) /* 4px */;
|
|
3400
|
+
font-size: var(--text-sm) /* 14px */;
|
|
3401
|
+
line-height: var(--text-sm--line-height);
|
|
3386
3402
|
font-weight: var(--font-weight-semibold) /* 600 */;
|
|
3387
3403
|
&:first-child {
|
|
3388
|
-
margin-top: calc(var(--spacing) * 0)
|
|
3404
|
+
margin-top: calc(var(--spacing) * 0);
|
|
3389
3405
|
}
|
|
3390
3406
|
&:last-child {
|
|
3391
|
-
margin-bottom: calc(var(--spacing) * 0)
|
|
3407
|
+
margin-bottom: calc(var(--spacing) * 0);
|
|
3392
3408
|
}
|
|
3393
3409
|
}
|
|
3394
3410
|
|
|
3395
3411
|
.omniscribe_markdown-h6 {
|
|
3396
|
-
margin-
|
|
3412
|
+
margin-top: calc(var(--spacing) * 3) /* 12px */;
|
|
3413
|
+
margin-bottom: calc(var(--spacing) * 1) /* 4px */;
|
|
3414
|
+
font-size: var(--text-sm) /* 14px */;
|
|
3415
|
+
line-height: var(--text-sm--line-height);
|
|
3397
3416
|
font-weight: var(--font-weight-semibold) /* 600 */;
|
|
3417
|
+
color: var(--color-zinc-500);
|
|
3398
3418
|
&:first-child {
|
|
3399
|
-
margin-top: calc(var(--spacing) * 0)
|
|
3419
|
+
margin-top: calc(var(--spacing) * 0);
|
|
3400
3420
|
}
|
|
3401
3421
|
&:last-child {
|
|
3402
|
-
margin-bottom: calc(var(--spacing) * 0)
|
|
3422
|
+
margin-bottom: calc(var(--spacing) * 0);
|
|
3403
3423
|
}
|
|
3404
3424
|
}
|
|
3405
3425
|
|
package/dist/react/index.d.ts
CHANGED
|
@@ -3,6 +3,9 @@ import { JSX } from 'react/jsx-runtime';
|
|
|
3
3
|
import * as React_2 from 'react';
|
|
4
4
|
import { VariantProps } from 'class-variance-authority';
|
|
5
5
|
|
|
6
|
+
/** Where audio stopped flowing, as reported by the recording pipeline. */
|
|
7
|
+
export declare type AudioLossCause = 'mic' | 'network' | 'server';
|
|
8
|
+
|
|
6
9
|
export declare function Button({ className, variant, size, asChild, isDisabled, isLoading, text, whitespace, rounded, type, ...props }: ButtonProps): JSX.Element;
|
|
7
10
|
|
|
8
11
|
declare type ButtonProps = React_2.ComponentProps<'button'> & VariantProps<typeof buttonVariants> & {
|
|
@@ -63,6 +66,11 @@ declare interface InsertionPreviewClassNames {
|
|
|
63
66
|
cancelButton?: string;
|
|
64
67
|
}
|
|
65
68
|
|
|
69
|
+
/** Coarse area of the widget the clinician touched. */
|
|
70
|
+
export declare type InteractionKind = 'recording' | 'chat' | 'settings' | 'report' | 'transcript' | 'history' | 'widget';
|
|
71
|
+
|
|
72
|
+
export declare type KnownSdkEventName = 'recording.started' | 'recording.stopped' | 'recording.audio_lost' | 'recording.microphone_disconnected' | 'recording.heartbeat' | 'activity.interaction' | 'activity.typing' | 'report.generation_started' | 'report.settled' | 'lifecycle.ready' | 'lifecycle.closed';
|
|
73
|
+
|
|
66
74
|
export declare enum LanguageCode {
|
|
67
75
|
ar = "ar",
|
|
68
76
|
ca = "ca",
|
|
@@ -252,8 +260,152 @@ export declare interface OmniscribeProps {
|
|
|
252
260
|
* the appropriate action. To change the delivered shape, change templateExtras.
|
|
253
261
|
*/
|
|
254
262
|
handleExtras?: (extras: Extra[]) => void;
|
|
263
|
+
/**
|
|
264
|
+
* Subscribe to the SDK's activity stream.
|
|
265
|
+
*
|
|
266
|
+
* Called with a typed, PHI-free event whenever something the host asked
|
|
267
|
+
* for happens inside the widget. Payloads carry only enums, booleans and
|
|
268
|
+
* numbers — never clinical content, message text or patient identifiers.
|
|
269
|
+
* Clinical content has its own explicitly scoped channels (`handleReport`,
|
|
270
|
+
* `onReportApply`, `handleExtras`).
|
|
271
|
+
*
|
|
272
|
+
* The primary use case is knowing whether the clinician is working, so the
|
|
273
|
+
* host can run an inactivity timeout:
|
|
274
|
+
* ```
|
|
275
|
+
* onEvent={e => {
|
|
276
|
+
* if (e.name === 'recording.started') idleTimer.cancel();
|
|
277
|
+
* if (e.name === 'recording.stopped') idleTimer.start();
|
|
278
|
+
* if (e.family === 'activity') idleTimer.reset();
|
|
279
|
+
* }}
|
|
280
|
+
* ```
|
|
281
|
+
* Suppress the timer between `report.generation_started` and
|
|
282
|
+
* `report.settled` — generation runs for tens of seconds with no user
|
|
283
|
+
* input, and closing the widget there loses the note.
|
|
284
|
+
*
|
|
285
|
+
* If the host must keep an *external* session alive (an auto-logout on
|
|
286
|
+
* inactivity), key off `recording.heartbeat` instead of the
|
|
287
|
+
* `started`/`stopped` pair. It beats every ~30s while audio is actually
|
|
288
|
+
* flowing to the transcriber, needs no host-side state, and stops by
|
|
289
|
+
* itself the moment a recording silently breaks:
|
|
290
|
+
* ```
|
|
291
|
+
* onEvent={e => {
|
|
292
|
+
* if (e.name === 'recording.heartbeat') session.keepAlive();
|
|
293
|
+
* }}
|
|
294
|
+
* ```
|
|
295
|
+
*
|
|
296
|
+
* Delivered asynchronously on a microtask, so a slow handler cannot block
|
|
297
|
+
* recording. Requires `eventSubscriptions`; without it nothing is sent.
|
|
298
|
+
*/
|
|
299
|
+
onEvent?: SdkEventHandler;
|
|
300
|
+
/**
|
|
301
|
+
* Which events `onEvent` should receive. Exact names
|
|
302
|
+
* (`'recording.started'`), family wildcards (`'recording.*'`), or `'*'`.
|
|
303
|
+
*
|
|
304
|
+
* Omitted or empty means no events are delivered — subscription is
|
|
305
|
+
* explicit so the SDK never does work for a listener that does not exist.
|
|
306
|
+
*/
|
|
307
|
+
eventSubscriptions?: SdkEventSubscription[];
|
|
255
308
|
}
|
|
256
309
|
|
|
310
|
+
export declare type RecordingMode = 'consultation' | 'dictation';
|
|
311
|
+
|
|
312
|
+
export declare interface SdkEvent<N extends SdkEventName = SdkEventName> {
|
|
313
|
+
/** Fully qualified name, e.g. `'recording.started'`. */
|
|
314
|
+
name: N;
|
|
315
|
+
/** The part of `name` before the dot. */
|
|
316
|
+
family: SdkEventFamily;
|
|
317
|
+
level: 'info' | 'warn' | 'error';
|
|
318
|
+
/** ISO-8601. */
|
|
319
|
+
ts: string;
|
|
320
|
+
/**
|
|
321
|
+
* Monotonic per page load. Restores ordering that the fire-and-forget
|
|
322
|
+
* analytics POSTs cannot guarantee.
|
|
323
|
+
*/
|
|
324
|
+
seq: number;
|
|
325
|
+
sdkVersion: string;
|
|
326
|
+
/** Random per-session UUID. Not an identifier for a person. */
|
|
327
|
+
sessionId: string | null;
|
|
328
|
+
payload: SdkEventPayload<N>;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Public, host-facing SDK event vocabulary.
|
|
333
|
+
*
|
|
334
|
+
* PRIVACY INVARIANT — read before adding an event.
|
|
335
|
+
* No payload field may carry user-, patient-, or clinician-derived text.
|
|
336
|
+
* Every field is a string-literal union, a boolean, or a number. Errors
|
|
337
|
+
* travel as codes, never as messages; reports as counts, never as content.
|
|
338
|
+
* A host that needs clinical content already has purpose-built, explicitly
|
|
339
|
+
* scoped channels for it (`handleReport`, `onReportApply`, `handleExtras`).
|
|
340
|
+
* `sdk-events.types.test.ts` fails the build if an unconstrained `string`
|
|
341
|
+
* appears in `SdkEventPayloadMap`.
|
|
342
|
+
*
|
|
343
|
+
* This vocabulary is deliberately separate from the internal analytics
|
|
344
|
+
* `AppEventName`. Merging them would make every internal telemetry addition
|
|
345
|
+
* a public breaking change.
|
|
346
|
+
*/
|
|
347
|
+
export declare type SdkEventFamily = 'recording' | 'activity' | 'report' | 'lifecycle';
|
|
348
|
+
|
|
349
|
+
/** Handler shape for the `onEvent` prop. */
|
|
350
|
+
export declare type SdkEventHandler = (event: SdkEvent) => void;
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Widened on purpose. New event names ship in minor releases, and a closed
|
|
354
|
+
* union would make every addition a type-level break for hosts that switch
|
|
355
|
+
* exhaustively. Hosts wanting exhaustiveness narrow to `KnownSdkEventName`.
|
|
356
|
+
*/
|
|
357
|
+
export declare type SdkEventName = KnownSdkEventName | (string & {});
|
|
358
|
+
|
|
359
|
+
declare type SdkEventPayload<N extends SdkEventName> = N extends KnownSdkEventName ? SdkEventPayloadMap[N] : Record<string, unknown>;
|
|
360
|
+
|
|
361
|
+
export declare interface SdkEventPayloadMap {
|
|
362
|
+
'recording.started': {
|
|
363
|
+
mode: RecordingMode;
|
|
364
|
+
};
|
|
365
|
+
'recording.stopped': {
|
|
366
|
+
mode: RecordingMode;
|
|
367
|
+
durationSeconds: number;
|
|
368
|
+
};
|
|
369
|
+
'recording.audio_lost': {
|
|
370
|
+
cause: AudioLossCause;
|
|
371
|
+
/**
|
|
372
|
+
* For `mic` / `network`: length of the gap, reported once audio
|
|
373
|
+
* recovers. For `server`: the recording position at which the socket
|
|
374
|
+
* closed — capture is torn down on the spot, so there is no gap to
|
|
375
|
+
* measure.
|
|
376
|
+
*/
|
|
377
|
+
durationSeconds: number;
|
|
378
|
+
};
|
|
379
|
+
'recording.microphone_disconnected': Record<string, never>;
|
|
380
|
+
/**
|
|
381
|
+
* Audio is actually flowing to the transcriber. Emitted from the
|
|
382
|
+
* audio-chunk send path, throttled — see `recording-heartbeat.ts`.
|
|
383
|
+
* A host that must keep an external session alive while the clinician
|
|
384
|
+
* records should key off this, not off `started`/`stopped`: it needs no
|
|
385
|
+
* host-side state and stops by itself the moment a recording silently
|
|
386
|
+
* breaks.
|
|
387
|
+
*/
|
|
388
|
+
'recording.heartbeat': Record<string, never>;
|
|
389
|
+
'activity.interaction': {
|
|
390
|
+
kind: InteractionKind;
|
|
391
|
+
};
|
|
392
|
+
'activity.typing': {
|
|
393
|
+
surface: TypingSurface;
|
|
394
|
+
};
|
|
395
|
+
'report.generation_started': Record<string, never>;
|
|
396
|
+
'report.settled': {
|
|
397
|
+
ok: boolean;
|
|
398
|
+
};
|
|
399
|
+
'lifecycle.ready': Record<string, never>;
|
|
400
|
+
'lifecycle.closed': Record<string, never>;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* What a host asks for: an exact name, a family wildcard (`'recording.*'`),
|
|
405
|
+
* or everything (`'*'`).
|
|
406
|
+
*/
|
|
407
|
+
export declare type SdkEventSubscription = KnownSdkEventName | `${SdkEventFamily}.*` | '*';
|
|
408
|
+
|
|
257
409
|
/**
|
|
258
410
|
* Get a value from local storage (decrypted)
|
|
259
411
|
* @param key - The key to get the value from
|
|
@@ -333,6 +485,9 @@ declare type TTranscriptorSelect = {
|
|
|
333
485
|
label: string;
|
|
334
486
|
}[];
|
|
335
487
|
|
|
488
|
+
/** Which free-text surface received keystrokes. Never the text itself. */
|
|
489
|
+
export declare type TypingSurface = 'chat' | 'note';
|
|
490
|
+
|
|
336
491
|
/**
|
|
337
492
|
* Host-provided callback that returns whatever the doctor has already written
|
|
338
493
|
* in SINA/HIS, keyed by template property id (e.g. `{ chief_complaint: '...',
|