ywana-core8 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/dist/index.cjs +2 -0
  2. package/dist/index.cjs.map +1 -0
  3. package/dist/index.css +2 -0
  4. package/dist/index.css.map +1 -0
  5. package/dist/index.modern.js +2 -0
  6. package/dist/index.modern.js.map +1 -0
  7. package/dist/index.umd.js +2 -0
  8. package/dist/index.umd.js.map +1 -0
  9. package/package.json +27 -0
  10. package/publish.sh +5 -0
  11. package/src/css/fonts.css +162 -0
  12. package/src/css/html.css +36 -0
  13. package/src/css/theme.css +89 -0
  14. package/src/css/theme_dark.css +85 -0
  15. package/src/css/theme_light.css +87 -0
  16. package/src/domain/CollectionPage.css +34 -0
  17. package/src/domain/CollectionPage.js +346 -0
  18. package/src/domain/ContentEditor.css +174 -0
  19. package/src/domain/ContentEditor.js +425 -0
  20. package/src/domain/ContentForm.js +74 -0
  21. package/src/domain/ContentType.js +187 -0
  22. package/src/domain/CreateContentDialog.js +59 -0
  23. package/src/domain/EditContentDialog.js +50 -0
  24. package/src/domain/TablePage.css +29 -0
  25. package/src/domain/TablePage.js +395 -0
  26. package/src/domain/index.js +5 -0
  27. package/src/fonts/Assistant-Bold.ttf +0 -0
  28. package/src/fonts/Assistant-ExtraBold.ttf +0 -0
  29. package/src/fonts/Assistant-ExtraLight.ttf +0 -0
  30. package/src/fonts/Assistant-Light.ttf +0 -0
  31. package/src/fonts/Assistant-Medium.ttf +0 -0
  32. package/src/fonts/Assistant-Regular.ttf +0 -0
  33. package/src/fonts/Assistant-SemiBold.ttf +0 -0
  34. package/src/fonts/Assistant-VariableFont_wght.ttf +0 -0
  35. package/src/html/button.css +79 -0
  36. package/src/html/button.js +26 -0
  37. package/src/html/checkbox.css +51 -0
  38. package/src/html/checkbox.js +33 -0
  39. package/src/html/chip.css +63 -0
  40. package/src/html/chip.js +39 -0
  41. package/src/html/form.css +17 -0
  42. package/src/html/form.js +80 -0
  43. package/src/html/header.css +64 -0
  44. package/src/html/header.js +30 -0
  45. package/src/html/icon.css +53 -0
  46. package/src/html/icon.js +21 -0
  47. package/src/html/index.js +18 -0
  48. package/src/html/list.css +72 -0
  49. package/src/html/list.js +78 -0
  50. package/src/html/menu.css +76 -0
  51. package/src/html/menu.js +80 -0
  52. package/src/html/progress.css +20 -0
  53. package/src/html/progress.js +27 -0
  54. package/src/html/property.css +18 -0
  55. package/src/html/property.js +16 -0
  56. package/src/html/radio.css +50 -0
  57. package/src/html/radio.js +25 -0
  58. package/src/html/section.css +6 -0
  59. package/src/html/section.js +31 -0
  60. package/src/html/tab.css +45 -0
  61. package/src/html/tab.js +68 -0
  62. package/src/html/table.css +56 -0
  63. package/src/html/table.js +186 -0
  64. package/src/html/text.js +20 -0
  65. package/src/html/textfield-outlined.css +52 -0
  66. package/src/html/textfield.css +130 -0
  67. package/src/html/textfield.js +99 -0
  68. package/src/html/tokenfield.css +51 -0
  69. package/src/html/tokenfield.js +74 -0
  70. package/src/html/tree.css +63 -0
  71. package/src/html/tree.js +49 -0
  72. package/src/http/client.js +62 -0
  73. package/src/http/index.js +2 -0
  74. package/src/http/session.js +39 -0
  75. package/src/index.js +9 -0
  76. package/src/site/details.css +58 -0
  77. package/src/site/dialog.css +63 -0
  78. package/src/site/dialog.js +43 -0
  79. package/src/site/index.js +3 -0
  80. package/src/site/layouts.css +27 -0
  81. package/src/site/page.css +44 -0
  82. package/src/site/page.js +36 -0
  83. package/src/site/site.css +85 -0
  84. package/src/site/site.js +234 -0
  85. package/src/site/siteContext.js +4 -0
  86. package/src/site/workspace.js +57 -0
  87. package/src/upload/UploadArea.js +64 -0
  88. package/src/upload/UploadDialog.js +41 -0
  89. package/src/upload/UploadFile.js +31 -0
  90. package/src/upload/index.js +1 -0
  91. package/src/upload/uploader.css +57 -0
  92. package/src/upload/uploader.js +69 -0
  93. package/src/widgets/index.js +4 -0
  94. package/src/widgets/kanban/Kanban.css +80 -0
  95. package/src/widgets/kanban/Kanban.js +65 -0
  96. package/src/widgets/login/LoginBox.css +89 -0
  97. package/src/widgets/login/LoginBox.js +66 -0
  98. package/src/widgets/login/ResetPasswordBox.css +50 -0
  99. package/src/widgets/login/ResetPasswordBox.js +56 -0
  100. package/src/widgets/viewer/Viewer.css +87 -0
  101. package/src/widgets/viewer/Viewer.js +47 -0
