@zuzjs/ui 0.3.1 → 0.3.3

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 CHANGED
@@ -7,7 +7,6 @@ import axios from 'axios';
7
7
  import { nanoid } from 'nanoid';
8
8
  import { ClassNames } from '@emotion/react';
9
9
  import ReactDOM from 'react-dom/client';
10
- export { Link } from 'react-router-dom';
11
10
  import styled from '@emotion/styled';
12
11
 
13
12
  const AppContext = createContext({});
@@ -50,7 +49,12 @@ function __classPrivateFieldSet(receiver, state, value, kind, f) {
50
49
  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
51
50
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
52
51
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
53
- }
52
+ }
53
+
54
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
55
+ var e = new Error(message);
56
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
57
+ };
54
58
 
55
59
  var _AppTheme_mode, _AppTheme_listen, _AppTheme_lightTheme, _AppTheme_darkTheme;
56
60
  class AppTheme {
@@ -62,11 +66,11 @@ class AppTheme {
62
66
  this.get = () => {
63
67
  let self = this;
64
68
  if (__classPrivateFieldGet(self, _AppTheme_mode, "f") === "auto") {
65
- window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
69
+ typeof window !== 'undefined' && window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
66
70
  __classPrivateFieldSet(self, _AppTheme_mode, event.matches ? "dark" : "light", "f");
67
71
  __classPrivateFieldGet(self, _AppTheme_listen, "f").call(self, __classPrivateFieldGet(self, _AppTheme_mode, "f"));
68
72
  });
69
- return window.matchMedia &&
73
+ return typeof window !== 'undefined' && window.matchMedia &&
70
74
  window.matchMedia('(prefers-color-scheme: dark)').matches ?
71
75
  __classPrivateFieldGet(self, _AppTheme_darkTheme, "f") : __classPrivateFieldGet(self, _AppTheme_lightTheme, "f");
72
76
  }
@@ -155,7 +159,7 @@ const AppProvider = ({ children, initialState = {}, theme = {}, lang = {} }) =>
155
159
  // }
156
160
  // }, [_dispatch]);
157
161
  const providedValue = useMemo(() => (Object.assign(Object.assign({}, state), { dispatch })), [state]);
158
- return jsx(AppContext.Provider, Object.assign({ value: providedValue }, { children: children }));
162
+ return jsx(AppContext.Provider, { value: providedValue, children: children });
159
163
  };
