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

@dactaiit/consent-cmp-react

v0.1.5

Published

React component để tải config consent từ API và gửi data-consent lên CMP server, có validator bắt buộc và custom CSS.

Readme

@dactaiit/consent-cmp-react

React component để:

  1. Tải cấu hình từ Config API và render checkbox + text mô tả.
  2. Khi tick/bỏ tick → tự động gọi CMP API gửi data-consent lên server.
  3. Validator giống captcha: bắt buộc tick các mục required mới submit được.
  4. Custom CSS linh hoạt: CSS variables, classNames từng phần tử, hoặc unstyled.

⚠️ Giả định về API (chưa được xác minh — chỉnh cho khớp backend của bạn): Các shape ConsentConfig / ConsentPayload dưới đây là đề xuất mặc định. Nếu backend dùng shape khác, sửa src/types.ts hoặc map dữ liệu trước khi truyền vào.

Cài đặt

npm install @dactaiit/consent-cmp-react

reactreact-dom (>= 17) là peer dependencies.

Dùng nhanh

import { ConsentInput } from '@dactaiit/consent-cmp-react';
import '@dactaiit/consent-cmp-react/styles.css'; // bỏ dòng này nếu tự style

export default function App() {
  return (
    <ConsentInput
      configApiUrl="https://api.example.com/consent/config"
      cmpApiUrl="https://api.example.com/cmp/data-consent"
      apiHeaders={{ Authorization: 'Bearer ...' }}
      metadata={{ userId: 'u_123', page: window.location.href }}
      onSubmit={(payload) => console.log('submitted', payload)}
      onError={(err) => console.error(err)}
    />
  );
}

Shape API (mặc định)

Config APIGET configApiUrl → trả về:

{
  "title": "Đồng ý xử lý dữ liệu",
  "submitLabel": "Đồng ý & Tiếp tục",
  "items": [
    {
      "id": "marketing",
      "label": "Nhận email marketing",
      "description": "Chúng tôi gửi ưu đãi theo định kỳ.",
      "required": false
    },
    {
      "id": "terms",
      "label": "Tôi đồng ý với Điều khoản dịch vụ",
      "required": true
    }
  ]
}

CMP APIPOST cmpApiUrl với body:

{
  "consents": [{ "id": "terms", "granted": true }],
  "timestamp": "2026-06-17T07:50:00.000Z",
  "metadata": { "userId": "u_123" }
}
  • Khi sendOnToggle (mặc định true): mỗi lần tick gửi 1 item.
  • Khi bấm submit: gửi toàn bộ trạng thái hiện tại.

Props chính

| Prop | Kiểu | Mặc định | Mô tả | |---|---|---|---| | configApiUrl | string | — | URL Config API (bắt buộc) | | cmpApiUrl | string | — | URL CMP API (bắt buộc) | | apiHeaders | Record<string,string> | — | Header cho cả 2 API (nên memo hóa) | | metadata | Record<string,unknown> | — | Đính kèm mỗi payload | | sendOnToggle | boolean | true | Gửi ngay mỗi lần tick | | onSubmit | (payload) => void | — | Sau khi submit thành công | | onChange | (state) => void | — | Khi đổi trạng thái checkbox | | onError | (error) => void | — | Khi API lỗi | | classNames | ConsentInputClassNames | — | Class cho từng phần tử | | style | CSSProperties | — | Style root (tiện set CSS vars) | | unstyled | boolean | false | Bỏ toàn bộ style mặc định | | validationMessage | string | (mặc định tiếng Việt) | Thông báo khi thiếu mục bắt buộc |

Custom CSS — 3 cách

1) CSS variables (ghi đè nhanh màu/spacing):

<ConsentInput
  style={{ ['--cmp-accent' as any]: '#16a34a', ['--cmp-radius' as any]: '4px' }}
  /* ... */
/>

Biến hỗ trợ: --cmp-accent, --cmp-text, --cmp-muted, --cmp-error, --cmp-border, --cmp-radius, --cmp-gap, --cmp-font-size.

2) classNames (gắn class riêng, dùng được với Tailwind/CSS Modules):

<ConsentInput
  classNames={{
    root: 'my-consent',
    submit: 'btn btn-primary',
    checkbox: 'my-checkbox',
  }}
  /* ... */
/>

3) unstyled (headless — tự viết 100% CSS):

<ConsentInput unstyled classNames={{ /* class của bạn */ }} /* ... */ />

Validator (cơ chế "captcha")

Mục có required: true phải được tick thì nút submit mới bật. Khi người dùng bấm submit lúc chưa đủ điều kiện, validationMessage hiển thị. Bạn cũng có thể tự kiểm tra qua onChange.

Dùng từng phần (nâng cao)

import { useConsentConfig, sendConsent, ConsentApiError } from '@dactaiit/consent-cmp-react';

useConsentConfig(url, options){ config, loading, error }. sendConsent(url, payload, options) → gửi thủ công, ném ConsentApiError khi lỗi.

Mock CMP API (giả lập backend)

Module mock-cmp/ mô phỏng hệ thống CMP: phục vụ config xuống clientlưu data-consent gửi lên.

Dữ liệu persist tại mock-cmp/.data/database.json (config, events, subjects, logs).

Chạy standalone

npm install
npm run mock:cmp
# → http://localhost:3100

Chạy kèm demo (Vite middleware — dùng chung store file)

npm run demo:dev
# → http://localhost:5173

Endpoints

| Method | Path | Mô tả | |---|---|---| | GET | /api/consent/config | Trả config checkbox (ConsentConfig) | | PUT | /api/consent/config | Cập nhật config (body = ConsentConfig) | | POST | /api/consent/config/reset | Reset config về mặc định | | POST | /api/cmp/data-consent | Lưu consent payload, merge snapshot theo subject | | GET | /api/cmp/data-consent | Danh sách event đã lưu (?subjectKey= lọc) | | DELETE | /api/cmp/data-consent | Xóa toàn bộ events + subjects | | GET | /api/cmp/subjects | Snapshot consent mới nhất theo subject | | GET | /api/cmp/stats | Thống kê store | | GET | /api/cmp/health | Health check | | GET | /api/demo/logs | Log request (debug) | | DELETE | /api/demo/logs | Xóa log | | POST | /api/register | Giả lập đăng ký (demo form) |

Subject key (gom consent theo người dùng): ưu tiên metadata.userIdmetadata.emailmetadata.formanonymous.

POST /api/cmp/data-consent — body:

{
  "consents": [{ "id": "terms", "granted": true }],
  "timestamp": "2026-06-17T08:00:00.000Z",
  "metadata": { "email": "[email protected]", "form": "register-demo" }
}

Response 201:

{
  "ok": true,
  "eventId": "evt_...",
  "subjectKey": "email:[email protected]",
  "snapshot": {
    "subjectKey": "email:[email protected]",
    "consents": { "terms": true },
    "updatedAt": "...",
    "lastEventId": "evt_..."
  }
}

Build

npm install
npm run build     # xuất ESM + CJS + .d.ts + styles.css vào dist/
npm run typecheck