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

notary-calculator

v1.0.4

Published

Bulgarian notary fee calculator React component for real estate transactions (Тарифа за нотариалните такси към ЗННД)

Readme

notary-calculator

npm version npm downloads CI License: MIT

🇧🇬 Bulgaria-only. A React component that calculates notary fees, local transfer tax, and land-registry fees when buying real estate in Bulgaria.

Live demo → vladi160.github.io/notary-calculator


Why Bulgaria-only?

The fee calculation is governed by the Тарифа за нотариалните такси към Закона за нотариусите и нотариалната дейност (ЗННД) — a tier-based schedule defined in Bulgarian law, denominated in BGN, and capped at 6 000 BGN. The local transfer tax (Местен данък) and land-registry fee (Агенция по Вписванията) are also specific to the Bulgarian legal and fiscal system.

This component is not applicable in other jurisdictions.


Installation

npm install notary-calculator
# or
yarn add notary-calculator
# or
pnpm add notary-calculator

Peer dependencies (install separately if not already present):

npm install react react-dom

Quick start

import { NotaryCalculator } from "notary-calculator";

export default function MyPage() {
  return <NotaryCalculator defaultPrice={150_000} />;
}

No styles are applied by default. The component renders clean HTML — style it however you like (see Styling below).


Props

| Prop | Type | Default | Description | |---|---|---|---| | defaultPrice | number | 100000 | Initial price shown in the input (in the currency determined by levaToCourse). | | dictionary | Partial<Dictionary> | Bulgarian labels | Override any or all UI labels. Omitted keys fall back to built-in Bulgarian text. | | config | Partial<Config> | Standard BG rates | Override fee percentages or the EUR→BGN exchange rate. | | classNames | ClassNames | {} | CSS class names injected into individual elements. No classes are applied by default. | | onPriceChange | (price: number) => void | — | Callback fired whenever the user updates the price input. | | locale | string | "bg-BG" | BCP 47 locale tag used for toLocaleString number formatting (e.g. "de-DE", "en-US"). |


Dictionary — UI labels

type Dictionary = {
  title: string;               // "Калкулатор за нотариални такси"
  explanation1: string;        // note above the form
  explanation2: string;        // note below the results
  taxAssessmentNote: string;   // tax-assessment warning note
  calculateAllCosts: string;   // label for the price input
  localTaxes: string;          // "Местен данък (прехвърляне)"
  registrationFee: string;     // "Такса вписване (Агенция по Вписванията)"
  notaryFees: string;          // "Нотариална такса (без ДДС)"
  notaryVat: string;           // "ДДС върху нотариалната такса (20%)"
  totalCosts: string;          // "Общо разходи"
  currency: string;            // "лв."
};

Config — fee parameters

type Config = {
  /**
   * Exchange rate: units of the input price per 1 BGN.
   * 1   → price already in BGN (default)
   * 1.95583 → price in EUR (fixed EUR/BGN peg)
   */
  levaToCourse: number;   // default: 1

  /**
   * Land-registry fee — Агенция по Вписванията (% of price).
   * default: 0.1  (= 0.1%)
   */
  regFeePercent: number;

  /**
   * Local transfer tax — Местен данък (% of price).
   * default: 2  (= 2%)
   */
  taxesFeePercent: number;
};

ClassNames — element-level class injection

Every rendered element can receive a CSS class name. No classes are applied by default.

type ClassNames = {
  container?: string;      // outermost <div>
  title?: string;          // <h3> heading
  note?: string;           // explanation <p> elements
  form?: string;           // form wrapper <div>
  inputRow?: string;       // price-input row <div>
  inputLabel?: string;     // <label> for price input
  inputWrapper?: string;   // <div> wrapping input + currency
  input?: string;          // <input>
  currency?: string;       // currency <span> next to input
  row?: string;            // each fee row <div>
  label?: string;          // fee label <span>
  value?: string;          // fee value <span>
  resultRow?: string;      // total row <div>
  resultLabel?: string;    // total label <span>
  resultValue?: string;    // total value <span>
};

Styling

The component ships with zero CSS. You have three options:

Option A — classNames prop (recommended)

Pass your own class names to every rendered element:

<NotaryCalculator
  classNames={{
    container: "my-calc",
    title: "my-calc__title",
    row: "my-calc__row",
    label: "my-calc__label",
    value: "my-calc__value",
    resultRow: "my-calc__row my-calc__row--total",
    resultValue: "my-calc__total-value",
    // ...
  }}
/>

Works with Tailwind CSS, CSS Modules, plain CSS classes — anything.

Option B — data-nc-* attribute selectors

