diff --git a/dist-extension/toolbar.html b/dist-extension/toolbar.html
index e8685ed2..cc713f45 100644
--- a/dist-extension/toolbar.html
+++ b/dist-extension/toolbar.html
@@ -1,396 +1,67 @@
-
+
-
- Dev Tools Toolbar
+
+ DevTools toolbar
-
-
+
+
diff --git a/dist-extension/toolbar.js b/dist-extension/toolbar.js
index 857c2d45..448fa939 100644
--- a/dist-extension/toolbar.js
+++ b/dist-extension/toolbar.js
@@ -1,446 +1,87 @@
-// Dev Tools Toolbar JavaScript
-// Floating toolbar similar to Vercel Toolbar
-
+const browserAPI = typeof browser !== 'undefined' ? browser : chrome;
const toolbar = document.getElementById('toolbar');
const menuBtn = document.getElementById('menuBtn');
const menuPanel = document.getElementById('menuPanel');
const menuSearch = document.getElementById('menuSearch');
+const toolSections = document.getElementById('toolSections');
const statusIndicator = document.getElementById('statusIndicator');
const dragHandle = document.getElementById('dragHandle');
-
-let isSleeping = true;
+const tools = [
+ { category: 'Quick actions', items: [
+ { id: 'search', label: 'Search all tools', description: 'Find a utility by name', icon: 'β', shortcut: '/' },
+ { id: 'inspect', label: 'Inspect element', description: 'Pick an element on this page', icon: 'β' },
+ { id: 'screenshot', label: 'Capture screenshot', description: 'Save the current page view', icon: 'β£' },
+ ]},
+ { category: 'Popular tools', items: [
+ { label: 'JSON Viewer', description: 'Format and explore JSON', icon: '{}' , path: 'json-viewer' },
+ { label: 'Base64 Converter', description: 'Encode and decode Base64', icon: '64', path: 'base64-string-converter' },
+ { label: 'Regex Tester', description: 'Build and test regular expressions', icon: '.*', path: 'regex-tester' },
+ { label: 'Color Converter', description: 'Convert colors between formats', icon: 'β', path: 'color-converter' },
+ { label: 'JWT Decoder', description: 'Inspect JSON Web Tokens', icon: 'jwt', path: 'jwt-decoder' },
+ ]},
+ { category: 'All tools', items: [
+ { label: 'Open DevTools', description: 'Browse the complete tool library', icon: 'β', path: '' },
+ ]},
+ { category: 'Settings', items: [
+ { id: 'preferences', label: 'Preferences', description: 'Configure toolbar behavior', icon: 'β' },
+ { id: 'hide', label: 'Hide toolbar', description: 'Show it again from the extension menu', icon: 'β', shortcut: 'Esc' },
+ ]},
+];
+let isSleeping = false;
let isMenuOpen = false;
let isDragging = false;
let dragOffset = { x: 0, y: 0 };
-// Default shortcuts
-const defaultShortcuts = {
- menu: 'Control',
- search: '/',
- inspect: '',
- screenshot: '',
- hide: 'Escape',
- json: '',
- base64: '',
-};
-
-// Current shortcuts
-let shortcuts = { ...defaultShortcuts };
-
-// Initialize toolbar
-function initToolbar() {
- loadPosition();
- loadState();
- loadShortcuts();
- setupEventListeners();
- setupKeyboardShortcuts();
-}
-
-// Load shortcuts from storage
-function loadShortcuts() {
- if (typeof browser !== 'undefined') {
- browser.storage.local.get(['shortcuts'], (result) => {
- shortcuts = { ...defaultShortcuts, ...(result.shortcuts || {}) };
- updateMenuShortcuts();
- });
- } else if (typeof chrome !== 'undefined') {
- chrome.storage.local.get(['shortcuts'], (result) => {
- shortcuts = { ...defaultShortcuts, ...(result.shortcuts || {}) };
- updateMenuShortcuts();
- });
- }
-}
-
-// Update menu shortcuts display
-function updateMenuShortcuts() {
- const shortcutMap = {
- search: 'search',
- inspect: 'inspect',
- screenshot: 'screenshot',
- hide: 'hide',
- };
-
- Object.keys(shortcutMap).forEach(action => {
- const shortcut = shortcuts[action];
- const items = menuPanel.querySelectorAll(`[data-action="${action}"]`);
- items.forEach(item => {
- let shortcutEl = item.querySelector('.menu-item-shortcut');
- if (!shortcutEl) {
- shortcutEl = document.createElement('span');
- shortcutEl.className = 'menu-item-shortcut';
- item.appendChild(shortcutEl);
- }
- shortcutEl.textContent = shortcut || '';
- shortcutEl.style.display = shortcut ? 'block' : 'none';
- });
- });
-}
-
-// Load saved position
-function loadPosition() {
- const position = localStorage.getItem('it-toolbar-position');
- if (position) {
- const { x, y } = JSON.parse(position);
- toolbar.style.right = 'auto';
- toolbar.style.left = `${x}px`;
- toolbar.style.top = `${y}px`;
- toolbar.style.transform = 'none';
- }
-}
-
-// Save position
-function savePosition() {
- const rect = toolbar.getBoundingClientRect();
- localStorage.setItem('it-toolbar-position', JSON.stringify({
- x: rect.left,
- y: rect.top,
- }));
-}
-
-// Load state (sleeping/active)
-function loadState() {
- const state = localStorage.getItem('it-toolbar-state');
- if (state === 'active') {
- wakeUp();
- } else {
- sleep();
- }
-}
-
-// Setup event listeners
-function setupEventListeners() {
- // Menu toggle
- menuBtn.addEventListener('click', toggleMenu);
-
- // Close menu when clicking outside
- document.addEventListener('click', (e) => {
- if (!toolbar.contains(e.target)) {
- closeMenu();
- }
- });
-
- // Menu item clicks
- menuPanel.querySelectorAll('.menu-item').forEach(item => {
- item.addEventListener('click', (e) => {
- const action = item.dataset.action;
- if (action) {
- e.preventDefault();
- handleMenuAction(action);
- }
- });
- });
-
- // Search
- menuSearch.addEventListener('input', (e) => {
- filterMenuItems(e.target.value);
- });
-
- // Dragging
- dragHandle.addEventListener('mousedown', startDrag);
- document.addEventListener('mousemove', onDrag);
- document.addEventListener('mouseup', stopDrag);
-
- // Toolbar buttons
- document.getElementById('searchBtn').addEventListener('click', () => {
- menuSearch.focus();
- openMenu();
- });
-
- document.getElementById('inspectBtn').addEventListener('click', () => {
- sendMessage('inspectElement');
- });
-
- document.getElementById('screenshotBtn').addEventListener('click', () => {
- sendMessage('takeScreenshot');
- });
-
- document.getElementById('hideBtn').addEventListener('click', () => {
- hideToolbar();
- });
-
- // Click on toolbar to wake up
- toolbar.addEventListener('click', () => {
- if (isSleeping) {
- wakeUp();
- }
- });
-}
-
-// Setup keyboard shortcuts
-function setupKeyboardShortcuts() {
- document.addEventListener('keydown', (e) => {
- const shortcut = buildShortcutString(e);
-
- // Check each shortcut
- if (shortcut === shortcuts.menu) {
- e.preventDefault();
- toggleMenu();
- }
-
- if (shortcut === shortcuts.search) {
- e.preventDefault();
- menuSearch.focus();
- openMenu();
- }
-
- if (shortcut === shortcuts.inspect) {
- e.preventDefault();
- sendMessage('inspectElement');
- }
-
- if (shortcut === shortcuts.screenshot) {
- e.preventDefault();
- sendMessage('takeScreenshot');
- }
-
- if (shortcut === shortcuts.hide) {
- e.preventDefault();
- if (isMenuOpen) {
- closeMenu();
- } else {
- hideToolbar();
- }
- }
-
- if (shortcut === shortcuts.json) {
- e.preventDefault();
- window.open('https://devtools.khulnasoft.com/json-viewer', '_blank');
- }
-
- if (shortcut === shortcuts.base64) {
- e.preventDefault();
- window.open('https://devtools.khulnasoft.com/base64-string-converter', '_blank');
- }
- });
-}
-
-// Build shortcut string from keyboard event
-function buildShortcutString(e) {
- const parts = [];
-
- if (e.ctrlKey) parts.push('Ctrl');
- if (e.altKey) parts.push('Alt');
- if (e.shiftKey) parts.push('Shift');
- if (e.metaKey) parts.push('Cmd');
-
- const key = e.key;
- if (!parts.includes(key) && key !== 'Control' && key !== 'Alt' && key !== 'Shift' && key !== 'Meta') {
- parts.push(key);
- }
-
- return parts.join('+');
-}
-
-// Toggle menu
-function toggleMenu() {
- if (isMenuOpen) {
- closeMenu();
- } else {
- openMenu();
- }
-}
-
-// Open menu
-function openMenu() {
- isMenuOpen = true;
- menuPanel.classList.add('open');
- menuBtn.classList.add('active');
- if (isSleeping) {
- wakeUp();
- }
-}
-
-// Close menu
-function closeMenu() {
- isMenuOpen = false;
- menuPanel.classList.remove('open');
- menuBtn.classList.remove('active');
- menuSearch.value = '';
- filterMenuItems('');
-}
-
-// Filter menu items
-function filterMenuItems(query) {
- const items = menuPanel.querySelectorAll('.menu-item');
- const lowerQuery = query.toLowerCase();
-
- items.forEach(item => {
- const text = item.querySelector('.menu-item-text').textContent.toLowerCase();
- if (text.includes(lowerQuery)) {
- item.style.display = 'flex';
- } else {
- item.style.display = 'none';
- }
- });
-}
-
-// Handle menu action
-function handleMenuAction(action) {
- closeMenu();
-
- switch (action) {
- case 'search':
- menuSearch.focus();
- openMenu();
- break;
- case 'inspect':
- sendMessage('inspectElement');
- break;
- case 'screenshot':
- sendMessage('takeScreenshot');
- break;
- case 'preferences':
- sendMessage('openPreferences');
- break;
- case 'hide':
- hideToolbar();
- break;
- }
-}
-
-// Wake up toolbar
-function wakeUp() {
- isSleeping = false;
- toolbar.classList.remove('sleeping');
- statusIndicator.classList.remove('sleeping');
- localStorage.setItem('it-toolbar-state', 'active');
-}
-
-// Sleep toolbar
-function sleep() {
- isSleeping = true;
- toolbar.classList.add('sleeping');
- statusIndicator.classList.add('sleeping');
- localStorage.setItem('it-toolbar-state', 'sleeping');
-}
-
-// Hide toolbar
-function hideToolbar() {
- toolbar.style.display = 'none';
- // Create a small indicator to show toolbar again
- showRestoreIndicator();
-}
-
-// Show restore indicator
-function showRestoreIndicator() {
- const indicator = document.createElement('button');
- indicator.id = 'it-toolbar-restore';
- indicator.innerHTML = 'π οΈ';
- indicator.style.cssText = `
- position: fixed;
- bottom: 20px;
- right: 20px;
- width: 50px;
- height: 50px;
- border-radius: 50%;
- background: #18a058;
- color: white;
- border: none;
- cursor: pointer;
- z-index: 999999;
- font-size: 24px;
- box-shadow: 0 4px 12px rgba(0,0,0,0.3);
- transition: transform 0.2s;
- `;
-
- indicator.addEventListener('mouseenter', () => {
- indicator.style.transform = 'scale(1.1)';
- });
-
- indicator.addEventListener('mouseleave', () => {
- indicator.style.transform = 'scale(1)';
- });
-
- indicator.addEventListener('click', () => {
- toolbar.style.display = 'flex';
- indicator.remove();
- wakeUp();
- });
-
- document.body.appendChild(indicator);
-}
-
-// Dragging
-function startDrag(e) {
- isDragging = true;
- const rect = toolbar.getBoundingClientRect();
- dragOffset.x = e.clientX - rect.left;
- dragOffset.y = e.clientY - rect.top;
- toolbar.style.transition = 'none';
-}
-
-function onDrag(e) {
- if (!isDragging) return;
-
- const x = e.clientX - dragOffset.x;
- const y = e.clientY - dragOffset.y;
-
- // Constrain to viewport
- const maxX = window.innerWidth - toolbar.offsetWidth;
- const maxY = window.innerHeight - toolbar.offsetHeight;
-
- toolbar.style.left = `${Math.max(0, Math.min(x, maxX))}px`;
- toolbar.style.top = `${Math.max(0, Math.min(y, maxY))}px`;
- toolbar.style.right = 'auto';
- toolbar.style.transform = 'none';
-}
-
-function stopDrag() {
- if (isDragging) {
- isDragging = false;
- toolbar.style.transition = 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)';
- savePosition();
- }
-}
-
-// Send message to extension
-function sendMessage(action) {
- if (typeof browser !== 'undefined') {
- browser.runtime.sendMessage({ action });
- } else if (typeof chrome !== 'undefined') {
- chrome.runtime.sendMessage({ action });
- }
-}
-
-// Listen for messages from extension
-if (typeof browser !== 'undefined') {
- browser.runtime.onMessage.addListener(handleMessage);
-} else if (typeof chrome !== 'undefined') {
- chrome.runtime.onMessage.addListener(handleMessage);
-}
-
-function handleMessage(request, sender, sendResponse) {
- if (request.action === 'showToolbar') {
- toolbar.style.display = 'flex';
- const indicator = document.getElementById('it-toolbar-restore');
- if (indicator) indicator.remove();
- wakeUp();
- }
-
- if (request.action === 'hideToolbar') {
- hideToolbar();
- }
-
- if (request.action === 'wakeUp') {
- wakeUp();
- }
-
- if (request.action === 'sleep') {
- sleep();
- }
-
- if (request.action === 'updateShortcuts') {
- shortcuts = { ...defaultShortcuts, ...(request.shortcuts || {}) };
- updateMenuShortcuts();
- }
-
- sendResponse({ success: true });
- return true;
-}
-
-// Initialize on load
-if (document.readyState === 'loading') {
- document.addEventListener('DOMContentLoaded', initToolbar);
-} else {
- initToolbar();
-}
+function renderTools(query = '') {
+ const normalized = query.trim().toLowerCase();
+ const html = tools.map((section) => {
+ const items = section.items.filter((item) => !normalized || `${item.label} ${item.description}`.toLowerCase().includes(normalized));
+ if (!items.length) return '';
+ return ``;
+ }).join('');
+ toolSections.innerHTML = html || 'No tools match your search.
';
+}
+
+function sendMessage(action) { browserAPI.runtime.sendMessage({ action }).catch(() => {}); }
+function openMenu(focus = false) { isMenuOpen = true; menuPanel.classList.add('open'); menuBtn.classList.add('active'); menuBtn.setAttribute('aria-expanded', 'true'); if (focus) menuSearch.focus(); }
+function closeMenu() { isMenuOpen = false; menuPanel.classList.remove('open'); menuBtn.classList.remove('active'); menuBtn.setAttribute('aria-expanded', 'false'); menuSearch.value = ''; renderTools(); }
+function hideToolbar() { toolbar.style.display = 'none'; browserAPI.storage.local.set({ toolbarHidden: true }); }
+function wakeUp() { isSleeping = false; toolbar.classList.remove('sleeping'); statusIndicator.classList.remove('sleeping'); }
+function sleep() { isSleeping = true; toolbar.classList.add('sleeping'); statusIndicator.classList.add('sleeping'); }
+function openTool(path) { window.open(`https://devtools.khulnasoft.com/${path}`, '_blank', 'noopener'); }
+
+renderTools();
+menuBtn.addEventListener('click', () => (isMenuOpen ? closeMenu() : openMenu()));
+document.getElementById('searchBtn').addEventListener('click', () => openMenu(true));
+document.getElementById('inspectBtn').addEventListener('click', () => sendMessage('inspectElement'));
+document.getElementById('screenshotBtn').addEventListener('click', () => sendMessage('takeScreenshot'));
+document.getElementById('hideBtn').addEventListener('click', hideToolbar);
+menuSearch.addEventListener('input', (event) => renderTools(event.target.value));
+toolSections.addEventListener('click', (event) => {
+ const item = event.target.closest('.menu-item');
+ if (!item) return;
+ const id = item.dataset.id;
+ if (id === 'search') return openMenu(true);
+ if (id === 'inspect') return sendMessage('inspectElement');
+ if (id === 'screenshot') return sendMessage('takeScreenshot');
+ if (id === 'hide') return hideToolbar();
+ if (id === 'preferences') return browserAPI.runtime.sendMessage({ action: 'openOptions' });
+ if (item.dataset.path !== '') openTool(item.dataset.path);
+ else openTool('');
+});
+document.addEventListener('click', (event) => { if (!toolbar.contains(event.target)) closeMenu(); });
+document.addEventListener('keydown', (event) => {
+ const key = event.key.toLowerCase();
+ if ((event.ctrlKey || event.metaKey) && key === 'k') { event.preventDefault(); openMenu(true); }
+ else if (key === '/' && document.activeElement !== menuSearch) { event.preventDefault(); openMenu(true); }
+ else if (key === 'escape') { if (isMenuOpen) closeMenu(); else hideToolbar(); }
+});
+
+dragHandle.addEventListener('mousedown', (event) => { isDragging = true; const rect = toolbar.getBoundingClientRect(); dragOffset = { x: event.clientX - rect.left, y: event.clientY - rect.top }; toolbar.style.right = 'auto'; toolbar.style.transform = 'none'; });
+document.addEventListener('mousemove', (event) => { if (!isDragging) return; toolbar.style.left = `${Math.max(8, Math.min(window.innerWidth - toolbar.offsetWidth - 8, event.clientX - dragOffset.x))}px`; toolbar.style.top = `${Math.max(8, Math.min(window.innerHeight - toolbar.offsetHeight - 8, event.clientY - dragOffset.y))}px`; });
+document.addEventListener('mouseup', () => { if (!isDragging) return; isDragging = false; const rect = toolbar.getBoundingClientRect(); browserAPI.storage.local.set({ toolbarPosition: { x: rect.left, y: rect.top } }); });
+
+browserAPI.storage.local.get(['toolbarPosition', 'toolbarHidden'], (result) => {
+ if (result.toolbarPosition) { toolbar.style.right = 'auto'; toolbar.style.transform = 'none'; toolbar.style.left = `${result.toolbarPosition.x}px`; toolbar.style.top = `${result.toolbarPosition.y}px`; }
+ if (result.toolbarHidden) toolbar.style.display = 'none';
+});
diff --git a/extension/toolbar.html b/extension/toolbar.html
index e8685ed2..cc713f45 100644
--- a/extension/toolbar.html
+++ b/extension/toolbar.html
@@ -1,396 +1,67 @@
-
+
-
- Dev Tools Toolbar
+
+ DevTools toolbar
-
-
+
+
diff --git a/extension/toolbar.js b/extension/toolbar.js
index 857c2d45..448fa939 100644
--- a/extension/toolbar.js
+++ b/extension/toolbar.js
@@ -1,446 +1,87 @@
-// Dev Tools Toolbar JavaScript
-// Floating toolbar similar to Vercel Toolbar
-
+const browserAPI = typeof browser !== 'undefined' ? browser : chrome;
const toolbar = document.getElementById('toolbar');
const menuBtn = document.getElementById('menuBtn');
const menuPanel = document.getElementById('menuPanel');
const menuSearch = document.getElementById('menuSearch');
+const toolSections = document.getElementById('toolSections');
const statusIndicator = document.getElementById('statusIndicator');
const dragHandle = document.getElementById('dragHandle');
-
-let isSleeping = true;
+const tools = [
+ { category: 'Quick actions', items: [
+ { id: 'search', label: 'Search all tools', description: 'Find a utility by name', icon: 'β', shortcut: '/' },
+ { id: 'inspect', label: 'Inspect element', description: 'Pick an element on this page', icon: 'β' },
+ { id: 'screenshot', label: 'Capture screenshot', description: 'Save the current page view', icon: 'β£' },
+ ]},
+ { category: 'Popular tools', items: [
+ { label: 'JSON Viewer', description: 'Format and explore JSON', icon: '{}' , path: 'json-viewer' },
+ { label: 'Base64 Converter', description: 'Encode and decode Base64', icon: '64', path: 'base64-string-converter' },
+ { label: 'Regex Tester', description: 'Build and test regular expressions', icon: '.*', path: 'regex-tester' },
+ { label: 'Color Converter', description: 'Convert colors between formats', icon: 'β', path: 'color-converter' },
+ { label: 'JWT Decoder', description: 'Inspect JSON Web Tokens', icon: 'jwt', path: 'jwt-decoder' },
+ ]},
+ { category: 'All tools', items: [
+ { label: 'Open DevTools', description: 'Browse the complete tool library', icon: 'β', path: '' },
+ ]},
+ { category: 'Settings', items: [
+ { id: 'preferences', label: 'Preferences', description: 'Configure toolbar behavior', icon: 'β' },
+ { id: 'hide', label: 'Hide toolbar', description: 'Show it again from the extension menu', icon: 'β', shortcut: 'Esc' },
+ ]},
+];
+let isSleeping = false;
let isMenuOpen = false;
let isDragging = false;
let dragOffset = { x: 0, y: 0 };
-// Default shortcuts
-const defaultShortcuts = {
- menu: 'Control',
- search: '/',
- inspect: '',
- screenshot: '',
- hide: 'Escape',
- json: '',
- base64: '',
-};
-
-// Current shortcuts
-let shortcuts = { ...defaultShortcuts };
-
-// Initialize toolbar
-function initToolbar() {
- loadPosition();
- loadState();
- loadShortcuts();
- setupEventListeners();
- setupKeyboardShortcuts();
-}
-
-// Load shortcuts from storage
-function loadShortcuts() {
- if (typeof browser !== 'undefined') {
- browser.storage.local.get(['shortcuts'], (result) => {
- shortcuts = { ...defaultShortcuts, ...(result.shortcuts || {}) };
- updateMenuShortcuts();
- });
- } else if (typeof chrome !== 'undefined') {
- chrome.storage.local.get(['shortcuts'], (result) => {
- shortcuts = { ...defaultShortcuts, ...(result.shortcuts || {}) };
- updateMenuShortcuts();
- });
- }
-}
-
-// Update menu shortcuts display
-function updateMenuShortcuts() {
- const shortcutMap = {
- search: 'search',
- inspect: 'inspect',
- screenshot: 'screenshot',
- hide: 'hide',
- };
-
- Object.keys(shortcutMap).forEach(action => {
- const shortcut = shortcuts[action];
- const items = menuPanel.querySelectorAll(`[data-action="${action}"]`);
- items.forEach(item => {
- let shortcutEl = item.querySelector('.menu-item-shortcut');
- if (!shortcutEl) {
- shortcutEl = document.createElement('span');
- shortcutEl.className = 'menu-item-shortcut';
- item.appendChild(shortcutEl);
- }
- shortcutEl.textContent = shortcut || '';
- shortcutEl.style.display = shortcut ? 'block' : 'none';
- });
- });
-}
-
-// Load saved position
-function loadPosition() {
- const position = localStorage.getItem('it-toolbar-position');
- if (position) {
- const { x, y } = JSON.parse(position);
- toolbar.style.right = 'auto';
- toolbar.style.left = `${x}px`;
- toolbar.style.top = `${y}px`;
- toolbar.style.transform = 'none';
- }
-}
-
-// Save position
-function savePosition() {
- const rect = toolbar.getBoundingClientRect();
- localStorage.setItem('it-toolbar-position', JSON.stringify({
- x: rect.left,
- y: rect.top,
- }));
-}
-
-// Load state (sleeping/active)
-function loadState() {
- const state = localStorage.getItem('it-toolbar-state');
- if (state === 'active') {
- wakeUp();
- } else {
- sleep();
- }
-}
-
-// Setup event listeners
-function setupEventListeners() {
- // Menu toggle
- menuBtn.addEventListener('click', toggleMenu);
-
- // Close menu when clicking outside
- document.addEventListener('click', (e) => {
- if (!toolbar.contains(e.target)) {
- closeMenu();
- }
- });
-
- // Menu item clicks
- menuPanel.querySelectorAll('.menu-item').forEach(item => {
- item.addEventListener('click', (e) => {
- const action = item.dataset.action;
- if (action) {
- e.preventDefault();
- handleMenuAction(action);
- }
- });
- });
-
- // Search
- menuSearch.addEventListener('input', (e) => {
- filterMenuItems(e.target.value);
- });
-
- // Dragging
- dragHandle.addEventListener('mousedown', startDrag);
- document.addEventListener('mousemove', onDrag);
- document.addEventListener('mouseup', stopDrag);
-
- // Toolbar buttons
- document.getElementById('searchBtn').addEventListener('click', () => {
- menuSearch.focus();
- openMenu();
- });
-
- document.getElementById('inspectBtn').addEventListener('click', () => {
- sendMessage('inspectElement');
- });
-
- document.getElementById('screenshotBtn').addEventListener('click', () => {
- sendMessage('takeScreenshot');
- });
-
- document.getElementById('hideBtn').addEventListener('click', () => {
- hideToolbar();
- });
-
- // Click on toolbar to wake up
- toolbar.addEventListener('click', () => {
- if (isSleeping) {
- wakeUp();
- }
- });
-}
-
-// Setup keyboard shortcuts
-function setupKeyboardShortcuts() {
- document.addEventListener('keydown', (e) => {
- const shortcut = buildShortcutString(e);
-
- // Check each shortcut
- if (shortcut === shortcuts.menu) {
- e.preventDefault();
- toggleMenu();
- }
-
- if (shortcut === shortcuts.search) {
- e.preventDefault();
- menuSearch.focus();
- openMenu();
- }
-
- if (shortcut === shortcuts.inspect) {
- e.preventDefault();
- sendMessage('inspectElement');
- }
-
- if (shortcut === shortcuts.screenshot) {
- e.preventDefault();
- sendMessage('takeScreenshot');
- }
-
- if (shortcut === shortcuts.hide) {
- e.preventDefault();
- if (isMenuOpen) {
- closeMenu();
- } else {
- hideToolbar();
- }
- }
-
- if (shortcut === shortcuts.json) {
- e.preventDefault();
- window.open('https://devtools.khulnasoft.com/json-viewer', '_blank');
- }
-
- if (shortcut === shortcuts.base64) {
- e.preventDefault();
- window.open('https://devtools.khulnasoft.com/base64-string-converter', '_blank');
- }
- });
-}
-
-// Build shortcut string from keyboard event
-function buildShortcutString(e) {
- const parts = [];
-
- if (e.ctrlKey) parts.push('Ctrl');
- if (e.altKey) parts.push('Alt');
- if (e.shiftKey) parts.push('Shift');
- if (e.metaKey) parts.push('Cmd');
-
- const key = e.key;
- if (!parts.includes(key) && key !== 'Control' && key !== 'Alt' && key !== 'Shift' && key !== 'Meta') {
- parts.push(key);
- }
-
- return parts.join('+');
-}
-
-// Toggle menu
-function toggleMenu() {
- if (isMenuOpen) {
- closeMenu();
- } else {
- openMenu();
- }
-}
-
-// Open menu
-function openMenu() {
- isMenuOpen = true;
- menuPanel.classList.add('open');
- menuBtn.classList.add('active');
- if (isSleeping) {
- wakeUp();
- }
-}
-
-// Close menu
-function closeMenu() {
- isMenuOpen = false;
- menuPanel.classList.remove('open');
- menuBtn.classList.remove('active');
- menuSearch.value = '';
- filterMenuItems('');
-}
-
-// Filter menu items
-function filterMenuItems(query) {
- const items = menuPanel.querySelectorAll('.menu-item');
- const lowerQuery = query.toLowerCase();
-
- items.forEach(item => {
- const text = item.querySelector('.menu-item-text').textContent.toLowerCase();
- if (text.includes(lowerQuery)) {
- item.style.display = 'flex';
- } else {
- item.style.display = 'none';
- }
- });
-}
-
-// Handle menu action
-function handleMenuAction(action) {
- closeMenu();
-
- switch (action) {
- case 'search':
- menuSearch.focus();
- openMenu();
- break;
- case 'inspect':
- sendMessage('inspectElement');
- break;
- case 'screenshot':
- sendMessage('takeScreenshot');
- break;
- case 'preferences':
- sendMessage('openPreferences');
- break;
- case 'hide':
- hideToolbar();
- break;
- }
-}
-
-// Wake up toolbar
-function wakeUp() {
- isSleeping = false;
- toolbar.classList.remove('sleeping');
- statusIndicator.classList.remove('sleeping');
- localStorage.setItem('it-toolbar-state', 'active');
-}
-
-// Sleep toolbar
-function sleep() {
- isSleeping = true;
- toolbar.classList.add('sleeping');
- statusIndicator.classList.add('sleeping');
- localStorage.setItem('it-toolbar-state', 'sleeping');
-}
-
-// Hide toolbar
-function hideToolbar() {
- toolbar.style.display = 'none';
- // Create a small indicator to show toolbar again
- showRestoreIndicator();
-}
-
-// Show restore indicator
-function showRestoreIndicator() {
- const indicator = document.createElement('button');
- indicator.id = 'it-toolbar-restore';
- indicator.innerHTML = 'π οΈ';
- indicator.style.cssText = `
- position: fixed;
- bottom: 20px;
- right: 20px;
- width: 50px;
- height: 50px;
- border-radius: 50%;
- background: #18a058;
- color: white;
- border: none;
- cursor: pointer;
- z-index: 999999;
- font-size: 24px;
- box-shadow: 0 4px 12px rgba(0,0,0,0.3);
- transition: transform 0.2s;
- `;
-
- indicator.addEventListener('mouseenter', () => {
- indicator.style.transform = 'scale(1.1)';
- });
-
- indicator.addEventListener('mouseleave', () => {
- indicator.style.transform = 'scale(1)';
- });
-
- indicator.addEventListener('click', () => {
- toolbar.style.display = 'flex';
- indicator.remove();
- wakeUp();
- });
-
- document.body.appendChild(indicator);
-}
-
-// Dragging
-function startDrag(e) {
- isDragging = true;
- const rect = toolbar.getBoundingClientRect();
- dragOffset.x = e.clientX - rect.left;
- dragOffset.y = e.clientY - rect.top;
- toolbar.style.transition = 'none';
-}
-
-function onDrag(e) {
- if (!isDragging) return;
-
- const x = e.clientX - dragOffset.x;
- const y = e.clientY - dragOffset.y;
-
- // Constrain to viewport
- const maxX = window.innerWidth - toolbar.offsetWidth;
- const maxY = window.innerHeight - toolbar.offsetHeight;
-
- toolbar.style.left = `${Math.max(0, Math.min(x, maxX))}px`;
- toolbar.style.top = `${Math.max(0, Math.min(y, maxY))}px`;
- toolbar.style.right = 'auto';
- toolbar.style.transform = 'none';
-}
-
-function stopDrag() {
- if (isDragging) {
- isDragging = false;
- toolbar.style.transition = 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)';
- savePosition();
- }
-}
-
-// Send message to extension
-function sendMessage(action) {
- if (typeof browser !== 'undefined') {
- browser.runtime.sendMessage({ action });
- } else if (typeof chrome !== 'undefined') {
- chrome.runtime.sendMessage({ action });
- }
-}
-
-// Listen for messages from extension
-if (typeof browser !== 'undefined') {
- browser.runtime.onMessage.addListener(handleMessage);
-} else if (typeof chrome !== 'undefined') {
- chrome.runtime.onMessage.addListener(handleMessage);
-}
-
-function handleMessage(request, sender, sendResponse) {
- if (request.action === 'showToolbar') {
- toolbar.style.display = 'flex';
- const indicator = document.getElementById('it-toolbar-restore');
- if (indicator) indicator.remove();
- wakeUp();
- }
-
- if (request.action === 'hideToolbar') {
- hideToolbar();
- }
-
- if (request.action === 'wakeUp') {
- wakeUp();
- }
-
- if (request.action === 'sleep') {
- sleep();
- }
-
- if (request.action === 'updateShortcuts') {
- shortcuts = { ...defaultShortcuts, ...(request.shortcuts || {}) };
- updateMenuShortcuts();
- }
-
- sendResponse({ success: true });
- return true;
-}
-
-// Initialize on load
-if (document.readyState === 'loading') {
- document.addEventListener('DOMContentLoaded', initToolbar);
-} else {
- initToolbar();
-}
+function renderTools(query = '') {
+ const normalized = query.trim().toLowerCase();
+ const html = tools.map((section) => {
+ const items = section.items.filter((item) => !normalized || `${item.label} ${item.description}`.toLowerCase().includes(normalized));
+ if (!items.length) return '';
+ return ``;
+ }).join('');
+ toolSections.innerHTML = html || 'No tools match your search.
';
+}
+
+function sendMessage(action) { browserAPI.runtime.sendMessage({ action }).catch(() => {}); }
+function openMenu(focus = false) { isMenuOpen = true; menuPanel.classList.add('open'); menuBtn.classList.add('active'); menuBtn.setAttribute('aria-expanded', 'true'); if (focus) menuSearch.focus(); }
+function closeMenu() { isMenuOpen = false; menuPanel.classList.remove('open'); menuBtn.classList.remove('active'); menuBtn.setAttribute('aria-expanded', 'false'); menuSearch.value = ''; renderTools(); }
+function hideToolbar() { toolbar.style.display = 'none'; browserAPI.storage.local.set({ toolbarHidden: true }); }
+function wakeUp() { isSleeping = false; toolbar.classList.remove('sleeping'); statusIndicator.classList.remove('sleeping'); }
+function sleep() { isSleeping = true; toolbar.classList.add('sleeping'); statusIndicator.classList.add('sleeping'); }
+function openTool(path) { window.open(`https://devtools.khulnasoft.com/${path}`, '_blank', 'noopener'); }
+
+renderTools();
+menuBtn.addEventListener('click', () => (isMenuOpen ? closeMenu() : openMenu()));
+document.getElementById('searchBtn').addEventListener('click', () => openMenu(true));
+document.getElementById('inspectBtn').addEventListener('click', () => sendMessage('inspectElement'));
+document.getElementById('screenshotBtn').addEventListener('click', () => sendMessage('takeScreenshot'));
+document.getElementById('hideBtn').addEventListener('click', hideToolbar);
+menuSearch.addEventListener('input', (event) => renderTools(event.target.value));
+toolSections.addEventListener('click', (event) => {
+ const item = event.target.closest('.menu-item');
+ if (!item) return;
+ const id = item.dataset.id;
+ if (id === 'search') return openMenu(true);
+ if (id === 'inspect') return sendMessage('inspectElement');
+ if (id === 'screenshot') return sendMessage('takeScreenshot');
+ if (id === 'hide') return hideToolbar();
+ if (id === 'preferences') return browserAPI.runtime.sendMessage({ action: 'openOptions' });
+ if (item.dataset.path !== '') openTool(item.dataset.path);
+ else openTool('');
+});
+document.addEventListener('click', (event) => { if (!toolbar.contains(event.target)) closeMenu(); });
+document.addEventListener('keydown', (event) => {
+ const key = event.key.toLowerCase();
+ if ((event.ctrlKey || event.metaKey) && key === 'k') { event.preventDefault(); openMenu(true); }
+ else if (key === '/' && document.activeElement !== menuSearch) { event.preventDefault(); openMenu(true); }
+ else if (key === 'escape') { if (isMenuOpen) closeMenu(); else hideToolbar(); }
+});
+
+dragHandle.addEventListener('mousedown', (event) => { isDragging = true; const rect = toolbar.getBoundingClientRect(); dragOffset = { x: event.clientX - rect.left, y: event.clientY - rect.top }; toolbar.style.right = 'auto'; toolbar.style.transform = 'none'; });
+document.addEventListener('mousemove', (event) => { if (!isDragging) return; toolbar.style.left = `${Math.max(8, Math.min(window.innerWidth - toolbar.offsetWidth - 8, event.clientX - dragOffset.x))}px`; toolbar.style.top = `${Math.max(8, Math.min(window.innerHeight - toolbar.offsetHeight - 8, event.clientY - dragOffset.y))}px`; });
+document.addEventListener('mouseup', () => { if (!isDragging) return; isDragging = false; const rect = toolbar.getBoundingClientRect(); browserAPI.storage.local.set({ toolbarPosition: { x: rect.left, y: rect.top } }); });
+
+browserAPI.storage.local.get(['toolbarPosition', 'toolbarHidden'], (result) => {
+ if (result.toolbarPosition) { toolbar.style.right = 'auto'; toolbar.style.transform = 'none'; toolbar.style.left = `${result.toolbarPosition.x}px`; toolbar.style.top = `${result.toolbarPosition.y}px`; }
+ if (result.toolbarHidden) toolbar.style.display = 'none';
+});