160
164
  AppProvider.defaultProps = {
161
165
  theme: {},
@@ -198,6 +202,10 @@ const cssProps = {
198
202
  "ac": "align-content",
199
203
  "alignContent": "align-content",
200
204
  "aic": "aic",
205
+ "ais": "ais",
206
+ "aie": "aie",
207
+ "nous": "nous",
208
+ "nope": "nope",
201
209
  "ai": "align-items",
202
210
  "alignItems": "align-items",
203
211
  "ass": "ass",
@@ -454,6 +462,7 @@ const cssProps = {
454
462
  "wordBreak": "word-break",
455
463
  "wordSpacing": "word-spacing",
456
464
  "wrap": "wrap",
465
+ "textWrap": "textWrap",
457
466
  "wordWrap": "word-wrap",
458
467
  "writingMode": "writing-mode",
459
468
  "zIndex": "z-index",
@@ -490,6 +499,8 @@ const cssPropsDirect = {
490
499
  'flex': 'display: flex;',
491
500
  'fwrap': 'flex-wrap: wrap;',
492
501
  'aic': 'align-items: center;',
502
+ 'ais': 'align-items: flex-start;',
503
+ 'aie': 'align-items: flex-end;',
493
504
  'ass': 'align-self: flex-start;',
494
505
  'asc': 'align-self: center;',
495
506
  'ase': 'align-self: flex-end;',
@@ -502,13 +513,17 @@ const cssPropsDirect = {
502
513
  'block': 'display: block;',
503
514
  'bold': "font-weight: bold;",
504
515
  'wrap': "word-wrap: break-word;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;max-width: 99%;",
516
+ 'textWrap': "word-wrap: break-word;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;max-width: 99%;",
505
517
  'pointer': "cursor: pointer;",
506
518
  'fb': 'font-family: var(--primary-font-bold);',
507
519
  'ph': 'padding-left: __VALUE__;padding-right: __VALUE__;',
508
520
  'pv': 'padding-bottom: __VALUE__;padding-top: __VALUE__;',
509
521
  'mv': 'margin-bottom: __VALUE__;margin-top: __VALUE__;',
510
522
  'mh': 'margin-left: __VALUE__;margin-right: __VALUE__;',
511
- 'anim': 'transition:all __VALUE__s linear 0s;'
523
+ 'anim': 'transition:all __VALUE__s linear 0s;',
524
+ 'nous': 'user-select: none;',
525
+ 'nope': 'pointer-events: none;',
526
+ 'tdn': 'text-decoration: none;',
512
527
  };
513
528
  const cssPropsIgnore = [
514
529
  'weight', `opacity`
@@ -581,27 +596,44 @@ const UPDATE_FORM_FIELD = (formName, field, value, forms) => {
581
596
  return {};
582
597
  };
583
598
 
599
+ typeof window !== "undefined" && !!document.documentElement.currentStyle;
584
600
  const Input = forwardRef((props, ref) => {
585
- const { as, accept, multiple, onChange, onKeyUp, onClick, readOnly, type, tag, placeholder, name, form, touched, onSubmit, value, defaultValue, fref, autoComplete } = props;
601
+ const { as, accept, multiple, onChange, onKeyUp, onClick, onBlur, onFocus, readOnly, type, tag, placeholder, name, form, touched, onSubmit, value, defaultValue, fref, autoComplete, elastic, minRows, maxRows } = props;
586
602
  const dispatch = useDispatch(STORE_FORM_KEY);
587
603
  const { forms } = useStore(state => state[STORE_FORM_KEY], false);
588
604
  let Tag = tag || 'input';
589
605
  const El = Tag;
590
606
  const _ref = fref || useRef();
591
607
  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);`;
608
+ props.value !== undefined;
609
+ useRef();
610
+ useEffect(() => { }, []);
592
611
  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) => {
593
612
  let k = e['keyCode'] || ['which'];
594
- if (El != 'textarea' && k == 13 && form && onSubmit) {
613
+ if (form && onSubmit && El != 'textarea' && k == 13) {
595
614
  onSubmit(forms[form]);
596
615
  }
616
+ else {
617
+ if (onKeyUp)
618
+ onKeyUp(e);
619
+ }
597
620
  }, onChange: e => {
598
621
  let val = type == 'file' ?
599
622
  e.currentTarget.files
600
623
  : e.currentTarget.value;
601
- dispatch(dispatch(UPDATE_FORM_FIELD(form || 'orphan', name, val == "" ? null : val, forms)));
624
+ if (form)
625
+ dispatch(dispatch(UPDATE_FORM_FIELD(form || 'orphan', name, val == "" ? null : val, forms)));
626
+ // if(El == `textarea` && elastic) handleElastic()
602
627
  onChange && onChange(val == "" ? null : val);
603
628
  }, onClick: onClick ? onClick : () => { }, readOnly: readOnly || false, onBlur: e => {
604
- }, onFocus: e => touched == false && dispatch(UPDATE_FORM_FIELD(form || 'orphan', `touched`, true, forms)) })) }));
629
+ if (onBlur)
630
+ onBlur(e);
631
+ }, onFocus: e => {
632
+ if (touched == false)
633
+ dispatch(UPDATE_FORM_FIELD(form || 'orphan', `touched`, true, forms));
634
+ if (onFocus)
635
+ onFocus(e);
636
+ } })) }));
605
637
  });
606
638
 
607
639
  const Select = forwardRef((props, ref) => {
@@ -614,12 +646,12 @@ const Select = forwardRef((props, ref) => {
614
646
  var _a;
615
647
  dispatch(dispatch(UPDATE_FORM_FIELD(form || 'orphan', name, defaultValue && defaultValue != null && defaultValue != "" && defaultValue != undefined ? defaultValue : ((_a = options[0]) === null || _a === void 0 ? void 0 : _a.value) || '-1', forms)));
616
648
  }, []);
617
- return (jsx(ClassNames, { children: ({ css, cx }) => jsx("select", Object.assign({ onChange: e => {
649
+ return (jsx(ClassNames, { children: ({ css, cx }) => jsx("select", { onChange: e => {
618
650
  let val = e.currentTarget.value;
619
651
  dispatch(dispatch(UPDATE_FORM_FIELD(form || 'orphan', name, val, forms)));
620
652
  onChange && onChange(val);
621
653
  }, onFocus: e => touched == false && dispatch(UPDATE_FORM_FIELD(form || 'orphan', `touched`, true, forms)), onBlur: e => {
622
- }, name: name || nanoid(), className: `${as ? as : ``} ${cx(css `${_defaultCSS}${buildCSS(props)}&:hover {${buildCSS(props.hover || {})}}`)}`, ref: _ref }, { children: options === null || options === void 0 ? void 0 : options.map(o => jsx("option", Object.assign({ value: o.value }, { children: o.label }), `select-${name}-option-${o.value}`)) })) }));
654
+ }, name: name || nanoid(), className: `${as ? as : ``} ${cx(css `${_defaultCSS}${buildCSS(props)}&:hover {${buildCSS(props.hover || {})}}`)}`, ref: _ref, children: options === null || options === void 0 ? void 0 : options.map(o => jsx("option", { value: o.value, children: o.label }, `select-${name}-option-${o.value}`)) }) }));
623
655
  });
624
656
 
625
657
  const useTheme = (mod = 'auto') => {
@@ -756,6 +788,7 @@ const EMPTY_BREAKPOINT = {
756
788
  minWidth: undefined,
757
789
  maxWidth: undefined,
758
790
  };
791
+ const isBrowser = typeof window !== 'undefined';
759
792
  const useDevice = (config, defaultBreakpoint, hydrateInitial = true) => {
760
793
  const buildQueries = (breakpoints) => {
761
794
  const sorted = Object.keys(breakpoints).sort((a, b) => breakpoints[b] - breakpoints[a]);
@@ -796,7 +829,7 @@ const useDevice = (config, defaultBreakpoint, hydrateInitial = true) => {
796
829
  */
797
830
  if (typeof window !== 'undefined' &&
798
831
  !(defaultBreakpoint && hydrateInitial)) {
799
- const mediaQuery = window.matchMedia(query);
832
+ const mediaQuery = window === null || window === void 0 ? void 0 : window.matchMedia(query);
800
833
  if (mediaQuery.matches) {
801
834
  return breakpoint;
802
835
  }
@@ -816,32 +849,34 @@ const useDevice = (config, defaultBreakpoint, hydrateInitial = true) => {
816
849
  }, []);
817
850
  /** On changes to mediaQueries, subscribe to changes using window.matchMedia */
818
851
  useChooseEffect(() => {
819
- const unsubscribers = mediaQueries.map((_a) => {
820
- var { query } = _a, breakpoint = __rest(_a, ["query"]);
821
- const list = window.matchMedia(query);
822
- updateBreakpoint(list, breakpoint);
823
- const handleChange = (event) => {
824
- updateBreakpoint(event, breakpoint);
825
- };
826
- const supportsNewEventListeners = 'addEventListener' in list && 'removeEventListener' in list;
827
- if (supportsNewEventListeners) {
828
- list.addEventListener('change', handleChange);
829
- }
830
- else {
831
- list.addListener(handleChange);
832
- }
833
- /** Map the unsubscribers array to a list of unsubscriber methods */
834
- return () => {
852
+ if (isBrowser) {
853
+ const unsubscribers = mediaQueries.map((_a) => {
854
+ var { query } = _a, breakpoint = __rest(_a, ["query"]);
855
+ const list = window.matchMedia(query);
856
+ updateBreakpoint(list, breakpoint);
857
+ const handleChange = (event) => {
858
+ updateBreakpoint(event, breakpoint);
859
+ };
860
+ const supportsNewEventListeners = 'addEventListener' in list && 'removeEventListener' in list;
835
861
  if (supportsNewEventListeners) {
836
- list.removeEventListener('change', handleChange);
862
+ list.addEventListener('change', handleChange);
837
863
  }
838
864
  else {
839
- list.removeListener(handleChange);
865
+ list.addListener(handleChange);
840
866
  }
841
- };
842
- });
843
- /** Return a function that when called, will call all unsubscribers */
844
- return () => unsubscribers.forEach((unsubscriber) => unsubscriber());
867
+ /** Map the unsubscribers array to a list of unsubscriber methods */
868
+ return () => {
869
+ if (supportsNewEventListeners) {
870
+ list.removeEventListener('change', handleChange);
871
+ }
872
+ else {
873
+ list.removeListener(handleChange);
874
+ }
875
+ };
876
+ });
877
+ /** Return a function that when called, will call all unsubscribers */
878
+ return () => unsubscribers.forEach((unsubscriber) => unsubscriber());
879
+ }
845
880
  }, [mediaQueries, updateBreakpoint]);
846
881
  /** Print a nice debug value for React Devtools */
847
882
  useDebugValue(currentBreakpoint, (c) => typeof c.breakpoint === 'string'
@@ -869,12 +904,15 @@ class Toaster {
869
904
  __classPrivateFieldSet(this, _Toaster_defaultTimeLeft, 4, "f");
870
905
  const rootID = (config === null || config === void 0 ? void 0 : config.root) || `toast-container`;
871
906
  __classPrivateFieldSet(this, _Toaster_root, rootID, "f");
872
- if (window.document.querySelector(`#${rootID}`))
907
+ this.addRoot();
908
+ }
909
+ addRoot() {
910
+ if (window.document.querySelector(`#${__classPrivateFieldGet(this, _Toaster_root, "f")}`))
873
911
  return;
874
912
  var root = window.document.createElement('div');
875
- root.id = rootID;
913
+ root.id = __classPrivateFieldGet(this, _Toaster_root, "f");
876
914
  window.document.body.appendChild(root);
877
- __classPrivateFieldSet(this, _Toaster_container, window.document.querySelector(`#${rootID}`), "f");
915
+ __classPrivateFieldSet(this, _Toaster_container, window.document.querySelector(`#${__classPrivateFieldGet(this, _Toaster_root, "f")}`), "f");
878
916
  }
879
917
  dismiss(ID) {
880
918
  let self = this;
@@ -894,6 +932,7 @@ class Toaster {
894
932
  }
895
933
  toast(config) {
896
934
  var self = this;
935
+ self.addRoot();
897
936
  var ID = 'toast-' + nanoid(), toast = window.document.createElement('div'); window.document.createElement('div');
898
937
  toast.id = ID;
899
938
  toast.style.backgroundColor = `#111`;
@@ -951,71 +990,115 @@ const useLang = (mod = 'en') => {
951
990
  const Box = forwardRef((props, ref) => {
952
991
  const _noClick = () => { };
953
992
  // 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 })) }));
993
+ return (jsx(ClassNames, { children: ({ css, cx }) => jsx("div", Object.assign({}, cleanProps(props), { title: props.title || undefined, id: props.id || undefined, onDoubleClick: props.onDoubleClick || 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
994
  });
956
995
 
957
- const useContextMenu = (contextID) => {
958
- const ID = `context-${contextID}`;
959
- useState(false);
960
- const [root, setRoot] = useState(null);
996
+ const Menu = ({ ID, hide, e, items, width }) => {
961
997
  const nodeRef = useRef(null);
962
- const el = (e) => window.document.createElement(e);
963
- function checkBoundaries(x, y) {
998
+ const [p, setP] = useState(getMousePosition(e));
999
+ const [visible, setVisible] = useState(false);
1000
+ const checkBoundaries = (x, y) => {
964
1001
  if (nodeRef.current) {
965
1002
  const { innerWidth, innerHeight } = window;
966
1003
  const { offsetWidth, offsetHeight } = nodeRef.current;
967
1004
  if (x + offsetWidth > innerWidth)
968
- x -= x + offsetWidth - innerWidth;
1005
+ x -= offsetWidth; //x + offsetWidth - innerWidth;
969
1006
  if (y + offsetHeight > innerHeight)
970
- y -= y + offsetHeight - innerHeight;
1007
+ y -= offsetHeight;
971
1008
  }
972
- return { x, y };
973
- }
974
- const hide = () => {
1009
+ setP({ x, y });
1010
+ setVisible(true);
1011
+ };
1012
+ useEffect(() => {
1013
+ checkBoundaries(p.x, p.y);
1014
+ }, [e]);
1015
+ return (jsx(Box, { bref: nodeRef, flex: true, dir: `cols`, fixed: true, top: p.y, left: p.x, w: width || 220, opacity: visible ? 1 : 0, as: `zuz-contextmenu ${ID}`, children: items.map((m, i) => m.id == `line` ? jsx(Box, { as: `line` }, `line-${i}-${m.id}`) : jsx("button", { onClick: ev => {
1016
+ if (m.onClick) {
1017
+ m.onClick(ev, m);
1018
+ }
1019
+ else {
1020
+ console.log(`No onClick eventFound`);
1021
+ }
1022
+ hide();
1023
+ }, children: m.label }, `cm-${i}-${m.id}`)) }));
1024
+ };
1025
+ const useContextMenu = (contextID, contextWidth, contextToken = `____uchides`) => {
1026
+ const ID = `contextmenu-${contextID}`;
1027
+ useState(false);
1028
+ const [root, setRoot] = useState(null);
1029
+ const el = (e) => window.document.createElement(e);
1030
+ const createRoot = () => {
1031
+ if (!window.document.querySelector(`#${ID}`)) {
1032
+ let div = el(`div`);
1033
+ div.id = ID;
1034
+ window.document.body.appendChild(div);
1035
+ }
1036
+ };
1037
+ const hideAll = () => {
1038
+ if (window[contextToken]) {
1039
+ window[contextToken].map((h) => h['ID'] != ID && h['fnc']());
1040
+ }
1041
+ };
1042
+ const _hide = () => {
975
1043
  try {
976
1044
  root === null || root === void 0 ? void 0 : root.unmount();
1045
+ document.querySelector(`#${ID}`).parentNode.removeChild(document.querySelector(`#${ID}`));
977
1046
  setRoot(null);
978
1047
  }
979
1048
  catch (e) { }
980
1049
  };
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}`)) })));
1050
+ const hide = () => {
1051
+ _hide();
1052
+ hideAll();
993
1053
  };
994
1054
  const show = (e, items) => {
995
1055
  e.preventDefault();
996
1056
  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));
1057
+ hideAll();
1058
+ root.render(jsx(Menu, { e: e, width: contextWidth || 220, items: items, ID: ID, hide: hide }));
1003
1059
  };
1004
1060
  useEffect(() => {
1005
- if (!window.document.querySelector(`#context-${contextID}`)) {
1006
- let div = el(`div`);
1007
- div.id = ID;
1008
- window.document.body.appendChild(div);
1009
- }
1061
+ createRoot();
1010
1062
  if (!root)
1011
1063
  setRoot(ReactDOM.createRoot(document.getElementById(ID)));
1012
1064
  }, [root]);
1065
+ useEffect(() => {
1066
+ if (contextToken in window == false) {
1067
+ window[contextToken] = [];
1068
+ }
1069
+ if (window[contextToken].findIndex(x => x.ID == ID) == -1) {
1070
+ window[contextToken].push({ ID: ID, fnc: _hide });
1071
+ if (window[contextToken].length > document.querySelectorAll('div[id^="contextmenu-"]').length) {
1072
+ window[contextToken].shift();
1073
+ }
1074
+ }
1075
+ }, []);
1013
1076
  return {
1014
1077
  show,
1015
- hide
1078
+ hide,
1079
+ hideAll
1016
1080
  };
1017
1081
  };
1018
1082
 
1083
+ const useRender = (isMounted, delay) => {
1084
+ const [canRender, setCanRender] = useState(false);
1085
+ // console.log(
1086
+ // `isMounted:`, isMounted,
1087
+ // `canRender:`, canRender,
1088
+ // )
1089
+ useEffect(() => {
1090
+ let outID;
1091
+ if (isMounted && !canRender) {
1092
+ setCanRender(true);
1093
+ }
1094
+ else if (isMounted && canRender) {
1095
+ outID = setTimeout(() => setCanRender(false), delay * 1000);
1096
+ }
1097
+ return () => clearTimeout(outID);
1098
+ }, [isMounted, delay]);
1099
+ return canRender;
1100
+ };
1101
+
1019
1102
  const Button = forwardRef((props, ref) => {
1020
1103
  const { forms } = useStore(state => state[STORE_FORM_KEY], false);
1021
1104
  if (props.html) {
@@ -1025,14 +1108,14 @@ const Button = forwardRef((props, ref) => {
1025
1108
  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 `
1026
1109
  padding: 5px 10px;
1027
1110
  border-radius: 2px;
1028
- ${buildCSS(props)} &:hover {${buildCSS(props.hover || {})}} &:active {${buildCSS(props.active || {})}}`)}`, ref: ref, onClick: e => {
1111
+ ${buildCSS(props)} &:hover {${buildCSS(props.hover || {})}} &:active {${buildCSS(props.active || {})}}`)}`, ref: ref, onDoubleClick: props.onDoubleClick || undefined, onClick: e => {
1029
1112
  if (props.form && props.type && props.type == 'submit') {
1030
1113
  props.onSubmit(forms[props.form]);
1031
1114
  }
1032
1115
  else {
1033
1116
  props.onClick ? props.onClick(e) : () => console.warn('onClick Missing');
1034
1117
  }
1035
- }, disabled: props.disabled || false }, { children: props.html ? jsx("span", { dangerouslySetInnerHTML: { __html: props.html } }) : props.children })));
1118
+ }, disabled: props.disabled || false, children: props.html ? jsx("span", { dangerouslySetInnerHTML: { __html: props.html } }) : props.children })));
1036
1119
  } }));
1037
1120
  });
1038
1121
 
@@ -1134,7 +1217,7 @@ const cleanProps = (props) => {
1134
1217
  delete _props[k];
1135
1218
  }
1136
1219
  });
1137
- let _extras = [`as`, `hover`, `bref`];
1220
+ let _extras = [`as`, `hover`, `bref`, `tag`];
1138
1221
  _extras.map(x => x in _props && delete _props[x]);
1139
1222
  return _props;
1140
1223
  };
@@ -1186,7 +1269,7 @@ const buildFormData = (data) => {
1186
1269
  [data['files']].map((f) => formData.append('files[]', f));
1187
1270
  return formData;
1188
1271
  };
1189
- const grab = async (uri, data, timeout = 60, fd = null, progress, bearer = `__ha`) => {
1272
+ const withRest = async (uri, data, timeout = 60, fd = null, progress, bearer = `__ha`) => {
1190
1273
  var Bearer = getCookie(bearer) || `${randstr(8)}^${randstr(8)}`;
1191
1274
  window['__grabToken'] = axios.CancelToken.source();
1192
1275
  if (fd) {
@@ -1291,7 +1374,7 @@ const filterHTMLProps = (props) => {
1291
1374
  });
1292
1375
  return filter;
1293
1376
  };
1294
- const uuid = () => nanoid();
1377
+ const uuid = (len = 21) => nanoid(len);
1295
1378
  const addScript = (src, callback) => {
1296
1379
  var s = document.createElement('script');
1297
1380
  s.setAttribute('src', src);
@@ -1374,13 +1457,75 @@ const getMousePosition = e => {
1374
1457
  pos.y = 0;
1375
1458
  return pos;
1376
1459
  };
1460
+ const copyToClipboard = (str, callback) => {
1461
+ const el = document.createElement('textarea');
1462
+ let storeContentEditable = el.contentEditable;
1463
+ let storeReadOnly = el.readOnly;
1464
+ el.value = str;
1465
+ el.contentEditable = `true`;
1466
+ el.readOnly = false;
1467
+ el.setAttribute('readonly', `false`);
1468
+ el.setAttribute('contenteditable', `true`);
1469
+ el.style.position = 'absolute';
1470
+ el.style.left = '-999999999px';
1471
+ document.body.appendChild(el);
1472
+ const selected = document.getSelection().rangeCount > 0
1473
+ ? document.getSelection().getRangeAt(0)
1474
+ : false;
1475
+ el.select();
1476
+ el.setSelectionRange(0, 999999);
1477
+ document.execCommand('copy');
1478
+ document.body.removeChild(el);
1479
+ if (selected) {
1480
+ document.getSelection().removeAllRanges();
1481
+ document.getSelection().addRange(selected);
1482
+ }
1483
+ el.contentEditable = storeContentEditable;
1484
+ el.readOnly = storeReadOnly;
1485
+ if (callback)
1486
+ callback();
1487
+ };
1488
+ /**
1489
+ * Format bytes as human-readable text.
1490
+ *
1491
+ * @param bytes Number of bytes.
1492
+ * @param si True to use metric (SI) units, aka powers of 1000. False to use
1493
+ * binary (IEC), aka powers of 1024.
1494
+ * @param dp Number of decimal places to display.
1495
+ *
1496
+ * @return Formatted string.
1497
+ */
1498
+ const formatSize = (bytes, si = false, dp = 1) => {
1499
+ const thresh = si ? 1000 : 1024;
1500
+ if (Math.abs(bytes) < thresh) {
1501
+ return bytes + ' B';
1502
+ }
1503
+ const units = ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
1504
+ let u = -1;
1505
+ const r = 10 ** dp;
1506
+ do {
1507
+ bytes /= thresh;
1508
+ ++u;
1509
+ } while (Math.round(Math.abs(bytes) * r) / r >= thresh && u < units.length - 1);
1510
+ return bytes.toFixed(dp) + ' ' + units[u];
1511
+ };
1512
+ const slugify = (...args) => {
1513
+ const value = args.join(' ');
1514
+ return value
1515
+ .normalize('NFD') // split an accented letter in the base letter and the acent
1516
+ .replace(/[\u0300-\u036f]/g, '') // remove all previously split accents
1517
+ .toLowerCase()
1518
+ .trim()
1519
+ .replace(/[^a-z0-9 ]/g, '') // remove all chars not letters, numbers and spaces (to be replaced)
1520
+ .replace(/\s+/g, '-'); // separator
1521
+ };
1377
1522
 
1378
1523
  const AppMain = forwardRef((props, ref) => {
1379
1524
  // const { dispatch } = useStore()
1380
1525
  // if("theme" in props && !theme){
1381
1526
  // dispatch(setTheme(props.theme));
1382
1527
  // }
1383
- return (jsx(ClassNames, { children: ({ css, cx }) => jsx("main", Object.assign({ className: `${props.as ? props.as : `zuz-app`} ${cx(css `${buildCSS(props)} &:hover {${buildCSS(props.hover || {})}} &:active {${buildCSS(props.active || {})}}`)}` }, { children: props.children })) }));
1528
+ return (jsx(ClassNames, { children: ({ css, cx }) => jsx("main", { className: `${props.as ? props.as : `zuz-app`} ${cx(css `${buildCSS(props)} &:hover {${buildCSS(props.hover || {})}} &:active {${buildCSS(props.active || {})}}`)}`, children: props.children }) }));
1384
1529
  });
1385
1530
  const App = forwardRef((props, ref) => {
1386
1531
  return (jsx(AppProvider, { children: jsx(AppMain, {}) }));
@@ -1432,7 +1577,7 @@ function Checkbox(props) {
1432
1577
  }
1433
1578
 
1434
1579
  const Spinner = (props) => {
1435
- return (jsxs(Box, Object.assign({ rel: true, w: props.size, h: props.size, zIndex: `1`, useSelect: `none` }, { children: [jsx(Box, { abs: true, 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 }), jsx(Box, { abs: true, 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 })] })));
1580
+ return (jsxs(Box, { rel: true, w: props.size, h: props.size, zIndex: `1`, useSelect: `none`, children: [jsx(Box, { abs: true, 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 }), jsx(Box, { abs: true, 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 })] }));
1436
1581
  };
1437
1582
  Spinner.defaultProps = {
1438
1583
  size: 30,
@@ -1453,11 +1598,11 @@ const Heading = forwardRef((props, ref) => {
1453
1598
  const { children, as, h } = props;
1454
1599
  let Tag = `h${h || 1}`;
1455
1600
  const HeadingTag = Tag;
1456
- return (jsx(ClassNames, { children: ({ css, cx }) => jsx(HeadingTag, Object.assign({ className: `${as ? `${as} ` : ``}${cx(css `${buildCSS(props)}`)}`, ref: ref }, { children: props.html ? jsx("span", { dangerouslySetInnerHTML: { __html: props.html } }) : children })) }));
1601
+ return (jsx(ClassNames, { children: ({ css, cx }) => jsx(HeadingTag, { className: `${as ? `${as} ` : ``}${cx(css `${buildCSS(props)}`)}`, ref: ref, children: props.html ? jsx("span", { dangerouslySetInnerHTML: { __html: props.html } }) : children }) }));
1457
1602
  });
1458
1603
 
1459
1604
  const Cover = (props) => {
1460
- return (jsx(Box, Object.assign({ abs: true, fill: true, bgFilter: props.backdrop ? `saturate(${props.backdrop.saturate}%) blur(${props.backdrop.blur}px)` : undefined, zIndex: `2`, bg: props.bg }, { children: jsxs(Box, Object.assign({ abs: true, abc: true, aic: true, jcc: true, flex: true, dir: `cols`, gap: 20 }, { children: [jsx(Spinner, {}, `cover-spinner`), props.label && jsx(Heading, Object.assign({ size: 16, as: `f`, opacity: 0.7 }, { children: props.label }), `cover-label`)] }), `cover-shadow`) }), `cover-cloud`));
1605
+ return (jsx(Box, { abs: true, fill: true, bgFilter: props.backdrop ? `saturate(${props.backdrop.saturate}%) blur(${props.backdrop.blur}px)` : undefined, zIndex: `2`, bg: props.bg, children: jsxs(Box, { abs: true, abc: true, aic: true, jcc: true, flex: true, dir: `cols`, gap: 20, children: [jsx(Spinner, {}, `cover-spinner`), props.label && jsx(Heading, { size: 16, as: `f`, opacity: 0.7, children: props.label }, `cover-label`)] }, `cover-shadow`) }, `cover-cloud`));
1461
1606
  };
1462
1607
  Cover.defaultProps = {
1463
1608
  bg: `rgba(0,0,0,0.5)`,
@@ -1514,7 +1659,7 @@ Form.propTypes = {
1514
1659
 
1515
1660
  const Icon = forwardRef((props, ref) => {
1516
1661
  const { as, path, size, color, hover } = props;
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}`)) })));
1662
+ return (jsx(Box, { 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}`)) }));
1518
1663
  });
1519
1664
 
1520
1665
  const Image$1 = forwardRef((props, ref) => {
@@ -1652,7 +1797,7 @@ class Masonry extends Component$1 {
1652
1797
  classNameOutput = 'my-masonry-grid';
1653
1798
  }
1654
1799
  }
1655
- return (jsx("div", Object.assign({}, rest, { className: classNameOutput }, { children: this.renderColumns() })));
1800
+ return (jsx("div", Object.assign({}, rest, { className: classNameOutput, children: this.renderColumns() })));
1656
1801
  }
1657
1802
  }
1658
1803
 
@@ -1679,7 +1824,7 @@ const Spacer = ({ w, h }) => {
1679
1824
 
1680
1825
  const Text = forwardRef((props, ref) => {
1681
1826
  const { children, as } = props;
1682
- return (jsx(ClassNames, { children: ({ css, cx }) => jsx("p", Object.assign({ className: `${as ? `${as} ` : ``}${cx(css `${buildCSS(props)}`)}`, ref: ref }, { children: props.html ? jsx("span", { dangerouslySetInnerHTML: { __html: props.html } }) : children })) }));
1827
+ return (jsx(ClassNames, { children: ({ css, cx }) => jsx("p", { className: `${as ? `${as} ` : ``}${cx(css `${buildCSS(props)}`)}`, ref: ref, children: props.html ? jsx("span", { dangerouslySetInnerHTML: { __html: props.html } }) : children }) }));
1683
1828
  });
1684
1829
 
1685
1830
  const Tweet = (props) => {
@@ -1714,11 +1859,6 @@ const Tweet = (props) => {
1714
1859
  return (jsx(Box, { as: `tweet`, weight: 1, bref: _tweet }));
1715
1860
  };
1716
1861
 
1717
- const ContextMenu = forwardRef((props, ref) => {
1718
- const { as, size, color, hover, pos, items } = props;
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}`)) })));
1720
- });
1721
-
1722
1862
  const buildElement = (el) => {
1723
1863
  switch (el.is) {
1724
1864
  case "Box":
@@ -1736,4 +1876,4 @@ const Header = forwardRef((props, ref) => {
1736
1876
  return (jsx(Fragment, { children: buildComponent(data) }));
1737
1877
  });
1738
1878
 
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 };
1879
+ export { App, Component as Block, Box, Button, Checkbox, 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, copyToClipboard, createSlice, el, filterHTMLProps, filterStyleProps, formatSize, generateModalRoutes, generatePreservedRoutes, generateRegularRoutes, getCookie, getHostname, getMousePosition, getUriParams, imgPromiseFactory, isEmail, isIPv4, isUrl, parseFilename, randstr, removeCookie, rgb2hex, setCSSVar, setCookie, shuffleArray, slugify, ucfirst, useContextMenu, useDevice, useDispatch, useImage, useLang, useRender, useResizeObserver, useStore, useTheme, useToast, uuid, withRest };
package/dist/styles.css CHANGED
@@ -458,7 +458,7 @@ button {
458
458
  }
459
459
 
460
460
  .zuz-contextmenu {
461
- min-width: 220px;
461
+ width: 220px;
462
462
  border-radius: 5px;
463
463
  padding: 4px;
464
464
  background: rgba(34, 34, 34, 0.5);
@@ -476,7 +476,7 @@ button {
476
476
  border-radius: 4px;
477
477
  }
478
478
  .zuz-contextmenu button:hover {
479
- background: #385fd2;
479
+ background: #5183ff;
480
480
  }
481
481
  .zuz-contextmenu .line {
482
482
  height: 1px;
package/jest.config.js ADDED
@@ -0,0 +1,7 @@
1
+ module.exports = {
2
+ testMatch: ['**/+(*.)+(spec|test).+(ts|js)?(x)'],
3
+ moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
4
+ transform: {
5
+ '^.+\\.tsx?$': 'ts-jest'
6
+ }
7
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zuzjs/ui",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "exports": {