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,80 @@
1
+ import React, { useContext, useState } from 'react'
2
+ import { Icon } from './icon';
3
+ import './menu.css'
4
+
5
+
6
+ /**
7
+ * Page Context
8
+ */
9
+ export const MenuContext = React.createContext({})
10
+
11
+ /**
12
+ * Menu
13
+ **/
14
+ export const Menu = (props) => {
15
+ const { children } = props
16
+ return (
17
+ <ul>
18
+ {children}
19
+ </ul>
20
+ )
21
+ }
22
+
23
+ /**
24
+ * Menu Icon
25
+ */
26
+ export const MenuIcon = (props) => {
27
+
28
+ const { icon = "more_vert", children, align } = props
29
+ const [open, setOpen] = useState(false)
30
+
31
+ function toggle() {
32
+ setOpen(!open)
33
+ }
34
+
35
+ return (
36
+ <MenuContext.Provider value={[open, setOpen]}>
37
+ <div className="menu-icon">
38
+ <Icon icon={icon} clickable action={toggle} />
39
+ {open ? (
40
+ <menu className={`${align}`}>
41
+ {children}
42
+ </menu>
43
+ ) : null}
44
+ {open ? <div className="overlay" onClick={toggle}/> : null}
45
+ </div>
46
+ </MenuContext.Provider>
47
+ )
48
+ }
49
+
50
+ /**
51
+ * Menu Item
52
+ */
53
+ export const MenuItem = (props) => {
54
+
55
+ const { id, icon, label, meta, onSelect } = props
56
+ const [open, setOpen] = useContext(MenuContext)
57
+
58
+ function select() {
59
+ if (onSelect) onSelect()
60
+ setOpen(false)
61
+ }
62
+ return (
63
+ <li className="menu-item" onClick={select}>
64
+ {icon ? <Icon icon={icon} /> : null}
65
+ <label>{label}</label>
66
+ {meta ? <div className="meta">{meta}</div> : null}
67
+ </li>
68
+ )
69
+ }
70
+
71
+ /**
72
+ * Menu Separator
73
+ */
74
+ export const MenuSeparator = (props) => {
75
+ return (
76
+ <li>
77
+ menuSeparator
78
+ </li>
79
+ )
80
+ }
@@ -0,0 +1,20 @@
1
+ @keyframes rotating {
2
+ from {
3
+ -ms-transform: rotate(0deg);
4
+ -moz-transform: rotate(0deg);
5
+ -webkit-transform: rotate(0deg);
6
+ -o-transform: rotate(0deg);
7
+ transform: rotate(0deg);
8
+ }
9
+ to {
10
+ -ms-transform: rotate(360deg);
11
+ -moz-transform: rotate(360deg);
12
+ -webkit-transform: rotate(360deg);
13
+ -o-transform: rotate(360deg);
14
+ transform: rotate(360deg);
15
+ }
16
+ }
17
+
18
+ .circular-progress {
19
+ animation: rotating 2s linear infinite;
20
+ }
@@ -0,0 +1,27 @@
1
+ import { Icon } from './icon'
2
+ import './progress.css'
3
+
4
+ /**
5
+ * Circular Progress
6
+ */
7
+ export const CircularProgress = (props) => {
8
+ return (
9
+ <div className="circular-progress">
10
+ <Icon icon="refresh" size="small" />
11
+ </div>
12
+ )
13
+ }
14
+
15
+ /**
16
+ * Linear Progress
17
+ */
18
+ export const LinearProgress = (props) => {
19
+
20
+ const { progress= 0, max = 100 } = props
21
+
22
+ return (
23
+ <div className="linear-progress">
24
+ <progress value={progress} max={max}/>
25
+ </div>
26
+ )
27
+ }
@@ -0,0 +1,18 @@
1
+ .property {
2
+ flex:1;
3
+ display: flex;
4
+ }
5
+
6
+ .property-name {
7
+ flex: 1;
8
+ overflow: hidden;
9
+ text-overflow: ellipsis;
10
+ white-space: nowrap;
11
+ }
12
+
13
+ .property-value {
14
+ flex: 1;
15
+ overflow: hidden;
16
+ text-overflow: ellipsis;
17
+ white-space: nowrap;
18
+ }
@@ -0,0 +1,16 @@
1
+ import './property.css'
2
+
3
+ /**
4
+ * Property
5
+ */
6
+ export const Property = (props) => {
7
+
8
+ const { name, value} = props
9
+
10
+ return (
11
+ <div className="property">
12
+ <div className="property-name">{name}</div>
13
+ <div className="property-value">{value}</div>
14
+ </div>
15
+ )
16
+ }
@@ -0,0 +1,50 @@
1
+ .radio {
2
+ flex: 1;
3
+ overflow: hidden;
4
+ display: flex;
5
+ align-items: center;
6
+ position: relative;
7
+ }
8
+
9
+ .radio .checkmark {
10
+ width: 1.5rem;
11
+ height: 1.5rem;
12
+ display: flex;
13
+ align-items: center;
14
+ justify-content: center;
15
+ margin: 0.3rem;
16
+ border: solid 1px var(--primary-color);
17
+ background-color: var(--paper-color);
18
+ border-radius: 3rem;
19
+ }
20
+
21
+ .radio .checkmark:after {
22
+ content: "";
23
+ width: .4rem;
24
+ height: .4rem;
25
+ border: solid 5px var(--primary-color);
26
+ border-radius: 5rem;
27
+ background-color: var(--primary-color);
28
+ display: none;
29
+ z-index: 0;
30
+ }
31
+
32
+ .radio > input {
33
+ position: absolute;
34
+ flex: 1;
35
+ width: 2rem;
36
+ height: 2rem;
37
+ opacity: 0;
38
+ z-index: 1;
39
+ }
40
+
41
+ input:checked ~ .checkmark:after {
42
+ display: block;
43
+ }
44
+
45
+ .radio > label {
46
+ color: var(--text-color-light);
47
+ font-size: 1rem;
48
+ font-weight: normal;
49
+ }
50
+
@@ -0,0 +1,25 @@
1
+ import React from 'react'
2
+ import { Text } from './text';
3
+ import './radio.css'
4
+
5
+ /**
6
+ * Radio Button
7
+ */
8
+ export const RadioButton = (props) => {
9
+
10
+ const { id, name, label, placeholder, value, onChange } = props
11
+
12
+ function change(event) {
13
+ const value = event.target.value
14
+ if (onChange) onChange(id, value)
15
+ }
16
+
17
+ const labelTxt = <Text>{label}</Text>
18
+ return (
19
+ <div className="radio">
20
+ <input id={id} name={name} type="radio" placeholder={placeholder} value={value} onClick={change} />
21
+ <span class="checkmark" />
22
+ <label htmlFor={id}>{labelTxt}</label>
23
+ </div>
24
+ )
25
+ }
@@ -0,0 +1,6 @@
1
+ .section2>header {
2
+ background-color: rgba(200,200,200,.1);
3
+ padding: 0 1rem;
4
+ min-height: 3rem;
5
+ font-weight: 500;
6
+ }
@@ -0,0 +1,31 @@
1
+ import React, { useEffect, useState } from 'react'
2
+ import { Icon } from './icon';
3
+ import { Header } from './header';
4
+ import './section.css'
5
+
6
+ /**
7
+ * Section
8
+ */
9
+ export const Section = (props) => {
10
+
11
+ const { icon, title = '', canCollapse = true, open = false, actions, children, className } = props
12
+ const [isOpen, setOpen] = useState(open)
13
+
14
+ useEffect(() => {
15
+ setOpen(open)
16
+ }, [open])
17
+
18
+ const toggle = () => {
19
+ setOpen(!open)
20
+ }
21
+
22
+ return (
23
+ <section className={`section2 ${className}`}>
24
+ <Header icon={{ icon }} title={title}>
25
+ {actions}
26
+ {canCollapse ? <Icon icon="expand_more" onIcon="expand_less" clickable action={toggle} /> : ''}
27
+ </Header>
28
+ {isOpen ? (<main>{children}</main>) : ''}
29
+ </section>
30
+ )
31
+ }
@@ -0,0 +1,45 @@
1
+ .tabs {
2
+ flex: 1;
3
+ display: flex;
4
+ overflow-x: auto;
5
+ align-items: flex-end;
6
+ max-height: 3rem;
7
+ }
8
+
9
+ .tab, .tab-filler {
10
+ padding: 0 1rem;
11
+ text-transform: uppercase;
12
+ overflow: hidden;
13
+ cursor: pointer;
14
+ display: flex;
15
+ justify-content: center;
16
+ align-items: center;
17
+ height: 2rem;
18
+ border-bottom: solid 1px var(--divider-color);
19
+ background-color: transparent !important;
20
+ min-width: 5rem;
21
+ font-size: .9rem;
22
+ color: var(--text-color-light);
23
+ }
24
+
25
+ .tab-filler {
26
+ flex: 1;
27
+ }
28
+
29
+ .tab:hover {
30
+ background-color: var(--background-color);
31
+ cursor: pointer;
32
+ }
33
+
34
+ .tab.selected {
35
+ background-color: var(--paper-color) !important;
36
+ color: var(--text-color);
37
+ border: solid 1px var(--divider-color);
38
+ border-bottom-width: 0;
39
+ min-height: 2.2rem;
40
+ border-radius: 0;
41
+ }
42
+
43
+ .tab.small {
44
+ padding: .2rem;
45
+ }
@@ -0,0 +1,68 @@
1
+ import React, { useState } from 'react'
2
+ import { Fragment } from 'react'
3
+ import './tab.css'
4
+
5
+ /**
6
+ * Tabs
7
+ */
8
+ export const Tabs = (props) => {
9
+
10
+ const { children, selected, onChange } = props
11
+
12
+ const tabs = React.Children.map(children, (child, index) => {
13
+
14
+ function select() {
15
+ if (onChange) onChange(index)
16
+ }
17
+
18
+ return React.cloneElement(child, {
19
+ selected: index === selected,
20
+ onSelect: select
21
+ })
22
+ })
23
+
24
+ return (
25
+ <div class="tabs">
26
+ {tabs}
27
+ <div class="tab-filler" />
28
+ </div>
29
+ )
30
+ }
31
+
32
+ /**
33
+ * Tab
34
+ */
35
+ export const Tab = (props) => {
36
+
37
+ const { label, selected, actions, onSelect } = props
38
+
39
+ function select() {
40
+ if (onSelect) onSelect()
41
+ }
42
+
43
+ const style = selected ? "selected" : ""
44
+ return (
45
+ <div className={`tab ${style}`} onClick={select}>
46
+ {label}
47
+ {actions ? actions : null}
48
+ </div>
49
+ )
50
+ }
51
+
52
+ /**
53
+ * Stack
54
+ */
55
+ export const Stack = (props) => {
56
+
57
+ const { selected = 0 } = props
58
+
59
+ const child = React.Children
60
+ .toArray(props.children)
61
+ .filter((child, index) => index === selected )[0]
62
+
63
+ return (
64
+ <Fragment>
65
+ {child}
66
+ </Fragment>
67
+ )
68
+ }
@@ -0,0 +1,56 @@
1
+ .datatable8 {
2
+ max-height: 40rem;
3
+ overflow: hidden;
4
+ border: solid 0px var(--divider-color);
5
+ background-color: var(--paper-color);
6
+ }
7
+
8
+ .datatable8.outlined {
9
+ border: solid 1px var(--divider-color);
10
+ }
11
+
12
+ .datatable8 table {
13
+ width: 100%;
14
+ }
15
+
16
+ .datatable8 thead {
17
+ position: sticky;
18
+ top: 0px;
19
+ background-color: rgba(200,200,200,.4);
20
+ overflow: hidden;
21
+ color: var(--text-color-lighter);
22
+ }
23
+
24
+ .datatable8 thead tr {
25
+ border-bottom: solid 1px var(--divider-color);
26
+ }
27
+
28
+ .datatable8 thead th {
29
+ padding: 0 1rem;
30
+ text-align: left;
31
+ font-weight: 600 !important;
32
+ }
33
+
34
+ .datatable8 tbody {
35
+ overflow: visible;
36
+ height: 5rem;
37
+ }
38
+
39
+ .datatable8 tbody tr {
40
+ border-bottom: solid 1px var(--divider-color);
41
+ }
42
+
43
+ .datatable8 tbody tr:hover {
44
+ background-color: rgba(200,200,200,.2);
45
+ cursor: pointer
46
+ }
47
+
48
+ .datatable8 tbody td {
49
+ height: 3rem;
50
+ padding: 0 1rem;
51
+ overflow: visible;
52
+ text-overflow: ellipsis;
53
+ white-space: nowrap;
54
+ max-width: 10rem;
55
+ color: var(--text-color-light);
56
+ }
@@ -0,0 +1,186 @@
1
+ import { Fragment, useState } from 'react'
2
+ import { CheckBox } from './checkbox'
3
+ import { Icon } from './icon'
4
+ import { Text } from './text'
5
+ import { DropDown, TextField } from './textfield'
6
+ import './table.css'
7
+
8
+ /**
9
+ * DataTable
10
+ */
11
+ export const DataTable = (props) => {
12
+
13
+ const { columns = [], rows = [], onRowSelection, onSort, editable, outlined } = props
14
+ const [sortDir, setSortDir] = useState({})
15
+
16
+ function multiSort(array, sortObject = {}) {
17
+
18
+ const sortKeys = Object.keys(sortObject);
19
+
20
+ if (!sortKeys.length) {
21
+ return array;
22
+ }
23
+
24
+ const keySort = (a, b, direction) => {
25
+ direction = direction !== null ? direction : 1;
26
+
27
+ if (a === b) { // If the values are the same, do not switch positions.
28
+ return 0;
29
+ }
30
+
31
+ // If b > a, multiply by -1 to get the reverse direction.
32
+ return a > b ? direction : -1 * direction;
33
+ };
34
+
35
+ return array.sort((a, b) => {
36
+ let sorted = 0;
37
+ let index = 0;
38
+
39
+ // Loop until sorted (-1 or 1) or until the sort keys have been processed.
40
+ while (sorted === 0 && index < sortKeys.length) {
41
+ const key = sortKeys[index];
42
+
43
+ if (key) {
44
+ const direction = sortObject[key];
45
+
46
+ sorted = keySort(a[key], b[key], direction);
47
+ index++;
48
+ }
49
+ }
50
+
51
+ return sorted;
52
+ });
53
+ }
54
+
55
+ function select(row, event) {
56
+ if (onRowSelection) onRowSelection(row, event)
57
+ }
58
+
59
+ function sort(dragged, dropped) {
60
+ if (onSort) onSort(dragged, dropped)
61
+ }
62
+
63
+ const style = outlined ? "outlined" : ""
64
+ return (
65
+ <div className={`datatable8 ${style}`}>
66
+ <table>
67
+ <thead>
68
+ <tr>
69
+ {columns.map(({ id, label, sortable }) => {
70
+ const sort = sortDir[id] ? sortDir[id] : null
71
+ return (
72
+ <th>
73
+ <Text>{label}</Text>
74
+ {sortable ? <Icon icon="arrow_up" size="small" clickable /> : null}
75
+ </th>
76
+ )
77
+ })}
78
+ </tr>
79
+ </thead>
80
+ <tbody>
81
+ {
82
+ multiSort(rows, sortDir).map(row => (
83
+ <DataTableRow key={row.id} row={row} columns={columns} onSelect={select} onDrop={sort} editable={editable}/>
84
+ ))
85
+ }
86
+ </tbody>
87
+ </table>
88
+ </div>
89
+ )
90
+ }
91
+
92
+ /**
93
+ * DataTable Row
94
+ */
95
+ const DataTableRow = (props) => {
96
+ const { row, columns = [], onSelect, editable } = props
97
+ const [isInfoOpen, toggleInfo] = useState(false)
98
+ const infoIcon = isInfoOpen ? 'expand_more' : 'expand_less'
99
+
100
+ const isFunction = value => value && (Object.prototype.toString.call(value) === "[object Function]" || "function" === typeof value || value instanceof Function);
101
+
102
+ return (
103
+ <Fragment>
104
+ <tr onClick={ev => onSelect(row, ev)}>
105
+ {columns.map(column => <DataTableCell row={row} column={column} cell={row[column.id]} editable={editable}/>)}
106
+ {row.info ? <Icon icon={infoIcon} clickable action={() => toggleInfo(!isInfoOpen)} /> : null}
107
+ </tr>
108
+ {row.info && isInfoOpen ? (
109
+ <tr className="table-row-info">
110
+ {isFunction(row.info) ? row.info() : row.info}
111
+ </tr>
112
+ ) : null}
113
+ </Fragment>
114
+ )
115
+ }
116
+
117
+ /**
118
+ * DataTable Cell
119
+ */
120
+ const DataTableCell = ({ row, column, cell, editable }) => {
121
+
122
+ const render = (type) => {
123
+ const { id, disabled = false, min, max, onChange, options } = column
124
+ if (editable && onChange) {
125
+ switch (type) {
126
+ case "ICON": return <Icon icon={cell} />
127
+ case "BOOLEAN": return <CheckBox id={id} value={cell} onChange={(id, value) => onChange(row.id, id, value)} disabled={disabled} />
128
+ case "Boolean": return <CheckBox id={id} value={cell} onChange={(id, value) => onChange(row.id, id, value)} disabled={disabled} />
129
+ case "SELECTION": return <DropDown id={id} value={cell} placeholder="--Select--" options={options} onChange={(id, value) => onChange(row.id, id, value)} />
130
+ case "CHECK": return <CheckBox id={id} value={cell} onChange={(id, value) => onChange(row.id, id, value)} disabled={row.disabled} />
131
+ case "CHECKABLE": return cell && cell.value ? <CheckBox id={id} value={cell.checked || false} label={cell.value} onChange={(id, checked) => onChange(row.id, id, cell.value, checked, cell)} /> : ''
132
+ case "TEXTFIELD": return <TextField id={id} value={cell} onChange={(id, value) => onChange(row.id, id, value)} />
133
+ case "String": return <StringCellEditor id={id} value={cell} options={options} onChange={(id, value) => onChange(row.id, id, value)} />
134
+ case "Number": return <TextField id={id} type="number" value={cell} min={min} max={max} onChange={(id, value) => onChange(row.id, id, value)} />
135
+ default: return cell
136
+ }
137
+ } else {
138
+ switch (type) {
139
+ case "ICON": return <Icon icon={cell} />
140
+ case "Boolean": return <BooleanCellViewer id={id} value={cell} />
141
+ case "String": return <StringCellViewer id={id} value={cell} options={options} />
142
+ default: return cell
143
+ }
144
+ }
145
+ }
146
+
147
+ return (
148
+ <td className={column.id}>{render(column.type)}</td>
149
+ )
150
+ }
151
+
152
+ /**
153
+ * Boolean Cell Viewer
154
+ */
155
+ const BooleanCellViewer = ({ id, value = false }) => {
156
+ const icon = value === true ? "check_box" : "check_box_outline_blank"
157
+ return <Icon icon={icon} />
158
+ }
159
+
160
+ /**
161
+ * String Cell Viewer
162
+ */
163
+ const StringCellViewer = ({ id, value, options }) => {
164
+ const option = options ? options.find( o => o.value === value) : null
165
+ const text = option ? option.label : value
166
+ return (<div className="field-editor string-editor">{text}</div>)
167
+ }
168
+
169
+ /**
170
+ * String Cell Editor
171
+ */
172
+ export const StringCellEditor = ({ id, value = '', options, onChange }) => {
173
+
174
+ function change(id, value) {
175
+ if (onChange) onChange(id, value)
176
+ }
177
+
178
+ return (
179
+ <div className='field-editor string-editor'>
180
+ {options ?
181
+ <DropDown outlined id={id} value={value} onChange={change} options={options} />
182
+ : <TextField outlined id={id} value={value} onChange={change} />
183
+ }
184
+ </div>
185
+ )
186
+ }
@@ -0,0 +1,20 @@
1
+ import { useContext } from "react"
2
+ import { SiteContext } from "../site/siteContext"
3
+
4
+ /**
5
+ * Text
6
+ */
7
+ export const Text = ({ children }) => {
8
+
9
+ const site = useContext(SiteContext)
10
+
11
+ if (site) {
12
+ const { lang, dictionary = {}} = site
13
+ const term = dictionary[children]
14
+ const text = term ? term[lang] : children
15
+ return text ? <span>{text}</span> : ''
16
+ }
17
+
18
+ return children ? <span>{children}</span> : ''
19
+
20
+ }