open-index/open-npm huggingface dataset:
npm package: @pacamelo/core
Description: Core PII detection and redaction engine for PURGE
Latest version: 1.1.0

# @pacamelo/core

Core PII detection and redaction engine for [PURGE](https://purgedata.app).

## Why Open Source?

This package contains all the code that touches your data. We open-source it so you can verify:

- **What patterns we search for** - See exactly which regex patterns detect PII
- **How files are parsed** - Verify no data is exfiltrated during processing
- **How masking works** - Check that sensitive data is properly hidden
- **Security measures** - Audit ReDoS protection, memory cleanup, etc.

The PURGE UI remains proprietary, but the data-processing core is transparent.

## Installation

```bash
npm install @pacamelo/core
```

## What's Included

### Detection Engine
- Regex patterns for: emails, SSNs, phone numbers, credit cards, addresses, names
- Configurable sensitivity levels
- Web Worker isolation for ReDoS protection

### Document Processors
- XLSX parser with column selection
- Metadata stripping on output
- Formula detection warnings

### Utilities
- PII masking (partial masks, full redaction)
- Secure random ID generation
- File type validation via magic bytes

### React Hooks
- `useDocumentProcessor` - Main processing orchestration
- `useOfflineEnforcement` - Privacy mode state machine
- `useFileEntropy` - Before/after verification

## Usage

```typescript
import {
  regexDetectionEngine,
  getProcessorForFile,
  useDocumentProcessor,
  type Detection,
} from '@pacamelo/core';

// Detect PII in text
const result = await regexDetectionEngine.detect(content, config);
console.log(result.detections); // Array of Detection objects

// Process a file
const processor = getProcessorForFile(file);
const parsed = await processor.parse(file);
const blob = await processor.applyRedactions(parsed, redactions);
```

## Security Features

- **ReDoS Protection**: Regex runs in Web Workers with enforced timeouts
- **Memory Cleanup**: Buffers zeroed after processing (best-effort in JS)
- **Metadata Stripping**: Output files rebuilt without hidden content
- **Offline Mode**: Encourages airplane mode during sensitive processing

## License

MIT - See [LICENSE](./LICENSE)

## Contributing

Issues and PRs welcome at [github.com/Pacamelo/purge-core](https://github.com/Pacamelo/purge-core).
npm package: @pacely-next/api-provider
Description: ### Functions
Latest version: 1.0.3

# API Provider for Pacely

### Functions

A list of Firebase Functions needed for Pacely.

| Resource        | What's the trigger? | Method name                     | What happens?                                           | Condition                                                                     |
|-----------------|---------------------|---------------------------------|---------------------------------------------------------|-------------------------------------------------------------------------------|
| `time_entries`  | `onDocumentCreated` | `timeEntryCreated`              | Update `totalTrackedTime` on the task.                  | When a time entry is completed, update the total time on the task.            |
| `time_entries`  | `onDocumentUpdated` | `timeEntryUpdated`              | Update `totalTrackedTime` on the task.                  | When a time entry is completed, update the total time on the task.            |
| `time_entries`  | `onDocumentUpdated` | `timeEntryUpdated`              | Update `totalTrackedTime` on the project.               | When a time entry is completed, update the total time on the project.         |
| `tasks`         | `onDocumentCreated` | `projectTasksCreated`           | Update `taskStatus` on the project.                     | When a task is created, update total and completed tasks on project.          |
| `tasks`         | `onDocumentUpdated` | `projectTasksUpdated`           | Update `taskStatus` on the project.                     | When a task is marked completed, update total and completed tasks on project. |
| `tasks`         | `onDocumentUpdated` | `projectMembershipUpdated`      | Update `taskIds` on the section.                        | When task membership changes, update the taskSections `taskIds`               |
| `projects`      | `onDocumentUpdated` | `updateTaskResource('project')` | Update `tasks.memberships.project.name` on the project. | When a project name changes, update the `tasks.memberships.project.name`      |
| `task_sections` | `onDocumentUpdated` | `updateTaskResource('section')` | Update `tasks.memberships.section.name` on the project. | When a section name changes, update the `tasks.memberships.section.name`      |
npm package: @pacely-next/office
Description: ## Authentication
Author: Chris Magnussen
Latest version: 1.0.3



# @pacely/office

## Authentication

#### Strategies

Our authentication strategies currently includes:

Protocol | Grant type | Current stats
-------- | -------- |  ---------
OAuth2 | [Client Credentials](https://oauth.net/2/grant-types/client-credentials/) | `ready`
OAuth2 | [Authorization Code](https://oauth.net/2/grant-types/authorization-code/) | `not started`
OAuth2 | [Device Code](https://oauth.net/2/grant-types/device-code/) | `not started`
JWT | [JSON Web Tokens](https://jwt.io/) | `not started`

#### Constructor options

Option | Type | Description | Default
------ | ---- | ----------- | -------
provider | string | Choose provider. | `poweroffice`
auth | object | Object containing keys etc. | -
testing | bool | Whether to authenticate with a demo api. | `false`

#### Example

```typescript
import Office from '@pacely/office'

let authenticated: boolean = false;

const office = new Office({
    provider: 'poweroffice',
    testing: true,
    auth: {
        client_id: '<Client ID>',
        client_key: '<Client key>'
    }
});

// Authenticate with the choosen provider
office.authenticate().then((authStatus: boolean) => {
    authenticated = authStatus
});
```

## Resources

### Customers

```typescript
const provider = office.provider;

if (provider.authenticated) {
    const customers: CustomerModel[] = provider.customers({ allFields: true }).all();
    
    customers.map((customer: CustomerModel) => {
        console.log(customer.name); // ACME AS
    })
}
```

### Invoices

#### Get invoices
```typescript
const provider = office.provider;

if (provider.authenticated) {
    const invoices: Invoice[] = provider.invoices.find({
        filter: {
            projectCode: 1234,
            totalAmount: {
                operator: 'gt',
                value: 200
            }
        },
        order: {
            totalAmount: 'asc'
        },
        top: 10
    });
    
    invoices.map((invoice: Invoice) => {
        console.log(invoice.totalAmount);
    })
}
```

#### Project
```typescript
if (provider.authenticated) {
    const projects: Project[] = provider.projects.all();
    const project: Project = provider.projects.find(id);
    const projectActivities: ProjectActivity[] = provider.projects.activities.all();
    const customers: CustomerModel[] = await office.customers().all();
}
```

### API'er

- PowerOffice - https://api.poweroffice.net/Web/docs/index.html#Reference/Rest/Services.md
- SuperOffice - https://community.superoffice.com/documentation/sdk/SO.NetServer.Web.Services/html/Reference-WebAPI-WebAPI.htm
- Fiken - https://api.fiken.no/api/v2/docs/#/companies/getCompanies


https://github.com/nuxt-community/auth-module/blob/dev/src/index.ts
npm package: @pacely-next/ui
Description: !! https://www.tremor.so/docs/components/area-chart !! https://github.com/tremorlabs/tremor
Latest version: 1.4.5

### TODO

!! https://www.tremor.so/docs/components/area-chart
!! https://github.com/tremorlabs/tremor

#### Reference

- https://flowbite.com/blocks/
- https://preline.co/docs/index.html
- https://www.material-tailwind.com/docs/react/button [Github](https://github.com/creativetimofficial/material-tailwind/tree/main)

#### Coded dashboards
- https://www.themes.dev/library/aircontrol-tailwindcss-admin-theme/#accounts
- https://flowbite.com/application-ui/preview/
- http://www.getnexel.link/html/crm/dist/templates/index.html
- https://ui8-brainwave.herokuapp.com/updates-and-faq
- https://www.tailwindawesome.com/resources/mosaic/demo
- Marketing: https://taildash.tailwinddashboard.com/index-marketing.html
npm package: @pacely/javascript-utilities
Description: JS/TS utilities for polaris-vue
Author: Chris Magnussen
Latest version: 3.0.14
Deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.

# `@pacely/javascript-utilities`

[![npm version](https://badge.fury.io/js/%40shopify%2Fjavascript-utilities.svg)](https://badge.fury.io/js/%40shopify%2Fjavascript-utilities)

## Installation

```bash
$ yarn add @pacely/javascript-utilities
```
npm package: @pacely/poweroffice-node
Description: API Client for PowerOffice Go. Supports API v2
Author: Prek AS
Latest version: 1.1.0

# @pacely/poweroffice-node (Unofficial)

A JS client for interacting with the PowerOffice API. Supports versjon 2.0 of the API and is designed to be used in Node.js environments.

> To get an API key, you need to create an application in PowerOffice and obtain the necessary keys (appKey, clientKey, subscriptionKey). You can find more information on how to do this in the [PowerOffice documentation](https://developer.poweroffice.net/gettingstarted/1).

## Features

- Simple and intuitive API for PowerOffice integration
- Supports authentication and common PowerOffice endpoints
- Written in TypeScript

## Installation

```bash
pnpm add @pacely/poweroffice-node
```

## Usage

```typescript
import dotenv from 'dotenv'; // Ensure you have dotenv installed and configured
import PowerOffice from '@pacely/poweroffice-node';

dotenv.config(); // Load environment variables from .env file

const client = new PowerOffice({
    appKey: process.env.POGO_APP_KEY,
    clientKey: process.env.POGO_CLIENT_KEY,
    subscriptionKey: process.env.POGO_SUBSCRIPTION_KEY,
    dev: true // Replace with false for production
});

async function main() {
    await client.authenticate();
    const companies = await client.getCompanies();
    console.log(companies);
}

main();
```

## API

### `new PowerOffice(options)`

- `appKey` (string): Your PowerOffice application key
- `clientKey` (string): Your PowerOffice client key
- `subscriptionKey` (string): Your PowerOffice subscription key
- `dev` (boolean): Set to `true` for development mode, `false` for production

### `authenticate()`

Authenticate with the PowerOffice API.

## Access services

All services are available as methods on the `PowerOffice` instance. You can access each service by their respective names. For example:

```typescript
// Sales Orders 
// https://goapi.poweroffice.net/v2/SalesOrders
const salesOrders = await client.salesOrders();

// Customers
// https://goapi.poweroffice.net/v2/Customers
const customers = await client.customers();

// Etc...
```

Each service has their own methods for interacting with the PowerOffice API. Refer to the source code for detailed method signatures and usage.

```typescript
// Initialize Sales Orders
const salesOrders = await client.salesOrders(); // Replace '12345' with actual sales order ID

// Get a specific sales order
const salesOrder = await salesOrders.salesOrder.getSalesOrderById({
    id: '12345'
});

console.log(salesOrder);
```

Read [PowerOffice API documentation](https://prdm0go0stor0apiv20eurw.z6.web.core.windows.net/?urls.primaryName=Accounting%20Settings) for more details on available endpoints and parameters.

## License

This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.

## Contributing

Contributions are welcome! Please read the [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute to this project.
npm package: @pacely/vatsearch
Description: Search for company records in all Nordic countries.
Author: Chris Magnussen
Latest version: 2.1.4

# @pacely/vatsearch

[![npm version][npm-version-src]][npm-version-href]
[![npm downloads][npm-downloads-src]][npm-downloads-href]
[![License][license-src]][license-href]

> Search for company records in all Nordic countries ⚡️

- [✨ &nbsp;Release Notes](https://github.com/pacelyapp/vatsearch/releases)

## Features

- 👌&nbsp; Search for all companies in Norway, Denmark, Sweden and Finland
- ⚡&nbsp; Get opinionated Risk Analysis on all companies 

## Quick Setup

Add `@pacely/vatsearch` dependency to your project

```bash
# Using npm
npm install @pacely/vatsearch

# Using yarn
yarn add @pacely/vatsearch
```

## Usage

```typescript
import VatSearch, { VatRegister, Company } from "@pacely/vatsearch";

// Initialize the parser
const vatsearch = new VatSearch({ register: VatRegister.NO }).parser()

// Get all companies (Only available for NO)
vatsearch.all().then((response: Company[]) => {
    console.log(response)
})

// Search for a company by name
vatsearch.find('Hirvi AS').then((response: Company[]) => {
    console.log(response)
})

// Get a single company by VATID/Organization identifier
vatsearch.get(10150817).then((response: Company) => {
    console.log(response)
})
```

## Response

The response object contains the following and is the same for all registers

```typescript
interface Company {
    vatid: string | number;
    name: string;
    dateStarted: string;
    employees: number | string;
    companyType: string;
    address: CompanyAddress;
    website: string;
    bankrupt: boolean | string | 'not_available';
    contact: CompanyContact | string | 'not_available';
    risk: RiskAnalyses;
    [x: string]: any;
}

interface CompanyAddress {
    address: string;
    zip: number;
    place: string;
    municipal?: string;
    country: string;
}

interface CompanyContact {
    phone?: string | number;
    email?: string;
    fax?: string | number;
}

interface RiskAnalyses {
    score: number
    risks: {
        [x: string]: any;
    }[]
    info: string
}
```

## Configuration

This package takes a single configuration while initializing. 
The `register` flag tells it what API to use for your request.

```typescript
const vatsearch = new VatSearch({
    register: 'NO' // NO, DK, SV, FI
})
```

You can change the configuration afterwards by doing `vatsearch.setOptions(options)`.

## License

[MIT License](./LICENSE)

Copyright (c) HIRVI AS

[npm-version-src]: https://img.shields.io/npm/v/@pacely/vatsearch/latest.svg
[npm-version-href]: https://npmjs.com/package/@pacely/vatsearch

[npm-downloads-src]: https://img.shields.io/npm/dt/@pacely/vatsearch.svg
[npm-downloads-href]: https://npmjs.com/package/@pacely/vatsearch

[license-src]: https://img.shields.io/npm/l/@pacely/vatsearch.svg
[license-href]: https://npmjs.com/package/@pacely/vatsearch
npm package: @pacely/vue-utilities
Description: Utilities/helpers for polaris-vue
Author: Chris Magnussen
Latest version: 2.0.28
Deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.

# `@pacely/vue-utilities`

[![npm version](https://badge.fury.io/js/%40shopify%2Freact-utilities.svg)](https://badge.fury.io/js/%40shopify%2Freact-utilities)

## Installation

```bash
$ yarn add @pacely/vue-utilities
```
npm package: @pacer-ui/tailwind-preset
Description: Shared Tailwind CSS preset untuk PACER (Pertamina Patra Niaga Components & Experience Resources).
Latest version: 1.0.1

# @pertamina/tailwind-preset

Shared Tailwind CSS preset untuk PACER (Pertamina Patra Niaga Components & Experience Resources).

## Installation

```bash
npm install @pertamina/tailwind-preset
# or
pnpm add @pertamina/tailwind-preset
```

## Usage

### Basic Setup

```js
// tailwind.config.js
module.exports = {
  presets: [require('@pertamina/tailwind-preset')],
  content: [
    './src/**/*.{js,jsx,ts,tsx}',
    './pages/**/*.{js,jsx,ts,tsx}',
  ],
}
```

### With Custom Overrides

```js
// tailwind.config.js
module.exports = {
  presets: [require('@pertamina/tailwind-preset')],
  content: [
    './src/**/*.{js,jsx,ts,tsx}',
  ],
  theme: {
    extend: {
      // Override atau tambah custom values
      colors: {
        custom: '#123456',
      },
    },
  },
}
```

## What's Included

Preset ini mengintegrasikan semua design tokens:

### Colors
```jsx
<div className="bg-brand-primary-500 text-neutral-0">
  Pertamina Primary
</div>
```

### Spacing
```jsx
<div className="p-4 m-6 gap-3">
  4px-based spacing
</div>
```

### Typography
```jsx
<p className="font-sans text-base font-medium leading-normal">
  Typography tokens
</p>
```

### Border Radius
```jsx
<div className="rounded-lg">
  Border radius tokens
</div>
```

### Shadows
```jsx
<div className="shadow-lg">
  Shadow tokens
</div>
```

### Animations
```jsx
<div className="transition-all duration-fast ease-easeInOut">
  Motion tokens
</div>
```

## Component Classes

Preset juga menyediakan base component classes:

### Button
```jsx
<button className="btn bg-brand-primary-500 text-neutral-0">
  Button
</button>
```

### Input
```jsx
<input className="input" type="text" />
```

### Card
```jsx
<div className="card">
  Card content
</div>
```

## Dark Mode

Dark mode menggunakan class strategy:

```jsx
// Tambah class 'dark' di root element
<html className="dark">
  <body>
    <div className="bg-neutral-0 dark:bg-neutral-900">
      Content
    </div>
  </body>
</html>
```

## Blazor Integration

Untuk Blazor, compile Tailwind CSS ke static file:

```bash
# package.json
{
  "scripts": {
    "build:css": "tailwindcss -i ./src/styles.css -o ./wwwroot/css/styles.css --minify"
  }
}
```

```css
/* src/styles.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
```

## Philosophy

1. **Token-based** - Semua value dari design tokens
2. **Consistent** - Sama di React, Vue, dan Blazor
3. **Extensible** - Dapat di-override sesuai kebutuhan
4. **Type-safe** - Full TypeScript support
5. **Tree-shakeable** - Hanya CSS yang dipakai akan di-bundle

## Updating

Ketika design tokens di-update, rebuild preset:

```bash
pnpm build
```

Semua library yang depend ke preset ini akan otomatis menggunakan tokens terbaru.
npm package: @pacer-ui/tokens
Description: Framework-agnostic design tokens untuk PACER (Pertamina Patra Niaga Components & Experience Resources).
Latest version: 1.0.1

# @pacer-ui/tokens

Framework-agnostic design tokens untuk PACER (Pertamina Patra Niaga Components & Experience Resources).

## Installation

```bash
npm install @pacer-ui/tokens
# or
pnpm add @pacer-ui/tokens
```

## Usage

### TypeScript/JavaScript

```typescript
import { tokens, colors, spacing, typography } from '@pacer-ui/tokens';

// Use individual tokens
const primaryColor = colors.brand.primary[500]; // #0073e6
const baseSpacing = spacing[4]; // 16px

// Use all tokens
console.log(tokens);
```

### JSON

```javascript
import tokens from '@pacer-ui/tokens/json';

// Raw token data as JSON
```

### CSS Custom Properties

```css
@import '@pacer-ui/tokens/css';

.my-component {
  color: var(--color-brand-primary-500);
  padding: var(--spacing-4);
  font-size: var(--font-size-base);
}
```

## Token Categories

### Colors
- `colors.brand.primary` - Primary brand colors
- `colors.brand.secondary` - Secondary brand colors
- `colors.success` - Success states
- `colors.warning` - Warning states
- `colors.error` - Error states
- `colors.info` - Info states
- `colors.neutral` - Neutral/grayscale colors

### Spacing
4px-based spacing scale: `0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24...`

### Typography
- `typography.fontFamily` - Font families
- `typography.fontSize` - Font sizes (xs - 7xl)
- `typography.fontWeight` - Font weights
- `typography.lineHeight` - Line heights
- `typography.letterSpacing` - Letter spacing

### Border Radius
From `sm` (2px) to `3xl` (24px), plus `full` (9999px)

### Shadows
Elevation system from `sm` to `2xl`

### Motion
- `motion.duration` - Animation durations
- `motion.easing` - Easing functions

### Breakpoints
Responsive breakpoints: `sm, md, lg, xl, 2xl`

### Z-Index
Layering system for UI elements

## Philosophy

Design tokens mengikuti prinsip:

1. **Semantic naming** - Nama berdasarkan tujuan, bukan nilai
2. **Hierarchical organization** - Struktur bertingkat yang konsisten
3. **Theme-able** - Mendukung light/dark mode
4. **Framework-agnostic** - Dapat digunakan di React, Vue, Blazor
5. **Single source of truth** - Satu sumber untuk semua nilai design

## Updating Tokens

Token dikelola di `src/index.ts`. Setelah update:

```bash
pnpm build
```

Akan men-generate:
- `dist/index.js` - ESM/CJS modules
- `dist/tokens.json` - Raw JSON
- `dist/tokens.css` - CSS Custom Properties
npm package: @paceui/cli
Description: Easily integrate, customizable, copy-pasteable Tailwind components and variants into your React and Next.js apps
Author: Denish Navadiya
Latest version: 0.0.2

[![hero](https://github.com/paceui/paceui/raw/main/public/images/banner.png)](https://paceui.com/)

# PaceUI

A collection of ready-to-use component variants that you can easily copy, paste, and customize for React and Next.js apps.
Stay tuned for more components, snippets, complete blocks, and design resources coming your way!

## Getting Started

Head over to the [paceui.com](https://paceui.com/) documentation to get started!
npm package: @pacexy/eslint-config
Description: ESLint config based on @antfu/eslint-config
Author: pacexy
Latest version: 2.0.0

# @pacexy/eslint-config

ESLint config based on [@antfu/eslint-config]

## Install

```bash
pnpm i -D eslint @pacexy/eslint-config
```

## Usage

```js
// eslint.config.mjs
import { defineConfig } from '@pacexy/eslint-config'

export default defineConfig()
```

See [@antfu/eslint-config] for more details.

## See Also

- [@sxzz/eslint-config](https://github.com/sxzz/eslint-config)
- [eslint-config-hyoban](https://github.com/hyoban/eslint-config-hyoban)

## License

[MIT](./LICENSE) License © [pacexy](https://github.com/pacexy)

[@antfu/eslint-config]: https://github.com/antfu/eslint-config
npm package: @pachamamas/factorial-clock-in
Description: Set of utilities to use from Google Chrome extensions to facilitate the use of Factorial HR.
Latest version: 1.0.2

# factorial-clock-in

Set of utilities to use from Google Chrome extensions to facilitate the use of
[Factorial HR](https://factorialhr.es/).

This library contains a set of functions intended to be run from
[https://factorialhr.es/](https://factorialhr.es/). These functions make
requests to the Factorial API to facilitate the use of this tool.

## Install

```bash
npm i -S @pachamamas/factorial-clock-in
```

## Use

Batch time recording:

```javascript
factorialhr
  .batch({
    month: 2, // First month is 0
    year: 2024,
    intervals: [
      {
        clock_in: '08:30',
        clock_out: '14:00',
      },
      {
        clock_in: '16:00',
        clock_out: '18:30',
      },
    ],
    minutes_per_day: 480,
    // dry_run: true, // Uncomment to see in console the simulated result of the execution without any change being made.
  })
  .then();
```

Delete all hours in a period:

```javascript
factorialhr.deleteAllShiftsByPeriodId({ period_id: 13401838 }).then();
```
npm package: @pachomski/delve
Description: Delve returns a useful data model of your GraphQL Schema. That's about it.
Author: Chris Pachomski
Latest version: 0.1.0

# Delve

Delve returns a useful data model of your GraphQL Schema. That's about it.

![](https://img.shields.io/npm/v/@pachomski/delve.svg?style=flat-square) ![](https://img.shields.io/bundlephobia/minzip/@pachomski/delve.svg?style=flat-square)

### Install

`npm i @pachomski/delve`

### Usage

```javascript
import delve from "@pachomski/delve";

const schema = await delve("https://your-graphql-endpoint.com/graphql");
// ...now do stuff with schema

// OR

delve("https://your-graphql-endpoint.com/graphql").then(schema => {
  // ...now do stuff with schema
});
```
npm package: @pachun/react-native-use-app-lifecycle
Description: React Native hook to run onLaunch, onFocus and onBlur callbacks
Latest version: 1.0.9

[![npm version](https://img.shields.io/npm/v/@pachun/react-native-use-app-lifecycle.svg)](https://www.npmjs.com/package/@pachun/react-native-use-app-lifecycle)
[![cov](https://pachun.github.io/react-native-use-app-lifecycle/badges/coverage.svg)](https://github.com/pachun/react-native-use-app-lifecycle/actions)

# useAppLifecycle

A react native hook to run code when your app is launched, focused and blurred.

## Install

```sh
yarn add @pachun/react-native-use-app-lifecycle
```

## Usage

In your topmost-level component:

```tsx
import useAppLifecycle from "@pachun/react-native-use-app-lifecycle"

const App = () => {
  useAppLifecycle({
    onLaunch: () => console.log("launch"),
    onFocus: () => console.log("focus"),
    onBlur: () => console.log("blur"),
  })

  return <></>
}

export default App
```

## Motivation

I've been copying and pasting this code into all my RN projects for a long time. Usually, I use it [to check for and download Over-The-Air (OTA) expo updates](https://docs.expo.dev/versions/latest/sdk/updates/).

## Contributing

PRs are exciting 🤟 Bump the version number in `package.json` and open some.
npm package: @pachun/rn-pdf-reader-js
Description: PDF reader for Expo
Author: Xavier Carpentier
Latest version: 0.5.0

<h1 align="center">PDF reader for Expo</h1>
<p align="center">Android support 🚀</p>

<p align="center">
   <img width="250" src="https://thumbs.gfycat.com/DeadPoisedBrownbutterfly-max-14mb.gif" />
   <br/>
   <br/>
   <br/>
   <br/>
   <a href="https://www.npmjs.com/package/rn-pdf-reader-js"><img alt="npm version" src="https://badge.fury.io/js/rn-pdf-reader-js.svg"/>
   <a href="http://reactnative.gallery/xcarpentier/rn-pdf-reader-js"><img src="https://img.shields.io/badge/reactnative.gallery-%F0%9F%8E%AC-green.svg"/></a>
</a>
</p>
<p align="center">
  <a href="https://exp.host/@xcarpentier/rn-pdf-reader-example">💥 DEMO 💥</a>
</p>

## Read a PDF just with JS (no native libs needed)

## Limitations

- **Display file only on full screen.**
- **Embeded images binary are not display (yet) in Android**

[PRs are welcome...](https://github.com/xcarpentier/rn-pdf-reader-js/pulls)

## Example

```javascript
import React from 'react'
import { StyleSheet, View } from 'react-native'
import PDFReader from 'rn-pdf-reader-js'
import Constants from 'expo-constants'

export default class App extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <PDFReader
          source={{
            uri: 'http://gahp.net/wp-content/uploads/2017/09/sample.pdf',
          }}
        />
      </View>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop: Constants.statusBarHeight,
    backgroundColor: '#ecf0f1',
  },
})
```

## Props

- source: `Object`
  - uri?: `string` - can be local or served on the web (ie. start withs `https://` or `file://`)
  - base64?: `string` - should start with `data:application/pdf;base64,`. A base64 encoded pdf file tends to start with `JVBERi0xL` so your complete string should look soemthing like this: `data:application/pdf;base64,JVBERi0xL...`
- style: `object` - style props to override default container style
- webviewStyle: `object` - style props to override default WebView style
- onLoad: `func` - callback that runs after WebView is loaded
- noLoader: `boolean` - show/hide the ActivityIndicator. Default is false

## Requirements

- Use it into Expo app (from expo client, Standalone app or ExpoKit app).
- Because we need to have access to `Expo.FileSystem`
- Only React-Native 0.54+ support, Expo SDK 27

## Features

- **For Android, use react-pdf / pdfjs in the webview**
- For iOS devices, display file directly to the WebView

## What rn-pdf-reader-js use?

- react-pdf (pdf.js)
- WebView
- Expo FileSystem API
- Base64

## FAQ

- [Why the component doesn't render PDF?](https://github.com/xcarpentier/rn-pdf-reader-js/issues/15#issuecomment-397306743)

## Hire an expert!

Looking for a ReactNative freelance expert with more than 12 years experience? Contact me from my [website](https://xaviercarpentier.com)!
npm package: @pachun/simple-expo-update
Description: Simpler expo-updates
Latest version: 1.0.11

[![npm version](https://img.shields.io/npm/v/@pachun/simple-expo-update.svg)](https://www.npmjs.com/package/@pachun/simple-expo-update)
[![cov](https://pachun.github.io/simple-expo-update/badges/coverage.svg)](https://github.com/pachun/simple-expo-update/actions)

# Simple Expo Update

```
yarn add @pachun/react-native-use-app-lifecycle
yarn add @pachun/simple-expo-update
```

```ts
import useAppLifecycle from "@pachun/react-native-use-app-lifecycle"
import simpleExpoUpdate from "@pachun/simple-expo-update"

const askPermissionToApplyUpdate = async (
  applyUpdateAndRestart: () => Promise<void>,
) => {
  Alert.alert(
    "An app update is available",
    "May we restart the app to apply the update?",
    [
      {
        text: "No",
        style: "cancel",
      },
      {
        text: "Yes",
        onPress: async () => {
          await applyUpdateAndRestart()
        },
      },
    ],
  )
}

const App = () => {
  useAppLifecycle({
    onLaunch: () =>
      simpleExpoUpdate({ whenPresent: "applyUpdate" }),
    onFocus: () =>
      simpleExpoUpdate({ whenPresent: askPermissionToApplyUpdate }),
  })
  return <></>
}
```

`"applyUpdate"` applies the update immediately, restarting the app.

You can also pass a function to `whenPresent` which accepts an argument that's an async function that you can run to apply the update on your own terms.

## Jest

```
"jest": {
  "setupFilesAfterEnv": ["<rootDir>/node_modules/@pachun/simple-expo-update/tests/jest.setup.ts"]
}
```

## Contributing

PRs are exciting 🤟 Bump the version number in `package.json` and open one.

- Please do not submit AI generated pull requests.
- Please keep coverage at or above where it is when you clone the repo (`yarn test --collectCoverage`).
npm package: @pachun/use-expo-push-notifications
Description: Simpler (and more testable) expo-notifications event handling
Latest version: 0.0.18

[![npm version](https://img.shields.io/npm/v/@pachun/use-expo-push-notifications.svg)](https://www.npmjs.com/package/@pachun/use-expo-push-notifications)

# useExpoPushNotifications

```
yarn add @pachun/use-expo-push-notifications
```

```ts
import React from "react"
import * as Notifications from "expo-notifications"
import useExpoPushNotifications from "@pachun/use-expo-push-notifications"

const App = () => {
  useExpoPushNotifications({
    onNotificationReceived: React.useCallback(
      (notification: Notifications.Notification) => {
        console.log(
          "Notification received",
          JSON.stringify(notification, null, 2),
        )
      },
      [],
    ),
    onNotificationInteraction: React.useCallback(
      (notificationResponse: Notifications.NotificationResponse) => {
        console.log(
          "Notification interaction",
          JSON.stringify(notificationResponse, null, 2),
        )
      },
      [],
    ),
  })

  return <></>
}
```

## Motivation

When you want to test the behavior of your app rather than [useEffect and useRef implementations](https://github.com/pachun/use-expo-push-notifications/blob/main/src/index.ts), this can be helpful.

```typescript
import { renderRouter, screen, waitFor } from "expo-router/testing-library"
import expoPushNotificationsSimulator from "tests/helpers/expo-push-notifications-simulator"

jest.mock("@pachun/use-expo-push-notifications", () => ({
  __esModule: true,
  default: jest.fn(),
}))

describe("receiving push notifications", () => {
  it("displays text received in notifications", async () => {
    // capture your notification handler before you render
    let sendNotification
    jest
      .mocked(useExpoPushNotifications)
      .mockImplementation(({ onNotificationReceived }) => {
        sendNotification = onNotificationReceived
      })

    renderRouter("src/app", { initialUrl: "/" })

    // call your actual notification handler
    sendNotification!({
      request: {
        content: {
          data: {
            text_received_in_notifications: "Hello, world!",
          },
        },
      },
    })

    await waitFor(async () => {
      expect(screen.getByText("Hello, world!")).toBeTruthy()
    })
  })
})
```

This will allow you to test the actual behavior of your app when receiving notifications.

You can test how it will handle receiving notifications on different screens by rendering the router at different routes.

You can do the same for testing notification interactions, like tapping a notification, or long pressing one to bring up the notification actions menu.

You can log the interaction if you don't know what it will look like in your handler, and then write a test for that format of message and what you'd like to happen when it's received.

## Contributing

PRs are exciting 🤟 Bump the version number in `package.json` and open one.

- Please do not submit AI generated pull requests.
- Please keep coverage at or above where it is when you clone the repo (`yarn test --collectCoverage`).