@ytspar/devbar 1.0.0-canary.4b73445 → 1.0.0-canary.6349f79
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/dist/GlobalDevBar.d.ts +3 -23
- package/dist/GlobalDevBar.js +109 -246
- package/package.json +1 -1
package/dist/GlobalDevBar.d.ts
CHANGED
|
@@ -259,30 +259,10 @@ export declare class GlobalDevBar {
|
|
|
259
259
|
private resetToDefaults;
|
|
260
260
|
private renderCollapsed;
|
|
261
261
|
private renderExpanded;
|
|
262
|
-
/**
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
private createTooltipContainer;
|
|
266
|
-
/** Add a bold title to tooltip (metric name, feature name, etc.) */
|
|
267
|
-
private addTooltipTitle;
|
|
268
|
-
/** Add a description paragraph to tooltip */
|
|
269
|
-
private addTooltipDescription;
|
|
270
|
-
/** Add a muted uppercase section header to tooltip */
|
|
271
|
-
private addTooltipSectionHeader;
|
|
272
|
-
/** Add a colored row with dot + label + value (for thresholds) */
|
|
273
|
-
private addTooltipColoredRow;
|
|
274
|
-
/** Add an info row with label + value (for breakpoint details) */
|
|
275
|
-
private addTooltipInfoRow;
|
|
276
|
-
/** Position tooltip above the anchor element, adjusting for screen edges */
|
|
277
|
-
private positionTooltip;
|
|
278
|
-
/** Attach an HTML tooltip to an element with custom content builder */
|
|
279
|
-
private attachHtmlTooltip;
|
|
280
|
-
/** Attach a metric tooltip with title, description, and colored thresholds */
|
|
262
|
+
/**
|
|
263
|
+
* Attach an HTML tooltip with colored threshold labels to a metric element
|
|
264
|
+
*/
|
|
281
265
|
private attachMetricTooltip;
|
|
282
|
-
/** Attach a breakpoint tooltip showing current breakpoint and all breakpoint ranges */
|
|
283
|
-
private attachBreakpointTooltip;
|
|
284
|
-
/** Attach a simple info tooltip with title and description */
|
|
285
|
-
private attachInfoTooltip;
|
|
286
266
|
/**
|
|
287
267
|
* Create a console badge for error/warning counts
|
|
288
268
|
*/
|
package/dist/GlobalDevBar.js
CHANGED
|
@@ -131,23 +131,6 @@ export class GlobalDevBar {
|
|
|
131
131
|
this.showSettingsPopover = false;
|
|
132
132
|
// Overlay element for modals
|
|
133
133
|
this.overlayElement = null;
|
|
134
|
-
// ============================================================================
|
|
135
|
-
// Tooltip Helpers (DRY system for HTML tooltips)
|
|
136
|
-
// ============================================================================
|
|
137
|
-
/** Base styles for tooltip containers */
|
|
138
|
-
this.TOOLTIP_BASE_STYLES = {
|
|
139
|
-
position: 'fixed',
|
|
140
|
-
zIndex: '10004',
|
|
141
|
-
backgroundColor: 'rgba(17, 24, 39, 0.98)',
|
|
142
|
-
border: `1px solid ${COLORS.border}`,
|
|
143
|
-
borderRadius: '6px',
|
|
144
|
-
padding: '10px 12px',
|
|
145
|
-
fontSize: '0.6875rem',
|
|
146
|
-
fontFamily: FONT_MONO,
|
|
147
|
-
maxWidth: '280px',
|
|
148
|
-
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.4)',
|
|
149
|
-
pointerEvents: 'none',
|
|
150
|
-
};
|
|
151
134
|
// Initialize debug config first so we can log during construction
|
|
152
135
|
this.debugConfig = normalizeDebugConfig(options.debug);
|
|
153
136
|
this.debug = new DebugLogger(this.debugConfig);
|
|
@@ -2643,10 +2626,9 @@ export class GlobalDevBar {
|
|
|
2643
2626
|
const bp = this.breakpointInfo.tailwindBreakpoint;
|
|
2644
2627
|
const breakpointData = TAILWIND_BREAKPOINTS[bp];
|
|
2645
2628
|
const bpSpan = document.createElement('span');
|
|
2646
|
-
bpSpan.className = 'devbar-item';
|
|
2629
|
+
bpSpan.className = this.tooltipClass('left', 'devbar-item');
|
|
2647
2630
|
Object.assign(bpSpan.style, { opacity: '0.9', cursor: 'default' });
|
|
2648
|
-
|
|
2649
|
-
this.attachBreakpointTooltip(bpSpan, bp, this.breakpointInfo.dimensions, breakpointData?.label || '');
|
|
2631
|
+
bpSpan.setAttribute('data-tooltip', `Tailwind Breakpoint: ${bp}\n${breakpointData?.label || ''}\n\nViewport: ${this.breakpointInfo.dimensions}\n\nBreakpoints:\nbase: <640px | sm: >=640px\nmd: >=768px | lg: >=1024px\nxl: >=1280px | 2xl: >=1536px`);
|
|
2650
2632
|
let bpText = bp;
|
|
2651
2633
|
if (bp !== 'base') {
|
|
2652
2634
|
bpText =
|
|
@@ -2671,7 +2653,7 @@ export class GlobalDevBar {
|
|
|
2671
2653
|
fcpSpan.className = 'devbar-item';
|
|
2672
2654
|
Object.assign(fcpSpan.style, { opacity: '0.85', cursor: 'default' });
|
|
2673
2655
|
fcpSpan.textContent = `FCP ${this.perfStats.fcp}`;
|
|
2674
|
-
this.attachMetricTooltip(fcpSpan, 'First Contentful Paint (FCP)
|
|
2656
|
+
this.attachMetricTooltip(fcpSpan, 'First Contentful Paint (FCP): Time until first text/image renders.', { good: '<1.8s', needsWork: '1.8-3s', poor: '>3s' });
|
|
2675
2657
|
infoSection.appendChild(fcpSpan);
|
|
2676
2658
|
}
|
|
2677
2659
|
if (showMetrics.lcp) {
|
|
@@ -2680,7 +2662,7 @@ export class GlobalDevBar {
|
|
|
2680
2662
|
lcpSpan.className = 'devbar-item';
|
|
2681
2663
|
Object.assign(lcpSpan.style, { opacity: '0.85', cursor: 'default' });
|
|
2682
2664
|
lcpSpan.textContent = `LCP ${this.perfStats.lcp}`;
|
|
2683
|
-
this.attachMetricTooltip(lcpSpan, 'Largest Contentful Paint (LCP)
|
|
2665
|
+
this.attachMetricTooltip(lcpSpan, 'Largest Contentful Paint (LCP): Time until largest visible element renders.', { good: '<2.5s', needsWork: '2.5-4s', poor: '>4s' });
|
|
2684
2666
|
infoSection.appendChild(lcpSpan);
|
|
2685
2667
|
}
|
|
2686
2668
|
if (showMetrics.cls) {
|
|
@@ -2689,7 +2671,7 @@ export class GlobalDevBar {
|
|
|
2689
2671
|
clsSpan.className = 'devbar-item';
|
|
2690
2672
|
Object.assign(clsSpan.style, { opacity: '0.85', cursor: 'default' });
|
|
2691
2673
|
clsSpan.textContent = `CLS ${this.perfStats.cls}`;
|
|
2692
|
-
this.attachMetricTooltip(clsSpan, 'Cumulative Layout Shift (CLS)
|
|
2674
|
+
this.attachMetricTooltip(clsSpan, 'Cumulative Layout Shift (CLS): Visual stability score. Higher values mean more unexpected layout shifts.', { good: '<0.1', needsWork: '0.1-0.25', poor: '>0.25' });
|
|
2693
2675
|
infoSection.appendChild(clsSpan);
|
|
2694
2676
|
}
|
|
2695
2677
|
if (showMetrics.inp) {
|
|
@@ -2698,15 +2680,15 @@ export class GlobalDevBar {
|
|
|
2698
2680
|
inpSpan.className = 'devbar-item';
|
|
2699
2681
|
Object.assign(inpSpan.style, { opacity: '0.85', cursor: 'default' });
|
|
2700
2682
|
inpSpan.textContent = `INP ${this.perfStats.inp}`;
|
|
2701
|
-
this.attachMetricTooltip(inpSpan, 'Interaction to Next Paint (INP)
|
|
2683
|
+
this.attachMetricTooltip(inpSpan, 'Interaction to Next Paint (INP): Responsiveness to user input. Measures the longest interaction delay.', { good: '<200ms', needsWork: '200-500ms', poor: '>500ms' });
|
|
2702
2684
|
infoSection.appendChild(inpSpan);
|
|
2703
2685
|
}
|
|
2704
2686
|
if (showMetrics.pageSize) {
|
|
2705
2687
|
addSeparator();
|
|
2706
2688
|
const sizeSpan = document.createElement('span');
|
|
2707
|
-
sizeSpan.className = 'devbar-item';
|
|
2689
|
+
sizeSpan.className = this.tooltipClass('left', 'devbar-item');
|
|
2708
2690
|
Object.assign(sizeSpan.style, { opacity: '0.7', cursor: 'default' });
|
|
2709
|
-
|
|
2691
|
+
sizeSpan.setAttribute('data-tooltip', 'Total page size (compressed/transferred).\nIncludes HTML, CSS, JS, images, and other resources.');
|
|
2710
2692
|
sizeSpan.textContent = this.perfStats.totalSize;
|
|
2711
2693
|
infoSection.appendChild(sizeSpan);
|
|
2712
2694
|
}
|
|
@@ -2787,206 +2769,104 @@ export class GlobalDevBar {
|
|
|
2787
2769
|
wrapper.appendChild(customRow);
|
|
2788
2770
|
}
|
|
2789
2771
|
}
|
|
2790
|
-
/**
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
Object.assign(tooltip.style, this.TOOLTIP_BASE_STYLES);
|
|
2795
|
-
return tooltip;
|
|
2796
|
-
}
|
|
2797
|
-
/** Add a bold title to tooltip (metric name, feature name, etc.) */
|
|
2798
|
-
addTooltipTitle(container, title) {
|
|
2799
|
-
const titleEl = document.createElement('div');
|
|
2800
|
-
const accentColor = this.settingsManager.get('accentColor') || COLORS.primary;
|
|
2801
|
-
Object.assign(titleEl.style, {
|
|
2802
|
-
color: accentColor,
|
|
2803
|
-
fontWeight: '600',
|
|
2804
|
-
marginBottom: '4px',
|
|
2805
|
-
});
|
|
2806
|
-
titleEl.textContent = title;
|
|
2807
|
-
container.appendChild(titleEl);
|
|
2808
|
-
}
|
|
2809
|
-
/** Add a description paragraph to tooltip */
|
|
2810
|
-
addTooltipDescription(container, description) {
|
|
2811
|
-
const descEl = document.createElement('div');
|
|
2812
|
-
Object.assign(descEl.style, {
|
|
2813
|
-
color: COLORS.text,
|
|
2814
|
-
marginBottom: '10px',
|
|
2815
|
-
lineHeight: '1.4',
|
|
2816
|
-
});
|
|
2817
|
-
descEl.textContent = description;
|
|
2818
|
-
container.appendChild(descEl);
|
|
2819
|
-
}
|
|
2820
|
-
/** Add a muted uppercase section header to tooltip */
|
|
2821
|
-
addTooltipSectionHeader(container, header) {
|
|
2822
|
-
const headerEl = document.createElement('div');
|
|
2823
|
-
Object.assign(headerEl.style, {
|
|
2824
|
-
color: COLORS.textMuted,
|
|
2825
|
-
fontSize: '0.625rem',
|
|
2826
|
-
textTransform: 'uppercase',
|
|
2827
|
-
letterSpacing: '0.05em',
|
|
2828
|
-
marginBottom: '6px',
|
|
2829
|
-
});
|
|
2830
|
-
headerEl.textContent = header;
|
|
2831
|
-
container.appendChild(headerEl);
|
|
2832
|
-
}
|
|
2833
|
-
/** Add a colored row with dot + label + value (for thresholds) */
|
|
2834
|
-
addTooltipColoredRow(container, label, value, color, labelWidth = '70px') {
|
|
2835
|
-
const row = document.createElement('div');
|
|
2836
|
-
Object.assign(row.style, { display: 'flex', alignItems: 'center', gap: '8px' });
|
|
2837
|
-
const dot = document.createElement('span');
|
|
2838
|
-
Object.assign(dot.style, {
|
|
2839
|
-
width: '6px',
|
|
2840
|
-
height: '6px',
|
|
2841
|
-
borderRadius: '50%',
|
|
2842
|
-
backgroundColor: color,
|
|
2843
|
-
flexShrink: '0',
|
|
2844
|
-
});
|
|
2845
|
-
row.appendChild(dot);
|
|
2846
|
-
const labelSpan = document.createElement('span');
|
|
2847
|
-
Object.assign(labelSpan.style, {
|
|
2848
|
-
color,
|
|
2849
|
-
fontWeight: '500',
|
|
2850
|
-
minWidth: labelWidth,
|
|
2851
|
-
});
|
|
2852
|
-
labelSpan.textContent = label;
|
|
2853
|
-
row.appendChild(labelSpan);
|
|
2854
|
-
const valueSpan = document.createElement('span');
|
|
2855
|
-
Object.assign(valueSpan.style, { color: COLORS.textMuted });
|
|
2856
|
-
valueSpan.textContent = value;
|
|
2857
|
-
row.appendChild(valueSpan);
|
|
2858
|
-
container.appendChild(row);
|
|
2859
|
-
}
|
|
2860
|
-
/** Add an info row with label + value (for breakpoint details) */
|
|
2861
|
-
addTooltipInfoRow(container, label, value) {
|
|
2862
|
-
const row = document.createElement('div');
|
|
2863
|
-
Object.assign(row.style, {
|
|
2864
|
-
display: 'flex',
|
|
2865
|
-
gap: '8px',
|
|
2866
|
-
lineHeight: '1.4',
|
|
2867
|
-
});
|
|
2868
|
-
const labelSpan = document.createElement('span');
|
|
2869
|
-
Object.assign(labelSpan.style, { color: COLORS.textMuted });
|
|
2870
|
-
labelSpan.textContent = label;
|
|
2871
|
-
row.appendChild(labelSpan);
|
|
2872
|
-
const valueSpan = document.createElement('span');
|
|
2873
|
-
Object.assign(valueSpan.style, { color: COLORS.text });
|
|
2874
|
-
valueSpan.textContent = value;
|
|
2875
|
-
row.appendChild(valueSpan);
|
|
2876
|
-
container.appendChild(row);
|
|
2877
|
-
}
|
|
2878
|
-
/** Position tooltip above the anchor element, adjusting for screen edges */
|
|
2879
|
-
positionTooltip(tooltip, anchor) {
|
|
2880
|
-
const rect = anchor.getBoundingClientRect();
|
|
2881
|
-
tooltip.style.left = `${rect.left}px`;
|
|
2882
|
-
tooltip.style.bottom = `${window.innerHeight - rect.top + 8}px`;
|
|
2883
|
-
document.body.appendChild(tooltip);
|
|
2884
|
-
// Adjust if off-screen
|
|
2885
|
-
const tooltipRect = tooltip.getBoundingClientRect();
|
|
2886
|
-
if (tooltipRect.right > window.innerWidth - 10) {
|
|
2887
|
-
tooltip.style.left = `${window.innerWidth - tooltipRect.width - 10}px`;
|
|
2888
|
-
}
|
|
2889
|
-
if (tooltipRect.left < 10) {
|
|
2890
|
-
tooltip.style.left = '10px';
|
|
2891
|
-
}
|
|
2892
|
-
}
|
|
2893
|
-
/** Attach an HTML tooltip to an element with custom content builder */
|
|
2894
|
-
attachHtmlTooltip(element, buildContent) {
|
|
2772
|
+
/**
|
|
2773
|
+
* Attach an HTML tooltip with colored threshold labels to a metric element
|
|
2774
|
+
*/
|
|
2775
|
+
attachMetricTooltip(element, description, thresholds) {
|
|
2895
2776
|
let tooltipEl = null;
|
|
2896
2777
|
element.onmouseenter = () => {
|
|
2897
|
-
tooltipEl =
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
/** Attach a metric tooltip with title, description, and colored thresholds */
|
|
2912
|
-
attachMetricTooltip(element, title, description, thresholds) {
|
|
2913
|
-
this.attachHtmlTooltip(element, (tooltip) => {
|
|
2914
|
-
this.addTooltipTitle(tooltip, title);
|
|
2915
|
-
this.addTooltipDescription(tooltip, description);
|
|
2916
|
-
this.addTooltipSectionHeader(tooltip, 'Thresholds');
|
|
2917
|
-
const thresholdsContainer = document.createElement('div');
|
|
2918
|
-
Object.assign(thresholdsContainer.style, {
|
|
2919
|
-
display: 'flex',
|
|
2920
|
-
flexDirection: 'column',
|
|
2921
|
-
gap: '4px',
|
|
2778
|
+
tooltipEl = document.createElement('div');
|
|
2779
|
+
tooltipEl.setAttribute('data-devbar', 'true');
|
|
2780
|
+
Object.assign(tooltipEl.style, {
|
|
2781
|
+
position: 'fixed',
|
|
2782
|
+
zIndex: '10004',
|
|
2783
|
+
backgroundColor: 'rgba(17, 24, 39, 0.98)',
|
|
2784
|
+
border: `1px solid ${COLORS.border}`,
|
|
2785
|
+
borderRadius: '6px',
|
|
2786
|
+
padding: '10px 12px',
|
|
2787
|
+
fontSize: '0.6875rem',
|
|
2788
|
+
fontFamily: FONT_MONO,
|
|
2789
|
+
maxWidth: '280px',
|
|
2790
|
+
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.4)',
|
|
2791
|
+
pointerEvents: 'none',
|
|
2922
2792
|
});
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2793
|
+
// Description
|
|
2794
|
+
const descEl = document.createElement('div');
|
|
2795
|
+
Object.assign(descEl.style, {
|
|
2796
|
+
color: COLORS.text,
|
|
2797
|
+
marginBottom: '10px',
|
|
2798
|
+
lineHeight: '1.4',
|
|
2799
|
+
});
|
|
2800
|
+
descEl.textContent = description;
|
|
2801
|
+
tooltipEl.appendChild(descEl);
|
|
2802
|
+
// Thresholds header
|
|
2803
|
+
const thresholdsHeader = document.createElement('div');
|
|
2804
|
+
Object.assign(thresholdsHeader.style, {
|
|
2805
|
+
color: COLORS.textMuted,
|
|
2806
|
+
fontSize: '0.625rem',
|
|
2807
|
+
textTransform: 'uppercase',
|
|
2808
|
+
letterSpacing: '0.05em',
|
|
2809
|
+
marginBottom: '6px',
|
|
2810
|
+
});
|
|
2811
|
+
thresholdsHeader.textContent = 'Thresholds';
|
|
2812
|
+
tooltipEl.appendChild(thresholdsHeader);
|
|
2813
|
+
// Thresholds with colors
|
|
2814
|
+
const thresholdsEl = document.createElement('div');
|
|
2815
|
+
Object.assign(thresholdsEl.style, {
|
|
2943
2816
|
display: 'flex',
|
|
2944
2817
|
flexDirection: 'column',
|
|
2945
|
-
gap: '
|
|
2946
|
-
fontSize: '0.625rem',
|
|
2818
|
+
gap: '4px',
|
|
2947
2819
|
});
|
|
2948
|
-
const
|
|
2949
|
-
{ name: 'base', range: '<640px' },
|
|
2950
|
-
{ name: 'sm', range: '≥640px' },
|
|
2951
|
-
{ name: 'md', range: '≥768px' },
|
|
2952
|
-
{ name: 'lg', range: '≥1024px' },
|
|
2953
|
-
{ name: 'xl', range: '≥1280px' },
|
|
2954
|
-
{ name: '2xl', range: '≥1536px' },
|
|
2955
|
-
];
|
|
2956
|
-
for (const bp of breakpoints) {
|
|
2820
|
+
const addThreshold = (label, value, color) => {
|
|
2957
2821
|
const row = document.createElement('div');
|
|
2958
|
-
Object.assign(row.style, { display: 'flex', gap: '8px' });
|
|
2959
|
-
const
|
|
2960
|
-
Object.assign(
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2822
|
+
Object.assign(row.style, { display: 'flex', alignItems: 'center', gap: '8px' });
|
|
2823
|
+
const dot = document.createElement('span');
|
|
2824
|
+
Object.assign(dot.style, {
|
|
2825
|
+
width: '6px',
|
|
2826
|
+
height: '6px',
|
|
2827
|
+
borderRadius: '50%',
|
|
2828
|
+
backgroundColor: color,
|
|
2829
|
+
flexShrink: '0',
|
|
2964
2830
|
});
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2831
|
+
row.appendChild(dot);
|
|
2832
|
+
const labelSpan = document.createElement('span');
|
|
2833
|
+
Object.assign(labelSpan.style, {
|
|
2834
|
+
color,
|
|
2835
|
+
fontWeight: '500',
|
|
2836
|
+
minWidth: '70px',
|
|
2970
2837
|
});
|
|
2971
|
-
|
|
2972
|
-
row.appendChild(
|
|
2973
|
-
|
|
2838
|
+
labelSpan.textContent = label;
|
|
2839
|
+
row.appendChild(labelSpan);
|
|
2840
|
+
const valueSpan = document.createElement('span');
|
|
2841
|
+
Object.assign(valueSpan.style, { color: COLORS.textMuted });
|
|
2842
|
+
valueSpan.textContent = value;
|
|
2843
|
+
row.appendChild(valueSpan);
|
|
2844
|
+
thresholdsEl.appendChild(row);
|
|
2845
|
+
};
|
|
2846
|
+
addThreshold('Good', thresholds.good, COLORS.primary);
|
|
2847
|
+
addThreshold('Needs work', thresholds.needsWork, COLORS.warning);
|
|
2848
|
+
addThreshold('Poor', thresholds.poor, COLORS.error);
|
|
2849
|
+
tooltipEl.appendChild(thresholdsEl);
|
|
2850
|
+
// Position tooltip above element
|
|
2851
|
+
const rect = element.getBoundingClientRect();
|
|
2852
|
+
tooltipEl.style.left = `${rect.left}px`;
|
|
2853
|
+
tooltipEl.style.bottom = `${window.innerHeight - rect.top + 8}px`;
|
|
2854
|
+
document.body.appendChild(tooltipEl);
|
|
2855
|
+
// Adjust if off-screen
|
|
2856
|
+
const tooltipRect = tooltipEl.getBoundingClientRect();
|
|
2857
|
+
if (tooltipRect.right > window.innerWidth - 10) {
|
|
2858
|
+
tooltipEl.style.left = `${window.innerWidth - tooltipRect.width - 10}px`;
|
|
2974
2859
|
}
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
lineHeight: '1.4',
|
|
2986
|
-
});
|
|
2987
|
-
descEl.textContent = description;
|
|
2988
|
-
tooltip.appendChild(descEl);
|
|
2989
|
-
});
|
|
2860
|
+
if (tooltipRect.left < 10) {
|
|
2861
|
+
tooltipEl.style.left = '10px';
|
|
2862
|
+
}
|
|
2863
|
+
};
|
|
2864
|
+
element.onmouseleave = () => {
|
|
2865
|
+
if (tooltipEl) {
|
|
2866
|
+
tooltipEl.remove();
|
|
2867
|
+
tooltipEl = null;
|
|
2868
|
+
}
|
|
2869
|
+
};
|
|
2990
2870
|
}
|
|
2991
2871
|
/**
|
|
2992
2872
|
* Create a console badge for error/warning counts
|
|
@@ -3026,9 +2906,6 @@ export class GlobalDevBar {
|
|
|
3026
2906
|
btn.type = 'button';
|
|
3027
2907
|
btn.className = this.tooltipClass('right');
|
|
3028
2908
|
const hasSuccessState = this.copiedToClipboard || this.copiedPath || this.lastScreenshot;
|
|
3029
|
-
const isDisabled = this.capturing;
|
|
3030
|
-
// Grey out when not connected (save won't work, but clipboard still does)
|
|
3031
|
-
const isGreyedOut = !this.sweetlinkConnected && !hasSuccessState;
|
|
3032
2909
|
const tooltip = this.getScreenshotTooltip();
|
|
3033
2910
|
btn.setAttribute('data-tooltip', tooltip);
|
|
3034
2911
|
Object.assign(btn.style, {
|
|
@@ -3045,11 +2922,11 @@ export class GlobalDevBar {
|
|
|
3045
2922
|
borderColor: hasSuccessState ? accentColor : `${accentColor}80`,
|
|
3046
2923
|
backgroundColor: hasSuccessState ? `${accentColor}33` : 'transparent',
|
|
3047
2924
|
color: hasSuccessState ? accentColor : `${accentColor}99`,
|
|
3048
|
-
cursor: !
|
|
3049
|
-
opacity:
|
|
2925
|
+
cursor: !this.capturing ? 'pointer' : 'not-allowed',
|
|
2926
|
+
opacity: '1',
|
|
3050
2927
|
transition: 'all 150ms',
|
|
3051
2928
|
});
|
|
3052
|
-
btn.disabled =
|
|
2929
|
+
btn.disabled = this.capturing;
|
|
3053
2930
|
btn.onclick = (e) => {
|
|
3054
2931
|
// If we have a saved screenshot path, clicking copies the path
|
|
3055
2932
|
if (this.lastScreenshot && !e.shiftKey) {
|
|
@@ -3106,10 +2983,10 @@ export class GlobalDevBar {
|
|
|
3106
2983
|
if (this.lastScreenshot) {
|
|
3107
2984
|
return `Screenshot saved!\n${this.lastScreenshot}\n\nClick to copy path`;
|
|
3108
2985
|
}
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
2986
|
+
const baseTooltip = `Screenshot\n\nClick: Save to file\nShift+Click: Copy to clipboard\n\nKeyboard:\nCmd/Ctrl+Shift+S: Save\nCmd/Ctrl+Shift+C: Copy`;
|
|
2987
|
+
return this.sweetlinkConnected
|
|
2988
|
+
? baseTooltip
|
|
2989
|
+
: `${baseTooltip}\n\nWarning: Sweetlink not connected`;
|
|
3113
2990
|
}
|
|
3114
2991
|
/**
|
|
3115
2992
|
* Get the tooltip text for the AI review button based on current state
|
|
@@ -3169,16 +3046,9 @@ export class GlobalDevBar {
|
|
|
3169
3046
|
const btn = document.createElement('button');
|
|
3170
3047
|
btn.type = 'button';
|
|
3171
3048
|
btn.className = this.tooltipClass('right');
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
}
|
|
3176
|
-
else if (!this.sweetlinkConnected) {
|
|
3177
|
-
tooltip = `Document Outline\n\nView page heading structure.\n\n⚠ Sweetlink not connected\nSave to file unavailable`;
|
|
3178
|
-
}
|
|
3179
|
-
else {
|
|
3180
|
-
tooltip = `Document Outline\n\nView page heading structure and\nsave as markdown.`;
|
|
3181
|
-
}
|
|
3049
|
+
const tooltip = this.lastOutline
|
|
3050
|
+
? `Outline saved to:\n${this.lastOutline}`
|
|
3051
|
+
: `Document Outline\n\nView page heading structure and\nsave as markdown.`;
|
|
3182
3052
|
btn.setAttribute('data-tooltip', tooltip);
|
|
3183
3053
|
const isActive = this.showOutlineModal || !!this.lastOutline;
|
|
3184
3054
|
Object.assign(btn.style, getButtonStyles(BUTTON_COLORS.outline, isActive, false));
|
|
@@ -3196,16 +3066,9 @@ export class GlobalDevBar {
|
|
|
3196
3066
|
const btn = document.createElement('button');
|
|
3197
3067
|
btn.type = 'button';
|
|
3198
3068
|
btn.className = this.tooltipClass('right');
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
}
|
|
3203
|
-
else if (!this.sweetlinkConnected) {
|
|
3204
|
-
tooltip = `Page Schema\n\nView JSON-LD, Open Graph, and\nother structured data.\n\n⚠ Sweetlink not connected\nSave to file unavailable`;
|
|
3205
|
-
}
|
|
3206
|
-
else {
|
|
3207
|
-
tooltip = `Page Schema\n\nView JSON-LD, Open Graph, and\nother structured data.`;
|
|
3208
|
-
}
|
|
3069
|
+
const tooltip = this.lastSchema
|
|
3070
|
+
? `Schema saved to:\n${this.lastSchema}`
|
|
3071
|
+
: `Page Schema\n\nView JSON-LD, Open Graph, and\nother structured data.`;
|
|
3209
3072
|
btn.setAttribute('data-tooltip', tooltip);
|
|
3210
3073
|
const isActive = this.showSchemaModal || !!this.lastSchema;
|
|
3211
3074
|
Object.assign(btn.style, getButtonStyles(BUTTON_COLORS.schema, isActive, false));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ytspar/devbar",
|
|
3
|
-
"version": "1.0.0-canary.
|
|
3
|
+
"version": "1.0.0-canary.6349f79",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"private": false,
|
|
6
6
|
"description": "Development toolbar and utilities with Sweetlink integration - pure vanilla JS, no framework dependencies",
|