@contractspec/lib.presentation-runtime-react 11.0.0 → 13.0.0
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/WorkflowStepRenderer.d.ts +14 -30
- package/dist/WorkflowStepRenderer.d.ts.map +1 -1
- package/dist/WorkflowStepRenderer.js +131 -101
- package/dist/WorkflowStepper.d.ts +7 -17
- package/dist/WorkflowStepper.d.ts.map +1 -1
- package/dist/WorkflowStepper.js +48 -35
- package/dist/browser/WorkflowStepRenderer.js +132 -0
- package/dist/browser/WorkflowStepper.js +51 -0
- package/dist/browser/index.js +366 -0
- package/dist/browser/nativewind-env.d.js +0 -0
- package/dist/browser/useWorkflow.js +78 -0
- package/dist/index.d.ts +88 -106
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +363 -126
- package/dist/nativewind-env.d.js +1 -0
- package/dist/useWorkflow.d.ts +15 -24
- package/dist/useWorkflow.d.ts.map +1 -1
- package/dist/useWorkflow.js +77 -77
- package/package.json +50 -22
- package/dist/WorkflowStepRenderer.js.map +0 -1
- package/dist/WorkflowStepper.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/nativewind-env.d.ts +0 -1
- package/dist/useWorkflow.js.map +0 -1
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
// src/WorkflowStepRenderer.tsx
|
|
2
|
+
import { EmptyState, LoaderBlock } from "@contractspec/lib.design-system";
|
|
3
|
+
import { jsxDEV } from "react/jsx-dev-runtime";
|
|
4
|
+
function WorkflowStepRenderer({
|
|
5
|
+
spec,
|
|
6
|
+
state,
|
|
7
|
+
className,
|
|
8
|
+
renderHumanStep,
|
|
9
|
+
renderAutomationStep,
|
|
10
|
+
renderDecisionStep,
|
|
11
|
+
loadingFallback,
|
|
12
|
+
completedFallback,
|
|
13
|
+
cancelledFallback,
|
|
14
|
+
failedFallback
|
|
15
|
+
}) {
|
|
16
|
+
const steps = spec.definition.steps;
|
|
17
|
+
if (!steps.length) {
|
|
18
|
+
return /* @__PURE__ */ jsxDEV("div", {
|
|
19
|
+
className,
|
|
20
|
+
children: /* @__PURE__ */ jsxDEV(EmptyState, {
|
|
21
|
+
title: "No steps defined",
|
|
22
|
+
description: "Add at least one step to this workflow to render it."
|
|
23
|
+
}, undefined, false, undefined, this)
|
|
24
|
+
}, undefined, false, undefined, this);
|
|
25
|
+
}
|
|
26
|
+
if (!state) {
|
|
27
|
+
return /* @__PURE__ */ jsxDEV("div", {
|
|
28
|
+
className,
|
|
29
|
+
children: loadingFallback ?? /* @__PURE__ */ jsxDEV(LoaderBlock, {
|
|
30
|
+
label: "Loading workflow",
|
|
31
|
+
description: "Fetching workflow state..."
|
|
32
|
+
}, undefined, false, undefined, this)
|
|
33
|
+
}, undefined, false, undefined, this);
|
|
34
|
+
}
|
|
35
|
+
const lastExecution = state.history.at(-1);
|
|
36
|
+
if (state.status === "failed") {
|
|
37
|
+
return /* @__PURE__ */ jsxDEV("div", {
|
|
38
|
+
className,
|
|
39
|
+
children: failedFallback?.(state, lastExecution) ?? /* @__PURE__ */ jsxDEV(EmptyState, {
|
|
40
|
+
title: "Workflow failed",
|
|
41
|
+
description: lastExecution?.error ?? "Fix the underlying issue and retry the step."
|
|
42
|
+
}, undefined, false, undefined, this)
|
|
43
|
+
}, undefined, false, undefined, this);
|
|
44
|
+
}
|
|
45
|
+
if (state.status === "cancelled") {
|
|
46
|
+
return /* @__PURE__ */ jsxDEV("div", {
|
|
47
|
+
className,
|
|
48
|
+
children: cancelledFallback ?? /* @__PURE__ */ jsxDEV(EmptyState, {
|
|
49
|
+
title: "Workflow cancelled",
|
|
50
|
+
description: "This workflow has been cancelled. Restart it to resume."
|
|
51
|
+
}, undefined, false, undefined, this)
|
|
52
|
+
}, undefined, false, undefined, this);
|
|
53
|
+
}
|
|
54
|
+
if (state.status === "completed") {
|
|
55
|
+
return /* @__PURE__ */ jsxDEV("div", {
|
|
56
|
+
className,
|
|
57
|
+
children: completedFallback ?? /* @__PURE__ */ jsxDEV(EmptyState, {
|
|
58
|
+
title: "Workflow complete",
|
|
59
|
+
description: "All steps have been executed successfully."
|
|
60
|
+
}, undefined, false, undefined, this)
|
|
61
|
+
}, undefined, false, undefined, this);
|
|
62
|
+
}
|
|
63
|
+
const activeStep = steps.find((step) => step.id === state.currentStep) ?? steps[0];
|
|
64
|
+
if (!activeStep) {
|
|
65
|
+
return /* @__PURE__ */ jsxDEV("div", {
|
|
66
|
+
className,
|
|
67
|
+
children: /* @__PURE__ */ jsxDEV(EmptyState, {
|
|
68
|
+
title: "No active step",
|
|
69
|
+
description: "This workflow has no active step."
|
|
70
|
+
}, undefined, false, undefined, this)
|
|
71
|
+
}, undefined, false, undefined, this);
|
|
72
|
+
}
|
|
73
|
+
switch (activeStep.type) {
|
|
74
|
+
case "human": {
|
|
75
|
+
const form = activeStep.action?.form;
|
|
76
|
+
if (form && renderHumanStep) {
|
|
77
|
+
return /* @__PURE__ */ jsxDEV("div", {
|
|
78
|
+
className,
|
|
79
|
+
children: renderHumanStep(form, activeStep)
|
|
80
|
+
}, undefined, false, undefined, this);
|
|
81
|
+
}
|
|
82
|
+
return /* @__PURE__ */ jsxDEV("div", {
|
|
83
|
+
className,
|
|
84
|
+
children: /* @__PURE__ */ jsxDEV(EmptyState, {
|
|
85
|
+
title: "Form renderer missing",
|
|
86
|
+
description: "Provide renderHumanStep to render this human step's form."
|
|
87
|
+
}, undefined, false, undefined, this)
|
|
88
|
+
}, undefined, false, undefined, this);
|
|
89
|
+
}
|
|
90
|
+
case "automation": {
|
|
91
|
+
if (renderAutomationStep) {
|
|
92
|
+
return /* @__PURE__ */ jsxDEV("div", {
|
|
93
|
+
className,
|
|
94
|
+
children: renderAutomationStep(activeStep)
|
|
95
|
+
}, undefined, false, undefined, this);
|
|
96
|
+
}
|
|
97
|
+
return /* @__PURE__ */ jsxDEV("div", {
|
|
98
|
+
className,
|
|
99
|
+
children: /* @__PURE__ */ jsxDEV(EmptyState, {
|
|
100
|
+
title: "Automation step in progress",
|
|
101
|
+
description: `Waiting for automation "${activeStep.label}" to finish.`
|
|
102
|
+
}, undefined, false, undefined, this)
|
|
103
|
+
}, undefined, false, undefined, this);
|
|
104
|
+
}
|
|
105
|
+
case "decision": {
|
|
106
|
+
if (renderDecisionStep) {
|
|
107
|
+
return /* @__PURE__ */ jsxDEV("div", {
|
|
108
|
+
className,
|
|
109
|
+
children: renderDecisionStep(activeStep)
|
|
110
|
+
}, undefined, false, undefined, this);
|
|
111
|
+
}
|
|
112
|
+
return /* @__PURE__ */ jsxDEV("div", {
|
|
113
|
+
className,
|
|
114
|
+
children: /* @__PURE__ */ jsxDEV(EmptyState, {
|
|
115
|
+
title: "Decision step awaiting input",
|
|
116
|
+
description: "Provide a custom decision renderer via renderDecisionStep."
|
|
117
|
+
}, undefined, false, undefined, this)
|
|
118
|
+
}, undefined, false, undefined, this);
|
|
119
|
+
}
|
|
120
|
+
default:
|
|
121
|
+
return /* @__PURE__ */ jsxDEV("div", {
|
|
122
|
+
className,
|
|
123
|
+
children: /* @__PURE__ */ jsxDEV(EmptyState, {
|
|
124
|
+
title: "Unknown step type",
|
|
125
|
+
description: `Step "${activeStep.id}" has an unsupported type.`
|
|
126
|
+
}, undefined, false, undefined, this)
|
|
127
|
+
}, undefined, false, undefined, this);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// src/WorkflowStepper.tsx
|
|
132
|
+
import { Stepper } from "@contractspec/lib.design-system";
|
|
133
|
+
import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
|
|
134
|
+
function WorkflowStepper({
|
|
135
|
+
spec,
|
|
136
|
+
state,
|
|
137
|
+
className,
|
|
138
|
+
showLabels = false
|
|
139
|
+
}) {
|
|
140
|
+
const steps = spec.definition.steps;
|
|
141
|
+
const total = steps.length;
|
|
142
|
+
const current = computeCurrent(steps, state);
|
|
143
|
+
return /* @__PURE__ */ jsxDEV2("div", {
|
|
144
|
+
className: ["flex flex-col gap-2", className].filter(Boolean).join(" "),
|
|
145
|
+
children: [
|
|
146
|
+
/* @__PURE__ */ jsxDEV2(Stepper, {
|
|
147
|
+
current,
|
|
148
|
+
total
|
|
149
|
+
}, undefined, false, undefined, this),
|
|
150
|
+
showLabels && total > 0 && /* @__PURE__ */ jsxDEV2("ol", {
|
|
151
|
+
className: "text-muted-foreground flex flex-wrap gap-2 text-sm",
|
|
152
|
+
children: steps.map((step, index) => {
|
|
153
|
+
const isActive = state?.status === "completed" ? index === total - 1 : step.id === state?.currentStep;
|
|
154
|
+
return /* @__PURE__ */ jsxDEV2("li", {
|
|
155
|
+
className: [
|
|
156
|
+
"rounded border px-2 py-1",
|
|
157
|
+
isActive ? "border-primary text-primary" : "border-border"
|
|
158
|
+
].join(" "),
|
|
159
|
+
children: /* @__PURE__ */ jsxDEV2("span", {
|
|
160
|
+
className: "font-medium",
|
|
161
|
+
children: step.label
|
|
162
|
+
}, undefined, false, undefined, this)
|
|
163
|
+
}, step.id, false, undefined, this);
|
|
164
|
+
})
|
|
165
|
+
}, undefined, false, undefined, this)
|
|
166
|
+
]
|
|
167
|
+
}, undefined, true, undefined, this);
|
|
168
|
+
}
|
|
169
|
+
function computeCurrent(steps, state) {
|
|
170
|
+
if (!steps.length)
|
|
171
|
+
return 0;
|
|
172
|
+
if (!state)
|
|
173
|
+
return 1;
|
|
174
|
+
if (state.status === "completed")
|
|
175
|
+
return steps.length;
|
|
176
|
+
const idx = steps.findIndex((step) => step.id === state.currentStep);
|
|
177
|
+
return idx === -1 ? 1 : idx + 1;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// src/useWorkflow.ts
|
|
181
|
+
import * as React from "react";
|
|
182
|
+
function useWorkflow({
|
|
183
|
+
workflowId,
|
|
184
|
+
runner,
|
|
185
|
+
autoRefresh = true,
|
|
186
|
+
refreshIntervalMs = 2000
|
|
187
|
+
}) {
|
|
188
|
+
const isMounted = React.useRef(true);
|
|
189
|
+
const [state, setState] = React.useState(null);
|
|
190
|
+
const [isLoading, setIsLoading] = React.useState(true);
|
|
191
|
+
const [error, setError] = React.useState(null);
|
|
192
|
+
const [isExecuting, setIsExecuting] = React.useState(false);
|
|
193
|
+
const refresh = React.useCallback(async () => {
|
|
194
|
+
try {
|
|
195
|
+
setIsLoading(true);
|
|
196
|
+
const next = await runner.getState(workflowId);
|
|
197
|
+
if (!isMounted.current)
|
|
198
|
+
return;
|
|
199
|
+
setState(next);
|
|
200
|
+
setError(null);
|
|
201
|
+
} catch (err) {
|
|
202
|
+
if (!isMounted.current)
|
|
203
|
+
return;
|
|
204
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
205
|
+
} finally {
|
|
206
|
+
if (isMounted.current)
|
|
207
|
+
setIsLoading(false);
|
|
208
|
+
}
|
|
209
|
+
}, [runner, workflowId]);
|
|
210
|
+
const executeStep = React.useCallback(async (input) => {
|
|
211
|
+
setIsExecuting(true);
|
|
212
|
+
try {
|
|
213
|
+
await runner.executeStep(workflowId, input);
|
|
214
|
+
await refresh();
|
|
215
|
+
} catch (err) {
|
|
216
|
+
if (isMounted.current) {
|
|
217
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
218
|
+
}
|
|
219
|
+
throw err;
|
|
220
|
+
} finally {
|
|
221
|
+
if (isMounted.current)
|
|
222
|
+
setIsExecuting(false);
|
|
223
|
+
}
|
|
224
|
+
}, [runner, workflowId, refresh]);
|
|
225
|
+
const cancel = React.useCallback(async () => {
|
|
226
|
+
await runner.cancel(workflowId);
|
|
227
|
+
await refresh();
|
|
228
|
+
}, [runner, workflowId, refresh]);
|
|
229
|
+
React.useEffect(() => {
|
|
230
|
+
isMounted.current = true;
|
|
231
|
+
refresh();
|
|
232
|
+
if (!autoRefresh) {
|
|
233
|
+
return () => {
|
|
234
|
+
isMounted.current = false;
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
const interval = setInterval(() => {
|
|
238
|
+
refresh();
|
|
239
|
+
}, refreshIntervalMs);
|
|
240
|
+
return () => {
|
|
241
|
+
isMounted.current = false;
|
|
242
|
+
clearInterval(interval);
|
|
243
|
+
};
|
|
244
|
+
}, [refresh, autoRefresh, refreshIntervalMs]);
|
|
245
|
+
return {
|
|
246
|
+
state,
|
|
247
|
+
isLoading,
|
|
248
|
+
error,
|
|
249
|
+
isExecuting,
|
|
250
|
+
refresh,
|
|
251
|
+
executeStep,
|
|
252
|
+
cancel
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// src/index.ts
|
|
257
|
+
import * as React2 from "react";
|
|
258
|
+
import { useForm } from "@contractspec/lib.ui-kit-web/ui/form";
|
|
259
|
+
function usePresentationController({
|
|
260
|
+
defaults,
|
|
261
|
+
form: formOpts,
|
|
262
|
+
toVariables,
|
|
263
|
+
fetcher,
|
|
264
|
+
toChips,
|
|
265
|
+
useUrlState,
|
|
266
|
+
replace
|
|
267
|
+
}) {
|
|
268
|
+
const url = useUrlState({ defaults, replace });
|
|
269
|
+
const form = useForm({
|
|
270
|
+
defaultValues: formOpts.defaultValues,
|
|
271
|
+
resolver: formOpts.resolver
|
|
272
|
+
});
|
|
273
|
+
React2.useEffect(() => {
|
|
274
|
+
form.reset({ ...form.getValues(), ...url.state.filters });
|
|
275
|
+
}, [url.state.filters]);
|
|
276
|
+
const submitFilters = form.handleSubmit((values) => {
|
|
277
|
+
url.setState({ filters: values, page: 1 });
|
|
278
|
+
});
|
|
279
|
+
const setSearch = React2.useCallback((q) => url.setState({ q, page: 1 }), [url]);
|
|
280
|
+
const variables = React2.useMemo(() => toVariables(url.state), [url.state, toVariables]);
|
|
281
|
+
const [data, setData] = React2.useState([]);
|
|
282
|
+
const [loading, setLoading] = React2.useState(false);
|
|
283
|
+
const [error, setError] = React2.useState(null);
|
|
284
|
+
const [totalItems, setTotalItems] = React2.useState(undefined);
|
|
285
|
+
const [totalPages, setTotalPages] = React2.useState(undefined);
|
|
286
|
+
const refetch = React2.useCallback(async () => {
|
|
287
|
+
setLoading(true);
|
|
288
|
+
setError(null);
|
|
289
|
+
try {
|
|
290
|
+
const out = await fetcher(variables);
|
|
291
|
+
setData(out.items);
|
|
292
|
+
setTotalItems(out.totalItems);
|
|
293
|
+
setTotalPages(out.totalPages);
|
|
294
|
+
} catch (e) {
|
|
295
|
+
setError(e);
|
|
296
|
+
} finally {
|
|
297
|
+
setLoading(false);
|
|
298
|
+
}
|
|
299
|
+
}, [variables, fetcher]);
|
|
300
|
+
React2.useEffect(() => {
|
|
301
|
+
refetch();
|
|
302
|
+
}, [refetch]);
|
|
303
|
+
const chips = React2.useMemo(() => toChips ? toChips(url.state.filters || {}, url.setFilter) : [], [url.state.filters, toChips]);
|
|
304
|
+
const clearAll = React2.useCallback(() => {
|
|
305
|
+
form.reset(formOpts.defaultValues);
|
|
306
|
+
url.setState({ filters: {}, page: 1 });
|
|
307
|
+
}, [form, formOpts.defaultValues, url]);
|
|
308
|
+
return {
|
|
309
|
+
form,
|
|
310
|
+
url,
|
|
311
|
+
variables,
|
|
312
|
+
data,
|
|
313
|
+
loading,
|
|
314
|
+
error,
|
|
315
|
+
totalItems,
|
|
316
|
+
totalPages,
|
|
317
|
+
refetch,
|
|
318
|
+
chips,
|
|
319
|
+
setSearch,
|
|
320
|
+
submitFilters,
|
|
321
|
+
clearAll
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
function useListCoordinator({
|
|
325
|
+
defaults,
|
|
326
|
+
form: formOpts,
|
|
327
|
+
toVariables,
|
|
328
|
+
toChips,
|
|
329
|
+
useUrlState,
|
|
330
|
+
replace
|
|
331
|
+
}) {
|
|
332
|
+
const url = useUrlState({ defaults, replace });
|
|
333
|
+
const form = useForm({
|
|
334
|
+
defaultValues: formOpts.defaultValues,
|
|
335
|
+
resolver: formOpts.resolver
|
|
336
|
+
});
|
|
337
|
+
React2.useEffect(() => {
|
|
338
|
+
form.reset({ ...form.getValues(), ...url.state.filters });
|
|
339
|
+
}, [url.state.filters]);
|
|
340
|
+
const submitFilters = form.handleSubmit((values) => {
|
|
341
|
+
url.setState({ filters: values, page: 1 });
|
|
342
|
+
});
|
|
343
|
+
const setSearch = React2.useCallback((q) => url.setState({ q, page: 1 }), [url]);
|
|
344
|
+
const variables = React2.useMemo(() => toVariables(url.state), [url.state, toVariables]);
|
|
345
|
+
const chips = React2.useMemo(() => toChips ? toChips(url.state.filters || {}, url.setFilter) : [], [url.state.filters, toChips]);
|
|
346
|
+
const clearAll = React2.useCallback(() => {
|
|
347
|
+
form.reset(formOpts.defaultValues);
|
|
348
|
+
url.setState({ filters: {}, page: 1 });
|
|
349
|
+
}, [form, formOpts.defaultValues, url]);
|
|
350
|
+
return {
|
|
351
|
+
form,
|
|
352
|
+
url,
|
|
353
|
+
variables,
|
|
354
|
+
chips,
|
|
355
|
+
setSearch,
|
|
356
|
+
submitFilters,
|
|
357
|
+
clearAll
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
export {
|
|
361
|
+
useWorkflow,
|
|
362
|
+
usePresentationController,
|
|
363
|
+
useListCoordinator,
|
|
364
|
+
WorkflowStepper,
|
|
365
|
+
WorkflowStepRenderer
|
|
366
|
+
};
|
|
File without changes
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// src/useWorkflow.ts
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
function useWorkflow({
|
|
4
|
+
workflowId,
|
|
5
|
+
runner,
|
|
6
|
+
autoRefresh = true,
|
|
7
|
+
refreshIntervalMs = 2000
|
|
8
|
+
}) {
|
|
9
|
+
const isMounted = React.useRef(true);
|
|
10
|
+
const [state, setState] = React.useState(null);
|
|
11
|
+
const [isLoading, setIsLoading] = React.useState(true);
|
|
12
|
+
const [error, setError] = React.useState(null);
|
|
13
|
+
const [isExecuting, setIsExecuting] = React.useState(false);
|
|
14
|
+
const refresh = React.useCallback(async () => {
|
|
15
|
+
try {
|
|
16
|
+
setIsLoading(true);
|
|
17
|
+
const next = await runner.getState(workflowId);
|
|
18
|
+
if (!isMounted.current)
|
|
19
|
+
return;
|
|
20
|
+
setState(next);
|
|
21
|
+
setError(null);
|
|
22
|
+
} catch (err) {
|
|
23
|
+
if (!isMounted.current)
|
|
24
|
+
return;
|
|
25
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
26
|
+
} finally {
|
|
27
|
+
if (isMounted.current)
|
|
28
|
+
setIsLoading(false);
|
|
29
|
+
}
|
|
30
|
+
}, [runner, workflowId]);
|
|
31
|
+
const executeStep = React.useCallback(async (input) => {
|
|
32
|
+
setIsExecuting(true);
|
|
33
|
+
try {
|
|
34
|
+
await runner.executeStep(workflowId, input);
|
|
35
|
+
await refresh();
|
|
36
|
+
} catch (err) {
|
|
37
|
+
if (isMounted.current) {
|
|
38
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
39
|
+
}
|
|
40
|
+
throw err;
|
|
41
|
+
} finally {
|
|
42
|
+
if (isMounted.current)
|
|
43
|
+
setIsExecuting(false);
|
|
44
|
+
}
|
|
45
|
+
}, [runner, workflowId, refresh]);
|
|
46
|
+
const cancel = React.useCallback(async () => {
|
|
47
|
+
await runner.cancel(workflowId);
|
|
48
|
+
await refresh();
|
|
49
|
+
}, [runner, workflowId, refresh]);
|
|
50
|
+
React.useEffect(() => {
|
|
51
|
+
isMounted.current = true;
|
|
52
|
+
refresh();
|
|
53
|
+
if (!autoRefresh) {
|
|
54
|
+
return () => {
|
|
55
|
+
isMounted.current = false;
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
const interval = setInterval(() => {
|
|
59
|
+
refresh();
|
|
60
|
+
}, refreshIntervalMs);
|
|
61
|
+
return () => {
|
|
62
|
+
isMounted.current = false;
|
|
63
|
+
clearInterval(interval);
|
|
64
|
+
};
|
|
65
|
+
}, [refresh, autoRefresh, refreshIntervalMs]);
|
|
66
|
+
return {
|
|
67
|
+
state,
|
|
68
|
+
isLoading,
|
|
69
|
+
error,
|
|
70
|
+
isExecuting,
|
|
71
|
+
refresh,
|
|
72
|
+
executeStep,
|
|
73
|
+
cancel
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
export {
|
|
77
|
+
useWorkflow
|
|
78
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,115 +1,97 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
import { DefaultValues, Resolver, UseFormReturn } from "react-hook-form";
|
|
6
|
-
import { ListFetcher, ListState } from "@contractspec/lib.presentation-runtime-core";
|
|
7
|
-
|
|
8
|
-
//#region src/index.d.ts
|
|
9
|
-
interface UsePresentationControllerOpts<TFilters extends Record<string, unknown>, TVars, TItem> {
|
|
10
|
-
defaults: ListState<TFilters>;
|
|
11
|
-
form: {
|
|
12
|
-
defaultValues: DefaultValues<TFilters> | TFilters;
|
|
13
|
-
resolver?: Resolver<TFilters>;
|
|
14
|
-
};
|
|
15
|
-
toVariables: (input: ListState<TFilters>) => TVars;
|
|
16
|
-
fetcher: ListFetcher<TVars, TItem>;
|
|
17
|
-
toChips?: (filters: TFilters, setFilter: (key: keyof TFilters, value: TFilters[keyof TFilters] | null) => void) => {
|
|
18
|
-
key: string;
|
|
19
|
-
label: React.ReactNode;
|
|
20
|
-
onRemove?: () => void;
|
|
21
|
-
}[];
|
|
22
|
-
useUrlState: (args: {
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { DefaultValues, Resolver, UseFormReturn } from 'react-hook-form';
|
|
3
|
+
import type { ListFetcher, ListState } from '@contractspec/lib.presentation-runtime-core';
|
|
4
|
+
export interface UsePresentationControllerOpts<TFilters extends Record<string, unknown>, TVars, TItem> {
|
|
23
5
|
defaults: ListState<TFilters>;
|
|
6
|
+
form: {
|
|
7
|
+
defaultValues: DefaultValues<TFilters> | TFilters;
|
|
8
|
+
resolver?: Resolver<TFilters>;
|
|
9
|
+
};
|
|
10
|
+
toVariables: (input: ListState<TFilters>) => TVars;
|
|
11
|
+
fetcher: ListFetcher<TVars, TItem>;
|
|
12
|
+
toChips?: (filters: TFilters, setFilter: (key: keyof TFilters, value: TFilters[keyof TFilters] | null) => void) => {
|
|
13
|
+
key: string;
|
|
14
|
+
label: React.ReactNode;
|
|
15
|
+
onRemove?: () => void;
|
|
16
|
+
}[];
|
|
17
|
+
useUrlState: (args: {
|
|
18
|
+
defaults: ListState<TFilters>;
|
|
19
|
+
replace?: boolean;
|
|
20
|
+
}) => {
|
|
21
|
+
state: ListState<TFilters>;
|
|
22
|
+
setState: (next: Partial<ListState<TFilters>>) => void;
|
|
23
|
+
setFilter: (key: keyof TFilters, value: TFilters[keyof TFilters] | null) => void;
|
|
24
|
+
clearFilters: () => void;
|
|
25
|
+
};
|
|
24
26
|
replace?: boolean;
|
|
25
|
-
}) => {
|
|
26
|
-
state: ListState<TFilters>;
|
|
27
|
-
setState: (next: Partial<ListState<TFilters>>) => void;
|
|
28
|
-
setFilter: (key: keyof TFilters, value: TFilters[keyof TFilters] | null) => void;
|
|
29
|
-
clearFilters: () => void;
|
|
30
|
-
};
|
|
31
|
-
replace?: boolean;
|
|
32
27
|
}
|
|
33
|
-
declare function usePresentationController<TFilters extends Record<string, unknown>, TVars, TItem>({
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
readonly chips: {
|
|
57
|
-
key: string;
|
|
58
|
-
label: React.ReactNode;
|
|
59
|
-
onRemove?: () => void;
|
|
60
|
-
}[];
|
|
61
|
-
readonly setSearch: (q: string) => void;
|
|
62
|
-
readonly submitFilters: (e?: React.BaseSyntheticEvent) => Promise<void>;
|
|
63
|
-
readonly clearAll: () => void;
|
|
28
|
+
export declare function usePresentationController<TFilters extends Record<string, unknown>, TVars, TItem>({ defaults, form: formOpts, toVariables, fetcher, toChips, useUrlState, replace, }: UsePresentationControllerOpts<TFilters, TVars, TItem>): {
|
|
29
|
+
readonly form: UseFormReturn<TFilters>;
|
|
30
|
+
readonly url: {
|
|
31
|
+
state: ListState<TFilters>;
|
|
32
|
+
setState: (next: Partial<ListState<TFilters>>) => void;
|
|
33
|
+
setFilter: (key: keyof TFilters, value: TFilters[keyof TFilters] | null) => void;
|
|
34
|
+
clearFilters: () => void;
|
|
35
|
+
};
|
|
36
|
+
readonly variables: TVars;
|
|
37
|
+
readonly data: TItem[];
|
|
38
|
+
readonly loading: boolean;
|
|
39
|
+
readonly error: unknown;
|
|
40
|
+
readonly totalItems: number | undefined;
|
|
41
|
+
readonly totalPages: number | undefined;
|
|
42
|
+
readonly refetch: () => Promise<void>;
|
|
43
|
+
readonly chips: {
|
|
44
|
+
key: string;
|
|
45
|
+
label: React.ReactNode;
|
|
46
|
+
onRemove?: () => void;
|
|
47
|
+
}[];
|
|
48
|
+
readonly setSearch: (q: string) => void;
|
|
49
|
+
readonly submitFilters: (e?: React.BaseSyntheticEvent) => Promise<void>;
|
|
50
|
+
readonly clearAll: () => void;
|
|
64
51
|
};
|
|
65
|
-
interface UseListCoordinatorOpts<TFilters extends Record<string, unknown>, TVars> {
|
|
66
|
-
defaults: ListState<TFilters>;
|
|
67
|
-
form: {
|
|
68
|
-
defaultValues: DefaultValues<TFilters>;
|
|
69
|
-
resolver?: Resolver<TFilters>;
|
|
70
|
-
};
|
|
71
|
-
toVariables: (input: ListState<TFilters>) => TVars;
|
|
72
|
-
toChips?: (filters: TFilters, setFilter: (key: keyof TFilters, value: TFilters[keyof TFilters] | null) => void) => {
|
|
73
|
-
key: string;
|
|
74
|
-
label: React.ReactNode;
|
|
75
|
-
onRemove?: () => void;
|
|
76
|
-
}[];
|
|
77
|
-
useUrlState: (args: {
|
|
52
|
+
export interface UseListCoordinatorOpts<TFilters extends Record<string, unknown>, TVars> {
|
|
78
53
|
defaults: ListState<TFilters>;
|
|
54
|
+
form: {
|
|
55
|
+
defaultValues: DefaultValues<TFilters>;
|
|
56
|
+
resolver?: Resolver<TFilters>;
|
|
57
|
+
};
|
|
58
|
+
toVariables: (input: ListState<TFilters>) => TVars;
|
|
59
|
+
toChips?: (filters: TFilters, setFilter: (key: keyof TFilters, value: TFilters[keyof TFilters] | null) => void) => {
|
|
60
|
+
key: string;
|
|
61
|
+
label: React.ReactNode;
|
|
62
|
+
onRemove?: () => void;
|
|
63
|
+
}[];
|
|
64
|
+
useUrlState: (args: {
|
|
65
|
+
defaults: ListState<TFilters>;
|
|
66
|
+
replace?: boolean;
|
|
67
|
+
}) => {
|
|
68
|
+
state: ListState<TFilters>;
|
|
69
|
+
setState: (next: Partial<ListState<TFilters>>) => void;
|
|
70
|
+
setFilter: (key: keyof TFilters, value: TFilters[keyof TFilters] | null) => void;
|
|
71
|
+
clearFilters: () => void;
|
|
72
|
+
};
|
|
79
73
|
replace?: boolean;
|
|
80
|
-
}) => {
|
|
81
|
-
state: ListState<TFilters>;
|
|
82
|
-
setState: (next: Partial<ListState<TFilters>>) => void;
|
|
83
|
-
setFilter: (key: keyof TFilters, value: TFilters[keyof TFilters] | null) => void;
|
|
84
|
-
clearFilters: () => void;
|
|
85
|
-
};
|
|
86
|
-
replace?: boolean;
|
|
87
74
|
}
|
|
88
|
-
declare function useListCoordinator<TFilters extends Record<string, unknown>, TVars>({
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
key: string;
|
|
106
|
-
label: React.ReactNode;
|
|
107
|
-
onRemove?: () => void;
|
|
108
|
-
}[];
|
|
109
|
-
readonly setSearch: (q: string) => void;
|
|
110
|
-
readonly submitFilters: (e?: React.BaseSyntheticEvent) => Promise<void>;
|
|
111
|
-
readonly clearAll: () => void;
|
|
75
|
+
export declare function useListCoordinator<TFilters extends Record<string, unknown>, TVars>({ defaults, form: formOpts, toVariables, toChips, useUrlState, replace, }: UseListCoordinatorOpts<TFilters, TVars>): {
|
|
76
|
+
readonly form: UseFormReturn<TFilters>;
|
|
77
|
+
readonly url: {
|
|
78
|
+
state: ListState<TFilters>;
|
|
79
|
+
setState: (next: Partial<ListState<TFilters>>) => void;
|
|
80
|
+
setFilter: (key: keyof TFilters, value: TFilters[keyof TFilters] | null) => void;
|
|
81
|
+
clearFilters: () => void;
|
|
82
|
+
};
|
|
83
|
+
readonly variables: TVars;
|
|
84
|
+
readonly chips: {
|
|
85
|
+
key: string;
|
|
86
|
+
label: React.ReactNode;
|
|
87
|
+
onRemove?: () => void;
|
|
88
|
+
}[];
|
|
89
|
+
readonly setSearch: (q: string) => void;
|
|
90
|
+
readonly submitFilters: (e?: React.BaseSyntheticEvent) => Promise<void>;
|
|
91
|
+
readonly clearAll: () => void;
|
|
112
92
|
};
|
|
113
|
-
|
|
114
|
-
export {
|
|
93
|
+
export { useWorkflow } from './useWorkflow';
|
|
94
|
+
export type { UseWorkflowOptions, UseWorkflowResult } from './useWorkflow';
|
|
95
|
+
export { WorkflowStepper } from './WorkflowStepper';
|
|
96
|
+
export { WorkflowStepRenderer } from './WorkflowStepRenderer';
|
|
115
97
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAE9E,OAAO,KAAK,EACV,WAAW,EACX,SAAS,EACV,MAAM,6CAA6C,CAAC;AAErD,MAAM,WAAW,6BAA6B,CAC5C,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACxC,KAAK,EACL,KAAK;IAEL,QAAQ,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC9B,IAAI,EAAE;QACJ,aAAa,EAAE,aAAa,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC;QAClD,QAAQ,CAAC,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;KAC/B,CAAC;IACF,WAAW,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC,QAAQ,CAAC,KAAK,KAAK,CAAC;IACnD,OAAO,EAAE,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACnC,OAAO,CAAC,EAAE,CACR,OAAO,EAAE,QAAQ,EACjB,SAAS,EAAE,CACT,GAAG,EAAE,MAAM,QAAQ,EACnB,KAAK,EAAE,QAAQ,CAAC,MAAM,QAAQ,CAAC,GAAG,IAAI,KACnC,IAAI,KACN;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;KAAE,EAAE,CAAC;IACtE,WAAW,EAAE,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK;QAC3E,KAAK,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC3B,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,KAAK,IAAI,CAAC;QACvD,SAAS,EAAE,CACT,GAAG,EAAE,MAAM,QAAQ,EACnB,KAAK,EAAE,QAAQ,CAAC,MAAM,QAAQ,CAAC,GAAG,IAAI,KACnC,IAAI,CAAC;QACV,YAAY,EAAE,MAAM,IAAI,CAAC;KAC1B,CAAC;IACF,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,yBAAyB,CACvC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACxC,KAAK,EACL,KAAK,EACL,EACA,QAAQ,EACR,IAAI,EAAE,QAAQ,EACd,WAAW,EACX,OAAO,EACP,OAAO,EACP,WAAW,EACX,OAAO,GACR,EAAE,6BAA6B,CAAC,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC;mBAwEtC,aAAa,CAAC,QAAQ,CAAC;;;0DA9Fa,IAAI;oFAIjD,IAAI;sBACK,MAAM,IAAI;;;;;;;;;;aARd,MAAM;eAAS,KAAK,CAAC,SAAS;mBAAa,MAAM,IAAI;;4BA0C3D,MAAM;;;EAqEb;AAED,MAAM,WAAW,sBAAsB,CACrC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACxC,KAAK;IAEL,QAAQ,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC9B,IAAI,EAAE;QACJ,aAAa,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;QACvC,QAAQ,CAAC,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;KAC/B,CAAC;IACF,WAAW,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC,QAAQ,CAAC,KAAK,KAAK,CAAC;IACnD,OAAO,CAAC,EAAE,CACR,OAAO,EAAE,QAAQ,EACjB,SAAS,EAAE,CACT,GAAG,EAAE,MAAM,QAAQ,EACnB,KAAK,EAAE,QAAQ,CAAC,MAAM,QAAQ,CAAC,GAAG,IAAI,KACnC,IAAI,KACN;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;KAAE,EAAE,CAAC;IACtE,WAAW,EAAE,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK;QAC3E,KAAK,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC3B,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,KAAK,IAAI,CAAC;QACvD,SAAS,EAAE,CACT,GAAG,EAAE,MAAM,QAAQ,EACnB,KAAK,EAAE,QAAQ,CAAC,MAAM,QAAQ,CAAC,GAAG,IAAI,KACnC,IAAI,CAAC;QACV,YAAY,EAAE,MAAM,IAAI,CAAC;KAC1B,CAAC;IACF,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,kBAAkB,CAChC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACxC,KAAK,EACL,EACA,QAAQ,EACR,IAAI,EAAE,QAAQ,EACd,WAAW,EACX,OAAO,EACP,WAAW,EACX,OAAO,GACR,EAAE,sBAAsB,CAAC,QAAQ,EAAE,KAAK,CAAC;mBA0CxB,aAAa,CAAC,QAAQ,CAAC;;;0DA9Da,IAAI;oFAIjD,IAAI;sBACK,MAAM,IAAI;;;;aARd,MAAM;eAAS,KAAK,CAAC,SAAS;mBAAa,MAAM,IAAI;;4BAuC3D,MAAM;;;EAkCb;AAED,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC"}
|