diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..e6fca03 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,70 @@ +# SPDX-FileCopyrightText: 2026 LibreCode coop and contributors +# SPDX-License-Identifier: AGPL-3.0-or-later + +name: Bug report +description: Report a reproducible problem in PDF Elements +title: "[Bug]: " +labels: + - bug +body: + - type: markdown + attributes: + value: | + Thanks for helping improve PDF Elements. Please provide a minimal, reproducible report and do not upload confidential PDFs. + + - type: textarea + id: description + attributes: + label: What happened? + description: Describe the problem and what you expected instead. + placeholder: Tell us what you observed and what should have happened. + validations: + required: true + + - type: textarea + id: reproduce + attributes: + label: Steps to reproduce + description: Include the smallest set of steps, code or sample needed to reproduce the issue. + placeholder: | + 1. Render PDFElements with... + 2. Add an element... + 3. Resize... + validations: + required: true + + - type: input + id: version + attributes: + label: PDF Elements version + placeholder: e.g. 1.2.7 + validations: + required: true + + - type: input + id: vue + attributes: + label: Vue version + placeholder: e.g. 3.5.28 + + - type: input + id: environment + attributes: + label: Browser and operating system + placeholder: e.g. Firefox 143 on Fedora 42 + + - type: textarea + id: logs + attributes: + label: Console output or screenshots + description: Paste relevant logs or drag screenshots here. Remove secrets and sensitive data. + + - type: checkboxes + id: checks + attributes: + label: Before submitting + options: + - label: I searched existing issues for duplicates. + required: true + - label: I removed confidential or sensitive information from the report. + required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..6523418 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,11 @@ +# SPDX-FileCopyrightText: 2026 LibreCode coop and contributors +# SPDX-License-Identifier: AGPL-3.0-or-later + +blank_issues_enabled: true +contact_links: + - name: Live demo + url: https://libresign.github.io/pdf-elements/ + about: Reproduce and explore PDF Elements behavior in the browser. + - name: LibreSign + url: https://github.com/LibreSign/libresign + about: Report issues that belong to the LibreSign application rather than the PDF Elements component. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..94a3cbb --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,51 @@ +# SPDX-FileCopyrightText: 2026 LibreCode coop and contributors +# SPDX-License-Identifier: AGPL-3.0-or-later + +name: Feature request +description: Propose an improvement or new use case for PDF Elements +title: "[Feature]: " +labels: + - enhancement +body: + - type: textarea + id: problem + attributes: + label: What problem would this solve? + description: Describe the user or developer problem before describing the solution. + validations: + required: true + + - type: textarea + id: use-case + attributes: + label: Use case + description: Show where this would be useful in a real PDF or document workflow. + validations: + required: true + + - type: textarea + id: proposal + attributes: + label: Proposed solution + description: Describe an API, UI or behavior if you already have an approach in mind. + + - type: textarea + id: alternatives + attributes: + label: Alternatives considered + description: Include workarounds or alternative approaches you have tried. + + - type: checkboxes + id: contribution + attributes: + label: Contribution + options: + - label: I would be interested in working on this change. + + - type: checkboxes + id: checks + attributes: + label: Before submitting + options: + - label: I searched existing issues for similar requests. + required: true diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..9f9d30f --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,20 @@ + + +## What does this change? + +Describe the problem and the approach used to solve it. + +## How was it tested? + +List the automated or manual checks you ran. + +## Checklist + +- [ ] The change is focused on one problem. +- [ ] Tests were added or updated when behavior changed. +- [ ] Documentation was updated when public behavior or APIs changed. +- [ ] `npm run lint`, `npm run typecheck`, `npm run test` and `npm run build` pass when applicable. +- [ ] New source files include SPDX headers. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3149c1c..9a60c70 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,67 +5,113 @@ SPDX-License-Identifier: AGPL-3.0-or-later # Contributing to @libresign/pdf-elements -Thank you for your interest in contributing to @libresign/pdf-elements! We welcome contributions from the community. +Contributions are welcome. You do not need to work on a large feature to help: bug reports, reproduction cases, documentation, accessibility improvements, tests and focused code changes are all useful. -## Code of Conduct +## Before you start + +- Check the [open issues](https://github.com/LibreSign/pdf-elements/issues) to avoid duplicate work. +- For a substantial behavior or API change, open an issue first so the approach can be discussed before implementation. +- Keep pull requests focused on one problem whenever possible. + +## Reporting bugs + +Use the bug report template and include: + +- a clear description of the problem; +- exact steps to reproduce it; +- expected and actual behavior; +- browser and operating-system information when relevant; +- a minimal reproduction or sample PDF when possible; +- screenshots or console output when they help explain the issue. + +Please avoid attaching confidential or sensitive documents. + +## Suggesting improvements + +Feature requests are welcome. Describe the user problem first, then the proposed solution. Concrete use cases make requests easier to evaluate and implement. + +Good contributions are not limited to new features. Improvements to documentation, test coverage, accessibility, performance and developer experience are also valuable. + +## Development setup + +1. Fork the repository. +2. Clone your fork: -This project follows the LibreSign Code of Conduct. By participating, you are expected to uphold this code. + ```bash + git clone https://github.com/YOUR-USERNAME/pdf-elements.git + cd pdf-elements + ``` -## How to Contribute +3. Install dependencies: -### Reporting Bugs + ```bash + npm ci + ``` -Before creating bug reports, please check the issue list as you might find out that you don't need to create one. When you are creating a bug report, please include as many details as possible: +4. Start the demo: -* Use a clear and descriptive title -* Describe the exact steps which reproduce the problem -* Provide specific examples to demonstrate the steps -* Describe the behavior you observed after following the steps -* Explain which behavior you expected to see instead and why -* Include screenshots if possible + ```bash + npm run dev + ``` -### Suggesting Enhancements +5. Create a focused branch and make your changes. -Enhancement suggestions are tracked as GitHub issues. When creating an enhancement suggestion, please include: +## Validate your change -* Use a clear and descriptive title -* Provide a detailed description of the suggested enhancement -* Provide examples of how the enhancement would be used -* Explain why this enhancement would be useful +Run the checks relevant to your change before opening a pull request: -### Pull Requests +```bash +npm run lint +npm run typecheck +npm run test +npm run build +``` -* Fill in the required template -* Follow the JavaScript/Vue.js style guide -* Include SPDX headers in all new files -* Update the README.md with details of changes if needed -* Update the CHANGELOG.md following Keep a Changelog format -* Ensure all tests pass and linting is clean +For user-interface or browser behavior changes, also run: -## Development Setup +```bash +npm run test:e2e +``` -1. Fork the repository -2. Clone your fork: `git clone https://github.com/YOUR-USERNAME/pdf-elements.git` -3. Install dependencies: `npm install` -4. Create a feature branch: `git checkout -b my-feature` -5. Make your changes -6. Run lint: `npm run lint` -7. Build the library: `npm run build:lib` -8. Commit your changes: `git commit -am 'Add some feature'` -9. Push to the branch: `git push origin my-feature` -10. Create a Pull Request +The CI executes linting, type checking, package validation, unit tests and Playwright coverage. -## Coding Standards +## Pull requests -* Use 2 spaces for indentation -* Follow Vue.js style guide -* Add SPDX headers to all source files: - ```javascript - // SPDX-FileCopyrightText: 2026 LibreCode coop and contributors - // SPDX-License-Identifier: AGPL-3.0-or-later +A good pull request should: + +- explain the problem being solved; +- describe the approach taken; +- include regression coverage for bug fixes when practical; +- update documentation when public behavior changes; +- include SPDX headers in new source files; +- keep unrelated refactors out of the same change. + +Use meaningful Conventional Commit-style messages where possible, for example: + +``` +fix: keep element coordinates after zoom +feat: expose custom page footer slot +docs: add worker configuration example +test: cover cancelled element placement +``` + +## Coding standards + +- Follow the existing Vue and TypeScript conventions in the repository. +- Use the repository ESLint configuration instead of manually formatting around lint rules. +- Add SPDX headers to new source files: + + ```text + SPDX-FileCopyrightText: 2026 LibreCode coop and contributors + SPDX-License-Identifier: AGPL-3.0-or-later ``` -* Write meaningful commit messages -* Keep pull requests focused on a single feature or fix + +- Prefer small components and focused changes. +- Add or update tests for behavior changes. + +## Code of Conduct + +This project follows the [LibreSign Code of Conduct](https://github.com/LibreSign/libresign/blob/main/CODE_OF_CONDUCT.md). By participating, you are expected to follow it. ## License diff --git a/README.md b/README.md index c0df9e2..93b6adb 100644 --- a/README.md +++ b/README.md @@ -5,119 +5,50 @@ SPDX-License-Identifier: AGPL-3.0-or-later # PDF Elements -A Vue 3 component for rendering PDFs with draggable and resizable element overlays. +[![npm version](https://img.shields.io/npm/v/@libresign/pdf-elements)](https://www.npmjs.com/package/@libresign/pdf-elements) +[![Node CI](https://github.com/LibreSign/pdf-elements/actions/workflows/node.yml/badge.svg)](https://github.com/LibreSign/pdf-elements/actions/workflows/node.yml) +[![Tests](https://github.com/LibreSign/pdf-elements/actions/workflows/tests.yml/badge.svg)](https://github.com/LibreSign/pdf-elements/actions/workflows/tests.yml) -**[Demo](https://libresign.github.io/pdf-elements/)** · [Examples](examples/) +A Vue 3 PDF viewer for building interactive document workflows with draggable, resizable and fully customizable overlay elements. + +Use it to build signature placement, form-field positioning, annotations, review tools, document preparation flows and other PDF experiences where users need to place or manipulate elements on top of a document. + +**[Try the live demo](https://libresign.github.io/pdf-elements/)** · [Getting started](docs/GETTING_STARTED.md) · [API](docs/API.md) · [Examples](examples/) · [Contributing](CONTRIBUTING.md) ![The pdf-elements demo with a sample PDF loaded and a signature element placed on the first page](img/screenshot/demo.png) -## Development - -- `npm run dev` - Run the demo with Vite -- `npm run build` - Build the library (ESM + types) -- `npm run build:demo` - Build the demo to `dist-demo` - -## API - -### Props - -| Prop | Type | Default | Description | -|------|------|---------|-------------| -| `width` | String | `'100%'` | Container width | -| `height` | String | `'100%'` | Container height | -| `initFiles` | Array | `[]` | PDF files to load | -| `initFileNames` | Array | `[]` | Names for the PDF files | -| `initialScale` | Number | `1` | Initial zoom scale | -| `showPageFooter` | Boolean | `true` | Show page footer with document name and page number | -| `hideSelectionUI` | Boolean | `false` | Hide selection handles and actions UI | -| `showSelectionHandles` | Boolean | `true` | Show resize/move handles on selected elements | -| `showElementActions` | Boolean | `true` | Show action buttons on selected elements | -| `readOnly` | Boolean | `false` | Disable drag, resize, and actions for elements | -| `ignoreClickOutsideSelectors` | Array | `[]` | CSS selectors that keep the selection active when clicking outside the element | -| `pageCountFormat` | String | `'{currentPage} of {totalPages}'` | Format string for page counter | -| `autoFitZoom` | Boolean | `false` | Automatically adjust zoom to fit viewport on window resize | -| `pdfjsOptions` | Object | `{}` | Options passed to PDF.js `getDocument` (advanced) | - -### PDF.js options - -`pdfjsOptions` is forwarded to PDF.js `getDocument(...)` and can be used to tune performance. - -Example: - -```ts - -``` - -### Events - -- `pdf-elements:end-init` - Emitted when PDF is loaded -- `pdf-elements:adding-ended` - Emitted when interactive placement ends. Payload: `{ reason: 'placed', object, docIndex, pageIndex }` on success or `{ reason: 'cancelled' }` when the placement is cancelled. - -### Exposed methods - -- `startAddingElement(templateObject)` - Starts interactive placement mode. -- `cancelAdding()` - Cancels the current placement session and emits `pdf-elements:adding-ended` with `{ reason: 'cancelled' }` when a session was active. - -### Slots - -- `element-{type}` - Custom element rendering (e.g., `element-signature`) -- `custom` - Fallback for elements without specific type -- `actions` - Custom action buttons - -#### `actions` slot props - -The `actions` slot receives: - -- `object` -- `onDelete` -- `onDuplicate` -- `toolbarClass` (`pdf-elements-actions-toolbar`) -- `actionClass` (`pdf-elements-action-btn`) -- `actionAttrs` (`{ 'data-pdf-elements-action': 'true' }`) - -Use these hooks to style third-party button components consistently (for example, Nextcloud `NcButton`) without relying on internal scoped selectors. - -Example: - -```vue - -``` - -### Theme variables - -Action toolbar and action buttons can be themed via CSS variables and follow host theme tokens by default. - -| Variable | Description | -|---|---| -| `--pdf-elements-toolbar-gap` | Toolbar button gap | -| `--pdf-elements-toolbar-padding` | Toolbar padding | -| `--pdf-elements-toolbar-background` | Toolbar background color | -| `--pdf-elements-toolbar-color` | Toolbar text/icon color | -| `--pdf-elements-toolbar-border-color` | Toolbar border color | -| `--pdf-elements-toolbar-border-radius` | Toolbar border radius | -| `--pdf-elements-toolbar-shadow` | Toolbar shadow | -| `--pdf-elements-action-btn-border` | Action button border | -| `--pdf-elements-action-btn-background` | Action button background | -| `--pdf-elements-action-btn-color` | Action button text/icon color | -| `--pdf-elements-action-btn-padding` | Action button padding | -| `--pdf-elements-action-btn-radius` | Action button border radius | -| `--pdf-elements-action-btn-min-height` | Action button min height | -| `--pdf-elements-action-btn-min-width` | Action button min width | -| `--pdf-elements-action-btn-shadow` | Action button shadow | -| `--pdf-elements-action-btn-hover-background` | Action button hover background | +## Why PDF Elements? + +PDF rendering is only part of many document workflows. Applications often also need to let users place, move, resize, inspect or remove interactive elements over PDF pages. + +PDF Elements provides that interaction layer as a reusable Vue 3 component. + +- **PDF.js-based rendering** for browser PDF viewing +- **Draggable and resizable overlays** positioned directly on PDF pages +- **Custom element types** rendered through Vue slots +- **Interactive placement mode** for adding elements to a document +- **Multiple PDF documents** in the same component +- **Read-only mode** for review and presentation flows +- **Custom action toolbars** for host-application controls +- **Themeable UI** using CSS variables +- **Typed public API** for TypeScript projects + +PDF Elements does **not** cryptographically sign or modify the PDF by itself. It focuses on the browser interaction layer, so it can be connected to signing, storage, form or document-processing backends. + +## Use cases + +PDF Elements can be used for: + +- electronic-signature and document-preparation interfaces; +- signature, initials, date or text placement; +- PDF annotation and review tools; +- document form builders; +- approval and document workflows; +- applications that need coordinates and sizing for PDF overlays. + +## Documentation + +- [Getting started](docs/GETTING_STARTED.md) +- [API reference](docs/API.md) +- [Basic example](examples/basic/) +- [Contributing](CONTRIBUTING.md) diff --git a/docs/API.md b/docs/API.md new file mode 100644 index 0000000..caa0a14 --- /dev/null +++ b/docs/API.md @@ -0,0 +1,105 @@ + + +# PDF Elements API + +## Props + +| Prop | Type | Default | Description | +|------|------|---------|-------------| +| `width` | String | `'100%'` | Container width | +| `height` | String | `'100%'` | Container height | +| `initFiles` | Array | `[]` | PDF files to load | +| `initFileNames` | Array | `[]` | Names for the PDF files | +| `initialScale` | Number | `1` | Initial zoom scale | +| `showPageFooter` | Boolean | `true` | Show page footer with document name and page number | +| `hideSelectionUI` | Boolean | `false` | Hide selection handles and actions UI | +| `showSelectionHandles` | Boolean | `true` | Show resize/move handles on selected elements | +| `showElementActions` | Boolean | `true` | Show action buttons on selected elements | +| `readOnly` | Boolean | `false` | Disable drag, resize, and actions for elements | +| `ignoreClickOutsideSelectors` | Array | `[]` | CSS selectors that keep the selection active when clicking outside the element | +| `pageCountFormat` | String | `'{currentPage} of {totalPages}'` | Format string for page counter | +| `autoFitZoom` | Boolean | `false` | Automatically adjust zoom to fit viewport on window resize | +| `pdfjsOptions` | Object | `{}` | Options passed to PDF.js `getDocument` | + +## PDF.js options + +`pdfjsOptions` is forwarded to PDF.js `getDocument(...)`. + +```vue + +``` + +## Events + +- `pdf-elements:end-init` - Emitted when PDF is loaded. +- `pdf-elements:adding-ended` - Emitted when interactive placement ends. Payload: `{ reason: 'placed', object, docIndex, pageIndex }` on success or `{ reason: 'cancelled' }` when placement is cancelled. + +## Exposed methods + +- `startAddingElement(templateObject)` - Starts interactive placement mode. +- `cancelAdding()` - Cancels the current placement session and emits `pdf-elements:adding-ended` with `{ reason: 'cancelled' }` when a session was active. + +## Slots + +- `element-{type}` - Custom element rendering, for example `element-signature`. +- `custom` - Fallback for elements without a specific type slot. +- `actions` - Custom action buttons. + +### `actions` slot props + +The `actions` slot receives: + +- `object` +- `onDelete` +- `onDuplicate` +- `toolbarClass` (`pdf-elements-actions-toolbar`) +- `actionClass` (`pdf-elements-action-btn`) +- `actionAttrs` (`{ 'data-pdf-elements-action': 'true' }`) + +These hooks allow host applications to style third-party button components consistently without depending on internal scoped selectors. + +```vue + +``` + +## Theme variables + +Action toolbar and action buttons can be themed via CSS variables and follow host theme tokens by default. + +| Variable | Description | +|---|---| +| `--pdf-elements-toolbar-gap` | Toolbar button gap | +| `--pdf-elements-toolbar-padding` | Toolbar padding | +| `--pdf-elements-toolbar-background` | Toolbar background color | +| `--pdf-elements-toolbar-color` | Toolbar text/icon color | +| `--pdf-elements-toolbar-border-color` | Toolbar border color | +| `--pdf-elements-toolbar-border-radius` | Toolbar border radius | +| `--pdf-elements-toolbar-shadow` | Toolbar shadow | +| `--pdf-elements-action-btn-border` | Action button border | +| `--pdf-elements-action-btn-background` | Action button background | +| `--pdf-elements-action-btn-color` | Action button text/icon color | +| `--pdf-elements-action-btn-padding` | Action button padding | +| `--pdf-elements-action-btn-radius` | Action button border radius | +| `--pdf-elements-action-btn-min-height` | Action button min height | +| `--pdf-elements-action-btn-min-width` | Action button min width | +| `--pdf-elements-action-btn-shadow` | Action button shadow | +| `--pdf-elements-action-btn-hover-background` | Action button hover background | diff --git a/docs/GETTING_STARTED.md b/docs/GETTING_STARTED.md new file mode 100644 index 0000000..a9d7109 --- /dev/null +++ b/docs/GETTING_STARTED.md @@ -0,0 +1,55 @@ + + +# Getting started + +## Install + +```bash +npm install @libresign/pdf-elements +``` + +## Basic usage + +```vue + + + +``` + +For a fuller integration with custom controls, actions and document handling, see the [basic example](../examples/basic/). + +For the available props, events, methods, slots and theme variables, see the [API reference](API.md). diff --git a/package.json b/package.json index 83700f0..31ec5a8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@libresign/pdf-elements", - "description": "PDF viewer with draggable and resizable element overlays for Vue 3", + "description": "Vue 3 PDF viewer with draggable and resizable overlay elements for document workflows", "version": "1.2.7", "author": "LibreCode ", "private": false, @@ -24,15 +24,21 @@ "bugs": { "url": "https://github.com/LibreSign/pdf-elements/issues" }, - "homepage": "https://github.com/LibreSign/pdf-elements#readme", + "homepage": "https://libresign.github.io/pdf-elements/", "keywords": [ "pdf", - "viewer", + "pdfjs", + "pdf-viewer", + "pdf-editor", + "document-workflow", + "electronic-signature", "annotations", + "overlay", "draggable", "resizable", - "libresign", - "vue3" + "vue", + "vue3", + "libresign" ], "scripts": { "dev": "vite",