@pageboard/html 0.15.0 → 0.15.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/elements/form.js +46 -0
- package/elements/input-otp.js +56 -0
- package/package.json +1 -1
- package/ui/otp.css +28 -0
- package/ui/otp.js +13 -0
package/elements/form.js
CHANGED
|
@@ -103,16 +103,62 @@ exports.api_form = {
|
|
|
103
103
|
},
|
|
104
104
|
request: {
|
|
105
105
|
title: 'Map inputs',
|
|
106
|
+
description: `
|
|
107
|
+
expr is supposed to be used to merge stuff into html,
|
|
108
|
+
not really to merge stuff into methods parameters
|
|
109
|
+
Also expr has a bad design because
|
|
110
|
+
- it can be replaced by a binding element inside the block
|
|
111
|
+
- it forces the expression to be in a specific attribute,
|
|
112
|
+
and mostly when a block has no content (so a binding cannot be used)
|
|
113
|
+
- the editor is ugly and shows fields that might not even be merged into html
|
|
114
|
+
Use cases
|
|
115
|
+
- links in anchors, images
|
|
116
|
+
- input or buttons values, checked attributes
|
|
117
|
+
- hidden attributes
|
|
118
|
+
- show/hide blocks depending on response
|
|
119
|
+
The "expr" mecanism could instead be a list of expressions like
|
|
120
|
+
[url|as:url|assign:.query.reservation:$query.reservation]
|
|
121
|
+
[url][$query|pick:text:cover|as:query]
|
|
122
|
+
|
|
123
|
+
Things to solve:
|
|
124
|
+
- do we want expr to be able to do changes outside the DOM of the block itself ? (no, this should be done by a binding element)
|
|
125
|
+
- do we want expr to change only data before merge - outside of any dom context ? Possibly ! In which case the current system is not that bad,
|
|
126
|
+
but it should not use matchdom dom plugin at all
|
|
127
|
+
- how to deal with "template" expressions when one cannot insert a binding
|
|
128
|
+
element ? Is it really something that happens ?
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
`,
|
|
106
133
|
type: 'object',
|
|
107
134
|
nullable: true
|
|
108
135
|
},
|
|
109
136
|
response: {
|
|
110
137
|
title: 'Map outputs',
|
|
138
|
+
description: `
|
|
139
|
+
'item.id': '[item.data.id]'
|
|
140
|
+
'item.title': '[item.content.title]'
|
|
141
|
+
// etc...
|
|
142
|
+
`,
|
|
111
143
|
type: 'object',
|
|
112
144
|
nullable: true
|
|
113
145
|
},
|
|
114
146
|
redirection: {
|
|
115
147
|
title: 'Success',
|
|
148
|
+
description: `
|
|
149
|
+
redirection can be used by client,
|
|
150
|
+
to change the page state. In which case the "url" is not an api url.
|
|
151
|
+
It can be used by the server, in which case the "url" is an api url.
|
|
152
|
+
The parameters for a page url make the query, and $query, $request, $response are available.
|
|
153
|
+
The parameters for a user api call are...?
|
|
154
|
+
The user api endpoint is a real url (/@api/xxx) that can expect
|
|
155
|
+
a body ($request) and a query ($query) too.
|
|
156
|
+
Currently client pages use a trick to redirect and submit: a specific parameter triggers a form submit on the redirected page. This makes sense in the context of page navigation - the body is filled by the form that is triggered by the parameters.
|
|
157
|
+
How can that be transposed for internal user api redirection ?
|
|
158
|
+
1. since it redirects, output mapping can be done to format the $response
|
|
159
|
+
2. in the next api call, parameters mean $query, $response becomes $request ?
|
|
160
|
+
3. this works if output can merge $query, $request as well
|
|
161
|
+
`,
|
|
116
162
|
type: 'object',
|
|
117
163
|
properties: {
|
|
118
164
|
url: {
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
exports.input_otp = {
|
|
2
|
+
title: 'OTP',
|
|
3
|
+
icon: '<i class="icons"><i class="text cursor icon"></i><i class="corner lock icon"></i></i>',
|
|
4
|
+
menu: "form",
|
|
5
|
+
required: ["name"],
|
|
6
|
+
group: "block input_field",
|
|
7
|
+
context: 'form//',
|
|
8
|
+
properties: {
|
|
9
|
+
name: {
|
|
10
|
+
title: "Name",
|
|
11
|
+
description: "The form object key",
|
|
12
|
+
type: "string",
|
|
13
|
+
format: "singleline",
|
|
14
|
+
$helper: 'element-property'
|
|
15
|
+
},
|
|
16
|
+
value: {
|
|
17
|
+
title: "Default value",
|
|
18
|
+
nullable: true,
|
|
19
|
+
type: "string",
|
|
20
|
+
format: "singleline"
|
|
21
|
+
},
|
|
22
|
+
required: {
|
|
23
|
+
title: 'Required',
|
|
24
|
+
type: 'boolean',
|
|
25
|
+
default: false
|
|
26
|
+
},
|
|
27
|
+
disabled: {
|
|
28
|
+
title: 'Disabled',
|
|
29
|
+
type: 'boolean',
|
|
30
|
+
default: false
|
|
31
|
+
},
|
|
32
|
+
readonly: {
|
|
33
|
+
title: 'Read only',
|
|
34
|
+
type: 'boolean',
|
|
35
|
+
default: false
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
contents: {
|
|
39
|
+
id: 'label',
|
|
40
|
+
nodes: 'inline*'
|
|
41
|
+
},
|
|
42
|
+
html: `<div class="otp field">
|
|
43
|
+
<label block-content="label">Label</label>
|
|
44
|
+
<input is="element-input-otp" name="[name]"
|
|
45
|
+
required="[required]"
|
|
46
|
+
readonly="[readonly]"
|
|
47
|
+
disabled="[disabled]"
|
|
48
|
+
value="[value]"
|
|
49
|
+
inputmode="numeric"
|
|
50
|
+
maxlength="6"
|
|
51
|
+
pattern="\\d{6}"
|
|
52
|
+
autocomplete="off" />
|
|
53
|
+
</div>`,
|
|
54
|
+
stylesheets: ['../ui/otp.css'],
|
|
55
|
+
scripts: ['../ui/otp.js']
|
|
56
|
+
};
|
package/package.json
CHANGED
package/ui/otp.css
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
form .otp.field > input[is="element-input-otp"] {
|
|
2
|
+
--otp-digits: 6;
|
|
3
|
+
--otp-ls: 2ch;
|
|
4
|
+
--otp-gap: 1.25;
|
|
5
|
+
--otp-fz: 1.5em;
|
|
6
|
+
--otp-pb: 0.5ch;
|
|
7
|
+
|
|
8
|
+
/* private consts */
|
|
9
|
+
--otp-bgsz: calc(var(--otp-ls) + 1ch);
|
|
10
|
+
--otp-digit: 0;
|
|
11
|
+
|
|
12
|
+
all: unset;
|
|
13
|
+
background:
|
|
14
|
+
linear-gradient(90deg, var(--otp-bg, #BBB) calc(var(--otp-gap) * var(--otp-ls)),
|
|
15
|
+
transparent 0),
|
|
16
|
+
linear-gradient(90deg, var(--otp-bg, #EEE) calc(var(--otp-gap) * var(--otp-ls)),
|
|
17
|
+
transparent 0) !important;
|
|
18
|
+
background-position: calc(var(--otp-digit) * var(--otp-bgsz)) 0, 0 0 !important;
|
|
19
|
+
background-repeat: no-repeat, repeat-x !important;
|
|
20
|
+
background-size: var(--otp-bgsz) 100% !important;
|
|
21
|
+
caret-color: var(--otp-cc, #222);
|
|
22
|
+
clip-path: inset(0% calc(var(--otp-ls) / 2) 0% 0%);
|
|
23
|
+
font-size: var(--otp-fz, 2.5em);
|
|
24
|
+
inline-size: calc(var(--otp-digits) * var(--otp-bgsz));
|
|
25
|
+
letter-spacing: var(--otp-ls);
|
|
26
|
+
padding-block: var(--otp-pb, 1ch);
|
|
27
|
+
padding-inline-start: calc(((var(--otp-ls) - 1ch) / 2) * var(--otp-gap));
|
|
28
|
+
}
|
package/ui/otp.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
class HTMLElementInputOtp extends Page.create(HTMLInputElement) {
|
|
2
|
+
handleInput() {
|
|
3
|
+
this.style.setProperty('--otp-digit', this.selectionStart);
|
|
4
|
+
}
|
|
5
|
+
handleFocus() {
|
|
6
|
+
this.value = "";
|
|
7
|
+
}
|
|
8
|
+
paint() {
|
|
9
|
+
this.focus();
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
Page.define('element-input-otp', HTMLElementInputOtp, 'input');
|