@lundal/zed-solid 0.0.13 → 0.0.15

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/TextBox.d.ts CHANGED
@@ -8,6 +8,7 @@ export type TextBoxProps = {
8
8
  errorId: string | undefined;
9
9
  autocomplete?: string;
10
10
  hidden?: boolean;
11
+ placeholder?: string;
11
12
  value: string;
12
13
  onChange: (value: string) => void;
13
14
  };
package/dist/index.d.ts CHANGED
@@ -22,3 +22,6 @@ export * from './Row.tsx';
22
22
  export * from './Select.tsx';
23
23
  export * from './Spinner.tsx';
24
24
  export * from './TextBox.tsx';
25
+ export * from './signals/createForm.ts';
26
+ export * from './signals/createInterval.ts';
27
+ export * from './signals/createSize.ts';
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import './style.css';
2
2
  import "@fontsource/inter/400.css";
3
3
  import "@fontsource/inter/500.css";
4
- import { sharedConfig, createRenderEffect, untrack, createComponent, For, createMemo, createSignal, onMount } from "solid-js";
4
+ import { sharedConfig, createRenderEffect, untrack, createComponent, For, createMemo, createSignal, onMount, onCleanup } from "solid-js";
5
5
  import { A } from "@solidjs/router";
6
6
  function reconcileArrays(parentNode, a, b) {
7
7
  let bLength = b.length, aEnd = a.length, bEnd = bLength, aStart = 0, bStart = 0, after = a[aEnd - 1].nextSibling, map = null;
@@ -993,7 +993,7 @@ function TextBox(props) {
993
993
  var _el$ = _tmpl$();
994
994
  _el$.$$input = (e) => props.onChange(e.target.value);
995
995
  createRenderEffect((_p$) => {
996
- var _v$ = mergeClasses("z-textbox", props.class), _v$2 = props.style, _v$3 = props.autocomplete ?? "off", _v$4 = props.hidden ? "password" : "text", _v$5 = props.id, _v$6 = props.invalid, _v$7 = props.errorId;
996
+ var _v$ = mergeClasses("z-textbox", props.class), _v$2 = props.style, _v$3 = props.autocomplete ?? "off", _v$4 = props.hidden ? "password" : "text", _v$5 = props.id, _v$6 = props.invalid, _v$7 = props.errorId, _v$8 = props.placeholder;
997
997
  _v$ !== _p$.e && className(_el$, _p$.e = _v$);
998
998
  _p$.t = style(_el$, _v$2, _p$.t);
999
999
  _v$3 !== _p$.a && setAttribute(_el$, "autocomplete", _p$.a = _v$3);
@@ -1001,6 +1001,7 @@ function TextBox(props) {
1001
1001
  _v$5 !== _p$.i && setAttribute(_el$, "id", _p$.i = _v$5);
1002
1002
  _v$6 !== _p$.n && setAttribute(_el$, "aria-invalid", _p$.n = _v$6);
1003
1003
  _v$7 !== _p$.s && setAttribute(_el$, "aria-errormessage", _p$.s = _v$7);
1004
+ _v$8 !== _p$.h && setAttribute(_el$, "placeholder", _p$.h = _v$8);
1004
1005
  return _p$;
1005
1006
  }, {
1006
1007
  e: void 0,
@@ -1009,13 +1010,88 @@ function TextBox(props) {
1009
1010
  o: void 0,
1010
1011
  i: void 0,
1011
1012
  n: void 0,
1012
- s: void 0
1013
+ s: void 0,
1014
+ h: void 0
1013
1015
  });
1014
1016
  createRenderEffect(() => _el$.value = props.value);
1015
1017
  return _el$;
1016
1018
  })();
1017
1019
  }
1018
1020
  delegateEvents(["input"]);
1021
+ function createForm(options) {
1022
+ const [fields, setFields] = createSignal(options.initiator());
1023
+ const errors = createMemo(() => options.validator(fields()));
1024
+ const invalid = createMemo(() => containsTruthy(errors()));
1025
+ const [state, setState] = createSignal({
1026
+ type: "HideErrors"
1027
+ });
1028
+ return {
1029
+ fields,
1030
+ errors: () => state().type === "ShowErrors" ? errors() : {},
1031
+ state,
1032
+ busy: () => state().type === "Submitting",
1033
+ update: (fields2) => {
1034
+ setFields((prevFields) => ({ ...prevFields, ...fields2 }));
1035
+ },
1036
+ reset: () => {
1037
+ setFields(() => options.initiator());
1038
+ },
1039
+ submit: () => {
1040
+ if (state().type === "Submitting") {
1041
+ return;
1042
+ }
1043
+ if (invalid()) {
1044
+ setState({ type: "ShowErrors" });
1045
+ return;
1046
+ }
1047
+ setState({ type: "Submitting" });
1048
+ options.submitter(fields()).then((value) => {
1049
+ var _a;
1050
+ setState({ type: "Success", value });
1051
+ (_a = options.onSuccess) == null ? void 0 : _a.call(options, value);
1052
+ }).catch((error) => {
1053
+ var _a;
1054
+ setState({ type: "Failure", error });
1055
+ (_a = options.onFailure) == null ? void 0 : _a.call(options, error);
1056
+ });
1057
+ }
1058
+ };
1059
+ }
1060
+ function containsTruthy(value) {
1061
+ if (!value) {
1062
+ return false;
1063
+ }
1064
+ if (typeof value === "object") {
1065
+ if (Array.isArray(value)) {
1066
+ return value.some(containsTruthy);
1067
+ } else {
1068
+ return Object.values(value).some(containsTruthy);
1069
+ }
1070
+ }
1071
+ return true;
1072
+ }
1073
+ function createInterval(fn, interval = 1e3) {
1074
+ const [value, setValue] = createSignal(fn());
1075
+ const id = setInterval(() => setValue(fn), interval);
1076
+ onCleanup(() => clearInterval(id));
1077
+ return value;
1078
+ }
1079
+ function createSize(element) {
1080
+ const [size, setSize] = createSignal({ width: 0, height: 0 });
1081
+ let observer;
1082
+ onMount(() => {
1083
+ const _element = element();
1084
+ observer = new ResizeObserver(() => {
1085
+ setSize({ width: _element.offsetWidth, height: _element.offsetHeight });
1086
+ });
1087
+ observer.observe(_element);
1088
+ });
1089
+ onCleanup(() => {
1090
+ observer == null ? void 0 : observer.disconnect();
1091
+ observer = void 0;
1092
+ });
1093
+ return size;
1094
+ }
1019
1095
  export {
1020
1096
  Button,
1021
1097
  Card,
@@ -1041,5 +1117,8 @@ export {
1041
1117
  Row,
1042
1118
  Select,
1043
1119
  Spinner,
1044
- TextBox
1120
+ TextBox,
1121
+ createForm,
1122
+ createInterval,
1123
+ createSize
1045
1124
  };
@@ -0,0 +1,38 @@
1
+ import { Accessor } from 'solid-js';
2
+
3
+ type Options<Fields, Errors, Success, Failure> = {
4
+ initiator: () => Fields;
5
+ validator: (fields: Fields) => Errors;
6
+ submitter: (fields: Fields) => Promise<Success>;
7
+ onSuccess?: (result: Success) => void;
8
+ onFailure?: (result: Failure) => void;
9
+ };
10
+ type Form<Fields, Errors, Success, Failure> = {
11
+ fields: Accessor<Fields>;
12
+ errors: Accessor<Partial<Errors>>;
13
+ state: Accessor<State<Success, Failure>>;
14
+ busy: Accessor<boolean>;
15
+ update: (fields: Partial<Fields>) => void;
16
+ reset: () => void;
17
+ submit: () => void;
18
+ };
19
+ export declare function createForm<Fields, Errors, Success, Failure>(options: Options<Fields, Errors, Success, Failure>): Form<Fields, Errors, Success, Failure>;
20
+ type State<Value, Error> = HideErrors | ShowErrors | Submitting | Success<Value> | Failure<Error>;
21
+ type HideErrors = {
22
+ type: "HideErrors";
23
+ };
24
+ type ShowErrors = {
25
+ type: "ShowErrors";
26
+ };
27
+ type Submitting = {
28
+ type: "Submitting";
29
+ };
30
+ type Success<Value> = {
31
+ type: "Success";
32
+ value: Value;
33
+ };
34
+ type Failure<Error> = {
35
+ type: "Failure";
36
+ error: Error;
37
+ };
38
+ export {};
@@ -0,0 +1,11 @@
1
+ import { Accessor } from 'solid-js';
2
+
3
+ /**
4
+ * Create a readonly signal that is recomputed at regular intervals
5
+ *
6
+ * ### Example
7
+ * ```ts
8
+ * const now = createInterval(() => Date.now());
9
+ * ```
10
+ */
11
+ export declare function createInterval<T>(fn: () => T, interval?: number): Accessor<T>;
@@ -0,0 +1,24 @@
1
+ import { Accessor } from 'solid-js';
2
+
3
+ type Size = {
4
+ width: number;
5
+ height: number;
6
+ };
7
+ /**
8
+ * Create a readonly signal for an element's size
9
+ *
10
+ * ### Example
11
+ * ```tsx
12
+ * export function Example() {
13
+ * let element!: HTMLDivElement;
14
+ * const size = createSize(() => element);
15
+ * return (
16
+ * <div ref={element}>
17
+ * Size: {JSON.stringify(size())}
18
+ * </div>
19
+ * );
20
+ * }
21
+ * ```
22
+ */
23
+ export declare function createSize(element: Accessor<HTMLElement>): Accessor<Size>;
24
+ export {};
package/dist/style.css CHANGED
@@ -651,7 +651,6 @@ dialog:focus-visible {
651
651
  --z-button-secondary-text: #e6e6e6;
652
652
  --z-button-tertiary-fill: transparent;
653
653
  --z-button-tertiary-text: #e6e6e6;
654
- --z-button-icon-fill: #2c2c35;
655
654
  --z-input-border: #79798a; /* Lc 30 */
656
655
  --z-input-active-border: #6068ff; /* Lc 30 */
657
656
  --z-input-active-fill: #7882ff; /* Lc 40 */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lundal/zed-solid",
3
- "version": "0.0.13",
3
+ "version": "0.0.15",
4
4
  "license": "LGPL-3.0-or-later",
5
5
  "type": "module",
6
6
  "module": "dist/index.js",