@zuzjs/ui 0.2.4 → 0.2.6
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.
- package/README.md +1 -0
- package/dist/index.js +214 -15
- package/package.json +4 -2
- package/src/actions/addForm.tsx +0 -0
- package/src/actions/index.tsx +29 -0
- package/src/actions/redo.tsx +1 -0
- package/src/actions/reset.tsx +1 -0
- package/src/actions/undo.tsx +1 -0
- package/src/comps/app.tsx +34 -0
- package/src/comps/box.tsx +23 -0
- package/src/comps/button.tsx +45 -0
- package/src/comps/checkbox.tsx +74 -0
- package/src/comps/component.tsx +32 -0
- package/src/comps/contextmenu.tsx +43 -0
- package/src/comps/cover.tsx +34 -0
- package/src/comps/form.tsx +89 -0
- package/src/comps/heading.tsx +31 -0
- package/src/comps/icon.tsx +36 -0
- package/src/comps/image.tsx +26 -0
- package/src/comps/input.tsx +80 -0
- package/src/comps/masonry.tsx +192 -0
- package/src/comps/placeholder.tsx +58 -0
- package/src/comps/root.tsx +32 -0
- package/src/comps/select.tsx +63 -0
- package/src/comps/spacer.tsx +20 -0
- package/src/comps/spinner.tsx +36 -0
- package/src/comps/text.tsx +27 -0
- package/src/comps/toaster.tsx +115 -0
- package/src/comps/tweet.tsx +48 -0
- package/src/context/AppContext.tsx +3 -0
- package/src/context/AppProvider.tsx +101 -0
- package/src/context/_AppProvider.tsx +116 -0
- package/src/context/combineReducers.tsx +47 -0
- package/src/context/combineState.tsx +14 -0
- package/src/context/createSlice.tsx +40 -0
- package/src/context/index.tsx +6 -0
- package/src/context/reduceReducers.tsx +6 -0
- package/src/context/store/appbase.tsx +19 -0
- package/src/context/store/theme.tsx +53 -0
- package/src/core/defaultTheme.ts +89 -0
- package/src/core/extractCurrentDesignState.tsx +0 -0
- package/src/core/index.ts +285 -0
- package/src/core/router.ts +86 -0
- package/src/core/styles.ts +361 -0
- package/src/hooks/index.tsx +8 -0
- package/src/hooks/useAppReducer.tsx +40 -0
- package/src/hooks/useChooseEffect.tsx +6 -0
- package/src/hooks/useDevice.tsx +164 -0
- package/src/hooks/useDispatch.tsx +37 -0
- package/src/hooks/useImage.tsx +58 -0
- package/src/hooks/useResizeObserver.tsx +84 -0
- package/src/hooks/useRouter.tsx +45 -0
- package/src/hooks/useSelector.tsx +9 -0
- package/src/hooks/useStore.tsx +27 -0
- package/src/hooks/useTheme.tsx +9 -0
- package/src/hooks/useToast.tsx +11 -0
- package/src/index.tsx +33 -0
- package/src/kit/Builder.tsx +18 -0
- package/src/kit/Component.tsx +32 -0
- package/src/kit/Header.tsx +21 -0
- package/src/redux/slices/app.js +26 -0
- package/src/redux/slices/form.js +46 -0
- package/src/redux/store.js +33 -0
- package/src/scss/constants.scss +4 -0
- package/src/scss/mixins.scss +3 -0
- package/src/scss/props.scss +60 -0
- package/src/scss/style.scss +106 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Ref,
|
|
3
|
+
LegacyRef,
|
|
4
|
+
forwardRef,
|
|
5
|
+
useState,
|
|
6
|
+
createElement,
|
|
7
|
+
useEffect,
|
|
8
|
+
useImperativeHandle
|
|
9
|
+
} from 'react';
|
|
10
|
+
import PropTypes from 'prop-types'
|
|
11
|
+
import Box from './box'
|
|
12
|
+
import Cover from './cover'
|
|
13
|
+
import { addProps } from '../core'
|
|
14
|
+
import useDispatch from '../hooks/useDispatch'
|
|
15
|
+
import useStore from '../hooks/useStore'
|
|
16
|
+
import { STORE_FORM_KEY, STORE_DEFAUTLS } from '../context/AppProvider'
|
|
17
|
+
import { nanoid } from 'nanoid'
|
|
18
|
+
import {
|
|
19
|
+
ADD_FORM,
|
|
20
|
+
UPDATE_FORM_FIELD
|
|
21
|
+
} from '../actions'
|
|
22
|
+
|
|
23
|
+
const Form = forwardRef((props : { [ key: string ] : any }, ref : Ref<any>) => {
|
|
24
|
+
|
|
25
|
+
const {
|
|
26
|
+
name,
|
|
27
|
+
children,
|
|
28
|
+
onSubmit,
|
|
29
|
+
cover,
|
|
30
|
+
debug
|
|
31
|
+
} = props;
|
|
32
|
+
|
|
33
|
+
const [_html, setHTML] = useState(null);
|
|
34
|
+
const [_loading, setLoading] = useState(debug?.loading || false);
|
|
35
|
+
const dispatch = useDispatch(STORE_FORM_KEY)
|
|
36
|
+
const { forms } = useStore(state => state[STORE_FORM_KEY], false)
|
|
37
|
+
|
|
38
|
+
const buildFields = () => {
|
|
39
|
+
return addProps(children, { form : name, touched: undefined, loading: undefined, onSubmit: onSubmit ? onSubmit : () => console.log(`onSubmit Missing`) })
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const update = (e : object) => Object.keys(e).map(k => {
|
|
43
|
+
dispatch( UPDATE_FORM_FIELD( name || 'orphan', k, e[k], forms ) )
|
|
44
|
+
if(k == 'loading') setLoading(e[k])
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
const get = (k : string) => forms[name][k] || null
|
|
48
|
+
|
|
49
|
+
useImperativeHandle(ref, () => ({
|
|
50
|
+
update,
|
|
51
|
+
get
|
|
52
|
+
}))
|
|
53
|
+
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
let f = buildFields();
|
|
56
|
+
setHTML(f.children);
|
|
57
|
+
if(!forms[name]){
|
|
58
|
+
dispatch(ADD_FORM(name, f.fields, forms))
|
|
59
|
+
}
|
|
60
|
+
}, [children, forms[name]?.loading])
|
|
61
|
+
|
|
62
|
+
return createElement(
|
|
63
|
+
Box,
|
|
64
|
+
{
|
|
65
|
+
rel: true,
|
|
66
|
+
...props,
|
|
67
|
+
as: name
|
|
68
|
+
},
|
|
69
|
+
[
|
|
70
|
+
_loading? <Cover key={`form-${name}-cover`} backdrop={cover?.filter || { saturate: 80, blur: 10 }} bg={cover?.bg || `rgba(0,0,0,0.5)`} /> : null,
|
|
71
|
+
_html
|
|
72
|
+
]
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
Form.defaultProps = {
|
|
78
|
+
name: 'form1',
|
|
79
|
+
onSubmit: () => { console.log(`onSubmit not provided`) }
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
Form.propTypes = {
|
|
83
|
+
name: PropTypes.string.isRequired,
|
|
84
|
+
children: PropTypes.node.isRequired,
|
|
85
|
+
onSubmit: PropTypes.func.isRequired
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
export default Form
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FC,
|
|
3
|
+
LegacyRef,
|
|
4
|
+
forwardRef,
|
|
5
|
+
HTMLAttributes
|
|
6
|
+
} from 'react';
|
|
7
|
+
import { ClassNames } from '@emotion/react'
|
|
8
|
+
import { buildCSS } from '../core'
|
|
9
|
+
|
|
10
|
+
const Heading = forwardRef((props : { [ key: string ] : any }, ref : LegacyRef<HTMLHeadingElement>) => {
|
|
11
|
+
|
|
12
|
+
const {
|
|
13
|
+
children,
|
|
14
|
+
as,
|
|
15
|
+
h
|
|
16
|
+
} = props;
|
|
17
|
+
|
|
18
|
+
let Tag : string = `h${h || 1}`;
|
|
19
|
+
const HeadingTag = Tag as `h1` | `h2` | `h3` | `h4` | `h5` | `h6`
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<ClassNames>
|
|
23
|
+
{({ css, cx }) => <HeadingTag
|
|
24
|
+
className={`${as ? `${as} ` : ``}${cx(css`${buildCSS(props)}`)}`}
|
|
25
|
+
ref={ref}
|
|
26
|
+
>{props.html ? <span dangerouslySetInnerHTML={{ __html: props.html }} /> : children}</HeadingTag>}
|
|
27
|
+
</ClassNames>
|
|
28
|
+
)
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
export default Heading;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FC,
|
|
3
|
+
LegacyRef,
|
|
4
|
+
forwardRef,
|
|
5
|
+
useRef,
|
|
6
|
+
SyntheticEvent,
|
|
7
|
+
} from 'react';
|
|
8
|
+
import Box from './box'
|
|
9
|
+
|
|
10
|
+
const Icon = forwardRef((props : { [ key: string ] : any }, ref : LegacyRef<HTMLHeadingElement>) => {
|
|
11
|
+
|
|
12
|
+
const {
|
|
13
|
+
as,
|
|
14
|
+
path,
|
|
15
|
+
size,
|
|
16
|
+
color,
|
|
17
|
+
hover
|
|
18
|
+
} = props;
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<Box
|
|
22
|
+
hover={hover || {}}
|
|
23
|
+
flex
|
|
24
|
+
bref={ref}
|
|
25
|
+
as={`icon-${as}`}
|
|
26
|
+
ai={`c`}
|
|
27
|
+
jc={`c`}
|
|
28
|
+
size={size || 24}
|
|
29
|
+
color={color || `#111111`}
|
|
30
|
+
>
|
|
31
|
+
{path && Array(path).fill(undefined).map((p : any, i : any) => <span key={`ico-${as}-${i}`} className={`path${i+1}`} />)}
|
|
32
|
+
</Box>
|
|
33
|
+
)
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
export default Icon;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import {
|
|
2
|
+
forwardRef,
|
|
3
|
+
LegacyRef
|
|
4
|
+
} from 'react'
|
|
5
|
+
import { ClassNames } from '@emotion/react'
|
|
6
|
+
import { buildCSS } from '../core'
|
|
7
|
+
import useImage from '../hooks/useImage'
|
|
8
|
+
import Box from './box'
|
|
9
|
+
|
|
10
|
+
const Image = forwardRef((props : { [ key: string ] : any }, ref : LegacyRef<HTMLImageElement>) => {
|
|
11
|
+
|
|
12
|
+
const [photo, status] = useImage(props.src, 'anonymous', 'origin');
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<ClassNames>
|
|
16
|
+
{({ css, cx }) => <picture className={cx(css`${buildCSS({ flex: true })}`)}>
|
|
17
|
+
{status == 'loading' && <Box className={`${props.as ? `${props.as} ` : ``}${cx(css`background: #eee;${buildCSS(props)}`)}`} />}
|
|
18
|
+
{status == 'loaded' && <img src={props.src}
|
|
19
|
+
className={`${props.as ? `${props.as} ` : ``}${cx(css`${buildCSS(props)}`)}`}
|
|
20
|
+
ref={ref} />}
|
|
21
|
+
</picture>}
|
|
22
|
+
</ClassNames>
|
|
23
|
+
)
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
export default Image;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FC,
|
|
3
|
+
LegacyRef,
|
|
4
|
+
forwardRef,
|
|
5
|
+
useRef,
|
|
6
|
+
SyntheticEvent,
|
|
7
|
+
} from 'react';
|
|
8
|
+
import { ClassNames } from '@emotion/react'
|
|
9
|
+
import { nanoid } from 'nanoid';
|
|
10
|
+
import { buildCSS } from '../core'
|
|
11
|
+
import { STORE_FORM_KEY } from '../context/AppProvider'
|
|
12
|
+
import useDispatch from '../hooks/useDispatch'
|
|
13
|
+
import useStore from '../hooks/useStore'
|
|
14
|
+
import {
|
|
15
|
+
UPDATE_FORM_FIELD
|
|
16
|
+
} from '../actions'
|
|
17
|
+
|
|
18
|
+
const Input = forwardRef((props : { [ key: string ] : any }, ref : LegacyRef<HTMLHeadingElement>) => {
|
|
19
|
+
|
|
20
|
+
const {
|
|
21
|
+
as,
|
|
22
|
+
accept,
|
|
23
|
+
multiple,
|
|
24
|
+
onChange,
|
|
25
|
+
onKeyUp,
|
|
26
|
+
type,
|
|
27
|
+
tag,
|
|
28
|
+
placeholder,
|
|
29
|
+
name,
|
|
30
|
+
form,
|
|
31
|
+
touched,
|
|
32
|
+
onSubmit,
|
|
33
|
+
defaultValue,
|
|
34
|
+
fref
|
|
35
|
+
} = props;
|
|
36
|
+
|
|
37
|
+
const dispatch = useDispatch(STORE_FORM_KEY)
|
|
38
|
+
const { forms } = useStore(state => state[STORE_FORM_KEY], false)
|
|
39
|
+
|
|
40
|
+
let Tag : string = tag || 'input';
|
|
41
|
+
const El = Tag as `textarea` | `input`
|
|
42
|
+
const _ref = fref || useRef();
|
|
43
|
+
|
|
44
|
+
const _defaultCSS = `width: 100%;border-radius: var(--radius-base);padding-left: 4px;padding-right: 4px;border-style: solid;border-width: 1px;border-color: var(--colors-gray-200);`;
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<ClassNames>
|
|
48
|
+
{({ css, cx }) => <El
|
|
49
|
+
type={type || `text`}
|
|
50
|
+
placeholder={placeholder || undefined}
|
|
51
|
+
name={name || nanoid()}
|
|
52
|
+
multiple={type == 'file' ? multiple : undefined}
|
|
53
|
+
accept={accept || `*`}
|
|
54
|
+
className={`${as ? `${as} ` : ``}f ${cx(css`${_defaultCSS}${buildCSS(props)}&:hover {${buildCSS(props.hover || {})}} &:focus {${buildCSS(props.focus || {})}}`)}`}
|
|
55
|
+
ref={_ref}
|
|
56
|
+
defaultValue={defaultValue || ``}
|
|
57
|
+
onKeyUp={(e : SyntheticEvent) => {
|
|
58
|
+
let k = e['keyCode'] || ['which'];
|
|
59
|
+
if(El != 'textarea' && k == 13 && form && onSubmit){
|
|
60
|
+
onSubmit(forms[form]);
|
|
61
|
+
}
|
|
62
|
+
}}
|
|
63
|
+
onChange={e => {
|
|
64
|
+
let val = type == 'file' ?
|
|
65
|
+
e.currentTarget.files
|
|
66
|
+
: e.currentTarget.value;
|
|
67
|
+
dispatch( dispatch( UPDATE_FORM_FIELD( form || 'orphan', name, val == "" ? null : val, forms ) ) );
|
|
68
|
+
onChange && onChange(val == "" ? null : val)
|
|
69
|
+
}}
|
|
70
|
+
onBlur={e => {
|
|
71
|
+
if(touched){}
|
|
72
|
+
}}
|
|
73
|
+
onFocus={ e => touched == false && dispatch( UPDATE_FORM_FIELD( form || 'orphan', `touched`, true, forms ) ) }
|
|
74
|
+
/>}
|
|
75
|
+
</ClassNames>
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
export default Input
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { Component, Children } from "react"
|
|
2
|
+
import PropTypes from 'prop-types'
|
|
3
|
+
|
|
4
|
+
const DEFAULT_COLUMNS = 2;
|
|
5
|
+
|
|
6
|
+
class Masonry extends Component<any, any> {
|
|
7
|
+
|
|
8
|
+
constructor(props : { [ key: string ] : any }) {
|
|
9
|
+
super(props);
|
|
10
|
+
// Correct scope for when methods are accessed externally
|
|
11
|
+
this.reCalculateColumnCount = this.reCalculateColumnCount.bind(this);
|
|
12
|
+
this.reCalculateColumnCountDebounce = this.reCalculateColumnCountDebounce.bind(this);
|
|
13
|
+
// default state
|
|
14
|
+
let columnCount
|
|
15
|
+
if (this.props && this.props.breakpointCols.default) {
|
|
16
|
+
columnCount = this.props.breakpointCols.default
|
|
17
|
+
} else {
|
|
18
|
+
columnCount = parseInt(this.props.breakpointCols) || DEFAULT_COLUMNS
|
|
19
|
+
}
|
|
20
|
+
this.state = {
|
|
21
|
+
columnCount
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
componentDidMount() {
|
|
26
|
+
this.reCalculateColumnCount();
|
|
27
|
+
// window may not be available in some environments
|
|
28
|
+
if(window) {
|
|
29
|
+
window.addEventListener('resize', this.reCalculateColumnCountDebounce);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
componentDidUpdate() {
|
|
34
|
+
this.reCalculateColumnCount();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
componentWillUnmount() {
|
|
38
|
+
if(window) {
|
|
39
|
+
window.removeEventListener('resize', this.reCalculateColumnCountDebounce);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
reCalculateColumnCountDebounce() {
|
|
44
|
+
if(!window || !window.requestAnimationFrame) { // IE10+
|
|
45
|
+
this.reCalculateColumnCount();
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if(window.cancelAnimationFrame) { // IE10+
|
|
50
|
+
window.cancelAnimationFrame(this._lastRecalculateAnimationFrame);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
_lastRecalculateAnimationFrame = window.requestAnimationFrame(() => {
|
|
56
|
+
this.reCalculateColumnCount();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
reCalculateColumnCount() {
|
|
60
|
+
const windowWidth = window && window.innerWidth || Infinity;
|
|
61
|
+
let breakpointColsObject = this.props.breakpointCols;
|
|
62
|
+
|
|
63
|
+
// Allow passing a single number to `breakpointCols` instead of an object
|
|
64
|
+
if(typeof breakpointColsObject !== 'object') {
|
|
65
|
+
breakpointColsObject = {
|
|
66
|
+
default: parseInt(breakpointColsObject) || DEFAULT_COLUMNS
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
let matchedBreakpoint = Infinity;
|
|
71
|
+
let columns = breakpointColsObject.default || DEFAULT_COLUMNS;
|
|
72
|
+
|
|
73
|
+
for(let breakpoint in breakpointColsObject) {
|
|
74
|
+
const optBreakpoint = parseInt(breakpoint);
|
|
75
|
+
const isCurrentBreakpoint = optBreakpoint > 0 && windowWidth <= optBreakpoint;
|
|
76
|
+
|
|
77
|
+
if(isCurrentBreakpoint && optBreakpoint < matchedBreakpoint) {
|
|
78
|
+
matchedBreakpoint = optBreakpoint;
|
|
79
|
+
columns = breakpointColsObject[breakpoint];
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
columns = Math.max(1, parseInt(columns) || 1);
|
|
84
|
+
|
|
85
|
+
if(this.state.columnCount !== columns) {
|
|
86
|
+
this.setState({
|
|
87
|
+
columnCount: columns
|
|
88
|
+
});
|
|
89
|
+
this.props.onChange && this.props.onChange({ columns: columns });
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
itemsInColumns() {
|
|
94
|
+
const currentColumnCount = this.state.columnCount;
|
|
95
|
+
const itemsInColumns = new Array(currentColumnCount);
|
|
96
|
+
|
|
97
|
+
// Force children to be handled as an array
|
|
98
|
+
const items = Children.toArray(this.props.children)
|
|
99
|
+
|
|
100
|
+
for (let i = 0; i < items.length; i++) {
|
|
101
|
+
const columnIndex = i % currentColumnCount;
|
|
102
|
+
|
|
103
|
+
if(!itemsInColumns[columnIndex]) {
|
|
104
|
+
itemsInColumns[columnIndex] = [];
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
itemsInColumns[columnIndex].push(items[i]);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return itemsInColumns;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
renderColumns() {
|
|
114
|
+
const { column, columnAttrs = {}, columnClassName } = this.props;
|
|
115
|
+
const childrenInColumns = this.itemsInColumns();
|
|
116
|
+
const columnWidth = `${100 / childrenInColumns.length}%`;
|
|
117
|
+
let className = columnClassName;
|
|
118
|
+
|
|
119
|
+
if(className && typeof className !== 'string') {
|
|
120
|
+
this.logDeprecated('The property "columnClassName" requires a string');
|
|
121
|
+
|
|
122
|
+
// This is a deprecated default and will be removed soon.
|
|
123
|
+
if(typeof className === 'undefined') {
|
|
124
|
+
className = 'my-masonry-grid_column';
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const columnAttributes = {
|
|
129
|
+
// NOTE: the column property is undocumented and considered deprecated.
|
|
130
|
+
// It is an alias of the `columnAttrs` property
|
|
131
|
+
...column,
|
|
132
|
+
...columnAttrs,
|
|
133
|
+
style: {
|
|
134
|
+
...columnAttrs.style,
|
|
135
|
+
width: columnWidth
|
|
136
|
+
},
|
|
137
|
+
className
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
return childrenInColumns.map((items, i) => {
|
|
141
|
+
return <div
|
|
142
|
+
{...columnAttributes}
|
|
143
|
+
|
|
144
|
+
key={i}
|
|
145
|
+
>
|
|
146
|
+
{items}
|
|
147
|
+
</div>;
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
logDeprecated(message) {
|
|
152
|
+
console.error('[Masonry]', message);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
render() {
|
|
156
|
+
const {
|
|
157
|
+
// ignored
|
|
158
|
+
children,
|
|
159
|
+
breakpointCols,
|
|
160
|
+
columnClassName,
|
|
161
|
+
columnAttrs,
|
|
162
|
+
column,
|
|
163
|
+
|
|
164
|
+
// used
|
|
165
|
+
className,
|
|
166
|
+
|
|
167
|
+
...rest
|
|
168
|
+
} = this.props;
|
|
169
|
+
|
|
170
|
+
let classNameOutput = className;
|
|
171
|
+
|
|
172
|
+
if(typeof className !== 'string') {
|
|
173
|
+
this.logDeprecated('The property "className" requires a string');
|
|
174
|
+
|
|
175
|
+
// This is a deprecated default and will be removed soon.
|
|
176
|
+
if(typeof className === 'undefined') {
|
|
177
|
+
classNameOutput = 'my-masonry-grid';
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return (
|
|
182
|
+
<div
|
|
183
|
+
{...rest}
|
|
184
|
+
className={classNameOutput}
|
|
185
|
+
>
|
|
186
|
+
{this.renderColumns()}
|
|
187
|
+
</div>
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export default Masonry;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import {
|
|
2
|
+
forwardRef
|
|
3
|
+
} from 'react';
|
|
4
|
+
import PropTypes from 'prop-types'
|
|
5
|
+
import Box from './box'
|
|
6
|
+
|
|
7
|
+
export interface PlaceholderProps {
|
|
8
|
+
width: number|string,
|
|
9
|
+
height: number|string,
|
|
10
|
+
duration?: number,
|
|
11
|
+
bg?: string,
|
|
12
|
+
bgFrom?: string,
|
|
13
|
+
bgTo?: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const calcPlaceholderStyle = (
|
|
17
|
+
width: number|string,
|
|
18
|
+
height: number|string,
|
|
19
|
+
duration = 1600
|
|
20
|
+
) => ({
|
|
21
|
+
backgroundSize: `${parseInt(width.toString()) * 10}px ${height}px`,
|
|
22
|
+
animationDuration: `${(duration / 1000).toFixed(1)}s`,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const Placeholder = forwardRef(({
|
|
26
|
+
width,
|
|
27
|
+
height,
|
|
28
|
+
duration,
|
|
29
|
+
bg,
|
|
30
|
+
bgFrom,
|
|
31
|
+
bgTo
|
|
32
|
+
} : PlaceholderProps, ref) => {
|
|
33
|
+
|
|
34
|
+
const placeholderStyle = calcPlaceholderStyle(width, height, duration);
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<Box
|
|
38
|
+
as={`shimmer`}
|
|
39
|
+
w={width}
|
|
40
|
+
h={height}
|
|
41
|
+
bg={bg || `#f6f7f8`}
|
|
42
|
+
backgroundImage={`linear-gradient(to right, ${bgFrom || `rgb(238, 238, 238)`} 8%, ${bgTo || `rgb(203, 203, 203)`} 18%, ${bgFrom || `rgb(238, 238, 238)`} 33%);`}
|
|
43
|
+
backgroundSize={placeholderStyle.backgroundSize}
|
|
44
|
+
animationDuration={placeholderStyle.animationDuration}
|
|
45
|
+
/>
|
|
46
|
+
)
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
Placeholder.propTypes = {
|
|
50
|
+
width: PropTypes.oneOfType([ PropTypes.number, PropTypes.string ]).isRequired,
|
|
51
|
+
height: PropTypes.oneOfType([ PropTypes.number, PropTypes.string ]).isRequired,
|
|
52
|
+
duration: PropTypes.number,
|
|
53
|
+
bg: PropTypes.string,
|
|
54
|
+
bgFrom: PropTypes.string,
|
|
55
|
+
bgTo: PropTypes.string
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export default Placeholder;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import {
|
|
2
|
+
forwardRef,
|
|
3
|
+
useEffect
|
|
4
|
+
} from 'react';
|
|
5
|
+
import {
|
|
6
|
+
Provider
|
|
7
|
+
} from 'react-redux'
|
|
8
|
+
import appstore from '../redux/store'
|
|
9
|
+
import { setCSSVar, buildCSS } from '../core'
|
|
10
|
+
import { ClassNames } from '@emotion/react'
|
|
11
|
+
|
|
12
|
+
const AppRoot = forwardRef((props : { [ key: string ] : any }, ref) => {
|
|
13
|
+
|
|
14
|
+
if("reducers" in props){
|
|
15
|
+
props.reducers.map(r => appstore['injectReducer'](r.id, r.reducer));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
if('primaryColor' in props) setCSSVar('primary-color', props.primaryColor);
|
|
20
|
+
if('primaryFont' in props) setCSSVar('primary-font', props.primaryFont);
|
|
21
|
+
}, [])
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<Provider store={appstore}>
|
|
25
|
+
<ClassNames>
|
|
26
|
+
{({ css, cx }) => <main className={`${props.as ? props.as : `zuz-app`} ${cx(css`${buildCSS(props)} &:hover {${buildCSS(props.hover || {})}} &:active {${buildCSS(props.active || {})}}`)}`}>{props.children}</main>}
|
|
27
|
+
</ClassNames>
|
|
28
|
+
</Provider>
|
|
29
|
+
)
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
export default AppRoot;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FC,
|
|
3
|
+
LegacyRef,
|
|
4
|
+
forwardRef,
|
|
5
|
+
useRef,
|
|
6
|
+
useEffect
|
|
7
|
+
} from 'react';
|
|
8
|
+
import { ClassNames } from '@emotion/react'
|
|
9
|
+
import { buildCSS } from '../core'
|
|
10
|
+
import { nanoid } from 'nanoid';
|
|
11
|
+
import useStore from "../hooks/useStore";
|
|
12
|
+
import useDispatch from "../hooks/useDispatch";
|
|
13
|
+
import {
|
|
14
|
+
UPDATE_FORM_FIELD
|
|
15
|
+
} from '../actions'
|
|
16
|
+
import { STORE_FORM_KEY } from '../context/AppProvider'
|
|
17
|
+
|
|
18
|
+
const Select = forwardRef((props : { [ key: string ] : any }, ref : LegacyRef<HTMLHeadingElement>) => {
|
|
19
|
+
|
|
20
|
+
const {
|
|
21
|
+
as,
|
|
22
|
+
onChange,
|
|
23
|
+
name,
|
|
24
|
+
form,
|
|
25
|
+
touched,
|
|
26
|
+
options,
|
|
27
|
+
defaultValue
|
|
28
|
+
} = props;
|
|
29
|
+
|
|
30
|
+
const _ref = useRef();
|
|
31
|
+
const dispatch = useDispatch(STORE_FORM_KEY)
|
|
32
|
+
const { forms } = useStore(state => state[STORE_FORM_KEY], false)
|
|
33
|
+
|
|
34
|
+
const _defaultCSS = `width: 100%;border-radius: var(--radius-base);padding-left: 4px;padding-right: 4px;border-style: solid;border-width: 1px;border-color: var(--colors-gray-200);`;
|
|
35
|
+
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
dispatch( dispatch( UPDATE_FORM_FIELD( form || 'orphan', name,
|
|
38
|
+
defaultValue && defaultValue != null && defaultValue != "" && defaultValue != undefined ? defaultValue : options[0]?.value || '-1',
|
|
39
|
+
forms ) ) );
|
|
40
|
+
}, [])
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<ClassNames>
|
|
44
|
+
{({ css, cx }) => <select
|
|
45
|
+
onChange={e => {
|
|
46
|
+
let val = e.currentTarget.value;
|
|
47
|
+
dispatch( dispatch( UPDATE_FORM_FIELD( form || 'orphan', name, val, forms ) ) );
|
|
48
|
+
onChange && onChange(val)
|
|
49
|
+
}}
|
|
50
|
+
onFocus={ e => touched == false && dispatch( UPDATE_FORM_FIELD( form || 'orphan', `touched`, true, forms ) ) }
|
|
51
|
+
onBlur={e => {
|
|
52
|
+
if(touched){}
|
|
53
|
+
}}
|
|
54
|
+
name={name || nanoid()}
|
|
55
|
+
className={`${as ? as : ``} ${cx(css`${_defaultCSS}${buildCSS(props)}&:hover {${buildCSS(props.hover || {})}}`)}`}
|
|
56
|
+
ref={_ref}>{options?.map(o => <option key={`select-${name}-option-${o.value}`} value={o.value}>{o.label}</option>)}</select>}
|
|
57
|
+
</ClassNames>
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
export default Select
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FC,
|
|
3
|
+
forwardRef
|
|
4
|
+
} from 'react';
|
|
5
|
+
import Box from './box'
|
|
6
|
+
|
|
7
|
+
interface Props {
|
|
8
|
+
w?: string|number,
|
|
9
|
+
h?: string|number
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const Spacer : FC<Props> = ({
|
|
13
|
+
w, h
|
|
14
|
+
}) => {
|
|
15
|
+
return (
|
|
16
|
+
<Box as={`spacer`} w={w || 0} h={h || 0} />
|
|
17
|
+
)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default Spacer;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import Box from './box'
|
|
3
|
+
import PropTypes from 'prop-types'
|
|
4
|
+
|
|
5
|
+
const Spinner = (props : any) => {
|
|
6
|
+
|
|
7
|
+
return (
|
|
8
|
+
<Box
|
|
9
|
+
rel
|
|
10
|
+
w={props.size}
|
|
11
|
+
h={props.size}
|
|
12
|
+
zIndex={`1`}
|
|
13
|
+
useSelect={`none`}>
|
|
14
|
+
<Box abs as={`spinner rotating`} animationDirection={`reverse`} animationDuration={typeof props.s1 == `string` ? props.s1 : `${props.s1}s`} w={props.size} r={props.radius} h={props.size} bg={props.color} opacity={0.2} />
|
|
15
|
+
<Box abs as={`spinner rotating`} animationDuration={typeof props.s2 == `string` ? props.s2 : `${props.s2}s`} w={props.size} r={props.radius} h={props.size} bg={props.color} opacity={0.5} />
|
|
16
|
+
</Box>
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
Spinner.defaultProps = {
|
|
21
|
+
size: 30,
|
|
22
|
+
radius: 4,
|
|
23
|
+
color: `black`,
|
|
24
|
+
s1: `5s`,
|
|
25
|
+
s2: `1s`
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
Spinner.propTypes = {
|
|
29
|
+
size: PropTypes.number.isRequired,
|
|
30
|
+
color: PropTypes.string,
|
|
31
|
+
radius: PropTypes.number,
|
|
32
|
+
s1: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
|
33
|
+
s2: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export default Spinner;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FC,
|
|
3
|
+
LegacyRef,
|
|
4
|
+
forwardRef,
|
|
5
|
+
HTMLAttributes
|
|
6
|
+
} from 'react';
|
|
7
|
+
import { ClassNames } from '@emotion/react'
|
|
8
|
+
import { buildCSS } from '../core'
|
|
9
|
+
|
|
10
|
+
const Text = forwardRef((props : { [ key: string ] : any }, ref : LegacyRef<HTMLParagraphElement>) => {
|
|
11
|
+
|
|
12
|
+
const {
|
|
13
|
+
children,
|
|
14
|
+
as
|
|
15
|
+
} = props;
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<ClassNames>
|
|
19
|
+
{({ css, cx }) => <p
|
|
20
|
+
className={`${as ? `${as} ` : ``}${cx(css`${buildCSS(props)}`)}`}
|
|
21
|
+
ref={ref}
|
|
22
|
+
>{props.html ? <span dangerouslySetInnerHTML={{ __html: props.html }} /> : children}</p>}
|
|
23
|
+
</ClassNames>
|
|
24
|
+
)
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
export default Text;
|