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,52 @@
1
+ .textfield-outlined {
2
+ flex: 1;
3
+ position: relative;
4
+ padding-top: 1.5rem;
5
+ border-radius: 5px;
6
+ display: flex;
7
+ max-height: 3.5rem;
8
+ min-height: 3.5rem;
9
+ }
10
+
11
+ .textfield-outlined.no-label {
12
+ padding-top: .5rem;
13
+ margin-bottom: .5rem;
14
+ }
15
+
16
+ .textfield-outlined > input {
17
+ flex: 1;
18
+ padding: 10px 10px 10px 0.5rem;
19
+ display: block;
20
+ border: none;
21
+ border: 1px solid var(--divider-color);
22
+ overflow: hidden;
23
+ }
24
+
25
+ .textfield-outlined > input:focus {
26
+ outline: none;
27
+ }
28
+
29
+ .textfield-outlined > label {
30
+ color: var(--primary-color);
31
+ font-size: 1rem;
32
+ font-weight: normal;
33
+ position: absolute;
34
+ pointer-events: none;
35
+ left: 0.4rem;
36
+ top: 2rem;
37
+ transition: 0.2s ease all;
38
+ -moz-transition: 0.2s ease all;
39
+ -webkit-transition: 0.2s ease all;
40
+ }
41
+
42
+ /* active state */
43
+ .textfield-outlined > input:focus ~ label,
44
+ .textfield-outlined > input:valid ~ label {
45
+ top: 0.3rem;
46
+ font-size: .9rem;
47
+ color: var(--primary-color);
48
+ }
49
+
50
+ .textfield-outlined > .bar {
51
+ display: none;
52
+ }
@@ -0,0 +1,130 @@
1
+ .textfield {
2
+ flex: 1;
3
+ position: relative;
4
+ padding-top: 1.5rem;
5
+ overflow: hidden;
6
+ display: flex;
7
+ max-height: 3.5rem;
8
+ min-height: 3.5;
9
+ }
10
+
11
+ .textfield.no-label {
12
+ padding-top: .5rem;
13
+ padding-bottom: .5rem;
14
+ }
15
+
16
+ .textfield > input {
17
+ flex: 1;
18
+ padding: 10px 10px 10px .5rem;
19
+ display: block;
20
+ border: none;
21
+ border-bottom: 1px solid var(--divider-color);
22
+ overflow: hidden;
23
+ font-size: 1rem;
24
+ }
25
+
26
+ .textfield > input:focus {
27
+ outline: none;
28
+ }
29
+
30
+ .textfield > label {
31
+ color: var(--primary-color);
32
+ font-size: .9rem;
33
+ font-weight: normal;
34
+ position: absolute;
35
+ pointer-events: none;
36
+ left: .4rem;
37
+ top: 2rem;
38
+ transition: 0.2s ease all;
39
+ -moz-transition: 0.2s ease all;
40
+ -webkit-transition: 0.2s ease all;
41
+ }
42
+
43
+ input:read-only {
44
+ background-color: rgba(200,200,200,.1);
45
+ border: 0px !important;
46
+ }
47
+
48
+ /* active state */
49
+ input:read-only ~ label,
50
+ .textfield > input:focus ~ label,
51
+ .textfield > input:valid ~ label {
52
+ top: .3rem;
53
+ font-size: .8rem;
54
+ color: var(--primary-color);
55
+ }
56
+
57
+ .textfield > .bar {
58
+ position: relative;
59
+ display: block;
60
+ }
61
+
62
+ .textfield > .bar:before,
63
+ .textfield > .bar:after {
64
+ content: "";
65
+ height: 2px;
66
+ width: 0;
67
+ bottom: 1px;
68
+ position: absolute;
69
+ background: #5264ae;
70
+ transition: 0.2s ease all;
71
+ -moz-transition: 0.2s ease all;
72
+ -webkit-transition: 0.2s ease all;
73
+ }
74
+
75
+ .textfield > .bar:before {
76
+ left: 50%;
77
+ }
78
+
79
+ .textfield > .bar:after {
80
+ right: 50%;
81
+ }
82
+
83
+ /* active state */
84
+ .textfield > input:focus ~ .bar:before,
85
+ .textfield > input:focus ~ .bar:after {
86
+ width: 50%;
87
+ }
88
+
89
+ .dropdown {
90
+ position: relative;
91
+ }
92
+
93
+ .dropdown>.icon {
94
+ position: absolute;
95
+ top: 1.7rem;
96
+ right: .2rem;
97
+ }
98
+
99
+ .dropdown>menu {
100
+ z-index: 2;
101
+ position: absolute;
102
+ top: 3.8rem;
103
+ left: 0px;
104
+ right: 0px;
105
+ margin: 0;
106
+ border: solid 1px var(--divider-color);
107
+ background-color: var(--paper-color);
108
+ padding: 0;
109
+ max-height: 20rem;
110
+ overflow: auto;
111
+ }
112
+
113
+ .dropdown>menu ul {
114
+ list-style: none;
115
+ margin: 0;
116
+ padding: .5rem 0;
117
+ cursor: pointer;
118
+ }
119
+
120
+ .dropdown>menu li {
121
+ min-height: 2rem;
122
+ padding: 0 .5rem;
123
+ display: flex;
124
+ align-items: center;
125
+ font-size: .9rem;
126
+ }
127
+
128
+ .dropdown>menu li:hover {
129
+ background-color: var(--primary-color-lighter);
130
+ }
@@ -0,0 +1,99 @@
1
+ import React, { useContext, useEffect, useState } from 'react'
2
+ import { SiteContext } from '../site/siteContext'
3
+ import { Icon } from './icon'
4
+ import { Text } from './text'
5
+ import './textfield-outlined.css'
6
+ import './textfield.css'
7
+
8
+ /**
9
+ * Text Field
10
+ */
11
+ export const TextField = (props) => {
12
+
13
+ const site = useContext(SiteContext)
14
+ const { id, type = 'text', label, placeholder, value, outlined, readOnly=false, onChange, onEnter, onClick } = props
15
+
16
+ function onKeyPress(event) {
17
+ var key = event.charCode ? event.charCode : event.keyCode ? event.keyCode : 0;
18
+ if (key == 13) {
19
+ onEnter()
20
+ }
21
+ }
22
+
23
+ function change(event) {
24
+ event.stopPropagation()
25
+ event.preventDefault()
26
+ const value = event.target.value
27
+ if (onChange) onChange(id, value)
28
+ }
29
+
30
+ function focus() {
31
+ if (site) {
32
+ site.changeFocus({ lose: () => {
33
+ // DO NOTHING
34
+ }})
35
+ }
36
+ }
37
+
38
+ const borderStyle = outlined ? "textfield-outlined" : "textfield"
39
+ const labelStyle = label ? "" : "no-label"
40
+ const style = `${labelStyle} ${borderStyle}`
41
+ const labelTxt = <Text>{label}</Text>
42
+ return (
43
+ <div className={`${style}`} onClick={onClick}>
44
+ <input id={id} type={type} placeholder={placeholder} value={value} required onChange={change} onKeyDown={onKeyPress} onFocus={focus} readOnly={readOnly}/>
45
+ <span className="bar"></span>
46
+ { label ? <label>{labelTxt}</label> : null }
47
+ </div>
48
+ )
49
+ }
50
+
51
+ /**
52
+ * Dropdown
53
+ */
54
+ export const DropDown = (props) => {
55
+
56
+ const site = useContext(SiteContext)
57
+ const { id, options = [], value, onChange } = props
58
+ const [open, setOpen] = useState(false)
59
+ const [label, setLabel] = useState()
60
+
61
+ useEffect(() => {
62
+ if (Array.isArray(options)) {
63
+ const option = options.find(option => option.value === value)
64
+ if (option) setLabel(option.label)
65
+ }
66
+ }, [value])
67
+
68
+
69
+ function toggle() {
70
+ if (site) {
71
+ site.changeFocus({ lose: () => {
72
+ setOpen(false)
73
+ }})
74
+ }
75
+ setOpen(!open)
76
+ }
77
+
78
+ function select(event) {
79
+ const next = event.target.getAttribute("value")
80
+ const option = options.find(option => option.value === next)
81
+ if (onChange) onChange(id, next)
82
+ setLabel(option.label)
83
+ setOpen(false)
84
+ }
85
+
86
+ return (
87
+ <div className="dropdown">
88
+ <TextField {...props} onClick={toggle} value={label} />
89
+ <Icon icon="expand_more" clickable size="small" action={toggle} />
90
+ {open == true ? (
91
+ <menu>
92
+ <ul onClick={select}>
93
+ {Array.isArray(options) ? options.map(option => <li key={option.value} value={option.value}>{option.label}</li>) : null}
94
+ </ul>
95
+ </menu>
96
+ ) : null}
97
+ </div>
98
+ )
99
+ }
@@ -0,0 +1,51 @@
1
+ .tokenField {
2
+ position: relative;
3
+ border: solid 1px var(--divider-color);
4
+ display: flex;
5
+ align-items: center;
6
+ border-radius: .3rem;
7
+ padding: 1rem;
8
+ margin: 1rem 0;
9
+ display: flex;
10
+ flex-wrap: wrap;
11
+ }
12
+
13
+ .tokenField>label {
14
+ position: absolute;
15
+ top:-9px;
16
+ padding: 2px 6px 2px 4px;
17
+ font-size: .8rem;
18
+ background-color: var(--paper-color);
19
+ color: var(--text-color-light)
20
+ }
21
+
22
+ .tokenField input {
23
+ border: 0px;
24
+ padding: .5rem 0;
25
+ font-size: 1rem;
26
+ flex: 1;
27
+ min-width: 3rem;
28
+ }
29
+
30
+ .token {
31
+ display: flex;
32
+ border: solid 1px var(--divider-color);
33
+ background-color: rgba(200,200,200,.1);
34
+ align-items: center;
35
+ padding: .2rem .2rem .2rem .4rem;
36
+ border-radius: .3rem !important;
37
+ margin: .2rem;
38
+ max-height: 2rem;
39
+ }
40
+
41
+ .token > div {
42
+ white-space: nowrap;
43
+ }
44
+
45
+ .token button {
46
+ width: 2rem;
47
+ height: 1.6rem;
48
+ font-size: .8rem !important;
49
+ padding: 0 !important;
50
+ margin-left: .2rem;
51
+ }
@@ -0,0 +1,74 @@
1
+ import React, { useEffect, useRef, useState } from 'react'
2
+ import { Icon } from './icon';
3
+ import { Text } from './text';
4
+ import './tokenfield.css'
5
+
6
+ /**
7
+ * Token Field
8
+ */
9
+ export const TokenField = ({ id, label, init, onChange }) => {
10
+ const mounted = useRef(false)
11
+ const [value, setValue] = useState()
12
+ const [tokens, setTokens] = useState(init)
13
+
14
+ useEffect(() => {
15
+ if (mounted.current) {
16
+ if (onChange) {
17
+ if (tokens) onChange(id, tokens)
18
+ }
19
+ } else {
20
+ mounted.current = true
21
+ }
22
+ }, [tokens])
23
+
24
+ function remove(index) {
25
+ const next = tokens.slice()
26
+ next.splice(index, 1)
27
+ setTokens(next)
28
+ }
29
+
30
+ function change(event) {
31
+ const value = event.target.value
32
+ setValue(value)
33
+ }
34
+
35
+ function onEnter(event) {
36
+ if (event.key === 'Enter') {
37
+ event.preventDefault()
38
+ event.stopPropagation()
39
+ const token = event.target.value
40
+ const next = tokens.concat(token)
41
+ setTokens(next)
42
+ setValue('')
43
+ }
44
+
45
+ if (value === '' && tokens.length> 0 && event.key === 'Backspace') {
46
+ const next = tokens.slice(0, -1)
47
+ setTokens(next)
48
+ }
49
+ }
50
+
51
+ return (
52
+ <div className='tokenField'>
53
+ <label>{label}</label>
54
+ {tokens.map((text, index) => (
55
+ <Token text={text} onDelete={() => remove(index)} />
56
+ ))}
57
+ <input type='text' value={value} onChange={change} onKeyDown={onEnter} />
58
+ </div>
59
+ )
60
+ }
61
+
62
+ /**
63
+ * Token
64
+ */
65
+ const Token = ({ text, onDelete }) => {
66
+ return (
67
+ <div className='token'>
68
+ <Text use='caption' tag='div'>
69
+ {text}
70
+ </Text>
71
+ <Icon icon='close' clickable action={onDelete} size="small"/>
72
+ </div>
73
+ )
74
+ }
@@ -0,0 +1,63 @@
1
+ .tree {
2
+ padding: .5rem 0;
3
+ }
4
+
5
+ .tree-node {
6
+ margin: 0;
7
+ padding: 0;
8
+ padding-left: 1rem;
9
+ }
10
+
11
+ .tree-item{
12
+ margin: 0;
13
+ padding: .5rem 0;
14
+ display: flex;
15
+ align-items: center;
16
+ font: 1rem;
17
+ color: rgba(0,0,0,.7);
18
+ }
19
+
20
+ .tree-item:hover {
21
+ cursor: pointer;
22
+ background-color: rgba(200,200,200,.7);
23
+ font-weight: 500;
24
+ }
25
+
26
+ .tree-item.final {
27
+ margin-left: 1rem;
28
+ padding-left: 1rem;
29
+ }
30
+
31
+ .tree-item>i {
32
+ padding-left: .3rem;
33
+ }
34
+
35
+ .tree-item>.label {
36
+ padding-left: .8rem;
37
+ width: 100%;
38
+ }
39
+
40
+ .tree-item>.actions {
41
+ padding: 0 .5rem;
42
+ color: var(--text-color-lighter);
43
+ }
44
+
45
+ .tree-item>.actions .rmwc-icon {
46
+ padding: 0;
47
+ font-size: 1rem;
48
+ width: 2rem;
49
+ height: 2rem;
50
+ }
51
+
52
+ .tree-node>summary::before {
53
+ content: "\25B6";
54
+ color: black;
55
+ display: inline-block;
56
+ margin-right: 6px;
57
+ font-size: 10px;
58
+ color: rgba(0,0,0,.3);
59
+ }
60
+
61
+ details[open].tree-node>summary::before {
62
+ transform: rotate(90deg)
63
+ }
@@ -0,0 +1,49 @@
1
+ import React from 'react'
2
+ import { Icon } from './icon'
3
+ import './tree.css'
4
+
5
+ /**
6
+ * Tree
7
+ */
8
+ export const Tree = ({ nodes = [], children }) => {
9
+ return (
10
+ <div className="tree">
11
+ {nodes}
12
+ {children}
13
+ </div>
14
+ )
15
+ }
16
+
17
+ /**
18
+ * Tree Node
19
+ */
20
+ export const TreeNode = ({ icon = 'folder', label, tooltip, open=false, children, actions }) => {
21
+ return (
22
+ <details className="tree-node" open={open}>
23
+ <summary className="tree-item">
24
+ { icon ? <Icon icon={icon} size="small" small /> : null }
25
+ <div className="label">{label}</div>
26
+ <div className="actions">{actions}</div>
27
+ </summary>
28
+ {children}
29
+ </details>
30
+ )
31
+ }
32
+
33
+ /**
34
+ * Tree Item
35
+ */
36
+ export const TreeItem = ({ id, icon = 'description', label, actions, onSelect }) => {
37
+
38
+ function select() {
39
+ if (onSelect) onSelect(id)
40
+ }
41
+
42
+ return (
43
+ <div className="tree-item final" onClick={select}>
44
+ <Icon icon={icon} size="small" small />
45
+ <div className="label">{label}</div>
46
+ <div className="actions">{actions}</div>
47
+ </div>
48
+ )
49
+ }
@@ -0,0 +1,62 @@
1
+ async function fetchAsync(method, URL, body = null, token) {
2
+
3
+ console.log('FETCH', method, URL)
4
+
5
+ const request = {
6
+ method,
7
+ mode: 'cors',
8
+ headers: {
9
+ "Accept": "application/json",
10
+ "Content-Type": "application/json",
11
+ "x-access-token": token
12
+ },
13
+ body
14
+ }
15
+
16
+ try {
17
+ var response = await fetch(URL, request);
18
+ if (response.ok) {
19
+ const json = await response.json();
20
+ return json
21
+ }
22
+ throw response
23
+ } catch (error) {
24
+ if (error instanceof Error) { throw { error }}
25
+ const json = await error.json()
26
+ throw {
27
+ success: false,
28
+ message: json.message
29
+ }
30
+ }
31
+ }
32
+
33
+
34
+ export const HTTPClient = (domain, securityCtx) => {
35
+ return {
36
+
37
+ GET: (URL) => {
38
+ const token = securityCtx ? securityCtx.token() : null;
39
+ return fetchAsync('GET', domain + URL, undefined, token);
40
+ },
41
+
42
+ POST: (URL, body) => {
43
+ const token = securityCtx ? securityCtx.token() : null;
44
+ return fetchAsync('POST', domain + URL, body, token);
45
+ },
46
+
47
+ PUT: (URL, body) => {
48
+ const token = securityCtx ? securityCtx.token() : null;
49
+ return fetchAsync('PUT', domain + URL, body, token);
50
+ },
51
+
52
+ PATCH: (URL, body) => {
53
+ const token = securityCtx ? securityCtx.token() : null;
54
+ return fetchAsync('PATCH', domain + URL, body, token);
55
+ },
56
+
57
+ DELETE: (URL) => {
58
+ const token = securityCtx ? securityCtx.token() : null;
59
+ return fetchAsync('DELETE', domain + URL, undefined, token);
60
+ }
61
+ }
62
+ }
@@ -0,0 +1,2 @@
1
+ export { HTTPClient } from './client'
2
+ export { Session } from './session'
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Session store
3
+ * implements securityCtx methods
4
+ */
5
+
6
+ const SESSION_NAME = process.env.REACT_APP_SESSION || window && window.SESSION ? window.SESSION : 'YWANA-CORE6-SESSION';
7
+
8
+ export const Session = {
9
+
10
+ token() {
11
+ const item = sessionStorage.getItem(SESSION_NAME);
12
+ const json = item ? JSON.parse(sessionStorage.getItem(SESSION_NAME)) : {};
13
+ return json.token;
14
+ },
15
+
16
+ me() {
17
+ const item = sessionStorage.getItem(SESSION_NAME);
18
+ const json = item ? JSON.parse(sessionStorage.getItem(SESSION_NAME)) : {};
19
+ return json.me;
20
+ },
21
+
22
+ init(token, me) {
23
+ sessionStorage.setItem(SESSION_NAME, JSON.stringify({ token, me }));
24
+ },
25
+
26
+ refresh(token) {
27
+ const me = this.me();
28
+ sessionStorage.setItem(SESSION_NAME, JSON.stringify({ token, me }));
29
+ },
30
+
31
+ isLoggedIn() {
32
+ return !!sessionStorage.DSSession;
33
+ },
34
+
35
+ logout() {
36
+ sessionStorage.removeItem(SESSION_NAME);
37
+ },
38
+
39
+ }
package/src/index.js ADDED
@@ -0,0 +1,9 @@
1
+ import 'material-design-icons-iconfont/dist/material-design-icons.css'
2
+
3
+ export * from './http'
4
+ export * from './html'
5
+ export * from './widgets'
6
+ export * from './site'
7
+ export * from './domain'
8
+
9
+ export const isFunction = value => value && (Object.prototype.toString.call(value) === "[object Function]" || "function" === typeof value || value instanceof Function);
@@ -0,0 +1,58 @@
1
+
2
+ .page6>details {
3
+ position: absolute;
4
+ bottom: 0px;
5
+ left: 0px;
6
+ right: 0px;
7
+ margin: auto;
8
+ min-width: 30rem;
9
+ width: 100vw;
10
+ max-width: 50rem;
11
+ min-height: 3rem;
12
+ background-color: var(--paper-color);
13
+ border-radius: 5px 5px 0 0;
14
+ overflow: hidden;
15
+ box-shadow: var(--shadow-top);
16
+ }
17
+
18
+ .page6>details>summary {
19
+ display: flex;
20
+ align-items: center;
21
+ min-height: 3rem;
22
+ }
23
+
24
+ summary {
25
+ /* list-style-type: none; /* Firefox */
26
+ padding: 0 0 0 1rem;
27
+ }
28
+
29
+ summary::-webkit-details-marker {
30
+ display: none; /* Chrome */
31
+ }
32
+
33
+ details[open] main {
34
+ animation-name: invisiblyGrowFontSize, fadeIn;
35
+ animation-duration: 500ms, 200ms;
36
+ animation-delay: 0ms, 500ms;
37
+ }
38
+
39
+ /* add wrapper, continue with font-size */
40
+ @keyframes invisiblyGrowFontSize {
41
+ 0% {
42
+ font-size: 0;
43
+ opacity: 0;
44
+ }
45
+ 100% {
46
+ font-size: 1em;
47
+ opacity: 0;
48
+ }
49
+ }
50
+
51
+ @keyframes fadeIn {
52
+ 0% {
53
+ opacity: 0;
54
+ }
55
+ 100% {
56
+ opacity: 1;
57
+ }
58
+ }