@kittler/tailwind-breakpoint-indicator 1.1.1 → 1.1.3
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 +4 -0
- package/dist/index.esm.js +66 -52
- 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 +2 -2
- package/dist/index.umd.js.map +1 -1
- package/dist/styles.css +1 -0
- package/package.json +59 -53
package/README.md
CHANGED
|
@@ -267,6 +267,10 @@ npm run build
|
|
|
267
267
|
|
|
268
268
|
For development and testing instructions, see [TESTING.md](./TESTING.md).
|
|
269
269
|
|
|
270
|
+
## Support
|
|
271
|
+
|
|
272
|
+
If this tool helps you in your work, you can support its development by buying me a coffee on [Ko-fi](https://ko-fi.com/jakubkittler).
|
|
273
|
+
|
|
270
274
|
## License
|
|
271
275
|
|
|
272
276
|
MIT
|
package/dist/index.esm.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
const
|
|
1
|
+
const P = {
|
|
2
2
|
hideDuration: 2e4
|
|
3
|
-
},
|
|
3
|
+
}, f = "[breakpoint-indicator]", E = {
|
|
4
4
|
sm: "40rem",
|
|
5
5
|
md: "48rem",
|
|
6
6
|
lg: "64rem",
|
|
@@ -20,12 +20,12 @@ const C = {
|
|
|
20
20
|
"#ec4899"
|
|
21
21
|
/* pink */
|
|
22
22
|
], k = /* @__PURE__ */ new WeakMap();
|
|
23
|
-
function
|
|
23
|
+
function C() {
|
|
24
24
|
if (typeof document > "u") return 16;
|
|
25
25
|
const n = document.documentElement, e = getComputedStyle(n).fontSize, r = parseFloat(e);
|
|
26
26
|
return Number.isNaN(r) ? 16 : r;
|
|
27
27
|
}
|
|
28
|
-
function
|
|
28
|
+
function L(n) {
|
|
29
29
|
if (typeof document > "u") return 0;
|
|
30
30
|
const e = document.createElement("div");
|
|
31
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);
|
|
@@ -35,7 +35,7 @@ function P(n) {
|
|
|
35
35
|
function H(n, e) {
|
|
36
36
|
const r = n.trim(), o = r.match(/^(-?\d*\.?\d+)(rem|em|px)$/i);
|
|
37
37
|
if (!o)
|
|
38
|
-
return
|
|
38
|
+
return L(r);
|
|
39
39
|
const t = parseFloat(o[1]), s = (o[2] || "").toLowerCase();
|
|
40
40
|
return s === "px" ? t : s === "rem" || s === "em" ? t * e : 0;
|
|
41
41
|
}
|
|
@@ -49,8 +49,8 @@ function S() {
|
|
|
49
49
|
for (let t = 0; t < (o.style.length || 0); t++) {
|
|
50
50
|
const s = o.style.item(t);
|
|
51
51
|
if (s?.startsWith("--breakpoint-")) {
|
|
52
|
-
const
|
|
53
|
-
|
|
52
|
+
const c = s.slice(13), i = o.style.getPropertyValue(s).trim();
|
|
53
|
+
c && i && (n[c] = i);
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
if (o.cssRules)
|
|
@@ -76,25 +76,25 @@ function S() {
|
|
|
76
76
|
const t = o.textContent || "";
|
|
77
77
|
let s;
|
|
78
78
|
for (y.lastIndex = 0; (s = y.exec(t)) !== null; ) {
|
|
79
|
-
const
|
|
80
|
-
|
|
79
|
+
const c = s[1], i = s[2].replace(/\/\*[\s\S]*?\*\//g, "").trim();
|
|
80
|
+
c && i && !n[c] && (n[c] = i);
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
return n;
|
|
84
84
|
}
|
|
85
85
|
function R(n) {
|
|
86
|
-
const e = n.baseLabel === void 0 ? "base" : n.baseLabel, r =
|
|
87
|
-
let
|
|
88
|
-
for (const [
|
|
89
|
-
const
|
|
90
|
-
if (!Number.isFinite(
|
|
91
|
-
|
|
86
|
+
const e = n.baseLabel === void 0 ? "base" : n.baseLabel, r = C(), o = n.customBreakpoints && Object.keys(n.customBreakpoints).length > 0 ? n.customBreakpoints : {}, t = { ...E, ...S(), ...o }, s = [];
|
|
87
|
+
let c = 0;
|
|
88
|
+
for (const [d, p] of Object.entries(t)) {
|
|
89
|
+
const u = H(p, r);
|
|
90
|
+
if (!Number.isFinite(u) || u <= 0) {
|
|
91
|
+
c++;
|
|
92
92
|
continue;
|
|
93
93
|
}
|
|
94
|
-
s.push({ name:
|
|
94
|
+
s.push({ name: d, valuePx: u, originalValue: p, _i: c }), c++;
|
|
95
95
|
}
|
|
96
|
-
s.sort((
|
|
97
|
-
const i = s.map(({ _i:
|
|
96
|
+
s.sort((d, p) => d.valuePx - p.valuePx || d._i - p._i);
|
|
97
|
+
const i = s.map(({ _i: d, ...p }) => p), l = i.length > 0 ? i[0].valuePx : 640;
|
|
98
98
|
return e !== !1 && i.unshift({
|
|
99
99
|
name: e,
|
|
100
100
|
valuePx: 0,
|
|
@@ -104,7 +104,7 @@ function R(n) {
|
|
|
104
104
|
function N(n) {
|
|
105
105
|
return n.trim().replace(/\s+/g, "-").replace(/[^a-z0-9_-]/gi, "-").toLowerCase();
|
|
106
106
|
}
|
|
107
|
-
function
|
|
107
|
+
function B() {
|
|
108
108
|
if (typeof import.meta < "u" && import.meta.env?.DEV || typeof globalThis < "u" && globalThis.process?.env?.NODE_ENV === "development")
|
|
109
109
|
return !0;
|
|
110
110
|
if (typeof window < "u") {
|
|
@@ -114,32 +114,46 @@ function w() {
|
|
|
114
114
|
}
|
|
115
115
|
return !1;
|
|
116
116
|
}
|
|
117
|
-
function
|
|
117
|
+
function T(n, e) {
|
|
118
118
|
let r = 0;
|
|
119
119
|
for (let o = 0; o < n.length; o++)
|
|
120
120
|
e >= n[o].valuePx && (r = o);
|
|
121
121
|
return r;
|
|
122
122
|
}
|
|
123
123
|
function h(n, e, r) {
|
|
124
|
-
const o = typeof window < "u" ? window.innerWidth : 0, t =
|
|
124
|
+
const o = typeof window < "u" ? window.innerWidth : 0, t = T(e, o), s = g[t % g.length];
|
|
125
125
|
n.style.backgroundColor = s, r.querySelectorAll(".breakpoint-helper-label").forEach((i, l) => {
|
|
126
126
|
i.classList.toggle("breakpoint-helper-active", l === t);
|
|
127
127
|
});
|
|
128
128
|
}
|
|
129
|
-
function
|
|
129
|
+
function O(n) {
|
|
130
130
|
const e = document.createElement("div");
|
|
131
131
|
e.id = "breakpoint-helper", e.className = "breakpoint-helper", e.setAttribute("style", "display: none");
|
|
132
|
-
const r =
|
|
132
|
+
const r = w(n);
|
|
133
133
|
return e.appendChild(r), h(e, n, r), e;
|
|
134
134
|
}
|
|
135
|
-
function
|
|
135
|
+
function w(n) {
|
|
136
136
|
const e = document.createElement("div");
|
|
137
137
|
e.className = "breakpoint-helper-content";
|
|
138
138
|
for (let o = 0; o < n.length; o++) {
|
|
139
|
-
const t = n[o], s = document.createElement("span"),
|
|
140
|
-
s.className = `breakpoint-helper-label breakpoint-helper-${
|
|
141
|
-
const i = t.valuePx === 0
|
|
142
|
-
|
|
139
|
+
const t = n[o], s = document.createElement("span"), c = N(t.name);
|
|
140
|
+
s.className = `breakpoint-helper-label breakpoint-helper-${c}`, s.setAttribute("data-breakpoint-px", String(t.valuePx)), s.setAttribute("data-breakpoint-name", t.name);
|
|
141
|
+
const i = t.valuePx === 0;
|
|
142
|
+
let l, d;
|
|
143
|
+
if (i) {
|
|
144
|
+
const u = n[1];
|
|
145
|
+
u ? (l = `< ${Math.round(u.valuePx) - 1}px`, d = `@media (width < ${u.originalValue})`) : (l = t.originalValue, d = "");
|
|
146
|
+
} else {
|
|
147
|
+
const u = Math.round(t.valuePx), m = n[o + 1];
|
|
148
|
+
if (m && m.valuePx > t.valuePx) {
|
|
149
|
+
const a = Math.round(m.valuePx) - 1;
|
|
150
|
+
l = `${u}px - ${a}px`;
|
|
151
|
+
} else
|
|
152
|
+
l = `>= ${u}px`;
|
|
153
|
+
d = `@media (width >= ${t.originalValue})`;
|
|
154
|
+
}
|
|
155
|
+
const p = d ? ` ${d}` : "";
|
|
156
|
+
s.innerHTML = `<strong class="breakpoint-helper-badge">${x(t.name)}</strong> ${x(l)}${p}`, e.appendChild(s);
|
|
143
157
|
}
|
|
144
158
|
const r = document.createElement("button");
|
|
145
159
|
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 = `
|
|
@@ -154,55 +168,55 @@ function x(n) {
|
|
|
154
168
|
}
|
|
155
169
|
function v(n = {}) {
|
|
156
170
|
if (typeof window > "u" || typeof document > "u") return;
|
|
157
|
-
const e = { ...
|
|
158
|
-
if (!(e.enabled !== void 0 ? e.enabled :
|
|
159
|
-
const
|
|
160
|
-
|
|
171
|
+
const e = { ...P, ...n };
|
|
172
|
+
if (!(e.enabled !== void 0 ? e.enabled : B())) {
|
|
173
|
+
const a = document.getElementById("breakpoint-helper");
|
|
174
|
+
a && (a.style.display = "none");
|
|
161
175
|
return;
|
|
162
176
|
}
|
|
163
177
|
const o = e.debug === !0, t = e.customBreakpoints && Object.keys(e.customBreakpoints).length > 0 ? e.customBreakpoints : {};
|
|
164
178
|
if (o) {
|
|
165
|
-
const
|
|
166
|
-
console.log(
|
|
179
|
+
const a = S();
|
|
180
|
+
console.log(f, "From CSS (--breakpoint-*):", a), Object.keys(a).length === 0 && Object.keys(t).length === 0 && console.log(f, "No custom breakpoints in CSS. Use customBreakpoints in initBreakpointHelper() for extra names or fallback.");
|
|
167
181
|
}
|
|
168
|
-
const s = R(e),
|
|
182
|
+
const s = R(e), c = JSON.stringify(s.map((a) => [a.name, a.originalValue]));
|
|
169
183
|
if (o) {
|
|
170
|
-
const
|
|
171
|
-
Object.keys(t).length > 0 && console.log(
|
|
172
|
-
|
|
184
|
+
const a = Object.keys(t).length > 0 ? "defaults + CSS + customBreakpoints" : "defaults + CSS";
|
|
185
|
+
Object.keys(t).length > 0 && console.log(f, "customBreakpoints:", t), console.log(f, "Breakpoint source:", a), console.log(
|
|
186
|
+
f,
|
|
173
187
|
"Resolved breakpoints:",
|
|
174
188
|
s.map((b) => `${b.name} (${b.originalValue})`).join(", ")
|
|
175
189
|
);
|
|
176
190
|
}
|
|
177
191
|
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 =
|
|
192
|
+
e.containerSelector ? i = document.querySelector(e.containerSelector) : i = document.getElementById("breakpoint-helper"), i ? i.classList.contains("breakpoint-helper") || i.classList.add("breakpoint-helper") : (i = O(s), document.body.appendChild(i)), i.style.display = "block";
|
|
179
193
|
const l = k.get(i) ?? {};
|
|
180
194
|
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
195
|
const d = i.querySelector(".breakpoint-helper-content");
|
|
184
|
-
d &&
|
|
185
|
-
const p = ()
|
|
186
|
-
|
|
187
|
-
|
|
196
|
+
(!d || l.signature !== c) && (d && d.remove(), i.appendChild(w(s)), l.signature = c);
|
|
197
|
+
const p = i.querySelector(".breakpoint-helper-content");
|
|
198
|
+
p && h(i, s, p);
|
|
199
|
+
const u = () => {
|
|
200
|
+
const a = i?.querySelector(".breakpoint-helper-content");
|
|
201
|
+
i && a && h(i, s, a);
|
|
188
202
|
};
|
|
189
|
-
l.resizeHandler =
|
|
190
|
-
const
|
|
191
|
-
if (
|
|
192
|
-
l.hideHandler && (
|
|
193
|
-
const
|
|
203
|
+
l.resizeHandler = u, window.addEventListener("resize", u);
|
|
204
|
+
const m = i.querySelector("#breakpoint-helper-hide-btn");
|
|
205
|
+
if (m) {
|
|
206
|
+
l.hideHandler && (m.removeEventListener("click", l.hideHandler), l.hideHandler = void 0);
|
|
207
|
+
const a = () => {
|
|
194
208
|
i.style.display = "none", window.setTimeout(() => {
|
|
195
209
|
i.style.display = "block";
|
|
196
210
|
}, e.hideDuration);
|
|
197
211
|
};
|
|
198
|
-
l.hideHandler =
|
|
212
|
+
l.hideHandler = a, m.addEventListener("click", a);
|
|
199
213
|
}
|
|
200
214
|
k.set(i, l);
|
|
201
215
|
}
|
|
202
216
|
function _() {
|
|
203
217
|
return { ...E };
|
|
204
218
|
}
|
|
205
|
-
typeof window < "u" &&
|
|
219
|
+
typeof window < "u" && B() && (document.readyState === "loading" ? document.addEventListener("DOMContentLoaded", () => v()) : v());
|
|
206
220
|
export {
|
|
207
221
|
A as DETECTABLE_CUSTOM_NAMES,
|
|
208
222
|
_ as getDefaultBreakpoints,
|
package/dist/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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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"}
|
|
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 isBase = bp.valuePx === 0\r\n let rangeText: string\r\n let mediaPart: string\r\n\r\n if (isBase) {\r\n const next = resolved[1]\r\n if (next) {\r\n const upperPx = Math.round(next.valuePx) - 1\r\n rangeText = `< ${upperPx}px`\r\n mediaPart = `@media (width < ${next.originalValue})`\r\n } else {\r\n // No other breakpoints; fall back to original text without media info\r\n rangeText = bp.originalValue\r\n mediaPart = ''\r\n }\r\n } else {\r\n const minPx = Math.round(bp.valuePx)\r\n const next = resolved[i + 1]\r\n\r\n if (next && next.valuePx > bp.valuePx) {\r\n const maxPx = Math.round(next.valuePx) - 1\r\n rangeText = `${minPx}px - ${maxPx}px`\r\n } else {\r\n rangeText = `>= ${minPx}px`\r\n }\r\n\r\n mediaPart = `@media (width >= ${bp.originalValue})`\r\n }\r\n\r\n const mediaPartHtml = mediaPart ? ` ${mediaPart}` : ''\r\n span.innerHTML = `<strong class=\"breakpoint-helper-badge\">${escapeHtml(bp.name)}</strong> ${escapeHtml(rangeText)}${mediaPartHtml}`\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","isBase","rangeText","mediaPart","next","minPx","maxPx","mediaPartHtml","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 f=typeof document<"u"?document.currentScript:null;const P={hideDuration:2e4},h="[breakpoint-indicator]",E={sm:"40rem",md:"48rem",lg:"64rem",xl:"80rem","2xl":"96rem"},L=["xs","3xl","4xl"],y=["#ef4444","#22c55e","#3b82f6","#eab308","#a855f7","#ec4899"],x=new WeakMap;function R(){if(typeof document>"u")return 16;const n=document.documentElement,e=getComputedStyle(n).fontSize,r=parseFloat(e);return Number.isNaN(r)?16:r}function T(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 r=e.getBoundingClientRect().width;return e.remove(),Number.isFinite(r)?r:0}function H(n,e){const r=n.trim(),o=r.match(/^(-?\d*\.?\d+)(rem|em|px)$/i);if(!o)return T(r);const t=parseFloat(o[1]),s=(o[2]||"").toLowerCase();return s==="px"?t:s==="rem"||s==="em"?t*e:0}const v=/--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 s=o.style.item(t);if(s?.startsWith("--breakpoint-")){const c=s.slice(13),i=o.style.getPropertyValue(s).trim();c&&i&&(n[c]=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{}},r=typeof location<"u"?location.origin:"";for(let o=0;o<document.styleSheets.length;o++){const t=document.styleSheets[o];if(!(t.href&&r&&!t.href.startsWith(r)))try{if(t.cssRules)for(let s=0;s<t.cssRules.length;s++)e(t.cssRules[s])}catch{}}for(const o of document.querySelectorAll("style")){const t=o.textContent||"";let s;for(v.lastIndex=0;(s=v.exec(t))!==null;){const c=s[1],i=s[2].replace(/\/\*[\s\S]*?\*\//g,"").trim();c&&i&&!n[c]&&(n[c]=i)}}return n}function N(n){const e=n.baseLabel===void 0?"base":n.baseLabel,r=R(),o=n.customBreakpoints&&Object.keys(n.customBreakpoints).length>0?n.customBreakpoints:{},t={...E,...B(),...o},s=[];let c=0;for(const[d,p]of Object.entries(t)){const u=H(p,r);if(!Number.isFinite(u)||u<=0){c++;continue}s.push({name:d,valuePx:u,originalValue:p,_i:c}),c++}s.sort((d,p)=>d.valuePx-p.valuePx||d._i-p._i);const i=s.map(({_i:d,...p})=>p),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:f&&f.tagName.toUpperCase()==="SCRIPT"&&f.src||new URL("index.js",document.baseURI).href};if(typeof{url:typeof document>"u"?require("url").pathToFileURL(__filename).href:f&&f.tagName.toUpperCase()==="SCRIPT"&&f.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 r=0;for(let o=0;o<n.length;o++)e>=n[o].valuePx&&(r=o);return r}function b(n,e,r){const o=typeof window<"u"?window.innerWidth:0,t=O(e,o),s=y[t%y.length];n.style.backgroundColor=s,r.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 r=C(n);return e.appendChild(r),b(e,n,r),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],s=document.createElement("span"),c=_(t.name);s.className=`breakpoint-helper-label breakpoint-helper-${c}`,s.setAttribute("data-breakpoint-px",String(t.valuePx)),s.setAttribute("data-breakpoint-name",t.name);const i=t.valuePx===0;let l,d;if(i){const u=n[1];u?(l=`< ${Math.round(u.valuePx)-1}px`,d=`@media (width < ${u.originalValue})`):(l=t.originalValue,d="")}else{const u=Math.round(t.valuePx),m=n[o+1];if(m&&m.valuePx>t.valuePx){const a=Math.round(m.valuePx)-1;l=`${u}px - ${a}px`}else l=`>= ${u}px`;d=`@media (width >= ${t.originalValue})`}const p=d?` ${d}`:"";s.innerHTML=`<strong class="breakpoint-helper-badge">${S(t.name)}</strong> ${S(l)}${p}`,e.appendChild(s)}const r=document.createElement("button");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=`
|
|
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(r),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={...P,...n};if(!(e.enabled!==void 0?e.enabled:w())){const a=document.getElementById("breakpoint-helper");a&&(a.style.display="none");return}const o=e.debug===!0,t=e.customBreakpoints&&Object.keys(e.customBreakpoints).length>0?e.customBreakpoints:{};if(o){const a=B();console.log(h,"From CSS (--breakpoint-*):",a),Object.keys(a).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 s=N(e),c=JSON.stringify(s.map(a=>[a.name,a.originalValue]));if(o){const a=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:",a),console.log(h,"Resolved breakpoints:",s.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(s),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 d=i.querySelector(".breakpoint-helper-content");(!d||l.signature!==c)&&(d&&d.remove(),i.appendChild(C(s)),l.signature=c);const p=i.querySelector(".breakpoint-helper-content");p&&b(i,s,p);const u=()=>{const a=i?.querySelector(".breakpoint-helper-content");i&&a&&b(i,s,a)};l.resizeHandler=u,window.addEventListener("resize",u);const m=i.querySelector("#breakpoint-helper-hide-btn");if(m){l.hideHandler&&(m.removeEventListener("click",l.hideHandler),l.hideHandler=void 0);const a=()=>{i.style.display="none",window.setTimeout(()=>{i.style.display="block"},e.hideDuration)};l.hideHandler=a,m.addEventListener("click",a)}x.set(i,l)}function M(){return{...E}}typeof window<"u"&&w()&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>g()):g());exports.DETECTABLE_CUSTOM_NAMES=L;exports.getDefaultBreakpoints=M;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":["/** 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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"}
|
|
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 isBase = bp.valuePx === 0\r\n let rangeText: string\r\n let mediaPart: string\r\n\r\n if (isBase) {\r\n const next = resolved[1]\r\n if (next) {\r\n const upperPx = Math.round(next.valuePx) - 1\r\n rangeText = `< ${upperPx}px`\r\n mediaPart = `@media (width < ${next.originalValue})`\r\n } else {\r\n // No other breakpoints; fall back to original text without media info\r\n rangeText = bp.originalValue\r\n mediaPart = ''\r\n }\r\n } else {\r\n const minPx = Math.round(bp.valuePx)\r\n const next = resolved[i + 1]\r\n\r\n if (next && next.valuePx > bp.valuePx) {\r\n const maxPx = Math.round(next.valuePx) - 1\r\n rangeText = `${minPx}px - ${maxPx}px`\r\n } else {\r\n rangeText = `>= ${minPx}px`\r\n }\r\n\r\n mediaPart = `@media (width >= ${bp.originalValue})`\r\n }\r\n\r\n const mediaPartHtml = mediaPart ? ` ${mediaPart}` : ''\r\n span.innerHTML = `<strong class=\"breakpoint-helper-badge\">${escapeHtml(bp.name)}</strong> ${escapeHtml(rangeText)}${mediaPartHtml}`\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","isBase","rangeText","mediaPart","next","minPx","maxPx","mediaPartHtml","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.umd.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
(function(f
|
|
1
|
+
(function(m,f){typeof exports=="object"&&typeof module<"u"?f(exports):typeof define=="function"&&define.amd?define(["exports"],f):(m=typeof globalThis<"u"?globalThis:m||self,f(m.TailwindBreakpointIndicator={}))})(this,(function(m){"use strict";var f=typeof document<"u"?document.currentScript:null;const T={hideDuration:2e4},b="[breakpoint-indicator]",k={sm:"40rem",md:"48rem",lg:"64rem",xl:"80rem","2xl":"96rem"},L=["xs","3xl","4xl"],x=["#ef4444","#22c55e","#3b82f6","#eab308","#a855f7","#ec4899"],v=new WeakMap;function R(){if(typeof document>"u")return 16;const n=document.documentElement,e=getComputedStyle(n).fontSize,r=parseFloat(e);return Number.isNaN(r)?16:r}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 r=e.getBoundingClientRect().width;return e.remove(),Number.isFinite(r)?r:0}function N(n,e){const r=n.trim(),o=r.match(/^(-?\d*\.?\d+)(rem|em|px)$/i);if(!o)return H(r);const t=parseFloat(o[1]),s=(o[2]||"").toLowerCase();return s==="px"?t:s==="rem"||s==="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 s=o.style.item(t);if(s?.startsWith("--breakpoint-")){const c=s.slice(13),i=o.style.getPropertyValue(s).trim();c&&i&&(n[c]=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{}},r=typeof location<"u"?location.origin:"";for(let o=0;o<document.styleSheets.length;o++){const t=document.styleSheets[o];if(!(t.href&&r&&!t.href.startsWith(r)))try{if(t.cssRules)for(let s=0;s<t.cssRules.length;s++)e(t.cssRules[s])}catch{}}for(const o of document.querySelectorAll("style")){const t=o.textContent||"";let s;for(S.lastIndex=0;(s=S.exec(t))!==null;){const c=s[1],i=s[2].replace(/\/\*[\s\S]*?\*\//g,"").trim();c&&i&&!n[c]&&(n[c]=i)}}return n}function _(n){const e=n.baseLabel===void 0?"base":n.baseLabel,r=R(),o=n.customBreakpoints&&Object.keys(n.customBreakpoints).length>0?n.customBreakpoints:{},t={...k,...E(),...o},s=[];let c=0;for(const[d,p]of Object.entries(t)){const u=N(p,r);if(!Number.isFinite(u)||u<=0){c++;continue}s.push({name:d,valuePx:u,originalValue:p,_i:c}),c++}s.sort((d,p)=>d.valuePx-p.valuePx||d._i-p._i);const i=s.map(({_i:d,...p})=>p),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:f&&f.tagName.toUpperCase()==="SCRIPT"&&f.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:f&&f.tagName.toUpperCase()==="SCRIPT"&&f.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 r=0;for(let o=0;o<n.length;o++)e>=n[o].valuePx&&(r=o);return r}function g(n,e,r){const o=typeof window<"u"?window.innerWidth:0,t=A(e,o),s=x[t%x.length];n.style.backgroundColor=s,r.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 r=w(n);return e.appendChild(r),g(e,n,r),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],s=document.createElement("span"),c=O(t.name);s.className=`breakpoint-helper-label breakpoint-helper-${c}`,s.setAttribute("data-breakpoint-px",String(t.valuePx)),s.setAttribute("data-breakpoint-name",t.name);const i=t.valuePx===0;let l,d;if(i){const u=n[1];u?(l=`< ${Math.round(u.valuePx)-1}px`,d=`@media (width < ${u.originalValue})`):(l=t.originalValue,d="")}else{const u=Math.round(t.valuePx),h=n[o+1];if(h&&h.valuePx>t.valuePx){const a=Math.round(h.valuePx)-1;l=`${u}px - ${a}px`}else l=`>= ${u}px`;d=`@media (width >= ${t.originalValue})`}const p=d?` ${d}`:"";s.innerHTML=`<strong class="breakpoint-helper-badge">${C(t.name)}</strong> ${C(l)}${p}`,e.appendChild(s)}const r=document.createElement("button");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=`
|
|
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(r),e}function C(n){const e=document.createElement("div");return e.textContent=n,e.innerHTML}function y(n={}){if(typeof window>"u"||typeof document>"u")return;const e={...T,...n};if(!(e.enabled!==void 0?e.enabled:B())){const a=document.getElementById("breakpoint-helper");a&&(a.style.display="none");return}const o=e.debug===!0,t=e.customBreakpoints&&Object.keys(e.customBreakpoints).length>0?e.customBreakpoints:{};if(o){const a=E();console.log(b,"From CSS (--breakpoint-*):",a),Object.keys(a).length===0&&Object.keys(t).length===0&&console.log(b,"No custom breakpoints in CSS. Use customBreakpoints in initBreakpointHelper() for extra names or fallback.")}const s=_(e),c=JSON.stringify(s.map(a=>[a.name,a.originalValue]));if(o){const a=Object.keys(t).length>0?"defaults + CSS + customBreakpoints":"defaults + CSS";Object.keys(t).length>0&&console.log(b,"customBreakpoints:",t),console.log(b,"Breakpoint source:",a),console.log(b,"Resolved breakpoints:",s.map(P=>`${P.name} (${P.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(s),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 d=i.querySelector(".breakpoint-helper-content");(!d||l.signature!==c)&&(d&&d.remove(),i.appendChild(w(s)),l.signature=c);const p=i.querySelector(".breakpoint-helper-content");p&&g(i,s,p);const u=()=>{const a=i?.querySelector(".breakpoint-helper-content");i&&a&&g(i,s,a)};l.resizeHandler=u,window.addEventListener("resize",u);const h=i.querySelector("#breakpoint-helper-hide-btn");if(h){l.hideHandler&&(h.removeEventListener("click",l.hideHandler),l.hideHandler=void 0);const a=()=>{i.style.display="none",window.setTimeout(()=>{i.style.display="block"},e.hideDuration)};l.hideHandler=a,h.addEventListener("click",a)}v.set(i,l)}function M(){return{...k}}typeof window<"u"&&B()&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>y()):y()),m.DETECTABLE_CUSTOM_NAMES=L,m.getDefaultBreakpoints=M,m.initBreakpointHelper=y,Object.defineProperty(m,Symbol.toStringTag,{value:"Module"})}));
|
|
6
6
|
//# sourceMappingURL=index.umd.js.map
|
package/dist/index.umd.js.map
CHANGED
|
@@ -1 +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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"}
|
|
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 isBase = bp.valuePx === 0\r\n let rangeText: string\r\n let mediaPart: string\r\n\r\n if (isBase) {\r\n const next = resolved[1]\r\n if (next) {\r\n const upperPx = Math.round(next.valuePx) - 1\r\n rangeText = `< ${upperPx}px`\r\n mediaPart = `@media (width < ${next.originalValue})`\r\n } else {\r\n // No other breakpoints; fall back to original text without media info\r\n rangeText = bp.originalValue\r\n mediaPart = ''\r\n }\r\n } else {\r\n const minPx = Math.round(bp.valuePx)\r\n const next = resolved[i + 1]\r\n\r\n if (next && next.valuePx > bp.valuePx) {\r\n const maxPx = Math.round(next.valuePx) - 1\r\n rangeText = `${minPx}px - ${maxPx}px`\r\n } else {\r\n rangeText = `>= ${minPx}px`\r\n }\r\n\r\n mediaPart = `@media (width >= ${bp.originalValue})`\r\n }\r\n\r\n const mediaPartHtml = mediaPart ? ` ${mediaPart}` : ''\r\n span.innerHTML = `<strong class=\"breakpoint-helper-badge\">${escapeHtml(bp.name)}</strong> ${escapeHtml(rangeText)}${mediaPartHtml}`\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","isBase","rangeText","mediaPart","next","minPx","maxPx","mediaPartHtml","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
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
background-color: #ef4444; /* red-500 - base */
|
|
15
15
|
color: white;
|
|
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
|
+
transition: background-color 200ms;
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
/* Default background; JS sets per-breakpoint color via inline style */
|
package/package.json
CHANGED
|
@@ -1,53 +1,59 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@kittler/tailwind-breakpoint-indicator",
|
|
3
|
-
"version": "1.1.
|
|
4
|
-
"description": "Visual breakpoint indicator for Tailwind CSS development",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "./dist/index.js",
|
|
7
|
-
"module": "./dist/index.esm.js",
|
|
8
|
-
"types": "./dist/index.d.ts",
|
|
9
|
-
"exports": {
|
|
10
|
-
".": {
|
|
11
|
-
"types": "./dist/index.d.ts",
|
|
12
|
-
"import": "./dist/index.esm.js",
|
|
13
|
-
"require": "./dist/index.js"
|
|
14
|
-
},
|
|
15
|
-
"./styles": {
|
|
16
|
-
"types": "./dist/styles.d.ts",
|
|
17
|
-
"default": "./dist/styles.css"
|
|
18
|
-
}
|
|
19
|
-
},
|
|
20
|
-
"files": [
|
|
21
|
-
"dist",
|
|
22
|
-
"README.md",
|
|
23
|
-
"LICENSE"
|
|
24
|
-
],
|
|
25
|
-
"scripts": {
|
|
26
|
-
"build": "vite build",
|
|
27
|
-
"dev": "vite build --watch",
|
|
28
|
-
"test:build": "node test/test-build.js",
|
|
29
|
-
"test": "npm run build && npm run test:build",
|
|
30
|
-
"test:server": "node test/server.js",
|
|
31
|
-
"prepublishOnly": "npm run build"
|
|
32
|
-
},
|
|
33
|
-
"keywords": [
|
|
34
|
-
"tailwind",
|
|
35
|
-
"tailwindcss",
|
|
36
|
-
"breakpoint",
|
|
37
|
-
"indicator",
|
|
38
|
-
"development",
|
|
39
|
-
"dev-tools",
|
|
40
|
-
"responsive"
|
|
41
|
-
],
|
|
42
|
-
"author": "",
|
|
43
|
-
"license": "MIT",
|
|
44
|
-
"
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
"
|
|
52
|
-
|
|
53
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@kittler/tailwind-breakpoint-indicator",
|
|
3
|
+
"version": "1.1.3",
|
|
4
|
+
"description": "Visual breakpoint indicator for Tailwind CSS development",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.esm.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.esm.js",
|
|
13
|
+
"require": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"./styles": {
|
|
16
|
+
"types": "./dist/styles.d.ts",
|
|
17
|
+
"default": "./dist/styles.css"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"README.md",
|
|
23
|
+
"LICENSE"
|
|
24
|
+
],
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "vite build",
|
|
27
|
+
"dev": "vite build --watch",
|
|
28
|
+
"test:build": "node test/test-build.js",
|
|
29
|
+
"test": "npm run build && npm run test:build",
|
|
30
|
+
"test:server": "node test/server.js",
|
|
31
|
+
"prepublishOnly": "npm run build"
|
|
32
|
+
},
|
|
33
|
+
"keywords": [
|
|
34
|
+
"tailwind",
|
|
35
|
+
"tailwindcss",
|
|
36
|
+
"breakpoint",
|
|
37
|
+
"indicator",
|
|
38
|
+
"development",
|
|
39
|
+
"dev-tools",
|
|
40
|
+
"responsive"
|
|
41
|
+
],
|
|
42
|
+
"author": "",
|
|
43
|
+
"license": "MIT",
|
|
44
|
+
"funding": [
|
|
45
|
+
{
|
|
46
|
+
"type": "ko-fi",
|
|
47
|
+
"url": "https://ko-fi.com/jakubkittler"
|
|
48
|
+
}
|
|
49
|
+
],
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"typescript": "^5.0.0",
|
|
52
|
+
"vite": "^7.0.0",
|
|
53
|
+
"vite-plugin-dts": "^4.5.0"
|
|
54
|
+
},
|
|
55
|
+
"repository": {
|
|
56
|
+
"type": "git",
|
|
57
|
+
"url": "https://github.com/kittlerstudio/tailwind-breakpoint-indicator.git"
|
|
58
|
+
}
|
|
59
|
+
}
|