Skip to content

Commit d5f65fc

Browse files
committed
Render outputs commit
1 parent cdf7a8a commit d5f65fc

File tree

1 file changed

+34
-17
lines changed

1 file changed

+34
-17
lines changed

packages/runtime/src/components.ts

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import {
22
ContentKitBlock,
3-
UIRenderEvent,
4-
ContentKitRenderOutput,
53
ContentKitContext,
64
ContentKitDefaultAction,
5+
ContentKitRenderOutput,
6+
UIRenderEvent,
77
} from '@gitbook/api';
88

99
import { RuntimeCallback, RuntimeContext } from './context';
@@ -67,15 +67,19 @@ export function createComponent<
6767
* Initial state of the component.
6868
*/
6969
initialState?:
70-
| State
71-
| ((props: Props, renderContext: ContentKitContext, context: Context) => State);
70+
| State
71+
| ((props: Props, renderContext: ContentKitContext, context: Context) => State);
7272

7373
/**
7474
* Callback to handle a dispatched action.
7575
*/
7676
action?: RuntimeCallback<
7777
[ComponentInstance<Props, State>, ComponentAction<Action>],
78-
Promise<{ props?: Props; state?: State } | undefined>,
78+
Promise<
79+
| { type?: 'element'; props?: Props; state?: State }
80+
| { type: 'complete'; returnValue?: PlainObject }
81+
| undefined
82+
>,
7983
Context
8084
>;
8185

@@ -112,29 +116,42 @@ export function createComponent<
112116
dynamicState: (key) => ({ $state: key }),
113117
};
114118

119+
const wrapResponse = (output: ContentKitRenderOutput) => {
120+
return new Response(JSON.stringify(output), {
121+
headers: {
122+
'Content-Type': 'application/json',
123+
...(cache
124+
? {
125+
// @ts-ignore - I'm not sure how to fix this one with TS
126+
'Cache-Control': `max-age=${cache.maxAge}`,
127+
}
128+
: {}),
129+
},
130+
});
131+
};
132+
115133
if (action && component.action) {
116-
instance = { ...instance, ...(await component.action(instance, action, context)) };
134+
const actionResult = await component.action(instance, action, context);
135+
136+
// If the action is complete, return the result directly. No need to render the component.
137+
if (actionResult?.type === 'complete') {
138+
return wrapResponse(actionResult);
139+
}
140+
141+
instance = { ...instance, ...actionResult };
117142
}
118143

119144
const element = await component.render(instance, context);
120145

121146
const output: ContentKitRenderOutput = {
147+
// for backward compatibility always default to 'element'
148+
type: 'element',
122149
state: instance.state,
123150
props: instance.props,
124151
element,
125152
};
126153

127-
return new Response(JSON.stringify(output), {
128-
headers: {
129-
'Content-Type': 'application/json',
130-
...(cache
131-
? {
132-
// @ts-ignore - I'm not sure how to fix this one with TS
133-
'Cache-Control': `max-age=${cache.maxAge}`,
134-
}
135-
: {}),
136-
},
137-
});
154+
return wrapResponse(output);
138155
},
139156
};
140157
}

0 commit comments

Comments
 (0)