@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 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 C = {
1
+ const P = {
2
2
  hideDuration: 2e4
3
- }, m = "[breakpoint-indicator]", E = {
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 L() {
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 P(n) {
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 P(r);
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 a = s.slice(13), i = o.style.getPropertyValue(s).trim();
53
- a && i && (n[a] = i);
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 a = s[1], i = s[2].replace(/\/\*[\s\S]*?\*\//g, "").trim();
80
- a && i && !n[a] && (n[a] = i);
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 = L(), o = n.customBreakpoints && Object.keys(n.customBreakpoints).length > 0 ? n.customBreakpoints : {}, t = { ...E, ...S(), ...o }, s = [];
87
- let a = 0;
88
- for (const [u, d] of Object.entries(t)) {
89
- const p = H(d, r);
90
- if (!Number.isFinite(p) || p <= 0) {
91
- a++;
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: u, valuePx: p, originalValue: d, _i: a }), a++;
94
+ s.push({ name: d, valuePx: u, originalValue: p, _i: c }), c++;
95
95
  }
96
- s.sort((u, d) => u.valuePx - d.valuePx || u._i - d._i);
97
- const i = s.map(({ _i: u, ...d }) => d), l = i.length > 0 ? i[0].valuePx : 640;
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 w() {
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 O(n, e) {
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 = O(e, o), s = g[t % g.length];
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 T(n) {
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 = B(n);
132
+ const r = w(n);
133
133
  return e.appendChild(r), h(e, n, r), e;
134
134
  }
135
- function B(n) {
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"), a = N(t.name);
140
- s.className = `breakpoint-helper-label breakpoint-helper-${a}`, s.setAttribute("data-breakpoint-px", String(t.valuePx)), s.setAttribute("data-breakpoint-name", t.name);
141
- const i = t.valuePx === 0 ? t.originalValue : `${t.originalValue} (${Math.round(t.valuePx)}px)`, l = t.valuePx === 0 ? `@media (width < ${n[1]?.originalValue ?? "40rem"})` : `@media (width >= ${t.originalValue})`;
142
- s.innerHTML = `<strong class="breakpoint-helper-badge">${x(t.name)}</strong> ${x(i)} ${l}`, e.appendChild(s);
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 = { ...C, ...n };
158
- if (!(e.enabled !== void 0 ? e.enabled : w())) {
159
- const c = document.getElementById("breakpoint-helper");
160
- c && (c.style.display = "none");
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 c = S();
166
- console.log(m, "From CSS (--breakpoint-*):", c), Object.keys(c).length === 0 && Object.keys(t).length === 0 && console.log(m, "No custom breakpoints in CSS. Use customBreakpoints in initBreakpointHelper() for extra names or fallback.");
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), a = JSON.stringify(s.map((c) => [c.name, c.originalValue]));
182
+ const s = R(e), c = JSON.stringify(s.map((a) => [a.name, a.originalValue]));
169
183
  if (o) {
170
- const c = Object.keys(t).length > 0 ? "defaults + CSS + customBreakpoints" : "defaults + CSS";
171
- Object.keys(t).length > 0 && console.log(m, "customBreakpoints:", t), console.log(m, "Breakpoint source:", c), console.log(
172
- m,
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 = T(s), document.body.appendChild(i)), i.style.display = "block";
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 && h(i, s, d);
185
- const p = () => {
186
- const c = i?.querySelector(".breakpoint-helper-content");
187
- i && c && h(i, s, c);
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 = p, window.addEventListener("resize", p);
190
- const f = i.querySelector("#breakpoint-helper-hide-btn");
191
- if (f) {
192
- l.hideHandler && (f.removeEventListener("click", l.hideHandler), l.hideHandler = void 0);
193
- const c = () => {
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 = c, f.addEventListener("click", c);
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" && w() && (document.readyState === "loading" ? document.addEventListener("DOMContentLoaded", () => v()) : v());
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,
@@ -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 m=typeof document<"u"?document.currentScript:null;const L={hideDuration:2e4},f="[breakpoint-indicator]",E={sm:"40rem",md:"48rem",lg:"64rem",xl:"80rem","2xl":"96rem"},R=["xs","3xl","4xl"],y=["#ef4444","#22c55e","#3b82f6","#eab308","#a855f7","#ec4899"],v=new WeakMap;function T(){if(typeof document>"u")return 16;const n=document.documentElement,e=getComputedStyle(n).fontSize,s=parseFloat(e);return Number.isNaN(s)?16:s}function P(n){if(typeof document>"u")return 0;const e=document.createElement("div");e.style.position="fixed",e.style.left="-9999px",e.style.top="0",e.style.visibility="hidden",e.style.pointerEvents="none",e.style.width=n,e.style.height="0",e.style.padding="0",e.style.margin="0",e.style.border="0",e.style.boxSizing="content-box",document.documentElement.appendChild(e);const s=e.getBoundingClientRect().width;return e.remove(),Number.isFinite(s)?s:0}function H(n,e){const s=n.trim(),o=s.match(/^(-?\d*\.?\d+)(rem|em|px)$/i);if(!o)return P(s);const t=parseFloat(o[1]),r=(o[2]||"").toLowerCase();return r==="px"?t:r==="rem"||r==="em"?t*e:0}const x=/--breakpoint-([a-zA-Z0-9_-]+)\s*:\s*([^;]+)/g;function B(){const n={};if(typeof document>"u")return n;const e=o=>{try{if(o.style)for(let t=0;t<(o.style.length||0);t++){const r=o.style.item(t);if(r?.startsWith("--breakpoint-")){const a=r.slice(13),i=o.style.getPropertyValue(r).trim();a&&i&&(n[a]=i)}}if(o.cssRules)for(let t=0;t<o.cssRules.length;t++)e(o.cssRules[t]);if(o.styleSheet?.cssRules)for(let t=0;t<o.styleSheet.cssRules.length;t++)e(o.styleSheet.cssRules[t])}catch{}},s=typeof location<"u"?location.origin:"";for(let o=0;o<document.styleSheets.length;o++){const t=document.styleSheets[o];if(!(t.href&&s&&!t.href.startsWith(s)))try{if(t.cssRules)for(let r=0;r<t.cssRules.length;r++)e(t.cssRules[r])}catch{}}for(const o of document.querySelectorAll("style")){const t=o.textContent||"";let r;for(x.lastIndex=0;(r=x.exec(t))!==null;){const a=r[1],i=r[2].replace(/\/\*[\s\S]*?\*\//g,"").trim();a&&i&&!n[a]&&(n[a]=i)}}return n}function N(n){const e=n.baseLabel===void 0?"base":n.baseLabel,s=T(),o=n.customBreakpoints&&Object.keys(n.customBreakpoints).length>0?n.customBreakpoints:{},t={...E,...B(),...o},r=[];let a=0;for(const[u,d]of Object.entries(t)){const p=H(d,s);if(!Number.isFinite(p)||p<=0){a++;continue}r.push({name:u,valuePx:p,originalValue:d,_i:a}),a++}r.sort((u,d)=>u.valuePx-d.valuePx||u._i-d._i);const i=r.map(({_i:u,...d})=>d),l=i.length>0?i[0].valuePx:640;return e!==!1&&i.unshift({name:e,valuePx:0,originalValue:`0 – ${l}px`}),i}function _(n){return n.trim().replace(/\s+/g,"-").replace(/[^a-z0-9_-]/gi,"-").toLowerCase()}function w(){const n={url:typeof document>"u"?require("url").pathToFileURL(__filename).href:m&&m.tagName.toUpperCase()==="SCRIPT"&&m.src||new URL("index.js",document.baseURI).href};if(typeof{url:typeof document>"u"?require("url").pathToFileURL(__filename).href:m&&m.tagName.toUpperCase()==="SCRIPT"&&m.src||new URL("index.js",document.baseURI).href}<"u"&&n.env?.DEV||typeof globalThis<"u"&&globalThis.process?.env?.NODE_ENV==="development")return!0;if(typeof window<"u"){const e=window.location.hostname;if(e==="localhost"||e==="127.0.0.1"||e.startsWith("192.168."))return!0}return!1}function O(n,e){let s=0;for(let o=0;o<n.length;o++)e>=n[o].valuePx&&(s=o);return s}function b(n,e,s){const o=typeof window<"u"?window.innerWidth:0,t=O(e,o),r=y[t%y.length];n.style.backgroundColor=r,s.querySelectorAll(".breakpoint-helper-label").forEach((i,l)=>{i.classList.toggle("breakpoint-helper-active",l===t)})}function A(n){const e=document.createElement("div");e.id="breakpoint-helper",e.className="breakpoint-helper",e.setAttribute("style","display: none");const s=C(n);return e.appendChild(s),b(e,n,s),e}function C(n){const e=document.createElement("div");e.className="breakpoint-helper-content";for(let o=0;o<n.length;o++){const t=n[o],r=document.createElement("span"),a=_(t.name);r.className=`breakpoint-helper-label breakpoint-helper-${a}`,r.setAttribute("data-breakpoint-px",String(t.valuePx)),r.setAttribute("data-breakpoint-name",t.name);const i=t.valuePx===0?t.originalValue:`${t.originalValue} (${Math.round(t.valuePx)}px)`,l=t.valuePx===0?`@media (width < ${n[1]?.originalValue??"40rem"})`:`@media (width >= ${t.originalValue})`;r.innerHTML=`<strong class="breakpoint-helper-badge">${S(t.name)}</strong> ${S(i)} ${l}`,e.appendChild(r)}const s=document.createElement("button");return s.id="breakpoint-helper-hide-btn",s.type="button",s.className="breakpoint-helper-hide-btn",s.setAttribute("aria-label","Hide breakpoint helper for 20 seconds"),s.innerHTML=`
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(s),e}function S(n){const e=document.createElement("div");return e.textContent=n,e.innerHTML}function g(n={}){if(typeof window>"u"||typeof document>"u")return;const e={...L,...n};if(!(e.enabled!==void 0?e.enabled:w())){const c=document.getElementById("breakpoint-helper");c&&(c.style.display="none");return}const o=e.debug===!0,t=e.customBreakpoints&&Object.keys(e.customBreakpoints).length>0?e.customBreakpoints:{};if(o){const c=B();console.log(f,"From CSS (--breakpoint-*):",c),Object.keys(c).length===0&&Object.keys(t).length===0&&console.log(f,"No custom breakpoints in CSS. Use customBreakpoints in initBreakpointHelper() for extra names or fallback.")}const r=N(e),a=JSON.stringify(r.map(c=>[c.name,c.originalValue]));if(o){const c=Object.keys(t).length>0?"defaults + CSS + customBreakpoints":"defaults + CSS";Object.keys(t).length>0&&console.log(f,"customBreakpoints:",t),console.log(f,"Breakpoint source:",c),console.log(f,"Resolved breakpoints:",r.map(k=>`${k.name} (${k.originalValue})`).join(", "))}let i=null;e.containerSelector?i=document.querySelector(e.containerSelector):i=document.getElementById("breakpoint-helper"),i?i.classList.contains("breakpoint-helper")||i.classList.add("breakpoint-helper"):(i=A(r),document.body.appendChild(i)),i.style.display="block";const l=v.get(i)??{};l.resizeHandler&&(window.removeEventListener("resize",l.resizeHandler),l.resizeHandler=void 0);const u=i.querySelector(".breakpoint-helper-content");(!u||l.signature!==a)&&(u&&u.remove(),i.appendChild(C(r)),l.signature=a);const d=i.querySelector(".breakpoint-helper-content");d&&b(i,r,d);const p=()=>{const c=i?.querySelector(".breakpoint-helper-content");i&&c&&b(i,r,c)};l.resizeHandler=p,window.addEventListener("resize",p);const h=i.querySelector("#breakpoint-helper-hide-btn");if(h){l.hideHandler&&(h.removeEventListener("click",l.hideHandler),l.hideHandler=void 0);const c=()=>{i.style.display="none",window.setTimeout(()=>{i.style.display="block"},e.hideDuration)};l.hideHandler=c,h.addEventListener("click",c)}v.set(i,l)}function D(){return{...E}}typeof window<"u"&&w()&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>g()):g());exports.DETECTABLE_CUSTOM_NAMES=R;exports.getDefaultBreakpoints=D;exports.initBreakpointHelper=g;
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,d){typeof exports=="object"&&typeof module<"u"?d(exports):typeof define=="function"&&define.amd?define(["exports"],d):(f=typeof globalThis<"u"?globalThis:f||self,d(f.TailwindBreakpointIndicator={}))})(this,(function(f){"use strict";var d=typeof document<"u"?document.currentScript:null;const L={hideDuration:2e4},h="[breakpoint-indicator]",k={sm:"40rem",md:"48rem",lg:"64rem",xl:"80rem","2xl":"96rem"},R=["xs","3xl","4xl"],v=["#ef4444","#22c55e","#3b82f6","#eab308","#a855f7","#ec4899"],x=new WeakMap;function P(){if(typeof document>"u")return 16;const n=document.documentElement,e=getComputedStyle(n).fontSize,s=parseFloat(e);return Number.isNaN(s)?16:s}function H(n){if(typeof document>"u")return 0;const e=document.createElement("div");e.style.position="fixed",e.style.left="-9999px",e.style.top="0",e.style.visibility="hidden",e.style.pointerEvents="none",e.style.width=n,e.style.height="0",e.style.padding="0",e.style.margin="0",e.style.border="0",e.style.boxSizing="content-box",document.documentElement.appendChild(e);const s=e.getBoundingClientRect().width;return e.remove(),Number.isFinite(s)?s:0}function N(n,e){const s=n.trim(),o=s.match(/^(-?\d*\.?\d+)(rem|em|px)$/i);if(!o)return H(s);const t=parseFloat(o[1]),r=(o[2]||"").toLowerCase();return r==="px"?t:r==="rem"||r==="em"?t*e:0}const S=/--breakpoint-([a-zA-Z0-9_-]+)\s*:\s*([^;]+)/g;function E(){const n={};if(typeof document>"u")return n;const e=o=>{try{if(o.style)for(let t=0;t<(o.style.length||0);t++){const r=o.style.item(t);if(r?.startsWith("--breakpoint-")){const a=r.slice(13),i=o.style.getPropertyValue(r).trim();a&&i&&(n[a]=i)}}if(o.cssRules)for(let t=0;t<o.cssRules.length;t++)e(o.cssRules[t]);if(o.styleSheet?.cssRules)for(let t=0;t<o.styleSheet.cssRules.length;t++)e(o.styleSheet.cssRules[t])}catch{}},s=typeof location<"u"?location.origin:"";for(let o=0;o<document.styleSheets.length;o++){const t=document.styleSheets[o];if(!(t.href&&s&&!t.href.startsWith(s)))try{if(t.cssRules)for(let r=0;r<t.cssRules.length;r++)e(t.cssRules[r])}catch{}}for(const o of document.querySelectorAll("style")){const t=o.textContent||"";let r;for(S.lastIndex=0;(r=S.exec(t))!==null;){const a=r[1],i=r[2].replace(/\/\*[\s\S]*?\*\//g,"").trim();a&&i&&!n[a]&&(n[a]=i)}}return n}function _(n){const e=n.baseLabel===void 0?"base":n.baseLabel,s=P(),o=n.customBreakpoints&&Object.keys(n.customBreakpoints).length>0?n.customBreakpoints:{},t={...k,...E(),...o},r=[];let a=0;for(const[p,u]of Object.entries(t)){const m=N(u,s);if(!Number.isFinite(m)||m<=0){a++;continue}r.push({name:p,valuePx:m,originalValue:u,_i:a}),a++}r.sort((p,u)=>p.valuePx-u.valuePx||p._i-u._i);const i=r.map(({_i:p,...u})=>u),l=i.length>0?i[0].valuePx:640;return e!==!1&&i.unshift({name:e,valuePx:0,originalValue:`0 – ${l}px`}),i}function O(n){return n.trim().replace(/\s+/g,"-").replace(/[^a-z0-9_-]/gi,"-").toLowerCase()}function B(){const n={url:typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:d&&d.tagName.toUpperCase()==="SCRIPT"&&d.src||new URL("index.umd.js",document.baseURI).href};if(typeof{url:typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:d&&d.tagName.toUpperCase()==="SCRIPT"&&d.src||new URL("index.umd.js",document.baseURI).href}<"u"&&n.env?.DEV||typeof globalThis<"u"&&globalThis.process?.env?.NODE_ENV==="development")return!0;if(typeof window<"u"){const e=window.location.hostname;if(e==="localhost"||e==="127.0.0.1"||e.startsWith("192.168."))return!0}return!1}function A(n,e){let s=0;for(let o=0;o<n.length;o++)e>=n[o].valuePx&&(s=o);return s}function b(n,e,s){const o=typeof window<"u"?window.innerWidth:0,t=A(e,o),r=v[t%v.length];n.style.backgroundColor=r,s.querySelectorAll(".breakpoint-helper-label").forEach((i,l)=>{i.classList.toggle("breakpoint-helper-active",l===t)})}function I(n){const e=document.createElement("div");e.id="breakpoint-helper",e.className="breakpoint-helper",e.setAttribute("style","display: none");const s=w(n);return e.appendChild(s),b(e,n,s),e}function w(n){const e=document.createElement("div");e.className="breakpoint-helper-content";for(let o=0;o<n.length;o++){const t=n[o],r=document.createElement("span"),a=O(t.name);r.className=`breakpoint-helper-label breakpoint-helper-${a}`,r.setAttribute("data-breakpoint-px",String(t.valuePx)),r.setAttribute("data-breakpoint-name",t.name);const i=t.valuePx===0?t.originalValue:`${t.originalValue} (${Math.round(t.valuePx)}px)`,l=t.valuePx===0?`@media (width < ${n[1]?.originalValue??"40rem"})`:`@media (width >= ${t.originalValue})`;r.innerHTML=`<strong class="breakpoint-helper-badge">${C(t.name)}</strong> ${C(i)} ${l}`,e.appendChild(r)}const s=document.createElement("button");return s.id="breakpoint-helper-hide-btn",s.type="button",s.className="breakpoint-helper-hide-btn",s.setAttribute("aria-label","Hide breakpoint helper for 20 seconds"),s.innerHTML=`
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(s),e}function C(n){const e=document.createElement("div");return e.textContent=n,e.innerHTML}function g(n={}){if(typeof window>"u"||typeof document>"u")return;const e={...L,...n};if(!(e.enabled!==void 0?e.enabled:B())){const c=document.getElementById("breakpoint-helper");c&&(c.style.display="none");return}const o=e.debug===!0,t=e.customBreakpoints&&Object.keys(e.customBreakpoints).length>0?e.customBreakpoints:{};if(o){const c=E();console.log(h,"From CSS (--breakpoint-*):",c),Object.keys(c).length===0&&Object.keys(t).length===0&&console.log(h,"No custom breakpoints in CSS. Use customBreakpoints in initBreakpointHelper() for extra names or fallback.")}const r=_(e),a=JSON.stringify(r.map(c=>[c.name,c.originalValue]));if(o){const c=Object.keys(t).length>0?"defaults + CSS + customBreakpoints":"defaults + CSS";Object.keys(t).length>0&&console.log(h,"customBreakpoints:",t),console.log(h,"Breakpoint source:",c),console.log(h,"Resolved breakpoints:",r.map(T=>`${T.name} (${T.originalValue})`).join(", "))}let i=null;e.containerSelector?i=document.querySelector(e.containerSelector):i=document.getElementById("breakpoint-helper"),i?i.classList.contains("breakpoint-helper")||i.classList.add("breakpoint-helper"):(i=I(r),document.body.appendChild(i)),i.style.display="block";const l=x.get(i)??{};l.resizeHandler&&(window.removeEventListener("resize",l.resizeHandler),l.resizeHandler=void 0);const p=i.querySelector(".breakpoint-helper-content");(!p||l.signature!==a)&&(p&&p.remove(),i.appendChild(w(r)),l.signature=a);const u=i.querySelector(".breakpoint-helper-content");u&&b(i,r,u);const m=()=>{const c=i?.querySelector(".breakpoint-helper-content");i&&c&&b(i,r,c)};l.resizeHandler=m,window.addEventListener("resize",m);const y=i.querySelector("#breakpoint-helper-hide-btn");if(y){l.hideHandler&&(y.removeEventListener("click",l.hideHandler),l.hideHandler=void 0);const c=()=>{i.style.display="none",window.setTimeout(()=>{i.style.display="block"},e.hideDuration)};l.hideHandler=c,y.addEventListener("click",c)}x.set(i,l)}function j(){return{...k}}typeof window<"u"&&B()&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>g()):g()),f.DETECTABLE_CUSTOM_NAMES=R,f.getDefaultBreakpoints=j,f.initBreakpointHelper=g,Object.defineProperty(f,Symbol.toStringTag,{value:"Module"})}));
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
@@ -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.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
- "devDependencies": {
45
- "typescript": "^5.0.0",
46
- "vite": "^7.0.0",
47
- "vite-plugin-dts": "^4.5.0"
48
- },
49
- "repository": {
50
- "type": "git",
51
- "url": "https://github.com/kittlerstudio/tailwind-breakpoint-indicator.git"
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
+ }