@pageboard/html 0.14.9 → 0.14.11
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/fieldsets.js +40 -4
- package/elements/form.js +2 -4
- package/elements/grid.js +1 -1
- package/elements/image.js +0 -3
- package/elements/input-date.js +1 -7
- package/elements/input-file.js +1 -7
- package/elements/input-property.js +1 -4
- package/elements/inputs.js +33 -22
- package/elements/layout.js +13 -8
- package/elements/link.js +66 -0
- package/elements/media.js +2 -2
- package/elements/menu.js +1 -1
- package/elements/navigation.js +1 -1
- package/elements/pagination.js +1 -1
- package/elements/sitemap.js +1 -56
- package/lib/object-fit-images.js +8 -3
- package/package.json +2 -7
- package/ui/button.css +11 -0
- package/ui/fieldset-list.js +120 -122
- package/ui/fieldset.js +5 -5
- package/ui/form.css +5 -2
- package/ui/form.js +22 -48
- package/ui/image.js +0 -17
- package/ui/input-file.css +1 -6
- package/ui/select.css +15 -0
- package/ui/select.js +76 -61
- package/ui/site.css +0 -21
- package/ui/sitemap-helper.js +0 -73
- package/ui/sitemap.css +0 -53
- package/ui/sitemap.js +0 -78
package/ui/select.js
CHANGED
|
@@ -1,15 +1,6 @@
|
|
|
1
1
|
class HTMLElementSelect extends Page.Element {
|
|
2
2
|
#observer;
|
|
3
3
|
|
|
4
|
-
static defaults = {
|
|
5
|
-
placeholder: null,
|
|
6
|
-
name: null,
|
|
7
|
-
value: null,
|
|
8
|
-
multiple: false,
|
|
9
|
-
disabled: false,
|
|
10
|
-
required: false
|
|
11
|
-
};
|
|
12
|
-
|
|
13
4
|
#child(sel) {
|
|
14
5
|
return this.children.find(node => node.matches(sel));
|
|
15
6
|
}
|
|
@@ -23,6 +14,49 @@ class HTMLElementSelect extends Page.Element {
|
|
|
23
14
|
return this.#child('select');
|
|
24
15
|
}
|
|
25
16
|
|
|
17
|
+
get name() {
|
|
18
|
+
return this.getAttribute('name');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
get required() {
|
|
22
|
+
return this.hasAttribute('required');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
get multiple() {
|
|
26
|
+
return this.hasAttribute('multiple');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
get disabled() {
|
|
30
|
+
return this.hasAttribute('disabled');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
get value() {
|
|
34
|
+
return this.getAttribute('value');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
set name(n) {
|
|
38
|
+
this.setAttribute('name', n);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
set required(b) {
|
|
42
|
+
if (b) this.setAttribute('required', '');
|
|
43
|
+
else this.removeAttribute('required');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
set multiple(b) {
|
|
47
|
+
if (b) this.setAttribute('multiple', '');
|
|
48
|
+
else this.removeAttribute('multiple');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
set disabled(b) {
|
|
52
|
+
if (b) this.setAttribute('disabled', '');
|
|
53
|
+
else this.removeAttribute('disabled');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
set value(v) {
|
|
57
|
+
this.getAttribute('value', v);
|
|
58
|
+
}
|
|
59
|
+
|
|
26
60
|
handleClick(e, state) {
|
|
27
61
|
if (state.scope.$write) return;
|
|
28
62
|
const node = e.target;
|
|
@@ -32,7 +66,7 @@ class HTMLElementSelect extends Page.Element {
|
|
|
32
66
|
if (opt) {
|
|
33
67
|
opt.selected = true;
|
|
34
68
|
state.dispatch(opt, 'change');
|
|
35
|
-
this
|
|
69
|
+
this.classList.remove('active');
|
|
36
70
|
}
|
|
37
71
|
return;
|
|
38
72
|
}
|
|
@@ -45,7 +79,7 @@ class HTMLElementSelect extends Page.Element {
|
|
|
45
79
|
}
|
|
46
80
|
return;
|
|
47
81
|
}
|
|
48
|
-
this
|
|
82
|
+
this.classList.toggle('active');
|
|
49
83
|
}
|
|
50
84
|
handleChange(e, state) {
|
|
51
85
|
const opt = e.target;
|
|
@@ -55,17 +89,12 @@ class HTMLElementSelect extends Page.Element {
|
|
|
55
89
|
this.#deselectItem(opt);
|
|
56
90
|
}
|
|
57
91
|
}
|
|
58
|
-
#toggleMenu(show) {
|
|
59
|
-
const style = this.#menu.style;
|
|
60
|
-
if (show === undefined) show = !style.display;
|
|
61
|
-
style.display = show ? "block" : null;
|
|
62
|
-
}
|
|
63
92
|
#selectItem(opt) {
|
|
64
93
|
const select = this.#select;
|
|
65
94
|
const val = opt.getAttribute('value');
|
|
66
95
|
const item = this.#menuOption(val);
|
|
67
96
|
|
|
68
|
-
if (this.
|
|
97
|
+
if (this.multiple) {
|
|
69
98
|
if (this.#child(`.label[data-value="${val}"]`) == null) {
|
|
70
99
|
this.#setText("").insertAdjacentHTML(
|
|
71
100
|
'beforeBegin',
|
|
@@ -81,7 +110,7 @@ class HTMLElementSelect extends Page.Element {
|
|
|
81
110
|
}
|
|
82
111
|
#deselectItem(opt) {
|
|
83
112
|
const val = opt.getAttribute('value');
|
|
84
|
-
if (this.
|
|
113
|
+
if (this.multiple && val) {
|
|
85
114
|
const item = this.#child(`.label[data-value="${val}"]`);
|
|
86
115
|
if (item) item.remove();
|
|
87
116
|
}
|
|
@@ -95,9 +124,8 @@ class HTMLElementSelect extends Page.Element {
|
|
|
95
124
|
text.classList.remove('default');
|
|
96
125
|
return text;
|
|
97
126
|
}
|
|
98
|
-
#setPlaceholder(str) {
|
|
127
|
+
#setPlaceholder(str = '') {
|
|
99
128
|
const text = this.#text;
|
|
100
|
-
if (!str) str = this.options.placeholder;
|
|
101
129
|
|
|
102
130
|
const defaultOption = this.#select.querySelector('option[value=""]');
|
|
103
131
|
if (defaultOption) {
|
|
@@ -123,57 +151,44 @@ class HTMLElementSelect extends Page.Element {
|
|
|
123
151
|
this.#observer = null;
|
|
124
152
|
}
|
|
125
153
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
setup(state) {
|
|
133
|
-
this.#observer = new MutationObserver(mutations => this.#fillSelect(state));
|
|
134
|
-
this.#observer.observe(this.#menu, {
|
|
135
|
-
childList: true
|
|
154
|
+
fill(values) {
|
|
155
|
+
this.#select.children.forEach(opt => {
|
|
156
|
+
if (opt.value) {
|
|
157
|
+
if (opt.selected) this.#selectItem(opt);
|
|
158
|
+
else this.#deselectItem(opt);
|
|
159
|
+
}
|
|
136
160
|
});
|
|
137
161
|
}
|
|
138
|
-
|
|
139
|
-
build(state) {
|
|
140
|
-
if (state.scope.$write) return;
|
|
141
|
-
if (this.children.length == 1) {
|
|
142
|
-
this.insertAdjacentHTML(
|
|
143
|
-
'afterBegin',
|
|
144
|
-
'<i class="dropdown icon"></i><div class="text"></div><select></select>'
|
|
145
|
-
);
|
|
146
|
-
}
|
|
162
|
+
prepare(editable) {
|
|
147
163
|
const select = this.#select;
|
|
148
|
-
|
|
149
|
-
select.
|
|
150
|
-
select.
|
|
151
|
-
select.multiple = this.options.multiple;
|
|
164
|
+
select.disabled = this.disabled;
|
|
165
|
+
select.required = this.required;
|
|
166
|
+
select.multiple = this.multiple;
|
|
152
167
|
if (!select.multiple) {
|
|
153
168
|
for (const node of this.querySelectorAll('.ui.label')) node.remove();
|
|
154
169
|
}
|
|
155
|
-
select.name = this.
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
170
|
+
select.name = this.name;
|
|
171
|
+
const menu = this.#menu;
|
|
172
|
+
const defaultOption = menu.querySelector('element-select-option[data-value=""]');
|
|
173
|
+
if (!select.required && !editable) {
|
|
174
|
+
if (!defaultOption) {
|
|
159
175
|
menu.insertAdjacentHTML('afterBegin', `<element-select-option data-value="" block-type="input_select_option" class="item">-</element-select-option>`);
|
|
160
176
|
}
|
|
177
|
+
} else if (defaultOption) {
|
|
178
|
+
defaultOption.remove();
|
|
179
|
+
}
|
|
180
|
+
if (menu.children.length != select.children.length && !editable) {
|
|
181
|
+
// TODO do a better check
|
|
182
|
+
select.textContent = '';
|
|
183
|
+
select.insertAdjacentHTML('afterBegin', '<option value="[item.dataset.value]">[children|at:*|repeat:item|.innerText]</option>');
|
|
184
|
+
select.fuse(this.#menu, {});
|
|
161
185
|
}
|
|
162
|
-
this.#fillSelect(state);
|
|
163
186
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
state.finish(() => {
|
|
170
|
-
// synchronize after form has filled select
|
|
171
|
-
this.#select.children.forEach(opt => {
|
|
172
|
-
if (opt.value) {
|
|
173
|
-
if (opt.selected) this.#selectItem(opt);
|
|
174
|
-
else this.#deselectItem(opt);
|
|
175
|
-
}
|
|
176
|
-
});
|
|
187
|
+
setup() {
|
|
188
|
+
if (this.isContentEditable) return;
|
|
189
|
+
this.#observer = new MutationObserver(mutations => this.prepare());
|
|
190
|
+
this.#observer.observe(this.#menu, {
|
|
191
|
+
childList: true
|
|
177
192
|
});
|
|
178
193
|
}
|
|
179
194
|
}
|
package/ui/site.css
CHANGED
|
@@ -258,24 +258,3 @@ body .ui.inverted::-webkit-scrollbar-thumb:hover {
|
|
|
258
258
|
margin-left: auto !important;
|
|
259
259
|
margin-right: auto !important;
|
|
260
260
|
}
|
|
261
|
-
|
|
262
|
-
/* for editor only, but semantic-ui dependent */
|
|
263
|
-
[contenteditable] .ui.buttons .disabled.button,
|
|
264
|
-
[contenteditable] .ui.disabled.button,
|
|
265
|
-
[contenteditable] .ui.button:disabled,
|
|
266
|
-
[contenteditable] .ui.disabled.button:hover,
|
|
267
|
-
[contenteditable] .ui.disabled.active.button {
|
|
268
|
-
pointer-events: auto !important;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
[contenteditable] .ui.dropdown[block-focused] > .menu {
|
|
272
|
-
overflow: visible;
|
|
273
|
-
width: auto;
|
|
274
|
-
height: auto;
|
|
275
|
-
top: 100% !important;
|
|
276
|
-
opacity: 1;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
[contenteditable] .field[block-focused] .dropdown > .menu {
|
|
280
|
-
display: block !important;
|
|
281
|
-
}
|
package/ui/sitemap-helper.js
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
class HTMLElementSitepage extends Page.Element {
|
|
2
|
-
static defaults = {
|
|
3
|
-
url: null,
|
|
4
|
-
index: (x) => parseInt(x) || 0
|
|
5
|
-
};
|
|
6
|
-
|
|
7
|
-
patch(state) {
|
|
8
|
-
if (this.isConnected) this.syncBlock(state.scope);
|
|
9
|
-
}
|
|
10
|
-
setup(state) {
|
|
11
|
-
const content = this.querySelector('[block-content="children"]');
|
|
12
|
-
if (!content) return;
|
|
13
|
-
this.observer = new MutationObserver(mutations => this.updateChildren());
|
|
14
|
-
this.observer.observe(content, {
|
|
15
|
-
childList: true
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
close(state) {
|
|
20
|
-
if (this.observer) this.observer.disconnect();
|
|
21
|
-
delete this.observer;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
updateChildren() {
|
|
25
|
-
if (this.updating) return;
|
|
26
|
-
const content = this.querySelector('[block-content="children"]');
|
|
27
|
-
if (!content) return;
|
|
28
|
-
this.updating = true;
|
|
29
|
-
const parentUrl = this.dataset.url || "";
|
|
30
|
-
const uniques = {};
|
|
31
|
-
Array.prototype.forEach.call(content.children, (child, index) => {
|
|
32
|
-
if (!child.matches('element-sitepage')) return; // cursor
|
|
33
|
-
const childUrl = child.dataset.url || '';
|
|
34
|
-
if (childUrl.startsWith('/.')) return;
|
|
35
|
-
const newUrl = parentUrl + "/" + childUrl.split('/').pop();
|
|
36
|
-
if (childUrl != newUrl && !uniques[newUrl]) {
|
|
37
|
-
child.setAttribute('data-url', newUrl);
|
|
38
|
-
}
|
|
39
|
-
uniques[newUrl] = true;
|
|
40
|
-
const curIndex = parseInt(child.dataset.index);
|
|
41
|
-
if (curIndex != index) {
|
|
42
|
-
child.setAttribute('data-index', index);
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
this.updating = false;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
syncBlock(scope) {
|
|
49
|
-
if (!this.parentNode || this.matches('element-sitemap')) return;
|
|
50
|
-
const editor = scope.editor;
|
|
51
|
-
if (!editor || editor.closed) return;
|
|
52
|
-
const block = editor.blocks.get(this.getAttribute('block-id'));
|
|
53
|
-
if (!block.data) block.data = {};
|
|
54
|
-
const data = this.options;
|
|
55
|
-
if (Object.keys(data).some(key => data[key] != block.data[key])) {
|
|
56
|
-
Object.assign(block.data, data);
|
|
57
|
-
editor.dispatch(editor.utils.refreshTr(editor.state.tr, this, block));
|
|
58
|
-
this.updateChildren();
|
|
59
|
-
} else this.updateChildren();
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
Page.define('element-sitepage', HTMLElementSitepage);
|
|
66
|
-
|
|
67
|
-
Page.setup(state => {
|
|
68
|
-
if (!state.scope.$write) return;
|
|
69
|
-
state.finish(() => {
|
|
70
|
-
Page.extend('element-sitemap', HTMLElementSitepage);
|
|
71
|
-
});
|
|
72
|
-
});
|
|
73
|
-
|
package/ui/sitemap.css
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
[block-type="sitemap"] {
|
|
2
|
-
min-height:2em;
|
|
3
|
-
position:relative;
|
|
4
|
-
display: block;
|
|
5
|
-
width: 100%;
|
|
6
|
-
}
|
|
7
|
-
[block-type="sitemap"] .caret-icon::before {
|
|
8
|
-
right:auto;
|
|
9
|
-
left:-0.8em;
|
|
10
|
-
}
|
|
11
|
-
.ui.list[block-type="sitemap"] {
|
|
12
|
-
padding:0.5em;
|
|
13
|
-
margin:0.5em;
|
|
14
|
-
box-shadow: -1px 1px 2px 1px grey;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
[block-type="sitemap"] .list > .item > .content {
|
|
18
|
-
box-shadow: 0 1px 1px 1px grey;
|
|
19
|
-
padding-right: 0.5em;
|
|
20
|
-
padding-bottom:1px;
|
|
21
|
-
margin-bottom: 0;
|
|
22
|
-
min-height:1em;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
[block-type="sitemap"] .list.content.active {
|
|
26
|
-
margin-top:0;
|
|
27
|
-
padding-bottom: 1em !important;
|
|
28
|
-
margin-left: 1em;
|
|
29
|
-
padding-top: 0 !important;
|
|
30
|
-
margin-right: 1em;
|
|
31
|
-
}
|
|
32
|
-
.ui.accordion[block-type="sitemap"] .title > a,
|
|
33
|
-
.ui.accordion[block-type="sitemap"] .accordion .title > a {
|
|
34
|
-
padding-left:1.25em;
|
|
35
|
-
}
|
|
36
|
-
element-sitepage {
|
|
37
|
-
display:block;
|
|
38
|
-
position: relative;
|
|
39
|
-
}
|
|
40
|
-
element-sitepage .title.caret-icon.active {
|
|
41
|
-
padding-bottom:0 !important;
|
|
42
|
-
}
|
|
43
|
-
element-sitepage > .title > .label {
|
|
44
|
-
float:right;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
element-sitepage > .title > a.description {
|
|
48
|
-
color: darkgrey;
|
|
49
|
-
}
|
|
50
|
-
element-sitepage > .title > a.redirection {
|
|
51
|
-
color:dodgerblue;
|
|
52
|
-
}
|
|
53
|
-
|
package/ui/sitemap.js
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
class HTMLElementSitemap extends Page.Element {
|
|
2
|
-
static makeTree(tree, parent) {
|
|
3
|
-
let page = tree._;
|
|
4
|
-
if (page) {
|
|
5
|
-
if (!parent.children) parent.children = [];
|
|
6
|
-
const old = parent.children.find(item => item.id == page.id);
|
|
7
|
-
if (!old) parent.children.push(page);
|
|
8
|
-
if (parent.content == null) parent.content = {};
|
|
9
|
-
if (parent.content.children == null) parent.content.children = "";
|
|
10
|
-
if (typeof parent.content.children == "string") {
|
|
11
|
-
parent.content.children += `<div block-id="${page.id}" block-type="${page.type}"></div>`;
|
|
12
|
-
}
|
|
13
|
-
delete tree._;
|
|
14
|
-
} else {
|
|
15
|
-
page = parent;
|
|
16
|
-
}
|
|
17
|
-
for (const name of Object.keys(tree).sort((a, b) => {
|
|
18
|
-
const pageA = tree[a]._;
|
|
19
|
-
const pageB = tree[b]._;
|
|
20
|
-
if (!pageA || !pageB) return 0;
|
|
21
|
-
let indexA = pageA.data.index;
|
|
22
|
-
if (indexA == null) indexA = Infinity;
|
|
23
|
-
let indexB = pageB.data.index;
|
|
24
|
-
if (indexB == null) indexB = Infinity;
|
|
25
|
-
if (indexA == indexB) return 0;
|
|
26
|
-
else if (indexA < indexB) return -1;
|
|
27
|
-
else if (indexA > indexB) return 1;
|
|
28
|
-
})) {
|
|
29
|
-
this.makeTree(tree[name], page);
|
|
30
|
-
}
|
|
31
|
-
return parent;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
static transformResponse(res) {
|
|
35
|
-
const pages = res.items;
|
|
36
|
-
const tree = {};
|
|
37
|
-
|
|
38
|
-
for (const page of pages) {
|
|
39
|
-
if (!page.data.url) continue;
|
|
40
|
-
let branch = tree;
|
|
41
|
-
const arr = page.data.url.substring(1).split('/');
|
|
42
|
-
arr.forEach((name, i) => {
|
|
43
|
-
if (!branch[name]) branch[name] = {};
|
|
44
|
-
branch = branch[name];
|
|
45
|
-
if (i == arr.length - 1) branch._ = page;
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
return this.makeTree(tree, {
|
|
49
|
-
type: 'sitemap',
|
|
50
|
-
content: { children: '' },
|
|
51
|
-
children: []
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
async build(state) {
|
|
56
|
-
if (this.firstElementChild.children.length > 0 && state.scope.$write) {
|
|
57
|
-
// workaround... build is called a second time with pagecut-placeholder set
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
const res = await state.fetch('get', `/.api/pages`);
|
|
61
|
-
const scope = state.scope.copy();
|
|
62
|
-
await scope.import(res);
|
|
63
|
-
const tree = this.constructor.transformResponse(res);
|
|
64
|
-
const node = scope.render({
|
|
65
|
-
item: tree
|
|
66
|
-
});
|
|
67
|
-
// only change block content
|
|
68
|
-
const src = node.firstElementChild;
|
|
69
|
-
const dst = this.firstElementChild;
|
|
70
|
-
dst.textContent = '';
|
|
71
|
-
while (src.firstChild) dst.appendChild(src.firstChild);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
Page.define('element-sitemap', HTMLElementSitemap);
|
|
77
|
-
|
|
78
|
-
|