@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 +13 -1
- package/README.md +63 -3
- package/api.d.ts +18 -2
- package/compile.d.ts +4 -1
- package/compile.js +33 -2
- package/package.json +11 -11
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
- **Last updated**: 2024-03-
|
|
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
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
40
|
-
"@thi.ng/checks": "^3.5.
|
|
41
|
-
"@thi.ng/defmulti": "^3.0.
|
|
42
|
-
"@thi.ng/hiccup-html": "^2.
|
|
43
|
-
"@thi.ng/rdom": "^1.1.
|
|
44
|
-
"@thi.ng/rstream": "^8.3.
|
|
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.
|
|
48
|
-
"esbuild": "^0.20.
|
|
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.
|
|
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": "
|
|
100
|
+
"gitHead": "db5f5a5d1b223a8e6b4999d67836678038fd3560\n"
|
|
101
101
|
}
|