npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@promr-acorda/react

v0.6.7

Published

React UI for Promr Acorda electronic contract documents

Readme

@promr-acorda/react

@promr-acorda/core 문서를 다루는 React 뷰어 및 필드 편집 UI입니다. 필드 생성/이동/크기 조절(builder), 입력(fill), 서명(sign), 조회 전용(readonly) 모드와 서명/도장 입력 기능을 제공합니다.

설치

npm install @promr-acorda/react @promr-acorda/core

peer dependency로 react, react-dom(^18.2.0 || ^19.0.0)이 필요합니다.

빠른 시작

import { useState } from 'react';
import { ContractViewer } from '@promr-acorda/react';
import { createDocument, type ContractDocument } from '@promr-acorda/core';

function Viewer() {
  const [doc, setDoc] = useState<ContractDocument>(() =>
    createDocument({
      id: 'contract-001',
      title: '근로계약서',
      pdfData: pdfBytes,
      pageCount: 1,
      pages: [{ index: 0, width: 612, height: 792 }],
    })
  );

  return (
    <ContractViewer
      mode="fill"
      document={doc}
      onDocumentChange={setDoc}
      pageWidth={900}
      viewportHeight="80vh"
    />
  );
}

document.pdfData가 실제 PDF(이미지 기반 pageImages가 없는 경우)라면, 렌더링 전에 pdf.js worker를 한 번 설정해야 합니다. (설정하지 않으면 렌더링 시 에러가 발생합니다.)

import { configurePdfWorker } from '@promr-acorda/react';

configurePdfWorker('/pdf.worker.min.mjs');

document.pageImages가 있으면(예: @promr-acorda/corecreateDocumentFromPdfData로 미리 렌더링한 이미지를 넣어둔 경우) 이미지 기반 렌더링을 우선 사용하므로 pdf.js worker 설정이 필요 없습니다.

모드

| 모드 | 설명 | | --- | --- | | builder | 필드 생성, 이동, 크기 조절 | | fill | 필드 값 입력 | | sign | 입력 + 서명/도장 입력 | | readonly | 조회 전용 |

ContractViewer Props

| Prop | 타입 | 설명 | | --- | --- | --- | | mode | ContractMode | builder | fill | sign | readonly | | document | ContractDocument | 렌더링할 문서 | | onDocumentChange | (next) => void | 문서가 변경될 때마다 다음 문서를 전달받는 콜백 | | onFieldValueChange? | (event) => void | 필드 값이 설정될 때 호출 | | onFieldValueClear? | (event) => void | 필드 값이 제거될 때 호출 | | onSignatureRequest? | (fieldId, mode) => void | 기본 서명/도장 입력 UI를 열어야 할 때 호출 | | onStampRequest? | 아래 참고 | 기본 업로드 UI 대신 외부 도장 선택 흐름 연결 | | pageWidth? | number | 렌더링 페이지 너비(px). 생략하면 뷰어 컨테이너 폭에 맞춰 자동 계산됩니다(240~1400px 범위) | | viewportHeight? | number \| string | 뷰어 높이. 기본값 '80vh' | | showPageNavigation? | boolean | 페이지 이동 UI 표시 여부 | | showZoomBar? | boolean | 하단 줌 바 표시 여부. 기본값 true | | pdfWorkerSrc? | string | pdf.js worker 경로 (configurePdfWorker 대신 사용 가능) | | layoutMode? | 'pagination' \| 'scroll' | 아래 참고. 기본값 'pagination' | | locale? | 'ko' \| 'en' | 기본값 'ko' | | localeMessages? | Partial<TranslationMessages> | 특정 문구만 덮어쓰기 | | className?, style? | - | 루트 엘리먼트에 적용 |

필드 텍스트는 실제 렌더링된 페이지 폭에 맞춰 함께 스케일되므로, 뷰어가 원본 크기로 표시되든(pageWidth 그대로) 화면이 작아 축소되든 항상 페이지 대비 비율이 유지됩니다.

layoutMode

  • 'pagination'(기본값): 현재 선택된 페이지만 렌더링하고 페이지 네비게이션을 표시합니다.
  • 'scroll': 모든 페이지를 세로로 나열해서 보여주고, 화면 밖 페이지는 spacer로 대체 렌더링(가상화)해 렌더링 리소스를 절약합니다.
<ContractViewer mode="builder" document={doc} onDocumentChange={setDoc} layoutMode="scroll" />

다국어(i18n)

기본 언어는 한국어('ko')이며, KO_MESSAGES/EN_MESSAGES를 내부에서 FieldBox, ContractCanvasPages 등 하위 컴포넌트에 일관되게 적용합니다.

<ContractViewer mode="fill" document={doc} onDocumentChange={setDoc} locale="en" />

