Skip to content

Commit 2bd993a

Browse files
committed
feat: add addNotification function for interactive instruments
1 parent bfee61b commit 2bd993a

File tree

4 files changed

+23
-3
lines changed

4 files changed

+23
-3
lines changed

packages/react-core/src/components/InteractiveContent/InteractiveContent.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import React, { useCallback, useEffect, useRef, useState } from 'react';
22

33
import { Button, Separator } from '@douglasneuroinformatics/libui/components';
4-
import { useTheme, useTranslation } from '@douglasneuroinformatics/libui/hooks';
4+
import { useNotificationsStore, useTheme, useTranslation } from '@douglasneuroinformatics/libui/hooks';
55
import type { Theme } from '@douglasneuroinformatics/libui/hooks';
6-
import type { Language } from '@opendatacapture/runtime-core';
6+
import type { Language, RuntimeNotification } from '@opendatacapture/runtime-core';
77
import { $Json } from '@opendatacapture/schemas/core';
88
import type { Json } from '@opendatacapture/schemas/core';
99
import { FullscreenIcon, ZoomInIcon, ZoomOutIcon } from 'lucide-react';
@@ -20,6 +20,7 @@ export const InteractiveContent = React.memo<InteractiveContentProps>(function I
2020
bundle,
2121
onSubmit
2222
}) {
23+
const addNotification = useNotificationsStore((store) => store.addNotification);
2324
const { changeLanguage, resolvedLanguage } = useTranslation();
2425
const [_, updateTheme] = useTheme();
2526
const [scale, setScale] = useState(100);
@@ -80,6 +81,12 @@ export const InteractiveContent = React.memo<InteractiveContentProps>(function I
8081
return () => document.removeEventListener('done', handleDoneEvent, false);
8182
}, [handleDoneEvent]);
8283

84+
useEffect(() => {
85+
const handler = (event: CustomEvent<RuntimeNotification>) => addNotification(event.detail);
86+
document.addEventListener('addNotification', handler, false);
87+
return () => document.removeEventListener('addNotification', handler, false);
88+
}, []);
89+
8390
const dimensions = `${(100 / scale) * 100}%`;
8491

8592
return (

packages/react-core/src/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22

33
import type { Theme } from '@douglasneuroinformatics/libui/hooks';
44
import type { Language } from '@douglasneuroinformatics/libui/i18n';
5-
import type { AnyUnilingualInstrument, Json } from '@opendatacapture/runtime-core';
5+
import type { AnyUnilingualInstrument, Json, RuntimeNotification } from '@opendatacapture/runtime-core';
66
import type { Subject } from '@opendatacapture/schemas/subject';
77
import type { Promisable } from 'type-fest';
88

99
declare global {
1010
interface GlobalEventHandlersEventMap {
11+
addNotification: CustomEvent<RuntimeNotification>;
1112
changeLanguage: CustomEvent<Language>;
1213
changeTheme: CustomEvent<Theme>;
1314
done: CustomEvent<Json>;

packages/runtime-core/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export * from './define.js';
22
export * from './i18n.js';
3+
export * from './notifications.js';
34
export type * from './types/core.js';
45
export type * from './types/instrument.base.js';
56
export type * from './types/instrument.core.js';
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export type RuntimeNotification = {
2+
message?: string;
3+
title?: string;
4+
type: 'error' | 'info' | 'success' | 'warning';
5+
variant?: 'critical' | 'standard';
6+
};
7+
8+
/** Display a notification in ODC for the user during an interactive instrument. Please note this will not work with forms. */
9+
export function addNotification(notification: RuntimeNotification) {
10+
window.parent.document.dispatchEvent(new CustomEvent('addNotification', { detail: notification }));
11+
}

0 commit comments

Comments
 (0)