11<script lang="ts" setup>
2- import JsonEditorVue from ' json-editor-vue'
32import { useHead } from ' nuxt/app'
43import { hasProductionUrl , previewSource , productionUrl } from ' nuxtseo-layer-devtools/composables/state'
54import { withHttps } from ' ufo'
@@ -10,6 +9,27 @@ import { isConnectionFailed, isFallbackMode } from '../composables/rpc'
109
1110const RE_SINGLE_QUOTE = / '/ g
1211const RE_VUE_FILENAME = / [^ /] + \. vue$ /
12+ const RE_HEX_COLOR = / ^ #(?:[0-9a-f ] {3,4} | [0-9a-f ] {6} | [0-9a-f ] {8} )$ / i
13+
14+ const EXCLUDED_PROPS = new Set ([' colorMode' ])
15+ const editableProps = computed (() =>
16+ Object .keys (propEditor .value ).filter (k => ! EXCLUDED_PROPS .has (k )),
17+ )
18+
19+ function editProp(key : string , value : unknown ) {
20+ propEditor .value = { ... propEditor .value , [key ]: value }
21+ updateProps ({ [key ]: value })
22+ }
23+
24+ function inferPropType(value : unknown ): ' color' | ' number' | ' json' | ' string' {
25+ if (typeof value === ' number' )
26+ return ' number'
27+ if (typeof value === ' string' && RE_HEX_COLOR .test (value ))
28+ return ' color'
29+ if (typeof value === ' string' )
30+ return ' string'
31+ return ' json'
32+ }
1333
1434const {
1535 globalDebug,
@@ -953,13 +973,45 @@ const productionHostname = computed(() => {
953973 </UButton >
954974 </div >
955975
956- <JsonEditorVue
957- :model-value =" propEditor"
958- class =" jse-theme-dark"
959- :main-menu-bar =" false"
960- :navigation-bar =" false"
961- @update:model-value =" updateProps"
962- />
976+ <div v-if =" editableProps.length" class =" prop-editor" >
977+ <div v-for =" key in editableProps" :key =" key" class =" prop-field" >
978+ <label class =" prop-label" >{{ key }}</label >
979+ <input
980+ v-if =" inferPropType(propEditor[key]) === 'color'"
981+ type =" color"
982+ :value =" propEditor[key]"
983+ class =" prop-input prop-input-color"
984+ @input =" editProp(key, ($event.target as HTMLInputElement).value)"
985+ >
986+ <input
987+ v-else-if =" inferPropType(propEditor[key]) === 'number'"
988+ type =" number"
989+ :value =" propEditor[key]"
990+ class =" prop-input"
991+ @input =" editProp(key, Number(($event.target as HTMLInputElement).value))"
992+ >
993+ <textarea
994+ v-else-if =" inferPropType(propEditor[key]) === 'json'"
995+ :value =" JSON.stringify(propEditor[key], null, 2)"
996+ class =" prop-input prop-input-json"
997+ rows =" 3"
998+ @change =" (() => {
999+ try { editProp(key, JSON.parse(($event.target as HTMLTextAreaElement).value)) }
1000+ catch {}
1001+ })()"
1002+ />
1003+ <input
1004+ v-else
1005+ type =" text"
1006+ :value =" propEditor[key]"
1007+ class =" prop-input"
1008+ @input =" editProp(key, ($event.target as HTMLInputElement).value)"
1009+ >
1010+ </div >
1011+ </div >
1012+ <div v-else class =" prop-editor-empty" >
1013+ No props defined
1014+ </div >
9631015 </div >
9641016
9651017 <!-- Fonts Tab -->
@@ -1558,6 +1610,63 @@ const productionHostname = computed(() => {
15581610 text-align : center ;
15591611}
15601612
1613+ /* Prop editor */
1614+ .prop-editor {
1615+ display : flex ;
1616+ flex-direction : column ;
1617+ gap : 0.375rem ;
1618+ padding : 0.5rem 0.75rem ;
1619+ }
1620+
1621+ .prop-field {
1622+ display : flex ;
1623+ flex-direction : column ;
1624+ gap : 0.125rem ;
1625+ }
1626+
1627+ .prop-label {
1628+ font-family : var (--font-mono );
1629+ font-size : 0.6875rem ;
1630+ color : var (--color-text-subtle );
1631+ letter-spacing : 0.01em ;
1632+ }
1633+
1634+ .prop-input {
1635+ font-family : var (--font-mono );
1636+ font-size : 0.75rem ;
1637+ padding : 0.25rem 0.375rem ;
1638+ border-radius : var (--radius-sm );
1639+ border : 1px solid var (--color-border-subtle );
1640+ background : var (--color-surface-sunken );
1641+ color : var (--color-text );
1642+ outline : none ;
1643+ transition : border-color 150ms ;
1644+ }
1645+
1646+ .prop-input :focus {
1647+ border-color : var (--seo-green );
1648+ }
1649+
1650+ .prop-input-color {
1651+ width : 2.5rem ;
1652+ height : 1.5rem ;
1653+ padding : 0.125rem ;
1654+ cursor : pointer ;
1655+ }
1656+
1657+ .prop-input-json {
1658+ resize : vertical ;
1659+ min-height : 2.5rem ;
1660+ line-height : 1.4 ;
1661+ }
1662+
1663+ .prop-editor-empty {
1664+ padding : 1rem 0.75rem ;
1665+ font-size : 0.75rem ;
1666+ color : var (--color-text-subtle );
1667+ text-align : center ;
1668+ }
1669+
15611670/* Inline code */
15621671.inline-code {
15631672 padding : 0.125rem 0.375rem ;
0 commit comments