Skip to content

Commit

Permalink
Implement Designer Components
Browse files Browse the repository at this point in the history
  • Loading branch information
s-cork committed Jun 2, 2021
1 parent 5d31e66 commit eb32ce9
Show file tree
Hide file tree
Showing 7 changed files with 522 additions and 256 deletions.
4 changes: 2 additions & 2 deletions .anvil_editor.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ unique_ids:
routing._routing: SDYG54CLQVFHGY7XHB2R44TZR6PXYUKY, utils: E7XISEGXUVZXV24JEVFT4SV64AJED3XJ,
routing._session_expired: 7I5VIVGMNIHYLE3UOMQZULQDDF6XR7UX}
server_modules: {authorisation: Z6AZ64JBAAHAVRYQJ63VZLOU4TESTAUN, server_utils: 4XEM7IGABFRXOMKOT7WB5BYR22LF4QH7}
assets: {loading-spinner.js: GNN5BGLOS3BHSXWTHXXQUT5BPTJQEUXA, standard-page.html: JYT2VG6NOSSLRNZR5GDSLLXUFJ7AZF4J,
theme.css: S5NWY72JOUFUHCDRRQX7DV3C5CKF4TGN}
assets: {designer.js: OEQ3CBH32UWA4O5CYXY5U7IEX32FLYYO, loading-spinner.js: GNN5BGLOS3BHSXWTHXXQUT5BPTJQEUXA,
standard-page.html: JYT2VG6NOSSLRNZR5GDSLLXUFJ7AZF4J, theme.css: S5NWY72JOUFUHCDRRQX7DV3C5CKF4TGN}
10 changes: 2 additions & 8 deletions client_code/MultiSelectDropDown/form_template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,6 @@ container:
role: null, html: "<select class=\"select-picker\" \n multiple \n \
\ data-container=\"body\"\n data-icon-base=\"fa\"\n data-tick-icon=\"\
fa-check\"\n data-show-subtext=\"true\"\n data-selected-text-format=\"\
count > 3\"\n/>\n<script>\nfunction addSelectPicker() {\n $.fn.selectpicker.Constructor.BootstrapVersion\
\ = \"3\";\n $(\".select-picker\").selectpicker();\n}\n$(() => {\n if\
\ (typeof $.fn.selectpicker === \"undefined\") {\n const l = document.createElement(\"\
link\");\n l.href = \"https://cdn.jsdelivr.net/npm/bootstrap-select@1.13.18/dist/css/bootstrap-select.min.css\"\
;\n l.rel = \"stylesheet\";\n document.head.appendChild(l);\n\n\
\ const s = document.createElement(\"script\");\n s.src = \"https://cdn.jsdelivr.net/npm/bootstrap-select@1.13.18/dist/js/bootstrap-select.min.js\"\
;\n document.body.appendChild(s);\n s.onload = addSelectPicker;\n\
\ } else {\n addSelectPicker();\n }\n});\n</script>\n"}
count > 3\"\n/>\n<script type=\"module\">\nimport {DesignerMultiSelectDropDown}\
\ from \"./_/theme/designer.js\";\nDesignerMultiSelectDropDown.init();\n</script>"}
event_bindings: {}
51 changes: 11 additions & 40 deletions client_code/Quill/form_template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,43 +32,14 @@ components: []
container:
type: HtmlTemplate
properties: {tooltip: '', background: '', foreground: '', border: '', visible: true,
role: null, html: "<div class=\"quill-editor\" style=\"min-height:150px;\"></div>\n\
<script>\nfunction updateDesignQuill(container, editor, props) {\n props\
\ ||\n (props = {\n auto_expand: true,\n content:\
\ \"\",\n enabled: true,\n height: 150,\n placeholder:\
\ null,\n readonly: false,\n spacing_above: \"small\"\
,\n spacing_below: \"small\",\n theme: \"snow\",\n \
\ toolbar: true,\n visible: true,\n });\n\n if\
\ (editor.firstElementChild) {\n editor.removeChild(editor.firstElementChild);\
\ // remove the editor and the toolabar\n }\n if (container.firstElementChild\
\ !== editor) {\n container.removeChild(container.firstElementChild);\
\ // remove the toolbar\n }\n const q = new Quill(editor, {\n modules:\
\ { toolbar: props.toolbar || false },\n readOnly: props.readonly,\n\
\ theme: props.theme,\n placeholder: props.placeholder,\n });\n\
\ const stale_spacing = [...container.classList].filter((x) => x.startsWith(\"\
anvil-spacing-\"));\n container.classList.remove(...stale_spacing);\n \
\ container.classList.add(\n \"anvil-spacing-above-\" + props.spacing_above,\n\
\ \"anvil-spacing-below-\" + props.spacing_below,\n );\n container.classList.toggle(\"\
visible-false\", !props.visible);\n let len = props.height;\n len = (\"\
\" + len).match(/[a-zA-Z%]/g) ? len : len + \"px\";\n editor.style.minHeight\
\ = len;\n editor.style.height = props.auto_expand ? len : \"auto\";\n \
\ q.setText(props.content || \"\");\n}\n\n \nfunction addQuill() {\n for\
\ (let editor of document.querySelectorAll(\".quill-editor\")) {\n const\
\ container = editor.parentElement;\n const py = $(container).data(\"\
anvilPyComponent\");\n const props = py._anvil.customPropVals;\n \
\ if (!editor.firstElementChild && props) {\n // we've not been\
\ here before\n const copyProps = { ...props };\n for\
\ (let propName in copyProps) {\n Object.defineProperty(props,\
\ propName, {\n get() {\n return copyProps[propName];\n\
\ },\n set(v) {\n \
\ copyProps[propName] = v;\n updateDesignQuill(container,\
\ editor, copyProps);\n },\n });\n \
\ }\n }\n updateDesignQuill(container, editor, props);\n \
\ }\n}\n\n$(() => {\n if (typeof Quill === \"undefined\") {\n let\
\ l = document.createElement(\"link\");\n l.href = \"//cdn.quilljs.com/1.3.6/quill.snow.css\"\
;\n l.rel = \"stylesheet\";\n document.head.appendChild(l);\n\
\ l = document.createElement(\"link\");\n l.href = \"//cdn.quilljs.com/1.3.6/quill.bubble.css\"\
;\n l.rel = \"stylesheet\";\n document.head.appendChild(l);\n\n\
\ const s = document.createElement(\"script\");\n s.src = \"//cdn.quilljs.com/1.3.6/quill.min.js\"\
;\n document.body.appendChild(s);\n s.onload = addQuill;\n \
\ } else {\n addQuill();\n }\n});\n\n</script>\n"}
role: null, html: '<div class="quill-editor" style="min-height:150px;"></div>

