@faasjs/react 3.7.0-beta.0 → 3.7.0-beta.10

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
@@ -20,6 +20,7 @@ function equal(a, b) {
20
20
  if ((a === null || a === void 0) && (b === null || b === void 0))
21
21
  return true;
22
22
  if (typeof a !== typeof b) return false;
23
+ if (b === null || b === void 0) return false;
23
24
  const ctor = a.constructor;
24
25
  if (ctor !== b.constructor) return false;
25
26
  switch (ctor) {
@@ -47,11 +48,8 @@ function equal(a, b) {
47
48
  case Promise:
48
49
  return a === b;
49
50
  case Object: {
50
- const keys = Object.keys(a);
51
- if (keys.length !== Object.keys(b).length) return false;
52
- for (const key of keys) {
51
+ for (const key of /* @__PURE__ */ new Set([...Object.keys(a), ...Object.keys(b)]))
53
52
  if (!equal(a[key], b[key])) return false;
54
- }
55
53
  return true;
56
54
  }
57
55
  default:
@@ -79,6 +77,24 @@ function useEqualCallback(callback, dependencies) {
79
77
  useEqualMemoize(dependencies)
80
78
  );
81
79
  }
80
+ function usePrevious(value) {
81
+ const ref = react.useRef();
82
+ react.useEffect(() => {
83
+ ref.current = value;
84
+ });
85
+ return ref.current;
86
+ }
87
+ function useSplittingState(initialStates) {
88
+ const states = {};
89
+ for (const key of Object.keys(initialStates)) {
90
+ const state = react.useState(initialStates[key]);
91
+ Object.assign(states, {
92
+ [key]: state[0],
93
+ [`set${String(key).charAt(0).toUpperCase()}${String(key).slice(1)}`]: state[1]
94
+ });
95
+ }
96
+ return states;
97
+ }
82
98
  function createSplittingContext(defaultValue) {
83
99
  const keys = Array.isArray(defaultValue) ? defaultValue : Object.keys(defaultValue);
84
100
  const defaultValues = Array.isArray(defaultValue) ? keys.reduce((prev, cur) => {
@@ -88,17 +104,20 @@ function createSplittingContext(defaultValue) {
88
104
  const contexts = {};
89
105
  for (const key of keys) contexts[key] = react.createContext(defaultValues[key]);
90
106
  function Provider(props) {
107
+ const states = props.initializeStates ? useSplittingState(props.initializeStates) : {};
91
108
  let children = props.memo ? useEqualMemo(
92
109
  () => props.children,
93
110
  props.memo === true ? [] : props.memo
94
111
  ) : props.children;
95
112
  for (const key of keys) {
96
113
  const Context = contexts[key];
97
- const value = props.value?.[key] ?? defaultValues[key];
114
+ const value = props.value?.[key] ?? states[key] ?? defaultValues[key];
98
115
  children = /* @__PURE__ */ jsxRuntime.jsx(Context.Provider, { value, children });
99
116
  }
100
117
  return children;
101
118
  }
119
+ Provider.displayName = "SplittingContextProvider";
120
+ Provider.whyDidYouRender = true;
102
121
  function use() {
103
122
  return useConstant(() => {
104
123
  const obj = /* @__PURE__ */ Object.create(null);
@@ -110,19 +129,12 @@ function createSplittingContext(defaultValue) {
110
129
  return Object.freeze(obj);
111
130
  });
112
131
  }
132
+ use.whyDidYouRender = true;
113
133
  return {
114
134
  Provider,
115
135
  use
116
136
  };
117
137
  }
118
- function useSplittingState(initialStates) {
119
- const states = {};
120
- for (const key of Object.keys(initialStates)) {
121
- const state = react.useState(initialStates[key]);
122
- Object.assign(states, { [key]: state[0], [`set${String(key).charAt(0).toUpperCase()}${String(key).slice(1)}`]: state[1] });
123
- }
124
- return states;
125
- }
126
138
  function FaasDataWrapper(props) {
127
139
  const request = getClient(props.baseUrl).useFaas(
128
140
  props.action,
@@ -155,10 +167,22 @@ function FaasDataWrapper(props) {
155
167
  ]);
156
168
  return child;
157
169
  }
170
+ FaasDataWrapper.displayName = "FaasDataWrapper";
158
171
  FaasDataWrapper.whyDidYouRender = true;
159
172
  function withFaasData(Component2, faasProps) {
160
173
  return (props) => /* @__PURE__ */ jsxRuntime.jsx(FaasDataWrapper, { ...faasProps, children: /* @__PURE__ */ jsxRuntime.jsx(Component2, { ...props }) });
161
174
  }
175
+
176
+ // src/faas.ts
177
+ async function faas(action, params, options) {
178
+ const client = getClient(options?.baseUrl);
179
+ if (client.onError)
180
+ return client.browserClient.action(action, params, options).catch(async (res) => {
181
+ await client.onError(action, params)(res);
182
+ return Promise.reject(res);
183
+ });
184
+ return client.browserClient.action(action, params, options);
185
+ }
162
186
  function useFaas(action, defaultParams, options = {}) {
163
187
  const [loading, setLoading] = react.useState(true);
164
188
  const [data, setData] = react.useState();
@@ -257,17 +281,6 @@ function useFaas(action, defaultParams, options = {}) {
257
281
  };
258
282
  }
259
283
  useFaas.whyDidYouRender = true;
260
-
261
- // src/faas.ts
262
- async function faas(action, params, options) {
263
- const client = getClient(options?.baseUrl);
264
- if (client.onError)
265
- return client.browserClient.action(action, params, options).catch(async (res) => {
266
- await client.onError(action, params)(res);
267
- return Promise.reject(res);
268
- });
269
- return client.browserClient.action(action, params, options);
270
- }
271
284
  var clients = {};
272
285
  function FaasReactClient({ baseUrl, options, onError } = {
273
286
  baseUrl: "/"
@@ -293,6 +306,7 @@ function getClient(host) {
293
306
  return client;
294
307
  }
295
308
  var ErrorBoundary = class extends react.Component {
309
+ static displayName = "ErrorBoundary";
296
310
  static whyDidYouRender = true;
297
311
  constructor(props) {
298
312
  super(props);
@@ -328,146 +342,200 @@ var ErrorBoundary = class extends react.Component {
328
342
  return this.props.children;
329
343
  }
330
344
  };
331
- ErrorBoundary.whyDidYouRender = true;
332
345
  var OptionalWrapper = ({ condition, Wrapper, wrapperProps, children }) => {
333
346
  return condition ? /* @__PURE__ */ jsxRuntime.jsx(Wrapper, { ...wrapperProps, children }) : /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
334
347
  };
348
+ OptionalWrapper.displayName = "OptionalWrapper";
335
349
  OptionalWrapper.whyDidYouRender = true;
336
350
 
337
351
  // src/Form/context.tsx
338
- var FormContext = createSplittingContext(["items", "onSubmit", "elements", "submitting", "setSubmitting", "values", "setValues"]);
352
+ var FormContext = createSplittingContext([
353
+ "items",
354
+ "onSubmit",
355
+ "Elements",
356
+ "lang",
357
+ "submitting",
358
+ "setSubmitting",
359
+ "values",
360
+ "setValues",
361
+ "errors",
362
+ "setErrors",
363
+ "rules"
364
+ ]);
339
365
  var FormContextProvider = FormContext.Provider;
340
366
  var useFormContext = FormContext.use;
341
- function FormLabel(props) {
342
- const { elements } = useFormContext();
343
- if (props.label?.Label) return /* @__PURE__ */ jsxRuntime.jsx(props.label.Label, { ...props });
344
- return /* @__PURE__ */ jsxRuntime.jsx(elements.label, { ...props });
367
+ function FormItem(props) {
368
+ const { Elements, values, setValues, errors } = useFormContext();
369
+ const Label = props.label?.Label ?? Elements.Label;
370
+ const Input = props.input?.Input ?? Elements.Input;
371
+ return /* @__PURE__ */ jsxRuntime.jsx(Label, { name: props.name, ...props.label, error: errors[props.name], children: /* @__PURE__ */ jsxRuntime.jsx(
372
+ Input,
373
+ {
374
+ name: props.name,
375
+ value: values[props.name],
376
+ onChange: (v) => setValues((prev) => ({
377
+ ...prev,
378
+ [props.name]: v
379
+ }))
380
+ }
381
+ ) });
345
382
  }
383
+ FormItem.displayName = "FormItem";
384
+ FormItem.whyDidYouRender = true;
346
385
  function FormBody() {
347
386
  const { items } = useFormContext();
348
- return items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(FormLabel, { ...item }, item.name));
387
+ return items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(FormItem, { ...item }, item.name));
349
388
  }
350
- function processValue(input, rules) {
351
- let value = input;
352
- if (typeof input === "object" && "target" in input) {
353
- value = input.target.value;
354
- }
355
- switch (rules?.type) {
356
- case "number":
357
- return Number(value);
358
- case "string":
359
- return String(value);
360
- default:
361
- return value;
389
+ FormBody.displayName = "FormBody";
390
+ FormBody.whyDidYouRender = true;
391
+
392
+ // src/Form/rules.ts
393
+ var FormDefaultRules = {
394
+ required: async (value, _, lang) => {
395
+ if (value === null || value === void 0 || value === "" || Number.isNaN(value)) {
396
+ throw Error(lang?.required);
397
+ }
398
+ },
399
+ type: async (value, options, lang) => {
400
+ switch (options) {
401
+ case "string":
402
+ if (typeof value !== "string") throw Error(lang?.string);
403
+ break;
404
+ case "number":
405
+ if (Number.isNaN(Number(value))) throw Error(lang?.number);
406
+ break;
407
+ }
408
+ },
409
+ custom: async (value, options) => {
410
+ return options(value);
362
411
  }
363
- }
364
- function FormInput({
365
- name,
366
- rules,
367
- ...rest
368
- }) {
369
- const { elements, values, setValues } = useFormContext();
370
- const value = values?.[name];
371
- if ("Input" in rest && rest.Input) {
372
- return /* @__PURE__ */ jsxRuntime.jsx(
373
- rest.Input,
374
- {
375
- name,
376
- value,
377
- onChange: (v) => setValues((prev) => ({
378
- ...prev,
379
- [name]: v
380
- }))
412
+ };
413
+ async function validValues(rules, items, values, lang) {
414
+ const errors = {};
415
+ for (const item of items) {
416
+ const value = values[item.name];
417
+ const rulesOptions = item.rules;
418
+ if (rulesOptions) {
419
+ for (const [name, options] of Object.entries(rulesOptions)) {
420
+ try {
421
+ await rules[name](value, options, lang);
422
+ } catch (error) {
423
+ errors[item.name] = error;
424
+ break;
425
+ }
381
426
  }
382
- );
383
- }
384
- if ("type" in rest || "props" in rest) {
385
- switch (rest.type) {
386
- case "select":
387
- return /* @__PURE__ */ jsxRuntime.jsx(
388
- elements.select,
389
- {
390
- name,
391
- value,
392
- onChange: (v) => setValues((prev) => ({
393
- ...prev,
394
- [name]: processValue(v, rules)
395
- })),
396
- ...rest.props
397
- }
398
- );
399
- default:
400
- return /* @__PURE__ */ jsxRuntime.jsx(
401
- elements.input,
402
- {
403
- name,
404
- value,
405
- onChange: (v) => setValues((prev) => ({
406
- ...prev,
407
- [name]: processValue(v, rules)
408
- })),
409
- ...rest.props
410
- }
411
- );
412
427
  }
413
428
  }
414
- return /* @__PURE__ */ jsxRuntime.jsx(
415
- elements.input,
416
- {
417
- name,
418
- value,
419
- onChange: (v) => setValues((prev) => ({
420
- ...prev,
421
- [name]: processValue(v, rules)
422
- }))
423
- }
424
- );
429
+ return errors;
425
430
  }
426
- var FormElements = {
427
- label: react.forwardRef(({ name, label, input, rules }, ref) => /* @__PURE__ */ jsxRuntime.jsxs("label", { ref, children: [
428
- label?.title ?? name,
429
- /* @__PURE__ */ jsxRuntime.jsx(FormInput, { name, rules, ...input }),
430
- label?.description
431
- ] })),
432
- input: react.forwardRef(
433
- (props, ref) => /* @__PURE__ */ jsxRuntime.jsx("input", { ...props, ref })
434
- ),
435
- select: react.forwardRef(({ options, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("select", { ...props, ref, children: options?.map((option) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: option.value, children: option.label }, option.value)) })),
436
- button: react.forwardRef(({ disabled, children, onClick, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", disabled, onClick, ...props, ref, children }))
437
- };
438
431
  function FormFooter() {
439
- const { submitting, setSubmitting, onSubmit, values, elements } = useFormContext();
432
+ const {
433
+ submitting,
434
+ setSubmitting,
435
+ onSubmit,
436
+ values,
437
+ Elements,
438
+ items,
439
+ setErrors,
440
+ lang,
441
+ rules
442
+ } = useFormContext();
440
443
  return /* @__PURE__ */ jsxRuntime.jsx(
441
- elements.button,
444
+ Elements.Button,
442
445
  {
443
446
  disabled: submitting,
444
- onClick: () => {
447
+ submit: async () => {
445
448
  setSubmitting(true);
449
+ const errors = await validValues(rules, items, values, lang);
450
+ if (Object.keys(errors).length) {
451
+ setErrors(errors);
452
+ setSubmitting(false);
453
+ return;
454
+ }
446
455
  onSubmit(values).finally(() => setSubmitting(false));
447
456
  },
448
- children: "Submit"
457
+ children: lang.submit
449
458
  }
450
459
  );
451
460
  }
461
+ FormFooter.displayName = "FormFooter";
462
+ FormFooter.whyDidYouRender = true;
463
+ var FormButtonElement = react.forwardRef(({ disabled, children, submit, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
464
+ "button",
465
+ {
466
+ type: "button",
467
+ disabled,
468
+ onClick: submit,
469
+ ...props,
470
+ ref,
471
+ children
472
+ }
473
+ ));
474
+ FormButtonElement.displayName = "FormButtonElement";
475
+ FormButtonElement.whyDidYouRender = true;
476
+ var FormInputElement = react.forwardRef(({ onChange, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("input", { ...props, onChange: (e) => onChange(e.target.value), ref }));
477
+ FormInputElement.displayName = "FormInputElement";
478
+ FormInputElement.whyDidYouRender = true;
479
+ var FormLabelElement = ({
480
+ name,
481
+ title,
482
+ description,
483
+ error,
484
+ children
485
+ }) => {
486
+ return /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
487
+ title ?? name,
488
+ children,
489
+ description,
490
+ error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "red" }, children: error.message })
491
+ ] });
492
+ };
493
+ FormLabelElement.displayName = "FormLabelElement";
494
+ FormLabelElement.whyDidYouRender = true;
495
+
496
+ // src/Form/elements/index.ts
497
+ var FormDefaultElements = {
498
+ Label: FormLabelElement,
499
+ Input: FormInputElement,
500
+ Button: FormButtonElement
501
+ };
502
+
503
+ // src/Form/lang.ts
504
+ var FormDefaultLang = {
505
+ submit: "Submit",
506
+ required: "This field is required",
507
+ string: "This field must be a string",
508
+ number: "This field must be a number"
509
+ };
452
510
  function mergeValues(items, defaultValues = {}) {
453
511
  const values = {};
454
512
  for (const item of items)
455
513
  values[item.name] = defaultValues[item.name] ?? "";
456
514
  return values;
457
515
  }
458
- function FormContainer({ defaultValues, elements, ...props }) {
459
- const states = useSplittingState({
460
- values: mergeValues(props.items, defaultValues),
461
- submitting: false,
462
- elements: Object.assign(FormElements, elements)
463
- });
516
+ function FormContainer({
517
+ defaultValues,
518
+ Elements,
519
+ rules,
520
+ lang,
521
+ ...props
522
+ }) {
464
523
  return /* @__PURE__ */ jsxRuntime.jsxs(
465
524
  FormContextProvider,
466
525
  {
467
- value: {
468
- ...states,
469
- ...props
526
+ initializeStates: {
527
+ values: mergeValues(props.items, defaultValues),
528
+ errors: {},
529
+ submitting: false,
530
+ Elements: Object.assign(
531
+ FormDefaultElements,
532
+ Elements
533
+ ),
534
+ lang: Object.assign(FormDefaultLang, lang),
535
+ rules: Object.assign(FormDefaultRules, rules)
470
536
  },
537
+ value: props,
538
+ memo: true,
471
539
  children: [
472
540
  /* @__PURE__ */ jsxRuntime.jsx(FormBody, {}),
473
541
  /* @__PURE__ */ jsxRuntime.jsx(FormFooter, {})
@@ -475,11 +543,18 @@ function FormContainer({ defaultValues, elements, ...props }) {
475
543
  }
476
544
  );
477
545
  }
546
+ FormContainer.displayName = "FormContainer";
547
+ FormContainer.whyDidYouRender = true;
478
548
 
479
549
  exports.ErrorBoundary = ErrorBoundary;
480
550
  exports.FaasDataWrapper = FaasDataWrapper;
481
551
  exports.FaasReactClient = FaasReactClient;
482
552
  exports.Form = FormContainer;
553
+ exports.FormContextProvider = FormContextProvider;
554
+ exports.FormDefaultElements = FormDefaultElements;
555
+ exports.FormDefaultLang = FormDefaultLang;
556
+ exports.FormDefaultRules = FormDefaultRules;
557
+ exports.FormItem = FormItem;
483
558
  exports.OptionalWrapper = OptionalWrapper;
484
559
  exports.createSplittingContext = createSplittingContext;
485
560
  exports.equal = equal;
@@ -491,5 +566,8 @@ exports.useEqualEffect = useEqualEffect;
491
566
  exports.useEqualMemo = useEqualMemo;
492
567
  exports.useEqualMemoize = useEqualMemoize;
493
568
  exports.useFaas = useFaas;
569
+ exports.useFormContext = useFormContext;
570
+ exports.usePrevious = usePrevious;
494
571
  exports.useSplittingState = useSplittingState;
572
+ exports.validValues = validValues;
495
573
  exports.withFaasData = withFaasData;