@zuzjs/ui 0.2.8 → 0.3.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.
- package/dist/index.js +266 -78
- package/dist/styles.css +71 -0
- package/package.json +1 -1
- package/src/comps/box.tsx +5 -1
- package/src/comps/button.tsx +2 -1
- package/src/comps/contextmenu.tsx +1 -3
- package/src/comps/image.tsx +15 -7
- package/src/comps/input.tsx +7 -2
- package/src/comps/toaster.tsx +9 -7
- package/src/context/AppProvider.tsx +8 -3
- package/src/context/store/lang.tsx +26 -0
- package/src/context/store/theme.tsx +15 -14
- package/src/core/defaultTheme.ts +14 -13
- package/src/core/index.ts +74 -2
- package/src/hooks/index.tsx +2 -1
- package/src/hooks/useContextMenu.tsx +88 -0
- package/src/hooks/useImage.tsx +75 -49
- package/src/hooks/useLang.tsx +9 -0
- package/src/index.tsx +2 -0
- package/src/scss/props.scss +10 -0
- package/src/scss/style.scss +27 -0
package/dist/index.js
CHANGED
|
@@ -6,6 +6,8 @@ import Cookies from 'js-cookie';
|
|
|
6
6
|
import axios from 'axios';
|
|
7
7
|
import { nanoid } from 'nanoid';
|
|
8
8
|
import { ClassNames } from '@emotion/react';
|
|
9
|
+
import ReactDOM from 'react-dom/client';
|
|
10
|
+
export { Link } from 'react-router-dom';
|
|
9
11
|
import styled from '@emotion/styled';
|
|
10
12
|
|
|
11
13
|
const AppContext = createContext({});
|
|
@@ -59,25 +61,27 @@ class AppTheme {
|
|
|
59
61
|
_AppTheme_darkTheme.set(this, void 0);
|
|
60
62
|
this.get = () => {
|
|
61
63
|
let self = this;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
// }else
|
|
71
|
-
if (__classPrivateFieldGet(self, _AppTheme_mode, "f") === "light") {
|
|
72
|
-
return __classPrivateFieldGet(self, _AppTheme_lightTheme, "f");
|
|
64
|
+
if (__classPrivateFieldGet(self, _AppTheme_mode, "f") === "auto") {
|
|
65
|
+
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
|
|
66
|
+
__classPrivateFieldSet(self, _AppTheme_mode, event.matches ? "dark" : "light", "f");
|
|
67
|
+
__classPrivateFieldGet(self, _AppTheme_listen, "f").call(self, __classPrivateFieldGet(self, _AppTheme_mode, "f"));
|
|
68
|
+
});
|
|
69
|
+
return window.matchMedia &&
|
|
70
|
+
window.matchMedia('(prefers-color-scheme: dark)').matches ?
|
|
71
|
+
__classPrivateFieldGet(self, _AppTheme_darkTheme, "f") : __classPrivateFieldGet(self, _AppTheme_lightTheme, "f");
|
|
73
72
|
}
|
|
74
|
-
else
|
|
75
|
-
|
|
73
|
+
else {
|
|
74
|
+
if (__classPrivateFieldGet(self, _AppTheme_mode, "f") === "light") {
|
|
75
|
+
return __classPrivateFieldGet(self, _AppTheme_lightTheme, "f");
|
|
76
|
+
}
|
|
77
|
+
else if (__classPrivateFieldGet(self, _AppTheme_mode, "f") === "dark") {
|
|
78
|
+
return __classPrivateFieldGet(self, _AppTheme_darkTheme, "f");
|
|
79
|
+
}
|
|
76
80
|
}
|
|
77
81
|
};
|
|
78
82
|
const conf = _conf || {};
|
|
79
83
|
__classPrivateFieldSet(this, _AppTheme_listen, "listen" in conf ? conf.listen : (mod) => { console.log(`Theme switched to ${mod}`); }, "f");
|
|
80
|
-
__classPrivateFieldSet(this, _AppTheme_mode, conf.mode || "auto", "f");
|
|
84
|
+
__classPrivateFieldSet(this, _AppTheme_mode, conf.mode || conf.theme.mode || "auto", "f");
|
|
81
85
|
__classPrivateFieldSet(this, _AppTheme_lightTheme, Object.assign({
|
|
82
86
|
//CORE
|
|
83
87
|
tag: "light", dark: false, primary: '#edeef5', secondary: '#f9f9f9', textColor: '#111111' }, ("theme" in conf && "light" in conf.theme ? Object.assign({}, conf.theme.light) : {})), "f");
|
|
@@ -88,6 +92,26 @@ class AppTheme {
|
|
|
88
92
|
}
|
|
89
93
|
_AppTheme_mode = new WeakMap(), _AppTheme_listen = new WeakMap(), _AppTheme_lightTheme = new WeakMap(), _AppTheme_darkTheme = new WeakMap();
|
|
90
94
|
|
|
95
|
+
var _AppLang_mode, _AppLang_listen, _AppLang_lang;
|
|
96
|
+
class AppLang {
|
|
97
|
+
constructor(_conf) {
|
|
98
|
+
_AppLang_mode.set(this, void 0);
|
|
99
|
+
_AppLang_listen.set(this, void 0);
|
|
100
|
+
_AppLang_lang.set(this, void 0);
|
|
101
|
+
this.get = () => {
|
|
102
|
+
let self = this;
|
|
103
|
+
return __classPrivateFieldGet(self, _AppLang_lang, "f");
|
|
104
|
+
};
|
|
105
|
+
const conf = _conf || {};
|
|
106
|
+
__classPrivateFieldSet(this, _AppLang_listen, "listen" in conf ? conf.listen : (mod) => { console.log(`Lang switched to ${mod}`); }, "f");
|
|
107
|
+
__classPrivateFieldSet(this, _AppLang_mode, conf.mode || "en", "f");
|
|
108
|
+
__classPrivateFieldSet(this, _AppLang_lang, Object.assign({
|
|
109
|
+
//CORE
|
|
110
|
+
tag: "en" }, ("lang" in conf ? Object.assign({}, conf.lang) : {})), "f");
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
_AppLang_mode = new WeakMap(), _AppLang_listen = new WeakMap(), _AppLang_lang = new WeakMap();
|
|
114
|
+
|
|
91
115
|
let isMounted = true;
|
|
92
116
|
const STORE_KEY = `__zuzjs`;
|
|
93
117
|
const STORE_FORM_KEY = `${STORE_KEY}forms`;
|
|
@@ -102,14 +126,14 @@ const defaultState = {
|
|
|
102
126
|
}
|
|
103
127
|
};
|
|
104
128
|
const rootReducer = (state, action) => (Object.assign(Object.assign({}, state), action.payload));
|
|
105
|
-
const AppProvider = ({ children, initialState = {}, theme = {} }) => {
|
|
129
|
+
const AppProvider = ({ children, initialState = {}, theme = {}, lang = {} }) => {
|
|
106
130
|
useEffect(() => {
|
|
107
131
|
isMounted = true;
|
|
108
132
|
return () => {
|
|
109
133
|
isMounted = false;
|
|
110
134
|
};
|
|
111
135
|
}, []);
|
|
112
|
-
const rootState = useMemo(() => (Object.assign(Object.assign(Object.assign({}, defaultState), initialState), { theme: new AppTheme({ theme }).get() })), [initialState]);
|
|
136
|
+
const rootState = useMemo(() => (Object.assign(Object.assign(Object.assign({}, defaultState), initialState), { theme: new AppTheme({ theme }).get(), lang: new AppLang({ lang }).get() })), [initialState]);
|
|
113
137
|
const [state, _dispatch] = useReducer(rootReducer, rootState);
|
|
114
138
|
const dispatch = useCallback((args) => {
|
|
115
139
|
if (isMounted) {
|
|
@@ -135,12 +159,14 @@ const AppProvider = ({ children, initialState = {}, theme = {} }) => {
|
|
|
135
159
|
};
|
|
136
160
|
AppProvider.defaultProps = {
|
|
137
161
|
theme: {},
|
|
162
|
+
lang: {},
|
|
138
163
|
initialState: {},
|
|
139
164
|
};
|
|
140
165
|
AppProvider.propTypes = {
|
|
141
166
|
children: PropTypes.node.isRequired,
|
|
142
167
|
initialState: PropTypes.instanceOf(Object),
|
|
143
|
-
theme: PropTypes.instanceOf(Object)
|
|
168
|
+
theme: PropTypes.instanceOf(Object),
|
|
169
|
+
lang: PropTypes.instanceOf(Object)
|
|
144
170
|
};
|
|
145
171
|
|
|
146
172
|
const createSlice = ({ name, initialState, reducers }) => {
|
|
@@ -556,14 +582,14 @@ const UPDATE_FORM_FIELD = (formName, field, value, forms) => {
|
|
|
556
582
|
};
|
|
557
583
|
|
|
558
584
|
const Input = forwardRef((props, ref) => {
|
|
559
|
-
const { as, accept, multiple, onChange, onKeyUp, onClick, readOnly, type, tag, placeholder, name, form, touched, onSubmit, defaultValue, fref } = props;
|
|
585
|
+
const { as, accept, multiple, onChange, onKeyUp, onClick, readOnly, type, tag, placeholder, name, form, touched, onSubmit, value, defaultValue, fref, autoComplete } = props;
|
|
560
586
|
const dispatch = useDispatch(STORE_FORM_KEY);
|
|
561
587
|
const { forms } = useStore(state => state[STORE_FORM_KEY], false);
|
|
562
588
|
let Tag = tag || 'input';
|
|
563
589
|
const El = Tag;
|
|
564
590
|
const _ref = fref || useRef();
|
|
565
591
|
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);`;
|
|
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) => {
|
|
592
|
+
return (jsx(ClassNames, { children: ({ css, cx }) => jsx(El, Object.assign({}, cleanProps(props), { type: type || `text`, placeholder: placeholder || undefined, autoComplete: autoComplete || 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, value: value || undefined, defaultValue: defaultValue || ``, onKeyUp: (e) => {
|
|
567
593
|
let k = e['keyCode'] || ['which'];
|
|
568
594
|
if (El != 'textarea' && k == 13 && form && onSubmit) {
|
|
569
595
|
onSubmit(forms[form]);
|
|
@@ -575,7 +601,7 @@ const Input = forwardRef((props, ref) => {
|
|
|
575
601
|
dispatch(dispatch(UPDATE_FORM_FIELD(form || 'orphan', name, val == "" ? null : val, forms)));
|
|
576
602
|
onChange && onChange(val == "" ? null : val);
|
|
577
603
|
}, onClick: onClick ? onClick : () => { }, readOnly: readOnly || false, onBlur: e => {
|
|
578
|
-
}, onFocus: e => touched == false && dispatch(UPDATE_FORM_FIELD(form || 'orphan', `touched`, true, forms)) }) }));
|
|
604
|
+
}, onFocus: e => touched == false && dispatch(UPDATE_FORM_FIELD(form || 'orphan', `touched`, true, forms)) })) }));
|
|
579
605
|
});
|
|
580
606
|
|
|
581
607
|
const Select = forwardRef((props, ref) => {
|
|
@@ -601,45 +627,70 @@ const useTheme = (mod = 'auto') => {
|
|
|
601
627
|
return state['theme'] || {};
|
|
602
628
|
};
|
|
603
629
|
|
|
604
|
-
const
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
oldReferrerPolicy.current = referrerpolicy;
|
|
617
|
-
}
|
|
618
|
-
useLayoutEffect(function () {
|
|
619
|
-
if (!url)
|
|
620
|
-
return;
|
|
621
|
-
var img = document.createElement('img');
|
|
622
|
-
function onload() {
|
|
623
|
-
statusRef.current = 'loaded';
|
|
624
|
-
imageRef.current = img;
|
|
625
|
-
setStateToken(Math.random());
|
|
626
|
-
}
|
|
627
|
-
function onerror() {
|
|
628
|
-
statusRef.current = 'failed';
|
|
629
|
-
imageRef.current = undefined;
|
|
630
|
-
setStateToken(Math.random());
|
|
631
|
-
}
|
|
632
|
-
img.addEventListener('load', onload);
|
|
633
|
-
img.addEventListener('error', onerror);
|
|
634
|
-
crossOrigin && (img.crossOrigin = crossOrigin);
|
|
635
|
-
referrerpolicy && (img.referrerPolicy = referrerpolicy);
|
|
636
|
-
img.src = url;
|
|
637
|
-
return function cleanup() {
|
|
638
|
-
img.removeEventListener('load', onload);
|
|
639
|
-
img.removeEventListener('error', onerror);
|
|
630
|
+
const removeBlankArrayElements = (a) => a.filter((x) => x);
|
|
631
|
+
const stringToArray = (x) => (Array.isArray(x) ? x : [x]);
|
|
632
|
+
const cache = {};
|
|
633
|
+
// sequential map.find for promises
|
|
634
|
+
const promiseFind = (arr, promiseFactory) => {
|
|
635
|
+
let done = false;
|
|
636
|
+
return new Promise((resolve, reject) => {
|
|
637
|
+
const queueNext = (src) => {
|
|
638
|
+
return promiseFactory(src).then(() => {
|
|
639
|
+
done = true;
|
|
640
|
+
resolve(src);
|
|
641
|
+
});
|
|
640
642
|
};
|
|
641
|
-
|
|
642
|
-
|
|
643
|
+
arr
|
|
644
|
+
.reduce((p, src) => {
|
|
645
|
+
// ensure we aren't done before enqueuing the next source
|
|
646
|
+
return p.catch(() => {
|
|
647
|
+
if (!done)
|
|
648
|
+
return queueNext(src);
|
|
649
|
+
});
|
|
650
|
+
}, queueNext(arr.shift()))
|
|
651
|
+
.catch(reject);
|
|
652
|
+
});
|
|
653
|
+
};
|
|
654
|
+
const useImage = ({ srcList, imgPromise = imgPromiseFactory({ decode: true }), useSuspense = true, }) => {
|
|
655
|
+
const [, setIsSettled] = useState(false);
|
|
656
|
+
const sourceList = removeBlankArrayElements(stringToArray(srcList));
|
|
657
|
+
const sourceKey = sourceList.join('');
|
|
658
|
+
if (!cache[sourceKey]) {
|
|
659
|
+
// create promise to loop through sources and try to load one
|
|
660
|
+
cache[sourceKey] = {
|
|
661
|
+
promise: promiseFind(sourceList, imgPromise),
|
|
662
|
+
cache: 'pending',
|
|
663
|
+
error: null,
|
|
664
|
+
};
|
|
665
|
+
}
|
|
666
|
+
// when promise resolves/reject, update cache & state
|
|
667
|
+
if (cache[sourceKey].cache === 'resolved') {
|
|
668
|
+
return { src: cache[sourceKey].src, isLoading: false, error: null };
|
|
669
|
+
}
|
|
670
|
+
if (cache[sourceKey].cache === 'rejected') {
|
|
671
|
+
if (useSuspense)
|
|
672
|
+
throw cache[sourceKey].error;
|
|
673
|
+
return { isLoading: false, error: cache[sourceKey].error, src: undefined };
|
|
674
|
+
}
|
|
675
|
+
cache[sourceKey].promise
|
|
676
|
+
// if a source was found, update cache
|
|
677
|
+
// when not using suspense, update state to force a rerender
|
|
678
|
+
.then((src) => {
|
|
679
|
+
cache[sourceKey] = Object.assign(Object.assign({}, cache[sourceKey]), { cache: 'resolved', src });
|
|
680
|
+
if (!useSuspense)
|
|
681
|
+
setIsSettled(sourceKey);
|
|
682
|
+
})
|
|
683
|
+
// if no source was found, or if another error occurred, update cache
|
|
684
|
+
// when not using suspense, update state to force a rerender
|
|
685
|
+
.catch((error) => {
|
|
686
|
+
cache[sourceKey] = Object.assign(Object.assign({}, cache[sourceKey]), { cache: 'rejected', error });
|
|
687
|
+
if (!useSuspense)
|
|
688
|
+
setIsSettled(sourceKey);
|
|
689
|
+
});
|
|
690
|
+
// cache[sourceKey].cache === 'pending')
|
|
691
|
+
if (useSuspense)
|
|
692
|
+
throw cache[sourceKey].promise;
|
|
693
|
+
return { isLoading: true, src: undefined, error: null };
|
|
643
694
|
};
|
|
644
695
|
|
|
645
696
|
/** External Dependencies */
|
|
@@ -799,13 +850,14 @@ const useDevice = (config, defaultBreakpoint, hydrateInitial = true) => {
|
|
|
799
850
|
return currentBreakpoint;
|
|
800
851
|
};
|
|
801
852
|
|
|
802
|
-
var _Toaster_container, _Toaster_startTop, _Toaster_tout, _Toaster_defaultTimeLeft;
|
|
853
|
+
var _Toaster_container, _Toaster_startTop, _Toaster_tout, _Toaster_defaultTimeLeft, _Toaster_root;
|
|
803
854
|
class Toaster {
|
|
804
855
|
constructor(config) {
|
|
805
856
|
_Toaster_container.set(this, void 0);
|
|
806
857
|
_Toaster_startTop.set(this, void 0);
|
|
807
858
|
_Toaster_tout.set(this, void 0);
|
|
808
859
|
_Toaster_defaultTimeLeft.set(this, void 0);
|
|
860
|
+
_Toaster_root.set(this, void 0);
|
|
809
861
|
this.show = (message, duration) => {
|
|
810
862
|
let self = this;
|
|
811
863
|
self.toast({
|
|
@@ -816,12 +868,13 @@ class Toaster {
|
|
|
816
868
|
__classPrivateFieldSet(this, _Toaster_startTop, 20, "f");
|
|
817
869
|
__classPrivateFieldSet(this, _Toaster_defaultTimeLeft, 4, "f");
|
|
818
870
|
const rootID = (config === null || config === void 0 ? void 0 : config.root) || `toast-container`;
|
|
819
|
-
|
|
871
|
+
__classPrivateFieldSet(this, _Toaster_root, rootID, "f");
|
|
872
|
+
if (window.document.querySelector(`#${rootID}`))
|
|
820
873
|
return;
|
|
821
|
-
var root = document.createElement('div');
|
|
874
|
+
var root = window.document.createElement('div');
|
|
822
875
|
root.id = rootID;
|
|
823
|
-
document.body.appendChild(root);
|
|
824
|
-
__classPrivateFieldSet(this, _Toaster_container, document.querySelector(`#${rootID}`), "f");
|
|
876
|
+
window.document.body.appendChild(root);
|
|
877
|
+
__classPrivateFieldSet(this, _Toaster_container, window.document.querySelector(`#${rootID}`), "f");
|
|
825
878
|
}
|
|
826
879
|
dismiss(ID) {
|
|
827
880
|
let self = this;
|
|
@@ -841,7 +894,7 @@ class Toaster {
|
|
|
841
894
|
}
|
|
842
895
|
toast(config) {
|
|
843
896
|
var self = this;
|
|
844
|
-
var ID = 'toast-' + nanoid(), toast = document.createElement('div'); document.createElement('div');
|
|
897
|
+
var ID = 'toast-' + nanoid(), toast = window.document.createElement('div'); window.document.createElement('div');
|
|
845
898
|
toast.id = ID;
|
|
846
899
|
toast.style.backgroundColor = `#111`;
|
|
847
900
|
toast.style.color = `#fff`;
|
|
@@ -856,7 +909,7 @@ class Toaster {
|
|
|
856
909
|
toast.classList.add('fixed');
|
|
857
910
|
toast.classList.add('f');
|
|
858
911
|
toast.innerHTML = config.message || `You haven't passed "message" in this toast`;
|
|
859
|
-
__classPrivateFieldGet(self, _Toaster_container, "f").appendChild(toast);
|
|
912
|
+
(__classPrivateFieldGet(self, _Toaster_container, "f") || window.document.querySelector(`#${__classPrivateFieldGet(self, _Toaster_root, "f")}`)).appendChild(toast);
|
|
860
913
|
self.arrangeToasts()
|
|
861
914
|
.then(() => {
|
|
862
915
|
setTimeout(() => {
|
|
@@ -883,20 +936,93 @@ class Toaster {
|
|
|
883
936
|
});
|
|
884
937
|
}
|
|
885
938
|
}
|
|
886
|
-
_Toaster_container = new WeakMap(), _Toaster_startTop = new WeakMap(), _Toaster_tout = new WeakMap(), _Toaster_defaultTimeLeft = new WeakMap();
|
|
939
|
+
_Toaster_container = new WeakMap(), _Toaster_startTop = new WeakMap(), _Toaster_tout = new WeakMap(), _Toaster_defaultTimeLeft = new WeakMap(), _Toaster_root = new WeakMap();
|
|
887
940
|
|
|
888
941
|
const useToast = () => {
|
|
889
942
|
const toaster = useMemo(() => new Toaster(), []);
|
|
890
943
|
return toaster;
|
|
891
944
|
};
|
|
892
945
|
|
|
946
|
+
const useLang = (mod = 'en') => {
|
|
947
|
+
const state = useContext(AppContext);
|
|
948
|
+
return state['lang'] || {};
|
|
949
|
+
};
|
|
950
|
+
|
|
951
|
+
const Box = forwardRef((props, ref) => {
|
|
952
|
+
const _noClick = () => { };
|
|
953
|
+
// console.log(props)
|
|
954
|
+
return (jsx(ClassNames, { children: ({ css, cx }) => jsx("div", Object.assign({}, cleanProps(props), { title: props.title || undefined, id: props.id || undefined, onClick: props.onClick || _noClick, className: `${props.as ? `${props.as} ` : ``}${cx(css `${buildCSS(props)} &:hover {${buildCSS(props.hover || {})}} &:active {${buildCSS(props.active || {})}}`)}`, ref: props.bref || ref }, { children: props.html ? jsx("span", { dangerouslySetInnerHTML: { __html: props.html } }) : props.children })) }));
|
|
955
|
+
});
|
|
956
|
+
|
|
957
|
+
const useContextMenu = (contextID) => {
|
|
958
|
+
const ID = `context-${contextID}`;
|
|
959
|
+
useState(false);
|
|
960
|
+
const [root, setRoot] = useState(null);
|
|
961
|
+
const nodeRef = useRef(null);
|
|
962
|
+
const el = (e) => window.document.createElement(e);
|
|
963
|
+
function checkBoundaries(x, y) {
|
|
964
|
+
if (nodeRef.current) {
|
|
965
|
+
const { innerWidth, innerHeight } = window;
|
|
966
|
+
const { offsetWidth, offsetHeight } = nodeRef.current;
|
|
967
|
+
if (x + offsetWidth > innerWidth)
|
|
968
|
+
x -= x + offsetWidth - innerWidth;
|
|
969
|
+
if (y + offsetHeight > innerHeight)
|
|
970
|
+
y -= y + offsetHeight - innerHeight;
|
|
971
|
+
}
|
|
972
|
+
return { x, y };
|
|
973
|
+
}
|
|
974
|
+
const hide = () => {
|
|
975
|
+
try {
|
|
976
|
+
root === null || root === void 0 ? void 0 : root.unmount();
|
|
977
|
+
setRoot(null);
|
|
978
|
+
}
|
|
979
|
+
catch (e) { }
|
|
980
|
+
};
|
|
981
|
+
const Menu = (e, items) => {
|
|
982
|
+
const p = getMousePosition(e);
|
|
983
|
+
const { x, y } = checkBoundaries(p.x, p.y);
|
|
984
|
+
return (jsx(Box, Object.assign({ bref: nodeRef, flex: true, dir: `cols`, fixed: true, top: y, left: x, as: `zuz-contextmenu ${ID}` }, { children: items && items.map((m, i) => m.id == `line` ? jsx(Box, { as: `line` }, `line-${i}-${m.id}`) : jsx("button", Object.assign({ onClick: ev => {
|
|
985
|
+
if (m.onClick) {
|
|
986
|
+
m.onClick(ev, m);
|
|
987
|
+
}
|
|
988
|
+
else {
|
|
989
|
+
console.log(`No onClick eventFound`);
|
|
990
|
+
}
|
|
991
|
+
hide();
|
|
992
|
+
} }, { children: m.label }), `cm-${i}-${m.id}`)) })));
|
|
993
|
+
};
|
|
994
|
+
const show = (e, items) => {
|
|
995
|
+
e.preventDefault();
|
|
996
|
+
e.stopPropagation();
|
|
997
|
+
if (!window.document.querySelector(`#context-${contextID}`)) {
|
|
998
|
+
let div = el(`div`);
|
|
999
|
+
div.id = ID;
|
|
1000
|
+
window.document.body.appendChild(div);
|
|
1001
|
+
}
|
|
1002
|
+
root.render(Menu(e, items));
|
|
1003
|
+
};
|
|
1004
|
+
useEffect(() => {
|
|
1005
|
+
if (!window.document.querySelector(`#context-${contextID}`)) {
|
|
1006
|
+
let div = el(`div`);
|
|
1007
|
+
div.id = ID;
|
|
1008
|
+
window.document.body.appendChild(div);
|
|
1009
|
+
}
|
|
1010
|
+
if (!root)
|
|
1011
|
+
setRoot(ReactDOM.createRoot(document.getElementById(ID)));
|
|
1012
|
+
}, [root]);
|
|
1013
|
+
return {
|
|
1014
|
+
show,
|
|
1015
|
+
hide
|
|
1016
|
+
};
|
|
1017
|
+
};
|
|
1018
|
+
|
|
893
1019
|
const Button = forwardRef((props, ref) => {
|
|
894
1020
|
const { forms } = useStore(state => state[STORE_FORM_KEY], false);
|
|
895
1021
|
if (props.html) {
|
|
896
1022
|
({ __html: props.html });
|
|
897
1023
|
}
|
|
898
1024
|
return (jsx(ClassNames, { children: ({ css, cx }) => {
|
|
899
|
-
return (jsx("button", Object.assign({ title: "title" in props ? props.title : undefined, type: props.type, className: `button${props.as ? ` ${props.as}` : ``} ${cx(css `
|
|
1025
|
+
return (jsx("button", Object.assign({}, cleanProps(props), { title: "title" in props ? props.title : undefined, type: props.type, className: `button${props.as ? ` ${props.as}` : ``} ${cx(css `
|
|
900
1026
|
padding: 5px 10px;
|
|
901
1027
|
border-radius: 2px;
|
|
902
1028
|
${buildCSS(props)} &:hover {${buildCSS(props.hover || {})}} &:active {${buildCSS(props.active || {})}}`)}`, ref: ref, onClick: e => {
|
|
@@ -1001,6 +1127,17 @@ const makeCSSValue = (k, v, o) => {
|
|
|
1001
1127
|
}
|
|
1002
1128
|
return `${k}:${v}${unit};`;
|
|
1003
1129
|
};
|
|
1130
|
+
const cleanProps = (props) => {
|
|
1131
|
+
let _props = Object.assign({}, props);
|
|
1132
|
+
Object.keys(_props).map(k => {
|
|
1133
|
+
if (k in cssProps) {
|
|
1134
|
+
delete _props[k];
|
|
1135
|
+
}
|
|
1136
|
+
});
|
|
1137
|
+
let _extras = [`as`, `hover`, `bref`];
|
|
1138
|
+
_extras.map(x => x in _props && delete _props[x]);
|
|
1139
|
+
return _props;
|
|
1140
|
+
};
|
|
1004
1141
|
const buildCSS = (props) => {
|
|
1005
1142
|
let css = ``;
|
|
1006
1143
|
Object.keys(props).map(k => {
|
|
@@ -1037,7 +1174,7 @@ const randstr = function (len) {
|
|
|
1037
1174
|
}
|
|
1038
1175
|
return text;
|
|
1039
1176
|
};
|
|
1040
|
-
const setCookie = (key, value, expiry) => Cookies.set(key, value, { expires: expiry || 7 });
|
|
1177
|
+
const setCookie = (key, value, expiry, host) => Cookies.set(key, value, { expires: expiry || 7, domain: host || window.location.host });
|
|
1041
1178
|
const getCookie = (key) => Cookies.get(key) || null;
|
|
1042
1179
|
const removeCookie = (key) => Cookies.remove(key);
|
|
1043
1180
|
const buildFormData = (data) => {
|
|
@@ -1190,6 +1327,53 @@ const getUriParams = () => {
|
|
|
1190
1327
|
return xny;
|
|
1191
1328
|
};
|
|
1192
1329
|
const rgb2hex = rgb => `#${rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/).slice(1).map(n => parseInt(n, 10).toString(16).padStart(2, '0')).join('')}`;
|
|
1330
|
+
const getHostname = url => {
|
|
1331
|
+
if (window.URL) {
|
|
1332
|
+
let u = new window.URL(url);
|
|
1333
|
+
return u.hostname;
|
|
1334
|
+
}
|
|
1335
|
+
else {
|
|
1336
|
+
var a = document.createElement(`a`);
|
|
1337
|
+
a.href = url;
|
|
1338
|
+
return a.hostname.replace("www.", "");
|
|
1339
|
+
}
|
|
1340
|
+
};
|
|
1341
|
+
const imgPromiseFactory = ({ decode = true, crossOrigin = '' }) => (src) => {
|
|
1342
|
+
return new Promise((resolve, reject) => {
|
|
1343
|
+
const i = new Image();
|
|
1344
|
+
if (crossOrigin)
|
|
1345
|
+
i.crossOrigin = crossOrigin;
|
|
1346
|
+
i.onload = () => {
|
|
1347
|
+
decode && i.decode ? i.decode().then(resolve).catch(reject) : resolve();
|
|
1348
|
+
};
|
|
1349
|
+
i.onerror = reject;
|
|
1350
|
+
i.src = src;
|
|
1351
|
+
});
|
|
1352
|
+
};
|
|
1353
|
+
const parseFilename = nm => {
|
|
1354
|
+
var re = /(?:\.([^.]+))?$/;
|
|
1355
|
+
return {
|
|
1356
|
+
name: nm.split('.').slice(0, -1).join('.'),
|
|
1357
|
+
ext: re.exec(nm)[1]
|
|
1358
|
+
};
|
|
1359
|
+
};
|
|
1360
|
+
const camelCase = str => str.replace(":", "-").replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); });
|
|
1361
|
+
const getMousePosition = e => {
|
|
1362
|
+
const pos = {
|
|
1363
|
+
x: e.clientX,
|
|
1364
|
+
y: e.clientY,
|
|
1365
|
+
};
|
|
1366
|
+
const touch = e.changedTouches;
|
|
1367
|
+
if (touch) {
|
|
1368
|
+
pos.x = touch[0].clientX;
|
|
1369
|
+
pos.y = touch[0].clientY;
|
|
1370
|
+
}
|
|
1371
|
+
if (!pos.x || pos.x < 0)
|
|
1372
|
+
pos.x = 0;
|
|
1373
|
+
if (!pos.y || pos.y < 0)
|
|
1374
|
+
pos.y = 0;
|
|
1375
|
+
return pos;
|
|
1376
|
+
};
|
|
1193
1377
|
|
|
1194
1378
|
const AppMain = forwardRef((props, ref) => {
|
|
1195
1379
|
// const { dispatch } = useStore()
|
|
@@ -1202,11 +1386,6 @@ const App = forwardRef((props, ref) => {
|
|
|
1202
1386
|
return (jsx(AppProvider, { children: jsx(AppMain, {}) }));
|
|
1203
1387
|
});
|
|
1204
1388
|
|
|
1205
|
-
const Box = forwardRef((props, ref) => {
|
|
1206
|
-
const _noClick = () => { };
|
|
1207
|
-
return (jsx(ClassNames, { children: ({ css, cx }) => jsx("div", Object.assign({ id: props.id || undefined, onClick: props.onClick || _noClick, className: `${props.as ? `${props.as} ` : ``}${cx(css `${buildCSS(props)} &:hover {${buildCSS(props.hover || {})}} &:active {${buildCSS(props.active || {})}}`)}`, ref: props.bref || ref }, { children: props.html ? jsx("span", { dangerouslySetInnerHTML: { __html: props.html } }) : props.children })) }));
|
|
1208
|
-
});
|
|
1209
|
-
|
|
1210
1389
|
// const CoreBlock = styled.section`display: block;`
|
|
1211
1390
|
// const buildComponent = (props: any) => Block.withComponent(props.for || `div`)`${buildCSS(props)}`
|
|
1212
1391
|
const Component = forwardRef((props, ref) => {
|
|
@@ -1338,9 +1517,18 @@ const Icon = forwardRef((props, ref) => {
|
|
|
1338
1517
|
return (jsx(Box, Object.assign({ hover: hover || {}, flex: true, bref: ref, as: `icon-${as}`, ai: `c`, jc: `c`, size: size || 24, color: color || `#111111` }, { children: path && Array(path).fill(undefined).map((p, i) => jsx("span", { className: `path${i + 1}` }, `ico-${as}-${i}`)) })));
|
|
1339
1518
|
});
|
|
1340
1519
|
|
|
1341
|
-
const Image = forwardRef((props, ref) => {
|
|
1342
|
-
const
|
|
1343
|
-
return (jsx(ClassNames, { children: ({ css, cx }) => jsxs(
|
|
1520
|
+
const Image$1 = forwardRef((props, ref) => {
|
|
1521
|
+
const { src, isLoading, error } = useImage({ srcList: props.src, useSuspense: false });
|
|
1522
|
+
return (jsx(ClassNames, { children: ({ css, cx }) => jsxs(Fragment, { children: [isLoading && jsx(Box, { className: `${props.as ? `${props.as} ` : ``}${cx(css `background: #eee;${buildCSS(props)}`)}` }), !isLoading && jsx("img", { src: src, className: `${props.as ? `${props.as} ` : ``}${cx(css `${buildCSS(props)}`)}`, ref: ref })] }) })
|
|
1523
|
+
// <ClassNames>
|
|
1524
|
+
// {({ css, cx }) => <picture className={cx(css`${buildCSS({ flex: true })}`)}>
|
|
1525
|
+
// {status == 'loading' && <Box className={`${props.as ? `${props.as} ` : ``}${cx(css`background: #eee;${buildCSS(props)}`)}`} />}
|
|
1526
|
+
// {status == 'loaded' && <img src={props.src}
|
|
1527
|
+
// className={`${props.as ? `${props.as} ` : ``}${cx(css`${buildCSS(props)}`)}`}
|
|
1528
|
+
// ref={ref} />}
|
|
1529
|
+
// </picture>}
|
|
1530
|
+
// </ClassNames>
|
|
1531
|
+
);
|
|
1344
1532
|
});
|
|
1345
1533
|
|
|
1346
1534
|
const DEFAULT_COLUMNS = 2;
|
|
@@ -1528,7 +1716,7 @@ const Tweet = (props) => {
|
|
|
1528
1716
|
|
|
1529
1717
|
const ContextMenu = forwardRef((props, ref) => {
|
|
1530
1718
|
const { as, size, color, hover, pos, items } = props;
|
|
1531
|
-
return (jsx(Box, Object.assign({ hover: hover || {}, flex: true, fixed: true, top: (pos === null || pos === void 0 ? void 0 : pos.y) || 0, left: (pos === null || pos === void 0 ? void 0 : pos.x) || 0, bref: ref, as: `contextmenu-${as}`,
|
|
1719
|
+
return (jsx(Box, Object.assign({ hover: hover || {}, flex: true, dir: `cols`, fixed: true, top: (pos === null || pos === void 0 ? void 0 : pos.y) || 0, left: (pos === null || pos === void 0 ? void 0 : pos.x) || 0, bref: ref, as: `contextmenu-${as}`, size: size || 24, color: color || `#111111` }, { children: items && items.map((m, i) => jsx(Button, Object.assign({ onClick: m.on ? m.on : () => { } }, { children: m.label }), `cm-${i}-${m.id}`)) })));
|
|
1532
1720
|
});
|
|
1533
1721
|
|
|
1534
1722
|
const buildElement = (el) => {
|
|
@@ -1548,4 +1736,4 @@ const Header = forwardRef((props, ref) => {
|
|
|
1548
1736
|
return (jsx(Fragment, { children: buildComponent(data) }));
|
|
1549
1737
|
});
|
|
1550
1738
|
|
|
1551
|
-
export { App, Component as Block, Box, Button, Checkbox, ContextMenu, Cover, Form, Header, Heading, Icon, Image, Input, Masonry, 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 };
|
|
1739
|
+
export { App, Component as Block, Box, Button, Checkbox, ContextMenu, Cover, Form, Header, Heading, Icon, Image$1 as Image, Input, Masonry, Placeholder, AppProvider as Provider, Select, Spacer, Spinner, Text, Toaster, Tweet, addProps, addScript, buildCSS, buildFormData, byId, byName, camelCase, cleanProps, createSlice, el, filterHTMLProps, filterStyleProps, generateModalRoutes, generatePreservedRoutes, generateRegularRoutes, getCookie, getHostname, getMousePosition, getUriParams, grab, imgPromiseFactory, isEmail, isIPv4, isUrl, parseFilename, randstr, removeCookie, rgb2hex, setCSSVar, setCookie, shuffleArray, ucfirst, useContextMenu, useDevice, useDispatch, useImage, useLang, useResizeObserver, useStore, useTheme, useToast, uuid };
|
package/dist/styles.css
CHANGED
|
@@ -312,6 +312,50 @@ button {
|
|
|
312
312
|
font-size: 72px;
|
|
313
313
|
}
|
|
314
314
|
|
|
315
|
+
/*
|
|
316
|
+
BoldSize
|
|
317
|
+
It will generate .b400 { font-weight: 400; } from '400'
|
|
318
|
+
*/
|
|
319
|
+
.bold {
|
|
320
|
+
font-weight: bold;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
.b100 {
|
|
324
|
+
font-weight: 100;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
.b200 {
|
|
328
|
+
font-weight: 200;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
.b300 {
|
|
332
|
+
font-weight: 300;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
.b400 {
|
|
336
|
+
font-weight: 400;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
.b500 {
|
|
340
|
+
font-weight: 500;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
.b600 {
|
|
344
|
+
font-weight: 600;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
.b700 {
|
|
348
|
+
font-weight: 700;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
.b800 {
|
|
352
|
+
font-weight: 800;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
.b900 {
|
|
356
|
+
font-weight: 900;
|
|
357
|
+
}
|
|
358
|
+
|
|
315
359
|
@-webkit-keyframes rotating /* Safari and Chrome */ {
|
|
316
360
|
from {
|
|
317
361
|
-webkit-transform: rotate(0deg);
|
|
@@ -411,4 +455,31 @@ button {
|
|
|
411
455
|
}
|
|
412
456
|
.zuz-checkbox:checked + label:after {
|
|
413
457
|
left: 20px;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
.zuz-contextmenu {
|
|
461
|
+
min-width: 220px;
|
|
462
|
+
border-radius: 5px;
|
|
463
|
+
padding: 4px;
|
|
464
|
+
background: rgba(34, 34, 34, 0.5);
|
|
465
|
+
border: 1px rgba(255, 255, 255, 0.25) solid;
|
|
466
|
+
box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.45);
|
|
467
|
+
backdrop-filter: blur(20px);
|
|
468
|
+
}
|
|
469
|
+
.zuz-contextmenu button {
|
|
470
|
+
border: 0px;
|
|
471
|
+
text-align: left;
|
|
472
|
+
padding: 4px 6px;
|
|
473
|
+
background: rgba(0, 0, 0, 0);
|
|
474
|
+
cursor: pointer;
|
|
475
|
+
color: #fff;
|
|
476
|
+
border-radius: 4px;
|
|
477
|
+
}
|
|
478
|
+
.zuz-contextmenu button:hover {
|
|
479
|
+
background: #385fd2;
|
|
480
|
+
}
|
|
481
|
+
.zuz-contextmenu .line {
|
|
482
|
+
height: 1px;
|
|
483
|
+
background: rgba(255, 255, 255, 0.25);
|
|
484
|
+
margin: 4px 6px;
|
|
414
485
|
}
|
package/package.json
CHANGED
package/src/comps/box.tsx
CHANGED
|
@@ -3,15 +3,19 @@ import {
|
|
|
3
3
|
useEffect
|
|
4
4
|
} from 'react';
|
|
5
5
|
import { ClassNames } from '@emotion/react'
|
|
6
|
-
import { buildCSS } from '../core'
|
|
6
|
+
import { cleanProps, buildCSS } from '../core'
|
|
7
7
|
|
|
8
8
|
const Box = forwardRef((props : { [ key: string ] : any }, ref) => {
|
|
9
9
|
|
|
10
10
|
const _noClick = () => {}
|
|
11
11
|
|
|
12
|
+
// console.log(props)
|
|
13
|
+
|
|
12
14
|
return (
|
|
13
15
|
<ClassNames>
|
|
14
16
|
{({ css, cx }) => <div
|
|
17
|
+
{...cleanProps(props)}
|
|
18
|
+
title={props.title || undefined}
|
|
15
19
|
id={props.id || undefined}
|
|
16
20
|
onClick={props.onClick || _noClick}
|
|
17
21
|
className={`${props.as ? `${props.as} ` : ``}${cx(css`${buildCSS(props)} &:hover {${buildCSS(props.hover || {})}} &:active {${buildCSS(props.active || {})}}`)}`}
|
package/src/comps/button.tsx
CHANGED
|
@@ -5,7 +5,7 @@ import React, {
|
|
|
5
5
|
import { ClassNames } from '@emotion/react'
|
|
6
6
|
import {
|
|
7
7
|
buildCSS,
|
|
8
|
-
|
|
8
|
+
cleanProps
|
|
9
9
|
} from '../core'
|
|
10
10
|
import { useStore } from '../hooks'
|
|
11
11
|
import { STORE_FORM_KEY } from '../context/AppProvider'
|
|
@@ -22,6 +22,7 @@ const Button = forwardRef((props: { [ key: string ] : any }, ref : LegacyRef<HTM
|
|
|
22
22
|
{({ css, cx }) => {
|
|
23
23
|
return (
|
|
24
24
|
<button
|
|
25
|
+
{...cleanProps(props)}
|
|
25
26
|
title={"title" in props ? props.title : undefined}
|
|
26
27
|
type={props.type}
|
|
27
28
|
className={`button${props.as ? ` ${props.as}` : ``} ${cx(css`
|
|
@@ -22,14 +22,12 @@ const ContextMenu = forwardRef((props : { [ key: string ] : any }, ref : LegacyR
|
|
|
22
22
|
return (
|
|
23
23
|
<Box
|
|
24
24
|
hover={hover || {}}
|
|
25
|
-
flex
|
|
25
|
+
flex dir={`cols`}
|
|
26
26
|
fixed
|
|
27
27
|
top={pos?.y || 0}
|
|
28
28
|
left={pos?.x || 0}
|
|
29
29
|
bref={ref}
|
|
30
30
|
as={`contextmenu-${as}`}
|
|
31
|
-
ai={`c`}
|
|
32
|
-
jc={`c`}
|
|
33
31
|
size={size || 24}
|
|
34
32
|
color={color || `#111111`}
|
|
35
33
|
>
|