@kittler/tailwind-breakpoint-indicator 1.0.3 → 1.1.1
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/README.md +67 -14
- package/dist/index.d.ts +34 -0
- package/dist/index.esm.js +190 -39
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +6 -0
- package/dist/index.umd.js.map +1 -0
- package/dist/styles.css +5 -86
- package/package.json +1 -2
package/README.md
CHANGED
|
@@ -8,10 +8,14 @@ Visual breakpoint indicator tool for Tailwind CSS development. Shows the current
|
|
|
8
8
|
|
|
9
9
|
- 🎨 Visual indicator with color-coded breakpoints
|
|
10
10
|
- 🔄 Automatically detects development mode
|
|
11
|
+
- 📐 Auto-detects breakpoints **(limited functionality)**
|
|
11
12
|
- ⏱️ Hide button with 20-second auto-show timer
|
|
12
13
|
- 🎯 Works with any build tool (Vite, Vue, Webpack, Rollup, etc.)
|
|
13
14
|
- 📦 Zero dependencies
|
|
14
|
-
- 🎛️ Configurable
|
|
15
|
+
- 🎛️ Configurable: customBreakpoints, baseLabel, containerSelector, hideDuration, debug
|
|
16
|
+
|
|
17
|
+
## Compatibility
|
|
18
|
+
Tailwind **v4** is supported and tested. **Tailwind v3 and below have not been officially tested yet.** If you use v3 or older, feedback is welcome.
|
|
15
19
|
|
|
16
20
|
## Installation
|
|
17
21
|
|
|
@@ -67,22 +71,40 @@ initBreakpointHelper()
|
|
|
67
71
|
```typescript
|
|
68
72
|
interface BreakpointHelperOptions {
|
|
69
73
|
/**
|
|
70
|
-
*
|
|
74
|
+
* When true: show the indicator (e.g. in production or when auto-detect would hide it).
|
|
75
|
+
* When false: indicator is not shown; if it was already created (e.g. by auto-init), it is hidden.
|
|
76
|
+
* When not passed: development mode is auto-detected (Vite, NODE_ENV, localhost).
|
|
77
|
+
* Note: With the auto-import (import '...tailwind-breakpoint-indicator'), the helper inits on load.
|
|
78
|
+
* To keep it off in dev, use manual init only and call initBreakpointHelper({ enabled: false }).
|
|
71
79
|
* @default undefined (auto-detect)
|
|
72
80
|
*/
|
|
73
81
|
enabled?: boolean
|
|
74
|
-
|
|
75
82
|
/**
|
|
76
|
-
*
|
|
83
|
+
* How long (ms) to hide the indicator when the hide button is clicked. After that, it shows again.
|
|
77
84
|
* @default 20000 (20 seconds)
|
|
78
85
|
*/
|
|
79
86
|
hideDuration?: number
|
|
80
|
-
|
|
81
87
|
/**
|
|
82
|
-
*
|
|
83
|
-
* @default undefined (creates new element)
|
|
88
|
+
* CSS selector for an existing element to use as the indicator container. If not set, one is created.
|
|
84
89
|
*/
|
|
85
90
|
containerSelector?: string
|
|
91
|
+
/**
|
|
92
|
+
* Custom breakpoints added to the auto-detected set (xs, sm–2xl, 3xl).
|
|
93
|
+
* Required for any other names (4xl, desktop, …). Fallback when CSS detection fails.
|
|
94
|
+
* In Tailwind v3, use for custom screens (xs, 3xl) from theme.extend.screens.
|
|
95
|
+
* @example { xs: '30rem', '3xl': '120rem', desktop: '64rem' }
|
|
96
|
+
*/
|
|
97
|
+
customBreakpoints?: Record<string, string>
|
|
98
|
+
/**
|
|
99
|
+
* Label for the range below the first breakpoint. Use false to hide the base row.
|
|
100
|
+
* @default 'base'
|
|
101
|
+
*/
|
|
102
|
+
baseLabel?: string | false
|
|
103
|
+
/**
|
|
104
|
+
* Enable debug output in console (CSS detection, breakpoints in use).
|
|
105
|
+
* @default false
|
|
106
|
+
*/
|
|
107
|
+
debug?: boolean
|
|
86
108
|
}
|
|
87
109
|
```
|
|
88
110
|
|
|
@@ -98,14 +120,45 @@ You can override this by setting `enabled: true` or `enabled: false` in options.
|
|
|
98
120
|
|
|
99
121
|
## Breakpoints
|
|
100
122
|
|
|
101
|
-
|
|
123
|
+
### Auto-detected breakpoints
|
|
124
|
+
|
|
125
|
+
The tool **automatically recognizes** (from CSS or built-in defaults):
|
|
126
|
+
|
|
127
|
+
- **xs** – custom (when in CSS, e.g. `--breakpoint-xs` / Tailwind v4 @theme)
|
|
128
|
+
- **sm, md, lg, xl, 2xl** – built-in default Tailwind breakpoints
|
|
129
|
+
- **3xl** – custom (when in CSS, e.g. `--breakpoint-3xl`)
|
|
130
|
+
|
|
131
|
+
**Any other names** (4xl, desktop, etc.) **must be defined** via **customBreakpoints**.
|
|
132
|
+
|
|
133
|
+
- **Tailwind v3:** Built-in sm–2xl work with no config. For custom screens (xs, 3xl) from `theme.extend.screens`, pass them as **customBreakpoints**.
|
|
134
|
+
- **Tailwind v4:** Reads from `@theme` when available. If detection fails (e.g. Vue/Vite) or you use extra names, add them with **customBreakpoints**.
|
|
135
|
+
|
|
136
|
+
Values can be in `px`, `rem`, or `em`.
|
|
102
137
|
|
|
103
|
-
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
138
|
+
**customBreakpoints** – Add to the auto-detected set. Use for extra names or as fallback when CSS detection fails:
|
|
139
|
+
|
|
140
|
+
```javascript
|
|
141
|
+
initBreakpointHelper({
|
|
142
|
+
enabled: true,
|
|
143
|
+
customBreakpoints: {
|
|
144
|
+
xs: '30rem', // v3 custom screen
|
|
145
|
+
'3xl': '120rem',
|
|
146
|
+
'4xl': '160rem',
|
|
147
|
+
desktop: '64rem'
|
|
148
|
+
}
|
|
149
|
+
})
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Base row
|
|
153
|
+
|
|
154
|
+
The “base” row is the range below the first breakpoint. You can rename it or hide it:
|
|
155
|
+
|
|
156
|
+
```javascript
|
|
157
|
+
initBreakpointHelper({
|
|
158
|
+
baseLabel: 'default', // show as "default" instead of "base"
|
|
159
|
+
// baseLabel: false, // hide the base row; only breakpoint names are shown
|
|
160
|
+
})
|
|
161
|
+
```
|
|
109
162
|
|
|
110
163
|
## Using Existing HTML Element
|
|
111
164
|
|
package/dist/index.d.ts
CHANGED
|
@@ -14,11 +14,45 @@ export declare interface BreakpointHelperOptions {
|
|
|
14
14
|
* @default undefined (creates new element)
|
|
15
15
|
*/
|
|
16
16
|
containerSelector?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Custom breakpoint names + values added to defaults and CSS detection.
|
|
19
|
+
* Use for extra names (4xl, desktop, …) or as fallback when CSS detection fails (e.g. Vue/Vite).
|
|
20
|
+
* In Tailwind v3, use this for custom screens (xs, 3xl) from theme.extend.screens.
|
|
21
|
+
* @example { xs: '30rem', '3xl': '120rem', desktop: '64rem' }
|
|
22
|
+
*/
|
|
23
|
+
customBreakpoints?: BreakpointsMap;
|
|
24
|
+
/**
|
|
25
|
+
* Label for the "base" range (below first breakpoint). Use string to rename, or false to hide base row.
|
|
26
|
+
* @default 'base'
|
|
27
|
+
*/
|
|
28
|
+
baseLabel?: string | false;
|
|
29
|
+
/**
|
|
30
|
+
* Enable debug output in console.
|
|
31
|
+
* @default false
|
|
32
|
+
*/
|
|
33
|
+
debug?: boolean;
|
|
17
34
|
}
|
|
18
35
|
|
|
36
|
+
/** Breakpoint value in original form (e.g. "40rem", "1280px") */
|
|
37
|
+
export declare type BreakpointsMap = Record<string, string>;
|
|
38
|
+
|
|
39
|
+
/** Names we know to look for in project CSS (--breakpoint-xs etc.). Documented for users. */
|
|
40
|
+
export declare const DETECTABLE_CUSTOM_NAMES: readonly ["xs", "3xl", "4xl"];
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Returns the default breakpoints. Useful for debugging or when building custom options.
|
|
44
|
+
*/
|
|
45
|
+
export declare function getDefaultBreakpoints(): BreakpointsMap;
|
|
46
|
+
|
|
19
47
|
/**
|
|
20
48
|
* Initializes the breakpoint helper
|
|
21
49
|
*/
|
|
22
50
|
export declare function initBreakpointHelper(options?: BreakpointHelperOptions): void;
|
|
23
51
|
|
|
52
|
+
export declare interface ResolvedBreakpoint {
|
|
53
|
+
name: string;
|
|
54
|
+
valuePx: number;
|
|
55
|
+
originalValue: string;
|
|
56
|
+
}
|
|
57
|
+
|
|
24
58
|
export { }
|
package/dist/index.esm.js
CHANGED
|
@@ -1,7 +1,110 @@
|
|
|
1
|
-
const
|
|
1
|
+
const C = {
|
|
2
2
|
hideDuration: 2e4
|
|
3
|
-
}
|
|
4
|
-
|
|
3
|
+
}, m = "[breakpoint-indicator]", E = {
|
|
4
|
+
sm: "40rem",
|
|
5
|
+
md: "48rem",
|
|
6
|
+
lg: "64rem",
|
|
7
|
+
xl: "80rem",
|
|
8
|
+
"2xl": "96rem"
|
|
9
|
+
}, A = ["xs", "3xl", "4xl"], g = [
|
|
10
|
+
"#ef4444",
|
|
11
|
+
/* red - base */
|
|
12
|
+
"#22c55e",
|
|
13
|
+
/* green */
|
|
14
|
+
"#3b82f6",
|
|
15
|
+
/* blue */
|
|
16
|
+
"#eab308",
|
|
17
|
+
/* yellow */
|
|
18
|
+
"#a855f7",
|
|
19
|
+
/* purple */
|
|
20
|
+
"#ec4899"
|
|
21
|
+
/* pink */
|
|
22
|
+
], k = /* @__PURE__ */ new WeakMap();
|
|
23
|
+
function L() {
|
|
24
|
+
if (typeof document > "u") return 16;
|
|
25
|
+
const n = document.documentElement, e = getComputedStyle(n).fontSize, r = parseFloat(e);
|
|
26
|
+
return Number.isNaN(r) ? 16 : r;
|
|
27
|
+
}
|
|
28
|
+
function P(n) {
|
|
29
|
+
if (typeof document > "u") return 0;
|
|
30
|
+
const e = document.createElement("div");
|
|
31
|
+
e.style.position = "fixed", e.style.left = "-9999px", e.style.top = "0", e.style.visibility = "hidden", e.style.pointerEvents = "none", e.style.width = n, e.style.height = "0", e.style.padding = "0", e.style.margin = "0", e.style.border = "0", e.style.boxSizing = "content-box", document.documentElement.appendChild(e);
|
|
32
|
+
const r = e.getBoundingClientRect().width;
|
|
33
|
+
return e.remove(), Number.isFinite(r) ? r : 0;
|
|
34
|
+
}
|
|
35
|
+
function H(n, e) {
|
|
36
|
+
const r = n.trim(), o = r.match(/^(-?\d*\.?\d+)(rem|em|px)$/i);
|
|
37
|
+
if (!o)
|
|
38
|
+
return P(r);
|
|
39
|
+
const t = parseFloat(o[1]), s = (o[2] || "").toLowerCase();
|
|
40
|
+
return s === "px" ? t : s === "rem" || s === "em" ? t * e : 0;
|
|
41
|
+
}
|
|
42
|
+
const y = /--breakpoint-([a-zA-Z0-9_-]+)\s*:\s*([^;]+)/g;
|
|
43
|
+
function S() {
|
|
44
|
+
const n = {};
|
|
45
|
+
if (typeof document > "u") return n;
|
|
46
|
+
const e = (o) => {
|
|
47
|
+
try {
|
|
48
|
+
if (o.style)
|
|
49
|
+
for (let t = 0; t < (o.style.length || 0); t++) {
|
|
50
|
+
const s = o.style.item(t);
|
|
51
|
+
if (s?.startsWith("--breakpoint-")) {
|
|
52
|
+
const a = s.slice(13), i = o.style.getPropertyValue(s).trim();
|
|
53
|
+
a && i && (n[a] = i);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (o.cssRules)
|
|
57
|
+
for (let t = 0; t < o.cssRules.length; t++)
|
|
58
|
+
e(o.cssRules[t]);
|
|
59
|
+
if (o.styleSheet?.cssRules)
|
|
60
|
+
for (let t = 0; t < o.styleSheet.cssRules.length; t++)
|
|
61
|
+
e(o.styleSheet.cssRules[t]);
|
|
62
|
+
} catch {
|
|
63
|
+
}
|
|
64
|
+
}, r = typeof location < "u" ? location.origin : "";
|
|
65
|
+
for (let o = 0; o < document.styleSheets.length; o++) {
|
|
66
|
+
const t = document.styleSheets[o];
|
|
67
|
+
if (!(t.href && r && !t.href.startsWith(r)))
|
|
68
|
+
try {
|
|
69
|
+
if (t.cssRules)
|
|
70
|
+
for (let s = 0; s < t.cssRules.length; s++)
|
|
71
|
+
e(t.cssRules[s]);
|
|
72
|
+
} catch {
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
for (const o of document.querySelectorAll("style")) {
|
|
76
|
+
const t = o.textContent || "";
|
|
77
|
+
let s;
|
|
78
|
+
for (y.lastIndex = 0; (s = y.exec(t)) !== null; ) {
|
|
79
|
+
const a = s[1], i = s[2].replace(/\/\*[\s\S]*?\*\//g, "").trim();
|
|
80
|
+
a && i && !n[a] && (n[a] = i);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return n;
|
|
84
|
+
}
|
|
85
|
+
function R(n) {
|
|
86
|
+
const e = n.baseLabel === void 0 ? "base" : n.baseLabel, r = L(), o = n.customBreakpoints && Object.keys(n.customBreakpoints).length > 0 ? n.customBreakpoints : {}, t = { ...E, ...S(), ...o }, s = [];
|
|
87
|
+
let a = 0;
|
|
88
|
+
for (const [u, d] of Object.entries(t)) {
|
|
89
|
+
const p = H(d, r);
|
|
90
|
+
if (!Number.isFinite(p) || p <= 0) {
|
|
91
|
+
a++;
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
s.push({ name: u, valuePx: p, originalValue: d, _i: a }), a++;
|
|
95
|
+
}
|
|
96
|
+
s.sort((u, d) => u.valuePx - d.valuePx || u._i - d._i);
|
|
97
|
+
const i = s.map(({ _i: u, ...d }) => d), l = i.length > 0 ? i[0].valuePx : 640;
|
|
98
|
+
return e !== !1 && i.unshift({
|
|
99
|
+
name: e,
|
|
100
|
+
valuePx: 0,
|
|
101
|
+
originalValue: `0 – ${l}px`
|
|
102
|
+
}), i;
|
|
103
|
+
}
|
|
104
|
+
function N(n) {
|
|
105
|
+
return n.trim().replace(/\s+/g, "-").replace(/[^a-z0-9_-]/gi, "-").toLowerCase();
|
|
106
|
+
}
|
|
107
|
+
function w() {
|
|
5
108
|
if (typeof import.meta < "u" && import.meta.env?.DEV || typeof globalThis < "u" && globalThis.process?.env?.NODE_ENV === "development")
|
|
6
109
|
return !0;
|
|
7
110
|
if (typeof window < "u") {
|
|
@@ -11,50 +114,98 @@ function d() {
|
|
|
11
114
|
}
|
|
12
115
|
return !1;
|
|
13
116
|
}
|
|
14
|
-
function
|
|
15
|
-
|
|
16
|
-
|
|
117
|
+
function O(n, e) {
|
|
118
|
+
let r = 0;
|
|
119
|
+
for (let o = 0; o < n.length; o++)
|
|
120
|
+
e >= n[o].valuePx && (r = o);
|
|
121
|
+
return r;
|
|
122
|
+
}
|
|
123
|
+
function h(n, e, r) {
|
|
124
|
+
const o = typeof window < "u" ? window.innerWidth : 0, t = O(e, o), s = g[t % g.length];
|
|
125
|
+
n.style.backgroundColor = s, r.querySelectorAll(".breakpoint-helper-label").forEach((i, l) => {
|
|
126
|
+
i.classList.toggle("breakpoint-helper-active", l === t);
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
function T(n) {
|
|
130
|
+
const e = document.createElement("div");
|
|
131
|
+
e.id = "breakpoint-helper", e.className = "breakpoint-helper", e.setAttribute("style", "display: none");
|
|
132
|
+
const r = B(n);
|
|
133
|
+
return e.appendChild(r), h(e, n, r), e;
|
|
134
|
+
}
|
|
135
|
+
function B(n) {
|
|
17
136
|
const e = document.createElement("div");
|
|
18
137
|
e.className = "breakpoint-helper-content";
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
const i = document.createElement("span");
|
|
28
|
-
i.className = "breakpoint-helper-label breakpoint-helper-xl", i.innerHTML = '<strong class="breakpoint-helper-badge">xl</strong> 80rem (1280px) @media (width >= 80rem)';
|
|
29
|
-
const p = document.createElement("span");
|
|
30
|
-
p.className = "breakpoint-helper-label breakpoint-helper-2xl", p.innerHTML = '<strong class="breakpoint-helper-badge">2xl</strong> 96rem (1536px) @media (width >= 96rem)', e.appendChild(o), e.appendChild(n), e.appendChild(r), e.appendChild(l), e.appendChild(i), e.appendChild(p);
|
|
31
|
-
const a = document.createElement("button");
|
|
32
|
-
return a.id = "breakpoint-helper-hide-btn", a.type = "button", a.className = "breakpoint-helper-hide-btn", a.setAttribute("aria-label", "Skrýt breakpoint helper na 20 sekund"), a.innerHTML = `
|
|
138
|
+
for (let o = 0; o < n.length; o++) {
|
|
139
|
+
const t = n[o], s = document.createElement("span"), a = N(t.name);
|
|
140
|
+
s.className = `breakpoint-helper-label breakpoint-helper-${a}`, s.setAttribute("data-breakpoint-px", String(t.valuePx)), s.setAttribute("data-breakpoint-name", t.name);
|
|
141
|
+
const i = t.valuePx === 0 ? t.originalValue : `${t.originalValue} (${Math.round(t.valuePx)}px)`, l = t.valuePx === 0 ? `@media (width < ${n[1]?.originalValue ?? "40rem"})` : `@media (width >= ${t.originalValue})`;
|
|
142
|
+
s.innerHTML = `<strong class="breakpoint-helper-badge">${x(t.name)}</strong> ${x(i)} ${l}`, e.appendChild(s);
|
|
143
|
+
}
|
|
144
|
+
const r = document.createElement("button");
|
|
145
|
+
return r.id = "breakpoint-helper-hide-btn", r.type = "button", r.className = "breakpoint-helper-hide-btn", r.setAttribute("aria-label", "Hide breakpoint helper for 20 seconds"), r.innerHTML = `
|
|
33
146
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="breakpoint-helper-icon">
|
|
34
147
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6v6h4.5m4.5 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
|
|
35
148
|
</svg>
|
|
36
|
-
`, e.appendChild(
|
|
149
|
+
`, e.appendChild(r), e;
|
|
37
150
|
}
|
|
38
|
-
function
|
|
39
|
-
const e =
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if (
|
|
151
|
+
function x(n) {
|
|
152
|
+
const e = document.createElement("div");
|
|
153
|
+
return e.textContent = n, e.innerHTML;
|
|
154
|
+
}
|
|
155
|
+
function v(n = {}) {
|
|
156
|
+
if (typeof window > "u" || typeof document > "u") return;
|
|
157
|
+
const e = { ...C, ...n };
|
|
158
|
+
if (!(e.enabled !== void 0 ? e.enabled : w())) {
|
|
159
|
+
const c = document.getElementById("breakpoint-helper");
|
|
160
|
+
c && (c.style.display = "none");
|
|
44
161
|
return;
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
162
|
+
}
|
|
163
|
+
const o = e.debug === !0, t = e.customBreakpoints && Object.keys(e.customBreakpoints).length > 0 ? e.customBreakpoints : {};
|
|
164
|
+
if (o) {
|
|
165
|
+
const c = S();
|
|
166
|
+
console.log(m, "From CSS (--breakpoint-*):", c), Object.keys(c).length === 0 && Object.keys(t).length === 0 && console.log(m, "No custom breakpoints in CSS. Use customBreakpoints in initBreakpointHelper() for extra names or fallback.");
|
|
167
|
+
}
|
|
168
|
+
const s = R(e), a = JSON.stringify(s.map((c) => [c.name, c.originalValue]));
|
|
169
|
+
if (o) {
|
|
170
|
+
const c = Object.keys(t).length > 0 ? "defaults + CSS + customBreakpoints" : "defaults + CSS";
|
|
171
|
+
Object.keys(t).length > 0 && console.log(m, "customBreakpoints:", t), console.log(m, "Breakpoint source:", c), console.log(
|
|
172
|
+
m,
|
|
173
|
+
"Resolved breakpoints:",
|
|
174
|
+
s.map((b) => `${b.name} (${b.originalValue})`).join(", ")
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
let i = null;
|
|
178
|
+
e.containerSelector ? i = document.querySelector(e.containerSelector) : i = document.getElementById("breakpoint-helper"), i ? i.classList.contains("breakpoint-helper") || i.classList.add("breakpoint-helper") : (i = T(s), document.body.appendChild(i)), i.style.display = "block";
|
|
179
|
+
const l = k.get(i) ?? {};
|
|
180
|
+
l.resizeHandler && (window.removeEventListener("resize", l.resizeHandler), l.resizeHandler = void 0);
|
|
181
|
+
const u = i.querySelector(".breakpoint-helper-content");
|
|
182
|
+
(!u || l.signature !== a) && (u && u.remove(), i.appendChild(B(s)), l.signature = a);
|
|
183
|
+
const d = i.querySelector(".breakpoint-helper-content");
|
|
184
|
+
d && h(i, s, d);
|
|
185
|
+
const p = () => {
|
|
186
|
+
const c = i?.querySelector(".breakpoint-helper-content");
|
|
187
|
+
i && c && h(i, s, c);
|
|
188
|
+
};
|
|
189
|
+
l.resizeHandler = p, window.addEventListener("resize", p);
|
|
190
|
+
const f = i.querySelector("#breakpoint-helper-hide-btn");
|
|
191
|
+
if (f) {
|
|
192
|
+
l.hideHandler && (f.removeEventListener("click", l.hideHandler), l.hideHandler = void 0);
|
|
193
|
+
const c = () => {
|
|
194
|
+
i.style.display = "none", window.setTimeout(() => {
|
|
195
|
+
i.style.display = "block";
|
|
196
|
+
}, e.hideDuration);
|
|
197
|
+
};
|
|
198
|
+
l.hideHandler = c, f.addEventListener("click", c);
|
|
199
|
+
}
|
|
200
|
+
k.set(i, l);
|
|
201
|
+
}
|
|
202
|
+
function _() {
|
|
203
|
+
return { ...E };
|
|
53
204
|
}
|
|
54
|
-
typeof window < "u" &&
|
|
55
|
-
s();
|
|
56
|
-
}) : s());
|
|
205
|
+
typeof window < "u" && w() && (document.readyState === "loading" ? document.addEventListener("DOMContentLoaded", () => v()) : v());
|
|
57
206
|
export {
|
|
58
|
-
|
|
207
|
+
A as DETECTABLE_CUSTOM_NAMES,
|
|
208
|
+
_ as getDefaultBreakpoints,
|
|
209
|
+
v as initBreakpointHelper
|
|
59
210
|
};
|
|
60
211
|
//# sourceMappingURL=index.esm.js.map
|
package/dist/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":["../src/index.ts"],"sourcesContent":["export interface BreakpointHelperOptions {\r\n /**\r\n * Whether the helper is enabled. If not provided, will try to detect dev mode.\r\n * @default undefined (auto-detect)\r\n */\r\n enabled?: boolean\r\n \r\n /**\r\n * Duration in milliseconds to hide the helper when hide button is clicked.\r\n * @default 20000 (20 seconds)\r\n */\r\n hideDuration?: number\r\n \r\n /**\r\n * Custom container selector. If provided, will use existing element instead of creating one.\r\n * @default undefined (creates new element)\r\n */\r\n containerSelector?: string\r\n}\r\n\r\nconst DEFAULT_OPTIONS: Required<Omit<BreakpointHelperOptions, 'enabled' | 'containerSelector'>> = {\r\n hideDuration: 20000\r\n}\r\n\r\n/**\r\n * Detects if we're in development mode\r\n */\r\nfunction isDevMode(): boolean {\r\n // Vite\r\n const meta = import.meta as { env?: { DEV?: boolean } }\r\n if (typeof import.meta !== 'undefined' && meta.env?.DEV) {\r\n return true\r\n }\r\n \r\n // Node.js / Webpack / Other bundlers\r\n if (typeof globalThis !== 'undefined') {\r\n const proc = (globalThis as unknown as { process?: { env?: { NODE_ENV?: string } } }).process\r\n if (proc?.env?.NODE_ENV === 'development') {\r\n return true\r\n }\r\n }\r\n \r\n // Fallback: check if we're in a development-like environment\r\n if (typeof window !== 'undefined') {\r\n // Check for common dev indicators\r\n const hostname = window.location.hostname\r\n if (hostname === 'localhost' || hostname === '127.0.0.1' || hostname.startsWith('192.168.')) {\r\n return true\r\n }\r\n }\r\n \r\n return false\r\n}\r\n\r\n/**\r\n * Creates the breakpoint helper HTML element\r\n */\r\nfunction createBreakpointHelperElement(): HTMLElement {\r\n const container = document.createElement('div')\r\n container.id = 'breakpoint-helper'\r\n container.className = 'breakpoint-helper'\r\n container.setAttribute('style', 'display: none')\r\n \r\n const content = document.createElement('div')\r\n content.className = 'breakpoint-helper-content'\r\n \r\n // Base breakpoint\r\n const baseSpan = document.createElement('span')\r\n baseSpan.className = 'breakpoint-helper-label breakpoint-helper-base'\r\n baseSpan.innerHTML = '<strong class=\"breakpoint-helper-badge\">base</strong> 32rem (512px) @media (width >= 32rem)'\r\n \r\n // SM breakpoint\r\n const smSpan = document.createElement('span')\r\n smSpan.className = 'breakpoint-helper-label breakpoint-helper-sm'\r\n smSpan.innerHTML = '<strong class=\"breakpoint-helper-badge\">sm</strong> 40rem (640px) @media (width >= 40rem)'\r\n \r\n // MD breakpoint\r\n const mdSpan = document.createElement('span')\r\n mdSpan.className = 'breakpoint-helper-label breakpoint-helper-md'\r\n mdSpan.innerHTML = '<strong class=\"breakpoint-helper-badge\">md</strong> 48rem (768px) @media (width >= 48rem)'\r\n \r\n // LG breakpoint\r\n const lgSpan = document.createElement('span')\r\n lgSpan.className = 'breakpoint-helper-label breakpoint-helper-lg'\r\n lgSpan.innerHTML = '<strong class=\"breakpoint-helper-badge\">lg</strong> 64rem (1024px) @media (width >= 64rem)'\r\n \r\n // XL breakpoint\r\n const xlSpan = document.createElement('span')\r\n xlSpan.className = 'breakpoint-helper-label breakpoint-helper-xl'\r\n xlSpan.innerHTML = '<strong class=\"breakpoint-helper-badge\">xl</strong> 80rem (1280px) @media (width >= 80rem)'\r\n \r\n // 2XL breakpoint\r\n const xl2Span = document.createElement('span')\r\n xl2Span.className = 'breakpoint-helper-label breakpoint-helper-2xl'\r\n xl2Span.innerHTML = '<strong class=\"breakpoint-helper-badge\">2xl</strong> 96rem (1536px) @media (width >= 96rem)'\r\n \r\n content.appendChild(baseSpan)\r\n content.appendChild(smSpan)\r\n content.appendChild(mdSpan)\r\n content.appendChild(lgSpan)\r\n content.appendChild(xlSpan)\r\n content.appendChild(xl2Span)\r\n \r\n // Hide button\r\n const hideButton = document.createElement('button')\r\n hideButton.id = 'breakpoint-helper-hide-btn'\r\n hideButton.type = 'button'\r\n hideButton.className = 'breakpoint-helper-hide-btn'\r\n hideButton.setAttribute('aria-label', 'Skrýt breakpoint helper na 20 sekund')\r\n \r\n hideButton.innerHTML = `\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"breakpoint-helper-icon\">\r\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M12 6v6h4.5m4.5 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z\" />\r\n </svg>\r\n `\r\n \r\n content.appendChild(hideButton)\r\n container.appendChild(content)\r\n \r\n return container\r\n}\r\n\r\n/**\r\n * Initializes the breakpoint helper\r\n */\r\nexport function initBreakpointHelper(options: BreakpointHelperOptions = {}): void {\r\n const opts = {\r\n ...DEFAULT_OPTIONS,\r\n ...options\r\n }\r\n \r\n // Determine if enabled\r\n const enabled = opts.enabled !== undefined ? opts.enabled : isDevMode()\r\n \r\n if (!enabled) {\r\n return\r\n }\r\n \r\n // Check if element already exists or use custom selector\r\n let breakpointHelper: HTMLElement | null = null\r\n \r\n if (opts.containerSelector) {\r\n breakpointHelper = document.querySelector(opts.containerSelector)\r\n } else {\r\n breakpointHelper = document.getElementById('breakpoint-helper')\r\n }\r\n \r\n // Create element if it doesn't exist\r\n if (!breakpointHelper) {\r\n breakpointHelper = createBreakpointHelperElement()\r\n document.body.appendChild(breakpointHelper)\r\n }\r\n \r\n // Show the helper\r\n breakpointHelper.style.display = 'block'\r\n \r\n // Setup hide button functionality\r\n const hideButton = breakpointHelper.querySelector('#breakpoint-helper-hide-btn') as HTMLButtonElement | null\r\n \r\n if (hideButton) {\r\n hideButton.addEventListener('click', () => {\r\n if (breakpointHelper) {\r\n breakpointHelper.style.display = 'none'\r\n \r\n setTimeout(() => {\r\n if (breakpointHelper) {\r\n breakpointHelper.style.display = 'block'\r\n }\r\n }, opts.hideDuration)\r\n }\r\n })\r\n }\r\n}\r\n\r\n/**\r\n * Auto-initialize if imported directly (for convenience)\r\n */\r\nif (typeof window !== 'undefined') {\r\n // Only auto-init in browser environment\r\n // Check if we should auto-init (dev mode)\r\n if (isDevMode()) {\r\n // Use requestAnimationFrame to ensure DOM is ready\r\n if (document.readyState === 'loading') {\r\n document.addEventListener('DOMContentLoaded', () => {\r\n initBreakpointHelper()\r\n })\r\n } else {\r\n initBreakpointHelper()\r\n }\r\n }\r\n}\r\n"],"names":["DEFAULT_OPTIONS","isDevMode","hostname","createBreakpointHelperElement","container","content","baseSpan","smSpan","mdSpan","lgSpan","xlSpan","xl2Span","hideButton","initBreakpointHelper","options","opts","breakpointHelper"],"mappings":"AAoBA,MAAMA,IAA4F;AAAA,EAChG,cAAc;AAChB;AAKA,SAASC,IAAqB;AAQ5B,MALI,OAAO,cAAgB,OADd,YACkC,KAAK,OAKhD,OAAO,aAAe,OACV,WAAwE,SAC5E,KAAK,aAAa;AAC1B,WAAO;AAKX,MAAI,OAAO,SAAW,KAAa;AAEjC,UAAMC,IAAW,OAAO,SAAS;AACjC,QAAIA,MAAa,eAAeA,MAAa,eAAeA,EAAS,WAAW,UAAU;AACxF,aAAO;AAAA,EAEX;AAEA,SAAO;AACT;AAKA,SAASC,IAA6C;AACpD,QAAMC,IAAY,SAAS,cAAc,KAAK;AAC9C,EAAAA,EAAU,KAAK,qBACfA,EAAU,YAAY,qBACtBA,EAAU,aAAa,SAAS,eAAe;AAE/C,QAAMC,IAAU,SAAS,cAAc,KAAK;AAC5C,EAAAA,EAAQ,YAAY;AAGpB,QAAMC,IAAW,SAAS,cAAc,MAAM;AAC9C,EAAAA,EAAS,YAAY,kDACrBA,EAAS,YAAY;AAGrB,QAAMC,IAAS,SAAS,cAAc,MAAM;AAC5C,EAAAA,EAAO,YAAY,gDACnBA,EAAO,YAAY;AAGnB,QAAMC,IAAS,SAAS,cAAc,MAAM;AAC5C,EAAAA,EAAO,YAAY,gDACnBA,EAAO,YAAY;AAGnB,QAAMC,IAAS,SAAS,cAAc,MAAM;AAC5C,EAAAA,EAAO,YAAY,gDACnBA,EAAO,YAAY;AAGnB,QAAMC,IAAS,SAAS,cAAc,MAAM;AAC5C,EAAAA,EAAO,YAAY,gDACnBA,EAAO,YAAY;AAGnB,QAAMC,IAAU,SAAS,cAAc,MAAM;AAC7C,EAAAA,EAAQ,YAAY,iDACpBA,EAAQ,YAAY,+FAEpBN,EAAQ,YAAYC,CAAQ,GAC5BD,EAAQ,YAAYE,CAAM,GAC1BF,EAAQ,YAAYG,CAAM,GAC1BH,EAAQ,YAAYI,CAAM,GAC1BJ,EAAQ,YAAYK,CAAM,GAC1BL,EAAQ,YAAYM,CAAO;AAG3B,QAAMC,IAAa,SAAS,cAAc,QAAQ;AAClD,SAAAA,EAAW,KAAK,8BAChBA,EAAW,OAAO,UAClBA,EAAW,YAAY,8BACvBA,EAAW,aAAa,cAAc,sCAAsC,GAE5EA,EAAW,YAAY;AAAA;AAAA;AAAA;AAAA,KAMvBP,EAAQ,YAAYO,CAAU,GAC9BR,EAAU,YAAYC,CAAO,GAEtBD;AACT;AAKO,SAASS,EAAqBC,IAAmC,IAAU;AAChF,QAAMC,IAAO;AAAA,IACX,GAAGf;AAAA,IACH,GAAGc;AAAA,EAAA;AAML,MAAI,EAFYC,EAAK,YAAY,SAAYA,EAAK,UAAUd,EAAA;AAG1D;AAIF,MAAIe,IAAuC;AAE3C,EAAID,EAAK,oBACPC,IAAmB,SAAS,cAAcD,EAAK,iBAAiB,IAEhEC,IAAmB,SAAS,eAAe,mBAAmB,GAI3DA,MACHA,IAAmBb,EAAA,GACnB,SAAS,KAAK,YAAYa,CAAgB,IAI5CA,EAAiB,MAAM,UAAU;AAGjC,QAAMJ,IAAaI,EAAiB,cAAc,6BAA6B;AAE/E,EAAIJ,KACFA,EAAW,iBAAiB,SAAS,MAAM;AACzC,IAAII,MACFA,EAAiB,MAAM,UAAU,QAEjC,WAAW,MAAM;AACf,MAAIA,MACFA,EAAiB,MAAM,UAAU;AAAA,IAErC,GAAGD,EAAK,YAAY;AAAA,EAExB,CAAC;AAEL;AAKI,OAAO,SAAW,OAGhBd,QAEE,SAAS,eAAe,YAC1B,SAAS,iBAAiB,oBAAoB,MAAM;AAClD,EAAAY,EAAA;AACF,CAAC,IAEDA,EAAA;"}
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../src/index.ts"],"sourcesContent":["/** Breakpoint value in original form (e.g. \"40rem\", \"1280px\") */\r\nexport type BreakpointsMap = Record<string, string>\r\n\r\nexport interface ResolvedBreakpoint {\r\n name: string\r\n valuePx: number\r\n originalValue: string\r\n}\r\n\r\nexport interface BreakpointHelperOptions {\r\n /**\r\n * Whether the helper is enabled. If not provided, will try to detect dev mode.\r\n * @default undefined (auto-detect)\r\n */\r\n enabled?: boolean\r\n\r\n /**\r\n * Duration in milliseconds to hide the helper when hide button is clicked.\r\n * @default 20000 (20 seconds)\r\n */\r\n hideDuration?: number\r\n\r\n /**\r\n * Custom container selector. If provided, will use existing element instead of creating one.\r\n * @default undefined (creates new element)\r\n */\r\n containerSelector?: string\r\n\r\n /**\r\n * Custom breakpoint names + values added to defaults and CSS detection.\r\n * Use for extra names (4xl, desktop, …) or as fallback when CSS detection fails (e.g. Vue/Vite).\r\n * In Tailwind v3, use this for custom screens (xs, 3xl) from theme.extend.screens.\r\n * @example { xs: '30rem', '3xl': '120rem', desktop: '64rem' }\r\n */\r\n customBreakpoints?: BreakpointsMap\r\n\r\n /**\r\n * Label for the \"base\" range (below first breakpoint). Use string to rename, or false to hide base row.\r\n * @default 'base'\r\n */\r\n baseLabel?: string | false\r\n\r\n /**\r\n * Enable debug output in console.\r\n * @default false\r\n */\r\n debug?: boolean\r\n}\r\n\r\nconst DEFAULT_OPTIONS: Required<Omit<BreakpointHelperOptions, 'enabled' | 'containerSelector' | 'customBreakpoints' | 'baseLabel' | 'debug'>> = {\r\n hideDuration: 20000\r\n}\r\n\r\nconst DEBUG_PREFIX = '[breakpoint-indicator]'\r\n\r\n/** Standard Tailwind breakpoints (sm–2xl). Custom names (xs, 3xl, 4xl, …) are detected from CSS. */\r\nconst DEFAULT_BREAKPOINTS: BreakpointsMap = {\r\n sm: '40rem',\r\n md: '48rem',\r\n lg: '64rem',\r\n xl: '80rem',\r\n '2xl': '96rem'\r\n}\r\n\r\n/** Names we know to look for in project CSS (--breakpoint-xs etc.). Documented for users. */\r\nexport const DETECTABLE_CUSTOM_NAMES = ['xs', '3xl', '4xl'] as const\r\n\r\n/** Container background colors by breakpoint index (base, xs, sm, md, …) */\r\nconst BREAKPOINT_COLORS = [\r\n '#ef4444', /* red - base */\r\n '#22c55e', /* green */\r\n '#3b82f6', /* blue */\r\n '#eab308', /* yellow */\r\n '#a855f7', /* purple */\r\n '#ec4899' /* pink */\r\n]\r\n\r\ntype HelperState = {\r\n resizeHandler?: () => void\r\n hideHandler?: () => void\r\n signature?: string\r\n}\r\n\r\nconst HELPER_STATE = new WeakMap<HTMLElement, HelperState>()\r\n\r\nfunction getRootFontSizePx(): number {\r\n if (typeof document === 'undefined') return 16\r\n const root = document.documentElement\r\n const computed = getComputedStyle(root).fontSize\r\n const parsed = parseFloat(computed)\r\n return Number.isNaN(parsed) ? 16 : parsed\r\n}\r\n\r\n/**\r\n * Try to resolve an arbitrary CSS length to pixels using layout measurement.\r\n */\r\nfunction measureCssLengthPx(value: string): number {\r\n if (typeof document === 'undefined') return 0\r\n const el = document.createElement('div')\r\n el.style.position = 'fixed'\r\n el.style.left = '-9999px'\r\n el.style.top = '0'\r\n el.style.visibility = 'hidden'\r\n el.style.pointerEvents = 'none'\r\n el.style.width = value\r\n el.style.height = '0'\r\n el.style.padding = '0'\r\n el.style.margin = '0'\r\n el.style.border = '0'\r\n el.style.boxSizing = 'content-box'\r\n\r\n document.documentElement.appendChild(el)\r\n const px = el.getBoundingClientRect().width\r\n el.remove()\r\n return Number.isFinite(px) ? px : 0\r\n}\r\n\r\n/**\r\n * Parse a breakpoint value (e.g. \"40rem\", \"1280px\") to pixels.\r\n */\r\nfunction parseBreakpointValue(value: string, rootFontSizePx: number): number {\r\n const trimmed = value.trim()\r\n const match = trimmed.match(/^(-?\\d*\\.?\\d+)(rem|em|px)$/i)\r\n if (!match) {\r\n return measureCssLengthPx(trimmed)\r\n }\r\n const num = parseFloat(match[1])\r\n const unit = (match[2] || '').toLowerCase()\r\n if (unit === 'px') return num\r\n if (unit === 'rem' || unit === 'em') return num * rootFontSizePx\r\n return 0\r\n}\r\n\r\nconst BREAKPOINT_RE = /--breakpoint-([a-zA-Z0-9_-]+)\\s*:\\s*([^;]+)/g\r\n\r\n/**\r\n * Read --breakpoint-* custom properties from the document (Tailwind v4 @theme).\r\n * Returns only custom breakpoints found in CSS (xs, 3xl, 4xl, desktop, …).\r\n * Merged with DEFAULT_BREAKPOINTS so project gets defaults + any extra it defines.\r\n */\r\nfunction getBreakpointsFromCss(): BreakpointsMap {\r\n const result: BreakpointsMap = {}\r\n if (typeof document === 'undefined') return result\r\n\r\n const collectFromRule = (rule: CSSRule & { style?: CSSStyleDeclaration; cssRules?: CSSRuleList; styleSheet?: { cssRules?: CSSRuleList } }): void => {\r\n try {\r\n if (rule.style) {\r\n for (let k = 0; k < (rule.style.length || 0); k++) {\r\n const prop = rule.style.item(k)\r\n if (prop?.startsWith('--breakpoint-')) {\r\n const name = prop.slice('--breakpoint-'.length)\r\n const val = rule.style.getPropertyValue(prop).trim()\r\n if (name && val) result[name] = val\r\n }\r\n }\r\n }\r\n if (rule.cssRules) {\r\n for (let i = 0; i < rule.cssRules.length; i++) {\r\n collectFromRule(rule.cssRules[i] as CSSRule & { style?: CSSStyleDeclaration; cssRules?: CSSRuleList })\r\n }\r\n }\r\n if (rule.styleSheet?.cssRules) {\r\n for (let i = 0; i < rule.styleSheet.cssRules.length; i++) {\r\n collectFromRule(rule.styleSheet.cssRules[i] as CSSRule & { style?: CSSStyleDeclaration; cssRules?: CSSRuleList; styleSheet?: { cssRules?: CSSRuleList } })\r\n }\r\n }\r\n } catch { /* cross-origin */ }\r\n }\r\n\r\n const origin = typeof location !== 'undefined' ? location.origin : ''\r\n for (let i = 0; i < document.styleSheets.length; i++) {\r\n const sheet = document.styleSheets[i] as CSSStyleSheet & { href?: string }\r\n if (sheet.href && origin && !sheet.href.startsWith(origin)) continue\r\n try {\r\n if (sheet.cssRules) {\r\n for (let j = 0; j < sheet.cssRules.length; j++) {\r\n collectFromRule(sheet.cssRules[j] as CSSRule & { style?: CSSStyleDeclaration; cssRules?: CSSRuleList; styleSheet?: { cssRules?: CSSRuleList } })\r\n }\r\n }\r\n } catch { /* cross-origin */ }\r\n }\r\n\r\n // Fallback: parse <style> textContent (Vite may use insertRule so cssRules has data but we also try text)\r\n for (const el of document.querySelectorAll('style')) {\r\n const text = el.textContent || ''\r\n let m: RegExpExecArray | null\r\n BREAKPOINT_RE.lastIndex = 0\r\n while ((m = BREAKPOINT_RE.exec(text)) !== null) {\r\n const name = m[1]\r\n const val = m[2].replace(/\\/\\*[\\s\\S]*?\\*\\//g, '').trim()\r\n if (name && val && !result[name]) result[name] = val\r\n }\r\n }\r\n\r\n return result\r\n}\r\n\r\n/**\r\n * Resolve breakpoints: defaults + detected from CSS + customBreakpoints.\r\n * Returns sorted list including optional base row.\r\n */\r\nfunction resolveBreakpoints(options: BreakpointHelperOptions): ResolvedBreakpoint[] {\r\n const baseLabel = options.baseLabel === undefined ? 'base' : options.baseLabel\r\n const rootFontSizePx = getRootFontSizePx()\r\n\r\n const customBreakpoints = options.customBreakpoints && Object.keys(options.customBreakpoints).length > 0 ? options.customBreakpoints : {}\r\n const raw: BreakpointsMap = { ...DEFAULT_BREAKPOINTS, ...getBreakpointsFromCss(), ...customBreakpoints }\r\n\r\n const listWithIndex: Array<ResolvedBreakpoint & { _i: number }> = []\r\n let idx = 0\r\n for (const [name, originalValue] of Object.entries(raw)) {\r\n const valuePx = parseBreakpointValue(originalValue, rootFontSizePx)\r\n if (!Number.isFinite(valuePx) || valuePx <= 0) {\r\n idx++\r\n continue\r\n }\r\n listWithIndex.push({ name, valuePx, originalValue, _i: idx })\r\n idx++\r\n }\r\n listWithIndex.sort((a, b) => (a.valuePx - b.valuePx) || (a._i - b._i))\r\n const list: ResolvedBreakpoint[] = listWithIndex.map(({ _i, ...bp }) => bp)\r\n\r\n const firstPx = list.length > 0 ? list[0].valuePx : 640\r\n if (baseLabel !== false) {\r\n list.unshift({\r\n name: baseLabel,\r\n valuePx: 0,\r\n originalValue: `0 – ${firstPx}px`\r\n })\r\n }\r\n\r\n return list\r\n}\r\n\r\nfunction breakpointNameToClass(name: string): string {\r\n return name\r\n .trim()\r\n .replace(/\\s+/g, '-')\r\n .replace(/[^a-z0-9_-]/gi, '-')\r\n .toLowerCase()\r\n}\r\n\r\nfunction isDevMode(): boolean {\r\n const meta = import.meta as { env?: { DEV?: boolean } }\r\n if (typeof import.meta !== 'undefined' && meta.env?.DEV) return true\r\n\r\n if (typeof globalThis !== 'undefined') {\r\n const proc = (globalThis as unknown as { process?: { env?: { NODE_ENV?: string } } }).process\r\n if (proc?.env?.NODE_ENV === 'development') return true\r\n }\r\n\r\n if (typeof window !== 'undefined') {\r\n const hostname = window.location.hostname\r\n if (hostname === 'localhost' || hostname === '127.0.0.1' || hostname.startsWith('192.168.')) {\r\n return true\r\n }\r\n }\r\n\r\n return false\r\n}\r\n\r\nfunction getActiveBreakpointIndex(resolved: ResolvedBreakpoint[], widthPx: number): number {\r\n let index = 0\r\n for (let i = 0; i < resolved.length; i++) {\r\n if (widthPx >= resolved[i].valuePx) index = i\r\n }\r\n return index\r\n}\r\n\r\nfunction updateActiveBreakpoint(\r\n container: HTMLElement,\r\n resolved: ResolvedBreakpoint[],\r\n content: HTMLElement\r\n): void {\r\n const width = typeof window !== 'undefined' ? window.innerWidth : 0\r\n const index = getActiveBreakpointIndex(resolved, width)\r\n const color = BREAKPOINT_COLORS[index % BREAKPOINT_COLORS.length]\r\n container.style.backgroundColor = color\r\n\r\n const labels = content.querySelectorAll('.breakpoint-helper-label')\r\n labels.forEach((el, i) => {\r\n el.classList.toggle('breakpoint-helper-active', i === index)\r\n })\r\n}\r\n\r\nfunction createBreakpointHelperElement(resolved: ResolvedBreakpoint[]): HTMLElement {\r\n const container = document.createElement('div')\r\n container.id = 'breakpoint-helper'\r\n container.className = 'breakpoint-helper'\r\n container.setAttribute('style', 'display: none')\r\n\r\n const content = buildBreakpointHelperContent(resolved)\r\n container.appendChild(content)\r\n\r\n updateActiveBreakpoint(container, resolved, content)\r\n return container\r\n}\r\n\r\nfunction buildBreakpointHelperContent(resolved: ResolvedBreakpoint[]): HTMLElement {\r\n const content = document.createElement('div')\r\n content.className = 'breakpoint-helper-content'\r\n\r\n for (let i = 0; i < resolved.length; i++) {\r\n const bp = resolved[i]\r\n const span = document.createElement('span')\r\n const classBase = breakpointNameToClass(bp.name)\r\n span.className = `breakpoint-helper-label breakpoint-helper-${classBase}`\r\n span.setAttribute('data-breakpoint-px', String(bp.valuePx))\r\n span.setAttribute('data-breakpoint-name', bp.name)\r\n\r\n const valueDisplay = bp.valuePx === 0\r\n ? bp.originalValue\r\n : `${bp.originalValue} (${Math.round(bp.valuePx)}px)`\r\n const mediaPart = bp.valuePx === 0\r\n ? `@media (width < ${resolved[1]?.originalValue ?? '40rem'})`\r\n : `@media (width >= ${bp.originalValue})`\r\n span.innerHTML = `<strong class=\"breakpoint-helper-badge\">${escapeHtml(bp.name)}</strong> ${escapeHtml(valueDisplay)} ${mediaPart}`\r\n content.appendChild(span)\r\n }\r\n\r\n const hideButton = document.createElement('button')\r\n hideButton.id = 'breakpoint-helper-hide-btn'\r\n hideButton.type = 'button'\r\n hideButton.className = 'breakpoint-helper-hide-btn'\r\n hideButton.setAttribute('aria-label', 'Hide breakpoint helper for 20 seconds')\r\n hideButton.innerHTML = `\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"breakpoint-helper-icon\">\r\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M12 6v6h4.5m4.5 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z\" />\r\n </svg>\r\n `\r\n content.appendChild(hideButton)\r\n\r\n return content\r\n}\r\n\r\nfunction escapeHtml(text: string): string {\r\n const div = document.createElement('div')\r\n div.textContent = text\r\n return div.innerHTML\r\n}\r\n\r\n/**\r\n * Initializes the breakpoint helper\r\n */\r\nexport function initBreakpointHelper(options: BreakpointHelperOptions = {}): void {\r\n if (typeof window === 'undefined' || typeof document === 'undefined') return\r\n\r\n const opts = { ...DEFAULT_OPTIONS, ...options }\r\n\r\n const enabled = opts.enabled !== undefined ? opts.enabled : isDevMode()\r\n if (!enabled) {\r\n const existing = document.getElementById('breakpoint-helper')\r\n if (existing) existing.style.display = 'none'\r\n return\r\n }\r\n\r\n const debug = opts.debug === true\r\n\r\n const customBreakpoints = opts.customBreakpoints && Object.keys(opts.customBreakpoints).length > 0 ? opts.customBreakpoints : {}\r\n\r\n if (debug) {\r\n const fromCss = getBreakpointsFromCss()\r\n console.log(DEBUG_PREFIX, 'From CSS (--breakpoint-*):', fromCss)\r\n if (Object.keys(fromCss).length === 0 && Object.keys(customBreakpoints).length === 0) {\r\n console.log(DEBUG_PREFIX, 'No custom breakpoints in CSS. Use customBreakpoints in initBreakpointHelper() for extra names or fallback.')\r\n }\r\n }\r\n\r\n const resolved = resolveBreakpoints(opts)\r\n const signature = JSON.stringify(resolved.map((bp) => [bp.name, bp.originalValue]))\r\n\r\n if (debug) {\r\n const source = Object.keys(customBreakpoints).length > 0 ? 'defaults + CSS + customBreakpoints' : 'defaults + CSS'\r\n if (Object.keys(customBreakpoints).length > 0) {\r\n console.log(DEBUG_PREFIX, 'customBreakpoints:', customBreakpoints)\r\n }\r\n console.log(DEBUG_PREFIX, 'Breakpoint source:', source)\r\n console.log(\r\n DEBUG_PREFIX,\r\n 'Resolved breakpoints:',\r\n resolved.map((bp) => `${bp.name} (${bp.originalValue})`).join(', ')\r\n )\r\n }\r\n\r\n let breakpointHelper: HTMLElement | null = null\r\n if (opts.containerSelector) {\r\n breakpointHelper = document.querySelector(opts.containerSelector) as HTMLElement | null\r\n } else {\r\n breakpointHelper = document.getElementById('breakpoint-helper')\r\n }\r\n\r\n if (!breakpointHelper) {\r\n breakpointHelper = createBreakpointHelperElement(resolved)\r\n document.body.appendChild(breakpointHelper)\r\n } else {\r\n if (!breakpointHelper.classList.contains('breakpoint-helper')) {\r\n breakpointHelper.classList.add('breakpoint-helper')\r\n }\r\n }\r\n\r\n breakpointHelper.style.display = 'block'\r\n\r\n const state: HelperState = HELPER_STATE.get(breakpointHelper) ?? {}\r\n\r\n if (state.resizeHandler) {\r\n window.removeEventListener('resize', state.resizeHandler)\r\n state.resizeHandler = undefined\r\n }\r\n\r\n const existingContent = breakpointHelper.querySelector('.breakpoint-helper-content') as HTMLElement | null\r\n if (!existingContent || state.signature !== signature) {\r\n if (existingContent) existingContent.remove()\r\n breakpointHelper.appendChild(buildBreakpointHelperContent(resolved))\r\n state.signature = signature\r\n }\r\n\r\n const contentEl = breakpointHelper.querySelector('.breakpoint-helper-content') as HTMLElement | null\r\n if (contentEl) updateActiveBreakpoint(breakpointHelper, resolved, contentEl)\r\n\r\n const resizeHandler = (): void => {\r\n const content = breakpointHelper?.querySelector('.breakpoint-helper-content') as HTMLElement | null\r\n if (breakpointHelper && content) updateActiveBreakpoint(breakpointHelper, resolved, content)\r\n }\r\n state.resizeHandler = resizeHandler\r\n window.addEventListener('resize', resizeHandler)\r\n\r\n const hideButton = breakpointHelper.querySelector('#breakpoint-helper-hide-btn') as HTMLButtonElement | null\r\n if (hideButton) {\r\n if (state.hideHandler) {\r\n hideButton.removeEventListener('click', state.hideHandler)\r\n state.hideHandler = undefined\r\n }\r\n const hideHandler = (): void => {\r\n breakpointHelper!.style.display = 'none'\r\n window.setTimeout(() => {\r\n breakpointHelper!.style.display = 'block'\r\n }, opts.hideDuration)\r\n }\r\n state.hideHandler = hideHandler\r\n hideButton.addEventListener('click', hideHandler)\r\n }\r\n\r\n HELPER_STATE.set(breakpointHelper, state)\r\n}\r\n\r\n/**\r\n * Returns the default breakpoints. Useful for debugging or when building custom options.\r\n */\r\nexport function getDefaultBreakpoints(): BreakpointsMap {\r\n return { ...DEFAULT_BREAKPOINTS }\r\n}\r\n\r\n/**\r\n * Auto-initialize if imported directly (for convenience)\r\n */\r\nif (typeof window !== 'undefined') {\r\n if (isDevMode()) {\r\n if (document.readyState === 'loading') {\r\n document.addEventListener('DOMContentLoaded', () => initBreakpointHelper())\r\n } else {\r\n initBreakpointHelper()\r\n }\r\n }\r\n}\r\n"],"names":["DEFAULT_OPTIONS","DEBUG_PREFIX","DEFAULT_BREAKPOINTS","DETECTABLE_CUSTOM_NAMES","BREAKPOINT_COLORS","HELPER_STATE","getRootFontSizePx","root","computed","parsed","measureCssLengthPx","value","el","px","parseBreakpointValue","rootFontSizePx","trimmed","match","num","unit","BREAKPOINT_RE","getBreakpointsFromCss","result","collectFromRule","rule","k","prop","name","val","i","origin","sheet","j","text","m","resolveBreakpoints","options","baseLabel","customBreakpoints","raw","listWithIndex","idx","originalValue","valuePx","a","b","list","_i","bp","firstPx","breakpointNameToClass","isDevMode","hostname","getActiveBreakpointIndex","resolved","widthPx","index","updateActiveBreakpoint","container","content","width","color","createBreakpointHelperElement","buildBreakpointHelperContent","span","classBase","valueDisplay","mediaPart","escapeHtml","hideButton","div","initBreakpointHelper","opts","existing","debug","fromCss","signature","source","breakpointHelper","state","existingContent","contentEl","resizeHandler","hideHandler","getDefaultBreakpoints"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});var
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});var m=typeof document<"u"?document.currentScript:null;const L={hideDuration:2e4},f="[breakpoint-indicator]",E={sm:"40rem",md:"48rem",lg:"64rem",xl:"80rem","2xl":"96rem"},R=["xs","3xl","4xl"],y=["#ef4444","#22c55e","#3b82f6","#eab308","#a855f7","#ec4899"],v=new WeakMap;function T(){if(typeof document>"u")return 16;const n=document.documentElement,e=getComputedStyle(n).fontSize,s=parseFloat(e);return Number.isNaN(s)?16:s}function P(n){if(typeof document>"u")return 0;const e=document.createElement("div");e.style.position="fixed",e.style.left="-9999px",e.style.top="0",e.style.visibility="hidden",e.style.pointerEvents="none",e.style.width=n,e.style.height="0",e.style.padding="0",e.style.margin="0",e.style.border="0",e.style.boxSizing="content-box",document.documentElement.appendChild(e);const s=e.getBoundingClientRect().width;return e.remove(),Number.isFinite(s)?s:0}function H(n,e){const s=n.trim(),o=s.match(/^(-?\d*\.?\d+)(rem|em|px)$/i);if(!o)return P(s);const t=parseFloat(o[1]),r=(o[2]||"").toLowerCase();return r==="px"?t:r==="rem"||r==="em"?t*e:0}const x=/--breakpoint-([a-zA-Z0-9_-]+)\s*:\s*([^;]+)/g;function B(){const n={};if(typeof document>"u")return n;const e=o=>{try{if(o.style)for(let t=0;t<(o.style.length||0);t++){const r=o.style.item(t);if(r?.startsWith("--breakpoint-")){const a=r.slice(13),i=o.style.getPropertyValue(r).trim();a&&i&&(n[a]=i)}}if(o.cssRules)for(let t=0;t<o.cssRules.length;t++)e(o.cssRules[t]);if(o.styleSheet?.cssRules)for(let t=0;t<o.styleSheet.cssRules.length;t++)e(o.styleSheet.cssRules[t])}catch{}},s=typeof location<"u"?location.origin:"";for(let o=0;o<document.styleSheets.length;o++){const t=document.styleSheets[o];if(!(t.href&&s&&!t.href.startsWith(s)))try{if(t.cssRules)for(let r=0;r<t.cssRules.length;r++)e(t.cssRules[r])}catch{}}for(const o of document.querySelectorAll("style")){const t=o.textContent||"";let r;for(x.lastIndex=0;(r=x.exec(t))!==null;){const a=r[1],i=r[2].replace(/\/\*[\s\S]*?\*\//g,"").trim();a&&i&&!n[a]&&(n[a]=i)}}return n}function N(n){const e=n.baseLabel===void 0?"base":n.baseLabel,s=T(),o=n.customBreakpoints&&Object.keys(n.customBreakpoints).length>0?n.customBreakpoints:{},t={...E,...B(),...o},r=[];let a=0;for(const[u,d]of Object.entries(t)){const p=H(d,s);if(!Number.isFinite(p)||p<=0){a++;continue}r.push({name:u,valuePx:p,originalValue:d,_i:a}),a++}r.sort((u,d)=>u.valuePx-d.valuePx||u._i-d._i);const i=r.map(({_i:u,...d})=>d),l=i.length>0?i[0].valuePx:640;return e!==!1&&i.unshift({name:e,valuePx:0,originalValue:`0 – ${l}px`}),i}function _(n){return n.trim().replace(/\s+/g,"-").replace(/[^a-z0-9_-]/gi,"-").toLowerCase()}function w(){const n={url:typeof document>"u"?require("url").pathToFileURL(__filename).href:m&&m.tagName.toUpperCase()==="SCRIPT"&&m.src||new URL("index.js",document.baseURI).href};if(typeof{url:typeof document>"u"?require("url").pathToFileURL(__filename).href:m&&m.tagName.toUpperCase()==="SCRIPT"&&m.src||new URL("index.js",document.baseURI).href}<"u"&&n.env?.DEV||typeof globalThis<"u"&&globalThis.process?.env?.NODE_ENV==="development")return!0;if(typeof window<"u"){const e=window.location.hostname;if(e==="localhost"||e==="127.0.0.1"||e.startsWith("192.168."))return!0}return!1}function O(n,e){let s=0;for(let o=0;o<n.length;o++)e>=n[o].valuePx&&(s=o);return s}function b(n,e,s){const o=typeof window<"u"?window.innerWidth:0,t=O(e,o),r=y[t%y.length];n.style.backgroundColor=r,s.querySelectorAll(".breakpoint-helper-label").forEach((i,l)=>{i.classList.toggle("breakpoint-helper-active",l===t)})}function A(n){const e=document.createElement("div");e.id="breakpoint-helper",e.className="breakpoint-helper",e.setAttribute("style","display: none");const s=C(n);return e.appendChild(s),b(e,n,s),e}function C(n){const e=document.createElement("div");e.className="breakpoint-helper-content";for(let o=0;o<n.length;o++){const t=n[o],r=document.createElement("span"),a=_(t.name);r.className=`breakpoint-helper-label breakpoint-helper-${a}`,r.setAttribute("data-breakpoint-px",String(t.valuePx)),r.setAttribute("data-breakpoint-name",t.name);const i=t.valuePx===0?t.originalValue:`${t.originalValue} (${Math.round(t.valuePx)}px)`,l=t.valuePx===0?`@media (width < ${n[1]?.originalValue??"40rem"})`:`@media (width >= ${t.originalValue})`;r.innerHTML=`<strong class="breakpoint-helper-badge">${S(t.name)}</strong> ${S(i)} ${l}`,e.appendChild(r)}const s=document.createElement("button");return s.id="breakpoint-helper-hide-btn",s.type="button",s.className="breakpoint-helper-hide-btn",s.setAttribute("aria-label","Hide breakpoint helper for 20 seconds"),s.innerHTML=`
|
|
2
2
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="breakpoint-helper-icon">
|
|
3
3
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6v6h4.5m4.5 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
|
|
4
4
|
</svg>
|
|
5
|
-
`,e.appendChild(
|
|
5
|
+
`,e.appendChild(s),e}function S(n){const e=document.createElement("div");return e.textContent=n,e.innerHTML}function g(n={}){if(typeof window>"u"||typeof document>"u")return;const e={...L,...n};if(!(e.enabled!==void 0?e.enabled:w())){const c=document.getElementById("breakpoint-helper");c&&(c.style.display="none");return}const o=e.debug===!0,t=e.customBreakpoints&&Object.keys(e.customBreakpoints).length>0?e.customBreakpoints:{};if(o){const c=B();console.log(f,"From CSS (--breakpoint-*):",c),Object.keys(c).length===0&&Object.keys(t).length===0&&console.log(f,"No custom breakpoints in CSS. Use customBreakpoints in initBreakpointHelper() for extra names or fallback.")}const r=N(e),a=JSON.stringify(r.map(c=>[c.name,c.originalValue]));if(o){const c=Object.keys(t).length>0?"defaults + CSS + customBreakpoints":"defaults + CSS";Object.keys(t).length>0&&console.log(f,"customBreakpoints:",t),console.log(f,"Breakpoint source:",c),console.log(f,"Resolved breakpoints:",r.map(k=>`${k.name} (${k.originalValue})`).join(", "))}let i=null;e.containerSelector?i=document.querySelector(e.containerSelector):i=document.getElementById("breakpoint-helper"),i?i.classList.contains("breakpoint-helper")||i.classList.add("breakpoint-helper"):(i=A(r),document.body.appendChild(i)),i.style.display="block";const l=v.get(i)??{};l.resizeHandler&&(window.removeEventListener("resize",l.resizeHandler),l.resizeHandler=void 0);const u=i.querySelector(".breakpoint-helper-content");(!u||l.signature!==a)&&(u&&u.remove(),i.appendChild(C(r)),l.signature=a);const d=i.querySelector(".breakpoint-helper-content");d&&b(i,r,d);const p=()=>{const c=i?.querySelector(".breakpoint-helper-content");i&&c&&b(i,r,c)};l.resizeHandler=p,window.addEventListener("resize",p);const h=i.querySelector("#breakpoint-helper-hide-btn");if(h){l.hideHandler&&(h.removeEventListener("click",l.hideHandler),l.hideHandler=void 0);const c=()=>{i.style.display="none",window.setTimeout(()=>{i.style.display="block"},e.hideDuration)};l.hideHandler=c,h.addEventListener("click",c)}v.set(i,l)}function D(){return{...E}}typeof window<"u"&&w()&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>g()):g());exports.DETECTABLE_CUSTOM_NAMES=R;exports.getDefaultBreakpoints=D;exports.initBreakpointHelper=g;
|
|
6
6
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["export interface BreakpointHelperOptions {\r\n /**\r\n * Whether the helper is enabled. If not provided, will try to detect dev mode.\r\n * @default undefined (auto-detect)\r\n */\r\n enabled?: boolean\r\n \r\n /**\r\n * Duration in milliseconds to hide the helper when hide button is clicked.\r\n * @default 20000 (20 seconds)\r\n */\r\n hideDuration?: number\r\n \r\n /**\r\n * Custom container selector. If provided, will use existing element instead of creating one.\r\n * @default undefined (creates new element)\r\n */\r\n containerSelector?: string\r\n}\r\n\r\nconst DEFAULT_OPTIONS: Required<Omit<BreakpointHelperOptions, 'enabled' | 'containerSelector'>> = {\r\n hideDuration: 20000\r\n}\r\n\r\n/**\r\n * Detects if we're in development mode\r\n */\r\nfunction isDevMode(): boolean {\r\n // Vite\r\n const meta = import.meta as { env?: { DEV?: boolean } }\r\n if (typeof import.meta !== 'undefined' && meta.env?.DEV) {\r\n return true\r\n }\r\n \r\n // Node.js / Webpack / Other bundlers\r\n if (typeof globalThis !== 'undefined') {\r\n const proc = (globalThis as unknown as { process?: { env?: { NODE_ENV?: string } } }).process\r\n if (proc?.env?.NODE_ENV === 'development') {\r\n return true\r\n }\r\n }\r\n \r\n // Fallback: check if we're in a development-like environment\r\n if (typeof window !== 'undefined') {\r\n // Check for common dev indicators\r\n const hostname = window.location.hostname\r\n if (hostname === 'localhost' || hostname === '127.0.0.1' || hostname.startsWith('192.168.')) {\r\n return true\r\n }\r\n }\r\n \r\n return false\r\n}\r\n\r\n/**\r\n * Creates the breakpoint helper HTML element\r\n */\r\nfunction createBreakpointHelperElement(): HTMLElement {\r\n const container = document.createElement('div')\r\n container.id = 'breakpoint-helper'\r\n container.className = 'breakpoint-helper'\r\n container.setAttribute('style', 'display: none')\r\n \r\n const content = document.createElement('div')\r\n content.className = 'breakpoint-helper-content'\r\n \r\n // Base breakpoint\r\n const baseSpan = document.createElement('span')\r\n baseSpan.className = 'breakpoint-helper-label breakpoint-helper-base'\r\n baseSpan.innerHTML = '<strong class=\"breakpoint-helper-badge\">base</strong> 32rem (512px) @media (width >= 32rem)'\r\n \r\n // SM breakpoint\r\n const smSpan = document.createElement('span')\r\n smSpan.className = 'breakpoint-helper-label breakpoint-helper-sm'\r\n smSpan.innerHTML = '<strong class=\"breakpoint-helper-badge\">sm</strong> 40rem (640px) @media (width >= 40rem)'\r\n \r\n // MD breakpoint\r\n const mdSpan = document.createElement('span')\r\n mdSpan.className = 'breakpoint-helper-label breakpoint-helper-md'\r\n mdSpan.innerHTML = '<strong class=\"breakpoint-helper-badge\">md</strong> 48rem (768px) @media (width >= 48rem)'\r\n \r\n // LG breakpoint\r\n const lgSpan = document.createElement('span')\r\n lgSpan.className = 'breakpoint-helper-label breakpoint-helper-lg'\r\n lgSpan.innerHTML = '<strong class=\"breakpoint-helper-badge\">lg</strong> 64rem (1024px) @media (width >= 64rem)'\r\n \r\n // XL breakpoint\r\n const xlSpan = document.createElement('span')\r\n xlSpan.className = 'breakpoint-helper-label breakpoint-helper-xl'\r\n xlSpan.innerHTML = '<strong class=\"breakpoint-helper-badge\">xl</strong> 80rem (1280px) @media (width >= 80rem)'\r\n \r\n // 2XL breakpoint\r\n const xl2Span = document.createElement('span')\r\n xl2Span.className = 'breakpoint-helper-label breakpoint-helper-2xl'\r\n xl2Span.innerHTML = '<strong class=\"breakpoint-helper-badge\">2xl</strong> 96rem (1536px) @media (width >= 96rem)'\r\n \r\n content.appendChild(baseSpan)\r\n content.appendChild(smSpan)\r\n content.appendChild(mdSpan)\r\n content.appendChild(lgSpan)\r\n content.appendChild(xlSpan)\r\n content.appendChild(xl2Span)\r\n \r\n // Hide button\r\n const hideButton = document.createElement('button')\r\n hideButton.id = 'breakpoint-helper-hide-btn'\r\n hideButton.type = 'button'\r\n hideButton.className = 'breakpoint-helper-hide-btn'\r\n hideButton.setAttribute('aria-label', 'Skrýt breakpoint helper na 20 sekund')\r\n \r\n hideButton.innerHTML = `\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"breakpoint-helper-icon\">\r\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M12 6v6h4.5m4.5 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z\" />\r\n </svg>\r\n `\r\n \r\n content.appendChild(hideButton)\r\n container.appendChild(content)\r\n \r\n return container\r\n}\r\n\r\n/**\r\n * Initializes the breakpoint helper\r\n */\r\nexport function initBreakpointHelper(options: BreakpointHelperOptions = {}): void {\r\n const opts = {\r\n ...DEFAULT_OPTIONS,\r\n ...options\r\n }\r\n \r\n // Determine if enabled\r\n const enabled = opts.enabled !== undefined ? opts.enabled : isDevMode()\r\n \r\n if (!enabled) {\r\n return\r\n }\r\n \r\n // Check if element already exists or use custom selector\r\n let breakpointHelper: HTMLElement | null = null\r\n \r\n if (opts.containerSelector) {\r\n breakpointHelper = document.querySelector(opts.containerSelector)\r\n } else {\r\n breakpointHelper = document.getElementById('breakpoint-helper')\r\n }\r\n \r\n // Create element if it doesn't exist\r\n if (!breakpointHelper) {\r\n breakpointHelper = createBreakpointHelperElement()\r\n document.body.appendChild(breakpointHelper)\r\n }\r\n \r\n // Show the helper\r\n breakpointHelper.style.display = 'block'\r\n \r\n // Setup hide button functionality\r\n const hideButton = breakpointHelper.querySelector('#breakpoint-helper-hide-btn') as HTMLButtonElement | null\r\n \r\n if (hideButton) {\r\n hideButton.addEventListener('click', () => {\r\n if (breakpointHelper) {\r\n breakpointHelper.style.display = 'none'\r\n \r\n setTimeout(() => {\r\n if (breakpointHelper) {\r\n breakpointHelper.style.display = 'block'\r\n }\r\n }, opts.hideDuration)\r\n }\r\n })\r\n }\r\n}\r\n\r\n/**\r\n * Auto-initialize if imported directly (for convenience)\r\n */\r\nif (typeof window !== 'undefined') {\r\n // Only auto-init in browser environment\r\n // Check if we should auto-init (dev mode)\r\n if (isDevMode()) {\r\n // Use requestAnimationFrame to ensure DOM is ready\r\n if (document.readyState === 'loading') {\r\n document.addEventListener('DOMContentLoaded', () => {\r\n initBreakpointHelper()\r\n })\r\n } else {\r\n initBreakpointHelper()\r\n }\r\n }\r\n}\r\n"],"names":["DEFAULT_OPTIONS","isDevMode","meta","_documentCurrentScript","hostname","createBreakpointHelperElement","container","content","baseSpan","smSpan","mdSpan","lgSpan","xlSpan","xl2Span","hideButton","initBreakpointHelper","options","opts","breakpointHelper"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["/** Breakpoint value in original form (e.g. \"40rem\", \"1280px\") */\r\nexport type BreakpointsMap = Record<string, string>\r\n\r\nexport interface ResolvedBreakpoint {\r\n name: string\r\n valuePx: number\r\n originalValue: string\r\n}\r\n\r\nexport interface BreakpointHelperOptions {\r\n /**\r\n * Whether the helper is enabled. If not provided, will try to detect dev mode.\r\n * @default undefined (auto-detect)\r\n */\r\n enabled?: boolean\r\n\r\n /**\r\n * Duration in milliseconds to hide the helper when hide button is clicked.\r\n * @default 20000 (20 seconds)\r\n */\r\n hideDuration?: number\r\n\r\n /**\r\n * Custom container selector. If provided, will use existing element instead of creating one.\r\n * @default undefined (creates new element)\r\n */\r\n containerSelector?: string\r\n\r\n /**\r\n * Custom breakpoint names + values added to defaults and CSS detection.\r\n * Use for extra names (4xl, desktop, …) or as fallback when CSS detection fails (e.g. Vue/Vite).\r\n * In Tailwind v3, use this for custom screens (xs, 3xl) from theme.extend.screens.\r\n * @example { xs: '30rem', '3xl': '120rem', desktop: '64rem' }\r\n */\r\n customBreakpoints?: BreakpointsMap\r\n\r\n /**\r\n * Label for the \"base\" range (below first breakpoint). Use string to rename, or false to hide base row.\r\n * @default 'base'\r\n */\r\n baseLabel?: string | false\r\n\r\n /**\r\n * Enable debug output in console.\r\n * @default false\r\n */\r\n debug?: boolean\r\n}\r\n\r\nconst DEFAULT_OPTIONS: Required<Omit<BreakpointHelperOptions, 'enabled' | 'containerSelector' | 'customBreakpoints' | 'baseLabel' | 'debug'>> = {\r\n hideDuration: 20000\r\n}\r\n\r\nconst DEBUG_PREFIX = '[breakpoint-indicator]'\r\n\r\n/** Standard Tailwind breakpoints (sm–2xl). Custom names (xs, 3xl, 4xl, …) are detected from CSS. */\r\nconst DEFAULT_BREAKPOINTS: BreakpointsMap = {\r\n sm: '40rem',\r\n md: '48rem',\r\n lg: '64rem',\r\n xl: '80rem',\r\n '2xl': '96rem'\r\n}\r\n\r\n/** Names we know to look for in project CSS (--breakpoint-xs etc.). Documented for users. */\r\nexport const DETECTABLE_CUSTOM_NAMES = ['xs', '3xl', '4xl'] as const\r\n\r\n/** Container background colors by breakpoint index (base, xs, sm, md, …) */\r\nconst BREAKPOINT_COLORS = [\r\n '#ef4444', /* red - base */\r\n '#22c55e', /* green */\r\n '#3b82f6', /* blue */\r\n '#eab308', /* yellow */\r\n '#a855f7', /* purple */\r\n '#ec4899' /* pink */\r\n]\r\n\r\ntype HelperState = {\r\n resizeHandler?: () => void\r\n hideHandler?: () => void\r\n signature?: string\r\n}\r\n\r\nconst HELPER_STATE = new WeakMap<HTMLElement, HelperState>()\r\n\r\nfunction getRootFontSizePx(): number {\r\n if (typeof document === 'undefined') return 16\r\n const root = document.documentElement\r\n const computed = getComputedStyle(root).fontSize\r\n const parsed = parseFloat(computed)\r\n return Number.isNaN(parsed) ? 16 : parsed\r\n}\r\n\r\n/**\r\n * Try to resolve an arbitrary CSS length to pixels using layout measurement.\r\n */\r\nfunction measureCssLengthPx(value: string): number {\r\n if (typeof document === 'undefined') return 0\r\n const el = document.createElement('div')\r\n el.style.position = 'fixed'\r\n el.style.left = '-9999px'\r\n el.style.top = '0'\r\n el.style.visibility = 'hidden'\r\n el.style.pointerEvents = 'none'\r\n el.style.width = value\r\n el.style.height = '0'\r\n el.style.padding = '0'\r\n el.style.margin = '0'\r\n el.style.border = '0'\r\n el.style.boxSizing = 'content-box'\r\n\r\n document.documentElement.appendChild(el)\r\n const px = el.getBoundingClientRect().width\r\n el.remove()\r\n return Number.isFinite(px) ? px : 0\r\n}\r\n\r\n/**\r\n * Parse a breakpoint value (e.g. \"40rem\", \"1280px\") to pixels.\r\n */\r\nfunction parseBreakpointValue(value: string, rootFontSizePx: number): number {\r\n const trimmed = value.trim()\r\n const match = trimmed.match(/^(-?\\d*\\.?\\d+)(rem|em|px)$/i)\r\n if (!match) {\r\n return measureCssLengthPx(trimmed)\r\n }\r\n const num = parseFloat(match[1])\r\n const unit = (match[2] || '').toLowerCase()\r\n if (unit === 'px') return num\r\n if (unit === 'rem' || unit === 'em') return num * rootFontSizePx\r\n return 0\r\n}\r\n\r\nconst BREAKPOINT_RE = /--breakpoint-([a-zA-Z0-9_-]+)\\s*:\\s*([^;]+)/g\r\n\r\n/**\r\n * Read --breakpoint-* custom properties from the document (Tailwind v4 @theme).\r\n * Returns only custom breakpoints found in CSS (xs, 3xl, 4xl, desktop, …).\r\n * Merged with DEFAULT_BREAKPOINTS so project gets defaults + any extra it defines.\r\n */\r\nfunction getBreakpointsFromCss(): BreakpointsMap {\r\n const result: BreakpointsMap = {}\r\n if (typeof document === 'undefined') return result\r\n\r\n const collectFromRule = (rule: CSSRule & { style?: CSSStyleDeclaration; cssRules?: CSSRuleList; styleSheet?: { cssRules?: CSSRuleList } }): void => {\r\n try {\r\n if (rule.style) {\r\n for (let k = 0; k < (rule.style.length || 0); k++) {\r\n const prop = rule.style.item(k)\r\n if (prop?.startsWith('--breakpoint-')) {\r\n const name = prop.slice('--breakpoint-'.length)\r\n const val = rule.style.getPropertyValue(prop).trim()\r\n if (name && val) result[name] = val\r\n }\r\n }\r\n }\r\n if (rule.cssRules) {\r\n for (let i = 0; i < rule.cssRules.length; i++) {\r\n collectFromRule(rule.cssRules[i] as CSSRule & { style?: CSSStyleDeclaration; cssRules?: CSSRuleList })\r\n }\r\n }\r\n if (rule.styleSheet?.cssRules) {\r\n for (let i = 0; i < rule.styleSheet.cssRules.length; i++) {\r\n collectFromRule(rule.styleSheet.cssRules[i] as CSSRule & { style?: CSSStyleDeclaration; cssRules?: CSSRuleList; styleSheet?: { cssRules?: CSSRuleList } })\r\n }\r\n }\r\n } catch { /* cross-origin */ }\r\n }\r\n\r\n const origin = typeof location !== 'undefined' ? location.origin : ''\r\n for (let i = 0; i < document.styleSheets.length; i++) {\r\n const sheet = document.styleSheets[i] as CSSStyleSheet & { href?: string }\r\n if (sheet.href && origin && !sheet.href.startsWith(origin)) continue\r\n try {\r\n if (sheet.cssRules) {\r\n for (let j = 0; j < sheet.cssRules.length; j++) {\r\n collectFromRule(sheet.cssRules[j] as CSSRule & { style?: CSSStyleDeclaration; cssRules?: CSSRuleList; styleSheet?: { cssRules?: CSSRuleList } })\r\n }\r\n }\r\n } catch { /* cross-origin */ }\r\n }\r\n\r\n // Fallback: parse <style> textContent (Vite may use insertRule so cssRules has data but we also try text)\r\n for (const el of document.querySelectorAll('style')) {\r\n const text = el.textContent || ''\r\n let m: RegExpExecArray | null\r\n BREAKPOINT_RE.lastIndex = 0\r\n while ((m = BREAKPOINT_RE.exec(text)) !== null) {\r\n const name = m[1]\r\n const val = m[2].replace(/\\/\\*[\\s\\S]*?\\*\\//g, '').trim()\r\n if (name && val && !result[name]) result[name] = val\r\n }\r\n }\r\n\r\n return result\r\n}\r\n\r\n/**\r\n * Resolve breakpoints: defaults + detected from CSS + customBreakpoints.\r\n * Returns sorted list including optional base row.\r\n */\r\nfunction resolveBreakpoints(options: BreakpointHelperOptions): ResolvedBreakpoint[] {\r\n const baseLabel = options.baseLabel === undefined ? 'base' : options.baseLabel\r\n const rootFontSizePx = getRootFontSizePx()\r\n\r\n const customBreakpoints = options.customBreakpoints && Object.keys(options.customBreakpoints).length > 0 ? options.customBreakpoints : {}\r\n const raw: BreakpointsMap = { ...DEFAULT_BREAKPOINTS, ...getBreakpointsFromCss(), ...customBreakpoints }\r\n\r\n const listWithIndex: Array<ResolvedBreakpoint & { _i: number }> = []\r\n let idx = 0\r\n for (const [name, originalValue] of Object.entries(raw)) {\r\n const valuePx = parseBreakpointValue(originalValue, rootFontSizePx)\r\n if (!Number.isFinite(valuePx) || valuePx <= 0) {\r\n idx++\r\n continue\r\n }\r\n listWithIndex.push({ name, valuePx, originalValue, _i: idx })\r\n idx++\r\n }\r\n listWithIndex.sort((a, b) => (a.valuePx - b.valuePx) || (a._i - b._i))\r\n const list: ResolvedBreakpoint[] = listWithIndex.map(({ _i, ...bp }) => bp)\r\n\r\n const firstPx = list.length > 0 ? list[0].valuePx : 640\r\n if (baseLabel !== false) {\r\n list.unshift({\r\n name: baseLabel,\r\n valuePx: 0,\r\n originalValue: `0 – ${firstPx}px`\r\n })\r\n }\r\n\r\n return list\r\n}\r\n\r\nfunction breakpointNameToClass(name: string): string {\r\n return name\r\n .trim()\r\n .replace(/\\s+/g, '-')\r\n .replace(/[^a-z0-9_-]/gi, '-')\r\n .toLowerCase()\r\n}\r\n\r\nfunction isDevMode(): boolean {\r\n const meta = import.meta as { env?: { DEV?: boolean } }\r\n if (typeof import.meta !== 'undefined' && meta.env?.DEV) return true\r\n\r\n if (typeof globalThis !== 'undefined') {\r\n const proc = (globalThis as unknown as { process?: { env?: { NODE_ENV?: string } } }).process\r\n if (proc?.env?.NODE_ENV === 'development') return true\r\n }\r\n\r\n if (typeof window !== 'undefined') {\r\n const hostname = window.location.hostname\r\n if (hostname === 'localhost' || hostname === '127.0.0.1' || hostname.startsWith('192.168.')) {\r\n return true\r\n }\r\n }\r\n\r\n return false\r\n}\r\n\r\nfunction getActiveBreakpointIndex(resolved: ResolvedBreakpoint[], widthPx: number): number {\r\n let index = 0\r\n for (let i = 0; i < resolved.length; i++) {\r\n if (widthPx >= resolved[i].valuePx) index = i\r\n }\r\n return index\r\n}\r\n\r\nfunction updateActiveBreakpoint(\r\n container: HTMLElement,\r\n resolved: ResolvedBreakpoint[],\r\n content: HTMLElement\r\n): void {\r\n const width = typeof window !== 'undefined' ? window.innerWidth : 0\r\n const index = getActiveBreakpointIndex(resolved, width)\r\n const color = BREAKPOINT_COLORS[index % BREAKPOINT_COLORS.length]\r\n container.style.backgroundColor = color\r\n\r\n const labels = content.querySelectorAll('.breakpoint-helper-label')\r\n labels.forEach((el, i) => {\r\n el.classList.toggle('breakpoint-helper-active', i === index)\r\n })\r\n}\r\n\r\nfunction createBreakpointHelperElement(resolved: ResolvedBreakpoint[]): HTMLElement {\r\n const container = document.createElement('div')\r\n container.id = 'breakpoint-helper'\r\n container.className = 'breakpoint-helper'\r\n container.setAttribute('style', 'display: none')\r\n\r\n const content = buildBreakpointHelperContent(resolved)\r\n container.appendChild(content)\r\n\r\n updateActiveBreakpoint(container, resolved, content)\r\n return container\r\n}\r\n\r\nfunction buildBreakpointHelperContent(resolved: ResolvedBreakpoint[]): HTMLElement {\r\n const content = document.createElement('div')\r\n content.className = 'breakpoint-helper-content'\r\n\r\n for (let i = 0; i < resolved.length; i++) {\r\n const bp = resolved[i]\r\n const span = document.createElement('span')\r\n const classBase = breakpointNameToClass(bp.name)\r\n span.className = `breakpoint-helper-label breakpoint-helper-${classBase}`\r\n span.setAttribute('data-breakpoint-px', String(bp.valuePx))\r\n span.setAttribute('data-breakpoint-name', bp.name)\r\n\r\n const valueDisplay = bp.valuePx === 0\r\n ? bp.originalValue\r\n : `${bp.originalValue} (${Math.round(bp.valuePx)}px)`\r\n const mediaPart = bp.valuePx === 0\r\n ? `@media (width < ${resolved[1]?.originalValue ?? '40rem'})`\r\n : `@media (width >= ${bp.originalValue})`\r\n span.innerHTML = `<strong class=\"breakpoint-helper-badge\">${escapeHtml(bp.name)}</strong> ${escapeHtml(valueDisplay)} ${mediaPart}`\r\n content.appendChild(span)\r\n }\r\n\r\n const hideButton = document.createElement('button')\r\n hideButton.id = 'breakpoint-helper-hide-btn'\r\n hideButton.type = 'button'\r\n hideButton.className = 'breakpoint-helper-hide-btn'\r\n hideButton.setAttribute('aria-label', 'Hide breakpoint helper for 20 seconds')\r\n hideButton.innerHTML = `\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"breakpoint-helper-icon\">\r\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M12 6v6h4.5m4.5 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z\" />\r\n </svg>\r\n `\r\n content.appendChild(hideButton)\r\n\r\n return content\r\n}\r\n\r\nfunction escapeHtml(text: string): string {\r\n const div = document.createElement('div')\r\n div.textContent = text\r\n return div.innerHTML\r\n}\r\n\r\n/**\r\n * Initializes the breakpoint helper\r\n */\r\nexport function initBreakpointHelper(options: BreakpointHelperOptions = {}): void {\r\n if (typeof window === 'undefined' || typeof document === 'undefined') return\r\n\r\n const opts = { ...DEFAULT_OPTIONS, ...options }\r\n\r\n const enabled = opts.enabled !== undefined ? opts.enabled : isDevMode()\r\n if (!enabled) {\r\n const existing = document.getElementById('breakpoint-helper')\r\n if (existing) existing.style.display = 'none'\r\n return\r\n }\r\n\r\n const debug = opts.debug === true\r\n\r\n const customBreakpoints = opts.customBreakpoints && Object.keys(opts.customBreakpoints).length > 0 ? opts.customBreakpoints : {}\r\n\r\n if (debug) {\r\n const fromCss = getBreakpointsFromCss()\r\n console.log(DEBUG_PREFIX, 'From CSS (--breakpoint-*):', fromCss)\r\n if (Object.keys(fromCss).length === 0 && Object.keys(customBreakpoints).length === 0) {\r\n console.log(DEBUG_PREFIX, 'No custom breakpoints in CSS. Use customBreakpoints in initBreakpointHelper() for extra names or fallback.')\r\n }\r\n }\r\n\r\n const resolved = resolveBreakpoints(opts)\r\n const signature = JSON.stringify(resolved.map((bp) => [bp.name, bp.originalValue]))\r\n\r\n if (debug) {\r\n const source = Object.keys(customBreakpoints).length > 0 ? 'defaults + CSS + customBreakpoints' : 'defaults + CSS'\r\n if (Object.keys(customBreakpoints).length > 0) {\r\n console.log(DEBUG_PREFIX, 'customBreakpoints:', customBreakpoints)\r\n }\r\n console.log(DEBUG_PREFIX, 'Breakpoint source:', source)\r\n console.log(\r\n DEBUG_PREFIX,\r\n 'Resolved breakpoints:',\r\n resolved.map((bp) => `${bp.name} (${bp.originalValue})`).join(', ')\r\n )\r\n }\r\n\r\n let breakpointHelper: HTMLElement | null = null\r\n if (opts.containerSelector) {\r\n breakpointHelper = document.querySelector(opts.containerSelector) as HTMLElement | null\r\n } else {\r\n breakpointHelper = document.getElementById('breakpoint-helper')\r\n }\r\n\r\n if (!breakpointHelper) {\r\n breakpointHelper = createBreakpointHelperElement(resolved)\r\n document.body.appendChild(breakpointHelper)\r\n } else {\r\n if (!breakpointHelper.classList.contains('breakpoint-helper')) {\r\n breakpointHelper.classList.add('breakpoint-helper')\r\n }\r\n }\r\n\r\n breakpointHelper.style.display = 'block'\r\n\r\n const state: HelperState = HELPER_STATE.get(breakpointHelper) ?? {}\r\n\r\n if (state.resizeHandler) {\r\n window.removeEventListener('resize', state.resizeHandler)\r\n state.resizeHandler = undefined\r\n }\r\n\r\n const existingContent = breakpointHelper.querySelector('.breakpoint-helper-content') as HTMLElement | null\r\n if (!existingContent || state.signature !== signature) {\r\n if (existingContent) existingContent.remove()\r\n breakpointHelper.appendChild(buildBreakpointHelperContent(resolved))\r\n state.signature = signature\r\n }\r\n\r\n const contentEl = breakpointHelper.querySelector('.breakpoint-helper-content') as HTMLElement | null\r\n if (contentEl) updateActiveBreakpoint(breakpointHelper, resolved, contentEl)\r\n\r\n const resizeHandler = (): void => {\r\n const content = breakpointHelper?.querySelector('.breakpoint-helper-content') as HTMLElement | null\r\n if (breakpointHelper && content) updateActiveBreakpoint(breakpointHelper, resolved, content)\r\n }\r\n state.resizeHandler = resizeHandler\r\n window.addEventListener('resize', resizeHandler)\r\n\r\n const hideButton = breakpointHelper.querySelector('#breakpoint-helper-hide-btn') as HTMLButtonElement | null\r\n if (hideButton) {\r\n if (state.hideHandler) {\r\n hideButton.removeEventListener('click', state.hideHandler)\r\n state.hideHandler = undefined\r\n }\r\n const hideHandler = (): void => {\r\n breakpointHelper!.style.display = 'none'\r\n window.setTimeout(() => {\r\n breakpointHelper!.style.display = 'block'\r\n }, opts.hideDuration)\r\n }\r\n state.hideHandler = hideHandler\r\n hideButton.addEventListener('click', hideHandler)\r\n }\r\n\r\n HELPER_STATE.set(breakpointHelper, state)\r\n}\r\n\r\n/**\r\n * Returns the default breakpoints. Useful for debugging or when building custom options.\r\n */\r\nexport function getDefaultBreakpoints(): BreakpointsMap {\r\n return { ...DEFAULT_BREAKPOINTS }\r\n}\r\n\r\n/**\r\n * Auto-initialize if imported directly (for convenience)\r\n */\r\nif (typeof window !== 'undefined') {\r\n if (isDevMode()) {\r\n if (document.readyState === 'loading') {\r\n document.addEventListener('DOMContentLoaded', () => initBreakpointHelper())\r\n } else {\r\n initBreakpointHelper()\r\n }\r\n }\r\n}\r\n"],"names":["DEFAULT_OPTIONS","DEBUG_PREFIX","DEFAULT_BREAKPOINTS","DETECTABLE_CUSTOM_NAMES","BREAKPOINT_COLORS","HELPER_STATE","getRootFontSizePx","root","computed","parsed","measureCssLengthPx","value","el","px","parseBreakpointValue","rootFontSizePx","trimmed","match","num","unit","BREAKPOINT_RE","getBreakpointsFromCss","result","collectFromRule","rule","k","prop","name","val","i","origin","sheet","j","text","m","resolveBreakpoints","options","baseLabel","customBreakpoints","raw","listWithIndex","idx","originalValue","valuePx","a","b","list","_i","bp","firstPx","breakpointNameToClass","isDevMode","meta","_documentCurrentScript","hostname","getActiveBreakpointIndex","resolved","widthPx","index","updateActiveBreakpoint","container","content","width","color","createBreakpointHelperElement","buildBreakpointHelperContent","span","classBase","valueDisplay","mediaPart","escapeHtml","hideButton","div","initBreakpointHelper","opts","existing","debug","fromCss","signature","source","breakpointHelper","state","existingContent","contentEl","resizeHandler","hideHandler","getDefaultBreakpoints"],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
(function(f,d){typeof exports=="object"&&typeof module<"u"?d(exports):typeof define=="function"&&define.amd?define(["exports"],d):(f=typeof globalThis<"u"?globalThis:f||self,d(f.TailwindBreakpointIndicator={}))})(this,(function(f){"use strict";var d=typeof document<"u"?document.currentScript:null;const L={hideDuration:2e4},h="[breakpoint-indicator]",k={sm:"40rem",md:"48rem",lg:"64rem",xl:"80rem","2xl":"96rem"},R=["xs","3xl","4xl"],v=["#ef4444","#22c55e","#3b82f6","#eab308","#a855f7","#ec4899"],x=new WeakMap;function P(){if(typeof document>"u")return 16;const n=document.documentElement,e=getComputedStyle(n).fontSize,s=parseFloat(e);return Number.isNaN(s)?16:s}function H(n){if(typeof document>"u")return 0;const e=document.createElement("div");e.style.position="fixed",e.style.left="-9999px",e.style.top="0",e.style.visibility="hidden",e.style.pointerEvents="none",e.style.width=n,e.style.height="0",e.style.padding="0",e.style.margin="0",e.style.border="0",e.style.boxSizing="content-box",document.documentElement.appendChild(e);const s=e.getBoundingClientRect().width;return e.remove(),Number.isFinite(s)?s:0}function N(n,e){const s=n.trim(),o=s.match(/^(-?\d*\.?\d+)(rem|em|px)$/i);if(!o)return H(s);const t=parseFloat(o[1]),r=(o[2]||"").toLowerCase();return r==="px"?t:r==="rem"||r==="em"?t*e:0}const S=/--breakpoint-([a-zA-Z0-9_-]+)\s*:\s*([^;]+)/g;function E(){const n={};if(typeof document>"u")return n;const e=o=>{try{if(o.style)for(let t=0;t<(o.style.length||0);t++){const r=o.style.item(t);if(r?.startsWith("--breakpoint-")){const a=r.slice(13),i=o.style.getPropertyValue(r).trim();a&&i&&(n[a]=i)}}if(o.cssRules)for(let t=0;t<o.cssRules.length;t++)e(o.cssRules[t]);if(o.styleSheet?.cssRules)for(let t=0;t<o.styleSheet.cssRules.length;t++)e(o.styleSheet.cssRules[t])}catch{}},s=typeof location<"u"?location.origin:"";for(let o=0;o<document.styleSheets.length;o++){const t=document.styleSheets[o];if(!(t.href&&s&&!t.href.startsWith(s)))try{if(t.cssRules)for(let r=0;r<t.cssRules.length;r++)e(t.cssRules[r])}catch{}}for(const o of document.querySelectorAll("style")){const t=o.textContent||"";let r;for(S.lastIndex=0;(r=S.exec(t))!==null;){const a=r[1],i=r[2].replace(/\/\*[\s\S]*?\*\//g,"").trim();a&&i&&!n[a]&&(n[a]=i)}}return n}function _(n){const e=n.baseLabel===void 0?"base":n.baseLabel,s=P(),o=n.customBreakpoints&&Object.keys(n.customBreakpoints).length>0?n.customBreakpoints:{},t={...k,...E(),...o},r=[];let a=0;for(const[p,u]of Object.entries(t)){const m=N(u,s);if(!Number.isFinite(m)||m<=0){a++;continue}r.push({name:p,valuePx:m,originalValue:u,_i:a}),a++}r.sort((p,u)=>p.valuePx-u.valuePx||p._i-u._i);const i=r.map(({_i:p,...u})=>u),l=i.length>0?i[0].valuePx:640;return e!==!1&&i.unshift({name:e,valuePx:0,originalValue:`0 – ${l}px`}),i}function O(n){return n.trim().replace(/\s+/g,"-").replace(/[^a-z0-9_-]/gi,"-").toLowerCase()}function B(){const n={url:typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:d&&d.tagName.toUpperCase()==="SCRIPT"&&d.src||new URL("index.umd.js",document.baseURI).href};if(typeof{url:typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:d&&d.tagName.toUpperCase()==="SCRIPT"&&d.src||new URL("index.umd.js",document.baseURI).href}<"u"&&n.env?.DEV||typeof globalThis<"u"&&globalThis.process?.env?.NODE_ENV==="development")return!0;if(typeof window<"u"){const e=window.location.hostname;if(e==="localhost"||e==="127.0.0.1"||e.startsWith("192.168."))return!0}return!1}function A(n,e){let s=0;for(let o=0;o<n.length;o++)e>=n[o].valuePx&&(s=o);return s}function b(n,e,s){const o=typeof window<"u"?window.innerWidth:0,t=A(e,o),r=v[t%v.length];n.style.backgroundColor=r,s.querySelectorAll(".breakpoint-helper-label").forEach((i,l)=>{i.classList.toggle("breakpoint-helper-active",l===t)})}function I(n){const e=document.createElement("div");e.id="breakpoint-helper",e.className="breakpoint-helper",e.setAttribute("style","display: none");const s=w(n);return e.appendChild(s),b(e,n,s),e}function w(n){const e=document.createElement("div");e.className="breakpoint-helper-content";for(let o=0;o<n.length;o++){const t=n[o],r=document.createElement("span"),a=O(t.name);r.className=`breakpoint-helper-label breakpoint-helper-${a}`,r.setAttribute("data-breakpoint-px",String(t.valuePx)),r.setAttribute("data-breakpoint-name",t.name);const i=t.valuePx===0?t.originalValue:`${t.originalValue} (${Math.round(t.valuePx)}px)`,l=t.valuePx===0?`@media (width < ${n[1]?.originalValue??"40rem"})`:`@media (width >= ${t.originalValue})`;r.innerHTML=`<strong class="breakpoint-helper-badge">${C(t.name)}</strong> ${C(i)} ${l}`,e.appendChild(r)}const s=document.createElement("button");return s.id="breakpoint-helper-hide-btn",s.type="button",s.className="breakpoint-helper-hide-btn",s.setAttribute("aria-label","Hide breakpoint helper for 20 seconds"),s.innerHTML=`
|
|
2
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="breakpoint-helper-icon">
|
|
3
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6v6h4.5m4.5 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
|
|
4
|
+
</svg>
|
|
5
|
+
`,e.appendChild(s),e}function C(n){const e=document.createElement("div");return e.textContent=n,e.innerHTML}function g(n={}){if(typeof window>"u"||typeof document>"u")return;const e={...L,...n};if(!(e.enabled!==void 0?e.enabled:B())){const c=document.getElementById("breakpoint-helper");c&&(c.style.display="none");return}const o=e.debug===!0,t=e.customBreakpoints&&Object.keys(e.customBreakpoints).length>0?e.customBreakpoints:{};if(o){const c=E();console.log(h,"From CSS (--breakpoint-*):",c),Object.keys(c).length===0&&Object.keys(t).length===0&&console.log(h,"No custom breakpoints in CSS. Use customBreakpoints in initBreakpointHelper() for extra names or fallback.")}const r=_(e),a=JSON.stringify(r.map(c=>[c.name,c.originalValue]));if(o){const c=Object.keys(t).length>0?"defaults + CSS + customBreakpoints":"defaults + CSS";Object.keys(t).length>0&&console.log(h,"customBreakpoints:",t),console.log(h,"Breakpoint source:",c),console.log(h,"Resolved breakpoints:",r.map(T=>`${T.name} (${T.originalValue})`).join(", "))}let i=null;e.containerSelector?i=document.querySelector(e.containerSelector):i=document.getElementById("breakpoint-helper"),i?i.classList.contains("breakpoint-helper")||i.classList.add("breakpoint-helper"):(i=I(r),document.body.appendChild(i)),i.style.display="block";const l=x.get(i)??{};l.resizeHandler&&(window.removeEventListener("resize",l.resizeHandler),l.resizeHandler=void 0);const p=i.querySelector(".breakpoint-helper-content");(!p||l.signature!==a)&&(p&&p.remove(),i.appendChild(w(r)),l.signature=a);const u=i.querySelector(".breakpoint-helper-content");u&&b(i,r,u);const m=()=>{const c=i?.querySelector(".breakpoint-helper-content");i&&c&&b(i,r,c)};l.resizeHandler=m,window.addEventListener("resize",m);const y=i.querySelector("#breakpoint-helper-hide-btn");if(y){l.hideHandler&&(y.removeEventListener("click",l.hideHandler),l.hideHandler=void 0);const c=()=>{i.style.display="none",window.setTimeout(()=>{i.style.display="block"},e.hideDuration)};l.hideHandler=c,y.addEventListener("click",c)}x.set(i,l)}function j(){return{...k}}typeof window<"u"&&B()&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>g()):g()),f.DETECTABLE_CUSTOM_NAMES=R,f.getDefaultBreakpoints=j,f.initBreakpointHelper=g,Object.defineProperty(f,Symbol.toStringTag,{value:"Module"})}));
|
|
6
|
+
//# sourceMappingURL=index.umd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.umd.js","sources":["../src/index.ts"],"sourcesContent":["/** Breakpoint value in original form (e.g. \"40rem\", \"1280px\") */\r\nexport type BreakpointsMap = Record<string, string>\r\n\r\nexport interface ResolvedBreakpoint {\r\n name: string\r\n valuePx: number\r\n originalValue: string\r\n}\r\n\r\nexport interface BreakpointHelperOptions {\r\n /**\r\n * Whether the helper is enabled. If not provided, will try to detect dev mode.\r\n * @default undefined (auto-detect)\r\n */\r\n enabled?: boolean\r\n\r\n /**\r\n * Duration in milliseconds to hide the helper when hide button is clicked.\r\n * @default 20000 (20 seconds)\r\n */\r\n hideDuration?: number\r\n\r\n /**\r\n * Custom container selector. If provided, will use existing element instead of creating one.\r\n * @default undefined (creates new element)\r\n */\r\n containerSelector?: string\r\n\r\n /**\r\n * Custom breakpoint names + values added to defaults and CSS detection.\r\n * Use for extra names (4xl, desktop, …) or as fallback when CSS detection fails (e.g. Vue/Vite).\r\n * In Tailwind v3, use this for custom screens (xs, 3xl) from theme.extend.screens.\r\n * @example { xs: '30rem', '3xl': '120rem', desktop: '64rem' }\r\n */\r\n customBreakpoints?: BreakpointsMap\r\n\r\n /**\r\n * Label for the \"base\" range (below first breakpoint). Use string to rename, or false to hide base row.\r\n * @default 'base'\r\n */\r\n baseLabel?: string | false\r\n\r\n /**\r\n * Enable debug output in console.\r\n * @default false\r\n */\r\n debug?: boolean\r\n}\r\n\r\nconst DEFAULT_OPTIONS: Required<Omit<BreakpointHelperOptions, 'enabled' | 'containerSelector' | 'customBreakpoints' | 'baseLabel' | 'debug'>> = {\r\n hideDuration: 20000\r\n}\r\n\r\nconst DEBUG_PREFIX = '[breakpoint-indicator]'\r\n\r\n/** Standard Tailwind breakpoints (sm–2xl). Custom names (xs, 3xl, 4xl, …) are detected from CSS. */\r\nconst DEFAULT_BREAKPOINTS: BreakpointsMap = {\r\n sm: '40rem',\r\n md: '48rem',\r\n lg: '64rem',\r\n xl: '80rem',\r\n '2xl': '96rem'\r\n}\r\n\r\n/** Names we know to look for in project CSS (--breakpoint-xs etc.). Documented for users. */\r\nexport const DETECTABLE_CUSTOM_NAMES = ['xs', '3xl', '4xl'] as const\r\n\r\n/** Container background colors by breakpoint index (base, xs, sm, md, …) */\r\nconst BREAKPOINT_COLORS = [\r\n '#ef4444', /* red - base */\r\n '#22c55e', /* green */\r\n '#3b82f6', /* blue */\r\n '#eab308', /* yellow */\r\n '#a855f7', /* purple */\r\n '#ec4899' /* pink */\r\n]\r\n\r\ntype HelperState = {\r\n resizeHandler?: () => void\r\n hideHandler?: () => void\r\n signature?: string\r\n}\r\n\r\nconst HELPER_STATE = new WeakMap<HTMLElement, HelperState>()\r\n\r\nfunction getRootFontSizePx(): number {\r\n if (typeof document === 'undefined') return 16\r\n const root = document.documentElement\r\n const computed = getComputedStyle(root).fontSize\r\n const parsed = parseFloat(computed)\r\n return Number.isNaN(parsed) ? 16 : parsed\r\n}\r\n\r\n/**\r\n * Try to resolve an arbitrary CSS length to pixels using layout measurement.\r\n */\r\nfunction measureCssLengthPx(value: string): number {\r\n if (typeof document === 'undefined') return 0\r\n const el = document.createElement('div')\r\n el.style.position = 'fixed'\r\n el.style.left = '-9999px'\r\n el.style.top = '0'\r\n el.style.visibility = 'hidden'\r\n el.style.pointerEvents = 'none'\r\n el.style.width = value\r\n el.style.height = '0'\r\n el.style.padding = '0'\r\n el.style.margin = '0'\r\n el.style.border = '0'\r\n el.style.boxSizing = 'content-box'\r\n\r\n document.documentElement.appendChild(el)\r\n const px = el.getBoundingClientRect().width\r\n el.remove()\r\n return Number.isFinite(px) ? px : 0\r\n}\r\n\r\n/**\r\n * Parse a breakpoint value (e.g. \"40rem\", \"1280px\") to pixels.\r\n */\r\nfunction parseBreakpointValue(value: string, rootFontSizePx: number): number {\r\n const trimmed = value.trim()\r\n const match = trimmed.match(/^(-?\\d*\\.?\\d+)(rem|em|px)$/i)\r\n if (!match) {\r\n return measureCssLengthPx(trimmed)\r\n }\r\n const num = parseFloat(match[1])\r\n const unit = (match[2] || '').toLowerCase()\r\n if (unit === 'px') return num\r\n if (unit === 'rem' || unit === 'em') return num * rootFontSizePx\r\n return 0\r\n}\r\n\r\nconst BREAKPOINT_RE = /--breakpoint-([a-zA-Z0-9_-]+)\\s*:\\s*([^;]+)/g\r\n\r\n/**\r\n * Read --breakpoint-* custom properties from the document (Tailwind v4 @theme).\r\n * Returns only custom breakpoints found in CSS (xs, 3xl, 4xl, desktop, …).\r\n * Merged with DEFAULT_BREAKPOINTS so project gets defaults + any extra it defines.\r\n */\r\nfunction getBreakpointsFromCss(): BreakpointsMap {\r\n const result: BreakpointsMap = {}\r\n if (typeof document === 'undefined') return result\r\n\r\n const collectFromRule = (rule: CSSRule & { style?: CSSStyleDeclaration; cssRules?: CSSRuleList; styleSheet?: { cssRules?: CSSRuleList } }): void => {\r\n try {\r\n if (rule.style) {\r\n for (let k = 0; k < (rule.style.length || 0); k++) {\r\n const prop = rule.style.item(k)\r\n if (prop?.startsWith('--breakpoint-')) {\r\n const name = prop.slice('--breakpoint-'.length)\r\n const val = rule.style.getPropertyValue(prop).trim()\r\n if (name && val) result[name] = val\r\n }\r\n }\r\n }\r\n if (rule.cssRules) {\r\n for (let i = 0; i < rule.cssRules.length; i++) {\r\n collectFromRule(rule.cssRules[i] as CSSRule & { style?: CSSStyleDeclaration; cssRules?: CSSRuleList })\r\n }\r\n }\r\n if (rule.styleSheet?.cssRules) {\r\n for (let i = 0; i < rule.styleSheet.cssRules.length; i++) {\r\n collectFromRule(rule.styleSheet.cssRules[i] as CSSRule & { style?: CSSStyleDeclaration; cssRules?: CSSRuleList; styleSheet?: { cssRules?: CSSRuleList } })\r\n }\r\n }\r\n } catch { /* cross-origin */ }\r\n }\r\n\r\n const origin = typeof location !== 'undefined' ? location.origin : ''\r\n for (let i = 0; i < document.styleSheets.length; i++) {\r\n const sheet = document.styleSheets[i] as CSSStyleSheet & { href?: string }\r\n if (sheet.href && origin && !sheet.href.startsWith(origin)) continue\r\n try {\r\n if (sheet.cssRules) {\r\n for (let j = 0; j < sheet.cssRules.length; j++) {\r\n collectFromRule(sheet.cssRules[j] as CSSRule & { style?: CSSStyleDeclaration; cssRules?: CSSRuleList; styleSheet?: { cssRules?: CSSRuleList } })\r\n }\r\n }\r\n } catch { /* cross-origin */ }\r\n }\r\n\r\n // Fallback: parse <style> textContent (Vite may use insertRule so cssRules has data but we also try text)\r\n for (const el of document.querySelectorAll('style')) {\r\n const text = el.textContent || ''\r\n let m: RegExpExecArray | null\r\n BREAKPOINT_RE.lastIndex = 0\r\n while ((m = BREAKPOINT_RE.exec(text)) !== null) {\r\n const name = m[1]\r\n const val = m[2].replace(/\\/\\*[\\s\\S]*?\\*\\//g, '').trim()\r\n if (name && val && !result[name]) result[name] = val\r\n }\r\n }\r\n\r\n return result\r\n}\r\n\r\n/**\r\n * Resolve breakpoints: defaults + detected from CSS + customBreakpoints.\r\n * Returns sorted list including optional base row.\r\n */\r\nfunction resolveBreakpoints(options: BreakpointHelperOptions): ResolvedBreakpoint[] {\r\n const baseLabel = options.baseLabel === undefined ? 'base' : options.baseLabel\r\n const rootFontSizePx = getRootFontSizePx()\r\n\r\n const customBreakpoints = options.customBreakpoints && Object.keys(options.customBreakpoints).length > 0 ? options.customBreakpoints : {}\r\n const raw: BreakpointsMap = { ...DEFAULT_BREAKPOINTS, ...getBreakpointsFromCss(), ...customBreakpoints }\r\n\r\n const listWithIndex: Array<ResolvedBreakpoint & { _i: number }> = []\r\n let idx = 0\r\n for (const [name, originalValue] of Object.entries(raw)) {\r\n const valuePx = parseBreakpointValue(originalValue, rootFontSizePx)\r\n if (!Number.isFinite(valuePx) || valuePx <= 0) {\r\n idx++\r\n continue\r\n }\r\n listWithIndex.push({ name, valuePx, originalValue, _i: idx })\r\n idx++\r\n }\r\n listWithIndex.sort((a, b) => (a.valuePx - b.valuePx) || (a._i - b._i))\r\n const list: ResolvedBreakpoint[] = listWithIndex.map(({ _i, ...bp }) => bp)\r\n\r\n const firstPx = list.length > 0 ? list[0].valuePx : 640\r\n if (baseLabel !== false) {\r\n list.unshift({\r\n name: baseLabel,\r\n valuePx: 0,\r\n originalValue: `0 – ${firstPx}px`\r\n })\r\n }\r\n\r\n return list\r\n}\r\n\r\nfunction breakpointNameToClass(name: string): string {\r\n return name\r\n .trim()\r\n .replace(/\\s+/g, '-')\r\n .replace(/[^a-z0-9_-]/gi, '-')\r\n .toLowerCase()\r\n}\r\n\r\nfunction isDevMode(): boolean {\r\n const meta = import.meta as { env?: { DEV?: boolean } }\r\n if (typeof import.meta !== 'undefined' && meta.env?.DEV) return true\r\n\r\n if (typeof globalThis !== 'undefined') {\r\n const proc = (globalThis as unknown as { process?: { env?: { NODE_ENV?: string } } }).process\r\n if (proc?.env?.NODE_ENV === 'development') return true\r\n }\r\n\r\n if (typeof window !== 'undefined') {\r\n const hostname = window.location.hostname\r\n if (hostname === 'localhost' || hostname === '127.0.0.1' || hostname.startsWith('192.168.')) {\r\n return true\r\n }\r\n }\r\n\r\n return false\r\n}\r\n\r\nfunction getActiveBreakpointIndex(resolved: ResolvedBreakpoint[], widthPx: number): number {\r\n let index = 0\r\n for (let i = 0; i < resolved.length; i++) {\r\n if (widthPx >= resolved[i].valuePx) index = i\r\n }\r\n return index\r\n}\r\n\r\nfunction updateActiveBreakpoint(\r\n container: HTMLElement,\r\n resolved: ResolvedBreakpoint[],\r\n content: HTMLElement\r\n): void {\r\n const width = typeof window !== 'undefined' ? window.innerWidth : 0\r\n const index = getActiveBreakpointIndex(resolved, width)\r\n const color = BREAKPOINT_COLORS[index % BREAKPOINT_COLORS.length]\r\n container.style.backgroundColor = color\r\n\r\n const labels = content.querySelectorAll('.breakpoint-helper-label')\r\n labels.forEach((el, i) => {\r\n el.classList.toggle('breakpoint-helper-active', i === index)\r\n })\r\n}\r\n\r\nfunction createBreakpointHelperElement(resolved: ResolvedBreakpoint[]): HTMLElement {\r\n const container = document.createElement('div')\r\n container.id = 'breakpoint-helper'\r\n container.className = 'breakpoint-helper'\r\n container.setAttribute('style', 'display: none')\r\n\r\n const content = buildBreakpointHelperContent(resolved)\r\n container.appendChild(content)\r\n\r\n updateActiveBreakpoint(container, resolved, content)\r\n return container\r\n}\r\n\r\nfunction buildBreakpointHelperContent(resolved: ResolvedBreakpoint[]): HTMLElement {\r\n const content = document.createElement('div')\r\n content.className = 'breakpoint-helper-content'\r\n\r\n for (let i = 0; i < resolved.length; i++) {\r\n const bp = resolved[i]\r\n const span = document.createElement('span')\r\n const classBase = breakpointNameToClass(bp.name)\r\n span.className = `breakpoint-helper-label breakpoint-helper-${classBase}`\r\n span.setAttribute('data-breakpoint-px', String(bp.valuePx))\r\n span.setAttribute('data-breakpoint-name', bp.name)\r\n\r\n const valueDisplay = bp.valuePx === 0\r\n ? bp.originalValue\r\n : `${bp.originalValue} (${Math.round(bp.valuePx)}px)`\r\n const mediaPart = bp.valuePx === 0\r\n ? `@media (width < ${resolved[1]?.originalValue ?? '40rem'})`\r\n : `@media (width >= ${bp.originalValue})`\r\n span.innerHTML = `<strong class=\"breakpoint-helper-badge\">${escapeHtml(bp.name)}</strong> ${escapeHtml(valueDisplay)} ${mediaPart}`\r\n content.appendChild(span)\r\n }\r\n\r\n const hideButton = document.createElement('button')\r\n hideButton.id = 'breakpoint-helper-hide-btn'\r\n hideButton.type = 'button'\r\n hideButton.className = 'breakpoint-helper-hide-btn'\r\n hideButton.setAttribute('aria-label', 'Hide breakpoint helper for 20 seconds')\r\n hideButton.innerHTML = `\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"breakpoint-helper-icon\">\r\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M12 6v6h4.5m4.5 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z\" />\r\n </svg>\r\n `\r\n content.appendChild(hideButton)\r\n\r\n return content\r\n}\r\n\r\nfunction escapeHtml(text: string): string {\r\n const div = document.createElement('div')\r\n div.textContent = text\r\n return div.innerHTML\r\n}\r\n\r\n/**\r\n * Initializes the breakpoint helper\r\n */\r\nexport function initBreakpointHelper(options: BreakpointHelperOptions = {}): void {\r\n if (typeof window === 'undefined' || typeof document === 'undefined') return\r\n\r\n const opts = { ...DEFAULT_OPTIONS, ...options }\r\n\r\n const enabled = opts.enabled !== undefined ? opts.enabled : isDevMode()\r\n if (!enabled) {\r\n const existing = document.getElementById('breakpoint-helper')\r\n if (existing) existing.style.display = 'none'\r\n return\r\n }\r\n\r\n const debug = opts.debug === true\r\n\r\n const customBreakpoints = opts.customBreakpoints && Object.keys(opts.customBreakpoints).length > 0 ? opts.customBreakpoints : {}\r\n\r\n if (debug) {\r\n const fromCss = getBreakpointsFromCss()\r\n console.log(DEBUG_PREFIX, 'From CSS (--breakpoint-*):', fromCss)\r\n if (Object.keys(fromCss).length === 0 && Object.keys(customBreakpoints).length === 0) {\r\n console.log(DEBUG_PREFIX, 'No custom breakpoints in CSS. Use customBreakpoints in initBreakpointHelper() for extra names or fallback.')\r\n }\r\n }\r\n\r\n const resolved = resolveBreakpoints(opts)\r\n const signature = JSON.stringify(resolved.map((bp) => [bp.name, bp.originalValue]))\r\n\r\n if (debug) {\r\n const source = Object.keys(customBreakpoints).length > 0 ? 'defaults + CSS + customBreakpoints' : 'defaults + CSS'\r\n if (Object.keys(customBreakpoints).length > 0) {\r\n console.log(DEBUG_PREFIX, 'customBreakpoints:', customBreakpoints)\r\n }\r\n console.log(DEBUG_PREFIX, 'Breakpoint source:', source)\r\n console.log(\r\n DEBUG_PREFIX,\r\n 'Resolved breakpoints:',\r\n resolved.map((bp) => `${bp.name} (${bp.originalValue})`).join(', ')\r\n )\r\n }\r\n\r\n let breakpointHelper: HTMLElement | null = null\r\n if (opts.containerSelector) {\r\n breakpointHelper = document.querySelector(opts.containerSelector) as HTMLElement | null\r\n } else {\r\n breakpointHelper = document.getElementById('breakpoint-helper')\r\n }\r\n\r\n if (!breakpointHelper) {\r\n breakpointHelper = createBreakpointHelperElement(resolved)\r\n document.body.appendChild(breakpointHelper)\r\n } else {\r\n if (!breakpointHelper.classList.contains('breakpoint-helper')) {\r\n breakpointHelper.classList.add('breakpoint-helper')\r\n }\r\n }\r\n\r\n breakpointHelper.style.display = 'block'\r\n\r\n const state: HelperState = HELPER_STATE.get(breakpointHelper) ?? {}\r\n\r\n if (state.resizeHandler) {\r\n window.removeEventListener('resize', state.resizeHandler)\r\n state.resizeHandler = undefined\r\n }\r\n\r\n const existingContent = breakpointHelper.querySelector('.breakpoint-helper-content') as HTMLElement | null\r\n if (!existingContent || state.signature !== signature) {\r\n if (existingContent) existingContent.remove()\r\n breakpointHelper.appendChild(buildBreakpointHelperContent(resolved))\r\n state.signature = signature\r\n }\r\n\r\n const contentEl = breakpointHelper.querySelector('.breakpoint-helper-content') as HTMLElement | null\r\n if (contentEl) updateActiveBreakpoint(breakpointHelper, resolved, contentEl)\r\n\r\n const resizeHandler = (): void => {\r\n const content = breakpointHelper?.querySelector('.breakpoint-helper-content') as HTMLElement | null\r\n if (breakpointHelper && content) updateActiveBreakpoint(breakpointHelper, resolved, content)\r\n }\r\n state.resizeHandler = resizeHandler\r\n window.addEventListener('resize', resizeHandler)\r\n\r\n const hideButton = breakpointHelper.querySelector('#breakpoint-helper-hide-btn') as HTMLButtonElement | null\r\n if (hideButton) {\r\n if (state.hideHandler) {\r\n hideButton.removeEventListener('click', state.hideHandler)\r\n state.hideHandler = undefined\r\n }\r\n const hideHandler = (): void => {\r\n breakpointHelper!.style.display = 'none'\r\n window.setTimeout(() => {\r\n breakpointHelper!.style.display = 'block'\r\n }, opts.hideDuration)\r\n }\r\n state.hideHandler = hideHandler\r\n hideButton.addEventListener('click', hideHandler)\r\n }\r\n\r\n HELPER_STATE.set(breakpointHelper, state)\r\n}\r\n\r\n/**\r\n * Returns the default breakpoints. Useful for debugging or when building custom options.\r\n */\r\nexport function getDefaultBreakpoints(): BreakpointsMap {\r\n return { ...DEFAULT_BREAKPOINTS }\r\n}\r\n\r\n/**\r\n * Auto-initialize if imported directly (for convenience)\r\n */\r\nif (typeof window !== 'undefined') {\r\n if (isDevMode()) {\r\n if (document.readyState === 'loading') {\r\n document.addEventListener('DOMContentLoaded', () => initBreakpointHelper())\r\n } else {\r\n initBreakpointHelper()\r\n }\r\n }\r\n}\r\n"],"names":["DEFAULT_OPTIONS","DEBUG_PREFIX","DEFAULT_BREAKPOINTS","DETECTABLE_CUSTOM_NAMES","BREAKPOINT_COLORS","HELPER_STATE","getRootFontSizePx","root","computed","parsed","measureCssLengthPx","value","el","px","parseBreakpointValue","rootFontSizePx","trimmed","match","num","unit","BREAKPOINT_RE","getBreakpointsFromCss","result","collectFromRule","rule","k","prop","name","val","i","origin","sheet","j","text","m","resolveBreakpoints","options","baseLabel","customBreakpoints","raw","listWithIndex","idx","originalValue","valuePx","a","b","list","_i","bp","firstPx","breakpointNameToClass","isDevMode","meta","_documentCurrentScript","hostname","getActiveBreakpointIndex","resolved","widthPx","index","updateActiveBreakpoint","container","content","width","color","createBreakpointHelperElement","buildBreakpointHelperContent","span","classBase","valueDisplay","mediaPart","escapeHtml","hideButton","div","initBreakpointHelper","opts","existing","debug","fromCss","signature","source","breakpointHelper","state","existingContent","contentEl","resizeHandler","hideHandler","getDefaultBreakpoints"],"mappings":"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"}
|
package/dist/styles.css
CHANGED
|
@@ -16,45 +16,9 @@
|
|
|
16
16
|
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
/*
|
|
20
|
-
/* Base (default) - red */
|
|
19
|
+
/* Default background; JS sets per-breakpoint color via inline style */
|
|
21
20
|
.breakpoint-helper {
|
|
22
|
-
background-color: #ef4444; /* red-500 */
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/* SM - green */
|
|
26
|
-
@media (min-width: 640px) {
|
|
27
|
-
.breakpoint-helper {
|
|
28
|
-
background-color: #22c55e; /* green-500 */
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/* MD - blue */
|
|
33
|
-
@media (min-width: 768px) {
|
|
34
|
-
.breakpoint-helper {
|
|
35
|
-
background-color: #3b82f6; /* blue-500 */
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/* LG - yellow */
|
|
40
|
-
@media (min-width: 1024px) {
|
|
41
|
-
.breakpoint-helper {
|
|
42
|
-
background-color: #eab308; /* yellow-500 */
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/* XL - purple */
|
|
47
|
-
@media (min-width: 1280px) {
|
|
48
|
-
.breakpoint-helper {
|
|
49
|
-
background-color: #a855f7; /* purple-500 */
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/* 2XL - pink */
|
|
54
|
-
@media (min-width: 1536px) {
|
|
55
|
-
.breakpoint-helper {
|
|
56
|
-
background-color: #ec4899; /* pink-500 */
|
|
57
|
-
}
|
|
21
|
+
background-color: #ef4444; /* red-500 - base */
|
|
58
22
|
}
|
|
59
23
|
|
|
60
24
|
.breakpoint-helper-content {
|
|
@@ -64,59 +28,14 @@
|
|
|
64
28
|
}
|
|
65
29
|
|
|
66
30
|
.breakpoint-helper-label {
|
|
67
|
-
display: none;
|
|
31
|
+
display: none;
|
|
68
32
|
}
|
|
69
33
|
|
|
70
|
-
/* Show only the active breakpoint */
|
|
71
|
-
.breakpoint-helper-
|
|
34
|
+
/* Show only the active breakpoint (set by JS) */
|
|
35
|
+
.breakpoint-helper-label.breakpoint-helper-active {
|
|
72
36
|
display: inline-block;
|
|
73
37
|
}
|
|
74
38
|
|
|
75
|
-
@media (min-width: 640px) {
|
|
76
|
-
.breakpoint-helper-base {
|
|
77
|
-
display: none;
|
|
78
|
-
}
|
|
79
|
-
.breakpoint-helper-sm {
|
|
80
|
-
display: inline-block;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
@media (min-width: 768px) {
|
|
85
|
-
.breakpoint-helper-sm {
|
|
86
|
-
display: none;
|
|
87
|
-
}
|
|
88
|
-
.breakpoint-helper-md {
|
|
89
|
-
display: inline-block;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
@media (min-width: 1024px) {
|
|
94
|
-
.breakpoint-helper-md {
|
|
95
|
-
display: none;
|
|
96
|
-
}
|
|
97
|
-
.breakpoint-helper-lg {
|
|
98
|
-
display: inline-block;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
@media (min-width: 1280px) {
|
|
103
|
-
.breakpoint-helper-lg {
|
|
104
|
-
display: none;
|
|
105
|
-
}
|
|
106
|
-
.breakpoint-helper-xl {
|
|
107
|
-
display: inline-block;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
@media (min-width: 1536px) {
|
|
112
|
-
.breakpoint-helper-xl {
|
|
113
|
-
display: none;
|
|
114
|
-
}
|
|
115
|
-
.breakpoint-helper-2xl {
|
|
116
|
-
display: inline-block;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
39
|
.breakpoint-helper-badge {
|
|
121
40
|
display: inline-block;
|
|
122
41
|
border-radius: 0.125rem;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kittler/tailwind-breakpoint-indicator",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Visual breakpoint indicator for Tailwind CSS development",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -46,7 +46,6 @@
|
|
|
46
46
|
"vite": "^7.0.0",
|
|
47
47
|
"vite-plugin-dts": "^4.5.0"
|
|
48
48
|
},
|
|
49
|
-
"peerDependencies": {},
|
|
50
49
|
"repository": {
|
|
51
50
|
"type": "git",
|
|
52
51
|
"url": "https://github.com/kittlerstudio/tailwind-breakpoint-indicator.git"
|