feat: signature squiggle #237
@ -7,13 +7,12 @@ import {
|
||||
isCurrentValueLast
|
||||
} from '../../utils'
|
||||
import React, { useState } from 'react'
|
||||
import { MARK_TYPE_CONFIG } from '../getMarkComponents.tsx'
|
||||
|
||||
interface MarkFormFieldProps {
|
||||
currentUserMarks: CurrentUserMark[]
|
||||
handleCurrentUserMarkChange: (mark: CurrentUserMark) => void
|
||||
handleSelectedMarkValueChange: (
|
||||
event: React.ChangeEvent<HTMLInputElement>
|
||||
) => void
|
||||
handleSelectedMarkValueChange: (value: string) => void
|
||||
handleSubmit: (event: React.FormEvent<HTMLFormElement>) => void
|
||||
selectedMark: CurrentUserMark
|
||||
selectedMarkValue: string
|
||||
@ -53,6 +52,8 @@ const MarkFormField = ({
|
||||
}
|
||||
const toggleActions = () => setDisplayActions(!displayActions)
|
||||
const markLabel = getToolboxLabelByMarkType(selectedMark.mark.type)
|
||||
const { input: MarkInputComponent } =
|
||||
MARK_TYPE_CONFIG[selectedMark.mark.type] || {}
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<div className={styles.trigger}>
|
||||
@ -83,12 +84,14 @@ const MarkFormField = ({
|
||||
</div>
|
||||
<div className={styles.inputWrapper}>
|
||||
<form onSubmit={(e) => handleFormSubmit(e)}>
|
||||
<input
|
||||
className={styles.input}
|
||||
placeholder={markLabel}
|
||||
onChange={handleSelectedMarkValueChange}
|
||||
value={selectedMarkValue}
|
||||
/>
|
||||
{typeof MarkInputComponent !== 'undefined' && (
|
||||
<MarkInputComponent
|
||||
value={selectedMarkValue}
|
||||
placeholder={markLabel}
|
||||
handler={handleSelectedMarkValueChange}
|
||||
userMark={selectedMark}
|
||||
/>
|
||||
)}
|
||||
<div className={styles.actionsBottom}>
|
||||
<button type="submit" className={styles.submitButton}>
|
||||
NEXT
|
||||
|
19
src/components/MarkInputs/Text.tsx
Normal file
19
src/components/MarkInputs/Text.tsx
Normal file
@ -0,0 +1,19 @@
|
||||
import { MarkInputProps } from '../../types/mark'
|
||||
import styles from '../MarkFormField/style.module.scss'
|
||||
|
||||
export const MarkInputText = ({
|
||||
value,
|
||||
handler,
|
||||
placeholder
|
||||
}: MarkInputProps) => {
|
||||
return (
|
||||
<input
|
||||
className={styles.input}
|
||||
placeholder={placeholder}
|
||||
onChange={(e) => {
|
||||
handler(e.currentTarget.value)
|
||||
}}
|
||||
value={value}
|
||||
/>
|
||||
)
|
||||
}
|
@ -4,6 +4,7 @@ import { FONT_SIZE, FONT_TYPE, inPx } from '../../utils/pdf.ts'
|
||||
import { useScale } from '../../hooks/useScale.tsx'
|
||||
import { forwardRef } from 'react'
|
||||
import { npubToHex } from '../../utils/nostr.ts'
|
||||
import { MARK_TYPE_CONFIG } from '../getMarkComponents.tsx'
|
||||
|
||||
interface PdfMarkItemProps {
|
||||
userMark: CurrentUserMark
|
||||
@ -27,6 +28,8 @@ const PdfMarkItem = forwardRef<HTMLDivElement, PdfMarkItemProps>(
|
||||
const getMarkValue = () =>
|
||||
isEdited() ? selectedMarkValue : userMark.currentValue
|
||||
const { from } = useScale()
|
||||
const { render: MarkRenderComponent } =
|
||||
MARK_TYPE_CONFIG[userMark.mark.type] || {}
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
@ -47,7 +50,9 @@ const PdfMarkItem = forwardRef<HTMLDivElement, PdfMarkItemProps>(
|
||||
fontSize: inPx(from(pageWidth, FONT_SIZE))
|
||||
}}
|
||||
>
|
||||
{getMarkValue()}
|
||||
{typeof MarkRenderComponent !== 'undefined' && (
|
||||
<MarkRenderComponent value={getMarkValue()} mark={userMark.mark} />
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -117,8 +117,7 @@ const PdfMarking = (props: PdfMarkingProps) => {
|
||||
// setCurrentUserMarks(updatedCurrentUserMarks)
|
||||
// }
|
||||
|
||||
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) =>
|
||||
setSelectedMarkValue(event.target.value)
|
||||
const handleChange = (value: string) => setSelectedMarkValue(value)
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -55,6 +55,7 @@ import {
|
||||
} from '@fortawesome/free-solid-svg-icons'
|
||||
import { upgradeAndVerifyTimestamp } from '../../utils/opentimestamps.ts'
|
||||
import _ from 'lodash'
|
||||
import { MARK_TYPE_CONFIG } from '../../components/getMarkComponents.tsx'
|
||||
|
||||
interface PdfViewProps {
|
||||
files: CurrentUserFile[]
|
||||
@ -114,6 +115,8 @@ const SlimPdfView = ({
|
||||
alt={`page ${i} of ${file.name}`}
|
||||
/>
|
||||
{marks.map((m) => {
|
||||
const { render: MarkRenderComponent } =
|
||||
MARK_TYPE_CONFIG[m.type] || {}
|
||||
return (
|
||||
<div
|
||||
className={`file-mark ${styles.mark}`}
|
||||
@ -129,7 +132,9 @@ const SlimPdfView = ({
|
||||
fontSize: inPx(from(page.width, FONT_SIZE))
|
||||
}}
|
||||
>
|
||||
{m.value}
|
||||
{typeof MarkRenderComponent !== 'undefined' && (
|
||||
<MarkRenderComponent value={m.value} mark={m} />
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { PdfPage } from '../types/drawing.ts'
|
||||
import { MarkType, PdfPage } from '../types/drawing.ts'
|
||||
import { PDFDocument, PDFFont, PDFPage, rgb } from 'pdf-lib'
|
||||
import { Mark } from '../types/mark.ts'
|
||||
import * as PDFJS from 'pdfjs-dist'
|
||||
@ -132,9 +132,17 @@ export const addMarks = async (
|
||||
|
||||
for (let i = 0; i < pages.length; i++) {
|
||||
if (marksPerPage && Object.hasOwn(marksPerPage, i)) {
|
||||
marksPerPage[i]?.forEach((mark) =>
|
||||
drawMarkText(mark, pages[i], robotoFont)
|
||||
)
|
||||
marksPerPage[i]?.forEach((mark) => {
|
||||
switch (mark.type) {
|
||||
case MarkType.SIGNATURE:
|
||||
drawSignatureText(mark, pages[i])
|
||||
break
|
||||
|
||||
default:
|
||||
drawMarkText(mark, pages[i], robotoFont)
|
||||
break
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -245,3 +253,19 @@ async function embedFont(pdf: PDFDocument) {
|
||||
const embeddedFont = await pdf.embedFont(fontBytes)
|
||||
return embeddedFont
|
||||
}
|
||||
|
||||
const drawSignatureText = (mark: Mark, page: PDFPage) => {
|
||||
const { location } = mark
|
||||
const { height } = page.getSize()
|
||||
|
||||
// Convert the mark location origin (top, left) to PDF origin (bottom, left)
|
||||
const x = location.left
|
||||
const y = height - location.top
|
||||
|
||||
if (hasValue(mark)) {
|
||||
const paths = JSON.parse(mark.value!)
|
||||
paths.forEach((d: string) => {
|
||||
page.drawSvgPath(d, { x, y })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user