@zuzjs/ui 0.2.4 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/README.md +1 -0
  2. package/dist/index.js +214 -15
  3. package/package.json +4 -2
  4. package/src/actions/addForm.tsx +0 -0
  5. package/src/actions/index.tsx +29 -0
  6. package/src/actions/redo.tsx +1 -0
  7. package/src/actions/reset.tsx +1 -0
  8. package/src/actions/undo.tsx +1 -0
  9. package/src/comps/app.tsx +34 -0
  10. package/src/comps/box.tsx +23 -0
  11. package/src/comps/button.tsx +45 -0
  12. package/src/comps/checkbox.tsx +74 -0
  13. package/src/comps/component.tsx +32 -0
  14. package/src/comps/contextmenu.tsx +43 -0
  15. package/src/comps/cover.tsx +34 -0
  16. package/src/comps/form.tsx +89 -0
  17. package/src/comps/heading.tsx +31 -0
  18. package/src/comps/icon.tsx +36 -0
  19. package/src/comps/image.tsx +26 -0
  20. package/src/comps/input.tsx +80 -0
  21. package/src/comps/masonry.tsx +192 -0
  22. package/src/comps/placeholder.tsx +58 -0
  23. package/src/comps/root.tsx +32 -0
  24. package/src/comps/select.tsx +63 -0
  25. package/src/comps/spacer.tsx +20 -0
  26. package/src/comps/spinner.tsx +36 -0
  27. package/src/comps/text.tsx +27 -0
  28. package/src/comps/toaster.tsx +115 -0
  29. package/src/comps/tweet.tsx +48 -0
  30. package/src/context/AppContext.tsx +3 -0
  31. package/src/context/AppProvider.tsx +101 -0
  32. package/src/context/_AppProvider.tsx +116 -0
  33. package/src/context/combineReducers.tsx +47 -0
  34. package/src/context/combineState.tsx +14 -0
  35. package/src/context/createSlice.tsx +40 -0
  36. package/src/context/index.tsx +6 -0
  37. package/src/context/reduceReducers.tsx +6 -0
  38. package/src/context/store/appbase.tsx +19 -0
  39. package/src/context/store/theme.tsx +53 -0
  40. package/src/core/defaultTheme.ts +89 -0
  41. package/src/core/extractCurrentDesignState.tsx +0 -0
  42. package/src/core/index.ts +285 -0
  43. package/src/core/router.ts +86 -0
  44. package/src/core/styles.ts +361 -0
  45. package/src/hooks/index.tsx +8 -0
  46. package/src/hooks/useAppReducer.tsx +40 -0
  47. package/src/hooks/useChooseEffect.tsx +6 -0
  48. package/src/hooks/useDevice.tsx +164 -0
  49. package/src/hooks/useDispatch.tsx +37 -0
  50. package/src/hooks/useImage.tsx +58 -0
  51. package/src/hooks/useResizeObserver.tsx +84 -0
  52. package/src/hooks/useRouter.tsx +45 -0
  53. package/src/hooks/useSelector.tsx +9 -0
  54. package/src/hooks/useStore.tsx +27 -0
  55. package/src/hooks/useTheme.tsx +9 -0
  56. package/src/hooks/useToast.tsx +11 -0
  57. package/src/index.tsx +33 -0
  58. package/src/kit/Builder.tsx +18 -0
  59. package/src/kit/Component.tsx +32 -0
  60. package/src/kit/Header.tsx +21 -0
  61. package/src/redux/slices/app.js +26 -0
  62. package/src/redux/slices/form.js +46 -0
  63. package/src/redux/store.js +33 -0
  64. package/src/scss/constants.scss +4 -0
  65. package/src/scss/mixins.scss +3 -0
  66. package/src/scss/props.scss +60 -0
  67. package/src/scss/style.scss +106 -0
