element === true).length === 0,
+ }`
+ f.bindAttribute(selectedContainer, 'class', selectedContainerClasses, false)
+ const mobileSelectAction = selectedContainer.find('.action').eq(0)
+ f.addIf(mobileSelectAction, '(model.mobiletablestyle === "" || model.mobiletablestyle === "default") && isMobile' )
+ f.bindEvent(mobileSelectAction, 'click', 'toggleAllRows');
+ f.addIf(mobileSelectAction.find('.unchecked'), '(!active.every(element => element === true) || active.length === 0)');
+ f.addElse(mobileSelectAction.find('.checked'));
+ const selectedText = selectedContainer.find('.selected-text').eq(0)
+ f.mapField(selectedText, '`${active.filter(element => element === true).length} selected`', false)
+ const actionDelete = selectedContainer.find('.selected-actions svg').eq(0)
+ f.bindEvent(actionDelete, 'click', 'deleteAction');
+
+ const desktopContainer = $.find('div.overflow-x-scroll').eq(0);
+ const desktopContainerClasses = `{
+ 'overflow-y-scroll': model.scrollabletable === 'true',
+ 'hidden': isMobile,
+ }`
+ f.bindAttribute(desktopContainer, 'class', desktopContainerClasses, false)
+ f.addStyle(desktopContainer, 'height', "(model.scrollabletable === 'true') ? model.tableheight + 'px' : 'auto'", false)
+
+ const mobileContainer = $.find('div.mobile-table').eq(0);
+ const mobileContainerClasses = `{
+ 'hidden': !isMobile,
+ }`
+ f.bindAttribute(mobileContainer, 'class', mobileContainerClasses, false)
+
+ //default mobile style
+ const mobileDefaultBody = mobileContainer.find('tbody').eq(0);
+ f.addIf(mobileDefaultBody, 'model.mobiletablestyle === "" || model.mobiletablestyle === "default"' )
+
+ const mobileDefaultTr = mobileContainer.find('tr.item-row').eq(0)
+ f.addFor(mobileDefaultTr, 'model.columns', 'col')
+ mobileDefaultTr.attr(':key', `data.path || j`)
+ f.addStyle(mobileDefaultTr, 'background', "active[j] ? 'var(--color-red-500) !important' : ''")
+
+ const mobileDefaultAction = mobileDefaultBody.find('td.action-head').eq(0)
+ f.addStyle(mobileDefaultAction, 'background', "active[j] ? 'var(--color-red-500) !important' : ''")
+ f.addIf(mobileDefaultAction, 'i === 0')
+ f.addIf(mobileDefaultAction.find('.unchecked'), '!active[j]');
+ f.addIf(mobileDefaultAction.find('.checked'), 'active[j]')
+ f.addStyle(mobileDefaultAction.find('.checked'), 'fill',"active[j] ? 'var(--text-secondary-color) !important' : ''");
+ f.bindEvent(mobileDefaultAction.find('.action').eq(0), 'click', 'toggleRow(j)');
+
+ const mobileDefaultActionSpacer = mobileDefaultBody.find('td.mobile-action-spacer').eq(0)
+ f.addIf(mobileDefaultActionSpacer, 'i !== 0')
+ f.addStyle(mobileDefaultActionSpacer, 'background', "active[j] ? 'var(--color-red-500) !important' : ''")
+
+ f.mapField(mobileDefaultBody.find('td.mobile-header').eq(0), 'col.header', false)
+ mobileDefaultBody.find('td.mobile-header').eq(0).attr(':key', `col.path || i`)
+
+ f.mapField(mobileDefaultBody.find('td.mobile-item').eq(0), 'data[col.value]', false)
+ f.addStyle(mobileDefaultBody.find('td.mobile-item').eq(0), 'background', "active[j] ? 'var(--color-red-500) !important' : ''")
+ f.addStyle(mobileDefaultBody.find('td.mobile-item').eq(0), 'color',"active[j] ? 'var(--text-secondary-color) !important' : ''");
+
+ f.wrap(mobileDefaultTr, 'template')
+
+ const mobileTemplate = mobileDefaultBody.find('template').first();
+ mobileTemplate.attr('v-for', `(data, j) in storageData`)
+ f.addIf(mobileTemplate, 'rowHasData(data,model.columns)')
+
+ //scroll mobile style
+ const scrollMobileBody = mobileContainer.find('tbody').eq(1)
+ f.addElse(scrollMobileBody)
+ const mobileScrollActionTr = scrollMobileBody.find('tr.action-row').eq(0)
+ const mobileScrollAction = scrollMobileBody.find('td.action-item').eq(0)
+ f.addFor(mobileScrollAction, 'storageData', 'data')
+ f.addIf(mobileScrollAction, 'rowHasData(data,model.columns)')
+ f.addIf(mobileScrollAction.find('.unchecked'), '!active[i]');
+ f.addIf(mobileScrollAction.find('.checked'), 'active[i]');
+ f.addStyle(mobileScrollAction, 'background', "active[i] ? 'var(--color-red-500) !important' : ''")
+ f.addStyle(mobileScrollAction.find('.checked'), 'fill',"active[i] ? 'var(--text-secondary-color) !important' : ''");
+ f.bindEvent(mobileScrollAction.find('.action').eq(0), 'click', 'toggleRow(i)');
+
+ const mobileScrollActionAll = mobileScrollActionTr.find('td.action-item-all').eq(0)
+ f.addIf(mobileScrollActionAll.find('.unchecked'), '(!active.every(element => element === true) || active.length === 0)');
+ f.addElse(mobileScrollActionAll.find('.checked'));
+ f.bindEvent(mobileScrollActionAll.find('.action').eq(0), 'click', 'toggleAllRows');
+
+ const mobileScrollBodyTr = scrollMobileBody.find('tr.item-row').first()
+ f.addFor(mobileScrollBodyTr, 'model.columns', 'col')
+
+ const mobileScrollTd = mobileScrollBodyTr.find('td').first()
+ mobileScrollTd.attr('v-for', `(data, j) in storageData`)
+ mobileScrollTd.attr(':key', `data.path || j`)
+ f.addIf(mobileScrollTd, 'rowHasData(data,model.columns)')
+ f.mapField(mobileScrollTd, 'data[col.value]', false)
+ f.addStyle(mobileScrollTd, 'background', "active[j] ? 'var(--color-red-500) !important' : ''")
+
+ mobileScrollBodyTr.prepend("")
+
+ const mobileTdClasses = `{
+ 'border': model.cellborders === 'true',
+ 'p-3': model.densetable !== 'true',
+ 'p-1': model.densetable === 'true',
+ 'align-top': model.rowalignment === 'top' || model.rowalignment === '',
+ 'align-center': model.rowalignment === 'center',
+ 'align-bottom': model.rowalignment === 'bottom'
+ }`
+ f.bindAttribute($.find('.mobile-table td'), 'class', mobileTdClasses, false)
+
+ //desktop
+ const table = $.find('table')
+ const tableClasses = `{
+ 'striped': model.stripedrows === 'true'
+ }`
+ f.bindAttribute(table, 'class', tableClasses, false)
+
+ const thText = $.find('th.header-item').first()
+ f.addFor(thText, 'model.columns', 'col')
+ const thTextClasses = `{
+ 'p-3': model.densetable !== 'true',
+ 'p-1': model.densetable === 'true',
+ 'sticky': model.stickyheader === 'true',
+ 'top-0': model.stickyheader === 'true',
+ 'text-left': (col && col.textalignment === 'left') || (col && col.textalignment === ''),
+ 'text-center': col && col.textalignment === 'center',
+ 'text-right': col && col.textalignment === 'right',
+ }`
+ f.bindAttribute(thText, 'class', thTextClasses, false)
+ f.mapField(thText.find('span'), 'col.header', false)
+
+ const thAction = $.find('th.action-head').first()
+ f.addIf(thAction, "model.selectable === 'true'")
+ f.addIf(thAction.find('.unchecked'), '(!active.every(element => element === true) || active.length === 0)');
+ f.addElse(thAction.find('.checked'));
+ f.bindEvent(thAction.find('.action').eq(0), 'click', 'toggleAllRows');
+ f.bindAttribute(thAction, 'class', thTextClasses, false)
+
+ const tbody = $.find('tbody').first()
+ const tr = tbody.find('tr').first()
+ const tdItem = tr.find('td.item').first()
+ tr.attr('v-for', `(data, j) in storageData`)
+ tr.attr(':key', `data.path || j`)
+ f.addIf(tr, 'rowHasData(data,model.columns)')
+
+ f.addFor(tdItem, 'model.columns', 'col')
+ f.mapField(tdItem.find('span.item-text'), 'data[col.value]', false)
+
+ const tdClasses = `{
+ 'border': model.cellborders === 'true',
+ 'p-3': model.densetable !== 'true',
+ 'p-1': model.densetable === 'true',
+ 'text-left': (col && col.textalignment === 'left') || (col && col.textalignment === ''),
+ 'text-center': col && col.textalignment === 'center',
+ 'text-right': col && col.textalignment === 'right',
+ 'align-top': model.rowalignment === 'top' || model.rowalignment === '',
+ 'align-center': model.rowalignment === 'center',
+ 'align-bottom': model.rowalignment === 'bottom'
+ }`
+ f.bindAttribute(tdItem, 'class', tdClasses, false)
+ f.addStyle(tdItem, 'background', "active[j] ? 'var(--color-red-500) !important' : ''")
+
+ f.addStyle(tdItem.find('span.item-text'), 'color',"active[j] ? 'var(--text-secondary-color) !important' : ''");
+
+ const tdAction = $.find('td.action-item').first()
+ f.addStyle(tdAction, 'background', "active[j] ? 'var(--color-red-500) !important' : ''")
+ f.addIf(tdAction, "model.selectable === 'true'")
+ f.addIf(tdAction.find('.unchecked'), '!active[j]');
+ f.addIf(tdAction.find('.checked'), 'active[j]');
+ f.addStyle(tdAction.find('.checked'), 'fill',"active[j] ? 'var(--text-secondary-color) !important' : ''");
+ f.bindEvent(tdAction.find('.action').eq(0), 'click', 'toggleRow(j)');
+ f.bindAttribute(tdAction, 'class', tdClasses, false)
+
+ const caption = $.find('caption')
+ const captionClasses = `{
+ 'text-left': model.captionalignment === 'left',
+ 'text-center': model.captionalignment === 'center',
+ 'text-right': model.captionalignment === 'right',
+ 'p-3': model.densetable !== 'true',
+ 'p-1': model.densetable === 'true',
+ 'hidden': model.caption !== 'true'
+ }`
+ f.bindAttribute(caption, 'class', captionClasses, false)
+ f.addStyle(caption, 'caption-side', "model.captionplacement", false);
+ f.mapField(caption, 'model.captiontext')
+
+ f.addElse($);
+ $.parent().prepend('
no content defined for component
')
+ }
+}
\ No newline at end of file
diff --git a/fragments/datalist/model.json b/fragments/datalist/model.json
new file mode 100644
index 000000000..aa60263de
--- /dev/null
+++ b/fragments/datalist/model.json
@@ -0,0 +1,222 @@
+{
+ "definitions": {
+ "Datalist": {
+ "type": "object",
+ "x-type": "component",
+ "properties": {
+ "endpointurl": {
+ "type": "string",
+ "x-source": "inject",
+ "x-form-label": "URL to load JSON data for table",
+ "x-form-type": "text",
+ "x-default": ""
+ },
+ "loadfunction": {
+ "type": "string",
+ "x-source": "inject",
+ "x-form-label": "Javascript function to call to load data",
+ "x-form-hint": "Function must accept (endpointurl)",
+ "x-form-type": "text"
+ },
+ "deletefunction": {
+ "type": "string",
+ "x-source": "inject",
+ "x-form-label": "Javascript function to call to delete rows",
+ "x-form-hint": "Function must accept (tableData, activeSelections, endpointurl)",
+ "x-form-type": "text"
+ },
+ "columns": {
+ "type": "string",
+ "x-source": "inject",
+ "x-form-label": "Table Configuration",
+ "x-form-fieldLabel": "header",
+ "x-form-type": "collection",
+ "properties": {
+ "header": {
+ "type": "string",
+ "x-source": "inject",
+ "x-form-label": "Column Header",
+ "x-form-type": "text"
+ },
+ "value": {
+ "type": "string",
+ "x-source": "inject",
+ "x-form-label": "Data Value",
+ "x-form-type": "text"
+ },
+ "textalignment": {
+ "type": "string",
+ "x-source": "inject",
+ "x-form-label": "Text alignment",
+ "x-form-type": "materialselect",
+ "x-default": "left",
+ "properties":{
+ "left": {
+ "x-form-name": "left",
+ "x-form-value": "left"
+ },
+ "center": {
+ "x-form-name": "center",
+ "x-form-value": "center"
+ },
+ "right": {
+ "x-form-name": "right",
+ "x-form-value": "right"
+ }
+ }
+ }
+ }
+ },
+ "rowalignment": {
+ "type": "string",
+ "x-source": "inject",
+ "x-form-label": "Row alignment",
+ "x-form-type": "materialselect",
+ "x-default": "top",
+ "properties":{
+ "top": {
+ "x-form-name": "top",
+ "x-form-value": "top"
+ },
+ "center": {
+ "x-form-name": "center",
+ "x-form-value": "center"
+ },
+ "bottom": {
+ "x-form-name": "bottom",
+ "x-form-value": "bottom"
+ }
+ }
+ },
+ "mobiletablestyle": {
+ "type": "string",
+ "x-source": "inject",
+ "x-form-label": "Mobile table style",
+ "x-form-type": "materialselect",
+ "x-default": "default",
+ "properties":{
+ "default": {
+ "x-form-name": "default",
+ "x-form-value": "default"
+ },
+ "scroll": {
+ "x-form-name": "scroll",
+ "x-form-value": "scroll"
+ }
+ }
+ },
+ "stripedrows": {
+ "type": "string",
+ "x-source": "inject",
+ "x-form-label": "Striped Rows",
+ "x-form-type": "materialswitch",
+ "x-default": false
+ },
+ "densetable": {
+ "type": "string",
+ "x-source": "inject",
+ "x-form-label": "Dense Table",
+ "x-form-type": "materialswitch",
+ "x-default": false
+ },
+ "scrollabletable": {
+ "type": "string",
+ "x-source": "inject",
+ "x-form-label": "Scrollable Table",
+ "x-form-type": "materialswitch",
+ "x-default": false
+ },
+ "stickyheader": {
+ "type": "string",
+ "x-source": "inject",
+ "x-form-label": "Sticky Header",
+ "x-form-type": "materialswitch",
+ "x-form-visible": "model.scrollabletable == 'true'",
+ "x-default": false
+ },
+ "tableheight": {
+ "type": "string",
+ "x-source": "inject",
+ "x-form-label": "Table Height",
+ "x-form-type": "materialrange",
+ "x-form-min": 100,
+ "x-form-max": 500,
+ "x-default": 300,
+ "x-form-visible": "model.scrollabletable == 'true'"
+ },
+ "selectable": {
+ "type": "string",
+ "x-source": "inject",
+ "x-form-label": "Selectable Table",
+ "x-form-type": "materialswitch",
+ "x-default": false
+ },
+ "cellborders": {
+ "type": "string",
+ "x-source": "inject",
+ "x-form-label": "Add borders around individual cells",
+ "x-form-type": "materialswitch",
+ "x-default": false
+ },
+ "caption": {
+ "type": "string",
+ "x-source": "inject",
+ "x-form-label": "Table caption",
+ "x-form-type": "materialswitch",
+ "x-default": false
+ },
+ "captiontext": {
+ "type": "string",
+ "x-source": "inject",
+ "x-form-label": "Caption text",
+ "x-form-type": "text",
+ "x-form-visible": "model.caption == 'true'"
+ },
+ "captionplacement": {
+ "type": "string",
+ "x-source": "inject",
+ "x-form-label": "Caption placement",
+ "x-form-type": "materialselect",
+ "x-default": "bottom",
+ "x-form-visible": "model.caption == 'true'",
+ "properties":{
+ "top": {
+ "x-form-name": "top",
+ "x-form-value": "top"
+ },
+ "bottom": {
+ "x-form-name": "bottom",
+ "x-form-value": "bottom"
+ }
+ }
+ },
+ "captionalignment": {
+ "type": "string",
+ "x-source": "inject",
+ "x-form-label": "Caption alignment",
+ "x-form-type": "materialselect",
+ "x-default": "left",
+ "x-form-visible": "model.caption == 'true'",
+ "properties":{
+ "left": {
+ "x-form-name": "left",
+ "x-form-value": "left"
+ },
+ "center": {
+ "x-form-name": "center",
+ "x-form-value": "center"
+ },
+ "right": {
+ "x-form-name": "right",
+ "x-form-value": "right"
+ }
+ }
+ },
+ "bgref": {
+ "$ref": "fragments/block/model.json#/definitions/Block",
+ "x-form-type": "reference"
+ }
+ }
+ }
+ }
+}
diff --git a/fragments/datalist/sample.json b/fragments/datalist/sample.json
new file mode 100644
index 000000000..010210861
--- /dev/null
+++ b/fragments/datalist/sample.json
@@ -0,0 +1,7 @@
+{
+ "title": "Datalist",
+ "group": "",
+ "model": {
+ "text": "example"
+ }
+}
\ No newline at end of file
diff --git a/fragments/datalist/template.html b/fragments/datalist/template.html
new file mode 100644
index 000000000..37de190ef
--- /dev/null
+++ b/fragments/datalist/template.html
@@ -0,0 +1,102 @@
+
+
+
+
+
+
+
+
+
+
0 Selected
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/fragments/datalist/template.vue b/fragments/datalist/template.vue
new file mode 100644
index 000000000..f6e4497c2
--- /dev/null
+++ b/fragments/datalist/template.vue
@@ -0,0 +1,427 @@
+
+
+ no content defined for component
+
+
+
+
+
+
+
+
+
+
{{`${active.filter(element => element === true).length} selected`}}
+
+
+
+
+
+
+
+
+
diff --git a/fragments/form/hatch.js b/fragments/form/hatch.js
new file mode 100644
index 000000000..2a4f91dfc
--- /dev/null
+++ b/fragments/form/hatch.js
@@ -0,0 +1,45 @@
+module.exports = {
+ convert: function($, f) {
+ f.wrap($, 'themecleanflex-components-block')
+ f.bindAttribute($.parent(),'model','model')
+
+ const failureP = $.find('p').eq(0)
+ f.mapField(failureP,'failureText',false)
+ f.addIf(failureP, "failureText");
+ const schemaErrorP = $.find('p').eq(1)
+ f.mapField(schemaErrorP,'schemaError',false)
+ f.addIf(schemaErrorP, "schemaError");
+
+ const messageContainer = $.find('div').eq(0);
+ f.addIf(messageContainer, "( failureText || schemaError )");
+
+ const submit = $.find('input').first()
+ f.bindAttribute(submit,'value','model.submittext')
+
+ const formContainer = $.find('form').eq(0);
+ let formContainerClasses = `{
+ 'justify-button-start': model.submitalignment === 'start',
+ 'justify-button-center': model.submitalignment === 'center',
+ 'justify-button-end': model.submitalignment === 'end',
+ 'normal-button': model.submitsize === 'normal',
+ 'sm-button': model.submitsize === 'small',
+ 'lg-button': model.submitsize === 'large',
+ 'full-button': model.submitsize === 'full',
+ }`
+ f.bindAttribute(formContainer, 'class', formContainerClasses, false);
+
+ const div2 = $.find('div').eq(1)
+ f.replace(div2, '
')
+
+ const formEl = $.find('form')
+ f.bindEvent(formEl,'submit.prevent.stop','onSubmit')
+
+ const form = $.find('vue-form-generator').first()
+ f.bindAttribute(form,'class','`w-full`', false)
+ f.bindAttribute(form,'model','formModel')
+ f.bindAttribute(form,'schema','schema')
+ f.bindAttribute(form,'options','formOptions')
+
+ f.bindPath($)
+ }
+}
\ No newline at end of file
diff --git a/fragments/form/model.json b/fragments/form/model.json
new file mode 100644
index 000000000..bb1fd7f4b
--- /dev/null
+++ b/fragments/form/model.json
@@ -0,0 +1,104 @@
+{
+ "definitions": {
+ "Form": {
+ "type": "object",
+ "x-type": "component",
+ "properties": {
+ "schema": {
+ "type": "string",
+ "x-source": "inject",
+ "x-form-label": "Form Model",
+ "x-form-type": "textarea",
+ "x-form-hint": "JSON description passed to vue-form-generator, see
vue form generator fields documentation ",
+ "x-form-max": "16000"
+ },
+ "endpointurl": {
+ "type": "string",
+ "x-source": "inject",
+ "x-form-label": "Form submit endpoint URL",
+ "x-form-type": "text",
+ "x-default": ""
+ },
+ "submitfunction": {
+ "type": "string",
+ "x-source": "inject",
+ "x-form-label": "Javascript function to call on submit",
+ "x-form-hint": "Function must accept (model, formdata)",
+ "x-form-type": "text",
+ "x-default": ""
+ },
+ "submittext": {
+ "type": "string",
+ "x-source": "inject",
+ "x-form-label": "Submit Button Text",
+ "x-form-type": "text",
+ "x-default": "Submit"
+ },
+ "submitsize": {
+ "type": "string",
+ "x-source": "inject",
+ "x-form-label": "Submit button size",
+ "x-form-type": "materialselect",
+ "x-default": "normal",
+ "properties":{
+ "section": {
+ "x-form-name": "normal",
+ "x-form-value": "normal"
+ },
+ "small": {
+ "x-form-name": "small",
+ "x-form-value": "small"
+ },
+ "large": {
+ "x-form-name": "large",
+ "x-form-value": "large"
+ },
+ "full": {
+ "x-form-name": "full width",
+ "x-form-value": "full"
+ }
+ }
+ },
+ "submitalignment": {
+ "type": "string",
+ "x-source": "inject",
+ "x-form-label": "Submit button alignment",
+ "x-form-type": "materialselect",
+ "x-default": "start",
+ "properties":{
+ "start": {
+ "x-form-name": "start",
+ "x-form-value": "start"
+ },
+ "center": {
+ "x-form-name": "center",
+ "x-form-value": "center"
+ },
+ "end": {
+ "x-form-name": "end",
+ "x-form-value": "end"
+ }
+ }
+ },
+ "failmessage": {
+ "type": "string",
+ "x-source": "inject",
+ "x-form-label": "Failure Message",
+ "x-form-type": "text",
+ "x-default": "Error processing form"
+ },
+ "successpage": {
+ "type": "string",
+ "x-source": "inject",
+ "x-form-type": "pathbrowser",
+ "x-form-label": "Submit Success Page",
+ "x-form-browserRoot": "/content/themecleanflex/pages"
+ },
+ "bgref": {
+ "$ref": "fragments/block/model.json#/definitions/Block",
+ "x-form-type": "reference"
+ }
+ }
+ }
+ }
+}
diff --git a/fragments/form/sample-all.json b/fragments/form/sample-all.json
new file mode 100644
index 000000000..21529522d
--- /dev/null
+++ b/fragments/form/sample-all.json
@@ -0,0 +1,7 @@
+{
+ "title": "Form - Input Types",
+ "group": "Features",
+ "model": {
+ "schema": "{\n\"groups\":[\n{\n\"legend\":\"Text Inputs\",\n\"fields\": [\n {\n \"type\": \"label\",\n \"label\": \"Label\",\n \"model\": \"label\"\n },{\n \"type\": \"input\",\n \"inputType\": \"text\",\n \"label\": \"Text\",\n \"model\": \"text\",\n \"id\": \"text\",\n \"placeholder\": \"Text\"\n },{\n \"type\": \"textArea\",\n \"label\": \"Text Area\",\n \"model\": \"textarea\",\n \"id\": \"textarea\",\n \"rows\": 4,\n \"placeholder\": \"Enter text here\"\n }\n ]\n},\n{\n\"legend\":\"Other Inputs\",\n\"fields\": [\n {\n \"type\": \"radios\",\n \"label\": \"Radios\",\n \"model\": \"radios\",\n \"values\": [\n \"Option 1\",\n \"Option 2\"\n ]\n },{\n \"type\": \"checkbox\",\n \"label\": \"Checkbox\",\n \"model\": \"checkbox\",\n \"default\": true\n },{\n \"type\": \"checklist\",\n \"label\": \"Checklist\",\n \"model\": \"checklist\",\n \"listBox\": true,\n \"values\": [\n \"Option 1\",\n \"Option 2\"\n ]\n },{\n \"type\": \"select\",\n \"label\": \"Select\",\n \"model\": \"select\",\n \"values\": [\n \"Option 1\",\n \"Option 2\"\n ]\n },{\n \"type\": \"submit\",\n \"buttonText\": \"Submit Button\",\n \"validateBeforeSubmit\": false\n }\n]}]}"
+ }
+}
\ No newline at end of file
diff --git a/fragments/form/sample-contact.json b/fragments/form/sample-contact.json
new file mode 100644
index 000000000..40ba62b26
--- /dev/null
+++ b/fragments/form/sample-contact.json
@@ -0,0 +1,7 @@
+{
+ "title": "Form - Contact",
+ "group": "Features",
+ "model": {
+ "schema": "{\n\"fields\": [\n {\n \"type\": \"input\",\n \"inputType\": \"text\",\n \"label\": \"First Name\",\n \"model\": \"first_name\",\n \"id\": \"first_name\",\n \"placeholder\": \"First Name\"\n },{\n \"type\": \"input\",\n \"inputType\": \"text\",\n \"label\": \"Last Name\",\n \"model\": \"last_name\",\n \"id\": \"last_name\",\n \"placeholder\": \"Last Name\"\n },{\n \"type\": \"input\",\n \"inputType\": \"text\",\n \"label\": \"Email\",\n \"model\": \"email\",\n \"id\": \"email\",\n \"placeholder\": \"Email\",\n \"featured\": true,\n \"required\": true\n },{\n \"type\": \"textArea\",\n \"label\": \"Text\",\n \"model\": \"text\",\n \"id\": \"text\",\n \"rows\": 4,\n \"placeholder\": \"Enter text here\",\n \"featured\": true,\n \"required\": true\n }\n]}"
+ }
+}
\ No newline at end of file
diff --git a/fragments/form/sample.json b/fragments/form/sample.json
new file mode 100644
index 000000000..b395deebf
--- /dev/null
+++ b/fragments/form/sample.json
@@ -0,0 +1,7 @@
+{
+ "title": "Form",
+ "group": "Features",
+ "model": {
+ "schema": "{\n\"fields\": [\n {\n \"type\": \"input\",\n \"inputType\": \"text\",\n \"label\": \"Name\",\n \"model\": \"name\",\n \"id\": \"user_name\",\n \"placeholder\": \"Your name\",\n \"featured\": true,\n \"required\": true\n }\n]}"
+ }
+}
\ No newline at end of file
diff --git a/fragments/form/template.html b/fragments/form/template.html
new file mode 100644
index 000000000..0a283a21c
--- /dev/null
+++ b/fragments/form/template.html
@@ -0,0 +1,10 @@
+
\ No newline at end of file
diff --git a/fragments/form/template.vue b/fragments/form/template.vue
new file mode 100644
index 000000000..afc8481c0
--- /dev/null
+++ b/fragments/form/template.vue
@@ -0,0 +1,107 @@
+
+
+
+
+
{{failureText}}
+
{{schemaError}}
+
+
+
+
+
+
+
+
diff --git a/fragments/media/model.json b/fragments/media/model.json
index 948dec5f8..48e6156c4 100644
--- a/fragments/media/model.json
+++ b/fragments/media/model.json
@@ -27,7 +27,8 @@
"x-form-visible": "model.mediatype == 'image'",
"x-form-type": "pathbrowser",
"x-form-browserRoot": "/content/themecleanflex/assets",
- "x-default": ""
+ "x-default": "",
+ "x-annotate": "size"
},
"videosrc": {
"type": "string",
diff --git a/fragments/mediavisible/model.json b/fragments/mediavisible/model.json
index e22504ca1..58e146c9e 100644
--- a/fragments/mediavisible/model.json
+++ b/fragments/mediavisible/model.json
@@ -34,7 +34,8 @@
"x-form-visible": "model.mediatype == 'image' and model.showmedia == 'true'",
"x-form-type": "pathbrowser",
"x-form-browserRoot": "/content/themecleanflex/assets",
- "x-default": ""
+ "x-default": "",
+ "x-annotate": "size"
},
"videosrc": {
"type": "string",
diff --git a/pom.xml b/pom.xml
index 8160f4bf5..8d6e80fd9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -56,7 +56,7 @@
3.0.2
1.4.1
3.6.1
-
2.5.4
+
4.2.1
3.0.0
2.5.2
2.20
@@ -80,7 +80,7 @@
6.1.23
-
7
+
11
4.12
diff --git a/ui.apps/src/main/content/jcr_root/apps/themecleanflex/components/cards/template.vue b/ui.apps/src/main/content/jcr_root/apps/themecleanflex/components/cards/template.vue
index 79f271abd..9670fbef0 100644
--- a/ui.apps/src/main/content/jcr_root/apps/themecleanflex/components/cards/template.vue
+++ b/ui.apps/src/main/content/jcr_root/apps/themecleanflex/components/cards/template.vue
@@ -36,7 +36,7 @@
+ v-bind:src-placeholder="placeholderSrc(item)" v-if="item.image">
+
+
+
\ No newline at end of file
diff --git a/ui.apps/src/main/content/jcr_root/apps/themecleanflex/components/datalist/dialog.json b/ui.apps/src/main/content/jcr_root/apps/themecleanflex/components/datalist/dialog.json
new file mode 100644
index 000000000..714589ea6
--- /dev/null
+++ b/ui.apps/src/main/content/jcr_root/apps/themecleanflex/components/datalist/dialog.json
@@ -0,0 +1,481 @@
+{
+ "fields": [
+ {
+ "type": "input",
+ "inputType": "text",
+ "placeholder": "endpointurl",
+ "label": "URL to load JSON data for table",
+ "model": "endpointurl"
+ },
+ {
+ "type": "input",
+ "inputType": "text",
+ "placeholder": "loadfunction",
+ "label": "Javascript function to call to load data",
+ "model": "loadfunction",
+ "hint": "Function must accept (endpointurl)"
+ },
+ {
+ "type": "input",
+ "inputType": "text",
+ "placeholder": "deletefunction",
+ "label": "Javascript function to call to delete rows",
+ "model": "deletefunction",
+ "hint": "Function must accept (tableData, activeSelections, endpointurl)"
+ },
+ {
+ "type": "collection",
+ "multifield": true,
+ "fieldLabel": [
+ "header",
+ "value"
+ ],
+ "fields": [
+ {
+ "type": "input",
+ "inputType": "text",
+ "placeholder": "header",
+ "label": "Column Header",
+ "model": "header"
+ },
+ {
+ "type": "input",
+ "inputType": "text",
+ "placeholder": "value",
+ "label": "Data Value",
+ "model": "value"
+ },
+ {
+ "type": "material-select",
+ "values": [
+ {
+ "name": "left",
+ "value": "left"
+ },
+ {
+ "name": "center",
+ "value": "center"
+ },
+ {
+ "name": "right",
+ "value": "right"
+ }
+ ],
+ "placeholder": "textalignment",
+ "label": "Text alignment",
+ "model": "textalignment"
+ }
+ ],
+ "placeholder": "columns",
+ "label": "Table Configuration",
+ "model": "columns"
+ },
+ {
+ "type": "material-select",
+ "values": [
+ {
+ "name": "top",
+ "value": "top"
+ },
+ {
+ "name": "center",
+ "value": "center"
+ },
+ {
+ "name": "bottom",
+ "value": "bottom"
+ }
+ ],
+ "placeholder": "rowalignment",
+ "label": "Row alignment",
+ "model": "rowalignment"
+ },
+ {
+ "type": "material-select",
+ "values": [
+ {
+ "name": "default",
+ "value": "default"
+ },
+ {
+ "name": "scroll",
+ "value": "scroll"
+ }
+ ],
+ "placeholder": "mobiletablestyle",
+ "label": "Mobile table style",
+ "model": "mobiletablestyle"
+ },
+ {
+ "type": "materialswitch",
+ "textOn": "yes",
+ "textOff": "no",
+ "valueOn": "true",
+ "valueOff": "false",
+ "placeholder": "stripedrows",
+ "label": "Striped Rows",
+ "model": "stripedrows"
+ },
+ {
+ "type": "materialswitch",
+ "textOn": "yes",
+ "textOff": "no",
+ "valueOn": "true",
+ "valueOff": "false",
+ "placeholder": "densetable",
+ "label": "Dense Table",
+ "model": "densetable"
+ },
+ {
+ "type": "materialswitch",
+ "textOn": "yes",
+ "textOff": "no",
+ "valueOn": "true",
+ "valueOff": "false",
+ "placeholder": "scrollabletable",
+ "label": "Scrollable Table",
+ "model": "scrollabletable"
+ },
+ {
+ "type": "materialswitch",
+ "textOn": "yes",
+ "textOff": "no",
+ "valueOn": "true",
+ "valueOff": "false",
+ "placeholder": "stickyheader",
+ "label": "Sticky Header",
+ "model": "stickyheader",
+ "visible": "model.scrollabletable == 'true'"
+ },
+ {
+ "type": "material-range",
+ "placeholder": "tableheight",
+ "label": "Table Height",
+ "model": "tableheight",
+ "visible": "model.scrollabletable == 'true'",
+ "min": 100,
+ "max": 500
+ },
+ {
+ "type": "materialswitch",
+ "textOn": "yes",
+ "textOff": "no",
+ "valueOn": "true",
+ "valueOff": "false",
+ "placeholder": "selectable",
+ "label": "Selectable Table",
+ "model": "selectable"
+ },
+ {
+ "type": "materialswitch",
+ "textOn": "yes",
+ "textOff": "no",
+ "valueOn": "true",
+ "valueOff": "false",
+ "placeholder": "cellborders",
+ "label": "Add borders around individual cells",
+ "model": "cellborders"
+ },
+ {
+ "type": "materialswitch",
+ "textOn": "yes",
+ "textOff": "no",
+ "valueOn": "true",
+ "valueOff": "false",
+ "placeholder": "caption",
+ "label": "Table caption",
+ "model": "caption"
+ },
+ {
+ "type": "input",
+ "inputType": "text",
+ "placeholder": "captiontext",
+ "label": "Caption text",
+ "model": "captiontext",
+ "visible": "model.caption == 'true'"
+ },
+ {
+ "type": "material-select",
+ "values": [
+ {
+ "name": "top",
+ "value": "top"
+ },
+ {
+ "name": "bottom",
+ "value": "bottom"
+ }
+ ],
+ "placeholder": "captionplacement",
+ "label": "Caption placement",
+ "model": "captionplacement",
+ "visible": "model.caption == 'true'"
+ },
+ {
+ "type": "material-select",
+ "values": [
+ {
+ "name": "left",
+ "value": "left"
+ },
+ {
+ "name": "center",
+ "value": "center"
+ },
+ {
+ "name": "right",
+ "value": "right"
+ }
+ ],
+ "placeholder": "captionalignment",
+ "label": "Caption alignment",
+ "model": "captionalignment",
+ "visible": "model.caption == 'true'"
+ },
+ {
+ "type": "input",
+ "inputType": "text",
+ "placeholder": "anchorname",
+ "label": "Anchor Name",
+ "model": "anchorname"
+ },
+ {
+ "type": "input",
+ "inputType": "text",
+ "placeholder": "extraclasses",
+ "label": "Additonal Classes",
+ "model": "extraclasses"
+ },
+ {
+ "type": "material-select",
+ "values": [
+ {
+ "name": "section",
+ "value": "section"
+ },
+ {
+ "name": "article",
+ "value": "article"
+ },
+ {
+ "name": "main",
+ "value": "main"
+ },
+ {
+ "name": "div",
+ "value": "div"
+ },
+ {
+ "name": "header",
+ "value": "header"
+ },
+ {
+ "name": "nav",
+ "value": "nav"
+ },
+ {
+ "name": "footer",
+ "value": "footer"
+ }
+ ],
+ "placeholder": "htmlelement",
+ "label": "Semantic Element",
+ "model": "htmlelement"
+ },
+ {
+ "type": "material-radios",
+ "values": [
+ {
+ "name": "None",
+ "value": ""
+ },
+ {
+ "name": "Light",
+ "value": "light"
+ },
+ {
+ "name": "Dark",
+ "value": "dark"
+ }
+ ],
+ "placeholder": "colorscheme",
+ "label": "Block Color Scheme",
+ "model": "colorscheme"
+ },
+ {
+ "type": "materialswitch",
+ "textOn": "yes",
+ "textOff": "no",
+ "valueOn": "true",
+ "valueOff": "false",
+ "placeholder": "custombackground",
+ "label": "Custom Background",
+ "model": "custombackground"
+ },
+ {
+ "type": "material-radios",
+ "values": [
+ {
+ "name": "Color",
+ "value": "color"
+ },
+ {
+ "name": "Gradient",
+ "value": "gradient"
+ },
+ {
+ "name": "Image",
+ "value": "image"
+ },
+ {
+ "name": "Video",
+ "value": "video"
+ }
+ ],
+ "placeholder": "backgroundtype",
+ "label": "Background Type",
+ "model": "backgroundtype",
+ "visible": "model.custombackground == 'true'"
+ },
+ {
+ "type": "pathbrowser",
+ "browserRoot": "/content/themecleanflex/assets",
+ "placeholder": "bgvideo",
+ "label": "Background Video",
+ "model": "bgvideo",
+ "visible": "model.backgroundtype == 'video' and model.custombackground == 'true'"
+ },
+ {
+ "type": "pathbrowser",
+ "browserRoot": "/content/themecleanflex/assets",
+ "placeholder": "bgimage",
+ "label": "Background Image",
+ "model": "bgimage",
+ "visible": "model.backgroundtype == 'image' and model.custombackground == 'true'"
+ },
+ {
+ "type": "material-range",
+ "placeholder": "bgxposition",
+ "label": "Background X Position",
+ "model": "bgxposition",
+ "visible": "model.backgroundtype == 'image' and model.custombackground == 'true'",
+ "min": 0,
+ "max": 100
+ },
+ {
+ "type": "material-range",
+ "placeholder": "bgyposition",
+ "label": "Background Y Position",
+ "model": "bgyposition",
+ "visible": "model.backgroundtype == 'image' and model.custombackground == 'true'",
+ "min": 0,
+ "max": 100
+ },
+ {
+ "type": "input",
+ "inputType": "text",
+ "placeholder": "bgsize",
+ "label": "Background Size Style",
+ "model": "bgsize"
+ },
+ {
+ "type": "materialswitch",
+ "textOn": "yes",
+ "textOff": "no",
+ "valueOn": "true",
+ "valueOff": "false",
+ "placeholder": "overlay",
+ "label": "Overlay",
+ "model": "overlay",
+ "visible": "model.backgroundtype == 'image' and model.custombackground == 'true'"
+ },
+ {
+ "type": "input",
+ "inputType": "color",
+ "placeholder": "overlaycolor",
+ "label": "Overlay Color",
+ "model": "overlaycolor",
+ "visible": "model.overlay == 'true' and model.backgroundtype == 'image' and model.custombackground == 'true'"
+ },
+ {
+ "type": "material-range",
+ "placeholder": "overlayopacity",
+ "label": "Overlay opacity",
+ "model": "overlayopacity",
+ "visible": "model.overlay == 'true' and model.backgroundtype == 'image' and model.custombackground == 'true'",
+ "min": 0,
+ "max": 100
+ },
+ {
+ "type": "input",
+ "inputType": "color",
+ "placeholder": "bgcolor",
+ "label": "Background Color",
+ "model": "bgcolor",
+ "visible": "(model.backgroundtype == 'color' or model.backgroundtype == 'gradient') and model.custombackground == 'true'"
+ },
+ {
+ "type": "input",
+ "inputType": "color",
+ "placeholder": "color2",
+ "label": "Color 2",
+ "model": "color2",
+ "visible": "model.backgroundtype == 'gradient' and model.custombackground == 'true'"
+ },
+ {
+ "type": "material-radios",
+ "values": [
+ {
+ "name": "Default",
+ "value": "default"
+ },
+ {
+ "name": "Full Width",
+ "value": "full"
+ },
+ {
+ "name": "Article Width",
+ "value": "article"
+ }
+ ],
+ "placeholder": "blockwidth",
+ "label": "Block Width",
+ "model": "blockwidth"
+ },
+ {
+ "type": "materialswitch",
+ "textOn": "yes",
+ "textOff": "no",
+ "valueOn": "true",
+ "valueOff": "false",
+ "placeholder": "fullheight",
+ "label": "Full Height",
+ "model": "fullheight"
+ },
+ {
+ "type": "material-range",
+ "placeholder": "toppadding",
+ "label": "Top Padding",
+ "model": "toppadding",
+ "visible": "model.fullheight != 'true'",
+ "min": 0,
+ "max": 300
+ },
+ {
+ "type": "material-range",
+ "placeholder": "bottompadding",
+ "label": "Bottom Padding",
+ "model": "bottompadding",
+ "visible": "model.fullheight != 'true'",
+ "min": 0,
+ "max": 300
+ },
+ {
+ "type": "input",
+ "inputType": "text",
+ "placeholder": "contentname",
+ "label": "Content Name",
+ "model": "contentname"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/ui.apps/src/main/content/jcr_root/apps/themecleanflex/components/datalist/template.vue b/ui.apps/src/main/content/jcr_root/apps/themecleanflex/components/datalist/template.vue
new file mode 100644
index 000000000..f6e4497c2
--- /dev/null
+++ b/ui.apps/src/main/content/jcr_root/apps/themecleanflex/components/datalist/template.vue
@@ -0,0 +1,427 @@
+
+
+ no content defined for component
+
+
+
+
+
+
+
+
+
+
{{`${active.filter(element => element === true).length} selected`}}
+
+
+
+
+
+
+
+
+
diff --git a/ui.apps/src/main/content/jcr_root/apps/themecleanflex/components/form/.content.xml b/ui.apps/src/main/content/jcr_root/apps/themecleanflex/components/form/.content.xml
new file mode 100644
index 000000000..5dc3a7d97
--- /dev/null
+++ b/ui.apps/src/main/content/jcr_root/apps/themecleanflex/components/form/.content.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ui.apps/src/main/content/jcr_root/apps/themecleanflex/components/form/dialog.json b/ui.apps/src/main/content/jcr_root/apps/themecleanflex/components/form/dialog.json
new file mode 100644
index 000000000..b57d1f269
--- /dev/null
+++ b/ui.apps/src/main/content/jcr_root/apps/themecleanflex/components/form/dialog.json
@@ -0,0 +1,338 @@
+{
+ "fields": [
+ {
+ "type": "material-textarea",
+ "rows": 10,
+ "max": "16000",
+ "placeholder": "schema",
+ "label": "Form Model",
+ "model": "schema",
+ "hint": "JSON description passed to vue-form-generator, see
vue form generator fields documentation "
+ },
+ {
+ "type": "input",
+ "inputType": "text",
+ "placeholder": "endpointurl",
+ "label": "Form submit endpoint URL",
+ "model": "endpointurl"
+ },
+ {
+ "type": "input",
+ "inputType": "text",
+ "placeholder": "submitfunction",
+ "label": "Javascript function to call on submit",
+ "model": "submitfunction",
+ "hint": "Function must accept (model, formdata)"
+ },
+ {
+ "type": "input",
+ "inputType": "text",
+ "placeholder": "submittext",
+ "label": "Submit Button Text",
+ "model": "submittext"
+ },
+ {
+ "type": "material-select",
+ "values": [
+ {
+ "name": "normal",
+ "value": "normal"
+ },
+ {
+ "name": "small",
+ "value": "small"
+ },
+ {
+ "name": "large",
+ "value": "large"
+ },
+ {
+ "name": "full width",
+ "value": "full"
+ }
+ ],
+ "placeholder": "submitsize",
+ "label": "Submit button size",
+ "model": "submitsize"
+ },
+ {
+ "type": "material-select",
+ "values": [
+ {
+ "name": "start",
+ "value": "start"
+ },
+ {
+ "name": "center",
+ "value": "center"
+ },
+ {
+ "name": "end",
+ "value": "end"
+ }
+ ],
+ "placeholder": "submitalignment",
+ "label": "Submit button alignment",
+ "model": "submitalignment"
+ },
+ {
+ "type": "input",
+ "inputType": "text",
+ "placeholder": "failmessage",
+ "label": "Failure Message",
+ "model": "failmessage"
+ },
+ {
+ "type": "pathbrowser",
+ "browserRoot": "/content/themecleanflex/pages",
+ "placeholder": "successpage",
+ "label": "Submit Success Page",
+ "model": "successpage"
+ },
+ {
+ "type": "input",
+ "inputType": "text",
+ "placeholder": "anchorname",
+ "label": "Anchor Name",
+ "model": "anchorname"
+ },
+ {
+ "type": "input",
+ "inputType": "text",
+ "placeholder": "extraclasses",
+ "label": "Additonal Classes",
+ "model": "extraclasses"
+ },
+ {
+ "type": "material-select",
+ "values": [
+ {
+ "name": "section",
+ "value": "section"
+ },
+ {
+ "name": "article",
+ "value": "article"
+ },
+ {
+ "name": "main",
+ "value": "main"
+ },
+ {
+ "name": "div",
+ "value": "div"
+ },
+ {
+ "name": "header",
+ "value": "header"
+ },
+ {
+ "name": "nav",
+ "value": "nav"
+ },
+ {
+ "name": "footer",
+ "value": "footer"
+ }
+ ],
+ "placeholder": "htmlelement",
+ "label": "Semantic Element",
+ "model": "htmlelement"
+ },
+ {
+ "type": "material-radios",
+ "values": [
+ {
+ "name": "None",
+ "value": ""
+ },
+ {
+ "name": "Light",
+ "value": "light"
+ },
+ {
+ "name": "Dark",
+ "value": "dark"
+ }
+ ],
+ "placeholder": "colorscheme",
+ "label": "Block Color Scheme",
+ "model": "colorscheme"
+ },
+ {
+ "type": "materialswitch",
+ "textOn": "yes",
+ "textOff": "no",
+ "valueOn": "true",
+ "valueOff": "false",
+ "placeholder": "custombackground",
+ "label": "Custom Background",
+ "model": "custombackground"
+ },
+ {
+ "type": "material-radios",
+ "values": [
+ {
+ "name": "Color",
+ "value": "color"
+ },
+ {
+ "name": "Gradient",
+ "value": "gradient"
+ },
+ {
+ "name": "Image",
+ "value": "image"
+ },
+ {
+ "name": "Video",
+ "value": "video"
+ }
+ ],
+ "placeholder": "backgroundtype",
+ "label": "Background Type",
+ "model": "backgroundtype",
+ "visible": "model.custombackground == 'true'"
+ },
+ {
+ "type": "pathbrowser",
+ "browserRoot": "/content/themecleanflex/assets",
+ "placeholder": "bgvideo",
+ "label": "Background Video",
+ "model": "bgvideo",
+ "visible": "model.backgroundtype == 'video' and model.custombackground == 'true'"
+ },
+ {
+ "type": "pathbrowser",
+ "browserRoot": "/content/themecleanflex/assets",
+ "placeholder": "bgimage",
+ "label": "Background Image",
+ "model": "bgimage",
+ "visible": "model.backgroundtype == 'image' and model.custombackground == 'true'"
+ },
+ {
+ "type": "material-range",
+ "placeholder": "bgxposition",
+ "label": "Background X Position",
+ "model": "bgxposition",
+ "visible": "model.backgroundtype == 'image' and model.custombackground == 'true'",
+ "min": 0,
+ "max": 100
+ },
+ {
+ "type": "material-range",
+ "placeholder": "bgyposition",
+ "label": "Background Y Position",
+ "model": "bgyposition",
+ "visible": "model.backgroundtype == 'image' and model.custombackground == 'true'",
+ "min": 0,
+ "max": 100
+ },
+ {
+ "type": "input",
+ "inputType": "text",
+ "placeholder": "bgsize",
+ "label": "Background Size Style",
+ "model": "bgsize"
+ },
+ {
+ "type": "materialswitch",
+ "textOn": "yes",
+ "textOff": "no",
+ "valueOn": "true",
+ "valueOff": "false",
+ "placeholder": "overlay",
+ "label": "Overlay",
+ "model": "overlay",
+ "visible": "model.backgroundtype == 'image' and model.custombackground == 'true'"
+ },
+ {
+ "type": "input",
+ "inputType": "color",
+ "placeholder": "overlaycolor",
+ "label": "Overlay Color",
+ "model": "overlaycolor",
+ "visible": "model.overlay == 'true' and model.backgroundtype == 'image' and model.custombackground == 'true'"
+ },
+ {
+ "type": "material-range",
+ "placeholder": "overlayopacity",
+ "label": "Overlay opacity",
+ "model": "overlayopacity",
+ "visible": "model.overlay == 'true' and model.backgroundtype == 'image' and model.custombackground == 'true'",
+ "min": 0,
+ "max": 100
+ },
+ {
+ "type": "input",
+ "inputType": "color",
+ "placeholder": "bgcolor",
+ "label": "Background Color",
+ "model": "bgcolor",
+ "visible": "(model.backgroundtype == 'color' or model.backgroundtype == 'gradient') and model.custombackground == 'true'"
+ },
+ {
+ "type": "input",
+ "inputType": "color",
+ "placeholder": "color2",
+ "label": "Color 2",
+ "model": "color2",
+ "visible": "model.backgroundtype == 'gradient' and model.custombackground == 'true'"
+ },
+ {
+ "type": "material-radios",
+ "values": [
+ {
+ "name": "Default",
+ "value": "default"
+ },
+ {
+ "name": "Full Width",
+ "value": "full"
+ },
+ {
+ "name": "Article Width",
+ "value": "article"
+ }
+ ],
+ "placeholder": "blockwidth",
+ "label": "Block Width",
+ "model": "blockwidth"
+ },
+ {
+ "type": "materialswitch",
+ "textOn": "yes",
+ "textOff": "no",
+ "valueOn": "true",
+ "valueOff": "false",
+ "placeholder": "fullheight",
+ "label": "Full Height",
+ "model": "fullheight"
+ },
+ {
+ "type": "material-range",
+ "placeholder": "toppadding",
+ "label": "Top Padding",
+ "model": "toppadding",
+ "visible": "model.fullheight != 'true'",
+ "min": 0,
+ "max": 300
+ },
+ {
+ "type": "material-range",
+ "placeholder": "bottompadding",
+ "label": "Bottom Padding",
+ "model": "bottompadding",
+ "visible": "model.fullheight != 'true'",
+ "min": 0,
+ "max": 300
+ },
+ {
+ "type": "input",
+ "inputType": "text",
+ "placeholder": "contentname",
+ "label": "Content Name",
+ "model": "contentname"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/ui.apps/src/main/content/jcr_root/apps/themecleanflex/components/form/template.vue b/ui.apps/src/main/content/jcr_root/apps/themecleanflex/components/form/template.vue
new file mode 100644
index 000000000..79df0f412
--- /dev/null
+++ b/ui.apps/src/main/content/jcr_root/apps/themecleanflex/components/form/template.vue
@@ -0,0 +1,106 @@
+
+
+
+
+
{{failureText}}
+
{{schemaError}}
+
+
+
+
+
+
+
+
diff --git a/ui.apps/src/main/content/jcr_root/apps/themecleanflex/components/media/template.vue b/ui.apps/src/main/content/jcr_root/apps/themecleanflex/components/media/template.vue
index df3f8de27..9308ca715 100644
--- a/ui.apps/src/main/content/jcr_root/apps/themecleanflex/components/media/template.vue
+++ b/ui.apps/src/main/content/jcr_root/apps/themecleanflex/components/media/template.vue
@@ -4,7 +4,8 @@
-
+
@@ -31,6 +32,10 @@
if (mediatype === 'image' && (imagesrc == null || imagesrc == "")) return true;
if (mediatype === 'video' && (videosrc == null || videosrc == "")) return true;
return false
+ },
+ placeholderSrc() {
+ const size = this.model.imagesrcSize
+ return size ? `data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${size.width} ${size.height}"%3E%3C/svg%3E` : null
}
}
}
diff --git a/ui.apps/src/main/content/jcr_root/apps/themecleanflex/components/page/renderer.html b/ui.apps/src/main/content/jcr_root/apps/themecleanflex/components/page/renderer.html
index 769f5acbc..000567364 100644
--- a/ui.apps/src/main/content/jcr_root/apps/themecleanflex/components/page/renderer.html
+++ b/ui.apps/src/main/content/jcr_root/apps/themecleanflex/components/page/renderer.html
@@ -31,6 +31,10 @@
// }
// }
+ if(window.VueFormGenerator) {
+ var VueFormGenerator = window.VueFormGenerator
+ Vue.component('vue-form-generator', VueFormGenerator.component)
+ }
Vue.use(window.VLazyImage.VLazyImagePlugin)
$peregrineApp.loadComponent('pagerendervue-components-placeholder')
$peregrineApp.loadComponent('themecleanflex-components-block')
diff --git a/ui.apps/src/main/content/jcr_root/content/themecleanflex/pages/css/palette.css b/ui.apps/src/main/content/jcr_root/content/themecleanflex/pages/css/palette.css
index 46ec62178..78d49d197 100644
--- a/ui.apps/src/main/content/jcr_root/content/themecleanflex/pages/css/palette.css
+++ b/ui.apps/src/main/content/jcr_root/content/themecleanflex/pages/css/palette.css
@@ -218,3 +218,42 @@
color: var(--btn-primary-color);
background-color: var(--btn-primary-bg);
}
+
+#peregrine-app [class$="-components-form"] input[type="submit"]{
+ color: var(--btn-color) !important;
+ background: var(--btn-bg) !important;
+}
+
+#peregrine-app [class$="-components-form"] input[type="submit"]:focus {
+ color: var(--btn-focus-color) !important;
+ background: var(--btn-focus-bg) !important;
+ box-shadow: 0 0 0 3px var(--btn-focus-border-color) !important;
+ outline: 2px solid transparent !important; /* Windows High Contrast Mode */
+}
+
+#peregrine-app [class$="-components-form"] input[type="submit"]:hover {
+ color: var(--btn-hover-color) !important;
+ background: var(--btn-hover-bg) !important;
+}
+#peregrine-app table thead th,
+#peregrine-app table thead th *,
+#peregrine-app table td.mobile-header,
+#peregrine-app table td.mobile-header * {
+ background: var(--bg-primary);
+ color: var(--text-primary-color);
+ fill: var(--text-primary-color);
+}
+#peregrine-app table.striped tbody tr:nth-of-type(2n+1) td:not(.mobile-header){
+ background: transparent;
+}
+#peregrine-app table.striped tbody tr:nth-of-type(2n) td:not(.mobile-header){
+ background: var(--bg-secondary);
+}
+#peregrine-app [class$="-components-datalist"].theme-dark table.striped tbody tr:nth-of-type(2n) td:not(.mobile-header),
+#peregrine-app [class$="-components-datalist"].theme-dark table.striped tbody tr:nth-of-type(2n) td:not(.mobile-header) *{
+ color: var(--text-secondary-color);
+ fill: var(--text-secondary-color);
+}
+#peregrine-app [class$="-components-datalist"] .action-btn:hover {
+ fill: var(--text-secondary-color);
+}
\ No newline at end of file
diff --git a/ui.apps/src/main/content/jcr_root/content/themecleanflex/pages/css/palettes/dawn.css b/ui.apps/src/main/content/jcr_root/content/themecleanflex/pages/css/palettes/dawn.css
index f0d816201..f69ce54fc 100644
--- a/ui.apps/src/main/content/jcr_root/content/themecleanflex/pages/css/palettes/dawn.css
+++ b/ui.apps/src/main/content/jcr_root/content/themecleanflex/pages/css/palettes/dawn.css
@@ -148,7 +148,39 @@
#peregrine-app [class$='components-quote'] {
--border-primary-color: var(--color-accent-1-700);
}
+
+ #peregrine-app .theme-dark[class$="-components-form"] input,
+ #peregrine-app .theme-dark[class$="-components-form"] textarea,
+ #peregrine-app .theme-dark[class$="-components-form"] .form-control,
+ #peregrine-app .theme-dark[class$="-components-form"] .form-control *{
+ --text-primary-color: rgba(0,0,0,0.87);
+ --text-secondary-color: rgba(0,0,0,0.6);
+ }
+
+#peregrine-app [class$="components-datalist"] table th,
+#peregrine-app [class$="components-datalist"] table th *,
+#peregrine-app [class$="components-datalist"] table td.mobile-header,
+#peregrine-app [class$="components-datalist"] table td.mobile-header * {
+ --bg-primary: var(--color-accent-1-700);
+ --text-primary-color: rgba(255,255,255);
+}
+#peregrine-app .theme-light[class$="components-datalist"] table.striped tbody td,
+#peregrine-app .theme-light[class$="components-datalist"] table.striped tbody td *{
+ --bg-secondary: rgba(255,255,255,0.6);
+}
+#peregrine-app .theme-dark[class$="components-datalist"] table th,
+#peregrine-app .theme-dark[class$="components-datalist"] table th *,
+#peregrine-app .theme-dark[class$="components-datalist"] table td.mobile-header,
+#peregrine-app .theme-dark[class$="components-datalist"] table td.mobile-header * {
+ --bg-primary: #fff;
+ --text-primary-color: rgba(0,0,0,0.87);
+}
+#peregrine-app .theme-dark[class$="components-datalist"] table.striped tbody td,
+#peregrine-app .theme-dark[class$="components-datalist"] table.striped tbody td *{
+ --bg-secondary: #f8f8f8;
+ --text-secondary-color: rgba(0,0,0,0.87);
+}
#peregrine-app .theme-dark[class$="-components-navigation"] a:hover{
color: var(--color-accent-1-700);
- }
\ No newline at end of file
+ }
diff --git a/ui.apps/src/main/content/jcr_root/content/themecleanflex/pages/css/palettes/ocean.css b/ui.apps/src/main/content/jcr_root/content/themecleanflex/pages/css/palettes/ocean.css
index 748880faf..06c7023f8 100644
--- a/ui.apps/src/main/content/jcr_root/content/themecleanflex/pages/css/palettes/ocean.css
+++ b/ui.apps/src/main/content/jcr_root/content/themecleanflex/pages/css/palettes/ocean.css
@@ -133,6 +133,38 @@
--border-primary-color: var(--color-accent-1-700);
}
+#peregrine-app .theme-dark[class$="-components-form"] input,
+#peregrine-app .theme-dark[class$="-components-form"] textarea,
+#peregrine-app .theme-dark[class$="-components-form"] .form-control,
+#peregrine-app .theme-dark[class$="-components-form"] .form-control *{
+ --text-primary-color: rgba(0,0,0,0.87);
+ --text-secondary-color: rgba(0,0,0,0.6);
+}
+
+#peregrine-app [class$="components-datalist"] table th,
+#peregrine-app [class$="components-datalist"] table th *,
+#peregrine-app [class$="components-datalist"] table td.mobile-header,
+#peregrine-app [class$="components-datalist"] table td.mobile-header * {
+ --bg-primary: var(--color-accent-1-700);
+ --text-primary-color: rgba(255,255,255);
+}
+#peregrine-app .theme-light[class$="components-datalist"] table.striped tbody td,
+#peregrine-app .theme-light[class$="components-datalist"] table.striped tbody td *{
+ --bg-secondary: rgba(255,255,255,0.6);
+}
+#peregrine-app .theme-dark[class$="components-datalist"] table th,
+#peregrine-app .theme-dark[class$="components-datalist"] table th *,
+#peregrine-app .theme-dark[class$="components-datalist"] table td.mobile-header,
+#peregrine-app .theme-dark[class$="components-datalist"] table td.mobile-header * {
+ --bg-primary: #fff;
+ --text-primary-color: rgba(0,0,0,0.87);
+}
+#peregrine-app .theme-dark[class$="components-datalist"] table.striped tbody td,
+#peregrine-app .theme-dark[class$="components-datalist"] table.striped tbody td *{
+ --bg-secondary: #e8f2ff;
+ --text-secondary-color: rgba(0,0,0,0.87);
+}
+
#peregrine-app .theme-dark[class$="-components-navigation"] a:hover{
color: var(--color-accent-1-700);
}
\ No newline at end of file
diff --git a/ui.apps/src/main/content/jcr_root/content/themecleanflex/pages/js/formsapp.js b/ui.apps/src/main/content/jcr_root/content/themecleanflex/pages/js/formsapp.js
new file mode 100644
index 000000000..e16f89f76
--- /dev/null
+++ b/ui.apps/src/main/content/jcr_root/content/themecleanflex/pages/js/formsapp.js
@@ -0,0 +1,38 @@
+$formsapp = {
+ save(model, data) {
+ var records = localStorage.getItem(model.endpointurl);
+ if(!records) {
+ records = [];
+ } else {
+ records = JSON.parse(records);
+ }
+ records.push(data);
+ localStorage.setItem(model.endpointurl, JSON.stringify(records, true, 2));
+ window.dispatchEvent(new CustomEvent('datalist-storage-update',{}));
+ window.dispatchEvent(new CustomEvent('form-clear',{}));
+ return true
+ },
+
+ load(path) {
+ var records = localStorage.getItem(path);
+ if(!records) {
+ return [];
+ } else {
+ return JSON.parse(records);
+ }
+ },
+
+ delete(data, active, path) {
+ // data loaded from local storage, find rows and delete them, then reset local storage
+ console.log('deleting rows');
+ let newData = data;
+ for( let i = active.length-1; i >= 0; i--) {
+ // iterate from end and delete active rows as we find them
+ if( active[i] ) {
+ newData.splice(i,1);
+ }
+ }
+ localStorage.setItem(path,JSON.stringify(newData));
+ return newData;
+ }
+}
diff --git a/ui.apps/src/main/content/jcr_root/content/themecleanflex/templates/.content.xml b/ui.apps/src/main/content/jcr_root/content/themecleanflex/templates/.content.xml
index 5b6798665..11c6bf4ee 100644
--- a/ui.apps/src/main/content/jcr_root/content/themecleanflex/templates/.content.xml
+++ b/ui.apps/src/main/content/jcr_root/content/themecleanflex/templates/.content.xml
@@ -8,7 +8,8 @@
jcr:primaryType="per:PageContent"
sling:resourceType="themecleanflex/components/page"
jcr:title="themecleanflex root template"
- siteCSS="[/content/themecleanflex/pages/css/commons.css,/content/themecleanflex/pages/css/palettes/default.css,/content/themecleanflex/pages/css/palette.css,/etc/felibs/themecleanflex.css,/content/themecleanflex/pages/css/custom.css,https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap]"
+ siteJS="[/etc/felibs/admin/dependencies/vfg.js,/content/themecleanflex/pages/js/formsapp.js]"
+ siteCSS="[/etc/felibs/admin/dependencies/vfg.css,/content/themecleanflex/pages/css/commons.css,/content/themecleanflex/pages/css/palettes/default.css,/content/themecleanflex/pages/css/palette.css,/etc/felibs/themecleanflex.css,/content/themecleanflex/pages/css/custom.css,https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap]"
prefetchDNS="[https://www.youtube.com,https://s.ytimg.com,https://www.google.com,https://fonts.gstatic.com,https://www.youtube-nocookie.com]"/>
diff --git a/ui.apps/src/main/content/jcr_root/etc/felibs/themecleanflex/css/build.css b/ui.apps/src/main/content/jcr_root/etc/felibs/themecleanflex/css/build.css
index bcbcd0e6a..3b62b450b 100644
--- a/ui.apps/src/main/content/jcr_root/etc/felibs/themecleanflex/css/build.css
+++ b/ui.apps/src/main/content/jcr_root/etc/felibs/themecleanflex/css/build.css
@@ -467,6 +467,10 @@ button,
cursor: pointer;
}
+table {
+ border-collapse: collapse;
+}
+
h1,
h2,
h3,
@@ -675,6 +679,11 @@ video {
border-radius: 9999px;
}
+.rounded-r {
+ border-top-right-radius: 0.25rem;
+ border-bottom-right-radius: 0.25rem;
+}
+
.border-solid {
border-style: solid;
}
@@ -715,6 +724,10 @@ video {
display: flex;
}
+.table {
+ display: table;
+}
+
.hidden {
display: none;
}
@@ -923,10 +936,18 @@ video {
margin-bottom: var(--spacing-3);
}
+.mt-4 {
+ margin-top: var(--spacing-4);
+}
+
.mr-4 {
margin-right: var(--spacing-4);
}
+.mb-4 {
+ margin-bottom: var(--spacing-4);
+}
+
.mb-6 {
margin-bottom: var(--spacing-6);
}
@@ -971,10 +992,30 @@ video {
overflow-x: auto;
}
+.overflow-y-hidden {
+ overflow-y: hidden;
+}
+
+.overflow-x-scroll {
+ overflow-x: scroll;
+}
+
+.overflow-y-scroll {
+ overflow-y: scroll;
+}
+
.p-0 {
padding: var(--spacing-0);
}
+.p-1 {
+ padding: var(--spacing-1);
+}
+
+.p-2 {
+ padding: var(--spacing-2);
+}
+
.p-3 {
padding: var(--spacing-3);
}
@@ -1160,6 +1201,14 @@ video {
text-decoration: underline;
}
+.align-top {
+ vertical-align: top;
+}
+
+.align-bottom {
+ vertical-align: bottom;
+}
+
.visible {
visibility: visible;
}
@@ -1168,6 +1217,14 @@ video {
visibility: hidden;
}
+.w-24 {
+ width: 24px;
+}
+
+.w-48 {
+ width: 48px;
+}
+
.w-auto {
width: auto;
}
@@ -1324,7 +1381,9 @@ video {
/* Base Overrides */
-html {
+html,
+textarea,
+select {
font-family: var(--font-sans);
font-size: var(--font-size-base);
}
@@ -1730,6 +1789,85 @@ p {
border-radius: 9999px;
}
+/* form */
+
+[class$="components-form"] fieldset{
+ padding: 0;
+ margin: 0;
+}
+
+[class$="components-form"] legend {
+ font-size: 20px;
+}
+
+.vue-form-generator .field-label span {
+ margin-left: 0;
+}
+
+.vue-form-generator .field-checkbox input {
+ margin-right: 5px;
+ margin-left: 1px;
+}
+
+[class$="components-form"] .field-checkbox {
+ display: flex;
+ align-items: center;
+ flex-direction: row-reverse;
+ justify-content: flex-end;
+}
+
+[class$="components-form"] .normal-button input[type="submit"]{
+ width: min-content;
+}
+
+[class$="components-form"] .lg-button input[type="submit"]{
+ width: min-content;
+ padding-top: var(--spacing-4);
+ padding-bottom: var(--spacing-4);
+ padding-left: var(--spacing-5);
+ padding-right: var(--spacing-5);
+ font-size: var(--font-size-lg)
+}
+
+[class$="components-form"] .sm-button input[type="submit"]{
+ width: min-content;
+ padding-top: var(--spacing-2);
+ padding-bottom: var(--spacing-2);
+ padding-left: var(--spacing-2);
+ padding-right: var(--spacing-2);
+ font-size: var(--font-size-sm)
+}
+
+[class$="components-form"] .full-button input[type="submit"]{
+ width: 100%;
+ margin-left: 0;
+ margin-right: 0;
+}
+
+[class$="components-form"] .justify-button-start{
+ align-items: flex-start;
+}
+
+[class$="components-form"] .justify-button-start .field-submit > div{
+ justify-content: flex-start;
+}
+
+[class$="components-form"] .justify-button-center{
+ align-items: center;
+}
+
+[class$="components-form"] .justify-button-center .field-submit > div{
+ justify-content: center;
+}
+
+[class$="components-form"] .justify-button-end{
+ align-items: flex-end;
+}
+
+[class$="components-form"] .justify-button-end .field-submit > div{
+ justify-content: flex-end;
+}
+
/* purgecss end ignore */
@media (min-width: 640px) {
diff --git a/ui.apps/src/main/content/jcr_root/etc/felibs/themecleanflex/styles.css b/ui.apps/src/main/content/jcr_root/etc/felibs/themecleanflex/styles.css
index d4fb44fb0..1d9cd7f7c 100644
--- a/ui.apps/src/main/content/jcr_root/etc/felibs/themecleanflex/styles.css
+++ b/ui.apps/src/main/content/jcr_root/etc/felibs/themecleanflex/styles.css
@@ -8,7 +8,9 @@
/* Base Overrides */
-html {
+html,
+textarea,
+select {
@apply font-sans text-base;
}
@@ -278,7 +280,6 @@ p {
}
}
-
/* header */
[class$="components-header"] a {
@apply text-sm font-medium;
@@ -324,5 +325,60 @@ p {
border-radius: 9999px;
}
+/* form */
+[class$="components-form"] fieldset{
+ padding: 0;
+ margin: 0;
+}
+[class$="components-form"] legend {
+ font-size: 20px;
+}
+.vue-form-generator .field-label span {
+ margin-left: 0;
+}
+.vue-form-generator .field-checkbox input {
+ margin-right: 5px;
+ margin-left: 1px;
+}
+[class$="components-form"] .field-checkbox {
+ display: flex;
+ align-items: center;
+ flex-direction: row-reverse;
+ justify-content: flex-end;
+}
+[class$="components-form"] .normal-button input[type="submit"]{
+ width: min-content;
+}
+[class$="components-form"] .lg-button input[type="submit"]{
+ width: min-content;
+ @apply py-4 px-5 text-lg
+}
+[class$="components-form"] .sm-button input[type="submit"]{
+ width: min-content;
+ @apply py-2 px-2 text-sm
+}
+[class$="components-form"] .full-button input[type="submit"]{
+ width: 100%;
+ margin-left: 0;
+ margin-right: 0;
+}
+[class$="components-form"] .justify-button-start{
+ align-items: flex-start;
+}
+[class$="components-form"] .justify-button-start .field-submit > div{
+ justify-content: flex-start;
+}
+[class$="components-form"] .justify-button-center{
+ align-items: center;
+}
+[class$="components-form"] .justify-button-center .field-submit > div{
+ justify-content: center;
+}
+[class$="components-form"] .justify-button-end{
+ align-items: flex-end;
+}
+[class$="components-form"] .justify-button-end .field-submit > div{
+ justify-content: flex-end;
+}
/* purgecss end ignore */
diff --git a/ui.apps/tailwind.config.js b/ui.apps/tailwind.config.js
index 7974bd391..c0c89c2b2 100644
--- a/ui.apps/tailwind.config.js
+++ b/ui.apps/tailwind.config.js
@@ -156,7 +156,8 @@ module.exports = {
backgroundColor: theme => ({
...theme('colors'),
primary: 'var(--bg-primary)',
- secondary: 'var(--bg-secondary)'
+ secondary: 'var(--bg-secondary)',
+ transparent: 'transparent',
}),
backgroundPosition: {
bottom: 'bottom',
@@ -390,6 +391,8 @@ module.exports = {
'11/12': '91.66667%',
full: '100%',
screen: '100vw',
+ '24': '24px',
+ '48': '48px',
}),
zIndex: {
auto: 'auto',