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 ;
+}