Add Custom Overlay Signing Demo for Document Workflows#146
Add Custom Overlay Signing Demo for Document Workflows#146
Conversation
|
Did some QA, below are my findings:
CleanShot.2025-10-28.at.21.49.15.mp4
CleanShot.2025-10-28.at.21.57.33.mp4
CleanShot.2025-10-28.at.22.03.20.mp4 |
@InosRahul thanks a lot.
3. will add
4. will add
5. I'll check it out
|
| ## Support | ||
|
|
||
| For issues related to: | ||
| - **Nutrient Viewer**: Check the [Nutrient documentation](https://docs.nutrient.io/) |
There was a problem hiding this comment.
This URL is incorrect. Should be https://www.nutrient.io/guides/web/
| The demo now supports all available NutrientViewer FormField types: | ||
| - **SignatureFormField**: Signature and Initials | ||
| - **TextFormField**: Text, Name, Email, Date (with format validation) | ||
| - **CheckBoxFormField**: Checkbox controls |
There was a problem hiding this comment.
Correct me if I'm wrong but the UI didn't show this,
| ### Developer-Friendly Features | ||
| - **TypeScript-Ready**: Structured for easy TypeScript integration | ||
| - **Modular Architecture**: Separated concerns with dedicated utility modules | ||
| - **Comprehensive Error Handling**: Graceful degradation when SDK features are unavailable | ||
| - **Performance Monitoring**: Built-in performance tracking utilities |
There was a problem hiding this comment.
These lines can be removed.
| "widget", | ||
| "overlay" | ||
| ], | ||
| "author": "Your Name", |
There was a problem hiding this comment.
Should be Nutrient or Eli
| "license": "MIT", | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "https://github.com/yourusername/nutrient-signing-demo.git" |
There was a problem hiding this comment.
URL should be corrected.
There was a problem hiding this comment.
I don't think we should commit this file. Can be kept in .gitignore.
There was a problem hiding this comment.
Completely disagree. Always keep the package-lock.json. That's the only thing that actually freezes the versions of the dependencies.
https://docs.npmjs.com/cli/v11/configuring-npm/package-lock-json#description
There was a problem hiding this comment.
Ahh yes, I forgot about this. My comment can be ignored in this case, thank you for correcting.
| }; | ||
|
|
||
| // Widget Overlay Manager Class | ||
| class WidgetOverlayManager { |
There was a problem hiding this comment.
Why is there a class inside a hook file? 😲 You can probably extract this into a different file.
There was a problem hiding this comment.
Honestly, This could be a nightmare to debug. This should be simplified.
There was a problem hiding this comment.
All in all it looks solid. Few comments, but mostly me being annoying and/or a smartass. All in all good job! Happy to approve once @InosRahul is happy.
One thing to consider - you have a lot of CSS text just baked in the code. Might be worth to "unbloat" the code by extracting it to classes and applying those to elements, but that's just a personal taste kind of thing.
| }; | ||
|
|
||
| // Widget Overlay Manager Class | ||
| class WidgetOverlayManager { |
There was a problem hiding this comment.
Completely disagree. Always keep the package-lock.json. That's the only thing that actually freezes the versions of the dependencies.
https://docs.npmjs.com/cli/v11/configuring-npm/package-lock-json#description
| function hexToRgb(hex) { | ||
| const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); | ||
| return result ? | ||
| `${parseInt(result[1], 16)}, ${parseInt(result[2], 16)}, ${parseInt(result[3], 16)}` : | ||
| "0, 123, 255"; | ||
| } |
There was a problem hiding this comment.
[nitpick] Sorry, I have natural allergy to regex -- if you're happy with this, ignore this comment.
This helper's not really required, since you're only using it with element.style.backgroundColor. CSS can take color in a lot of formats, including hex. That also includes opacity, so if you have a color #aaffee and want to change it to 10% opacity, you can just write it as #aaffee1a (where 1a is 0.1 * 255 ≈ 26). So lines like fieldElement.style.backgroundColor = 'rgba(${hexToRgb(fieldType.color)}, 0.1)'; can be simplified to fieldElement.style.backgroundColor = fieldType.color + "1a";. It's also a little more performant for the browser to render, but that's a totally marginal gain.
Also this helper function kinda doesn't really belong here, but I'm just being annoying, it doesn't matter.
There was a problem hiding this comment.
I get the idea and I understand ui customization guides use dynamic element creation, but I feel like this is taking it to extreme, resulting in very hard to maintain code. Since you're using React, I'd consider hacking it around a bit, creating a proper React component and just returning it as HTMLElement. I did not test this approach and can't guarantee it'll work, but think it's worth exploring. Here's a short snippet that might help, by the courtesy of GPT 5-mini:
import { createRoot } from 'react-dom/client';
function createInteractiveElement(props) {
const container = document.createElement('div'); // not in DOM unless you append it
const root = createRoot(container);
root.render(<MyComplexComponent {...props} />);
// Return the element the library expects.
// If the library will insert this into the document, you may want to return container.firstElementChild
// or append `container` itself where needed.
return {
element: container.firstElementChild,
cleanup: () => root.unmount(), // caller can call when done
};
}Please feel free to reach out if you need help with that.



Overview
This PR introduces a new signing demo implementation that leverages Custom Overlays instead of the traditional CustomRenderer callback approach, providing a more robust and developer-friendly solution for signing workflows.
Key Features
Why Custom Overlays Beat CustomRenderer?
The Problem with CustomRenderer:
The Custom Overlay Solution:
Key Technical Improvements
Demo Capabilities
This approach provides a more maintainable and scalable foundation for document signing workflows while significantly reducing implementation complexity.