<script type="module">

import {DesignerQuill} from "./_/theme/designer.js";

DesignerQuill.init();

</script>

'}
91 changes: 9 additions & 82 deletions client_code/Slider/form_template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -103,85 +103,12 @@ components: []
container:
type: HtmlTemplate
properties: {tooltip: '', background: '', foreground: '', border: '', visible: true,
role: null, html: "<div class=\"anvil-slider anvil-measure-this\" anvil-slot></div>\n\
\n<style>\n.anvil-container-overflow, .anvil-panel-col {\n overflow: visible;\n\
}\n.anvil-slider-container {\n padding: 10px 0;\n min-height: 50px;\n}\n.anvil-slider-container.has-pips\
\ {\n padding-bottom: 40px;\n}\n.noUi-connect {\n background: var(--primary);\n\
}\n.noUi-horizontal .noUi-handle {\n width: 34px;\n height: 34px;\n \
\ right: -17px;\n top: -10px;\n border-radius: 50%;\n}\n.noUi-handle::before,\
\ .noUi-handle::after {\n content: none\n}\n\n</style>\n\n<script>\nfunction\
\ _parse(val, force_list = false) {\n if (typeof val !== \"string\") {\n\
\ return val;\n }\n val = val.toLowerCase().trim();\n if (!val)\
\ return force_list ? [] : null;\n try {\n return JSON.parse((force_list\
\ || val.includes(\",\")) && val[0] !== \"[\" ? `[${val}]` : val);\n } catch\
\ {\n return force_list ? [] : val;\n }\n}\n\nfunction _get_formatter(formatspec)\
\ {\n const first = formatspec.indexOf(\"{\");\n const last = formatspec.indexOf(\"\
}\");\n const prefix = first === -1 ? \"\" : formatspec.slice(0, first);\n\
\ const suffix = last === -1 ? \"\" : formatspec.slice(last + 1);\n const\
\ type = formatspec[last - 1] === \"%\" ? \"%\" : null;\n\n formatspec =\
\ Sk.ffi.toPy(formatspec);\n const format = formatspec.tp$getattr(Sk.ffi.toPy(\"\
format\"));\n\n const do_to = (f) => {\n f = Sk.ffi.toPy(f);\n \
\ return first === -1 ? Sk.builtin.format(f, formatspec) : format.tp$call([f]);\n\
\ };\n\n try {\n do_to(1.1);\n } catch (e) {\n throw\
\ new Error(e.toString());\n }\n\n return {\n to: (f) => {\n \
\ try {\n return do_to(f);\n } catch {\n\
\ return f;\n }\n },\n from: (s) =>\
\ {\n if (s.startsWith(prefix)) {\n s = s.slice(prefix.length);\n\
\ }\n if (s.endsWith(suffix)) {\n s = s.slice(0,\
\ s.length - suffix.length);\n }\n const has_percent =\
\ type === \"%\" && s.endsWith(\"%\");\n s = s.trim().replace(/[,_]/g,\
\ \"\");\n let f = parseFloat(s);\n if (has_percent) {\n\
\ f = f / 100;\n }\n return f;\n \
\ },\n };\n}\n\nfunction updateDesignSlider(container, slider, _props) {\n\
\ try {\n _props || (_props = { start: [20, 80], connect: true, min:\
\ 0, max: 100, visible: true, enabled: true });\n const props = { ..._props\
\ };\n\n for (let prop of [\"start\", \"connect\", \"margin\", \"padding\"\
, \"limit\", \"pips_values\"]) {\n props[prop] = _parse(props[prop],\
\ prop === \"pips_values\");\n }\n props.range = { min: props.min,\
\ max: props.max };\n props.format = _get_formatter(props.format || \"\
.2f\");\n\n if (props.pips) {\n props.pips = {\n \
\ format: props[\"format\"],\n mode: props[\"pips_mode\"\
],\n values: props[\"pips_values\"],\n density:\
\ props[\"pips_density\"],\n stepped: props[\"pips_stepped\"\
],\n };\n }\n\n container.classList.toggle(\"has-pips\"\
, !!props.pips);\n slider.noUiSlider?.destroy();\n if (slider.firstElementChild)\
\ {\n slider.removeChild(slider.firstElementChild);\n }\n\
\ let color = props.color;\n if (color && color.startsWith(\"\
theme:\")) {\n color = window.anvilThemeColors[color.replace(\"theme:\"\
, \"\")];\n }\n color = color || window.anvilThemeColors[\"Primary\
\ 500\"] || \"#2196F3\";\n container.style.setProperty(\"--primary\"\
, color);\n\n const stale_spacing = [...container.classList].filter((x)\
\ => x.startsWith(\"anvil-spacing-\"));\n container.classList.remove(...stale_spacing);\n\
\ container.classList.add(\n \"anvil-spacing-above-\" + props.spacing_above,\n\
\ \"anvil-spacing-below-\" + props.spacing_below\n );\n \
\ container.classList.toggle(\"visible-false\", !props.visible);\n \
\ props.enabled ? slider.removeAttribute(\"disabled\") : slider.setAttribute(\"\
disabled\", true);\n noUiSlider.create(slider, props);\n } catch (e)\
\ {\n slider.noUiSlider?.destroy();\n if (slider.firstElementChild)\
\ {\n slider.removeChild(slider.firstElementChild);\n }\n\
\ const invalidComponent = $(`<div class='invalid-component'>\n \
\ <i class=\"glyphicon glyphicon-remove\"></i>\n <div class=\"\
err\">${e.message.replaceAll(\"noUiSlider\", \"Slider\")}</div></div>`);\n \
\ slider.appendChild(invalidComponent[0]);\n }\n}\n\nfunction addSlider()\
\ {\n for (let slider of document.querySelectorAll(\".anvil-slider\")) {\n\
\ const container = slider.parentElement;\n if (container.classList.contains(\"\
anvil-slider-container\")) {\n return; // we've already set the property\
\ getters and setters so exit early\n }\n const py = $(container).data(\"\
anvilPyComponent\");\n const props = py._anvil.customPropVals;\n\n \
\ if (!slider.firstElementChild && props) {\n // we've not been\
\ here before\n container.classList.add(\"anvil-slider-container\"\
);\n const copyProps = { ...props };\n for (let propName\
\ in copyProps) {\n Object.defineProperty(props, propName, {\n\
\ get() {\n return copyProps[propName];\n\
\ },\n set(v) {\n \
\ copyProps[propName] = v;\n try {\n \
\ updateDesignSlider(container, slider, copyProps);\n \
\ } catch {}\n return true;\n \
\ },\n });\n }\n }\n\n updateDesignSlider(container,\
\ slider, props);\n }\n}\n\n$(() => {\n if (typeof noUiSlider === \"undefined\"\
) {\n let l = document.createElement(\"link\");\n l.href = \"\
https://cdn.jsdelivr.net/npm/nouislider@15.1.1/dist/nouislider.css\";\n \
\ l.rel = \"stylesheet\";\n document.head.appendChild(l);\n\n \
\ let s = document.createElement(\"script\");\n s.src = \"https://cdn.jsdelivr.net/npm/nouislider@15.1.1/dist/nouislider.js\"\
;\n document.body.appendChild(s);\n s.onload = addSlider;\n \
\ } else {\n addSlider();\n }\n});\n\n</script>"}
role: null, html: '<div class="anvil-slider anvil-measure-this" anvil-slot></div>

