@lssm/lib.presentation-runtime-react 0.0.0-canary-20251120170226
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/README.md +43 -0
- package/dist/WorkflowStepRenderer.d.ts +32 -0
- package/dist/WorkflowStepRenderer.d.ts.map +1 -0
- package/dist/WorkflowStepRenderer.js +103 -0
- package/dist/WorkflowStepRenderer.js.map +1 -0
- package/dist/WorkflowStepper.d.ts +19 -0
- package/dist/WorkflowStepper.d.ts.map +1 -0
- package/dist/WorkflowStepper.js +39 -0
- package/dist/WorkflowStepper.js.map +1 -0
- package/dist/index.d.ts +115 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +130 -0
- package/dist/index.js.map +1 -0
- package/dist/nativewind-env.d.ts +1 -0
- package/dist/useWorkflow.d.ts +27 -0
- package/dist/useWorkflow.d.ts.map +1 -0
- package/dist/useWorkflow.js +79 -0
- package/dist/useWorkflow.js.map +1 -0
- package/package.json +50 -0
package/README.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# @lssm/lib.presentation-runtime-react
|
|
2
|
+
|
|
3
|
+
React bindings for ContractSpec presentations (Workflows, DataViews).
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
|
|
7
|
+
To render ContractSpec-defined UIs in standard React web applications.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @lssm/lib.presentation-runtime-react
|
|
13
|
+
# or
|
|
14
|
+
bun add @lssm/lib.presentation-runtime-react
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Key Concepts
|
|
18
|
+
|
|
19
|
+
- **useWorkflow**: Hook to drive a multi-step workflow.
|
|
20
|
+
- **WorkflowStepper**: UI component to show progress.
|
|
21
|
+
- **WorkflowStepRenderer**: Component to render the current step's form or content.
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
```tsx
|
|
26
|
+
import {
|
|
27
|
+
useWorkflow,
|
|
28
|
+
WorkflowStepRenderer,
|
|
29
|
+
} from '@lssm/lib.presentation-runtime-react';
|
|
30
|
+
import { MyWorkflowSpec } from './specs';
|
|
31
|
+
|
|
32
|
+
export function WorkflowPage() {
|
|
33
|
+
const workflow = useWorkflow(MyWorkflowSpec);
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<div>
|
|
37
|
+
<WorkflowStepRenderer workflow={workflow} />
|
|
38
|
+
<button onClick={workflow.next}>Next</button>
|
|
39
|
+
</div>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
3
|
+
import { FormRef, Step, StepExecution, WorkflowSpec, WorkflowState } from "@lssm/lib.contracts/workflow";
|
|
4
|
+
|
|
5
|
+
//#region src/WorkflowStepRenderer.d.ts
|
|
6
|
+
interface WorkflowStepRendererProps {
|
|
7
|
+
spec: WorkflowSpec;
|
|
8
|
+
state: WorkflowState | null;
|
|
9
|
+
className?: string;
|
|
10
|
+
renderHumanStep?: (form: FormRef, step: Step) => React.ReactNode;
|
|
11
|
+
renderAutomationStep?: (step: Step) => React.ReactNode;
|
|
12
|
+
renderDecisionStep?: (step: Step) => React.ReactNode;
|
|
13
|
+
loadingFallback?: React.ReactNode;
|
|
14
|
+
completedFallback?: React.ReactNode;
|
|
15
|
+
cancelledFallback?: React.ReactNode;
|
|
16
|
+
failedFallback?: (state: WorkflowState, last: StepExecution | undefined) => React.ReactNode;
|
|
17
|
+
}
|
|
18
|
+
declare function WorkflowStepRenderer({
|
|
19
|
+
spec,
|
|
20
|
+
state,
|
|
21
|
+
className,
|
|
22
|
+
renderHumanStep,
|
|
23
|
+
renderAutomationStep,
|
|
24
|
+
renderDecisionStep,
|
|
25
|
+
loadingFallback,
|
|
26
|
+
completedFallback,
|
|
27
|
+
cancelledFallback,
|
|
28
|
+
failedFallback
|
|
29
|
+
}: WorkflowStepRendererProps): react_jsx_runtime0.JSX.Element;
|
|
30
|
+
//#endregion
|
|
31
|
+
export { WorkflowStepRenderer, WorkflowStepRendererProps };
|
|
32
|
+
//# sourceMappingURL=WorkflowStepRenderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorkflowStepRenderer.d.ts","names":[],"sources":["../src/WorkflowStepRenderer.tsx"],"sourcesContent":[],"mappings":";;;;;UAUiB,yBAAA;QACT;SACC;EAFQ,SAAA,CAAA,EAAA,MAAA;EACT,eAAA,CAAA,EAAA,CAAA,IAAA,EAGmB,OAHnB,EAAA,IAAA,EAGkC,IAHlC,EAAA,GAG2C,KAAA,CAAM,SAHjD;EACC,oBAAA,CAAA,EAAA,CAAA,IAAA,EAGuB,IAHvB,EAAA,GAGgC,KAAA,CAAM,SAHtC;EAEkB,kBAAA,CAAA,EAAA,CAAA,IAAA,EAEG,IAFH,EAAA,GAEY,KAAA,CAAM,SAFlB;EAAe,eAAA,CAAA,EAGtB,KAAA,CAAM,SAHgB;EAAS,iBAAM,CAAA,EAInC,KAAA,CAAM,SAJ6B;EACzB,iBAAA,CAAA,EAIV,KAAA,CAAM,SAJI;EAAS,cAAM,CAAA,EAAA,CAAA,KAAA,EAMpC,aANoC,EAAA,IAAA,EAOrC,aAPqC,GAAA,SAAA,EAAA,GAQxC,KAAA,CAAM,SARkC;;AACF,iBAU7B,oBAAA,CAV6B;EAAA,IAAA;EAAA,KAAA;EAAA,SAAA;EAAA,eAAA;EAAA,oBAAA;EAAA,kBAAA;EAAA,eAAA;EAAA,iBAAA;EAAA,iBAAA;EAAA;AAAA,CAAA,EAqB1C,yBArB0C,CAAA,EAqBjB,kBAAA,CAAA,GAAA,CAAA,OArBiB"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import "react";
|
|
2
|
+
import { EmptyState, LoaderBlock } from "@lssm/lib.design-system";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
|
|
5
|
+
//#region src/WorkflowStepRenderer.tsx
|
|
6
|
+
function WorkflowStepRenderer({ spec, state, className, renderHumanStep, renderAutomationStep, renderDecisionStep, loadingFallback, completedFallback, cancelledFallback, failedFallback }) {
|
|
7
|
+
const steps = spec.definition.steps;
|
|
8
|
+
if (!steps.length) return /* @__PURE__ */ jsx("div", {
|
|
9
|
+
className,
|
|
10
|
+
children: /* @__PURE__ */ jsx(EmptyState, {
|
|
11
|
+
title: "No steps defined",
|
|
12
|
+
description: "Add at least one step to this workflow to render it."
|
|
13
|
+
})
|
|
14
|
+
});
|
|
15
|
+
if (!state) return /* @__PURE__ */ jsx("div", {
|
|
16
|
+
className,
|
|
17
|
+
children: loadingFallback ?? /* @__PURE__ */ jsx(LoaderBlock, {
|
|
18
|
+
label: "Loading workflow",
|
|
19
|
+
description: "Fetching workflow state..."
|
|
20
|
+
})
|
|
21
|
+
});
|
|
22
|
+
const lastExecution = state.history.at(-1);
|
|
23
|
+
if (state.status === "failed") return /* @__PURE__ */ jsx("div", {
|
|
24
|
+
className,
|
|
25
|
+
children: failedFallback?.(state, lastExecution) ?? /* @__PURE__ */ jsx(EmptyState, {
|
|
26
|
+
title: "Workflow failed",
|
|
27
|
+
description: lastExecution?.error ?? "Fix the underlying issue and retry the step."
|
|
28
|
+
})
|
|
29
|
+
});
|
|
30
|
+
if (state.status === "cancelled") return /* @__PURE__ */ jsx("div", {
|
|
31
|
+
className,
|
|
32
|
+
children: cancelledFallback ?? /* @__PURE__ */ jsx(EmptyState, {
|
|
33
|
+
title: "Workflow cancelled",
|
|
34
|
+
description: "This workflow has been cancelled. Restart it to resume."
|
|
35
|
+
})
|
|
36
|
+
});
|
|
37
|
+
if (state.status === "completed") return /* @__PURE__ */ jsx("div", {
|
|
38
|
+
className,
|
|
39
|
+
children: completedFallback ?? /* @__PURE__ */ jsx(EmptyState, {
|
|
40
|
+
title: "Workflow complete",
|
|
41
|
+
description: "All steps have been executed successfully."
|
|
42
|
+
})
|
|
43
|
+
});
|
|
44
|
+
const activeStep = steps.find((step) => step.id === state.currentStep) ?? steps[0];
|
|
45
|
+
if (!activeStep) return /* @__PURE__ */ jsx("div", {
|
|
46
|
+
className,
|
|
47
|
+
children: /* @__PURE__ */ jsx(EmptyState, {
|
|
48
|
+
title: "No active step",
|
|
49
|
+
description: "This workflow has no active step."
|
|
50
|
+
})
|
|
51
|
+
});
|
|
52
|
+
switch (activeStep.type) {
|
|
53
|
+
case "human": {
|
|
54
|
+
const form = activeStep.action?.form;
|
|
55
|
+
if (form && renderHumanStep) return /* @__PURE__ */ jsx("div", {
|
|
56
|
+
className,
|
|
57
|
+
children: renderHumanStep(form, activeStep)
|
|
58
|
+
});
|
|
59
|
+
return /* @__PURE__ */ jsx("div", {
|
|
60
|
+
className,
|
|
61
|
+
children: /* @__PURE__ */ jsx(EmptyState, {
|
|
62
|
+
title: "Form renderer missing",
|
|
63
|
+
description: "Provide renderHumanStep to render this human step's form."
|
|
64
|
+
})
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
case "automation":
|
|
68
|
+
if (renderAutomationStep) return /* @__PURE__ */ jsx("div", {
|
|
69
|
+
className,
|
|
70
|
+
children: renderAutomationStep(activeStep)
|
|
71
|
+
});
|
|
72
|
+
return /* @__PURE__ */ jsx("div", {
|
|
73
|
+
className,
|
|
74
|
+
children: /* @__PURE__ */ jsx(EmptyState, {
|
|
75
|
+
title: "Automation step in progress",
|
|
76
|
+
description: `Waiting for automation "${activeStep.label}" to finish.`
|
|
77
|
+
})
|
|
78
|
+
});
|
|
79
|
+
case "decision":
|
|
80
|
+
if (renderDecisionStep) return /* @__PURE__ */ jsx("div", {
|
|
81
|
+
className,
|
|
82
|
+
children: renderDecisionStep(activeStep)
|
|
83
|
+
});
|
|
84
|
+
return /* @__PURE__ */ jsx("div", {
|
|
85
|
+
className,
|
|
86
|
+
children: /* @__PURE__ */ jsx(EmptyState, {
|
|
87
|
+
title: "Decision step awaiting input",
|
|
88
|
+
description: "Provide a custom decision renderer via renderDecisionStep."
|
|
89
|
+
})
|
|
90
|
+
});
|
|
91
|
+
default: return /* @__PURE__ */ jsx("div", {
|
|
92
|
+
className,
|
|
93
|
+
children: /* @__PURE__ */ jsx(EmptyState, {
|
|
94
|
+
title: "Unknown step type",
|
|
95
|
+
description: `Step "${activeStep.id}" has an unsupported type.`
|
|
96
|
+
})
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
//#endregion
|
|
102
|
+
export { WorkflowStepRenderer };
|
|
103
|
+
//# sourceMappingURL=WorkflowStepRenderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorkflowStepRenderer.js","names":[],"sources":["../src/WorkflowStepRenderer.tsx"],"sourcesContent":["import * as React from 'react';\nimport { EmptyState, LoaderBlock } from '@lssm/lib.design-system';\nimport type {\n FormRef,\n Step,\n WorkflowSpec,\n WorkflowState,\n StepExecution,\n} from '@lssm/lib.contracts/workflow';\n\nexport interface WorkflowStepRendererProps {\n spec: WorkflowSpec;\n state: WorkflowState | null;\n className?: string;\n renderHumanStep?: (form: FormRef, step: Step) => React.ReactNode;\n renderAutomationStep?: (step: Step) => React.ReactNode;\n renderDecisionStep?: (step: Step) => React.ReactNode;\n loadingFallback?: React.ReactNode;\n completedFallback?: React.ReactNode;\n cancelledFallback?: React.ReactNode;\n failedFallback?: (\n state: WorkflowState,\n last: StepExecution | undefined\n ) => React.ReactNode;\n}\n\nexport function WorkflowStepRenderer({\n spec,\n state,\n className,\n renderHumanStep,\n renderAutomationStep,\n renderDecisionStep,\n loadingFallback,\n completedFallback,\n cancelledFallback,\n failedFallback,\n}: WorkflowStepRendererProps) {\n const steps = spec.definition.steps;\n if (!steps.length) {\n return (\n <div className={className}>\n <EmptyState\n title=\"No steps defined\"\n description=\"Add at least one step to this workflow to render it.\"\n />\n </div>\n );\n }\n\n if (!state) {\n return (\n <div className={className}>\n {loadingFallback ?? (\n <LoaderBlock\n label=\"Loading workflow\"\n description=\"Fetching workflow state...\"\n />\n )}\n </div>\n );\n }\n\n const lastExecution = state.history.at(-1);\n\n if (state.status === 'failed') {\n return (\n <div className={className}>\n {failedFallback?.(state, lastExecution) ?? (\n <EmptyState\n title=\"Workflow failed\"\n description={\n lastExecution?.error ??\n 'Fix the underlying issue and retry the step.'\n }\n />\n )}\n </div>\n );\n }\n\n if (state.status === 'cancelled') {\n return (\n <div className={className}>\n {cancelledFallback ?? (\n <EmptyState\n title=\"Workflow cancelled\"\n description=\"This workflow has been cancelled. Restart it to resume.\"\n />\n )}\n </div>\n );\n }\n\n if (state.status === 'completed') {\n return (\n <div className={className}>\n {completedFallback ?? (\n <EmptyState\n title=\"Workflow complete\"\n description=\"All steps have been executed successfully.\"\n />\n )}\n </div>\n );\n }\n\n const activeStep =\n steps.find((step) => step.id === state.currentStep) ?? steps[0];\n\n if (!activeStep) {\n return (\n <div className={className}>\n <EmptyState\n title=\"No active step\"\n description=\"This workflow has no active step.\"\n />\n </div>\n );\n }\n\n switch (activeStep.type) {\n case 'human': {\n const form = activeStep.action?.form;\n if (form && renderHumanStep) {\n return (\n <div className={className}>{renderHumanStep(form, activeStep)}</div>\n );\n }\n return (\n <div className={className}>\n <EmptyState\n title=\"Form renderer missing\"\n description=\"Provide renderHumanStep to render this human step's form.\"\n />\n </div>\n );\n }\n case 'automation': {\n if (renderAutomationStep) {\n return (\n <div className={className}>{renderAutomationStep(activeStep)}</div>\n );\n }\n return (\n <div className={className}>\n <EmptyState\n title=\"Automation step in progress\"\n description={`Waiting for automation \"${activeStep.label}\" to finish.`}\n />\n </div>\n );\n }\n case 'decision': {\n if (renderDecisionStep) {\n return (\n <div className={className}>{renderDecisionStep(activeStep)}</div>\n );\n }\n return (\n <div className={className}>\n <EmptyState\n title=\"Decision step awaiting input\"\n description=\"Provide a custom decision renderer via renderDecisionStep.\"\n />\n </div>\n );\n }\n default:\n return (\n <div className={className}>\n <EmptyState\n title=\"Unknown step type\"\n description={`Step \"${activeStep.id}\" has an unsupported type.`}\n />\n </div>\n );\n }\n}\n"],"mappings":";;;;;AA0BA,SAAgB,qBAAqB,EACnC,MACA,OACA,WACA,iBACA,sBACA,oBACA,iBACA,mBACA,mBACA,kBAC4B;CAC5B,MAAM,QAAQ,KAAK,WAAW;AAC9B,KAAI,CAAC,MAAM,OACT,QACE,oBAAC;EAAe;YACd,oBAAC;GACC,OAAM;GACN,aAAY;IACZ;GACE;AAIV,KAAI,CAAC,MACH,QACE,oBAAC;EAAe;YACb,mBACC,oBAAC;GACC,OAAM;GACN,aAAY;IACZ;GAEA;CAIV,MAAM,gBAAgB,MAAM,QAAQ,GAAG,GAAG;AAE1C,KAAI,MAAM,WAAW,SACnB,QACE,oBAAC;EAAe;YACb,iBAAiB,OAAO,cAAc,IACrC,oBAAC;GACC,OAAM;GACN,aACE,eAAe,SACf;IAEF;GAEA;AAIV,KAAI,MAAM,WAAW,YACnB,QACE,oBAAC;EAAe;YACb,qBACC,oBAAC;GACC,OAAM;GACN,aAAY;IACZ;GAEA;AAIV,KAAI,MAAM,WAAW,YACnB,QACE,oBAAC;EAAe;YACb,qBACC,oBAAC;GACC,OAAM;GACN,aAAY;IACZ;GAEA;CAIV,MAAM,aACJ,MAAM,MAAM,SAAS,KAAK,OAAO,MAAM,YAAY,IAAI,MAAM;AAE/D,KAAI,CAAC,WACH,QACE,oBAAC;EAAe;YACd,oBAAC;GACC,OAAM;GACN,aAAY;IACZ;GACE;AAIV,SAAQ,WAAW,MAAnB;EACE,KAAK,SAAS;GACZ,MAAM,OAAO,WAAW,QAAQ;AAChC,OAAI,QAAQ,gBACV,QACE,oBAAC;IAAe;cAAY,gBAAgB,MAAM,WAAW;KAAO;AAGxE,UACE,oBAAC;IAAe;cACd,oBAAC;KACC,OAAM;KACN,aAAY;MACZ;KACE;;EAGV,KAAK;AACH,OAAI,qBACF,QACE,oBAAC;IAAe;cAAY,qBAAqB,WAAW;KAAO;AAGvE,UACE,oBAAC;IAAe;cACd,oBAAC;KACC,OAAM;KACN,aAAa,2BAA2B,WAAW,MAAM;MACzD;KACE;EAGV,KAAK;AACH,OAAI,mBACF,QACE,oBAAC;IAAe;cAAY,mBAAmB,WAAW;KAAO;AAGrE,UACE,oBAAC;IAAe;cACd,oBAAC;KACC,OAAM;KACN,aAAY;MACZ;KACE;EAGV,QACE,QACE,oBAAC;GAAe;aACd,oBAAC;IACC,OAAM;IACN,aAAa,SAAS,WAAW,GAAG;KACpC;IACE"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
2
|
+
import { WorkflowSpec, WorkflowState } from "@lssm/lib.contracts/workflow";
|
|
3
|
+
|
|
4
|
+
//#region src/WorkflowStepper.d.ts
|
|
5
|
+
interface WorkflowStepperProps {
|
|
6
|
+
spec: WorkflowSpec;
|
|
7
|
+
state: WorkflowState | null;
|
|
8
|
+
className?: string;
|
|
9
|
+
showLabels?: boolean;
|
|
10
|
+
}
|
|
11
|
+
declare function WorkflowStepper({
|
|
12
|
+
spec,
|
|
13
|
+
state,
|
|
14
|
+
className,
|
|
15
|
+
showLabels
|
|
16
|
+
}: WorkflowStepperProps): react_jsx_runtime0.JSX.Element;
|
|
17
|
+
//#endregion
|
|
18
|
+
export { WorkflowStepper, WorkflowStepperProps };
|
|
19
|
+
//# sourceMappingURL=WorkflowStepper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorkflowStepper.d.ts","names":[],"sources":["../src/WorkflowStepper.tsx"],"sourcesContent":[],"mappings":";;;;UAIiB,oBAAA;QACT;SACC;EAFQ,SAAA,CAAA,EAAA,MAAA;EAOD,UAAA,CAAA,EAAA,OAAe;;AAE7B,iBAFc,eAAA,CAEd;EAAA,IAAA;EAAA,KAAA;EAAA,SAAA;EAAA;AAAA,CAAA,EAGC,oBAHD,CAAA,EAGqB,kBAAA,CAAA,GAAA,CAAA,OAHrB"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import "react";
|
|
2
|
+
import { Stepper } from "@lssm/lib.design-system";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
|
|
5
|
+
//#region src/WorkflowStepper.tsx
|
|
6
|
+
function WorkflowStepper({ spec, state, className, showLabels = false }) {
|
|
7
|
+
const steps = spec.definition.steps;
|
|
8
|
+
const total = steps.length;
|
|
9
|
+
const current = computeCurrent(steps, state);
|
|
10
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
11
|
+
className: ["flex flex-col gap-2", className].filter(Boolean).join(" "),
|
|
12
|
+
children: [/* @__PURE__ */ jsx(Stepper, {
|
|
13
|
+
current,
|
|
14
|
+
total
|
|
15
|
+
}), showLabels && total > 0 && /* @__PURE__ */ jsx("ol", {
|
|
16
|
+
className: "text-muted-foreground flex flex-wrap gap-2 text-sm",
|
|
17
|
+
children: steps.map((step, index) => {
|
|
18
|
+
return /* @__PURE__ */ jsx("li", {
|
|
19
|
+
className: ["rounded border px-2 py-1", (state?.status === "completed" ? index === total - 1 : step.id === state?.currentStep) ? "border-primary text-primary" : "border-border"].join(" "),
|
|
20
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
21
|
+
className: "font-medium",
|
|
22
|
+
children: step.label
|
|
23
|
+
})
|
|
24
|
+
}, step.id);
|
|
25
|
+
})
|
|
26
|
+
})]
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
function computeCurrent(steps, state) {
|
|
30
|
+
if (!steps.length) return 0;
|
|
31
|
+
if (!state) return 1;
|
|
32
|
+
if (state.status === "completed") return steps.length;
|
|
33
|
+
const idx = steps.findIndex((step) => step.id === state.currentStep);
|
|
34
|
+
return idx === -1 ? 1 : idx + 1;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
//#endregion
|
|
38
|
+
export { WorkflowStepper };
|
|
39
|
+
//# sourceMappingURL=WorkflowStepper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorkflowStepper.js","names":[],"sources":["../src/WorkflowStepper.tsx"],"sourcesContent":["import * as React from 'react';\nimport type { WorkflowSpec, WorkflowState } from '@lssm/lib.contracts/workflow';\nimport { Stepper } from '@lssm/lib.design-system';\n\nexport interface WorkflowStepperProps {\n spec: WorkflowSpec;\n state: WorkflowState | null;\n className?: string;\n showLabels?: boolean;\n}\n\nexport function WorkflowStepper({\n spec,\n state,\n className,\n showLabels = false,\n}: WorkflowStepperProps) {\n const steps = spec.definition.steps;\n const total = steps.length;\n const current = computeCurrent(steps, state);\n\n return (\n <div\n className={['flex flex-col gap-2', className].filter(Boolean).join(' ')}\n >\n <Stepper current={current} total={total} />\n {showLabels && total > 0 && (\n <ol className=\"text-muted-foreground flex flex-wrap gap-2 text-sm\">\n {steps.map((step, index) => {\n const isActive =\n state?.status === 'completed'\n ? index === total - 1\n : step.id === state?.currentStep;\n return (\n <li\n key={step.id}\n className={[\n 'rounded border px-2 py-1',\n isActive ? 'border-primary text-primary' : 'border-border',\n ].join(' ')}\n >\n <span className=\"font-medium\">{step.label}</span>\n </li>\n );\n })}\n </ol>\n )}\n </div>\n );\n}\n\nfunction computeCurrent(\n steps: WorkflowSpec['definition']['steps'],\n state: WorkflowState | null\n) {\n if (!steps.length) return 0;\n if (!state) return 1;\n\n if (state.status === 'completed') return steps.length;\n\n const idx = steps.findIndex((step) => step.id === state.currentStep);\n return idx === -1 ? 1 : idx + 1;\n}\n"],"mappings":";;;;;AAWA,SAAgB,gBAAgB,EAC9B,MACA,OACA,WACA,aAAa,SACU;CACvB,MAAM,QAAQ,KAAK,WAAW;CAC9B,MAAM,QAAQ,MAAM;CACpB,MAAM,UAAU,eAAe,OAAO,MAAM;AAE5C,QACE,qBAAC;EACC,WAAW,CAAC,uBAAuB,UAAU,CAAC,OAAO,QAAQ,CAAC,KAAK,IAAI;aAEvE,oBAAC;GAAiB;GAAgB;IAAS,EAC1C,cAAc,QAAQ,KACrB,oBAAC;GAAG,WAAU;aACX,MAAM,KAAK,MAAM,UAAU;AAK1B,WACE,oBAAC;KAEC,WAAW,CACT,6BAPJ,OAAO,WAAW,cACd,UAAU,QAAQ,IAClB,KAAK,OAAO,OAAO,eAMR,gCAAgC,gBAC5C,CAAC,KAAK,IAAI;eAEX,oBAAC;MAAK,WAAU;gBAAe,KAAK;OAAa;OAN5C,KAAK,GAOP;KAEP;IACC;GAEH;;AAIV,SAAS,eACP,OACA,OACA;AACA,KAAI,CAAC,MAAM,OAAQ,QAAO;AAC1B,KAAI,CAAC,MAAO,QAAO;AAEnB,KAAI,MAAM,WAAW,YAAa,QAAO,MAAM;CAE/C,MAAM,MAAM,MAAM,WAAW,SAAS,KAAK,OAAO,MAAM,YAAY;AACpE,QAAO,QAAQ,KAAK,IAAI,MAAM"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { WorkflowStepRenderer } from "./WorkflowStepRenderer.js";
|
|
2
|
+
import { WorkflowStepper } from "./WorkflowStepper.js";
|
|
3
|
+
import { UseWorkflowOptions, UseWorkflowResult, useWorkflow } from "./useWorkflow.js";
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
import { DefaultValues, Resolver, UseFormReturn } from "react-hook-form";
|
|
6
|
+
import { ListFetcher, ListState } from "@lssm/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: {
|
|
23
|
+
defaults: ListState<TFilters>;
|
|
24
|
+
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
|
+
}
|
|
33
|
+
declare function usePresentationController<TFilters extends Record<string, unknown>, TVars, TItem>({
|
|
34
|
+
defaults,
|
|
35
|
+
form: formOpts,
|
|
36
|
+
toVariables,
|
|
37
|
+
fetcher,
|
|
38
|
+
toChips,
|
|
39
|
+
useUrlState,
|
|
40
|
+
replace
|
|
41
|
+
}: UsePresentationControllerOpts<TFilters, TVars, TItem>): {
|
|
42
|
+
readonly form: UseFormReturn<TFilters>;
|
|
43
|
+
readonly url: {
|
|
44
|
+
state: ListState<TFilters>;
|
|
45
|
+
setState: (next: Partial<ListState<TFilters>>) => void;
|
|
46
|
+
setFilter: (key: keyof TFilters, value: TFilters[keyof TFilters] | null) => void;
|
|
47
|
+
clearFilters: () => void;
|
|
48
|
+
};
|
|
49
|
+
readonly variables: TVars;
|
|
50
|
+
readonly data: TItem[];
|
|
51
|
+
readonly loading: boolean;
|
|
52
|
+
readonly error: unknown;
|
|
53
|
+
readonly totalItems: number | undefined;
|
|
54
|
+
readonly totalPages: number | undefined;
|
|
55
|
+
readonly refetch: () => Promise<void>;
|
|
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;
|
|
64
|
+
};
|
|
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: {
|
|
78
|
+
defaults: ListState<TFilters>;
|
|
79
|
+
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
|
+
}
|
|
88
|
+
declare function useListCoordinator<TFilters extends Record<string, unknown>, TVars>({
|
|
89
|
+
defaults,
|
|
90
|
+
form: formOpts,
|
|
91
|
+
toVariables,
|
|
92
|
+
toChips,
|
|
93
|
+
useUrlState,
|
|
94
|
+
replace
|
|
95
|
+
}: UseListCoordinatorOpts<TFilters, TVars>): {
|
|
96
|
+
readonly form: UseFormReturn<TFilters>;
|
|
97
|
+
readonly url: {
|
|
98
|
+
state: ListState<TFilters>;
|
|
99
|
+
setState: (next: Partial<ListState<TFilters>>) => void;
|
|
100
|
+
setFilter: (key: keyof TFilters, value: TFilters[keyof TFilters] | null) => void;
|
|
101
|
+
clearFilters: () => void;
|
|
102
|
+
};
|
|
103
|
+
readonly variables: TVars;
|
|
104
|
+
readonly chips: {
|
|
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;
|
|
112
|
+
};
|
|
113
|
+
//#endregion
|
|
114
|
+
export { UseListCoordinatorOpts, UsePresentationControllerOpts, type UseWorkflowOptions, type UseWorkflowResult, WorkflowStepRenderer, WorkflowStepper, useListCoordinator, usePresentationController, useWorkflow };
|
|
115
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { WorkflowStepRenderer } from "./WorkflowStepRenderer.js";
|
|
2
|
+
import { WorkflowStepper } from "./WorkflowStepper.js";
|
|
3
|
+
import { useWorkflow } from "./useWorkflow.js";
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
import { useForm } from "@lssm/lib.ui-kit-web/ui/form";
|
|
6
|
+
|
|
7
|
+
//#region src/index.ts
|
|
8
|
+
function usePresentationController({ defaults, form: formOpts, toVariables, fetcher, toChips, useUrlState, replace }) {
|
|
9
|
+
const url = useUrlState({
|
|
10
|
+
defaults,
|
|
11
|
+
replace
|
|
12
|
+
});
|
|
13
|
+
const form = useForm({
|
|
14
|
+
defaultValues: formOpts.defaultValues,
|
|
15
|
+
resolver: formOpts.resolver
|
|
16
|
+
});
|
|
17
|
+
React.useEffect(() => {
|
|
18
|
+
form.reset({
|
|
19
|
+
...form.getValues(),
|
|
20
|
+
...url.state.filters
|
|
21
|
+
});
|
|
22
|
+
}, [url.state.filters]);
|
|
23
|
+
const submitFilters = form.handleSubmit((values) => {
|
|
24
|
+
url.setState({
|
|
25
|
+
filters: values,
|
|
26
|
+
page: 1
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
const setSearch = React.useCallback((q) => url.setState({
|
|
30
|
+
q,
|
|
31
|
+
page: 1
|
|
32
|
+
}), [url]);
|
|
33
|
+
const variables = React.useMemo(() => toVariables(url.state), [url.state, toVariables]);
|
|
34
|
+
const [data, setData] = React.useState([]);
|
|
35
|
+
const [loading, setLoading] = React.useState(false);
|
|
36
|
+
const [error, setError] = React.useState(null);
|
|
37
|
+
const [totalItems, setTotalItems] = React.useState(void 0);
|
|
38
|
+
const [totalPages, setTotalPages] = React.useState(void 0);
|
|
39
|
+
const refetch = React.useCallback(async () => {
|
|
40
|
+
setLoading(true);
|
|
41
|
+
setError(null);
|
|
42
|
+
try {
|
|
43
|
+
const out = await fetcher(variables);
|
|
44
|
+
setData(out.items);
|
|
45
|
+
setTotalItems(out.totalItems);
|
|
46
|
+
setTotalPages(out.totalPages);
|
|
47
|
+
} catch (e) {
|
|
48
|
+
setError(e);
|
|
49
|
+
} finally {
|
|
50
|
+
setLoading(false);
|
|
51
|
+
}
|
|
52
|
+
}, [variables, fetcher]);
|
|
53
|
+
React.useEffect(() => {
|
|
54
|
+
refetch();
|
|
55
|
+
}, [refetch]);
|
|
56
|
+
return {
|
|
57
|
+
form,
|
|
58
|
+
url,
|
|
59
|
+
variables,
|
|
60
|
+
data,
|
|
61
|
+
loading,
|
|
62
|
+
error,
|
|
63
|
+
totalItems,
|
|
64
|
+
totalPages,
|
|
65
|
+
refetch,
|
|
66
|
+
chips: React.useMemo(() => toChips ? toChips(url.state.filters || {}, url.setFilter) : [], [url.state.filters, toChips]),
|
|
67
|
+
setSearch,
|
|
68
|
+
submitFilters,
|
|
69
|
+
clearAll: React.useCallback(() => {
|
|
70
|
+
form.reset(formOpts.defaultValues);
|
|
71
|
+
url.setState({
|
|
72
|
+
filters: {},
|
|
73
|
+
page: 1
|
|
74
|
+
});
|
|
75
|
+
}, [
|
|
76
|
+
form,
|
|
77
|
+
formOpts.defaultValues,
|
|
78
|
+
url
|
|
79
|
+
])
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function useListCoordinator({ defaults, form: formOpts, toVariables, toChips, useUrlState, replace }) {
|
|
83
|
+
const url = useUrlState({
|
|
84
|
+
defaults,
|
|
85
|
+
replace
|
|
86
|
+
});
|
|
87
|
+
const form = useForm({
|
|
88
|
+
defaultValues: formOpts.defaultValues,
|
|
89
|
+
resolver: formOpts.resolver
|
|
90
|
+
});
|
|
91
|
+
React.useEffect(() => {
|
|
92
|
+
form.reset({
|
|
93
|
+
...form.getValues(),
|
|
94
|
+
...url.state.filters
|
|
95
|
+
});
|
|
96
|
+
}, [url.state.filters]);
|
|
97
|
+
const submitFilters = form.handleSubmit((values) => {
|
|
98
|
+
url.setState({
|
|
99
|
+
filters: values,
|
|
100
|
+
page: 1
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
const setSearch = React.useCallback((q) => url.setState({
|
|
104
|
+
q,
|
|
105
|
+
page: 1
|
|
106
|
+
}), [url]);
|
|
107
|
+
return {
|
|
108
|
+
form,
|
|
109
|
+
url,
|
|
110
|
+
variables: React.useMemo(() => toVariables(url.state), [url.state, toVariables]),
|
|
111
|
+
chips: React.useMemo(() => toChips ? toChips(url.state.filters || {}, url.setFilter) : [], [url.state.filters, toChips]),
|
|
112
|
+
setSearch,
|
|
113
|
+
submitFilters,
|
|
114
|
+
clearAll: React.useCallback(() => {
|
|
115
|
+
form.reset(formOpts.defaultValues);
|
|
116
|
+
url.setState({
|
|
117
|
+
filters: {},
|
|
118
|
+
page: 1
|
|
119
|
+
});
|
|
120
|
+
}, [
|
|
121
|
+
form,
|
|
122
|
+
formOpts.defaultValues,
|
|
123
|
+
url
|
|
124
|
+
])
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
//#endregion
|
|
129
|
+
export { WorkflowStepRenderer, WorkflowStepper, useListCoordinator, usePresentationController, useWorkflow };
|
|
130
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import * as React from 'react';\nimport type { DefaultValues, Resolver, UseFormReturn } from 'react-hook-form';\nimport { useForm } from '@lssm/lib.ui-kit-web/ui/form';\nimport type {\n ListFetcher,\n ListState,\n} from '@lssm/lib.presentation-runtime-core';\n\nexport interface UsePresentationControllerOpts<\n TFilters extends Record<string, unknown>,\n TVars,\n TItem,\n> {\n defaults: ListState<TFilters>;\n form: {\n defaultValues: DefaultValues<TFilters> | TFilters;\n resolver?: Resolver<TFilters>;\n };\n toVariables: (input: ListState<TFilters>) => TVars;\n fetcher: ListFetcher<TVars, TItem>;\n toChips?: (\n filters: TFilters,\n setFilter: (\n key: keyof TFilters,\n value: TFilters[keyof TFilters] | null\n ) => void\n ) => { key: string; label: React.ReactNode; onRemove?: () => void }[];\n useUrlState: (args: { defaults: ListState<TFilters>; replace?: boolean }) => {\n state: ListState<TFilters>;\n setState: (next: Partial<ListState<TFilters>>) => void;\n setFilter: (\n key: keyof TFilters,\n value: TFilters[keyof TFilters] | null\n ) => void;\n clearFilters: () => void;\n };\n replace?: boolean;\n}\n\nexport function usePresentationController<\n TFilters extends Record<string, unknown>,\n TVars,\n TItem,\n>({\n defaults,\n form: formOpts,\n toVariables,\n fetcher,\n toChips,\n useUrlState,\n replace,\n}: UsePresentationControllerOpts<TFilters, TVars, TItem>) {\n const url = useUrlState({ defaults, replace });\n const form = useForm<TFilters>({\n defaultValues: formOpts.defaultValues,\n resolver: formOpts.resolver as any,\n } as any);\n\n React.useEffect(() => {\n form.reset({ ...(form.getValues() as any), ...(url.state.filters as any) });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [url.state.filters]);\n\n const submitFilters = form.handleSubmit((values) => {\n url.setState({ filters: values as TFilters, page: 1 });\n });\n\n const setSearch = React.useCallback(\n (q: string) => url.setState({ q, page: 1 }),\n [url]\n );\n const variables = React.useMemo(\n () => toVariables(url.state),\n [url.state, toVariables]\n );\n\n const [data, setData] = React.useState<TItem[]>([]);\n const [loading, setLoading] = React.useState(false);\n const [error, setError] = React.useState<unknown>(null);\n const [totalItems, setTotalItems] = React.useState<number | undefined>(\n undefined\n );\n const [totalPages, setTotalPages] = React.useState<number | undefined>(\n undefined\n );\n\n const refetch = React.useCallback(async () => {\n setLoading(true);\n setError(null);\n try {\n const out = await fetcher(variables);\n setData(out.items);\n setTotalItems(out.totalItems);\n setTotalPages(out.totalPages);\n } catch (e) {\n setError(e);\n } finally {\n setLoading(false);\n }\n }, [variables, fetcher]);\n\n React.useEffect(() => {\n void refetch();\n }, [refetch]);\n\n const chips = React.useMemo(\n () =>\n toChips\n ? toChips(\n (url.state.filters as TFilters) || ({} as any),\n url.setFilter as any\n )\n : [],\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [url.state.filters, toChips]\n );\n\n const clearAll = React.useCallback(() => {\n form.reset(formOpts.defaultValues as any);\n url.setState({ filters: {} as TFilters, page: 1 });\n }, [form, formOpts.defaultValues, url]);\n\n return {\n form: form as UseFormReturn<TFilters>,\n url,\n variables,\n data,\n loading,\n error,\n totalItems,\n totalPages,\n refetch,\n chips,\n setSearch,\n submitFilters,\n clearAll,\n } as const;\n}\n\nexport interface UseListCoordinatorOpts<\n TFilters extends Record<string, unknown>,\n TVars,\n> {\n defaults: ListState<TFilters>;\n form: {\n defaultValues: DefaultValues<TFilters>;\n resolver?: Resolver<TFilters>;\n };\n toVariables: (input: ListState<TFilters>) => TVars;\n toChips?: (\n filters: TFilters,\n setFilter: (\n key: keyof TFilters,\n value: TFilters[keyof TFilters] | null\n ) => void\n ) => { key: string; label: React.ReactNode; onRemove?: () => void }[];\n useUrlState: (args: { defaults: ListState<TFilters>; replace?: boolean }) => {\n state: ListState<TFilters>;\n setState: (next: Partial<ListState<TFilters>>) => void;\n setFilter: (\n key: keyof TFilters,\n value: TFilters[keyof TFilters] | null\n ) => void;\n clearFilters: () => void;\n };\n replace?: boolean;\n}\n\nexport function useListCoordinator<\n TFilters extends Record<string, unknown>,\n TVars,\n>({\n defaults,\n form: formOpts,\n toVariables,\n toChips,\n useUrlState,\n replace,\n}: UseListCoordinatorOpts<TFilters, TVars>) {\n const url = useUrlState({ defaults, replace });\n const form = useForm<TFilters>({\n defaultValues: formOpts.defaultValues,\n resolver: formOpts.resolver,\n } as any);\n\n React.useEffect(() => {\n form.reset({ ...(form.getValues() as any), ...(url.state.filters as any) });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [url.state.filters]);\n\n const submitFilters = form.handleSubmit((values) => {\n url.setState({ filters: values as TFilters, page: 1 });\n });\n\n const setSearch = React.useCallback(\n (q: string) => url.setState({ q, page: 1 }),\n [url]\n );\n const variables = React.useMemo(\n () => toVariables(url.state),\n [url.state, toVariables]\n );\n\n const chips = React.useMemo(\n () =>\n toChips\n ? toChips(\n (url.state.filters as TFilters) || ({} as any),\n url.setFilter as any\n )\n : [],\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [url.state.filters, toChips]\n );\n\n const clearAll = React.useCallback(() => {\n form.reset(formOpts.defaultValues as any);\n url.setState({ filters: {} as TFilters, page: 1 });\n }, [form, formOpts.defaultValues, url]);\n\n return {\n form: form as UseFormReturn<TFilters>,\n url,\n variables,\n chips,\n setSearch,\n submitFilters,\n clearAll,\n } as const;\n}\n\nexport { useWorkflow } from './useWorkflow';\nexport type {\n UseWorkflowOptions,\n UseWorkflowResult,\n} from './useWorkflow';\nexport { WorkflowStepper } from './WorkflowStepper';\nexport { WorkflowStepRenderer } from './WorkflowStepRenderer';\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { WorkflowRunner, WorkflowState } from "@lssm/lib.contracts/workflow";
|
|
2
|
+
|
|
3
|
+
//#region src/useWorkflow.d.ts
|
|
4
|
+
interface UseWorkflowOptions {
|
|
5
|
+
workflowId: string;
|
|
6
|
+
runner: WorkflowRunner;
|
|
7
|
+
autoRefresh?: boolean;
|
|
8
|
+
refreshIntervalMs?: number;
|
|
9
|
+
}
|
|
10
|
+
interface UseWorkflowResult {
|
|
11
|
+
state: WorkflowState | null;
|
|
12
|
+
isLoading: boolean;
|
|
13
|
+
error: Error | null;
|
|
14
|
+
isExecuting: boolean;
|
|
15
|
+
refresh: () => Promise<void>;
|
|
16
|
+
executeStep: (input?: unknown) => Promise<void>;
|
|
17
|
+
cancel: () => Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
declare function useWorkflow({
|
|
20
|
+
workflowId,
|
|
21
|
+
runner,
|
|
22
|
+
autoRefresh,
|
|
23
|
+
refreshIntervalMs
|
|
24
|
+
}: UseWorkflowOptions): UseWorkflowResult;
|
|
25
|
+
//#endregion
|
|
26
|
+
export { UseWorkflowOptions, UseWorkflowResult, useWorkflow };
|
|
27
|
+
//# sourceMappingURL=useWorkflow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useWorkflow.d.ts","names":[],"sources":["../src/useWorkflow.ts"],"sourcesContent":[],"mappings":";;;UAMiB,kBAAA;;EAAA,MAAA,EAEP,cAFyB;EAOlB,WAAA,CAAA,EAAA,OAAiB;EACzB,iBAAA,CAAA,EAAA,MAAA;;AAIQ,UALA,iBAAA,CAKA;EACmB,KAAA,EAL3B,aAK2B,GAAA,IAAA;EACpB,SAAA,EAAA,OAAA;EAAO,KAAA,EAJd,KAIc,GAAA,IAAA;EAGP,WAAA,EAAA,OAAW;EACzB,OAAA,EAAA,GAAA,GANe,OAMf,CAAA,IAAA,CAAA;EACA,WAAA,EAAA,CAAA,KAAA,CAAA,EAAA,OAAA,EAAA,GANkC,OAMlC,CAAA,IAAA,CAAA;EACA,MAAA,EAAA,GAAA,GANc,OAMd,CAAA,IAAA,CAAA;;AAEC,iBALa,WAAA,CAKb;EAAA,UAAA;EAAA,MAAA;EAAA,WAAA;EAAA;AAAA,CAAA,EAAA,kBAAA,CAAA,EAAqB,iBAArB"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
//#region src/useWorkflow.ts
|
|
4
|
+
function useWorkflow({ workflowId, runner, autoRefresh = true, refreshIntervalMs = 2e3 }) {
|
|
5
|
+
const isMounted = React.useRef(true);
|
|
6
|
+
const [state, setState] = React.useState(null);
|
|
7
|
+
const [isLoading, setIsLoading] = React.useState(true);
|
|
8
|
+
const [error, setError] = React.useState(null);
|
|
9
|
+
const [isExecuting, setIsExecuting] = React.useState(false);
|
|
10
|
+
const refresh = React.useCallback(async () => {
|
|
11
|
+
try {
|
|
12
|
+
setIsLoading(true);
|
|
13
|
+
const next = await runner.getState(workflowId);
|
|
14
|
+
if (!isMounted.current) return;
|
|
15
|
+
setState(next);
|
|
16
|
+
setError(null);
|
|
17
|
+
} catch (err) {
|
|
18
|
+
if (!isMounted.current) return;
|
|
19
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
20
|
+
} finally {
|
|
21
|
+
if (isMounted.current) setIsLoading(false);
|
|
22
|
+
}
|
|
23
|
+
}, [runner, workflowId]);
|
|
24
|
+
const executeStep = React.useCallback(async (input) => {
|
|
25
|
+
setIsExecuting(true);
|
|
26
|
+
try {
|
|
27
|
+
await runner.executeStep(workflowId, input);
|
|
28
|
+
await refresh();
|
|
29
|
+
} catch (err) {
|
|
30
|
+
if (isMounted.current) setError(err instanceof Error ? err : new Error(String(err)));
|
|
31
|
+
throw err;
|
|
32
|
+
} finally {
|
|
33
|
+
if (isMounted.current) setIsExecuting(false);
|
|
34
|
+
}
|
|
35
|
+
}, [
|
|
36
|
+
runner,
|
|
37
|
+
workflowId,
|
|
38
|
+
refresh
|
|
39
|
+
]);
|
|
40
|
+
const cancel = React.useCallback(async () => {
|
|
41
|
+
await runner.cancel(workflowId);
|
|
42
|
+
await refresh();
|
|
43
|
+
}, [
|
|
44
|
+
runner,
|
|
45
|
+
workflowId,
|
|
46
|
+
refresh
|
|
47
|
+
]);
|
|
48
|
+
React.useEffect(() => {
|
|
49
|
+
isMounted.current = true;
|
|
50
|
+
refresh();
|
|
51
|
+
if (!autoRefresh) return () => {
|
|
52
|
+
isMounted.current = false;
|
|
53
|
+
};
|
|
54
|
+
const interval = setInterval(() => {
|
|
55
|
+
refresh();
|
|
56
|
+
}, refreshIntervalMs);
|
|
57
|
+
return () => {
|
|
58
|
+
isMounted.current = false;
|
|
59
|
+
clearInterval(interval);
|
|
60
|
+
};
|
|
61
|
+
}, [
|
|
62
|
+
refresh,
|
|
63
|
+
autoRefresh,
|
|
64
|
+
refreshIntervalMs
|
|
65
|
+
]);
|
|
66
|
+
return {
|
|
67
|
+
state,
|
|
68
|
+
isLoading,
|
|
69
|
+
error,
|
|
70
|
+
isExecuting,
|
|
71
|
+
refresh,
|
|
72
|
+
executeStep,
|
|
73
|
+
cancel
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
//#endregion
|
|
78
|
+
export { useWorkflow };
|
|
79
|
+
//# sourceMappingURL=useWorkflow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useWorkflow.js","names":[],"sources":["../src/useWorkflow.ts"],"sourcesContent":["import * as React from 'react';\nimport type {\n WorkflowRunner,\n WorkflowState,\n} from '@lssm/lib.contracts/workflow';\n\nexport interface UseWorkflowOptions {\n workflowId: string;\n runner: WorkflowRunner;\n autoRefresh?: boolean;\n refreshIntervalMs?: number;\n}\n\nexport interface UseWorkflowResult {\n state: WorkflowState | null;\n isLoading: boolean;\n error: Error | null;\n isExecuting: boolean;\n refresh: () => Promise<void>;\n executeStep: (input?: unknown) => Promise<void>;\n cancel: () => Promise<void>;\n}\n\nexport function useWorkflow({\n workflowId,\n runner,\n autoRefresh = true,\n refreshIntervalMs = 2000,\n}: UseWorkflowOptions): UseWorkflowResult {\n const isMounted = React.useRef(true);\n const [state, setState] = React.useState<WorkflowState | null>(null);\n const [isLoading, setIsLoading] = React.useState(true);\n const [error, setError] = React.useState<Error | null>(null);\n const [isExecuting, setIsExecuting] = React.useState(false);\n\n const refresh = React.useCallback(async () => {\n try {\n setIsLoading(true);\n const next = await runner.getState(workflowId);\n if (!isMounted.current) return;\n setState(next);\n setError(null);\n } catch (err) {\n if (!isMounted.current) return;\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n if (isMounted.current) setIsLoading(false);\n }\n }, [runner, workflowId]);\n\n const executeStep = React.useCallback(\n async (input?: unknown) => {\n setIsExecuting(true);\n try {\n await runner.executeStep(workflowId, input);\n await refresh();\n } catch (err) {\n if (isMounted.current) {\n setError(err instanceof Error ? err : new Error(String(err)));\n }\n throw err;\n } finally {\n if (isMounted.current) setIsExecuting(false);\n }\n },\n [runner, workflowId, refresh]\n );\n\n const cancel = React.useCallback(async () => {\n await runner.cancel(workflowId);\n await refresh();\n }, [runner, workflowId, refresh]);\n\n React.useEffect(() => {\n isMounted.current = true;\n void refresh();\n if (!autoRefresh) {\n return () => {\n isMounted.current = false;\n };\n }\n const interval = setInterval(() => {\n void refresh();\n }, refreshIntervalMs);\n return () => {\n isMounted.current = false;\n clearInterval(interval);\n };\n }, [refresh, autoRefresh, refreshIntervalMs]);\n\n return {\n state,\n isLoading,\n error,\n isExecuting,\n refresh,\n executeStep,\n cancel,\n };\n}\n\n"],"mappings":";;;AAuBA,SAAgB,YAAY,EAC1B,YACA,QACA,cAAc,MACd,oBAAoB,OACoB;CACxC,MAAM,YAAY,MAAM,OAAO,KAAK;CACpC,MAAM,CAAC,OAAO,YAAY,MAAM,SAA+B,KAAK;CACpE,MAAM,CAAC,WAAW,gBAAgB,MAAM,SAAS,KAAK;CACtD,MAAM,CAAC,OAAO,YAAY,MAAM,SAAuB,KAAK;CAC5D,MAAM,CAAC,aAAa,kBAAkB,MAAM,SAAS,MAAM;CAE3D,MAAM,UAAU,MAAM,YAAY,YAAY;AAC5C,MAAI;AACF,gBAAa,KAAK;GAClB,MAAM,OAAO,MAAM,OAAO,SAAS,WAAW;AAC9C,OAAI,CAAC,UAAU,QAAS;AACxB,YAAS,KAAK;AACd,YAAS,KAAK;WACP,KAAK;AACZ,OAAI,CAAC,UAAU,QAAS;AACxB,YAAS,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,IAAI,CAAC,CAAC;YACrD;AACR,OAAI,UAAU,QAAS,cAAa,MAAM;;IAE3C,CAAC,QAAQ,WAAW,CAAC;CAExB,MAAM,cAAc,MAAM,YACxB,OAAO,UAAoB;AACzB,iBAAe,KAAK;AACpB,MAAI;AACF,SAAM,OAAO,YAAY,YAAY,MAAM;AAC3C,SAAM,SAAS;WACR,KAAK;AACZ,OAAI,UAAU,QACZ,UAAS,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,IAAI,CAAC,CAAC;AAE/D,SAAM;YACE;AACR,OAAI,UAAU,QAAS,gBAAe,MAAM;;IAGhD;EAAC;EAAQ;EAAY;EAAQ,CAC9B;CAED,MAAM,SAAS,MAAM,YAAY,YAAY;AAC3C,QAAM,OAAO,OAAO,WAAW;AAC/B,QAAM,SAAS;IACd;EAAC;EAAQ;EAAY;EAAQ,CAAC;AAEjC,OAAM,gBAAgB;AACpB,YAAU,UAAU;AACpB,EAAK,SAAS;AACd,MAAI,CAAC,YACH,cAAa;AACX,aAAU,UAAU;;EAGxB,MAAM,WAAW,kBAAkB;AACjC,GAAK,SAAS;KACb,kBAAkB;AACrB,eAAa;AACX,aAAU,UAAU;AACpB,iBAAc,SAAS;;IAExB;EAAC;EAAS;EAAa;EAAkB,CAAC;AAE7C,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACD"}
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lssm/lib.presentation-runtime-react",
|
|
3
|
+
"version": "0.0.0-canary-20251120170226",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"sideEffects": false,
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "bun build:bundle && bun build:types",
|
|
11
|
+
"build:bundle": "tsdown",
|
|
12
|
+
"build:types": "tsc --noEmit -p tsconfig.json",
|
|
13
|
+
"dev": "bun run build:bundle --watch",
|
|
14
|
+
"lint": "bun run lint:fix",
|
|
15
|
+
"lint:fix": "eslint src --fix",
|
|
16
|
+
"lint:check": "eslint src"
|
|
17
|
+
},
|
|
18
|
+
"peerDependencies": {
|
|
19
|
+
"react": "^19.1.0",
|
|
20
|
+
"react-hook-form": "7.66.0",
|
|
21
|
+
"zod": "^4.1.5",
|
|
22
|
+
"@lssm/lib.presentation-runtime-core": "0.0.0-canary-20251120170226"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@lssm/lib.presentation-runtime-core": "0.0.0-canary-20251120170226",
|
|
26
|
+
"@lssm/lib.contracts": "0.0.0-canary-20251120170226",
|
|
27
|
+
"@lssm/lib.design-system": "0.0.0-canary-20251120170226",
|
|
28
|
+
"@lssm/lib.ui-kit-web": "0.0.0-canary-20251120170226"
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"dist",
|
|
32
|
+
"README.md"
|
|
33
|
+
],
|
|
34
|
+
"exports": {
|
|
35
|
+
".": "./dist/index.js",
|
|
36
|
+
"./useWorkflow": "./dist/useWorkflow.js",
|
|
37
|
+
"./WorkflowStepper": "./dist/WorkflowStepper.js",
|
|
38
|
+
"./WorkflowStepRenderer": "./dist/WorkflowStepRenderer.js",
|
|
39
|
+
"./*": "./*"
|
|
40
|
+
},
|
|
41
|
+
"publishConfig": {
|
|
42
|
+
"exports": {
|
|
43
|
+
".": "./dist/index.js",
|
|
44
|
+
"./useWorkflow": "./dist/useWorkflow.js",
|
|
45
|
+
"./WorkflowStepper": "./dist/WorkflowStepper.js",
|
|
46
|
+
"./WorkflowStepRenderer": "./dist/WorkflowStepRenderer.js",
|
|
47
|
+
"./*": "./*"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|