@@ -0,0 +1,63 @@
1
+ .overlay {
2
+ opacity: 0.5;
3
+ position: absolute;
4
+ top: 0;
5
+ right: 0;
6
+ bottom: 0;
7
+ left: 0;
8
+ display: flex;
9
+ align-items: center;
10
+ justify-content: center;
11
+ background: rgba(77, 77, 77, 0.7);
12
+ z-index: 100;
13
+ }
14
+
15
+ .dialog {
16
+ border-radius: 4px;
17
+ position: absolute;
18
+ top: 0;
19
+ right: 0;
20
+ bottom: 0;
21
+ left: 0;
22
+ z-index: 110;
23
+ display: flex;
24
+ align-items: center;
25
+ justify-content: center;
26
+ }
27
+
28
+ .dialog-panel {
29
+ min-width: 500px;
30
+ max-width: 90%;
31
+ top: 0;
32
+ right: 0;
33
+ bottom: 0;
34
+ left: 0;
35
+ background: var(--paper-color, #fff);
36
+ padding: 0;
37
+ display: flex;
38
+ flex-direction: column;
39
+ border-radius: 5px;
40
+ box-shadow: var(--shadow1);
41
+ overflow: auto;
42
+ }
43
+
44
+ .dialog-panel > header {
45
+ font-size: 1rem;
46
+ font-weight: 600;
47
+ padding: 1rem;
48
+ }
49
+
50
+ .dialog-panel > main {
51
+ flex: 1;
52
+ padding: 1rem;
53
+ }
54
+
55
+ .dialog-panel > footer {
56
+ padding: 1rem;
57
+ display: flex;
58
+ justify-content: flex-end;
59
+ }
60
+
61
+ .dialog-panel > footer button {
62
+ min-width: 5rem;
63
+ }
@@ -0,0 +1,43 @@
1
+ import { Fragment, useContext } from 'react'
2
+ import { SiteContext } from './siteContext'
3
+ import { MenuIcon, Text } from '../html'
4
+ import './dialog.css'
5
+
6
+ /**
7
+ * Dialog
8
+ *
9
+ * <Dialog title={title} open={true} onAction={onAction} actions={actions}>
10
+ */
11
+ export const Dialog = (props) => {
12
+ const site = useContext(SiteContext)
13
+ const { icon, title = "Dialog", children, onAction, actions } = props
14
+
15
+ function close() {
16
+ site.closeDialog()
17
+ }
18
+
19
+ function prevent(e) {
20
+ e.preventDefault()
21
+ e.stopPropagation()
22
+ }
23
+
24
+ return (
25
+ <Fragment>
26
+ <div className="overlay" />
27
+ <div className="dialog" onClick={close}>
28
+ <div className="dialog-panel" onClick={prevent}>
29
+ <header>
30
+ {icon ? <MenuIcon icon={icon} /> : null}
31
+ <Text>{title}</Text>
32
+ </header>
33
+ <main>
34
+ {children}
35
+ </main>
36
+ <footer>
37
+ {actions}
38
+ </footer>
39
+ </div>
40
+ </div>
41
+ </Fragment>
42
+ )
43
+ }
@@ -0,0 +1,3 @@
1
+ export * from './site'
2
+ export * from './page'
3
+ export * from './dialog'
@@ -0,0 +1,27 @@
1
+ :root {
2
+ --timeout: 800ms;
3
+ }
4
+
5
+ .workspace {
6
+ display: grid;
7
+ grid-template-areas: "header header header"
8
+ "menu nav nav"
9
+ "menu main aside"
10
+ "menu detail aside"
11
+ "footer footer footer";
12
+ grid-template-columns: auto 1fr auto;
13
+ grid-template-rows: auto auto 1fr auto auto;
14
+ }
15
+
16
+ .workspace>nav {
17
+ min-height: 3rem;
18
+ }
19
+
20
+ .overall {
21
+ position: absolute;
22
+ top:0;
23
+ bottom: 0;
24
+ left:0;
25
+ right: 0;
26
+ background-color: var(--background-color);
27
+ }
@@ -0,0 +1,44 @@
1
+ .page6 {
2
+ height: 100%;
3
+ color: var(--text-color);
4
+ }
5
+
6
+ .page6>menu {
7
+ padding: 0px;
8
+ margin: 0px;
9
+ grid-area: menu;
10
+ width: var(--page-menu-width);
11
+ color: var(--page-menu-color);
12
+ background-color: var(--page-menu-bgcolor);
13
+ border-right: solid 1px var(--divider-color);
14
+ }
15
+
16
+ .page6>header {
17
+ grid-area: header;
18
+ height: var(--page-header-height);
19
+ color: var(--page-header-color);
20
+ background-color: var(--page-header-bgcolor);
21
+ border-bottom: solid 1px var(--divider-color);
22
+ }
23
+
24
+ .page6>nav {
25
+ grid-area: nav;
26
+ height: var(--page-nav-height);
27
+ }
28
+
29
+ .page6>main {
30
+ grid-area: main;
31
+ overflow: hidden;
32
+ }
33
+
34
+ .page6>aside {
35
+ grid-area: aside;
36
+ width: var(--page-aside-width);
37
+ color: var(--page-aside-color);
38
+ background-color: var(--page-aside-bgcolor);
39
+ }
40
+
41
+ .page6>footer {
42
+ grid-area: footer;
43
+ min-height: var(--page-footer-height);
44
+ }
@@ -0,0 +1,36 @@
1
+ import React, { useState, useEffect } from 'react'
2
+ import './page.css'
3
+ import './layouts.css'
4
+
5
+ /**
6
+ * Page Context
7
+ */
8
+ export const PageContext = React.createContext({})
9
+
10
+ /**
11
+ * Page Provider
12
+ */
13
+ export const PageProvider = ({ context = {}, children }) => {
14
+
15
+ const [pageCtx, setPageCtx] = useState(context)
16
+
17
+ return (
18
+ <PageContext.Provider value={[pageCtx, setPageCtx]}>
19
+ {children}
20
+ </PageContext.Provider>
21
+ )
22
+ }
23
+
24
+ /**
25
+ * Page
26
+ */
27
+ export const Page = (props) => {
28
+ const { children, layout = "simple", context = {} } = props
29
+ return (
30
+ <PageProvider context={context}>
31
+ <article className={`page6 ${layout}`}>
32
+ {children}
33
+ </article>
34
+ </PageProvider>
35
+ )
36
+ }
@@ -0,0 +1,85 @@
1
+
2
+ .site6 {
3
+ width: 100vw;
4
+ height: 100vh;
5
+ display: grid;
6
+ grid-template-columns: auto 1fr auto;
7
+ grid-template-rows: var(--site-header-height) 1fr auto;
8
+ grid-template-areas: "header nav nav" "menu main aside" "footer footer footer";
9
+ background-color: var(--background-color);
10
+ }
11
+
12
+ .site6>header {
13
+ grid-area: header;
14
+ color: var(--site-header-color);
15
+ background-color: var(--site-header-bgcolor);
16
+ display: flex;
17
+ align-items: center;
18
+ width: var(--site-menu-width);
19
+ }
20
+
21
+ .site6>nav {
22
+ grid-area: nav;
23
+ color: var(--site-nav-color);
24
+ background-color: var(--site-nav-bgcolor);
25
+ display: flex;
26
+ justify-content: flex-end;
27
+ align-items: center;
28
+ padding-right: 1rem;
29
+ }
30
+
31
+ .site6>nav>header {
32
+ flex: 1;
33
+ }
34
+
35
+ .site6>menu {
36
+ grid-area: menu;
37
+ margin: 0;
38
+ border-right: solid 1px var(--divider-color);
39
+ padding: .2rem;
40
+ color: var(--site-menu-color);
41
+ background-color: var(--site-menu-bgcolor);
42
+ display: flex;
43
+ flex-direction: column;
44
+ overflow: hidden;
45
+ width: var(--site-menu-width);
46
+ }
47
+
48
+ .site6>menu>main {
49
+ flex: 1;
50
+ overflow-x: hidden;
51
+ overflow-y: auto;
52
+ display: flex;
53
+ flex-direction: column;
54
+ align-items: center;
55
+ }
56
+
57
+ .site6>main {
58
+ grid-area: main;
59
+ overflow: hidden;
60
+ }
61
+
62
+ .site6>aside {
63
+ grid-area: aside;
64
+ color: var(--site-aside-color);
65
+ background-color: var(--site-aside-bgcolor);
66
+ }
67
+
68
+ .site6>footer {
69
+ grid-area: footer;
70
+ min-height: 20rem;
71
+ background-color: rgb(222, 222, 222);
72
+ color: #FFF;
73
+ }
74
+
75
+ .site6>.site-preview {
76
+ position: absolute;
77
+ z-index: 10;
78
+ width: 100vw;
79
+ height: 100vh;
80
+ background-color: rgba(0, 0, 0, 0.32);
81
+ display: flex;
82
+ flex-direction: column;
83
+ align-items: center;
84
+ justify-content: center;
85
+ }
@@ -0,0 +1,234 @@
1
+ import React, { Children, Fragment, useState, useContext, useEffect } from 'react'
2
+ import { Icon } from '../html/icon'
3
+ import { Tabs, Tab } from '../html/tab'
4
+ import { Header } from '../html/header'
5
+ import { Page } from './page'
6
+ import './site.css'
7
+ import { SiteContext } from './siteContext'
8
+
9
+
10
+
11
+ /**
12
+ * Site Provider
13
+ */
14
+ export const SiteProvider = ({ children, siteLang, siteDictionary, showConsole }) => {
15
+
16
+ const [lang, setLang] = useState(siteLang)
17
+ const [dictionary, setDictionary] = useState(siteDictionary)
18
+ const [sideNav, setSideNav] = useState('max')
19
+ const [showNav, setShowNav] = useState(false)
20
+ const [info, setInfo] = useState(null)
21
+ const [console, setConsole] = useState(false)
22
+ const [page, setPage] = useState()
23
+ const [dialog, setDialog] = useState()
24
+ const [preview, setPreview] = useState()
25
+ const [breadcrumb, setBreadcrumb] = useState()
26
+ const [focused, setFocused] = useState()
27
+
28
+ const value = {
29
+
30
+ lang,
31
+ setLang,
32
+
33
+ dictionary,
34
+ setDictionary,
35
+
36
+ focused,
37
+ changeFocus: (next) => {
38
+ if (focused) focused.lose()
39
+ setFocused(next)
40
+ },
41
+
42
+ sideNav,
43
+ setSideNav,
44
+
45
+ showNav,
46
+ setShowNav,
47
+
48
+ info,
49
+ openInfo: (info) => { setInfo(info) },
50
+ closeInfo: () => { setInfo(null) },
51
+
52
+ console,
53
+ toggleConsole: () => { setConsole(!console) },
54
+
55
+ breadcrumb,
56
+ setBreadcrumb,
57
+
58
+ page,
59
+ goto: (id) => { setPage(id) },
60
+
61
+ dialog,
62
+ openDialog: (dialog) => { setDialog(dialog) },
63
+ closeDialog: () => { setDialog(null) },
64
+
65
+ preview,
66
+ openPreview: (preview) => { setPreview(preview) },
67
+ closePreview: () => { setPreview(null) }
68
+
69
+ }
70
+
71
+ return (
72
+ <SiteContext.Provider value={value}>
73
+ {children}
74
+ </SiteContext.Provider>
75
+ )
76
+ }
77
+
78
+ /**
79
+ * Site
80
+ */
81
+ export const Site = ({ icon, logo, title, toolbar, children, init, min, lang, dictionary }) => {
82
+ return (
83
+ <SiteProvider siteLang={lang} siteDictionary={dictionary}>
84
+ <div className="site6">
85
+ <SiteHeader icon={icon} />
86
+ <SiteToolBar >{toolbar}</SiteToolBar>
87
+ <SiteMenu logo={logo} title={title} min={min} >{children}</SiteMenu>
88
+ <SitePage init={init}>
89
+ {children}
90
+ <Page id="EMPTY">EMPTY</Page>
91
+ </SitePage>
92
+ <SiteAside />
93
+ <SiteConsole />
94
+ <SiteDialog />
95
+ <SitePreview />
96
+ </div>
97
+ </SiteProvider>
98
+ )
99
+ }
100
+
101
+ /**
102
+ * Site Header
103
+ */
104
+ const SiteHeader = (props) => {
105
+ const { icon = "equalizer", title } = props
106
+ return (
107
+ <Header icon={icon} title={title} />
108
+ )
109
+ }
110
+ /**
111
+ * Site ToolBar
112
+ */
113
+ const SiteToolBar = ({ children }) => {
114
+ const context = useContext(SiteContext)
115
+ const { breadcrumb } = context
116
+ return (
117
+ <nav>
118
+ {children}
119
+ </nav>
120
+ )
121
+ }
122
+
123
+ /**
124
+ * Site Aside
125
+ */
126
+ const SiteAside = () => {
127
+ const context = useContext(SiteContext)
128
+ return context.info ? (
129
+ <aside>
130
+ {context.info}
131
+ </aside>
132
+ ) : ''
133
+ }
134
+
135
+ /**
136
+ * SiteMenu
137
+ */
138
+ const SiteMenu = ({ logo, title, children, min }) => {
139
+
140
+ const context = useContext(SiteContext)
141
+ const { sideNav, showNav } = context
142
+ const toggleIcon = sideNav === 'max' ? 'chevron_left' : 'chevron_right'
143
+
144
+ useEffect(() => {
145
+ if (min) context.setSideNav('min')
146
+ }, [])
147
+
148
+ const goto = (id) => {
149
+ context.setShowNav(false)
150
+ context.goto(id)
151
+ }
152
+ const sections = children ?
153
+ Children.toArray(children).reduce((sections, page) => {
154
+ const section = page.props ? page.props.section : '...'
155
+ if (!sections[section]) sections[section] = []
156
+ const { id, icon, title } = page.props
157
+ if (title) sections[section].push({ id, icon, title })
158
+ return sections
159
+ }, {}) : {}
160
+
161
+ return (
162
+ <menu className={`min ${showNav ? 'show' : ''}`}>
163
+ <main >
164
+ {Object.keys(sections).map(title => (
165
+ <Fragment key={title}>
166
+ {sections[title].map(({ id, icon = 'info', title }) => {
167
+ return (<Icon key={id} icon={icon} clickable checked={id === context.page} action={() => goto(id)} />)
168
+ })}
169
+ <div className="section-divider" ></div>
170
+ </Fragment>
171
+ ))}
172
+ </main>
173
+ </menu>
174
+ )
175
+ }
176
+
177
+ /**
178
+ * SitePage
179
+ */
180
+ const SitePage = ({ children, init }) => {
181
+ const context = useContext(SiteContext)
182
+ const { page } = context
183
+ useEffect(() => {
184
+ if (init) {
185
+ context.goto(init)
186
+ } else {
187
+ context.goto("EMPTY")
188
+ }
189
+ }, [])
190
+ return (
191
+ <main>
192
+ {React.Children.toArray(children).filter(child => child.props ? child.props.id === page : false)}
193
+ </main>
194
+ )
195
+ }
196
+
197
+ /**
198
+ * Site Dialog
199
+ */
200
+ const SiteDialog = () => {
201
+ const context = useContext(SiteContext)
202
+ return context.dialog ? context.dialog : ''
203
+ }
204
+
205
+ /**
206
+ * Site Preview
207
+ */
208
+ const SitePreview = () => {
209
+ const context = useContext(SiteContext)
210
+ return context.preview ? (
211
+ <div className="site-preview" >
212
+ {context.preview}
213
+ </div>
214
+ ) : ''
215
+ }
216
+
217
+ /**
218
+ * Site Console
219
+ */
220
+ const SiteConsole = () => {
221
+ const context = useContext(SiteContext)
222
+ return context.console ? (
223
+ <footer className="site-console" >
224
+ <Header>
225
+ <Tabs>
226
+ <Tab label="Console" />
227
+ </Tabs>
228
+ </Header>
229
+ <main>
230
+
231
+ </main>
232
+ </footer>
233
+ ) : ''
234
+ }
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Site Context
3
+ */
4
+ export const SiteContext = React.createContext({})
@@ -0,0 +1,57 @@
1
+ import React, { useState } from 'react'
2
+ import { Button } from '../src/widgets'
3
+ import { TransitionGroup, CSSTransition } from 'react-transition-group'
4
+
5
+ /**
6
+ * Workspace Page Layout
7
+ */
8
+ // TODO: WIP
9
+ export const Workspace = () => {
10
+
11
+ const [active, setActive] = useState(1)
12
+ const [effect, setEffect] = useState('shift')
13
+
14
+ function changeActive(next) {
15
+ const nextEffect = next > active ? 'shift' : 'unshift'
16
+ setEffect(nextEffect)
17
+ setActive(next)
18
+ }
19
+
20
+ function canRender(area) {
21
+ const desktop = window.matchMedia('(min-width: 416px)').matches
22
+ return desktop ? true : active === area
23
+ }
24
+
25
+ return (
26
+ <TransitionGroup component={null}>
27
+ {canRender(1) ? (
28
+ <CSSTransition timeout={1500} classNames={effect} key='menu'>
29
+ <menu>
30
+ <span>menu</span>
31
+ <Button label=">>>" action={() => changeActive(2)} />
32
+ </menu>
33
+ </CSSTransition>
34
+ ) : null}
35
+ {canRender('header') ? <header>Title</header> : null}
36
+ {canRender('nav') ? <nav>Nav Toolbar</nav> : null}
37
+ {canRender(2) ? (
38
+ <CSSTransition timeout={3500} classNames={effect} key='main'>
39
+ <main>
40
+ <Button label="<<<" action={() => changeActive(1)} />
41
+ <span>Content</span>
42
+ <Button label=">>>" action={() => changeActive(3)} />
43
+ </main>
44
+ </CSSTransition>
45
+ ) : null}
46
+ {canRender(3) ? (
47
+ <CSSTransition timeout={3500} classNames={effect} key='aside'>
48
+ <aside>
49
+ <Button label="<<<" action={() => changeActive(2)} />
50
+ <span>aside</span>
51
+ </aside>
52
+ </CSSTransition>
53
+ ) : null}
54
+ {canRender('footer') ? <footer>Footer</footer> : null}
55
+ </TransitionGroup>
56
+ )
57
+ }
@@ -0,0 +1,64 @@
1
+ import React, { useState, useEffect, useRef } from 'react'
2
+ import { CircularProgress } from 'rmwc'
3
+ import { Icon, Text } from 'ywana-core7'
4
+ import '@rmwc/circular-progress/styles';
5
+
6
+ /**
7
+ * Component
8
+ */
9
+ export const UploadArea = (props) => {
10
+
11
+ const STATES = { 'IDLE': 0, 'RUNNING': 1, 'SUCCESS': 2, 'ERROR': 3 }
12
+
13
+ const areaElement = useRef()
14
+ const [drag, setDrag] = useState(false)
15
+
16
+ useEffect(() => {
17
+ const { resumable } = props
18
+ if (resumable && areaElement) resumable.assignDrop(areaElement.current)
19
+ }, [])
20
+
21
+ const onDragOver = () => {
22
+ setDrag(true)
23
+ }
24
+
25
+ const onDragLeave = () => {
26
+ setDrag(false)
27
+ }
28
+
29
+ const { state = STATES.IDLE, label = 'Add file or drop file here...', error } = props
30
+ const dragging = drag === true ? 'drag-over' : ''
31
+
32
+ return (
33
+ <div className={`upload-area6 ${dragging}`}
34
+ onDragOver={onDragOver}
35
+ onDragLeave={onDragLeave}
36
+ ref={areaElement}
37
+ >
38
+ {state === STATES.IDLE ? <UploadIcon resumable={props.resumable} /> : ''}
39
+ {state === STATES.IDLE ? <label>{label}</label> : ''}
40
+ {state === STATES.RUNNING ? <CircularProgress size="xlarge" /> : ''}
41
+ {state === STATES.SUCCESS ? <Icon icon="done_all" /> : ''}
42
+ {state === STATES.ERROR ? <Text use="body1">{error}</Text> : ''}
43
+ {props.children}
44
+ </div>
45
+ )
46
+ }
47
+
48
+ /**
49
+ * Component
50
+ */
51
+ const UploadIcon = ({ resumable }) => {
52
+
53
+ const iconElement = useRef()
54
+
55
+ useEffect(() => {
56
+ if (resumable && iconElement) resumable.assignBrowse(iconElement.current)
57
+ }, [])
58
+
59
+ return (
60
+ <div className="upload-icon" ref={iconElement}>
61
+ <Icon icon="folder_open" clickable/>
62
+ </div>
63
+ )
64
+ }