<script type="module">

import {DesignerSlider} from "./_/theme/designer.js";

DesignerSlider.init();

</script>'}
65 changes: 9 additions & 56 deletions client_code/Switch/form_template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,59 +32,12 @@ components:
container:
type: HtmlTemplate
properties: {tooltip: '', background: '', foreground: '', border: '', visible: true,
role: switch, html: "<div class=\"anvil-extras-switch\"></div>\n\n<script>\nfunction\
\ _colorToRGB(v) {\n if (v && v.startsWith(\"theme:\")) {\n v = window.anvilThemeColors[v.replace(\"\
theme:\", \"\")];\n }\n v = v || window.anvilThemeColors[\"Primary 500\"\
] || \"#2196F3\";\n const bigint = parseInt(v.slice(1), 16);\n v = [(bigint\
\ >> 16) & 255, (bigint >> 8) & 255, bigint & 255].join(\",\");\n return\
\ v;\n}\n$(() => {\n if (typeof window.anvilSwitchStyle === \"undefined\"\
) {\n const s = document.createElement(\"style\");\n s.innerHTML\
\ = `.switch,.switch *{-webkit-tap-highlight-color:transparent;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.switch\
\ label{cursor:pointer}.switch label input[type=checkbox]{opacity:0;width:0;height:0}.switch\
\ label input[type=checkbox]:checked+.lever{background-color:rgba(var(--color),\
\ .5)}.switch label input[type=checkbox]:checked+.lever:after,.switch label\
\ input[type=checkbox]:checked+.lever:before{left:18px}.switch label input[type=checkbox]:checked+.lever:after{background-color:rgb(var(--color))}.switch\
\ label .lever{content:\"\";display:inline-block;position:relative;width:36px;height:14px;background-color:rgba(0,0,0,0.38);border-radius:15px;margin-right:10px;-webkit-transition:background\
\ 0.3s ease;transition:background 0.3s ease;vertical-align:middle;margin:0 16px}.switch\
\ label .lever:after,.switch label .lever:before{content:\"\";position:absolute;display:inline-block;width:20px;height:20px;border-radius:50%;left:0;top:-3px;-webkit-transition:left\
\ 0.3s ease, background 0.3s ease, -webkit-box-shadow 0.1s ease, -webkit-transform\
\ 0.1s ease;transition:left 0.3s ease, background 0.3s ease, -webkit-box-shadow\
\ 0.1s ease, -webkit-transform 0.1s ease;transition:left 0.3s ease, background\
\ 0.3s ease, box-shadow 0.1s ease, transform 0.1s ease;transition:left 0.3s\
\ ease, background 0.3s ease, box-shadow 0.1s ease, transform 0.1s ease, -webkit-box-shadow\
\ 0.1s ease, -webkit-transform 0.1s ease}.switch label .lever:before{background-color:rgb(var(--color),\
\ 0.15)}.switch label .lever:after{background-color:#F1F1F1;-webkit-box-shadow:0\
\ 3px 1px -2px rgba(0,0,0,0.2),0px 2px 2px 0 rgba(0,0,0,0.14),0px 1px 5px 0\
\ rgba(0,0,0,0.12);box-shadow:0 3px 1px -2px rgba(0,0,0,0.2),0px 2px 2px 0 rgba(0,0,0,0.14),0px\
\ 1px 5px 0 rgba(0,0,0,0.12)}input[type=checkbox]:checked:not(:disabled) ~ .lever:active::before,input[type=checkbox]:checked:not(:disabled).tabbed:focus\
\ ~ .lever::before{-webkit-transform:scale(2.4);transform:scale(2.4);background-color:rgb(var(--color),\
\ 0.15)}input[type=checkbox]:not(:disabled) ~ .lever:active:before,input[type=checkbox]:not(:disabled).tabbed:focus\
\ ~ .lever::before{-webkit-transform:scale(2.4);transform:scale(2.4);background-color:rgba(0,0,0,0.08)}.switch\
\ input[type=checkbox][disabled]+.lever{cursor:default;background-color:rgba(0,0,0,0.12)}.switch\
\ label input[type=checkbox][disabled]+.lever:after,.switch label input[type=checkbox][disabled]:checked+.lever:after{background-color:#949494}`;\n\
\ document.body.appendChild(s);\n window.anvilSwitchStyle = true;\n\
\ }\n for (element of document.querySelectorAll(\".anvil-extras-switch\"\
)) {\n const parent = element.parentElement;\n parent.removeChild(element);\n\
\ parent.style.width = \"100%\";\n const pyComponent = $(parent).data(\"\
anvilPyComponent\");\n const cb = pyComponent._anvil.components[0].component;\n\
\ domNode = cb._anvil.domNode;\n domNode.style.setProperty(\"\
--color\", _colorToRGB());\n domNode.querySelector(\".checkbox\").classList.add(\"\
switch\");\n const span = domNode.querySelector(\"span\");\n span.classList.add(\"\
lever\");\n span.removeAttribute(\"style\");\n const label = domNode.querySelector(\"\
label\");\n const textnode_pre = document.createTextNode(\"\");\n \
\ const textnode_post = document.createTextNode(\"\");\n label.prepend(textnode_pre);\n\
\ label.append(textnode_post);\n label.style.padding = \"7px 0\"\
;\n\n const props = pyComponent._anvil.customPropVals || {};\n \
\ const copyProps = { ...props };\n\n const setProp = (propName, v)\
\ => {\n try {\n cb._anvil.setProp(propName, Sk.ffi.toPy(v));\n\
\ } catch {\n if (propName === \"checked_color\")\
\ {\n cb._anvil.domNode.style.setProperty(\"--color\", _colorToRGB(v));\n\
\ } else if (propName === \"text_pre\") {\n \
\ textnode_pre.textContent = v;\n } else {\n \
\ textnode_post.textContent = v;\n }\n }\n \
\ };\n\n for (let propName in copyProps) {\n setProp(propName,\
\ copyProps[propName]);\n Object.defineProperty(props, propName,\
\ {\n get() {\n return copyProps[propName];\n\
\ },\n set(v) {\n copyProps[propName]\
\ = v;\n setProp(propName, copyProps[propName]);\n \
\ },\n });\n }\n }\n});\n</script>\n"}
role: switch, html: '<div class="anvil-extras-switch"></div>

<script type="module">

import {DesignerSwitch} from "./_/theme/designer.js";

DesignerSwitch.init();

</script>'}
Loading

0 comments on commit eb32ce9

Please sign in to comment.