@@ -0,0 +1,285 @@
1
+ import {
2
+ cloneElement,
3
+ isValidElement
4
+ } from 'react'
5
+ import type { ReactNode, ReactElement } from 'react'
6
+ import Children from 'react-children-utilities';
7
+ import Cookies from 'js-cookie'
8
+ import axios from 'axios'
9
+ import {
10
+ cssPropsDirect,
11
+ cssProps,
12
+ cssPropsVals,
13
+ cssPropsIgnore,
14
+ cssColors
15
+ } from './styles'
16
+ import { nanoid } from 'nanoid'
17
+ import Input from '../comps/input'
18
+ import Select from '../comps/select'
19
+ import Button from '../comps/button'
20
+ import { generateModalRoutes, generatePreservedRoutes, generateRegularRoutes } from './router'
21
+
22
+ const makeCSSValue = (k : any, v : any, o : any) => {
23
+ let ignore = cssPropsIgnore.indexOf(o) == -1;
24
+ if(k in cssPropsDirect && ignore == true){
25
+ // return cssPropsDirect[k];
26
+ return cssPropsDirect[k].indexOf(`__VALUE__`) > - 1 ?
27
+ cssPropsDirect[k].replaceAll(`__VALUE__`, `${v}${"number" == typeof v ? `px` : ``}`)
28
+ : cssPropsDirect[k];
29
+ }
30
+ let unit = "number" == typeof v && ignore ? `px` : ``;
31
+ if(cssColors.indexOf(v) > -1){
32
+ v = `var(--colors-${v.replaceAll(`.`, `-`)})`;
33
+ unit = ``;
34
+ }
35
+ else if(v in cssPropsVals){
36
+ v = cssPropsVals[v];
37
+ }
38
+ return `${k}:${v}${unit};`;
39
+ }
40
+
41
+ const buildCSS = (props : any) => {
42
+ let css = ``;
43
+ Object.keys(props).map(k => {
44
+ css += k in cssProps ? makeCSSValue(cssProps[k], props[k], k) : '';
45
+ });
46
+ return css;
47
+ }
48
+
49
+ const setCSSVar = ( key : string, val : string ) => {
50
+ document.documentElement.style.setProperty(`--${key}`, val);
51
+ }
52
+
53
+ const isUrl = (u : string) => {
54
+ let url;
55
+ try{
56
+ url = new URL(u);
57
+ }catch(_){
58
+ return false;
59
+ }
60
+ return url.protocol === 'http:' || url.protocol === 'https:'
61
+ }
62
+
63
+ const isEmail = (e : string) => {
64
+ let reg = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/ ;
65
+ return reg.test(e);
66
+ }
67
+
68
+ const isIPv4 = (ipaddress : string) => {
69
+ return /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(ipaddress);
70
+ }
71
+
72
+ const randstr = function(len? : number){
73
+ var text = ""; var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
74
+ len = len || 10;
75
+ for (var i = 0; i < len; i++){
76
+ text += possible.charAt(Math.floor(Math.random() * possible.length));
77
+ }
78
+ return text;
79
+ }
80
+
81
+ const setCookie = (key : string, value : any, expiry? : number) => Cookies.set(key, value, { expires: expiry || 7 })
82
+
83
+ const getCookie = (key : string) => Cookies.get(key) || null;
84
+
85
+ const removeCookie = (key : string) => Cookies.remove(key)
86
+
87
+ const buildFormData = (data : object) : FormData => {
88
+ var formData = new FormData();
89
+ var _data = Cookies.get();
90
+ Object.keys(_data).map(k => formData.append(k, _data[k]));
91
+ Object.keys(data).filter(x => x != 'files').map(k => formData.append(k, data[k]));
92
+ if('files' in data) [data['files']].map((f: any) => formData.append('files[]', f));
93
+ return formData;
94
+ }
95
+
96
+ const grab = async (uri : string, data : object, timeout : number = 60, fd : object = null, progress? : Function, bearer : string = `__ha`) => {
97
+ var Bearer = getCookie(bearer) || `${randstr(8)}^${randstr(8)}`;
98
+ window['__grabToken'] = axios.CancelToken.source();
99
+ if(fd){
100
+ return new Promise((resolve, reject) => {
101
+ axios({
102
+ method: "post",
103
+ url: uri,
104
+ data: buildFormData(data),
105
+ timeout: 1000 * timeout,
106
+ cancelToken: window['__grabToken'].token,
107
+ headers: {
108
+ 'Content-Type': 'multipart/form-data',
109
+ 'Authorization': `Bearer ${Bearer}`
110
+ },
111
+ onUploadProgress: ev => {
112
+ //TODO: Add progress
113
+ // if(progress) progress(ev.)
114
+ }
115
+ })
116
+ .then(resp => {
117
+ if(resp.data && "kind" in resp.data){
118
+ resolve(resp.data)
119
+ }else{
120
+ reject(resp.data)
121
+ }
122
+ })
123
+ .catch(err => reject(err));
124
+ })
125
+ }
126
+ return new Promise((resolve, reject) => {
127
+ axios.post(
128
+ uri,
129
+ {
130
+ ...Cookies.get(),
131
+ ...data,
132
+ __ustmp: new Date().getTime() / 1000
133
+ },
134
+ {
135
+ timeout: 1000 * timeout,
136
+ headers: {
137
+ 'Content-Type': 'application/json',
138
+ 'Authorization': `Bearer ${Bearer}`
139
+ },
140
+ cancelToken: window['__grabToken'].token
141
+ }
142
+ )
143
+ .then(resp => {
144
+ if(resp.data && "kind" in resp.data){
145
+ resolve(resp.data)
146
+ }else{
147
+ reject(resp.data)
148
+ }
149
+ })
150
+ .catch(err => reject(err));
151
+ })
152
+ }
153
+
154
+ const el = (e : string) => document.querySelector(e);
155
+
156
+ const byName = (e : string) => document.querySelector(`*[name="${e}"]`);
157
+
158
+ const byId = (e : string) => document.getElementById(e);
159
+
160
+ const addProps = (children : any, prop : any) => {
161
+ let form = {}
162
+ let allowedFields = [Input, Select, Button];
163
+ let child = Children.deepMap(children, c => {
164
+ if(allowedFields.indexOf(c['type']) > -1 && c['props'] && !form[c['props'].name]){
165
+ form[c['props'].name] = c['props'].value || null;
166
+ }
167
+ let Clone = cloneElement(c as ReactElement<any>, prop);
168
+ return Clone;
169
+ });
170
+
171
+ return {
172
+ children : child,
173
+ fields: form
174
+ }
175
+ }
176
+
177
+ const ucfirst = ( str : string ) => {
178
+ return str.charAt(0).toUpperCase() + str.slice(1);
179
+ }
180
+
181
+ const filterStyleProps = (props : any) => {
182
+
183
+ const pks = Object.keys(props);
184
+ const css = Object.keys(cssProps);
185
+ let filter = {}
186
+ css.filter(x => pks.includes(x))
187
+
188
+ // .map(k => filter[k] = props[k].toString());
189
+ return filter;
190
+ // const allowed = Object.keys(props);
191
+ // let allowed = Object.keys(cssProps);
192
+
193
+ // return Object.keys(props)
194
+ // .filter( k => allowed.includes(k))
195
+ // .reduce( (o, k) => {
196
+ // // console.log(o)
197
+ // console.log(k, props[k])
198
+ // // o[k] = props[k].toString();
199
+ // // return o;
200
+ // })
201
+ // return [props].filter( row => (
202
+ // Object.keys(row)
203
+ // .map(key => css.includes(key))
204
+ // ));
205
+ }
206
+
207
+ const filterHTMLProps = (props : any) => {
208
+ const pks = Object.keys(props);
209
+ const css = Object.keys(cssProps);
210
+ let filter = {}
211
+ pks.filter(x => {
212
+ if(x!= `for` && !css.includes(x)){
213
+ filter[x] = props[x]
214
+ }
215
+ })
216
+ return filter;
217
+ }
218
+
219
+ const uuid = () => nanoid()
220
+
221
+ const addScript = (src: string, callback: () => any) => {
222
+ var s = document.createElement('script')
223
+ s.setAttribute('src', src)
224
+ s.addEventListener('load', callback, false)
225
+ document.body.appendChild(s)
226
+ }
227
+
228
+ const shuffleArray = array => {
229
+ for (let i = array.length - 1; i > 0; i--) {
230
+ const j = Math.floor(Math.random() * (i + 1));
231
+ [array[i], array[j]] = [array[j], array[i]];
232
+ }
233
+ return array
234
+ }
235
+
236
+ const getUriParams = () => {
237
+ var search = location.search.substring(1);
238
+ if(search=='') return JSON.parse('{}');
239
+ var xny = {};
240
+ if("URLSearchParams" in window){
241
+ var items = new URLSearchParams(search);
242
+ for(const [k, v] of items){
243
+ xny[k] = v || ``;
244
+ }
245
+ }else{
246
+ try{
247
+ xny = JSON.parse('{"' + decodeURI(search).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g,'":"') + '"}');
248
+ }catch(e){
249
+ xny = {};
250
+ }
251
+ }
252
+ return xny;
253
+ }
254
+
255
+ const rgb2hex = rgb => `#${rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/).slice(1).map(n => parseInt(n, 10).toString(16).padStart(2, '0')).join('')}`
256
+
257
+ export {
258
+ addProps,
259
+ addScript,
260
+ buildCSS,
261
+ buildFormData,
262
+ byName,
263
+ byId,
264
+ el,
265
+ grab,
266
+ isEmail,
267
+ isIPv4,
268
+ isUrl,
269
+ randstr,
270
+ setCSSVar,
271
+ getCookie,
272
+ setCookie,
273
+ removeCookie,
274
+ ucfirst,
275
+ filterStyleProps,
276
+ filterHTMLProps,
277
+ uuid,
278
+ shuffleArray,
279
+ getUriParams,
280
+ rgb2hex,
281
+ generateModalRoutes,
282
+ generatePreservedRoutes,
283
+ generateRegularRoutes
284
+ }
285
+
@@ -0,0 +1,86 @@
1
+ export const patterns = {
2
+ route: [/^.*\/src\/pages\/|\.(jsx|tsx)$/g, ''],
3
+ splat: [/\[\.{3}\w+\]/g, '*'],
4
+ param: [/\[([^\]]+)\]/g, ':$1'],
5
+ slash: [/^index$|\./g, '/'],
6
+ optional: [/^-(:?[\w-]+)/, '$1?'],
7
+ } as const
8
+
9
+ type PreservedKey = '_app' | '404'
10
+ type BaseRoute = { id?: string; path?: string; children?: BaseRoute[] } & Record<string, any>
11
+
12
+ export const generatePreservedRoutes = <T>(files: Record<string, T | any>): Partial<Record<PreservedKey, T>> => {
13
+ return Object.keys(files).reduce((routes, key) => {
14
+ const path = key.replace(...patterns.route)
15
+ return { ...routes, [path]: files[key] }
16
+ }, {})
17
+ }
18
+
19
+ export const generateRegularRoutes = <T extends BaseRoute, M>(
20
+ files: Record<string, any>,
21
+ buildRoute: (module: M, key: string) => T
22
+ ) => {
23
+ const filteredRoutes = Object.keys(files).filter((key) => !key.includes('/_') || /_layout\.(jsx|tsx)$/.test(key))
24
+ return filteredRoutes.reduce<T[]>((routes, key) => {
25
+ const module = files[key]
26
+ const route = { id: key.replace(...patterns.route), ...buildRoute(module, key) }
27
+
28
+ const segments = key
29
+ .replace(...patterns.route)
30
+ .replace(...patterns.splat)
31
+ .replace(...patterns.param)
32
+ .split('/')
33
+ .filter(Boolean)
34
+
35
+ segments.reduce((parent, segment, index) => {
36
+ const path = segment.replace(...patterns.slash).replace(...patterns.optional)
37
+ const root = index === 0
38
+ const leaf = index === segments.length - 1 && segments.length > 1
39
+ const node = !root && !leaf
40
+ const layout = segment === '_layout'
41
+ const group = /\(\w+\)/.test(path)
42
+ const insert = /^\w|\//.test(path) ? 'unshift' : 'push'
43
+
44
+ if (root) {
45
+ const last = segments.length === 1
46
+ if (last) {
47
+ routes.push({ path, ...route })
48
+ return parent
49
+ }
50
+ }
51
+
52
+ if (root || node) {
53
+ const current = root ? routes : parent.children
54
+ const found = current?.find((route) => route.path === path || route.id?.split('@')?.[0] === path)
55
+ const props = group ? (route?.component ? { id: path, path: '/' } : { id: path }) : { path }
56
+ if (found) found.children ??= []
57
+ else current?.[insert]({ ...props, children: [] })
58
+ return found || (current?.[insert === 'unshift' ? 0 : current.length - 1] as BaseRoute)
59
+ }
60
+
61
+ if (layout) {
62
+ return Object.assign(parent, { ...route, id: `${parent.id || parent.path}@${route.id}` })
63
+ }
64
+
65
+ if (leaf) {
66
+ parent?.children?.[insert](route?.index ? route : { path, ...route })
67
+ }
68
+
69
+ return parent
70
+ }, {} as BaseRoute)
71
+
72
+ return routes
73
+ }, [])
74
+ }
75
+
76
+ export const generateModalRoutes = <T>(files: Record<string, T | any>): Record<string, T> => {
77
+ return Object.keys(files).reduce((modals, key) => {
78
+ const path = key
79
+ .replace(...patterns.route)
80
+ .replace(/\+|\(\w+\)\//g, '')
81
+ .replace(/(\/)?index/g, '')
82
+ .replace(/\./g, '/')
83
+
84
+ return { ...modals, [`/${path}`]: files[key]?.default }
85
+ }, {})
86
+ }