From c174fa439a9fd2ad683a781b3575c0feb0c42b67 Mon Sep 17 00:00:00 2001 From: PhoneDroid <73050054+PhoneDroid@users.noreply.github.com> Date: Sun, 8 Jan 2023 09:11:43 -0500 Subject: [PATCH] Extended schema editor --- Source/Schema/App.js | 489 ++++++++++++++++++++++++++++++++++++++-- Source/Schema/Style.css | 83 ++++++- 2 files changed, 556 insertions(+), 16 deletions(-) diff --git a/Source/Schema/App.js b/Source/Schema/App.js index 032fc00..680a3b7 100644 --- a/Source/Schema/App.js +++ b/Source/Schema/App.js @@ -40,8 +40,8 @@ log('API',api); html_max_blocks.oninput = update; -html_class.oninput = update; html_limit.onchange = update; +html_class.oninput = update; html_name.oninput = update; html_tag.onchange = update; @@ -146,15 +146,24 @@ const Settings = { 'article' : simple , 'blog' : simple , 'collection' : simple , - 'html' : simple , + 'html' : html , 'image_picker' : simple , 'link_list' : simple , 'page' : simple , + 'text' : text , + 'textarea' : textarea , + 'collection_list' : collection_list , + 'color' : color , + 'color_background' : color_background , + 'font_picker' : font_picker , + 'liquid' : liquid , + 'product' : simple , 'video' : simple , 'url' : url , 'richtext' : richtext , - 'product_list' : product_list + 'product_list' : product_list , + 'inline_richtext' : inline_richtext } @@ -456,6 +465,206 @@ function richtext ( setting ){ + html_settings.appendChild(item); +} + +function textarea ( setting ){ + + const item = settingTemplate(setting); + + item.appendChild(create('br')); + item.appendChild(create('br')); + + { + item.appendChild(create('br')); + item.appendChild(create('br')); + + const label = create('label'); + label.innerHTML = ` Default
content to display.`; + + const input = create('textarea'); + input.cols = 16; + input.rows = 4; + input.value = setting.default ?? ''; + + input.addEventListener('change',() => { + settings.default = input.value; + update(); + }) + + item.appendChild(label); + item.appendChild(create('br')); + item.appendChild(input); + } + + + + html_settings.appendChild(item); +} + +function liquid ( setting ){ + + const item = settingTemplate(setting); + + item.appendChild(create('br')); + item.appendChild(create('br')); + + { + item.appendChild(create('br')); + item.appendChild(create('br')); + + const label = create('label'); + label.innerHTML = ` Default
liquid code to insert.`; + + const input = create('textarea'); + input.cols = 16; + input.rows = 4; + input.value = setting.default ?? ''; + + input.addEventListener('change',() => { + settings.default = input.value; + update(); + }) + + item.appendChild(label); + item.appendChild(create('br')); + item.appendChild(input); + } + + + + html_settings.appendChild(item); +} + +function inline_richtext ( setting ){ + + const item = settingTemplate(setting); + + item.appendChild(create('br')); + item.appendChild(create('br')); + + { + item.appendChild(create('br')); + item.appendChild(create('br')); + + const label = create('label'); + label.innerHTML = ` Default
inline richtext to use.`; + + const input = create('textarea'); + input.rows = 1; + input.wrap = 'soft'; + input.value = setting.default ?? ''; + input.style.resize = 'none'; + + const { ceil , max } = Math; + + input.addEventListener('input',() => { + + const { length } = input.value; + + input.style.height = `${ max((ceil(length / 40) * 1.3 + 0.4).toFixed(2),1.7) }rem` + }) + + input.addEventListener('change',() => { + settings.default = input.value; + update(); + }) + + item.appendChild(label); + item.appendChild(create('br')); + item.appendChild(input); + } + + + + html_settings.appendChild(item); +} + +function text ( setting ){ + + const item = settingTemplate(setting); + + item.appendChild(create('br')); + item.appendChild(create('br')); + + { + item.appendChild(create('br')); + item.appendChild(create('br')); + + const label = create('label'); + label.innerHTML = ` Default
text to display.`; + + const input = create('textarea'); + input.rows = 1; + input.wrap = 'soft'; + input.value = setting.default ?? ''; + input.style.resize = 'none'; + + const { ceil , max } = Math; + + input.addEventListener('input',() => { + + const { length } = input.value; + + input.style.height = `${ max((ceil(length / 40) * 1.3 + 0.4).toFixed(2),1.7) }rem` + }) + + input.addEventListener('change',() => { + settings.default = input.value; + update(); + }) + + item.appendChild(label); + item.appendChild(create('br')); + item.appendChild(input); + } + + + + html_settings.appendChild(item); +} + +function color_background ( setting ){ + + const item = settingTemplate(setting); + + item.appendChild(create('br')); + item.appendChild(create('br')); + + { + item.appendChild(create('br')); + item.appendChild(create('br')); + + const label = create('label'); + label.innerHTML = ` Default
background to use.`; + + const input = create('textarea'); + input.rows = 1; + input.wrap = 'soft'; + input.value = setting.default ?? ''; + input.style.resize = 'none'; + + const { ceil , max } = Math; + + input.addEventListener('input',() => { + + const { length } = input.value; + + input.style.height = `${ max((ceil(length / 40) * 1.3 + 0.4).toFixed(2),1.7) }rem` + }) + + input.addEventListener('change',() => { + settings.default = input.value; + update(); + }) + + item.appendChild(label); + item.appendChild(create('br')); + item.appendChild(input); + } + + + html_settings.appendChild(item); } @@ -512,24 +721,81 @@ function product_list ( setting ){ html_settings.appendChild(item); } - -function radio ( setting ){ +function collection_list ( setting ){ const item = settingTemplate(setting); + item.appendChild(create('br')); + item.appendChild(create('br')); + + { + item.appendChild(create('br')); + item.appendChild(create('br')); + + const label = create('label'); + label.innerHTML = ` Limit
of collections to include ( 1 - 50 ).`; + + const input = create('input'); + input.type = 'text'; + input.value = setting.limit ?? ''; + + input.addEventListener('change',() => { + + let { value } = input; + + value = parseInt(value); + + + if( Number.isFinite(value) ){ + + if( value < 1 ) + value = 1; + + if( value > 50 ) + value = 50; + + input.value = value; + + } else { + value = null; + } + + settings.limit = value; + update(); + }) + + item.appendChild(label); + item.appendChild(create('br')); + item.appendChild(input); + } + + + + html_settings.appendChild(item); +} + + +function font_picker ( setting ){ + + const item = settingTemplate(setting); item.appendChild(create('br')); item.appendChild(create('br')); { + item.appendChild(create('br')); + item.appendChild(create('br')); + const label = create('label'); - label.innerHTML = ` Options
the merchant can choose from.`; + label.innerHTML = ` Default
font to use.`; - const input = create('select'); - input.value = setting.label ?? ''; + const input = create('input'); + input.type = 'text'; + input.value = setting.default ?? ''; - input.addEventListener('input',() => { - settings.label = input.value; + + input.addEventListener('change',() => { + settings.default = input.value; update(); }) @@ -538,18 +804,30 @@ function radio ( setting ){ item.appendChild(input); } + + + html_settings.appendChild(item); +} + +function color ( setting ){ + + const item = settingTemplate(setting); + item.appendChild(create('br')); item.appendChild(create('br')); { + item.appendChild(create('br')); + item.appendChild(create('br')); + const label = create('label'); - label.innerHTML = ` Default
state to be set to.`; + label.innerHTML = ` Default
color to use.`; const input = create('input'); - input.type = 'checkbox'; - input.value = setting.default ?? 0; + input.type = 'text'; + input.value = setting.default ?? ''; - input.addEventListener('input',() => { + input.addEventListener('change',() => { settings.default = input.value; update(); }) @@ -560,6 +838,189 @@ function radio ( setting ){ } + + html_settings.appendChild(item); +} + +function html ( setting ){ + + const item = settingTemplate(setting); + + item.appendChild(create('br')); + item.appendChild(create('br')); + + { + item.appendChild(create('br')); + item.appendChild(create('br')); + + const label = create('label'); + label.innerHTML = ` Placeholder
html to display.`; + + const input = create('textarea'); + input.cols = 16; + input.rows = 4; + input.value = setting.placeholder ?? ''; + + input.addEventListener('change',() => { + settings.placeholder = input.value; + update(); + }) + + item.appendChild(label); + item.appendChild(create('br')); + item.appendChild(input); + } + + + + html_settings.appendChild(item); +} + + +function radio ( setting ){ + + setting.options ??= []; + + + const item = settingTemplate(setting); + + + item.appendChild(create('br')); + item.appendChild(create('br')); + + { + const label = create('label'); + label.innerHTML = ` Options
the merchant can choose from.`; + + const wrapper = create(); + wrapper.className = 'Options'; + + const options = create(); + wrapper.appendChild(options); + + function buildOptions (){ + + for ( const option of setting.options ){ + + const element = create(); + + const label = create('input'); + label.type = 'text'; + label.placeholder = '< Label >'; + label.value = option.label; + + const value = create('input'); + value.type = 'text'; + value.placeholder = '< Value >'; + value.value = option.value; + + const remove = create('button'); + remove.innerText = 'X'; + + label.addEventListener('change',() => { + option.label = label.value; + updateDefault(); + update(); + }) + + value.addEventListener('change',() => { + option.value = value.value; + updateDefault(); + update(); + }) + + remove.addEventListener('click',() => { + setting.options.splice(setting.options.indexOf(option),1); + element.remove(); + updateDefault(); + update(); + }) + + element.appendChild(label); + element.appendChild(value); + element.appendChild(remove); + + options.appendChild(element); + } + } + + buildOptions(); + + const add = create('button'); + wrapper.appendChild(add); + add.innerText = '+'; + + add.addEventListener('click',() => { + + setting.options.push({ + label : '' , + value : '' + }) + + while ( options.childNodes.length ) + options.childNodes[0].remove(); + + buildOptions(); + updateDefault(); + + update(); + }) + + item.appendChild(label); + item.appendChild(create('br')); + item.appendChild(wrapper); + } + + item.appendChild(create('br')); + item.appendChild(create('br')); + + + const label = create('label'); + label.innerHTML = ` Default
state to be set to.`; + + const selection = create('select'); + + item.appendChild(label); + item.appendChild(create('br')); + item.appendChild(selection); + + + function updateDefault (){ + + selection.onchange = () => {}; + + selection.innerHTML = setting.options.map((option) => { + return `` + }).join(''); + + let selected = setting.default ?? ''; + + if( ! setting.options.find(({ value }) => value === selected) ) + selected = setting.options[0]?.value ?? ''; + + if( setting.options.length === 0 ) + selected = ''; + + selection.style.display = ( setting.options.length === 0 ) + ? 'none' + : null ; + + selection.selected = selected; + + selection.onchange = save; + + if( selected !== setting.default ) + save(); + + function save (){ + setting.default = selection.selected; + update(); + } + } + + updateDefault(); + + html_settings.appendChild(item); } diff --git a/Source/Schema/Style.css b/Source/Schema/Style.css index 8054301..0e0c4a7 100644 --- a/Source/Schema/Style.css +++ b/Source/Schema/Style.css @@ -24,7 +24,7 @@ display : flex ; } -:is( input , select , textarea ) { +input , select , textarea , button { max-width : 100% ; @@ -41,6 +41,27 @@ filter : drop-shadow( 2px 2px 4px #FFFFFF11 ) ; } +button { + + border-color : var(--vscode-activityBar-inactiveForeground) ; + background : var(--vscode-activityBarItem-profilesForeground) ; + + text-align : center !important ; + font-size : 1rem ; + color : white ; + + cursor : pointer ; +} + +button:hover { + background : steelblue ; +} + +textarea { + + overflow-x : hidden ; +} + label { user-select : none ; text-align : center ; @@ -195,4 +216,62 @@ input[ type = 'checkbox' ]{ input[ type = 'checkbox' ]:checked { border-color : var(--vscode-button-secondaryBackground) ; background : var(--vscode-button-background) ; -} \ No newline at end of file +} + + +.Options { + + flex-direction : column ; + display : flex ; + gap : 1rem ; +} + +.Options > :first-child { + + flex-direction : column ; + display: flex ; + gap : 0.6rem +} + +.Options > :last-child { + width : 100% ; +} + + +/* Items */ + +.Options > :first-child > div { + + grid-template-columns : 1fr 1fr 2rem ; + grid-template-rows : 2rem ; + grid-gap : 1rem ; + display : grid ; +} + + +/* Label & Value */ + +.Options > :first-child > div > input { + + text-align : center !important ; + width : 100% ; +} + + +/* Remove Button */ + +.Options > :first-child > div > :last-child { + + background : var(--vscode-charts-red) ; + + justify-content : center ; + align-items : center ; + display : grid ; + + line-height : 0 ; + font-size : 0.8rem ; +} + +.Options > :first-child > div > :last-child:hover { + opacity : 0.8 ; +}