Created
July 9, 2019 14:28
-
-
Save egorguscha/271be58931fc41da2c6455a606be4bd9 to your computer and use it in GitHub Desktop.
test1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// @jsx el | |
// @jsxFrag 'Fragment' | |
import * as React from 'react' | |
import {catalogs} from './effects/fetch-data' | |
import {createStore, createEvent, createEffect, createApi} from 'effector' | |
import {useStore} from 'effector-react' | |
const root = document.getElementById('root') | |
function el(tag, props, ...children) { | |
if (tag === 'Fragment') { | |
const frag = document.createDocumentFragment(tag) | |
return appendChild(frag, children) | |
} | |
if (typeof tag === 'function') return tag({props: props || {}, children}) | |
const element = document.createElement(tag) | |
if (props) { | |
// console.log(props) | |
for (const key in props) { | |
if (typeof props[key] === 'function') { | |
element.setAttribute(key, props[key]) | |
element.addEventListener('click', props[key]) | |
} else if (props[key] !== false) { | |
element.setAttribute(key, String(props[key])) | |
} | |
} | |
} | |
return appendChild(element, children) | |
} | |
function appendChild(element, children) { | |
if (Array.isArray(children)) { | |
for (const child of children) { | |
appendChild(element, child) | |
} | |
} else if (typeof children === 'string' || typeof children === 'number') { | |
const textNode = document.createTextNode(String(children)) | |
element.appendChild(textNode) | |
} else { | |
element.appendChild(children) | |
} | |
return element | |
} | |
function cssVars(vars) { | |
let style = '' | |
for (const name in vars) { | |
style += `--${name}: ${String(vars[name])};` | |
} | |
return style | |
} | |
function css(tags, ...attrs) { | |
const value = style(tags, ...attrs) | |
const node = document.createElement('style') | |
node.id = 'insertedStyle' | |
node.appendChild(document.createTextNode(value)) | |
const sheet = document.getElementById('insertedStyle') | |
if (sheet) { | |
sheet.disabled = true | |
sheet.parentNode.removeChild(sheet) | |
} | |
document.head.appendChild(node) | |
function style(tags, ...attrs) { | |
if (tags.length === 0) return '' | |
let result = ' ' + tags[0] | |
for (let i = 0; i < attrs.length; i++) { | |
result += attrs[i] | |
result += tags[i + 1] | |
} | |
return result | |
} | |
} | |
css` | |
.project-tree { | |
background: #333; | |
border: none; | |
color: #dedede; | |
font-family: 'Roboto'; | |
width: 400px; | |
margin: 30px auto 0 auto; | |
padding: 25px; | |
} | |
.tree-folder { | |
padding: 0 0 0 var(--offset, 0); | |
user-select: none; | |
position: relative; | |
} | |
.tree-folder:hover { | |
background: rgba(255, 255, 255, 0.1); | |
cursor: pointer; | |
} | |
.tree-item-name { | |
padding: 5px; | |
box-sizing: border-box; | |
} | |
.primary-button { | |
border: none; | |
box-sizing: border-box; | |
padding: 5px 10px; | |
background: #186cde; | |
color: #fff; | |
border-radius: 5px; | |
transition: 0.2s; | |
margin: 0 10px 0 0; | |
} | |
.primary-button:last-child { | |
margin: 0; | |
} | |
.primary-button:hover { | |
background: #4d99ff; | |
cursor: pointer; | |
} | |
.primary-button:active { | |
background: rgba(24, 108, 222, 0.56); | |
} | |
.primary-button:focus { | |
outline: none; | |
} | |
.manage-button-bar { | |
margin: 0 0 15px 0; | |
} | |
.primary-checkbox { | |
position: absolute; | |
z-index: -1000; | |
} | |
.primary-label { | |
box-sizing: border-box; | |
position: absolute; | |
width: 15px; | |
height: 15px; | |
display: block; | |
right: 10px; | |
top: 50%; | |
margin: -8px 0 0 0; | |
border-radius: 50%; | |
border: 2px solid #186cde; | |
} | |
.primary-checkbox:checked + .primary-label { | |
background: #186cde; | |
} | |
.primary-label:hover { | |
cursor: pointer; | |
} | |
.primary-field { | |
border: none; | |
padding: 7px 15px; | |
border: 1px solid #186cde; | |
background: transparent; | |
transition: 0.2s; | |
color: #dedede; | |
border-radius: 5px; | |
} | |
.primary-field:focus { | |
outline: none; | |
} | |
.field-wrapper { | |
margin: 15px 0 0 0; | |
display: flex; | |
justify-content: space-between; | |
} | |
` | |
//stores | |
const outlineManagePanelStore = createStore({ | |
addDirectory: false, | |
addFile: false, | |
}) | |
const outlineManagePanelApi = createApi(outlineManagePanelStore, { | |
addDirectory: state => ({...state, addDirectory: true}), | |
addFile: state => ({...state, addFile: true}), | |
}) | |
// handlers | |
const clickOnFile = () => console.log('click on file') | |
const clickOnDir = () => console.log('click on dir') | |
const handleAddFile = () => console.log('add file') | |
const handleAddDir = () => console.log('add dir') | |
//events | |
// effects | |
// components | |
const ProjectTree = ({children}) => <div class="project-tree">{children}</div> | |
const Folder = ({children, props: {offset, onClick, name}}) => { | |
return ( | |
<div class="tree-folder" style={cssVars({offset})}> | |
<div onClick={onClick} class="tree-item-name"> | |
{name} | |
</div> | |
{children} | |
</div> | |
) | |
} | |
const File = ({children, props: {onClick, name, offset}}) => { | |
return ( | |
<div class="tree-folder" style={cssVars({offset})}> | |
<div onClick={onClick} class="tree-item-name"> | |
{name} | |
</div> | |
{children} | |
</div> | |
) | |
} | |
const ManageButtonBar = ({children}) => ( | |
<div class="manage-button-bar">{children}</div> | |
) | |
const PrimaryButton = ({children, props: {onClick}}) => { | |
return ( | |
<button class="primary-button" onClick={onClick} style={cssVars({})}> | |
{children} | |
</button> | |
) | |
} | |
const PrimaryCheckbox = ({children, props: {id}}) => ( | |
<> | |
<input class="primary-checkbox" type="checkbox" id={id} /> | |
<label class="primary-label" for={id} /> | |
</> | |
) | |
const PrimaryFiled = ({props: {onChange}}) => ( | |
<input class="primary-field" onChange={onChange} /> | |
) | |
const FieldWrapper = ({children}) => <div class="field-wrapper">{children}</div> | |
// building components stage | |
const ManagePanel = ({}) => { | |
const {addDirectory, addFile} = useStore(outlineManagePanelStore) | |
return ( | |
<ManageButtonBar> | |
<PrimaryButton onClick={handleAddFile}>Add file</PrimaryButton> | |
<PrimaryButton onClick={handleAddDir}>Add directory</PrimaryButton> | |
<PrimaryButton onClick={handleAddDir}>Delete</PrimaryButton> | |
<FieldWrapper> | |
<PrimaryFiled /> | |
<PrimaryButton>Add</PrimaryButton> | |
</FieldWrapper> | |
</ManageButtonBar> | |
) | |
} | |
const App = ({props: {folders}}) => ( | |
<ProjectTree> | |
<ManagePanel /> | |
{folders.map(({dir, offset, filesName, id}) => ( | |
<> | |
<Folder offset={`${offset}px`} name={dir} onClick={clickOnDir}> | |
<PrimaryCheckbox id={id} /> | |
</Folder> | |
{filesName | |
? filesName.map(name => ( | |
<File | |
name={name} | |
onClick={clickOnFile} | |
offset={`${offset + 15}px`} | |
/> | |
)) | |
: ''} | |
</> | |
))} | |
</ProjectTree> | |
) | |
catalogs.watch(state => { | |
if (state.length > 0) appendChild(root, <App folders={state} />) | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment