refactor(elements): use luna box model

This commit is contained in:
redhoodsu
2023-02-12 21:21:49 +08:00
parent 7cb5bea838
commit e671cbadfc
6 changed files with 103 additions and 183 deletions

View File

@@ -7,8 +7,6 @@ const path = require('path')
process.traceDeprecation = true process.traceDeprecation = true
const nodeModDir = path.resolve('./node_modules/') + '/'
const srcDir = path.resolve('./src') + '/'
const banner = pkg.name + ' v' + pkg.version + ' ' + pkg.homepage const banner = pkg.name + ' v' + pkg.version + ' ' + pkg.homepage
const postcssLoader = { const postcssLoader = {
@@ -69,6 +67,7 @@ module.exports = {
path.resolve(__dirname, '../node_modules/luna-dom-viewer'), path.resolve(__dirname, '../node_modules/luna-dom-viewer'),
path.resolve(__dirname, '../node_modules/luna-text-viewer'), path.resolve(__dirname, '../node_modules/luna-text-viewer'),
path.resolve(__dirname, '../node_modules/luna-setting'), path.resolve(__dirname, '../node_modules/luna-setting'),
path.resolve(__dirname, '../node_modules/luna-box-model'),
], ],
use: [ use: [
{ {

View File

@@ -63,6 +63,7 @@
"karma-sourcemap-loader": "^0.3.7", "karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^5.0.0", "karma-webpack": "^5.0.0",
"licia": "^1.37.1", "licia": "^1.37.1",
"luna-box-model": "^0.1.0",
"luna-console": "^1.3.0", "luna-console": "^1.3.0",
"luna-data-grid": "^0.4.0", "luna-data-grid": "^0.4.0",
"luna-dom-viewer": "^1.2.3", "luna-dom-viewer": "^1.2.3",

View File

@@ -8,9 +8,6 @@ import escape from 'licia/escape'
import startWith from 'licia/startWith' import startWith from 'licia/startWith'
import contain from 'licia/contain' import contain from 'licia/contain'
import unique from 'licia/unique' import unique from 'licia/unique'
import isStr from 'licia/isStr'
import isNaN from 'licia/isNaN'
import isNum from 'licia/isNum'
import each from 'licia/each' import each from 'licia/each'
import keys from 'licia/keys' import keys from 'licia/keys'
import isNull from 'licia/isNull' import isNull from 'licia/isNull'
@@ -19,13 +16,15 @@ import isFn from 'licia/isFn'
import isBool from 'licia/isBool' import isBool from 'licia/isBool'
import safeGet from 'licia/safeGet' import safeGet from 'licia/safeGet'
import $ from 'licia/$' import $ from 'licia/$'
import h from 'licia/h'
import MutationObserver from 'licia/MutationObserver' import MutationObserver from 'licia/MutationObserver'
import CssStore from './CssStore' import CssStore from './CssStore'
import Settings from '../Settings/Settings' import Settings from '../Settings/Settings'
import LunaModal from 'luna-modal' import LunaModal from 'luna-modal'
import LunaBoxModel from 'luna-box-model'
import chobitsu from '../lib/chobitsu' import chobitsu from '../lib/chobitsu'
import { formatNodeName } from './util' import { formatNodeName } from './util'
import { pxToNum, isErudaEl, classPrefix as c } from '../lib/util' import { isErudaEl, classPrefix as c } from '../lib/util'
export default class Detail { export default class Detail {
constructor($container, devtools) { constructor($container, devtools) {
@@ -35,6 +34,7 @@ export default class Detail {
this._bindEvent() this._bindEvent()
this._initObserver() this._initObserver()
this._initCfg() this._initCfg()
this._initTpl()
} }
show(el) { show(el) {
this._curEl = el this._curEl = el
@@ -87,6 +87,33 @@ export default class Detail {
if (this._origAddEvent) winEventProto.addEventListener = this._origAddEvent if (this._origAddEvent) winEventProto.addEventListener = this._origAddEvent
if (this._origRmEvent) winEventProto.removeEventListener = this._origRmEvent if (this._origRmEvent) winEventProto.removeEventListener = this._origRmEvent
} }
_initTpl() {
const $container = this._$container
const html = `<div class="${c('control')}">
<span class="${c('icon-arrow-left back')}"></span>
<span class="${c('element-name')}"></span>
<span class="${c('icon-refresh refresh')}"></span>
</div>
<div class="${c('element')}">
<div class="${c('attributes section')}"></div>
<div class="${c('styles section')}"></div>
<div class="${c('computed-style section')}"></div>
<div class="${c('listeners section')}"></div>
</div>`
$container.html(html)
this._$elementName = $container.find(c('.element-name'))
this._$attributes = $container.find(c('.attributes'))
this._$styles = $container.find(c('.styles'))
this._$listeners = $container.find(c('.listeners'))
this._$computedStyle = $container.find(c('.computed-style'))
const boxModelContainer = h('div')
this._$boxModel = $(boxModelContainer)
this._boxModel = new LunaBoxModel(boxModelContainer)
}
_toggleAllComputedStyle() { _toggleAllComputedStyle() {
this._rmDefComputedStyle = !this._rmDefComputedStyle this._rmDefComputedStyle = !this._rmDefComputedStyle
@@ -94,26 +121,32 @@ export default class Detail {
} }
_render() { _render() {
const data = this._getData(this._curEl) const data = this._getData(this._curEl)
const $attributes = this._$attributes
const $elementName = this._$elementName
const $styles = this._$styles
const $computedStyle = this._$computedStyle
const $listeners = this._$listeners
let attribute = '<tr><td>Empty</td></tr>' $elementName.html(data.name)
let attributes = '<tr><td>Empty</td></tr>'
if (!isEmpty(data.attributes)) { if (!isEmpty(data.attributes)) {
attribute = map(data.attributes, ({ name, value }) => { attributes = map(data.attributes, ({ name, value }) => {
return `<tr> return `<tr>
<td class="${c('attribute-name-color')}">${escape(name)}</td> <td class="${c('attribute-name-color')}">${escape(name)}</td>
<td class="${c('string-color')}">${value}</td> <td class="${c('string-color')}">${value}</td>
</tr>` </tr>`
}).join('') }).join('')
} }
attribute = `<div class="${c('attributes section')}"> attributes = `<h2>Attributes</h2>
<h2>Attributes</h2> <div class="${c('table-wrapper')}">
<div class="${c('table-wrapper')}"> <table>
<table> <tbody>
<tbody> ${attributes}
${attribute} </tbody>
</tbody> </table>
</table>
</div>
</div>` </div>`
$attributes.html(attributes)
let styles = '' let styles = ''
if (!isEmpty(data.styles)) { if (!isEmpty(data.styles)) {
@@ -129,12 +162,13 @@ export default class Detail {
<div>}</div> <div>}</div>
</div>` </div>`
}).join('') }).join('')
styles = `<div class="${c('styles section')}"> styles = `<h2>Styles</h2>
<h2>Styles</h2> <div class="${c('style-wrapper')}">
<div class="${c('style-wrapper')}"> ${style}
${style}
</div>
</div>` </div>`
$styles.html(styles).show()
} else {
$styles.hide()
} }
let computedStyle = '' let computedStyle = ''
@@ -148,59 +182,39 @@ export default class Detail {
</div>`) </div>`)
} }
const boxModel = data.boxModel computedStyle = `<h2>
// prettier-ignore Computed Style
const boxModelHtml = [`<div class="${c('box-model')}">`, ${toggleButton}
boxModel.position ? `<div class="${c('position')}">` : '', <div class="${c('btn computed-style-search')}">
boxModel.position ? `<div class="${c('label')}">position</div><div class="${c('top')}">${boxModel.position.top}</div><br><div class="${c('left')}">${boxModel.position.left}</div>` : '', <span class="${c('icon-filter')}"></span>
`<div class="${c('margin')}">`,
`<div class="${c('label')}">margin</div><div class="${c('top')}">${boxModel.margin.top}</div><br><div class="${c('left')}">${boxModel.margin.left}</div>`,
`<div class="${c('border')}">`,
`<div class="${c('label')}">border</div><div class="${c('top')}">${boxModel.border.top}</div><br><div class="${c('left')}">${boxModel.border.left}</div>`,
`<div class="${c('padding')}">`,
`<div class="${c('label')}">padding</div><div class="${c('top')}">${boxModel.padding.top}</div><br><div class="${c('left')}">${boxModel.padding.left}</div>`,
`<div class="${c('content')}">`,
`<span>${boxModel.content.width}</span>&nbsp;×&nbsp;<span>${boxModel.content.height}</span>`,
'</div>',
`<div class="${c('right')}">${boxModel.padding.right}</div><br><div class="${c('bottom')}">${boxModel.padding.bottom}</div>`,
'</div>',
`<div class="${c('right')}">${boxModel.border.right}</div><br><div class="${c('bottom')}">${boxModel.border.bottom}</div>`,
'</div>',
`<div class="${c('right')}">${boxModel.margin.right}</div><br><div class="${c('bottom')}">${boxModel.margin.bottom}</div>`,
'</div>',
boxModel.position ? `<div class="${c('right')}">${boxModel.position.right}</div><br><div class="${c('bottom')}">${boxModel.position.bottom}</div>` : '',
boxModel.position ? '</div>' : '',
'</div>'].join('')
computedStyle = `<div class="${c('computed-style section')}">
<h2>
Computed Style
${toggleButton}
<div class="${c('btn computed-style-search')}">
<span class="${c('icon-filter')}"></span>
</div>
${
data.computedStyleSearchKeyword
? `<div class="${c('btn filter-text')}">${escape(
data.computedStyleSearchKeyword
)}</div>`
: ''
}
</h2>
${boxModelHtml}
<div class="${c('table-wrapper')}">
<table>
<tbody>
${map(data.computedStyle, (val, key) => {
return `<tr>
<td class="${c('key')}">${escape(key)}</td>
<td>${val}</td>
</tr>`
}).join('')}
</tbody>
</table>
</div> </div>
${
data.computedStyleSearchKeyword
? `<div class="${c('btn filter-text')}">${escape(
data.computedStyleSearchKeyword
)}</div>`
: ''
}
</h2>
<div class="${c('box-model')}"></div>
<div class="${c('table-wrapper')}">
<table>
<tbody>
${map(data.computedStyle, (val, key) => {
return `<tr>
<td class="${c('key')}">${escape(key)}</td>
<td>${val}</td>
</tr>`
}).join('')}
</tbody>
</table>
</div>` </div>`
$computedStyle.html(computedStyle).show()
this._boxModel.setOption('element', this._curEl)
$computedStyle.find(c('.box-model')).append(this._$boxModel.get(0))
} else {
$computedStyle.text('').hide()
} }
let listeners = '' let listeners = ''
@@ -218,27 +232,16 @@ export default class Detail {
</ul> </ul>
</div>` </div>`
}).join('') }).join('')
listeners = `<div class="${c('listeners section')}"> listeners = `<h2>Event Listeners</h2>
<h2>Event Listeners</h2> <div class="${c('listener-wrapper')}">
<div class="${c('listener-wrapper')}"> ${listeners}
${listeners}
</div>
</div>` </div>`
$listeners.html(listeners).show()
} else {
$listeners.hide()
} }
const html = `<div class="${c('control')}"> this._$container.show()
<span class="${c('icon-arrow-left back')}"></span>
<span class="${c('element-name')}">${data.name}</span>
<span class="${c('icon-refresh refresh')}"></span>
</div>
<div class="${c('element')}">
${attribute}
${styles}
${computedStyle}
${listeners}
</div>`
this._$container.html(html).show()
} }
_getData(el) { _getData(el) {
const ret = {} const ret = {}
@@ -258,34 +261,6 @@ export default class Detail {
let computedStyle = cssStore.getComputedStyle() let computedStyle = cssStore.getComputedStyle()
function getBoxModelValue(type) {
let keys = ['top', 'left', 'right', 'bottom']
if (type !== 'position') keys = map(keys, (key) => `${type}-${key}`)
if (type === 'border') keys = map(keys, (key) => `${key}-width`)
return {
top: boxModelValue(computedStyle[keys[0]], type),
left: boxModelValue(computedStyle[keys[1]], type),
right: boxModelValue(computedStyle[keys[2]], type),
bottom: boxModelValue(computedStyle[keys[3]], type),
}
}
const boxModel = {
margin: getBoxModelValue('margin'),
border: getBoxModelValue('border'),
padding: getBoxModelValue('padding'),
content: {
width: boxModelValue(computedStyle['width']),
height: boxModelValue(computedStyle['height']),
},
}
if (computedStyle['position'] !== 'static') {
boxModel.position = getBoxModelValue('position')
}
ret.boxModel = boxModel
const styles = cssStore.getMatchedCSSRules() const styles = cssStore.getMatchedCSSRules()
styles.unshift(getInlineStyle(el.style)) styles.unshift(getInlineStyle(el.style))
styles.forEach((style) => processStyleRules(style.style)) styles.forEach((style) => processStyleRules(style.style))
@@ -480,19 +455,6 @@ const needNoStyle = (tagName) =>
const wrapLink = (link) => `<a href="${link}" target="_blank">${link}</a>` const wrapLink = (link) => `<a href="${link}" target="_blank">${link}</a>`
function boxModelValue(val, type) {
if (isNum(val)) return val
if (!isStr(val)) return ''
const ret = pxToNum(val)
if (isNaN(ret)) return val
if (type === 'position') return ret
return ret === 0 ? '' : ret
}
function addEvent(el, type, listener, useCapture = false) { function addEvent(el, type, listener, useCapture = false) {
if (!isEl(el) || !isFn(listener) || !isBool(useCapture)) return if (!isEl(el) || !isFn(listener) || !isBool(useCapture)) return

View File

@@ -136,60 +136,9 @@
} }
.box-model { .box-model {
@include overflow-auto(x); @include overflow-auto(x);
color: #222;
font-size: $font-size-s;
padding: $padding; padding: $padding;
text-align: center; text-align: center;
white-space: nowrap;
border-bottom: 1px solid var(--color); border-bottom: 1px solid var(--color);
.label {
position: absolute;
margin-left: 3px;
padding: 0 2px;
}
.top,
.left,
.right,
.bottom {
display: inline-block;
}
.left,
.right {
vertical-align: middle;
}
.position,
.margin,
.border,
.padding,
.content {
position: relative;
background: #fff;
display: inline-block;
text-align: center;
vertical-align: middle;
padding: 3px;
margin: 3px;
}
.position {
border: 1px grey dotted;
}
.margin {
border: 1px dashed;
background: rgba(246, 178, 107, 0.66);
}
.border {
border: 1px #000 solid;
background: rgba(255, 229, 153, 0.66);
}
.padding {
border: 1px grey dashed;
background: rgba(147, 196, 125, 0.55);
}
.content {
border: 1px grey solid;
min-width: 100px;
background: rgba(111, 168, 220, 0.66);
}
} }
.computed-style { .computed-style {
font-size: $font-size-s; font-size: $font-size-s;

View File

@@ -234,6 +234,7 @@ export default {
require('luna-tab/luna-tab.css') + require('luna-tab/luna-tab.css') +
require('luna-text-viewer/luna-text-viewer.css') + require('luna-text-viewer/luna-text-viewer.css') +
require('luna-setting/luna-setting.css') + require('luna-setting/luna-setting.css') +
require('luna-box-model/luna-box-model.css') +
require('./style/style.scss') + require('./style/style.scss') +
require('./style/icon.css') require('./style/icon.css')
) )

View File

@@ -440,3 +440,11 @@
} }
} }
} }
.luna-box-model {
background: transparent;
}
.luna-box-model-position {
color: var(--foreground);
}