@pageboard/html 0.14.36 → 0.15.0
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 +14 -4
- package/elements/inlines.js +2 -41
- package/elements/input-property.js +1 -1
- package/elements/layout.js +62 -1
- package/elements/link.js +3 -3
- package/elements/menu.js +1 -1
- package/elements/navigation.js +1 -1
- package/elements/textcard.js +21 -0
- package/package.json +2 -2
- package/ui/image.js +61 -62
- package/ui/inlines.css +1 -15
- package/ui/input-file.js +5 -4
- package/ui/layout.js +18 -51
- package/ui/pagination.js +1 -1
- package/ui/textcard.css +3 -0
package/elements/form.js
CHANGED
|
@@ -38,7 +38,7 @@ exports.query_form = {
|
|
|
38
38
|
title: 'Page',
|
|
39
39
|
nullable: true,
|
|
40
40
|
type: "string",
|
|
41
|
-
format: "
|
|
41
|
+
format: "page",
|
|
42
42
|
$helper: "page"
|
|
43
43
|
},
|
|
44
44
|
parameters: {
|
|
@@ -79,7 +79,7 @@ exports.api_form = {
|
|
|
79
79
|
properties: {
|
|
80
80
|
name: {
|
|
81
81
|
title: 'Name',
|
|
82
|
-
description: "Used by query 'submit' or 'toggle'\nExposes
|
|
82
|
+
description: "Used by query 'submit' or 'toggle'\nExposes /@api/form/$name",
|
|
83
83
|
type: 'string',
|
|
84
84
|
format: 'id',
|
|
85
85
|
nullable: true
|
|
@@ -101,6 +101,16 @@ exports.api_form = {
|
|
|
101
101
|
description: 'Choose a service',
|
|
102
102
|
$ref: '/writes'
|
|
103
103
|
},
|
|
104
|
+
request: {
|
|
105
|
+
title: 'Map inputs',
|
|
106
|
+
type: 'object',
|
|
107
|
+
nullable: true
|
|
108
|
+
},
|
|
109
|
+
response: {
|
|
110
|
+
title: 'Map outputs',
|
|
111
|
+
type: 'object',
|
|
112
|
+
nullable: true
|
|
113
|
+
},
|
|
104
114
|
redirection: {
|
|
105
115
|
title: 'Success',
|
|
106
116
|
type: 'object',
|
|
@@ -109,7 +119,7 @@ exports.api_form = {
|
|
|
109
119
|
title: 'Page',
|
|
110
120
|
nullable: true,
|
|
111
121
|
type: "string",
|
|
112
|
-
format: "
|
|
122
|
+
format: "page",
|
|
113
123
|
$helper: "page"
|
|
114
124
|
},
|
|
115
125
|
parameters: {
|
|
@@ -160,7 +170,7 @@ exports.api_form = {
|
|
|
160
170
|
contents: 'block+',
|
|
161
171
|
tag: 'form[method="post"]',
|
|
162
172
|
html: `<form is="element-form" method="post" name="[name]" masked="[masked]"
|
|
163
|
-
action="
|
|
173
|
+
action="/@api/form/[name|else:$id]"
|
|
164
174
|
parameters="[$expr?.action?.parameters|as:expressions]"
|
|
165
175
|
success="[redirection.url][redirection.parameters|as:query]"
|
|
166
176
|
badrequest="[badrequest.url][badrequest.parameters|as:query]"
|
package/elements/inlines.js
CHANGED
|
@@ -95,35 +95,7 @@ exports.style = {
|
|
|
95
95
|
group: "inline nolink",
|
|
96
96
|
tag: 'span.style',
|
|
97
97
|
properties: {
|
|
98
|
-
size:
|
|
99
|
-
title: 'Size',
|
|
100
|
-
default: null,
|
|
101
|
-
anyOf: [{
|
|
102
|
-
const: null,
|
|
103
|
-
title: 'Default',
|
|
104
|
-
icon: '<span class="icon">∅</span>'
|
|
105
|
-
}, {
|
|
106
|
-
const: 'tiny',
|
|
107
|
-
title: 'Tiny',
|
|
108
|
-
icon: '<span class="icon char" style="font-size:0.6em;margin-inline:0.6rem">aA</span>'
|
|
109
|
-
}, {
|
|
110
|
-
const: 'small',
|
|
111
|
-
title: 'Small',
|
|
112
|
-
icon: '<span class="icon char" style="font-size:0.8em;margin-inline:0.6rem">aA</span>'
|
|
113
|
-
}, {
|
|
114
|
-
const: 'base',
|
|
115
|
-
title: 'Base',
|
|
116
|
-
icon: '<span class="icon char" style="font-size:1em;margin-inline:0.6rem">aA</span>'
|
|
117
|
-
}, {
|
|
118
|
-
const: 'large',
|
|
119
|
-
title: 'Large',
|
|
120
|
-
icon: '<span class="icon char" style="font-size:1.2em;margin-inline:0.6rem">aA</span>'
|
|
121
|
-
}, {
|
|
122
|
-
const: 'extra',
|
|
123
|
-
title: 'Extra',
|
|
124
|
-
icon: '<span class="icon char" style="font-size:1.6em;margin-inline:0.6rem">aA</span>'
|
|
125
|
-
}]
|
|
126
|
-
},
|
|
98
|
+
size: exports.paragraph.properties.size,
|
|
127
99
|
transform: {
|
|
128
100
|
title: 'Transform',
|
|
129
101
|
default: null,
|
|
@@ -197,18 +169,7 @@ exports.style = {
|
|
|
197
169
|
nullable: true
|
|
198
170
|
}
|
|
199
171
|
},
|
|
200
|
-
parse:
|
|
201
|
-
const data = {};
|
|
202
|
-
for (const [key, schema] of Object.entries(this.properties)) {
|
|
203
|
-
if (schema.anyOf) for (const item of schema.anyOf) {
|
|
204
|
-
if (item.const && dom.classList.contains(item.const)) {
|
|
205
|
-
data[key] = item.const;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
if (dom.translate === false) data.idiom = true;
|
|
210
|
-
return data;
|
|
211
|
-
},
|
|
172
|
+
parse: exports.paragraph.parse,
|
|
212
173
|
html: '<span class="style [size] [transform] [color]" translate="[idiom|alt:no:]"></span>',
|
|
213
174
|
stylesheets: [
|
|
214
175
|
'../ui/inlines.css'
|
package/elements/layout.js
CHANGED
|
@@ -133,6 +133,64 @@ exports.layout = {
|
|
|
133
133
|
heightUnits: {
|
|
134
134
|
$ref: "#/definitions/units/properties/data/properties/block"
|
|
135
135
|
},
|
|
136
|
+
column: {
|
|
137
|
+
title: 'Column',
|
|
138
|
+
nullable: true,
|
|
139
|
+
properties: {
|
|
140
|
+
count: {
|
|
141
|
+
title: 'Count',
|
|
142
|
+
description: 'empty for auto',
|
|
143
|
+
type: 'integer',
|
|
144
|
+
nullable: true,
|
|
145
|
+
minimum: 1
|
|
146
|
+
},
|
|
147
|
+
width: {
|
|
148
|
+
title: 'Width',
|
|
149
|
+
properties: {
|
|
150
|
+
length: {
|
|
151
|
+
title: 'Length',
|
|
152
|
+
type: 'number',
|
|
153
|
+
default: 0,
|
|
154
|
+
minimum: 0,
|
|
155
|
+
multipleOf: 0.01,
|
|
156
|
+
nullable: true
|
|
157
|
+
},
|
|
158
|
+
unit: {
|
|
159
|
+
$ref: "#/definitions/units/properties/data/properties/inline"
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
fill: {
|
|
164
|
+
title: 'Fill',
|
|
165
|
+
anyOf: [{
|
|
166
|
+
type: 'null',
|
|
167
|
+
title: 'Auto'
|
|
168
|
+
}, {
|
|
169
|
+
const: 'balance',
|
|
170
|
+
title: 'Balance'
|
|
171
|
+
}, {
|
|
172
|
+
const: 'balance-all',
|
|
173
|
+
title: 'Balance All'
|
|
174
|
+
}]
|
|
175
|
+
},
|
|
176
|
+
gap: {
|
|
177
|
+
title: 'Gap',
|
|
178
|
+
properties: {
|
|
179
|
+
length: {
|
|
180
|
+
title: 'Length',
|
|
181
|
+
type: 'number',
|
|
182
|
+
default: 0,
|
|
183
|
+
minimum: 0,
|
|
184
|
+
multipleOf: 0.01,
|
|
185
|
+
nullable: true
|
|
186
|
+
},
|
|
187
|
+
unit: {
|
|
188
|
+
$ref: "#/definitions/units/properties/data/properties/inline"
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
},
|
|
136
194
|
margins: {
|
|
137
195
|
title: 'Margins',
|
|
138
196
|
type: 'object',
|
|
@@ -391,6 +449,10 @@ exports.layout = {
|
|
|
391
449
|
style-background-repeat="[background.repeat]"
|
|
392
450
|
style-background-attachment="[background.attachment]"
|
|
393
451
|
style-background-position="[background.position]"
|
|
452
|
+
style-column-gap="[column.gap.length|fail:][column.gap.unit]"
|
|
453
|
+
style-column-fill="[column.fill|or:auto]"
|
|
454
|
+
style-column-count="[column.count|or:auto]"
|
|
455
|
+
style-column-width="[column.width.length|fail:][column.width.unit]"
|
|
394
456
|
></div>`,
|
|
395
457
|
stylesheets: [
|
|
396
458
|
'../ui/components/container.css',
|
|
@@ -400,4 +462,3 @@ exports.layout = {
|
|
|
400
462
|
'../ui/layout.js'
|
|
401
463
|
]
|
|
402
464
|
};
|
|
403
|
-
|
package/elements/link.js
CHANGED
|
@@ -29,7 +29,7 @@ exports.link = {
|
|
|
29
29
|
nullable: true,
|
|
30
30
|
$helper: {
|
|
31
31
|
name: 'datalist',
|
|
32
|
-
url: '
|
|
32
|
+
url: '/@api/languages'
|
|
33
33
|
}
|
|
34
34
|
},
|
|
35
35
|
id: {
|
|
@@ -75,7 +75,7 @@ exports.link_button = {
|
|
|
75
75
|
nullable: true,
|
|
76
76
|
$helper: {
|
|
77
77
|
name: 'datalist',
|
|
78
|
-
url: '
|
|
78
|
+
url: '/@api/languages'
|
|
79
79
|
}
|
|
80
80
|
},
|
|
81
81
|
full: {
|
|
@@ -108,7 +108,7 @@ exports.link_button = {
|
|
|
108
108
|
default: null
|
|
109
109
|
}
|
|
110
110
|
},
|
|
111
|
-
contents: "
|
|
111
|
+
contents: "inline*",
|
|
112
112
|
group: "block",
|
|
113
113
|
html: '<a href="[url|lang:[lang]]" hreflang="[lang]" class="ui [full|alt:fluid:] [icon] [compact] [float|post:%20floated] button"></a>',
|
|
114
114
|
stylesheets: [
|
package/elements/menu.js
CHANGED
package/elements/navigation.js
CHANGED
|
@@ -20,7 +20,7 @@ exports.nav = {
|
|
|
20
20
|
}
|
|
21
21
|
},
|
|
22
22
|
group: "block",
|
|
23
|
-
html: `<a class="ui icon button [$links.[relation]|as:array|.first|alt::disabled]" href="[$links.[relation]|as:array|.first.url]" title="[$links.[relation]|as:array|.first.title]"><i class="icon [
|
|
23
|
+
html: `<a class="ui icon button [$links.[relation]|as:array|.first|alt::disabled]" href="[$links.[relation]|as:array|.first.url]" title="[$links.[relation]|as:array|.first.title]"><i class="icon [relation]"></i></a>`
|
|
24
24
|
};
|
|
25
25
|
|
|
26
26
|
exports.scrollLink = {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
exports.textcard = {
|
|
2
|
+
title: 'Text Card',
|
|
3
|
+
group: 'block',
|
|
4
|
+
icon: '<i class="icons"><i class="small heading icon"></i><i class="bottom right corner text cursor icon"></i></i>',
|
|
5
|
+
contents: [{
|
|
6
|
+
id: 'title',
|
|
7
|
+
nodes: "inline*",
|
|
8
|
+
title: 'title'
|
|
9
|
+
}, {
|
|
10
|
+
id: 'content',
|
|
11
|
+
nodes: "inline*",
|
|
12
|
+
title: 'content'
|
|
13
|
+
}],
|
|
14
|
+
html: `<div class="ui textcard">
|
|
15
|
+
<div class="header" block-content="title"></div>
|
|
16
|
+
<div class="content" block-content="content"></div>
|
|
17
|
+
</div>`,
|
|
18
|
+
stylesheets: [
|
|
19
|
+
"../ui/textcard.css"
|
|
20
|
+
]
|
|
21
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pageboard/html",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"dependencies": {},
|
|
17
17
|
"devDependencies": {
|
|
18
18
|
"nouislider": "^15.7.1",
|
|
19
|
-
"postinstall": "^0.
|
|
19
|
+
"postinstall": "^0.10.3"
|
|
20
20
|
},
|
|
21
21
|
"postinstall": {},
|
|
22
22
|
"prepare": {
|
package/ui/image.js
CHANGED
|
@@ -9,27 +9,20 @@ const HTMLElementImageConstructor = Superclass => class extends Superclass {
|
|
|
9
9
|
|
|
10
10
|
#defer;
|
|
11
11
|
|
|
12
|
-
static getZoom({ w, h, rw, rh, fit }) {
|
|
13
|
-
let z = 100;
|
|
14
|
-
if (!rw && !rh) return z;
|
|
15
|
-
if (!rw) rw = rh * w / h;
|
|
16
|
-
if (!rh) rh = rw * h / w;
|
|
17
|
-
z = Math.ceil((fit == "contain" ? Math.min : Math.max)(rw / w, rh / h) * 100 * (window.devicePixelRatio || 1));
|
|
18
|
-
// svg need to be resized to scale to its intrinsic dimension
|
|
19
|
-
if (z > 100) z = 100;
|
|
20
|
-
const zstep = 5;
|
|
21
|
-
z = Math.ceil(z / zstep) * zstep;
|
|
22
|
-
return z;
|
|
23
|
-
}
|
|
24
12
|
get dimensions() {
|
|
13
|
+
// dimension in pixels of the (extracted) source image
|
|
25
14
|
let w = parseInt(this.dataset.width);
|
|
26
15
|
let h = parseInt(this.dataset.height);
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
h = Math.round(h *
|
|
16
|
+
const { crop } = this;
|
|
17
|
+
if (crop.w != 100) {
|
|
18
|
+
w = Math.round(w * crop.w / 100);
|
|
19
|
+
}
|
|
20
|
+
if (crop.h != 100) {
|
|
21
|
+
h = Math.round(h * crop.h / 100);
|
|
22
|
+
}
|
|
23
|
+
if (crop.z != 100) {
|
|
24
|
+
w = Math.round(w * crop.z / 100);
|
|
25
|
+
h = Math.round(h * crop.z / 100);
|
|
33
26
|
}
|
|
34
27
|
return { w, h };
|
|
35
28
|
}
|
|
@@ -53,12 +46,12 @@ const HTMLElementImageConstructor = Superclass => class extends Superclass {
|
|
|
53
46
|
});
|
|
54
47
|
}
|
|
55
48
|
get crop() {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
49
|
+
const defs = [50, 50, 100, 100, 100];
|
|
50
|
+
const list = (this.dataset.crop || ";;;;").split(";").map(x => parseFloat(x));
|
|
51
|
+
for (let i = 0; i < defs.length; i++) {
|
|
52
|
+
if (Number.isNaN(list[i])) list[i] = defs[i];
|
|
53
|
+
}
|
|
54
|
+
const [x, y, w, h, z] = list;
|
|
62
55
|
return { x, y, w, h, z };
|
|
63
56
|
}
|
|
64
57
|
set crop({ x, y, w, h, z }) {
|
|
@@ -99,6 +92,44 @@ const HTMLElementImageConstructor = Superclass => class extends Superclass {
|
|
|
99
92
|
else return src;
|
|
100
93
|
}
|
|
101
94
|
|
|
95
|
+
requestSrc(srcLoc) {
|
|
96
|
+
const { crop, fit } = this;
|
|
97
|
+
const { w, h } = this.dimensions;
|
|
98
|
+
const r = {};
|
|
99
|
+
if (!Number.isNaN(w) && !Number.isNaN(h)) {
|
|
100
|
+
if (fit == "none") {
|
|
101
|
+
r.width = w;
|
|
102
|
+
r.height = h;
|
|
103
|
+
} else {
|
|
104
|
+
const rect = this.getBoundingClientRect();
|
|
105
|
+
r.width = rect.width;
|
|
106
|
+
r.height = rect.height;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (!r.width && !r.height) {
|
|
110
|
+
// don't show
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
if (crop.x != 50 || crop.y != 50 || crop.w != 100 || crop.h != 100) {
|
|
114
|
+
if (Math.round((crop.x - crop.w / 2) * 100) < 0 || Math.round((crop.x + crop.w / 2) * 100) > 10000) {
|
|
115
|
+
crop.w = 2 * Math.min(crop.x, 100 - crop.x);
|
|
116
|
+
}
|
|
117
|
+
if (Math.round((crop.y - crop.h / 2) * 100) < 0 || Math.round((crop.y + crop.h / 2) * 100) > 10000) {
|
|
118
|
+
crop.h = 2 * Math.min(crop.y, 100 - crop.y);
|
|
119
|
+
}
|
|
120
|
+
srcLoc.query.ex = `x-${crop.x}_y-${crop.y}_w-${crop.w}_h-${crop.h}`;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (!r.width) r.width = r.height * w / h;
|
|
124
|
+
if (!r.height) r.height = r.width * h / w;
|
|
125
|
+
const clientHintWidth = Math.ceil(
|
|
126
|
+
(fit == "contain" ? Math.min : Math.max)(r.width / w, r.height / h)
|
|
127
|
+
* w * (window.devicePixelRatio || 1)
|
|
128
|
+
);
|
|
129
|
+
srcLoc.query.rs = `w-${clientHintWidth}`; // max, min ?
|
|
130
|
+
return srcLoc.toString();
|
|
131
|
+
}
|
|
132
|
+
|
|
102
133
|
reveal(state) {
|
|
103
134
|
const img = this.image;
|
|
104
135
|
if (!this.options.src) {
|
|
@@ -108,47 +139,15 @@ const HTMLElementImageConstructor = Superclass => class extends Superclass {
|
|
|
108
139
|
if (this.classList.contains('loading')) {
|
|
109
140
|
return;
|
|
110
141
|
}
|
|
111
|
-
const
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
if (
|
|
116
|
-
loc = Page.parse({
|
|
117
|
-
pathname: "/.api/image",
|
|
118
|
-
query: {
|
|
119
|
-
url: this.options.src
|
|
120
|
-
}
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (r.x != 50 || r.y != 50 || r.w != 100 || r.h != 100) {
|
|
125
|
-
if (Math.round((r.x - r.w / 2) * 100) < 0 || Math.round((r.x + r.w / 2) * 100) > 10000) {
|
|
126
|
-
r.w = 2 * Math.min(r.x, 100 - r.x);
|
|
127
|
-
}
|
|
128
|
-
if (Math.round((r.y - r.h / 2) * 100) < 0 || Math.round((r.y + r.h / 2) * 100) > 10000) {
|
|
129
|
-
r.h = 2 * Math.min(r.y, 100 - r.y);
|
|
130
|
-
}
|
|
131
|
-
loc.query.ex = `x-${r.x}_y-${r.y}_w-${r.w}_h-${r.h}`;
|
|
132
|
-
}
|
|
133
|
-
const { w, h } = this.dimensions;
|
|
134
|
-
if (fit == "none") {
|
|
135
|
-
loc.query.rs = `z-${r.z}`;
|
|
136
|
-
} else if (!Number.isNaN(w) && !Number.isNaN(h)) {
|
|
137
|
-
const rect = this.getBoundingClientRect();
|
|
138
|
-
const rw = rect.width;
|
|
139
|
-
const rh = rect.height;
|
|
140
|
-
if (rw == 0 && rh == 0) {
|
|
141
|
-
// don't show
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
loc.query.rs = "z-" + this.constructor.getZoom({ w, h, rw, rh, fit });
|
|
145
|
-
}
|
|
146
|
-
const curSrc = loc.toString();
|
|
147
|
-
if (curSrc != this.currentSrc) {
|
|
142
|
+
const srcLoc = Page.parse(this.options.src);
|
|
143
|
+
const reqSrc = this.requestSrc(srcLoc);
|
|
144
|
+
if (!reqSrc) {
|
|
145
|
+
img.setAttribute('src', '');
|
|
146
|
+
} else if (reqSrc != this.currentSrc) {
|
|
148
147
|
this.classList.add('loading');
|
|
149
148
|
this.#defer?.resolve();
|
|
150
149
|
this.#defer = new Deferred();
|
|
151
|
-
img.setAttribute('src',
|
|
150
|
+
img.setAttribute('src', reqSrc);
|
|
152
151
|
return this.#defer;
|
|
153
152
|
}
|
|
154
153
|
}
|
package/ui/inlines.css
CHANGED
|
@@ -37,18 +37,4 @@ span.blue {
|
|
|
37
37
|
span.purple {
|
|
38
38
|
color: purple;
|
|
39
39
|
}
|
|
40
|
-
|
|
41
|
-
font-size: 0.5715em;
|
|
42
|
-
}
|
|
43
|
-
span.small {
|
|
44
|
-
font-size: 0.8em;
|
|
45
|
-
}
|
|
46
|
-
span.base {
|
|
47
|
-
font-size: 1.2em;
|
|
48
|
-
}
|
|
49
|
-
span.large {
|
|
50
|
-
font-size: 1.6em;
|
|
51
|
-
}
|
|
52
|
-
span.extra {
|
|
53
|
-
font-size: 2em;
|
|
54
|
-
}
|
|
40
|
+
|
package/ui/input-file.js
CHANGED
|
@@ -73,9 +73,10 @@ class HTMLElementInputFile extends Page.create(HTMLInputElement) {
|
|
|
73
73
|
this.#defer = null;
|
|
74
74
|
};
|
|
75
75
|
const pass = (obj) => {
|
|
76
|
-
if (!obj.
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
if (!obj.hrefs?.length) {
|
|
77
|
+
return fail(new Error("File rejected"));
|
|
78
|
+
}
|
|
79
|
+
this.value = obj.hrefs[0]?.pathname;
|
|
79
80
|
field.classList.add('success');
|
|
80
81
|
field.classList.remove('loading');
|
|
81
82
|
this.#xhr = null;
|
|
@@ -124,7 +125,7 @@ class HTMLElementInputFile extends Page.create(HTMLInputElement) {
|
|
|
124
125
|
fail(err);
|
|
125
126
|
});
|
|
126
127
|
try {
|
|
127
|
-
xhr.open("POST",
|
|
128
|
+
xhr.open("POST", `/@api/upload/${this.id}`, true);
|
|
128
129
|
xhr.setRequestHeader('Accept', "application/json; q=1.0");
|
|
129
130
|
xhr.send(fd);
|
|
130
131
|
this.#xhr = xhr;
|
package/ui/layout.js
CHANGED
|
@@ -14,48 +14,16 @@ class HTMLElementLayout extends Page.create(HTMLDivElement) {
|
|
|
14
14
|
this.style.backgroundImage = '';
|
|
15
15
|
return;
|
|
16
16
|
}
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
pathname: "/.api/image",
|
|
24
|
-
query: {
|
|
25
|
-
url: this.options.src
|
|
26
|
-
}
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if (r.x != 50 || r.y != 50 || r.w != 100 || r.h != 100) {
|
|
31
|
-
if (Math.round((r.x - r.w / 2) * 100) < 0 || Math.round((r.x + r.w / 2) * 100) > 10000) {
|
|
32
|
-
r.w = 2 * Math.min(r.x, 100 - r.x);
|
|
33
|
-
}
|
|
34
|
-
if (Math.round((r.y - r.h / 2) * 100) < 0 || Math.round((r.y + r.h / 2) * 100) > 10000) {
|
|
35
|
-
r.h = 2 * Math.min(r.y, 100 - r.y);
|
|
36
|
-
}
|
|
37
|
-
loc.query.ex = `x-${r.x}_y-${r.y}_w-${r.w}_h-${r.h}`;
|
|
38
|
-
}
|
|
39
|
-
const {w, h} = this.dimensions;
|
|
40
|
-
if (fit == "none") {
|
|
41
|
-
loc.query.rs = `z-${r.z}`;
|
|
42
|
-
} else if (!Number.isNaN(w) && !Number.isNaN(h)) {
|
|
43
|
-
const rect = this.getBoundingClientRect();
|
|
44
|
-
const rw = rect.width;
|
|
45
|
-
const rh = rect.height;
|
|
46
|
-
if (rw == 0 && rh == 0) {
|
|
47
|
-
// don't show
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
loc.query.rs = "z-" + HTMLElementLayout.getZoom({w, h, rw, rh, fit});
|
|
17
|
+
const srcLoc = Page.parse(this.options.src);
|
|
18
|
+
const reqSrc = this.requestSrc(srcLoc);
|
|
19
|
+
try {
|
|
20
|
+
this.currentSrc = reqSrc;
|
|
21
|
+
} catch (e) {
|
|
22
|
+
// pass
|
|
51
23
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
this.currentSrc = curSrc;
|
|
56
|
-
} catch(e) {
|
|
57
|
-
// pass
|
|
58
|
-
}
|
|
24
|
+
if (!reqSrc) {
|
|
25
|
+
this.style.backgroundImage = '';
|
|
26
|
+
} else if (reqSrc != this.currentSrc) {
|
|
59
27
|
this.#defer?.resolve();
|
|
60
28
|
this.#defer = new Deferred();
|
|
61
29
|
const img = new Image();
|
|
@@ -63,8 +31,8 @@ class HTMLElementLayout extends Page.create(HTMLDivElement) {
|
|
|
63
31
|
img.addEventListener('error',
|
|
64
32
|
e => this.#defer.reject(new Error(this.currentSrc))
|
|
65
33
|
);
|
|
66
|
-
img.src =
|
|
67
|
-
this.style.backgroundImage = `url("${
|
|
34
|
+
img.src = reqSrc;
|
|
35
|
+
this.style.backgroundImage = `url("${reqSrc}")`;
|
|
68
36
|
return this.#defer;
|
|
69
37
|
}
|
|
70
38
|
}
|
|
@@ -74,14 +42,13 @@ class HTMLElementLayout extends Page.create(HTMLDivElement) {
|
|
|
74
42
|
}
|
|
75
43
|
|
|
76
44
|
(function(HTMLElementImage) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
45
|
+
for (const name of ['crop', 'dimensions', 'requestSrc']) {
|
|
46
|
+
Object.defineProperty(
|
|
47
|
+
HTMLElementLayout.prototype,
|
|
48
|
+
name,
|
|
49
|
+
Object.getOwnPropertyDescriptor(HTMLElementImage.prototype, name)
|
|
50
|
+
);
|
|
51
|
+
}
|
|
85
52
|
})(window.customElements.get('element-image'));
|
|
86
53
|
|
|
87
54
|
Page.define(`element-layout`, HTMLElementLayout, 'div');
|
package/ui/pagination.js
CHANGED
|
@@ -9,7 +9,7 @@ class HTMLElementPagination extends Page.create(HTMLAnchorElement) {
|
|
|
9
9
|
#update(state) {
|
|
10
10
|
const { fetch } = this.dataset;
|
|
11
11
|
const node = this.ownerDocument.querySelector(
|
|
12
|
-
`element-template[action="
|
|
12
|
+
`element-template[action="/@api/query/${fetch}"]`
|
|
13
13
|
);
|
|
14
14
|
if (!node) {
|
|
15
15
|
console.warn("pagination does not find fetch node", fetch);
|
package/ui/textcard.css
ADDED