@bdking71/spsignature 1.3.5 → 1.3.6
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/lib/SignatureDisplay.d.ts +62 -0
- package/lib/SignatureDisplay.js +156 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/package.json +7 -3
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file SignatureDisplay.tsx
|
|
3
|
+
*
|
|
4
|
+
* React component that renders a signature verification display card
|
|
5
|
+
* showing the signature image, signer information, validation status,
|
|
6
|
+
* timestamp, and cryptographic hash.
|
|
7
|
+
*
|
|
8
|
+
* @module SignatureDisplay
|
|
9
|
+
*/
|
|
10
|
+
import React from "react";
|
|
11
|
+
import { SharePointAuditRecord } from "./TransactionSigner";
|
|
12
|
+
/**
|
|
13
|
+
* Props for the SignatureDisplay component.
|
|
14
|
+
*/
|
|
15
|
+
export interface ISignatureDisplayProps {
|
|
16
|
+
/** The audit record to display containing signature data and metadata. */
|
|
17
|
+
auditRecord: SharePointAuditRecord;
|
|
18
|
+
/** Whether the signature has been cryptographically verified as authentic. */
|
|
19
|
+
isValid: boolean;
|
|
20
|
+
/** Optional custom CSS class name for the root container. */
|
|
21
|
+
className?: string;
|
|
22
|
+
/** Optional inline styles for the root container. */
|
|
23
|
+
style?: React.CSSProperties;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* React component that displays a digital signature with verification status,
|
|
27
|
+
* signer information, timestamp, and hash digest.
|
|
28
|
+
*
|
|
29
|
+
* Renders a structured div containing:
|
|
30
|
+
* - Signature image preview
|
|
31
|
+
* - Validation status badge (green for valid, red for invalid)
|
|
32
|
+
* - Signer name/email
|
|
33
|
+
* - Signature date and time (localized)
|
|
34
|
+
* - SHA-256 hash digest (truncated, light gray)
|
|
35
|
+
*
|
|
36
|
+
* All styling is customizable via `className` and `style` props, allowing
|
|
37
|
+
* consumers to integrate the component into any design system.
|
|
38
|
+
*
|
|
39
|
+
* @param props - Component props.
|
|
40
|
+
* @returns JSX.Element representing the signature display.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```tsx
|
|
44
|
+
* import { SignatureDisplay } from "@bdking71/spsignature";
|
|
45
|
+
*
|
|
46
|
+
* const MyComponent: React.FC = () => {
|
|
47
|
+
* const [auditRecord, setAuditRecord] = React.useState<SharePointAuditRecord | null>(null);
|
|
48
|
+
* const [isValid, setIsValid] = React.useState(false);
|
|
49
|
+
*
|
|
50
|
+
* return (
|
|
51
|
+
* <SignatureDisplay
|
|
52
|
+
* auditRecord={auditRecord}
|
|
53
|
+
* isValid={isValid}
|
|
54
|
+
* className="my-signature-display"
|
|
55
|
+
* style={{ padding: "20px", border: "1px solid #ccc" }}
|
|
56
|
+
* />
|
|
57
|
+
* );
|
|
58
|
+
* };
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export declare const SignatureDisplay: React.FC<ISignatureDisplayProps>;
|
|
62
|
+
export default SignatureDisplay;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @file SignatureDisplay.tsx
|
|
4
|
+
*
|
|
5
|
+
* React component that renders a signature verification display card
|
|
6
|
+
* showing the signature image, signer information, validation status,
|
|
7
|
+
* timestamp, and cryptographic hash.
|
|
8
|
+
*
|
|
9
|
+
* @module SignatureDisplay
|
|
10
|
+
*/
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.SignatureDisplay = void 0;
|
|
16
|
+
const react_1 = __importDefault(require("react"));
|
|
17
|
+
/**
|
|
18
|
+
* Formats an ISO-8601 timestamp into a localized human-readable date and time string.
|
|
19
|
+
*
|
|
20
|
+
* @param isoTimestamp - ISO-8601 formatted timestamp string.
|
|
21
|
+
* @returns Formatted date/time string in local timezone (e.g., "8/31/2026, 7:55:06 PM").
|
|
22
|
+
*/
|
|
23
|
+
function formatLocalDateTime(isoTimestamp) {
|
|
24
|
+
try {
|
|
25
|
+
const date = new Date(isoTimestamp);
|
|
26
|
+
return date.toLocaleString();
|
|
27
|
+
}
|
|
28
|
+
catch (_a) {
|
|
29
|
+
return isoTimestamp;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Truncates a long hash string to a specified length with ellipsis.
|
|
34
|
+
*
|
|
35
|
+
* @param hash - Full hash string.
|
|
36
|
+
* @param length - Number of characters to display before ellipsis (default: 40).
|
|
37
|
+
* @returns Truncated hash string with "..." suffix.
|
|
38
|
+
*/
|
|
39
|
+
function truncateHash(hash, length = 40) {
|
|
40
|
+
if (hash.length <= length)
|
|
41
|
+
return hash;
|
|
42
|
+
return hash.substring(0, length) + "...";
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Extracts the signer's display name or email from the audit record.
|
|
46
|
+
* Falls back to "Unknown Signer" if not available.
|
|
47
|
+
*
|
|
48
|
+
* @param auditRecord - The audit record containing signature data.
|
|
49
|
+
* @returns The signer identifier or a default fallback string.
|
|
50
|
+
*/
|
|
51
|
+
function getSignerDisplay(auditRecord) {
|
|
52
|
+
// The audit record doesn't store signer name by design (for security),
|
|
53
|
+
// so consumers must pass it separately. This is a fallback.
|
|
54
|
+
return "Signature";
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* React component that displays a digital signature with verification status,
|
|
58
|
+
* signer information, timestamp, and hash digest.
|
|
59
|
+
*
|
|
60
|
+
* Renders a structured div containing:
|
|
61
|
+
* - Signature image preview
|
|
62
|
+
* - Validation status badge (green for valid, red for invalid)
|
|
63
|
+
* - Signer name/email
|
|
64
|
+
* - Signature date and time (localized)
|
|
65
|
+
* - SHA-256 hash digest (truncated, light gray)
|
|
66
|
+
*
|
|
67
|
+
* All styling is customizable via `className` and `style` props, allowing
|
|
68
|
+
* consumers to integrate the component into any design system.
|
|
69
|
+
*
|
|
70
|
+
* @param props - Component props.
|
|
71
|
+
* @returns JSX.Element representing the signature display.
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```tsx
|
|
75
|
+
* import { SignatureDisplay } from "@bdking71/spsignature";
|
|
76
|
+
*
|
|
77
|
+
* const MyComponent: React.FC = () => {
|
|
78
|
+
* const [auditRecord, setAuditRecord] = React.useState<SharePointAuditRecord | null>(null);
|
|
79
|
+
* const [isValid, setIsValid] = React.useState(false);
|
|
80
|
+
*
|
|
81
|
+
* return (
|
|
82
|
+
* <SignatureDisplay
|
|
83
|
+
* auditRecord={auditRecord}
|
|
84
|
+
* isValid={isValid}
|
|
85
|
+
* className="my-signature-display"
|
|
86
|
+
* style={{ padding: "20px", border: "1px solid #ccc" }}
|
|
87
|
+
* />
|
|
88
|
+
* );
|
|
89
|
+
* };
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
const SignatureDisplay = ({ auditRecord, isValid, className, style, }) => {
|
|
93
|
+
const signatureImageSrc = auditRecord.signatureData;
|
|
94
|
+
const formattedDateTime = formatLocalDateTime(auditRecord.signatureTimestamp);
|
|
95
|
+
const truncatedHash = truncateHash(auditRecord.signatureHash);
|
|
96
|
+
const validationStatusColor = isValid ? "#107c10" : "#d13438";
|
|
97
|
+
const validationStatusLabel = isValid
|
|
98
|
+
? "Signature is Valid"
|
|
99
|
+
: "Signature is Invalid";
|
|
100
|
+
return (react_1.default.createElement("div", { className: className, style: Object.assign({ border: "1px solid #e0e0e0", borderRadius: "8px", padding: "16px", backgroundColor: "#ffffff", fontFamily: "'Segoe UI', Tahoma, Geneva, Verdana, sans-serif" }, style) },
|
|
101
|
+
react_1.default.createElement("div", { style: {
|
|
102
|
+
marginBottom: "16px",
|
|
103
|
+
textAlign: "center",
|
|
104
|
+
padding: "12px",
|
|
105
|
+
backgroundColor: "#fafafa",
|
|
106
|
+
borderRadius: "6px",
|
|
107
|
+
border: "1px solid #e0e0e0",
|
|
108
|
+
} },
|
|
109
|
+
react_1.default.createElement("img", { src: signatureImageSrc, alt: "Digital Signature", style: {
|
|
110
|
+
maxWidth: "100%",
|
|
111
|
+
height: "auto",
|
|
112
|
+
minHeight: "80px",
|
|
113
|
+
maxHeight: "200px",
|
|
114
|
+
display: "block",
|
|
115
|
+
margin: "0 auto",
|
|
116
|
+
objectFit: "contain",
|
|
117
|
+
} })),
|
|
118
|
+
react_1.default.createElement("div", { style: {
|
|
119
|
+
marginBottom: "12px",
|
|
120
|
+
fontSize: "16px",
|
|
121
|
+
fontWeight: "600",
|
|
122
|
+
color: "#323130",
|
|
123
|
+
} }, getSignerDisplay(auditRecord)),
|
|
124
|
+
react_1.default.createElement("div", { style: {
|
|
125
|
+
marginBottom: "12px",
|
|
126
|
+
fontSize: "14px",
|
|
127
|
+
fontWeight: "600",
|
|
128
|
+
color: validationStatusColor,
|
|
129
|
+
} }, validationStatusLabel),
|
|
130
|
+
react_1.default.createElement("div", { style: {
|
|
131
|
+
marginBottom: "12px",
|
|
132
|
+
fontSize: "14px",
|
|
133
|
+
color: "#323130",
|
|
134
|
+
display: "flex",
|
|
135
|
+
alignItems: "center",
|
|
136
|
+
gap: "8px",
|
|
137
|
+
} },
|
|
138
|
+
react_1.default.createElement("span", null, "\uD83D\uDCC5"),
|
|
139
|
+
formattedDateTime),
|
|
140
|
+
react_1.default.createElement("div", { style: {
|
|
141
|
+
fontSize: "11px",
|
|
142
|
+
color: "#999999",
|
|
143
|
+
backgroundColor: "#f5f5f5",
|
|
144
|
+
padding: "8px 12px",
|
|
145
|
+
borderRadius: "4px",
|
|
146
|
+
wordBreak: "break-all",
|
|
147
|
+
fontFamily: "'Courier New', monospace",
|
|
148
|
+
border: "1px solid #e0e0e0",
|
|
149
|
+
maxHeight: "60px",
|
|
150
|
+
overflowY: "auto",
|
|
151
|
+
}, title: auditRecord.signatureHash },
|
|
152
|
+
react_1.default.createElement("strong", { style: { color: "#666666" } }, "Hash: "),
|
|
153
|
+
truncatedHash)));
|
|
154
|
+
};
|
|
155
|
+
exports.SignatureDisplay = SignatureDisplay;
|
|
156
|
+
exports.default = exports.SignatureDisplay;
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -17,3 +17,4 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
__exportStar(require("./ProvisioningService"), exports);
|
|
18
18
|
__exportStar(require("./OtpService"), exports);
|
|
19
19
|
__exportStar(require("./TransactionSigner"), exports);
|
|
20
|
+
__exportStar(require("./SignatureDisplay"), exports);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bdking71/spsignature",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.6",
|
|
4
4
|
"description": "SharePoint Framework isolated digital signing, LZW compression, and OTP audit engine.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"module": "lib/index.js",
|
|
@@ -32,7 +32,8 @@
|
|
|
32
32
|
"2fa",
|
|
33
33
|
"otp",
|
|
34
34
|
"audit",
|
|
35
|
-
"m365"
|
|
35
|
+
"m365",
|
|
36
|
+
"react"
|
|
36
37
|
],
|
|
37
38
|
"author": {
|
|
38
39
|
"name": "Bryan King",
|
|
@@ -49,11 +50,14 @@
|
|
|
49
50
|
"homepage": "https://github.com/bdking71/spsignature#readme",
|
|
50
51
|
"peerDependencies": {
|
|
51
52
|
"@microsoft/sp-webpart-base": ">=1.15.0",
|
|
52
|
-
"@pnp/sp": ">=3.0.0"
|
|
53
|
+
"@pnp/sp": ">=3.0.0",
|
|
54
|
+
"react": ">=16.8.0"
|
|
53
55
|
},
|
|
54
56
|
"devDependencies": {
|
|
55
57
|
"@microsoft/sp-webpart-base": "^1.18.0",
|
|
56
58
|
"@pnp/sp": "^3.0.0",
|
|
59
|
+
"@types/react": "^17.0.0",
|
|
60
|
+
"react": "^17.0.1",
|
|
57
61
|
"rimraf": "^5.0.0",
|
|
58
62
|
"typescript": "~5.3.3"
|
|
59
63
|
}
|