Every element has a data-nc-* attribute you can target in plain CSS without touching props:

[data-nc-container] { font-family: sans-serif; }
[data-nc-title]     { font-size: 1.2rem; color: navy; }
[data-nc-input]     { border: 1px solid #ccc; padding: 4px 8px; }
[data-nc-result-row]{ background: #eef; font-weight: bold; }

Available attributes: data-nc-container, data-nc-title, data-nc-note, data-nc-form, data-nc-row, data-nc-input-row, data-nc-fee-row, data-nc-result-row, data-nc-input, data-nc-input-label, data-nc-input-wrapper, data-nc-currency, data-nc-label, data-nc-value, data-nc-result-label, data-nc-result-value.

Option C — Tailwind CSS

<NotaryCalculator
  classNames={{
    container: "rounded-lg border p-6 shadow-sm",
    title: "text-lg font-semibold text-blue-700 mb-3",
    form: "flex flex-col gap-2",
    row: "flex justify-between items-center py-1 border-b",
    label: "text-gray-600 text-sm",
    value: "font-medium",
    resultRow: "flex justify-between items-center py-2 bg-blue-50 rounded px-2 mt-1",
    resultLabel: "font-bold text-blue-800",
    resultValue: "font-bold text-blue-800 text-lg",
    input: "w-32 text-right border rounded px-2 py-1",
    inputRow: "flex justify-between items-center mb-2 border-b-2 pb-2",
  }}
/>

Usage examples

Prices in EUR (with fixed EUR/BGN peg)

The notary fee tiers are defined in BGN. Set levaToCourse to 1.95583 and the component automatically converts to/from BGN for the tier calculation.

<NotaryCalculator
  defaultPrice={65_999}
  config={{ levaToCourse: 1.96, taxesFeePercent: 3, regFeePercent: 0.1 }}
  dictionary={{ currency: "EUR" }}
/>

English labels

<NotaryCalculator
  dictionary={{
    title: "Bulgarian Notary Fee Calculator",
    calculateAllCosts: "Property price",
    localTaxes: "Local transfer tax",
    registrationFee: "Land Registry fee",
    notaryFees: "Notary fee (excl. VAT)",
    notaryVat: "VAT on notary fee (20%)",
    totalCosts: "Total costs",
    currency: "BGN",
    explanation1: "Estimate your costs when buying property in Bulgaria.",
    explanation2: "Amounts are approximate.",
    taxAssessmentNote:
      "If the tax-assessed value exceeds the contract price, the higher figure is used.",
  }}
/>

With price-change callback

<NotaryCalculator
  defaultPrice={200_000}
  onPriceChange={(price) => console.log("New price:", price)}
/>

Standalone calcNotaryFee utility

The tier-calculation function is exported separately for server-side or non-React use:

import { calcNotaryFee } from "notary-calculator";

const fee = calcNotaryFee(350_000); // → 1230.5 BGN

Next.js (App Router)

The component uses "use client" internally, so it works in Server Components files — no wrapper needed.

// app/property/[id]/page.tsx  — Server Component is fine
import { NotaryCalculator } from "notary-calculator";

export default function PropertyPage({ price }: { price: number }) {
  return <NotaryCalculator defaultPrice={price} />;
}

Fee calculation details

| Fee | Formula | Notes | |---|---|---| | Local transfer tax (Местен данък) | price × taxesFeePercent / 100 | Default 2%. Set by the municipality; most commonly 2–3%. | | Land-registry fee (Агенция по Вписванията) | price × regFeePercent / 100 | Default 0.1%. Fixed by regulation. | | Notary fee (Нотариална такса) | Tier table per ЗННД (see below), capped at 6 000 BGN | Applied to the BGN-equivalent price. | | VAT on notary fee | notaryFee × 0.20 | Applied to the notary fee; currently 20%. |

Notary fee tiers (BGN)

| Price range (BGN) | Marginal rate | |---|---| | up to 100 | flat 30 BGN | | 101 – 1 000 | 1.5% | | 1 001 – 10 000 | 1.3% | | 10 001 – 50 000 | 0.8% | | 50 001 – 100 000 | 0.5% | | 100 001 – 500 000 | 0.2% | | above 500 000 | 0.1% | | cap | 6 000 BGN |


Publishing a new version

  1. Bump the version in package.json.
  2. Commit and tag: git tag v1.x.x && git push --tags.
  3. The publish workflow will run automatically and publish to npm.

Prerequisite: Add your npm token as NPM_TOKEN in the GitHub repository secrets (Settings → Secrets → Actions).


License

MIT © vladi160