@thi.ng/rdom-forms 0.2.33 → 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/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Change Log
2
2
 
3
- - **Last updated**: 2024-03-13T14:04:31Z
3
+ - **Last updated**: 2024-03-28T10:57:28Z
4
4
  - **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
5
5
 
6
6
  All notable changes to this project will be documented in this file.
@@ -9,6 +9,18 @@ See [Conventional Commits](https://conventionalcommits.org/) for commit guidelin
9
9
  **Note:** Unlisted _patch_ versions only involve non-code or otherwise excluded changes
10
10
  and/or version bumps of transitive dependencies.
11
11
 
12
+ ### [0.3.1](https://github.com/thi-ng/umbrella/tree/@thi.ng/rdom-forms@0.3.1) (2024-03-28)
13
+
14
+ #### 🩹 Bug fixes
15
+
16
+ - fix multiFile() handling/detection ([5339339](https://github.com/thi-ng/umbrella/commit/5339339))
17
+
18
+ ## [0.3.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/rdom-forms@0.3.0) (2024-03-27)
19
+
20
+ #### 🚀 Features
21
+
22
+ - add hidden(), reset() & submit() field types ([3304ee4](https://github.com/thi-ng/umbrella/commit/3304ee4))
23
+
12
24
  ## [0.2.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/rdom-forms@0.2.0) (2023-12-11)
13
25
 
14
26
  #### 🚀 Features
package/README.md CHANGED
@@ -15,6 +15,8 @@
15
15
  > GitHub](https://github.com/sponsors/postspectacular). Thank you! ❤️
16
16
 
17
17
  - [About](#about)
18
+ - [Examples](#examples)
19
+ - [Login form](#login-form)
18
20
  - [Status](#status)
19
21
  - [Related packages](#related-packages)
20
22
  - [Installation](#installation)
@@ -38,9 +40,67 @@ can then be used with
38
40
  for static (or SSR) HTML generation via
39
41
  [thi.ng/hiccup](https://github.com/thi-ng/umbrella/tree/develop/packages/hiccup).
40
42
 
41
- All generated form elements are unstyled by default, but can be fully customized (in various stages) via user-provided options.
43
+ All generated form elements are unstyled by default, but can be fully customized
44
+ (in various stages) via user-provided options.
45
+
46
+ ## Examples
47
+
48
+ Please see the [rdom-formgen example
49
+ project](https://github.com/thi-ng/umbrella/blob/develop/examples/rdom-formgen),
50
+ which demonstrates **all** supported elements and various customization
51
+ options...
52
+
53
+ ### Login form
54
+
55
+ ```ts tangle:export/readme1.ts
56
+ import {
57
+ compileForm, form, hidden, password, str, submit
58
+ } from "@thi.ng/rdom-forms";
59
+
60
+ // compile form from given field descriptions
61
+ const loginForm = compileForm(
62
+ form({ action: "/login", method: "post" },
63
+ // string input
64
+ str({ id: "user", label: "Username", desc: "or email address" }),
65
+ // password
66
+ password({ id: "pass", label: "Password", desc: "min. 8 characters", min: 8 }),
67
+ // hidden form value
68
+ hidden({ name: "target", value: "user-home" }),
69
+ submit({ title: "Login", label: "" })
70
+ ),
71
+ {
72
+ // disable reactive value subscriptions
73
+ behaviors: { values: false },
74
+ // customize attribs for label descriptions
75
+ descAttribs: { class: "desc" }
76
+ }
77
+ );
78
+
79
+ // use thi.ng/hiccup to serialize as HTML
80
+ import { serialize } from "@thi.ng/hiccup";
81
+
82
+ console.log(serialize(loginForm));
83
+ ```
84
+
85
+ Resulting output (reformatted):
42
86
 
43
- Please see the example project linked further below, which demonstrates all currently provided elements...
87
+ ```html
88
+ <form action="/login" method="post">
89
+ <div>
90
+ <label for="user">Username<span class="desc">or email address</span></label>
91
+ <input type="text" id="user" name="user" />
92
+ </div>
93
+ <div>
94
+ <label for="pass">Password<span class="desc">min. 8 characters</span></label>
95
+ <input type="password" autocomplete minlength="8" id="pass" name="pass" />
96
+ </div>
97
+ <input type="hidden" id="target" name="target" value="user-home" />
98
+ <div>
99
+ <label for="submit-0"></label>
100
+ <input type="submit" value="Login" id="submit-0" name="submit-0" />
101
+ </div>
102
+ </form>
103
+ ```
44
104
 
45
105
  ## Status
46
106
 
@@ -72,7 +132,7 @@ For Node.js REPL:
72
132
  const rdomForms = await import("@thi.ng/rdom-forms");
73
133
  ```
74
134
 
75
- Package sizes (brotli'd, pre-treeshake): ESM: 2.18 KB
135
+ Package sizes (brotli'd, pre-treeshake): ESM: 2.28 KB
76
136
 
77
137
  ## Dependencies
78
138
 
package/api.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { Fn, Predicate } from "@thi.ng/api";
2
- import type { Attribs, FormAttribs, InputAttribs, InputCheckboxAttribs, InputFileAttribs, InputNumericAttribs, InputRadioAttribs, InputTextAttribs, SelectAttribs, TextAreaAttribs } from "@thi.ng/hiccup-html";
2
+ import type { Attribs, FormAttribs, InputAttribs, InputCheckboxAttribs, InputFileAttribs, InputNumericAttribs, InputRadioAttribs, InputSubmitAttribs, InputTextAttribs, SelectAttribs, StringAttrib, TextAreaAttribs } from "@thi.ng/hiccup-html";
3
3
  import type { ComponentLike } from "@thi.ng/rdom";
4
4
  import type { ISubscriber, ISubscription } from "@thi.ng/rstream";
5
5
  export interface CommonAttribs {
@@ -44,6 +44,11 @@ export interface Value extends FormItem, Partial<CommonAttribs> {
44
44
  readonly?: boolean;
45
45
  attribs?: Partial<InputAttribs>;
46
46
  }
47
+ export interface HiddenValue extends Omit<FormItem, "attribs"> {
48
+ id?: string;
49
+ name: string;
50
+ value: StringAttrib;
51
+ }
47
52
  export interface WithPresets<T> {
48
53
  /**
49
54
  * Array of possible preset values.
@@ -155,12 +160,23 @@ export interface MultiSelectNum<T extends number = number> extends MultiSelect<T
155
160
  export interface Toggle extends Value {
156
161
  type: "toggle";
157
162
  value?: ISubscription<boolean, boolean>;
163
+ attribs?: Partial<InputCheckboxAttribs>;
158
164
  }
159
165
  export interface Trigger extends Value {
160
166
  type: "trigger";
161
167
  title: string;
162
168
  value?: ISubscriber<boolean>;
163
- attribs?: Partial<InputCheckboxAttribs>;
169
+ }
170
+ export interface Submit extends Omit<Value, "required" | "readonly"> {
171
+ type: "submit";
172
+ title: string;
173
+ value?: ISubscriber<boolean>;
174
+ attribs?: Partial<InputSubmitAttribs>;
175
+ }
176
+ export interface Reset extends Omit<Value, "required" | "readonly"> {
177
+ type: "submit";
178
+ title: string;
179
+ value?: ISubscriber<boolean>;
164
180
  }
165
181
  export interface Radio<T> extends Value {
166
182
  items: (T | SelectItem<T>)[];
package/compile.d.ts CHANGED
@@ -2,13 +2,14 @@ import type { MultiFn2 } from "@thi.ng/defmulti";
2
2
  import type { Attribs, FormAttribs } from "@thi.ng/hiccup-html";
3
3
  import { type ComponentLike } from "@thi.ng/rdom";
4
4
  import type { ISubscribable } from "@thi.ng/rstream";
5
- import type { Color, Container, Custom, DateTime, DateVal, Email, FileVal, Form, FormItem, FormOpts, Group, Month, MultiFileVal, MultiSelectNum, MultiSelectStr, Num, Password, RadioNum, RadioStr, Range, SelectNum, SelectStr, Str, Text, Time, Toggle, Trigger, UrlVal, Value, Week } from "./api.js";
5
+ import type { Color, Container, Custom, DateTime, DateVal, Email, FileVal, Form, FormItem, FormOpts, Group, HiddenValue, Month, MultiFileVal, MultiSelectNum, MultiSelectStr, Num, Password, RadioNum, RadioStr, Range, Reset, SelectNum, SelectStr, Str, Submit, Text, Time, Toggle, Trigger, UrlVal, Value, Week } from "./api.js";
6
6
  export declare const form: (attribs: Partial<FormAttribs>, ...items: FormItem[]) => Form;
7
7
  export declare const container: (attribs: Partial<Attribs>, ...items: FormItem[]) => Container;
8
8
  export declare const group: (spec: Omit<Group, "type" | "id" | "items"> & {
9
9
  id?: string;
10
10
  }, ...items: FormItem[]) => Group;
11
11
  export declare const custom: (body: ComponentLike) => Custom;
12
+ export declare const hidden: (spec: Omit<HiddenValue, "type">) => HiddenValue;
12
13
  export type PartialSpec<T extends Value> = Omit<T, "type" | "id"> & {
13
14
  id?: string;
14
15
  };
@@ -30,8 +31,10 @@ export declare const phone: (spec: PartialSpec<Email> | ReadonlyPartialSpec<Emai
30
31
  export declare const radioNum: (spec: PartialSpec<RadioNum> | ReadonlyPartialSpec<RadioNum, number>) => RadioNum;
31
32
  export declare const radioStr: (spec: PartialSpec<RadioStr> | ReadonlyPartialSpec<RadioStr, string>) => RadioStr;
32
33
  export declare const range: (spec: PartialSpec<Range> | ReadonlyPartialSpec<Range, number>) => Range;
34
+ export declare const reset: (spec: PartialSpec<Reset> | ReadonlyPartialSpec<Reset, string>) => Reset;
33
35
  export declare const search: (spec: PartialSpec<Str> | ReadonlyPartialSpec<Str, string>) => Str;
34
36
  export declare const str: (spec: PartialSpec<Str> | ReadonlyPartialSpec<Str, string>) => Str;
37
+ export declare const submit: (spec: PartialSpec<Submit> | ReadonlyPartialSpec<Submit, string>) => Submit;
35
38
  export declare const text: (spec: PartialSpec<Text> | ReadonlyPartialSpec<Text, string>) => Text;
36
39
  export declare const time: (spec: PartialSpec<Time> | ReadonlyPartialSpec<Time, string>) => Time;
37
40
  export declare const toggle: (spec: PartialSpec<Toggle> | ReadonlyPartialSpec<Toggle, boolean>) => Toggle;
package/compile.js CHANGED
@@ -13,6 +13,8 @@ import {
13
13
  inputFile,
14
14
  inputNumber,
15
15
  inputRange,
16
+ inputReset,
17
+ inputSubmit,
16
18
  inputText,
17
19
  label,
18
20
  legend,
@@ -53,6 +55,10 @@ const custom = (body) => ({
53
55
  type: "custom",
54
56
  body
55
57
  });
58
+ const hidden = (spec) => ({
59
+ type: "hidden",
60
+ ...spec
61
+ });
56
62
  let __nextID = 0;
57
63
  const $ = (type, defaults) => (spec) => ({
58
64
  id: spec.id || `${type}-${__nextID++}`,
@@ -73,8 +79,10 @@ const phone = $("tel", { autocomplete: true });
73
79
  const radioNum = $("radioNum");
74
80
  const radioStr = $("radioStr");
75
81
  const range = $("range");
82
+ const reset = $("reset");
76
83
  const search = $("search");
77
84
  const str = $("str");
85
+ const submit = $("submit");
78
86
  const text = $("text");
79
87
  const time = $("time");
80
88
  const toggle = $("toggle");
@@ -88,7 +96,7 @@ const multiSelectStr = (spec) => $("multiSelectStr")(spec);
88
96
  const __genID = (id, opts) => opts.prefix ? opts.prefix + id : id;
89
97
  const __genLabel = (x, opts) => label(
90
98
  { ...opts.labelAttribs, ...x.labelAttribs, for: __genID(x.id, opts) },
91
- x.label ?? x.id,
99
+ x.label != void 0 ? x.label || null : x.id,
92
100
  x.desc ? span({ ...opts.descAttribs, ...x.descAttribs }, x.desc) : null
93
101
  );
94
102
  const __genList = (id, list) => datalist({ id: id + "--list" }, ...list.map((value) => option({ value })));
@@ -202,6 +210,10 @@ const compileForm = defmulti(
202
210
  );
203
211
  },
204
212
  custom: (val) => val.body,
213
+ hidden: ($val) => {
214
+ const { id, name, value } = $val;
215
+ return inputText({ type: "hidden", id: id ?? name, name, value });
216
+ },
205
217
  toggle: ($val, opts) => {
206
218
  const val = $val;
207
219
  const label2 = __genLabel(val, opts);
@@ -228,6 +240,22 @@ const compileForm = defmulti(
228
240
  false,
229
241
  $val.title
230
242
  ),
243
+ submit: ($val, opts) => __component(
244
+ $val,
245
+ opts,
246
+ inputSubmit,
247
+ { ...opts.typeAttribs?.submit, value: $val.title },
248
+ { onclick: $inputTrigger($val.value) },
249
+ false
250
+ ),
251
+ reset: ($val, opts) => __component(
252
+ $val,
253
+ opts,
254
+ inputReset,
255
+ { ...opts.typeAttribs?.reset, value: $val.title },
256
+ { onclick: $inputTrigger($val.value) },
257
+ false
258
+ ),
231
259
  radio: ($val, opts) => {
232
260
  const val = $val;
233
261
  const labelAttribs = {
@@ -283,7 +311,7 @@ const compileForm = defmulti(
283
311
  ),
284
312
  file: ($val, opts) => {
285
313
  const val = $val;
286
- const isMulti = val.id.startsWith("multi");
314
+ const isMulti = val.type.startsWith("multi");
287
315
  return __component(
288
316
  val,
289
317
  opts,
@@ -499,6 +527,7 @@ export {
499
527
  file,
500
528
  form,
501
529
  group,
530
+ hidden,
502
531
  month,
503
532
  multiFile,
504
533
  multiSelectNum,
@@ -509,10 +538,12 @@ export {
509
538
  radioNum,
510
539
  radioStr,
511
540
  range,
541
+ reset,
512
542
  search,
513
543
  selectNum,
514
544
  selectStr,
515
545
  str,
546
+ submit,
516
547
  text,
517
548
  time,
518
549
  toggle,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thi.ng/rdom-forms",
3
- "version": "0.2.33",
3
+ "version": "0.3.1",
4
4
  "description": "Data-driven declarative & extensible HTML form generation",
5
5
  "type": "module",
6
6
  "module": "./index.js",
@@ -36,19 +36,19 @@
36
36
  "tool:tangle": "../../node_modules/.bin/tangle src/**/*.ts"
37
37
  },
38
38
  "dependencies": {
39
- "@thi.ng/api": "^8.9.30",
40
- "@thi.ng/checks": "^3.5.4",
41
- "@thi.ng/defmulti": "^3.0.33",
42
- "@thi.ng/hiccup-html": "^2.4.15",
43
- "@thi.ng/rdom": "^1.1.18",
44
- "@thi.ng/rstream": "^8.3.16"
39
+ "@thi.ng/api": "^8.9.31",
40
+ "@thi.ng/checks": "^3.5.5",
41
+ "@thi.ng/defmulti": "^3.0.34",
42
+ "@thi.ng/hiccup-html": "^2.5.0",
43
+ "@thi.ng/rdom": "^1.1.20",
44
+ "@thi.ng/rstream": "^8.3.18"
45
45
  },
46
46
  "devDependencies": {
47
- "@microsoft/api-extractor": "^7.42.3",
48
- "esbuild": "^0.20.1",
47
+ "@microsoft/api-extractor": "^7.43.0",
48
+ "esbuild": "^0.20.2",
49
49
  "rimraf": "^5.0.5",
50
50
  "typedoc": "^0.25.12",
51
- "typescript": "^5.4.2"
51
+ "typescript": "^5.4.3"
52
52
  },
53
53
  "keywords": [
54
54
  "browser",
@@ -97,5 +97,5 @@
97
97
  "status": "alpha",
98
98
  "year": 2023
99
99
  },
100
- "gitHead": "16686bb40f7bd7a14a5d1304e353a82cb0069a1a\n"
100
+ "gitHead": "db5f5a5d1b223a8e6b4999d67836678038fd3560\n"
101
101
  }