notiqjs 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Andrés Rengifo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,188 @@
1
+ <div align="center">
2
+ <h1>Notiq</h1>
3
+ <p><strong>A sub-2kb, framework-agnostic toast notification library.</strong></p>
4
+
5
+ <p>
6
+ <img alt="npm package size" src="https://img.shields.io/badge/size-%3C%202kb%20(gzip)-success?style=for-the-badge">
7
+ <img alt="Dependencies" src="https://img.shields.io/badge/dependencies-0-blue?style=for-the-badge">
8
+ <img alt="A11y" src="https://img.shields.io/badge/A11y-Supported-blueviolet?style=for-the-badge">
9
+ </p>
10
+ </div>
11
+
12
+ <br>
13
+
14
+ Notiq is a microscopic, highly optimized toast notification library written in pure TypeScript. It has zero dependencies, operates entirely on the DOM, and integrates seamlessly into any frontend environment without the need for wrappers or providers.
15
+
16
+ ## Features
17
+
18
+ - **Microscopic Size:** < 2kb minified + gzipped.
19
+ - **Zero Dependencies:** Pure Vanilla JS/TS under the hood.
20
+ - **Framework Agnostic:** Works beautifully in React, Vue, Svelte, Astro, or plain HTML.
21
+ - **SSR Safe:** Safely executed in server-rendered frameworks (Next.js, Nuxt, Astro).
22
+ - **Accessible:** Automatic `aria-live` regions for screen readers.
23
+ - **XSS Secure:** Uses `textContent` to prevent script injections.
24
+ - **Smooth Animations:** Hardware-accelerated sliding and scaling transitions.
25
+
26
+ ## Installation
27
+
28
+ ```bash
29
+ # npm
30
+ npm install notiqjs
31
+
32
+ # yarn
33
+ yarn add notiqjs
34
+
35
+ # pnpm
36
+ pnpm add notiqjs
37
+
38
+ # bun
39
+ bun add notiqjs
40
+ ```
41
+
42
+ ## Quick Start
43
+
44
+ Import the class and call a static method. No context providers or root components required.
45
+
46
+ ```ts
47
+ import { Notiq } from 'notiqjs';
48
+
49
+ // Basic usage
50
+ Notiq.success('Payment processed successfully');
51
+
52
+ // With description and custom position
53
+ Notiq.error({
54
+ message: 'Connection Timeout',
55
+ description: 'Please check your internet connection and try again.',
56
+ position: 'top-center'
57
+ });
58
+ ```
59
+
60
+ ---
61
+
62
+ ## Framework Integration
63
+
64
+ Because Notiq does not rely on a Virtual DOM, it can be called directly from component logic, event handlers, or even external services (like Axios interceptors).
65
+
66
+ ### React / Next.js
67
+ ```tsx
68
+ import { Notiq } from 'notiqjs';
69
+
70
+ export default function Checkout() {
71
+ const handlePayment = () => {
72
+ Notiq.success({
73
+ message: 'Order placed!',
74
+ description: 'Receipt sent to your email.'
75
+ });
76
+ };
77
+
78
+ return <button onClick={handlePayment}>Pay Now</button>;
79
+ }
80
+ ```
81
+
82
+ ### Angular
83
+ ```typescript
84
+ import { Component } from '@angular/core';
85
+ import { Notiq } from 'notiqjs';
86
+
87
+ @Component({
88
+ selector: 'app-checkout',
89
+ template: `<button (click)="handlePayment()">Pay Now</button>`
90
+ })
91
+ export class CheckoutComponent {
92
+ handlePayment() {
93
+ Notiq.success({
94
+ message: 'Order placed!',
95
+ description: 'Receipt sent to your email.'
96
+ });
97
+ }
98
+ }
99
+ ```
100
+
101
+ ### Astro
102
+ In Astro, client-side code runs inside standard `<script>` tags.
103
+
104
+ ```astro
105
+ ---
106
+ // src/components/NotifyButton.astro
107
+ ---
108
+ <button id="notify-btn">Launch Toast</button>
109
+
110
+ <script>
111
+ import { Notiq } from 'notiqjs';
112
+
113
+ document.getElementById('notify-btn')?.addEventListener('click', () => {
114
+ Notiq.success('Hello from Astro!');
115
+ });
116
+ </script>
117
+ ```
118
+
119
+ ---
120
+
121
+ ## Customization
122
+
123
+ Notiq is designed to be fully customizable without fighting inline styles.
124
+
125
+ ### 1. Global CSS Overrides
126
+ Every toast automatically receives the `notiq` CSS class. Target this in your global stylesheet to override defaults (like `border-radius`, `font-family`, etc.) across your entire application.
127
+
128
+ ```css
129
+ /* global.css */
130
+ .notiq {
131
+ border-radius: 12px;
132
+ border: 1px solid rgba(255, 255, 255, 0.1);
133
+ backdrop-filter: blur(8px);
134
+ }
135
+ ```
136
+
137
+ ### 2. Utility Classes (Tailwind CSS)
138
+ Pass specific utility classes directly to individual toasts using the `className` property.
139
+
140
+ ```ts
141
+ Notiq.info({
142
+ message: 'Update available',
143
+ className: 'border-2 border-blue-500 shadow-xl'
144
+ });
145
+ ```
146
+
147
+ ### 3. Custom Icons & Colors
148
+ You can inject any raw HTML into the `icon` property (perfect for SVGs or Iconify) and pass any valid CSS `background` value to `color`.
149
+
150
+ ```ts
151
+ Notiq.custom({
152
+ message: 'Premium Unlocked',
153
+ color: 'linear-gradient(135deg, #6366f1 0%, #a855f7 100%)',
154
+ icon: '<svg>...</svg>', /* Your custom SVG string */
155
+ textColor: '#ffffff'
156
+ });
157
+ ```
158
+
159
+ ---
160
+
161
+ ## API Reference
162
+
163
+ ### Methods
164
+ - `Notiq.success(options)`
165
+ - `Notiq.error(options)`
166
+ - `Notiq.warning(options)`
167
+ - `Notiq.info(options)`
168
+ - `Notiq.custom(options)`
169
+
170
+ ### `NotiqOptions`
171
+
172
+ | Property | Type | Default | Description |
173
+ | :--- | :--- | :--- | :--- |
174
+ | `message` | `string` | **Required** | The main text of the notification. |
175
+ | `description` | `string` | `undefined` | Secondary text displayed below the message. |
176
+ | `position` | `string` | `bottom-right` | `top-right`, `top-left`, `top-center`, `bottom-right`, `bottom-left`, `bottom-center`. |
177
+ | `duration` | `number` | `3000` | Time in milliseconds before the toast auto-dismisses. |
178
+ | `icon` | `string \| false` | *(Default icon)* | Custom SVG/HTML string, or `false` to hide. |
179
+ | `dismiss` | `boolean` | `true` | If true, clicking the toast will close it immediately. |
180
+ | `color` | `string` | *(Theme default)* | Background color. Accepts hex, rgb, or CSS gradients. |
181
+ | `textColor` | `string` | `#fff` | Override the text color. |
182
+ | `className` | `string` | `undefined` | Inject custom CSS classes (e.g. Tailwind). |
183
+
184
+ ---
185
+
186
+ ## License
187
+
188
+ Notiq is under [MIT license](https://opensource.org/license/mit)
@@ -0,0 +1,48 @@
1
+ //#region src/ntiq.ts
2
+ var e = {
3
+ success: ["<path d=\"M20 6L9 17l-5-5\"/>", "#10b981"],
4
+ error: ["<path d=\"M18 6L6 18M6 6l12 12\"/>", "#ef4444"],
5
+ info: ["<path d=\"M12 8h0M12 12v4\"/>", "#3b82f6"],
6
+ warning: ["<path d=\"M12 9v4M12 17h0M10.3 4L2 18h20L13.7 4a2 2 0 0 0-3.4 0z\"/>", "#f59e0b"]
7
+ }, t = !1;
8
+ function n() {
9
+ t || typeof document > "u" || (t = !0, document.head.insertAdjacentHTML("afterbegin", "<style>\n .nq-c{position:fixed;display:flex;flex-direction:column;gap:12px;z-index:9999;pointer-events:none}\n .nq-tr,.nq-br{right:20px;align-items:flex-end}\n .nq-tl,.nq-bl{left:20px;align-items:flex-start}\n .nq-tc,.nq-bc{left:50%;transform:translateX(-50%);align-items:center}\n .nq-tr,.nq-tl,.nq-tc{top:20px}\n .nq-br,.nq-bl,.nq-bc{bottom:20px}\n .nq-t{max-width:600px;pointer-events:auto;position:relative;overflow:hidden;padding:12px 16px;border-radius:8px;color:#fff;font:500 14px/1.4 system-ui,sans-serif;box-shadow:0 4px 12px rgba(0,0,0,.15);display:flex;align-items:flex-start;gap:10px;opacity:0;transition:opacity .3s,transform .3s cubic-bezier(.175,.885,.32,1.27)}\n .nq-s{opacity:1!important;transform:none!important}\n .nq-i{flex-shrink:0;margin-top:1px}\n .nq-i svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}\n .nq-p{position:absolute;bottom:0;left:0;height:3px;background:rgba(255,255,255,.35);animation:nq-p linear forwards}\n @keyframes nq-p{from{width:100%}to{width:0}}\n @media(max-width:480px){.nq-c{left:12px!important;right:12px!important;transform:none!important;align-items:stretch!important}}\n </style>"));
10
+ }
11
+ function r(t, r) {
12
+ if (typeof window > "u") return;
13
+ n();
14
+ let i = typeof t == "string" ? { message: t } : t, a = i.type ?? r, o = i.position ?? "bottom-right", s = i.duration ?? 3e3, c = o.split("-").map((e) => e[0]).join(""), [l, u] = e[a], d = document.querySelector(`.nq-${c}`);
15
+ d ||= (document.body.insertAdjacentHTML("beforeend", `<div class="nq-c nq-${c}"></div>`), document.querySelector(`.nq-${c}`));
16
+ let f = document.createElement("div");
17
+ if (f.className = [
18
+ "ntiq",
19
+ "nq-t",
20
+ i.className
21
+ ].filter(Boolean).join(" "), f.setAttribute("role", "alert"), f.setAttribute("aria-live", a === "error" || a === "warning" ? "assertive" : "polite"), f.style.cssText = `background:${i.color ?? u};transform:translateY(${o[0] === "t" ? "-" : ""}16px) scale(.95)`, i.textColor && (f.style.color = i.textColor), i.icon !== !1) {
22
+ let e = document.createElement("span");
23
+ e.className = "nq-i", e.innerHTML = i.icon ?? `<svg viewBox="0 0 24 24">${l}</svg>`, f.appendChild(e);
24
+ }
25
+ let p = document.createElement("div");
26
+ p.style.flexGrow = "1";
27
+ let m = document.createElement("div");
28
+ if (m.textContent = i.message, i.description && (m.style.fontWeight = "600"), p.appendChild(m), i.description) {
29
+ let e = document.createElement("div");
30
+ e.textContent = i.description, e.style.cssText = "font-size:.875em;opacity:.85;margin-top:3px", p.appendChild(e);
31
+ }
32
+ f.appendChild(p), f.insertAdjacentHTML("beforeend", `<div class="nq-p" style="animation-duration:${s}ms"></div>`), o[0] === "t" ? d.prepend(f) : d.appendChild(f), f.offsetHeight, f.classList.add("nq-s");
33
+ let h = () => {
34
+ f.classList.remove("nq-s"), f.addEventListener("transitionend", () => {
35
+ f.remove(), d.childElementCount || d.remove();
36
+ }, { once: !0 });
37
+ };
38
+ i.dismiss !== !1 && (f.onclick = h), setTimeout(h, s);
39
+ }
40
+ var i = class {
41
+ static success = (e) => r(e, "success");
42
+ static error = (e) => r(e, "error");
43
+ static info = (e) => r(e, "info");
44
+ static warning = (e) => r(e, "warning");
45
+ static custom = (e) => r(e, "info");
46
+ };
47
+ //#endregion
48
+ export { i as Ntiq };
@@ -0,0 +1,15 @@
1
+ (function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports):typeof define==`function`&&define.amd?define([`exports`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.Ntiq={}))})(this,function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var t={success:[`<path d="M20 6L9 17l-5-5"/>`,`#10b981`],error:[`<path d="M18 6L6 18M6 6l12 12"/>`,`#ef4444`],info:[`<path d="M12 8h0M12 12v4"/>`,`#3b82f6`],warning:[`<path d="M12 9v4M12 17h0M10.3 4L2 18h20L13.7 4a2 2 0 0 0-3.4 0z"/>`,`#f59e0b`]},n=!1;function r(){n||typeof document>`u`||(n=!0,document.head.insertAdjacentHTML(`afterbegin`,`<style>
2
+ .nq-c{position:fixed;display:flex;flex-direction:column;gap:12px;z-index:9999;pointer-events:none}
3
+ .nq-tr,.nq-br{right:20px;align-items:flex-end}
4
+ .nq-tl,.nq-bl{left:20px;align-items:flex-start}
5
+ .nq-tc,.nq-bc{left:50%;transform:translateX(-50%);align-items:center}
6
+ .nq-tr,.nq-tl,.nq-tc{top:20px}
7
+ .nq-br,.nq-bl,.nq-bc{bottom:20px}
8
+ .nq-t{max-width:600px;pointer-events:auto;position:relative;overflow:hidden;padding:12px 16px;border-radius:8px;color:#fff;font:500 14px/1.4 system-ui,sans-serif;box-shadow:0 4px 12px rgba(0,0,0,.15);display:flex;align-items:flex-start;gap:10px;opacity:0;transition:opacity .3s,transform .3s cubic-bezier(.175,.885,.32,1.27)}
9
+ .nq-s{opacity:1!important;transform:none!important}
10
+ .nq-i{flex-shrink:0;margin-top:1px}
11
+ .nq-i svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
12
+ .nq-p{position:absolute;bottom:0;left:0;height:3px;background:rgba(255,255,255,.35);animation:nq-p linear forwards}
13
+ @keyframes nq-p{from{width:100%}to{width:0}}
14
+ @media(max-width:480px){.nq-c{left:12px!important;right:12px!important;transform:none!important;align-items:stretch!important}}
15
+ </style>`))}function i(e,n){if(typeof window>`u`)return;r();let i=typeof e==`string`?{message:e}:e,a=i.type??n,o=i.position??`bottom-right`,s=i.duration??3e3,c=o.split(`-`).map(e=>e[0]).join(``),[l,u]=t[a],d=document.querySelector(`.nq-${c}`);d||=(document.body.insertAdjacentHTML(`beforeend`,`<div class="nq-c nq-${c}"></div>`),document.querySelector(`.nq-${c}`));let f=document.createElement(`div`);if(f.className=[`ntiq`,`nq-t`,i.className].filter(Boolean).join(` `),f.setAttribute(`role`,`alert`),f.setAttribute(`aria-live`,a===`error`||a===`warning`?`assertive`:`polite`),f.style.cssText=`background:${i.color??u};transform:translateY(${o[0]===`t`?`-`:``}16px) scale(.95)`,i.textColor&&(f.style.color=i.textColor),i.icon!==!1){let e=document.createElement(`span`);e.className=`nq-i`,e.innerHTML=i.icon??`<svg viewBox="0 0 24 24">${l}</svg>`,f.appendChild(e)}let p=document.createElement(`div`);p.style.flexGrow=`1`;let m=document.createElement(`div`);if(m.textContent=i.message,i.description&&(m.style.fontWeight=`600`),p.appendChild(m),i.description){let e=document.createElement(`div`);e.textContent=i.description,e.style.cssText=`font-size:.875em;opacity:.85;margin-top:3px`,p.appendChild(e)}f.appendChild(p),f.insertAdjacentHTML(`beforeend`,`<div class="nq-p" style="animation-duration:${s}ms"></div>`),o[0]===`t`?d.prepend(f):d.appendChild(f),f.offsetHeight,f.classList.add(`nq-s`);let h=()=>{f.classList.remove(`nq-s`),f.addEventListener(`transitionend`,()=>{f.remove(),d.childElementCount||d.remove()},{once:!0})};i.dismiss!==!1&&(f.onclick=h),setTimeout(h,s)}e.Ntiq=class{static success=e=>i(e,`success`);static error=e=>i(e,`error`);static info=e=>i(e,`info`);static warning=e=>i(e,`warning`);static custom=e=>i(e,`info`)}});
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,19 @@
1
+ export interface NtiqOptions {
2
+ message: string;
3
+ description?: string;
4
+ type?: 'success' | 'error' | 'info' | 'warning';
5
+ position?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' | 'top-center' | 'bottom-center';
6
+ duration?: number;
7
+ icon?: string | false;
8
+ dismiss?: boolean;
9
+ color?: string;
10
+ textColor?: string;
11
+ className?: string;
12
+ }
13
+ export declare class Ntiq {
14
+ static success: (o: string | NtiqOptions) => void;
15
+ static error: (o: string | NtiqOptions) => void;
16
+ static info: (o: string | NtiqOptions) => void;
17
+ static warning: (o: string | NtiqOptions) => void;
18
+ static custom: (o: NtiqOptions) => void;
19
+ }
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "notiqjs",
3
+ "version": "1.0.0",
4
+ "description": "The sub-2kb, framework-agnostic, toast notification library.",
5
+ "type": "module",
6
+ "main": "./dist/notiq.umd.js",
7
+ "module": "./dist/notiq.es.js",
8
+ "types": "./dist/notiq.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/notiq.es.js",
12
+ "require": "./dist/notiq.umd.js",
13
+ "types": "./dist/notiq.d.ts"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "README.md"
19
+ ],
20
+ "keywords": [
21
+ "toast",
22
+ "notification",
23
+ "alert",
24
+ "framework-agnostic",
25
+ "vanilla",
26
+ "typescript"
27
+ ],
28
+ "author": "Andrés Rengifo <andresm.rengifo@gmail.com>",
29
+ "license": "MIT",
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "https://github.com/afmosquerare/notiq"
33
+ },
34
+ "scripts": {
35
+ "dev": "vite",
36
+ "build": "vite build",
37
+ "preview": "vite preview"
38
+ },
39
+ "devDependencies": {
40
+ "typescript": "~6.0.2",
41
+ "vite": "^8.0.12",
42
+ "vite-plugin-dts": "^5.0.1"
43
+ }
44
+ }