From 1452fd18ed2ac27a319ca46f3130a923e2d2df7b Mon Sep 17 00:00:00 2001 From: Evgeny Abramovich Date: Sun, 12 May 2024 17:30:15 -0300 Subject: [PATCH] Added raw and formatted buttons --- src/index.ts | 26 +++++++++---- src/styles.scss | 85 ++++++++++++++++++++++++++++++++++++++++++ src/ui/buttons.test.ts | 53 ++++++++++++++++++++++++++ src/ui/buttons.ts | 32 ++++++++++++++++ src/ui/containers.ts | 16 ++++++++ 5 files changed, 204 insertions(+), 8 deletions(-) create mode 100644 src/ui/buttons.test.ts create mode 100644 src/ui/buttons.ts create mode 100644 src/ui/containers.ts diff --git a/src/index.ts b/src/index.ts index 4e6521b..97f07a1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,6 +2,8 @@ import { isNotNull } from 'typed-assert'; import { buildDom } from './dom'; import { initParser } from './parser'; import styles from './styles.scss'; +import { buildButtons } from './ui/buttons'; +import { buildContainers } from './ui/containers'; const runPlugin = async () => { const shadow = document.body.attachShadow({ mode: 'open' }); @@ -11,9 +13,23 @@ const runPlugin = async () => { shadow.appendChild(styleNode); const data = document.querySelector('body > pre'); - isNotNull(data, 'No data found'); + const { rootContainer, rawContainer, formatContainer } = buildContainers(shadow); + rawContainer.appendChild(data); + + const { rawButton, formatButton } = buildButtons(shadow); + + rawButton.addEventListener('click', () => { + rootContainer.classList.remove('formatted'); + rootContainer.classList.add('raw'); + }); + + formatButton.addEventListener('click', () => { + rootContainer.classList.remove('raw'); + rootContainer.classList.add('formatted'); + }); + await initParser(); const parsedJson = parseJSON(data.innerText); @@ -23,13 +39,7 @@ const runPlugin = async () => { } const dom = buildDom(parsedJson.value); - shadow.appendChild(dom); - dom.addEventListener('click', (event) => { - if (event.target instanceof HTMLElement) { - console.log('Clicked:', event.target.className.includes('array-handler')); - console.log(event.target.parentNode); - } - }); + formatContainer.appendChild(dom); }; if (document.querySelector('pre + .json-formatter-container')) { diff --git a/src/styles.scss b/src/styles.scss index 7d10d6b..ab9adcd 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -10,6 +10,57 @@ $indentation: 20px; background: #282828; color: #eeeeee; font-size: 14px; + + pre { + margin: 0; + padding: 0; + font-size: 14px; + } + + & > .root-container.formatted { + & > .raw-json-container { + display: none; + } + + & > .formatted-json-container { + display: block; + } + } + + & > .root-container.raw { + & > .raw-json-container { + display: block; + } + + & > .formatted-json-container { + display: none; + } + } + + & > .root-container > { + .raw-json-container { + display: none; + } + + .formatted-json-container { + display: block; + } + } + + .button-container { + display: flex; + justify-content: space-between; + margin-bottom: 10px; + position: fixed; + top: 0; + right: 0; + padding: 15px; + } +} + +pre { + margin: 0; + padding: 0; } .bracket { @@ -66,3 +117,37 @@ $indentation: 20px; color: #eeeeee; } +.button-container { + button { + &:first-child { + border-bottom-left-radius: 5px; + border-top-left-radius: 5px; + } + + &:last-child { + border-bottom-right-radius: 5px; + border-top-right-radius: 5px; + } + + &:hover { + background: #525252; + } + + &.active { + background: #2c2c2c; + color: #b4b2b2; + cursor: default; + } + + padding: 5px 10px; + background: #3b3b3b; + color: #eeeeee; + border: none; + cursor: pointer; + font-size: 14px; + font-weight: 500; + transition: background 0.3s; + min-width: 41px; + display: block; + } +} diff --git a/src/ui/buttons.test.ts b/src/ui/buttons.test.ts new file mode 100644 index 0000000..99b4048 --- /dev/null +++ b/src/ui/buttons.test.ts @@ -0,0 +1,53 @@ +import { buildButtons } from './buttons'; + +describe('buildButtons', () => { + let root: ShadowRoot; + let result: ReturnType; + + beforeEach(() => { + const element = document.createElement('div'); + root = element.attachShadow({ mode: 'open' }); + result = buildButtons(root); + }); + + test('raw button should bee defined buttons', () => { + expect(result.rawButton).toBeDefined(); + expect(result.rawButton.tagName).toBe('BUTTON'); + }); + + test('formated button should bee defined buttons', () => { + expect(result.formatButton).toBeDefined(); + expect(result.rawButton.tagName).toBe('BUTTON'); + }); + + test('formated should be active by default', () => { + expect(result.formatButton.classList).toContain('active'); + }); + + describe('clicking on raw button', () => { + beforeEach(() => result.rawButton.click()); + + test('should make raw button active', () => { + expect(result.rawButton.classList).toContain('active'); + }); + + test('should make formatted button inactive', () => { + expect(result.formatButton.classList).not.toContain('active'); + }); + }); + + describe('clicking on formated button should make it active', () => { + beforeEach(() => { + result.rawButton.click(); + result.formatButton.click(); + }); + + test('should make formatted button active', () => { + expect(result.formatButton.classList).toContain('active'); + }); + + test('should make raw button inactive', () => { + expect(result.rawButton.classList).not.toContain('active'); + }); + }); +}); diff --git a/src/ui/buttons.ts b/src/ui/buttons.ts new file mode 100644 index 0000000..d143a78 --- /dev/null +++ b/src/ui/buttons.ts @@ -0,0 +1,32 @@ +export const buildButtons = (root: ShadowRoot) => { + const container = document.createElement('div'); + container.className = 'button-container'; + const formatButton = document.createElement('button'); + formatButton.textContent = 'Formatted'; + formatButton.classList.add('active'); + + const rawButton = document.createElement('button'); + rawButton.textContent = 'Raw'; + + container.appendChild(formatButton); + container.appendChild(rawButton); + + const buttons = [formatButton, rawButton]; + + container.addEventListener('click', (event) => { + if (event.target instanceof HTMLButtonElement) { + for (const button of buttons) { + if (button === event.target) { + button.classList.add('active'); + continue; + } + + button.classList.remove('active'); + } + } + }); + + root.appendChild(container); + + return { formatButton, rawButton }; +}; diff --git a/src/ui/containers.ts b/src/ui/containers.ts new file mode 100644 index 0000000..3f646e6 --- /dev/null +++ b/src/ui/containers.ts @@ -0,0 +1,16 @@ +export const buildContainers = (root: ShadowRoot) => { + const rootContainer = document.createElement('div'); + rootContainer.className = 'root-container'; + + const formatContainer = document.createElement('div'); + formatContainer.className = 'formatted-json-container'; + rootContainer.appendChild(formatContainer); + + const rawContainer = document.createElement('div'); + rawContainer.className = 'raw-json-container'; + rootContainer.appendChild(rawContainer); + + root.appendChild(rootContainer); + + return { rootContainer, formatContainer, rawContainer }; +};