// 일부 문구만 덮어쓰기
<ContractViewer
  mode="fill"
  document={doc}
  onDocumentChange={setDoc}
  locale="ko"
  localeMessages={{ uploadStamp: '도장 첨부' }}
/>

값 변경 처리

<ContractViewer
  mode="sign"
  document={doc}
  onDocumentChange={setDoc}
  onFieldValueChange={(event) => {
    console.log(event.fieldId, event.value, event.nextDocument);
  }}
  onFieldValueClear={(event) => {
    console.log('cleared', event.fieldId, event.nextDocument);
  }}
  onSignatureRequest={(fieldId, signatureMode) => {
    console.log('signature requested', fieldId, signatureMode);
  }}
/>

외부 도장 선택 UI 연결 (onStampRequest)

onStampRequestsignatureMode: 'stamp-only' 서명 필드의 도장 입력을 외부 앱(예: 등록된 도장 목록)에서 처리하기 위한 콜백입니다. 빈 상태의 Upload Stamp 버튼과 signatureActions.edit 액션에서 우선 호출됩니다.

type OnStampRequest = (
  fieldId: string,
  context: { field: ContractField; document: ContractDocument }
) =>
  | Promise<ContractViewerBinaryImageInput | void>
  | ContractViewerBinaryImageInput
  | void;
<ContractViewer
  mode="sign"
  document={doc}
  onDocumentChange={setDoc}
  onStampRequest={async (fieldId, { field, document }) => {
    const selectedStamp = await openRegisteredStampPicker();
    if (!selectedStamp) return; // 기본 업로드 UI로 fallback

    return {
      image: selectedStamp.bytes,
      mimeType: selectedStamp.mimeType,
      width: selectedStamp.width,
      height: selectedStamp.height,
    };
  }}
/>

반환값 처리 규칙:

  • 이미지를 반환하면 뷰어가 내부적으로 setStampImage(fieldId, image)와 동일한 경로로 값을 저장하고, 기존과 동일하게 onDocumentChange/onFieldValueChange를 호출합니다.
  • void를 반환하거나 prop이 없으면 기존 파일 업로드 UI로 fallback합니다.
  • 콜백이 throw/reject되면 파일 업로드 UI로 fallback하지 않고 필드 위에 에러를 표시합니다.
  • 같은 필드에 대해 요청이 이미 진행 중이면 중복 요청을 보내지 않습니다.
  • disabled, readonly, mirror 공유 필드처럼 편집할 수 없는 필드는 액션이 표시되지 않거나 동작하지 않습니다.

뷰어 Ref API

import { useRef } from 'react';
import { ContractViewer, type ContractViewerHandle } from '@promr-acorda/react';

const viewerRef = useRef<ContractViewerHandle>(null);

// 페이지 이동
viewerRef.current?.goToPage(2);
viewerRef.current?.nextPage();
viewerRef.current?.previousPage();
viewerRef.current?.getActivePageIndex();
viewerRef.current?.getPageCount();

// builder 모드에서 드래그로 필드 배치 시작/취소
viewerRef.current?.beginDragCreate('text', { placeholder: '이름 입력' });
viewerRef.current?.cancelDragCreate();

// 서명/도장 이미지 직접 주입
viewerRef.current?.setSignatureImage('employeeSignature', {
  image: signaturePngBytes,
  mimeType: 'image/png',
});

viewerRef.current?.setStampImage('employeeSignature', {
  image: stampPngBytes,
  mimeType: 'image/png',
});

// 서명/도장 구분 없이 필드 타입에 맞는 이미지 주입
viewerRef.current?.setFieldImage('employeeSignature', {
  image: pngBytes,
  mimeType: 'image/png',
});

필드 표시 관련 세부 동작

  • 텍스트 정렬/크기: field.textAlign, field.textSize가 화면 렌더링에도 그대로 반영됩니다 (PDF export와 동일 기준).
  • 체크박스: 텍스트 대신 체크박스 아이콘으로 표시됩니다.
  • readonly vs disabled: readonly 필드는 값만 표시하고, disabled 필드는 테두리/placeholder 같은 입력 UI는 유지한 채 입력·이동·크기조절만 막습니다.
  • 공유 필드: sharedMode: 'mirror' 필드는 직접 입력할 수 없고 source 필드의 값을 따라갑니다.

그 외 내보낸 컴포넌트

  • ContractCanvasPagesContractViewer 내부에서 사용하는 캔버스 페이지 렌더러를 직접 제어해야 할 때 사용합니다.
  • ContractPdfPages — pdf.js 기반 PDF 페이지 렌더링만 필요할 때 사용합니다.
  • FieldBox — 단일 필드 오버레이 컴포넌트입니다.
  • getDocumentPageCount(document), loadRenderedPage(document, pageIndex, signal?) — 페이지 렌더링을 직접 다룰 때 사용하는 저수준 유틸리티입니다.

라이선스

MIT