@zuzjs/ui 0.2.4 → 0.2.5
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 +78 -4
- 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/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 +52 -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 +32 -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
package/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# zuzjs
|
package/dist/index.js
CHANGED
|
@@ -251,6 +251,7 @@ const cssProps = {
|
|
|
251
251
|
"@charset": "@charset",
|
|
252
252
|
"clear": "clear",
|
|
253
253
|
"clip": "clip",
|
|
254
|
+
"clipPath": "clip-path",
|
|
254
255
|
"color": "color",
|
|
255
256
|
"columnCount": "column-count",
|
|
256
257
|
"columnFill": "column-fill",
|
|
@@ -555,12 +556,12 @@ const UPDATE_FORM_FIELD = (formName, field, value, forms) => {
|
|
|
555
556
|
};
|
|
556
557
|
|
|
557
558
|
const Input = forwardRef((props, ref) => {
|
|
558
|
-
const { as, accept, multiple, onChange, type, tag, placeholder, name, form, touched, onSubmit, defaultValue } = props;
|
|
559
|
+
const { as, accept, multiple, onChange, type, tag, placeholder, name, form, touched, onSubmit, defaultValue, fref } = props;
|
|
559
560
|
const dispatch = useDispatch(STORE_FORM_KEY);
|
|
560
561
|
const { forms } = useStore(state => state[STORE_FORM_KEY], false);
|
|
561
562
|
let Tag = tag || 'input';
|
|
562
563
|
const El = Tag;
|
|
563
|
-
const _ref = useRef();
|
|
564
|
+
const _ref = fref || useRef();
|
|
564
565
|
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);`;
|
|
565
566
|
return (jsx(ClassNames, { children: ({ css, cx }) => jsx(El, { type: type || `text`, placeholder: placeholder || undefined, name: name || nanoid(), multiple: type == 'file' ? multiple : undefined, accept: accept || `*`, className: `${as ? `${as} ` : ``}f ${cx(css `${_defaultCSS}${buildCSS(props)}&:hover {${buildCSS(props.hover || {})}} &:focus {${buildCSS(props.focus || {})}}`)}`, ref: _ref, defaultValue: defaultValue || ``, onKeyUp: (e) => {
|
|
566
567
|
let k = e['keyCode'] || ['which'];
|
|
@@ -572,7 +573,7 @@ const Input = forwardRef((props, ref) => {
|
|
|
572
573
|
e.currentTarget.files
|
|
573
574
|
: e.currentTarget.value;
|
|
574
575
|
dispatch(dispatch(UPDATE_FORM_FIELD(form || 'orphan', name, val == "" ? null : val, forms)));
|
|
575
|
-
onChange && onChange(
|
|
576
|
+
onChange && onChange(val == "" ? null : val);
|
|
576
577
|
}, onBlur: e => {
|
|
577
578
|
}, onFocus: e => touched == false && dispatch(UPDATE_FORM_FIELD(form || 'orphan', `touched`, true, forms)) }) }));
|
|
578
579
|
});
|
|
@@ -909,6 +910,79 @@ const Button = forwardRef((props, ref) => {
|
|
|
909
910
|
} }));
|
|
910
911
|
});
|
|
911
912
|
|
|
913
|
+
const patterns = {
|
|
914
|
+
route: [/^.*\/src\/pages\/|\.(jsx|tsx)$/g, ''],
|
|
915
|
+
splat: [/\[\.{3}\w+\]/g, '*'],
|
|
916
|
+
param: [/\[([^\]]+)\]/g, ':$1'],
|
|
917
|
+
slash: [/^index$|\./g, '/'],
|
|
918
|
+
optional: [/^-(:?[\w-]+)/, '$1?'],
|
|
919
|
+
};
|
|
920
|
+
const generatePreservedRoutes = (files) => {
|
|
921
|
+
return Object.keys(files).reduce((routes, key) => {
|
|
922
|
+
const path = key.replace(...patterns.route);
|
|
923
|
+
return Object.assign(Object.assign({}, routes), { [path]: files[key] });
|
|
924
|
+
}, {});
|
|
925
|
+
};
|
|
926
|
+
const generateRegularRoutes = (files, buildRoute) => {
|
|
927
|
+
const filteredRoutes = Object.keys(files).filter((key) => !key.includes('/_') || /_layout\.(jsx|tsx)$/.test(key));
|
|
928
|
+
return filteredRoutes.reduce((routes, key) => {
|
|
929
|
+
const module = files[key];
|
|
930
|
+
const route = Object.assign({ id: key.replace(...patterns.route) }, buildRoute(module, key));
|
|
931
|
+
const segments = key
|
|
932
|
+
.replace(...patterns.route)
|
|
933
|
+
.replace(...patterns.splat)
|
|
934
|
+
.replace(...patterns.param)
|
|
935
|
+
.split('/')
|
|
936
|
+
.filter(Boolean);
|
|
937
|
+
segments.reduce((parent, segment, index) => {
|
|
938
|
+
var _a, _b;
|
|
939
|
+
const path = segment.replace(...patterns.slash).replace(...patterns.optional);
|
|
940
|
+
const root = index === 0;
|
|
941
|
+
const leaf = index === segments.length - 1 && segments.length > 1;
|
|
942
|
+
const node = !root && !leaf;
|
|
943
|
+
const layout = segment === '_layout';
|
|
944
|
+
const group = /\(\w+\)/.test(path);
|
|
945
|
+
const insert = /^\w|\//.test(path) ? 'unshift' : 'push';
|
|
946
|
+
if (root) {
|
|
947
|
+
const last = segments.length === 1;
|
|
948
|
+
if (last) {
|
|
949
|
+
routes.push(Object.assign({ path }, route));
|
|
950
|
+
return parent;
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
if (root || node) {
|
|
954
|
+
const current = root ? routes : parent.children;
|
|
955
|
+
const found = current === null || current === void 0 ? void 0 : current.find((route) => { var _a, _b; return route.path === path || ((_b = (_a = route.id) === null || _a === void 0 ? void 0 : _a.split('@')) === null || _b === void 0 ? void 0 : _b[0]) === path; });
|
|
956
|
+
const props = group ? ((route === null || route === void 0 ? void 0 : route.component) ? { id: path, path: '/' } : { id: path }) : { path };
|
|
957
|
+
if (found)
|
|
958
|
+
(_a = found.children) !== null && _a !== void 0 ? _a : (found.children = []);
|
|
959
|
+
else
|
|
960
|
+
current === null || current === void 0 ? void 0 : current[insert](Object.assign(Object.assign({}, props), { children: [] }));
|
|
961
|
+
return found || (current === null || current === void 0 ? void 0 : current[insert === 'unshift' ? 0 : current.length - 1]);
|
|
962
|
+
}
|
|
963
|
+
if (layout) {
|
|
964
|
+
return Object.assign(parent, Object.assign(Object.assign({}, route), { id: `${parent.id || parent.path}@${route.id}` }));
|
|
965
|
+
}
|
|
966
|
+
if (leaf) {
|
|
967
|
+
(_b = parent === null || parent === void 0 ? void 0 : parent.children) === null || _b === void 0 ? void 0 : _b[insert]((route === null || route === void 0 ? void 0 : route.index) ? route : Object.assign({ path }, route));
|
|
968
|
+
}
|
|
969
|
+
return parent;
|
|
970
|
+
}, {});
|
|
971
|
+
return routes;
|
|
972
|
+
}, []);
|
|
973
|
+
};
|
|
974
|
+
const generateModalRoutes = (files) => {
|
|
975
|
+
return Object.keys(files).reduce((modals, key) => {
|
|
976
|
+
var _a;
|
|
977
|
+
const path = key
|
|
978
|
+
.replace(...patterns.route)
|
|
979
|
+
.replace(/\+|\(\w+\)\//g, '')
|
|
980
|
+
.replace(/(\/)?index/g, '')
|
|
981
|
+
.replace(/\./g, '/');
|
|
982
|
+
return Object.assign(Object.assign({}, modals), { [`/${path}`]: (_a = files[key]) === null || _a === void 0 ? void 0 : _a.default });
|
|
983
|
+
}, {});
|
|
984
|
+
};
|
|
985
|
+
|
|
912
986
|
const makeCSSValue = (k, v, o) => {
|
|
913
987
|
let ignore = cssPropsIgnore.indexOf(o) == -1;
|
|
914
988
|
if (k in cssPropsDirect && ignore == true) {
|
|
@@ -1349,4 +1423,4 @@ const Header = forwardRef((props, ref) => {
|
|
|
1349
1423
|
return (jsx(Fragment, { children: buildComponent(data) }));
|
|
1350
1424
|
});
|
|
1351
1425
|
|
|
1352
|
-
export { App, Component as Block, Box, Button, Checkbox, ContextMenu, Cover, Form, Header, Heading, Icon, Image, Input, Placeholder, AppProvider as Provider, Select, Spacer, Spinner, Text, Toaster, Tweet, addProps, addScript, buildCSS, buildFormData, byId, byName, createSlice, el, filterHTMLProps, filterStyleProps, getCookie, getUriParams, grab, isEmail, isIPv4, isUrl, randstr, removeCookie, rgb2hex, setCSSVar, setCookie, shuffleArray, ucfirst, useDevice, useDispatch, useImage, useResizeObserver, useStore, useTheme, useToast, uuid };
|
|
1426
|
+
export { App, Component as Block, Box, Button, Checkbox, ContextMenu, Cover, Form, Header, Heading, Icon, Image, Input, Placeholder, AppProvider as Provider, Select, Spacer, Spinner, Text, Toaster, Tweet, addProps, addScript, buildCSS, buildFormData, byId, byName, createSlice, el, filterHTMLProps, filterStyleProps, generateModalRoutes, generatePreservedRoutes, generateRegularRoutes, getCookie, getUriParams, grab, isEmail, isIPv4, isUrl, randstr, removeCookie, rgb2hex, setCSSVar, setCookie, shuffleArray, ucfirst, useDevice, useDispatch, useImage, useResizeObserver, useStore, useTheme, useToast, uuid };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zuzjs/ui",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -34,12 +34,14 @@
|
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@rollup/plugin-commonjs": "^24.0.1",
|
|
36
36
|
"postcss": "^8.4.21",
|
|
37
|
+
"react-router-dom": "^6.14.2",
|
|
37
38
|
"rimraf": "^4.4.1",
|
|
38
39
|
"rollup": "^3.20.2",
|
|
39
40
|
"rollup-plugin-livereload": "^2.0.5",
|
|
40
41
|
"rollup-plugin-scss": "^4.0.0",
|
|
41
42
|
"rollup-plugin-typescript2": "^0.34.1",
|
|
42
43
|
"rollup-plugin-uglify": "^6.0.4",
|
|
43
|
-
"sass": "^1.60.0"
|
|
44
|
+
"sass": "^1.60.0",
|
|
45
|
+
"vite-plugin-environment": "^1.1.3"
|
|
44
46
|
}
|
|
45
47
|
}
|
|
File without changes
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { UNDO } from './undo'
|
|
2
|
+
import { REDO } from './redo'
|
|
3
|
+
import { RESET } from './reset'
|
|
4
|
+
|
|
5
|
+
export const ADD_FORM = (name, fields, forms) => ({
|
|
6
|
+
forms: {
|
|
7
|
+
...forms,
|
|
8
|
+
[name] : { touched: false, loading: false, ...fields }
|
|
9
|
+
}
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
export const UPDATE_FORM_FIELD = (formName, field, value, forms) => {
|
|
13
|
+
if(forms[formName]){
|
|
14
|
+
let _forms = {
|
|
15
|
+
...forms
|
|
16
|
+
}
|
|
17
|
+
_forms[formName][field] = value;
|
|
18
|
+
return {
|
|
19
|
+
forms: _forms
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return {}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export {
|
|
26
|
+
UNDO,
|
|
27
|
+
REDO,
|
|
28
|
+
RESET
|
|
29
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const REDO = 'REDO';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const RESET = 'RESET';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const UNDO = 'UNDO';
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import {
|
|
2
|
+
forwardRef,
|
|
3
|
+
useEffect
|
|
4
|
+
} from 'react';
|
|
5
|
+
import { setCSSVar, buildCSS } from '../core'
|
|
6
|
+
import { Provider } from '../context'
|
|
7
|
+
import { ClassNames } from '@emotion/react'
|
|
8
|
+
import { useStore } from '../hooks'
|
|
9
|
+
|
|
10
|
+
const AppMain = forwardRef((props : { [ key: string ] : any }, ref) => {
|
|
11
|
+
|
|
12
|
+
// const { dispatch } = useStore()
|
|
13
|
+
|
|
14
|
+
// if("theme" in props && !theme){
|
|
15
|
+
// dispatch(setTheme(props.theme));
|
|
16
|
+
// }
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<ClassNames>
|
|
20
|
+
{({ 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>}
|
|
21
|
+
</ClassNames>
|
|
22
|
+
)
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
const App = forwardRef((props : { [ key: string ] : any }, ref) => {
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<Provider>
|
|
29
|
+
<AppMain />
|
|
30
|
+
</Provider>
|
|
31
|
+
)
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
export default App
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import {
|
|
2
|
+
forwardRef,
|
|
3
|
+
useEffect
|
|
4
|
+
} from 'react';
|
|
5
|
+
import { ClassNames } from '@emotion/react'
|
|
6
|
+
import { buildCSS } from '../core'
|
|
7
|
+
|
|
8
|
+
const Box = forwardRef((props : { [ key: string ] : any }, ref) => {
|
|
9
|
+
|
|
10
|
+
const _noClick = () => {}
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<ClassNames>
|
|
14
|
+
{({ css, cx }) => <div
|
|
15
|
+
id={props.id || undefined}
|
|
16
|
+
onClick={props.onClick || _noClick}
|
|
17
|
+
className={`${props.as ? `${props.as} ` : ``}${cx(css`${buildCSS(props)} &:hover {${buildCSS(props.hover || {})}} &:active {${buildCSS(props.active || {})}}`)}`}
|
|
18
|
+
ref={props.bref || ref}>{props.html ? <span dangerouslySetInnerHTML={{ __html: props.html }} /> : props.children}</div>}
|
|
19
|
+
</ClassNames>
|
|
20
|
+
)
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
export default Box;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import React, {
|
|
2
|
+
forwardRef,
|
|
3
|
+
LegacyRef
|
|
4
|
+
} from 'react';
|
|
5
|
+
import { ClassNames } from '@emotion/react'
|
|
6
|
+
import {
|
|
7
|
+
buildCSS,
|
|
8
|
+
filterStyleProps
|
|
9
|
+
} from '../core'
|
|
10
|
+
import { useStore } from '../hooks'
|
|
11
|
+
import { STORE_FORM_KEY } from '../context/AppProvider'
|
|
12
|
+
const Button = forwardRef((props: { [ key: string ] : any }, ref : LegacyRef<HTMLButtonElement>) => {
|
|
13
|
+
|
|
14
|
+
const { forms } = useStore(state => state[STORE_FORM_KEY], false);
|
|
15
|
+
const _otherProps = {}
|
|
16
|
+
if(props.html){
|
|
17
|
+
_otherProps['dangerouslySetInnerHTML'] = { __html: props.html }
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<ClassNames>
|
|
22
|
+
{({ css, cx }) => {
|
|
23
|
+
return (
|
|
24
|
+
<button
|
|
25
|
+
title={"title" in props ? props.title : undefined}
|
|
26
|
+
type={props.type}
|
|
27
|
+
className={`button${props.as ? ` ${props.as}` : ``} ${cx(css`
|
|
28
|
+
padding: 5px 10px;
|
|
29
|
+
border-radius: 2px;
|
|
30
|
+
${buildCSS(props)} &:hover {${buildCSS(props.hover || {})}} &:active {${buildCSS(props.active || {})}}`)}`}
|
|
31
|
+
ref={ref}
|
|
32
|
+
onClick={e => {
|
|
33
|
+
if(props.form && props.type && props.type == 'submit'){
|
|
34
|
+
props.onSubmit(forms[props.form]);
|
|
35
|
+
}else{
|
|
36
|
+
props.onClick ? props.onClick(e) : () => console.warn('onClick Missing')
|
|
37
|
+
}
|
|
38
|
+
}} disabled={props.disabled || false} >{props.html ? <span dangerouslySetInnerHTML={{ __html: props.html }} /> : props.children}</button>
|
|
39
|
+
)
|
|
40
|
+
}}
|
|
41
|
+
</ClassNames>
|
|
42
|
+
)
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
export default Button;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types'
|
|
3
|
+
import { nanoid } from 'nanoid'
|
|
4
|
+
import Box from './box'
|
|
5
|
+
import Button from './button'
|
|
6
|
+
import useTheme from '../hooks/useTheme'
|
|
7
|
+
import useDispatch from '../hooks/useDispatch'
|
|
8
|
+
import useStore from '../hooks/useStore'
|
|
9
|
+
import { STORE_FORM_KEY } from '../context/AppProvider'
|
|
10
|
+
import {
|
|
11
|
+
UPDATE_FORM_FIELD
|
|
12
|
+
} from '../actions'
|
|
13
|
+
import { ClassNames } from '@emotion/react'
|
|
14
|
+
|
|
15
|
+
function Checkbox(props) {
|
|
16
|
+
|
|
17
|
+
const {
|
|
18
|
+
checked,
|
|
19
|
+
as,
|
|
20
|
+
name,
|
|
21
|
+
form,
|
|
22
|
+
touched,
|
|
23
|
+
onChange
|
|
24
|
+
} = props;
|
|
25
|
+
|
|
26
|
+
const [_checked, setChecked] = useState(checked || false)
|
|
27
|
+
const theme = useTheme();
|
|
28
|
+
|
|
29
|
+
const dispatch = useDispatch(STORE_FORM_KEY)
|
|
30
|
+
const { forms } = useStore(state => state[STORE_FORM_KEY], false)
|
|
31
|
+
|
|
32
|
+
const switchCheck = useCallback(() => {
|
|
33
|
+
let nextVal = !_checked;
|
|
34
|
+
onChange && onChange(nextVal)
|
|
35
|
+
setChecked(nextVal)
|
|
36
|
+
dispatch( dispatch( UPDATE_FORM_FIELD( form || 'orphan', name, nextVal, forms ) ) );
|
|
37
|
+
}, [_checked])
|
|
38
|
+
|
|
39
|
+
const defaultCSS = `cursor: pointer;&:before {
|
|
40
|
+
background: ${!_checked ? `transparent` : theme.color} !important;
|
|
41
|
+
}`
|
|
42
|
+
|
|
43
|
+
const _name = useMemo(() => name || nanoid(), [name])
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<ClassNames>
|
|
47
|
+
{({ css, cx }) => <>
|
|
48
|
+
<input
|
|
49
|
+
onChange={switchCheck}
|
|
50
|
+
id={`zuz${_name}`}
|
|
51
|
+
// className={`${_checked ? 'y' : 'n'} ${as ? ` ${as} ` : ``}f ${cx(css`opacity: 0;position: absolute;&:checked {${defaultCSSChecked}}`)}`}
|
|
52
|
+
className={`zuz-checkbox`}
|
|
53
|
+
name={_name}
|
|
54
|
+
type={`checkbox`}
|
|
55
|
+
value={`checked`}
|
|
56
|
+
/>
|
|
57
|
+
<label
|
|
58
|
+
className={`${as ? `${as} ` : ``}f ${cx(css`${defaultCSS}`)}`}
|
|
59
|
+
htmlFor={`zuz${_name}`} />
|
|
60
|
+
</>}
|
|
61
|
+
</ClassNames>
|
|
62
|
+
// <Button
|
|
63
|
+
// overflow={`hidden`}
|
|
64
|
+
// name={name || nanoid()}
|
|
65
|
+
// onClick={switchCheck}
|
|
66
|
+
// w={38} h={22} r={20} bg={`#ddd`} rel>
|
|
67
|
+
// <Box w={38} h={22} anim={`0.2`} abs top={0} r={20} left={0} transform={`translateX(${_checked ? 0 : -16}px)`} bg={theme.color}>
|
|
68
|
+
// <Box w={18} h={18} abs right={2} top={2} bg={`#fff`} r={20} boxShadow={`0px 0px 0px 5px ${_checked ? theme.color : `#ddd`}`} />
|
|
69
|
+
// </Box>
|
|
70
|
+
// </Button>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export default Checkbox;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import React, {
|
|
2
|
+
forwardRef
|
|
3
|
+
} from 'react';
|
|
4
|
+
import styled from '@emotion/styled'
|
|
5
|
+
import { css } from '@emotion/react'
|
|
6
|
+
import {
|
|
7
|
+
buildCSS,
|
|
8
|
+
filterHTMLProps
|
|
9
|
+
} from '../core'
|
|
10
|
+
|
|
11
|
+
// const CoreBlock = styled.section`display: block;`
|
|
12
|
+
// const buildComponent = (props: any) => Block.withComponent(props.for || `div`)`${buildCSS(props)}`
|
|
13
|
+
|
|
14
|
+
const Component = forwardRef((props: any, ref: any) => {
|
|
15
|
+
|
|
16
|
+
const Tag = props.for;
|
|
17
|
+
const Block = (
|
|
18
|
+
typeof props.for == 'string' ?
|
|
19
|
+
styled[props.for || `div`] : Tag
|
|
20
|
+
)`${buildCSS(props)}`;
|
|
21
|
+
// const Block = styled.`${buildCSS(props)}`;
|
|
22
|
+
// const Block = CoreBlock.withComponent(props.for)`background: red`
|
|
23
|
+
// console.log(props)
|
|
24
|
+
// console.log(Styles)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
// return <button>{props.children}</button>
|
|
28
|
+
return <Block className={props.as || ``} {...filterHTMLProps(props)} />
|
|
29
|
+
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
export default Component;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FC,
|
|
3
|
+
LegacyRef,
|
|
4
|
+
forwardRef,
|
|
5
|
+
useRef,
|
|
6
|
+
SyntheticEvent,
|
|
7
|
+
} from 'react';
|
|
8
|
+
import Box from './box'
|
|
9
|
+
import Button from './button'
|
|
10
|
+
|
|
11
|
+
const ContextMenu = forwardRef((props : { [ key: string ] : any }, ref : LegacyRef<HTMLHeadingElement>) => {
|
|
12
|
+
|
|
13
|
+
const {
|
|
14
|
+
as,
|
|
15
|
+
size,
|
|
16
|
+
color,
|
|
17
|
+
hover,
|
|
18
|
+
pos,
|
|
19
|
+
items
|
|
20
|
+
} = props;
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<Box
|
|
24
|
+
hover={hover || {}}
|
|
25
|
+
flex
|
|
26
|
+
fixed
|
|
27
|
+
top={pos?.y || 0}
|
|
28
|
+
left={pos?.x || 0}
|
|
29
|
+
bref={ref}
|
|
30
|
+
as={`contextmenu-${as}`}
|
|
31
|
+
ai={`c`}
|
|
32
|
+
jc={`c`}
|
|
33
|
+
size={size || 24}
|
|
34
|
+
color={color || `#111111`}
|
|
35
|
+
>
|
|
36
|
+
{items && items.map((m, i) => <Button
|
|
37
|
+
key={`cm-${i}-${m.id}`}
|
|
38
|
+
onClick={m.on ? m.on : () => {}}>{m.label}</Button>)}
|
|
39
|
+
</Box>
|
|
40
|
+
)
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
export default ContextMenu;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import Box from './box'
|
|
3
|
+
import Spinner from './spinner'
|
|
4
|
+
import Heading from './heading'
|
|
5
|
+
import PropTypes from 'prop-types'
|
|
6
|
+
|
|
7
|
+
const Cover = (props) => {
|
|
8
|
+
|
|
9
|
+
return (
|
|
10
|
+
<Box key={`cover-cloud`} abs fill
|
|
11
|
+
bgFilter={props.backdrop ? `saturate(${props.backdrop.saturate}%) blur(${props.backdrop.blur}px)` : undefined}
|
|
12
|
+
zIndex={`2`}
|
|
13
|
+
bg={props.bg}>
|
|
14
|
+
<Box key={`cover-shadow`} abs abc aic jcc flex dir={`cols`} gap={20}>
|
|
15
|
+
<Spinner key={`cover-spinner`} />
|
|
16
|
+
{props.label && <Heading key={`cover-label`} size={16} as={`f`} opacity={0.7}>{props.label}</Heading>}
|
|
17
|
+
</Box>
|
|
18
|
+
</Box>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
Cover.defaultProps = {
|
|
23
|
+
bg: `rgba(0,0,0,0.5)`,
|
|
24
|
+
backdrop: { saturate: 80, blur: 10 },
|
|
25
|
+
label: null
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
Cover.propTypes = {
|
|
29
|
+
bg: PropTypes.string,
|
|
30
|
+
backdrop: PropTypes.object,
|
|
31
|
+
label: PropTypes.string,
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export default Cover;
|
|
@@ -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;
|