@pageboard/html 0.10.5 → 0.10.9

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.
@@ -54,6 +54,7 @@ exports.input_property = {
54
54
  // /.api/form wraps it into block.data
55
55
  list.shift();
56
56
  name = list.join('.');
57
+ const id = scope.$id;
57
58
  let prop = el;
58
59
  let propKey;
59
60
  let required = false;
@@ -65,7 +66,9 @@ exports.input_property = {
65
66
  prop = cases[propKey];
66
67
  cases = null;
67
68
  } else {
68
- cases = prop.selectCases;
69
+ if (prop.select && prop.select.$data == `0/${propKey}`) {
70
+ cases = prop.selectCases;
71
+ }
69
72
  prop = (prop.properties || {})[propKey] || null;
70
73
  }
71
74
  if (prop == null) break;
@@ -75,8 +78,14 @@ exports.input_property = {
75
78
  }
76
79
  node.textContent = "";
77
80
  if (prop.nullable) required = false;
78
- let listOf = prop.anyOf || prop.oneOf;
79
- let propType;
81
+ let propType = prop;
82
+ let multiple = d.multiple;
83
+ if (prop.type == "array" && prop.items && Array.isArray(prop.items) == false) {
84
+ propType = prop.items;
85
+ multiple = true;
86
+ }
87
+
88
+ let listOf = propType.anyOf || propType.oneOf;
80
89
  if (listOf) {
81
90
  const listOfNo = listOf.filter((item) => item.type != "null");
82
91
  if (listOfNo.length != listOf.length) {
@@ -85,7 +94,7 @@ exports.input_property = {
85
94
  if (listOfNo.length == 1 && listOfNo[0].const === undefined) {
86
95
  propType = listOfNo[0];
87
96
  listOf = null;
88
- } else if (d.multiple) {
97
+ } else if (multiple) {
89
98
  listOf = listOfNo;
90
99
  }
91
100
  } else if (Array.isArray(prop.type)) {
@@ -104,7 +113,6 @@ exports.input_property = {
104
113
  listOf = null; // cannot deal with this for now
105
114
  }
106
115
  }
107
- if (!propType) propType = prop;
108
116
 
109
117
  if (listOf) {
110
118
  if (listOf.length <= d.radios) {
@@ -124,7 +132,7 @@ exports.input_property = {
124
132
  content = content.lastElementChild;
125
133
  for (const item of listOf) {
126
134
  content.appendChild(view.render({
127
- type: d.multiple ? 'input_checkbox' : 'input_radio',
135
+ type: multiple ? 'input_checkbox' : 'input_radio',
128
136
  data: {
129
137
  name: name,
130
138
  value: item.type == "null" ? null : item.const,
@@ -149,10 +157,11 @@ exports.input_property = {
149
157
  }));
150
158
  }
151
159
  node.appendChild(view.render({
160
+ id,
152
161
  type: 'input_select',
153
162
  data: {
154
163
  name: name,
155
- multiple: d.multiple,
164
+ multiple: multiple,
156
165
  placeholder: prop.description,
157
166
  disabled: d.disabled,
158
167
  required: required
@@ -163,20 +172,22 @@ exports.input_property = {
163
172
  }
164
173
  }));
165
174
  }
166
- } else if (propType.type == "integer") {
175
+ } else if (propType.type == "integer" || propType.type == "number") {
176
+ const step = propType.multipleOf || (propType.type == "integer" ? 1 : 0.001);
167
177
  if (propType.minimum != null && propType.maximum != null) {
168
178
  if (propType.maximum - propType.minimum <= d.range) {
169
179
  return node.appendChild(view.render({
180
+ id,
170
181
  type: 'input_range',
171
182
  data: {
172
183
  name: name,
173
184
  min: propType.minimum,
174
185
  max: propType.maximum,
175
- value: d.multiple ? `${propType.minimum}⩽${propType.maximum}` : propType.default,
186
+ value: multiple ? `${propType.minimum}⩽${propType.maximum}` : propType.default,
176
187
  disabled: d.disabled,
177
188
  required: required,
178
- multiple: d.multiple,
179
- step: 1
189
+ multiple: multiple,
190
+ step: step
180
191
  },
181
192
  content: {
182
193
  label: prop.title
@@ -185,13 +196,16 @@ exports.input_property = {
185
196
  }
186
197
  }
187
198
  node.appendChild(view.render({
188
- type: 'input_text',
199
+ id,
200
+ type: 'input_number',
189
201
  data: {
190
202
  name: name,
191
- type: 'number',
192
203
  default: propType.default,
193
204
  disabled: d.disabled,
194
- required: required
205
+ required: required,
206
+ min: propType.minimum,
207
+ max: propType.maximum,
208
+ step: step
195
209
  },
196
210
  content: {
197
211
  label: prop.title
@@ -199,6 +213,7 @@ exports.input_property = {
199
213
  }));
200
214
  } else if (propType.type == "boolean") {
201
215
  node.appendChild(view.render({
216
+ id,
202
217
  type: 'input_checkbox',
203
218
  data: {
204
219
  name: name,
@@ -211,8 +226,13 @@ exports.input_property = {
211
226
  }
212
227
  }));
213
228
  } else if (propType.type == "string" && propType.format == "date") {
229
+ let type = "input_date_time";
230
+ if (!scope.$elements[type]) {
231
+ type = 'input_text';
232
+ }
214
233
  node.appendChild(view.render({
215
- type: 'input_date_time',
234
+ id,
235
+ type: type,
216
236
  data: {
217
237
  name: name,
218
238
  type: propType.format,
@@ -226,8 +246,13 @@ exports.input_property = {
226
246
  }
227
247
  }));
228
248
  } else if (propType.type == "string" && propType.format == "time") {
249
+ let type = "input_date_time";
250
+ if (!scope.$elements[type]) {
251
+ type = 'input_text';
252
+ }
229
253
  node.appendChild(view.render({
230
- type: 'input_date_time',
254
+ id,
255
+ type: type,
231
256
  data: {
232
257
  name: name,
233
258
  type: propType.format,
@@ -240,14 +265,42 @@ exports.input_property = {
240
265
  label: prop.title
241
266
  }
242
267
  }));
268
+ } else if (propType.$helper && propType.$helper.name == "href") {
269
+ const limits = {
270
+ files: multiple ? null : 1
271
+ };
272
+ const filter = propType.$helper.filter;
273
+ if (filter && filter.type) {
274
+ limits.types = filter.type.map((type) => {
275
+ if (type == "image") return "image/*";
276
+ else if (type == "video") return "video/*";
277
+ else return "*/*";
278
+ });
279
+ }
280
+ node.appendChild(view.render({
281
+ id,
282
+ type: 'input_file',
283
+ data: {
284
+ name: name,
285
+ disabled: d.disabled,
286
+ placeholder: propType.description,
287
+ required: required,
288
+ limits: limits
289
+ },
290
+ content: {
291
+ label: prop.title
292
+ }
293
+ }));
243
294
  } else {
244
295
  node.appendChild(view.render({
296
+ id,
245
297
  type: 'input_text',
246
298
  data: {
247
299
  name: name,
248
- type: propType.format == 'singleline' ? 'text' : 'textarea',
300
+ type: (propType.pattern || propType.format) ? 'text' : 'textarea',
249
301
  disabled: d.disabled,
250
302
  default: propType.default,
303
+ placeholder: propType.description,
251
304
  required: required
252
305
  },
253
306
  content: {
@@ -5,6 +5,25 @@ exports.fieldset = {
5
5
  group: 'block',
6
6
  context: 'form//',
7
7
  properties: {
8
+ name: {
9
+ title: 'Show if input named',
10
+ type: 'string',
11
+ format: 'singleline',
12
+ nullable: true,
13
+ $helper: {
14
+ name: 'element-property',
15
+ existing: true
16
+ }
17
+ },
18
+ value: {
19
+ title: 'matches this value',
20
+ type: 'string',
21
+ format: 'singleline',
22
+ $filter: {
23
+ name: 'element-value',
24
+ using: 'name'
25
+ }
26
+ },
8
27
  plain: {
9
28
  title: 'Without borders',
10
29
  type: 'boolean',
@@ -12,7 +31,8 @@ exports.fieldset = {
12
31
  }
13
32
  },
14
33
  contents: "fieldset_legend block+",
15
- html: '<fieldset class="[plain|?]"></fieldset>'
34
+ html: '<fieldset class="[plain|?]" data-name="[name]" data-value="[value]" is="element-fieldset"></fieldset>',
35
+ scripts: ["../ui/fieldset.js"]
16
36
  };
17
37
 
18
38
  exports.fieldset_legend = {
@@ -152,8 +172,8 @@ exports.input_text = {
152
172
  const: "tel",
153
173
  title: "Tel"
154
174
  }, {
155
- const: "number",
156
- title: "Number"
175
+ // deprecated, use input_number or input_range
176
+ const: "number"
157
177
  }, {
158
178
  const: "hidden",
159
179
  title: "Hidden"
@@ -203,60 +223,71 @@ exports.input_text = {
203
223
  </div>`
204
224
  };
205
225
 
206
- exports.input_range = {
207
- title: 'Range',
208
- icon: '<i class="options icon"></i>',
226
+ exports.input_number = {
227
+ title: 'Number',
228
+ icon: '<i class="text cursor icon"></i>',
209
229
  menu: "form",
230
+ required: ["name"],
210
231
  group: "block",
211
232
  context: 'form//',
212
233
  properties: {
213
- name: {
214
- title: "Name",
215
- description: "The form object key",
216
- type: "string",
217
- format: "singleline"
218
- },
219
- disabled: {
220
- title: 'Disabled',
221
- type: 'boolean',
222
- default: false
223
- },
224
- required: {
225
- title: 'Required',
226
- type: 'boolean',
227
- default: false
228
- },
229
- multiple: {
230
- title: 'Multiple',
231
- type: 'boolean',
232
- default: false
233
- },
234
- value: {
235
- title: "Value",
236
- type: "number",
237
- nullable: true
238
- },
234
+ name: exports.input_text.properties.name,
235
+ disabled: exports.input_text.properties.disabled,
236
+ required: exports.input_text.properties.required,
237
+ value: exports.input_text.properties.value,
239
238
  min: {
240
239
  title: 'Minimum value',
241
240
  type: "number",
242
- default: 0
241
+ nullable: true
243
242
  },
244
243
  max: {
245
244
  title: 'Maximum value',
246
245
  type: "number",
247
- default: 100
246
+ nullable: true
248
247
  },
249
248
  step: {
250
249
  title: 'Step',
251
250
  type: "number",
252
- default: 1
251
+ default: 0.001
252
+ }
253
+ },
254
+ contents: {
255
+ id: 'label',
256
+ nodes: 'inline*'
257
+ },
258
+ html: `<div class="[width|num: wide] field">
259
+ <label block-content="label">Label</label>
260
+ <input name="[name]"
261
+ required="[required]"
262
+ readonly="[readonly]"
263
+ disabled="[disabled]"
264
+ placeholder="[placeholder]"
265
+ type="number"
266
+ value="[value]"
267
+ min="[minimum]"
268
+ max="[maximum]"
269
+ step="[step]"
270
+ </div>`
271
+ };
272
+
273
+ exports.input_range = {
274
+ title: 'Range',
275
+ icon: '<i class="options icon"></i>',
276
+ menu: "form",
277
+ group: "block",
278
+ context: 'form//',
279
+ properties: Object.assign({
280
+ multiple: {
281
+ title: 'Multiple',
282
+ type: 'boolean',
283
+ default: false
253
284
  },
254
285
  pips: {
255
286
  title: 'Pips',
256
287
  type: 'boolean',
257
288
  default: true
258
289
  }
259
- },
290
+ }, exports.input_number.properties),
260
291
  contents: {
261
292
  id: 'label',
262
293
  nodes: 'inline*'
package/elements/form.js CHANGED
@@ -17,7 +17,7 @@ exports.query_form = {
17
17
  description: 'Checks schema and helps adding form controls',
18
18
  nullable: true,
19
19
  type: 'string',
20
- format: 'id',
20
+ format: 'name',
21
21
  $filter: {
22
22
  name: 'element',
23
23
  contentless: true,
@@ -128,7 +128,7 @@ exports.heading = {
128
128
  id: {
129
129
  nullable: true,
130
130
  type: 'string',
131
- format: 'id'
131
+ pattern: '^[a-z0-9-]*$'
132
132
  }
133
133
  },
134
134
  contents: {
@@ -38,20 +38,14 @@
38
38
  z-index: 1;
39
39
  top: 0;
40
40
  right: 0;
41
+ height: 100%;
42
+ width: 100%;
41
43
  -ms-transform-origin: 0 0;
42
44
  -webkit-transform-origin: 0 0;
43
45
  -webkit-transform-style: preserve-3d;
44
46
  transform-origin: 0 0;
45
47
  transform-style: flat;
46
48
  }
47
- .noUi-connect {
48
- height: 100%;
49
- width: 100%;
50
- }
51
- .noUi-origin {
52
- height: 10%;
53
- width: 10%;
54
- }
55
49
  /* Offset direction
56
50
  */
57
51
  .noUi-txt-dir-rtl.noUi-horizontal .noUi-origin {
@@ -62,6 +56,7 @@
62
56
  * connect elements.
63
57
  */
64
58
  .noUi-vertical .noUi-origin {
59
+ top: -100%;
65
60
  width: 0;
66
61
  }
67
62
  .noUi-horizontal .noUi-origin {
@@ -102,7 +97,7 @@
102
97
  width: 28px;
103
98
  height: 34px;
104
99
  right: -6px;
105
- top: -17px;
100
+ bottom: -17px;
106
101
  }
107
102
  .noUi-txt-dir-rtl.noUi-horizontal .noUi-handle {
108
103
  left: -17px;
package/lib/nouislider.js CHANGED
@@ -281,17 +281,8 @@
281
281
  }
282
282
  }
283
283
  Spectrum.prototype.getDistance = function (value) {
284
- var index;
285
284
  var distances = [];
286
- for (index = 0; index < this.xNumSteps.length - 1; index++) {
287
- // last "range" can't contain step size as it is purely an endpoint.
288
- var step = this.xNumSteps[index];
289
- if (step && (value / step) % 1 !== 0) {
290
- throw new Error("noUiSlider: 'limit', 'margin' and 'padding' of " +
291
- this.xPct[index] +
292
- "% range must be divisible by step.");
293
- }
294
- // Calculate percentual distance in current range of limit, margin or padding
285
+ for (var index = 0; index < this.xNumSteps.length - 1; index++) {
295
286
  distances[index] = fromPercentage(this.xVal, value, index);
296
287
  }
297
288
  return distances;
@@ -1896,7 +1887,7 @@
1896
1887
  scope_Locations[handleNumber] = to;
1897
1888
  // Convert the value to the slider stepping/range.
1898
1889
  scope_Values[handleNumber] = scope_Spectrum.fromStepping(to);
1899
- var translation = 10 * (transformDirection(to, 0) - scope_DirOffset);
1890
+ var translation = transformDirection(to, 0) - scope_DirOffset;
1900
1891
  var translateRule = "translate(" + inRuleOrder(translation + "%", "0") + ")";
1901
1892
  scope_Handles[handleNumber].style[options.transformRule] = translateRule;
1902
1893
  updateConnect(handleNumber);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pageboard/html",
3
- "version": "0.10.5",
3
+ "version": "0.10.9",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -19,14 +19,14 @@
19
19
  },
20
20
  "homepage": "https://github.com/pageboard/client#readme",
21
21
  "dependencies": {
22
- "postinstall": "^0.7.3",
22
+ "postinstall": "^0.7.4",
23
23
  "semantic-ui-css": "^2.4.1"
24
24
  },
25
25
  "devDependencies": {
26
- "formdata-polyfill": "^4.0.7",
27
- "nouislider": "^15.4.0",
26
+ "formdata-polyfill": "^4.0.10",
27
+ "nouislider": "^15.5.0",
28
28
  "object-fit-images": "^3.2.4",
29
- "postinstall-bundle": "^0.7.3"
29
+ "postinstall-bundle": "^0.7.4"
30
30
  },
31
31
  "postinstall": {
32
32
  "semantic-ui-css/components": "link lib/components",
package/ui/fieldset.js ADDED
@@ -0,0 +1,36 @@
1
+ class HTMLCustomFieldSetElement extends HTMLFieldSetElement {
2
+ static defaults = {
3
+ dataName: null,
4
+ dataValue: null
5
+ };
6
+ constructor() {
7
+ super();
8
+ this.init?.();
9
+ }
10
+
11
+ #update() {
12
+ if (this.isContentEditable || !this.options.name) return;
13
+ const name = this.options.name.split(".").slice(1).join('.');
14
+ const val = this.form?.read(true)?.[name];
15
+ this.disabled = this.hidden = val != this.options.value;
16
+ }
17
+
18
+ patch() {
19
+ this.#update();
20
+ }
21
+ setup() {
22
+ this.form?.addEventListener('change', this);
23
+ }
24
+ close() {
25
+ this.form?.removeEventListener('change', this);
26
+ }
27
+ handleEvent(e) {
28
+ if (e.type == "change") {
29
+ this.#update();
30
+ }
31
+ }
32
+ }
33
+
34
+ Page.ready(() => {
35
+ VirtualHTMLElement.define(`element-fieldset`, HTMLCustomFieldSetElement, 'fieldset');
36
+ });
package/ui/form.js CHANGED
@@ -87,6 +87,8 @@ class HTMLCustomFormElement extends HTMLFormElement {
87
87
  }
88
88
  }
89
89
  const btn = document.activeElement;
90
+ // FIXME https://github.com/whatwg/html/issues/3195 use e.submitter polyfill
91
+ // https://github.com/whatwg/xhr/issues/262 it's a mess
90
92
  if (btn && btn.type == "submit" && btn.name && btn.value) {
91
93
  query[btn.name] = btn.value;
92
94
  }