@pacem/pacem 1.0.0-bessel → 1.0.0-binet
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/dist/browser/pacem-2d.js +149 -2
- package/dist/browser/pacem-2d.js.map +1 -1
- package/dist/browser/pacem-2d.min.js +1 -1
- package/dist/browser/pacem-3d.js +646 -2
- package/dist/browser/pacem-3d.js.map +1 -1
- package/dist/browser/pacem-3d.min.js +1 -1
- package/dist/browser/pacem-charts.js +21 -1
- package/dist/browser/pacem-charts.js.map +1 -1
- package/dist/browser/pacem-charts.min.js +1 -1
- package/dist/browser/pacem-cms.js +118 -3
- package/dist/browser/pacem-cms.js.map +1 -1
- package/dist/browser/pacem-cms.min.js +1 -1
- package/dist/browser/pacem-core.js +870 -9
- package/dist/browser/pacem-core.js.map +1 -1
- package/dist/browser/pacem-core.min.js +2 -2
- package/dist/browser/pacem-foundation.js +296 -1
- package/dist/browser/pacem-foundation.js.map +1 -1
- package/dist/browser/pacem-foundation.min.js +1 -1
- package/dist/browser/pacem-fx.js +18 -1
- package/dist/browser/pacem-fx.js.map +1 -1
- package/dist/browser/pacem-fx.min.js +1 -1
- package/dist/browser/pacem-logging.js +15 -1
- package/dist/browser/pacem-logging.js.map +1 -1
- package/dist/browser/pacem-logging.min.js +1 -1
- package/dist/browser/pacem-maps.js +97 -1
- package/dist/browser/pacem-maps.js.map +1 -1
- package/dist/browser/pacem-maps.min.js +1 -1
- package/dist/browser/pacem-media.js +14 -1
- package/dist/browser/pacem-media.js.map +1 -1
- package/dist/browser/pacem-media.min.js +1 -1
- package/dist/browser/pacem-networking.js +22 -1
- package/dist/browser/pacem-networking.js.map +1 -1
- package/dist/browser/pacem-networking.min.js +1 -1
- package/dist/browser/pacem-numerical.js +360 -1
- package/dist/browser/pacem-numerical.js.map +1 -1
- package/dist/browser/pacem-numerical.min.js +1 -1
- package/dist/browser/pacem-plus.js +195 -4
- package/dist/browser/pacem-plus.js.map +1 -1
- package/dist/browser/pacem-plus.min.js +1 -1
- package/dist/browser/pacem-scaffolding.js +420 -38
- package/dist/browser/pacem-scaffolding.js.map +1 -1
- package/dist/browser/pacem-scaffolding.min.js +2 -2
- package/dist/browser/pacem-ui.js +143 -19
- package/dist/browser/pacem-ui.js.map +1 -1
- package/dist/browser/pacem-ui.min.js +2 -2
- package/dist/bundle/pacem.min.mjs +147 -147
- package/dist/bundle/pacem.mjs +2905 -1417
- package/dist/bundle/pacem.mjs.map +3 -3
- package/dist/docs/pacem-2d.json +11549 -0
- package/dist/docs/pacem-3d.json +29096 -0
- package/dist/docs/pacem-charts.json +4244 -0
- package/dist/docs/pacem-cms.json +9325 -0
- package/dist/docs/pacem-core.json +40109 -0
- package/dist/docs/pacem-foundation.json +8941 -0
- package/dist/docs/pacem-fx.json +3121 -0
- package/dist/docs/pacem-logging.json +941 -0
- package/dist/docs/pacem-maps.json +17387 -0
- package/dist/docs/pacem-media.json +1203 -0
- package/dist/docs/pacem-networking.json +1798 -0
- package/dist/docs/pacem-numerical.json +13706 -0
- package/dist/docs/pacem-plus.json +8468 -0
- package/dist/docs/pacem-scaffolding.json +34788 -0
- package/dist/docs/pacem-ui.json +18628 -0
- package/dist/typings/index.d.ts +4109 -31
- package/dist/vscode.html-custom.json +1303 -741
- package/package.json +4 -2
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @pacem/pacem v1.0.0-
|
|
2
|
+
* @pacem/pacem v1.0.0-binet (https://js.pacem.it)
|
|
3
3
|
* Pacem (https://pacem.it)
|
|
4
4
|
* Licensed under Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
(function (pacemFoundation, pacemCore, pacemUi, pacemMaps) {
|
|
7
7
|
'use strict';
|
|
8
8
|
|
|
9
|
+
/** Event type name (`'change'`) dispatched as a {@link FieldChangeEvent}. */
|
|
9
10
|
const FieldChangeEventName = 'change';
|
|
11
|
+
/** Dispatched by a scaffolding field (see `PacemBaseElement.changeHandler` in `types-components.ts`) whenever its `value` actually changes as a result of user interaction; bubbles so an ancestor {@link PacemFormElement}/`PacemFormFieldElement` can react to it. */
|
|
10
12
|
class FieldChangeEvent extends pacemCore.CustomTypedEvent {
|
|
11
13
|
constructor(args) {
|
|
12
14
|
super(FieldChangeEventName, args, { bubbles: true, cancelable: false });
|
|
@@ -14,6 +16,7 @@
|
|
|
14
16
|
}
|
|
15
17
|
//}
|
|
16
18
|
|
|
19
|
+
/** The primitive kinds an {@link ApiParameter} (or {@link DataField}) can be translated to, used to choose the appropriate auto-generated form field editor. */
|
|
17
20
|
var ApiParameterType;
|
|
18
21
|
(function (ApiParameterType) {
|
|
19
22
|
ApiParameterType["String"] = "string";
|
|
@@ -23,7 +26,14 @@
|
|
|
23
26
|
ApiParameterType["Binary"] = "binary";
|
|
24
27
|
ApiParameterType["Object"] = "object";
|
|
25
28
|
})(ApiParameterType || (ApiParameterType = {}));
|
|
29
|
+
/** Shared base for the OpenAPI/Swagger parsers: implements the common fetch-then-parse {@link ApiParser.load} flow, leaving the actual schema-to-{@link ApiManifest} translation to derived classes' `parse` implementation. */
|
|
26
30
|
class ApiParserBase {
|
|
31
|
+
/**
|
|
32
|
+
* Fetches the API description document from `url` and parses it into an {@link ApiManifest}.
|
|
33
|
+
* @param url Url the API description (OpenAPI/Swagger document) is fetched from.
|
|
34
|
+
* @param headers Optional request headers (e.g. for authentication) sent along with the fetch.
|
|
35
|
+
* @returns The parsed manifest, or `null` if the response could not be retrieved/parsed as JSON.
|
|
36
|
+
*/
|
|
27
37
|
async load(url, headers) {
|
|
28
38
|
let resp = await fetch(url, {
|
|
29
39
|
mode: 'cors', credentials: 'omit', headers: headers
|
|
@@ -38,6 +48,12 @@
|
|
|
38
48
|
}
|
|
39
49
|
}
|
|
40
50
|
const $refPattern = /^#\/(definitions|components\/schemas)\/(.+)$/;
|
|
51
|
+
/**
|
|
52
|
+
* Resolves a `$ref` pointer (e.g. `#/definitions/Foo` or `#/components/schemas/Foo`) against an {@link ApiManifest}'s `definitions` map.
|
|
53
|
+
* @param manifest Manifest whose `definitions` are searched.
|
|
54
|
+
* @param $ref The `$ref` pointer to resolve.
|
|
55
|
+
* @returns The referenced definition's name and schema, or `null` if `$ref` doesn't match the expected pattern.
|
|
56
|
+
*/
|
|
41
57
|
function getOpenApiDefinition(manifest, $ref) {
|
|
42
58
|
var rec = $refPattern.exec($ref);
|
|
43
59
|
if (rec && rec.length > 2) {
|
|
@@ -49,6 +65,7 @@
|
|
|
49
65
|
|
|
50
66
|
//namespace Pacem.Scaffolding.OpenApi {
|
|
51
67
|
const ApiMethod = pacemCore.Net.HttpMethod;
|
|
68
|
+
/** Parses a Swagger (OpenAPI 2.0) document into a format-agnostic {@link ApiManifest}, translating its `paths`/`definitions` into endpoints, resolved schema definitions and parameter types used to auto-generate form fields. */
|
|
52
69
|
class SwaggerParser extends ApiParserBase {
|
|
53
70
|
_findDefinitionName(definitionHashTag) {
|
|
54
71
|
var pattern = /#\/definitions\/(.+)/;
|
|
@@ -57,6 +74,12 @@
|
|
|
57
74
|
return definitionHashTag;
|
|
58
75
|
return arr[1];
|
|
59
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* Parses a Swagger (OpenAPI 2.0) document into an {@link ApiManifest}.
|
|
79
|
+
* @param content The Swagger document, either as a parsed object or as a JSON string.
|
|
80
|
+
* @param url Base url of the API, used to derive `baseUrl` when the document doesn't specify `host`/`schemes`.
|
|
81
|
+
* @returns The parsed manifest, with endpoints and resolved schema definitions.
|
|
82
|
+
*/
|
|
60
83
|
parse(content, url) {
|
|
61
84
|
let j = content;
|
|
62
85
|
if (typeof j === 'string') {
|
|
@@ -176,7 +199,14 @@
|
|
|
176
199
|
}
|
|
177
200
|
}
|
|
178
201
|
|
|
202
|
+
/** Parses an OpenAPI 3.x document into a format-agnostic {@link ApiManifest}, translating its `paths`/`components.schemas` into endpoints, resolved schema definitions and parameter types used to auto-generate form fields. */
|
|
179
203
|
class OpenApi3Parser extends ApiParserBase {
|
|
204
|
+
/**
|
|
205
|
+
* Parses an OpenAPI 3.x document into an {@link ApiManifest}.
|
|
206
|
+
* @param content The OpenAPI 3.x document, either as a parsed object or as a JSON string.
|
|
207
|
+
* @param url Base url of the API, used as the manifest's `baseUrl`.
|
|
208
|
+
* @returns The parsed manifest, with endpoints and resolved schema definitions.
|
|
209
|
+
*/
|
|
180
210
|
parse(content, url) {
|
|
181
211
|
let j = content;
|
|
182
212
|
if (typeof j === 'string') {
|
|
@@ -289,12 +319,19 @@
|
|
|
289
319
|
}
|
|
290
320
|
|
|
291
321
|
//namespace Pacem.Scaffolding.OpenApi {
|
|
322
|
+
/** Format-detecting facade parser: inspects an API description document and delegates to {@link OpenApi3Parser} or {@link SwaggerParser} accordingly, producing a unified {@link ApiManifest} used to auto-generate form fields regardless of the source spec version. */
|
|
292
323
|
class OpenApiParser extends ApiParserBase {
|
|
293
324
|
constructor(_openApi3 = new OpenApi3Parser(), _swagger = new SwaggerParser()) {
|
|
294
325
|
super();
|
|
295
326
|
this._openApi3 = _openApi3;
|
|
296
327
|
this._swagger = _swagger;
|
|
297
328
|
}
|
|
329
|
+
/**
|
|
330
|
+
* Parses `content` as either an OpenAPI 3.x or a Swagger (OpenAPI 2.0) document, dispatching on the presence of an `openapi` property.
|
|
331
|
+
* @param content The API description, either as a parsed object or as a JSON string.
|
|
332
|
+
* @param url Base url of the API, forwarded to the delegate parser to resolve/derive the manifest's `baseUrl`.
|
|
333
|
+
* @returns The parsed manifest.
|
|
334
|
+
*/
|
|
298
335
|
parse(content, url) {
|
|
299
336
|
let j = content;
|
|
300
337
|
if (typeof j === 'string') {
|
|
@@ -330,6 +367,7 @@
|
|
|
330
367
|
validator: (validatorType, validatorTypeIndex, prop, dictionary) => dictionary['validator_' + validatorType + '_' + prop] ?? dictionary['validator_' + validatorType + validatorTypeIndex + '_' + prop],
|
|
331
368
|
commandTooltip: (commandName, dictionary) => dictionary['command_tooltip_' + commandName]
|
|
332
369
|
};
|
|
370
|
+
/** Namespace-like static helper for localizing form {@link TypeMetadata} (labels, watermarks, descriptions, validator error messages, command tooltips) against a translation dictionary. */
|
|
333
371
|
class Forms {
|
|
334
372
|
/**
|
|
335
373
|
* Localizes the metadata of a form **in place** using a translation dictionary.
|
|
@@ -404,20 +442,37 @@
|
|
|
404
442
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
405
443
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
406
444
|
};
|
|
445
|
+
/** Event type name (`'submit'`) dispatched as a {@link FormSubmitEvent}. */
|
|
407
446
|
const FormSubmitEventName = 'submit';
|
|
447
|
+
/** Event type name (`'reset'`) dispatched as a {@link FormResetEvent}. */
|
|
408
448
|
const FormResetEventName = 'reset';
|
|
449
|
+
/**
|
|
450
|
+
* Dispatched by {@link PacemFormElement} right before a submission is actually sent to the server, once all
|
|
451
|
+
* fields have validated successfully. Cancelable: calling `preventDefault()` (or handling the event and
|
|
452
|
+
* returning `false`) aborts the submission before any request is made - useful to inject/transform
|
|
453
|
+
* {@link FormSubmitEventArgs#parameters} or veto the submit outright.
|
|
454
|
+
*/
|
|
409
455
|
class FormSubmitEvent extends pacemCore.CustomTypedEvent {
|
|
410
456
|
constructor(args) {
|
|
411
457
|
super(FormSubmitEventName, args, { bubbles: true, cancelable: true });
|
|
412
458
|
}
|
|
413
459
|
}
|
|
460
|
+
/** Dispatched by {@link PacemFormElement} when the form is about to be reset (programmatically or via its generated reset button). Cancelable: calling `preventDefault()` aborts the reset, leaving fields as they were. */
|
|
414
461
|
class FormResetEvent extends Event {
|
|
415
462
|
constructor() {
|
|
416
463
|
super(FormResetEventName, { bubbles: true, cancelable: true });
|
|
417
464
|
}
|
|
418
465
|
}
|
|
466
|
+
/** Event types re-dispatched/handled on behalf of a {@link PacemFormElement} by its {@link FormEventEmitter}: upload `download` events, field {@link FieldChangeEventName} changes, and item `command` events (see {@link Components.CommandEvent}). */
|
|
419
467
|
const EMITTABLE_EVENT_TYPES = ['download' /* < dedicated, for the upload custom element */, FieldChangeEventName /* expose */, pacemCore.CommandEventName];
|
|
468
|
+
/** Sentinel value used to reject a submission's promise when it was canceled via {@link FormSubmitEvent#preventDefault}, as opposed to a genuine fetch failure. */
|
|
420
469
|
const SUBMIT_CANCELLATION_TOKEN = false;
|
|
470
|
+
/**
|
|
471
|
+
* Listens on a {@link PacemEventTarget} (typically a {@link PacemFormElement}) for the events listed in
|
|
472
|
+
* {@link EMITTABLE_EVENT_TYPES} and pipes each through the target's `handle` method, additionally
|
|
473
|
+
* re-dispatching `command` events as a synthesized `'item' + commandName`-named `CustomEvent` (e.g.
|
|
474
|
+
* `itemdelete`, `itemselect`) so listeners can subscribe to the specific command they care about.
|
|
475
|
+
*/
|
|
421
476
|
class FormEventEmitter {
|
|
422
477
|
constructor(_element) {
|
|
423
478
|
this._element = _element;
|
|
@@ -431,13 +486,16 @@
|
|
|
431
486
|
}
|
|
432
487
|
};
|
|
433
488
|
}
|
|
489
|
+
/** Starts listening for {@link EMITTABLE_EVENT_TYPES} on the target element. */
|
|
434
490
|
start() {
|
|
435
491
|
EMITTABLE_EVENT_TYPES.forEach(t => this._element.addEventListener(t, this._itemEmitHandler, false));
|
|
436
492
|
}
|
|
493
|
+
/** Stops listening for {@link EMITTABLE_EVENT_TYPES} on the target element. */
|
|
437
494
|
stop() {
|
|
438
495
|
EMITTABLE_EVENT_TYPES.forEach(t => this._element.removeEventListener(t, this._itemEmitHandler, false));
|
|
439
496
|
}
|
|
440
497
|
}
|
|
498
|
+
/** Base class for elements that need a reference to their closest ancestor {@link PacemFormElement} (form fields, validators): resolves and exposes it as {@link form} on activation. */
|
|
441
499
|
class PacemFormRelevantElement extends pacemCore.Components.PacemElement {
|
|
442
500
|
viewActivatedCallback() {
|
|
443
501
|
super.viewActivatedCallback();
|
|
@@ -447,9 +505,18 @@
|
|
|
447
505
|
__decorate$J([
|
|
448
506
|
pacemCore.Watch({ converter: pacemCore.PropertyConverters.Element })
|
|
449
507
|
], PacemFormRelevantElement.prototype, "form", void 0);
|
|
508
|
+
/**
|
|
509
|
+
* `<p-form>`: the scaffolding package's central form element. Aggregates the validity/dirty state of its
|
|
510
|
+
* registered fields ({@link registerField}) and validators ({@link registerValidator}), of any nested
|
|
511
|
+
* sub-forms ({@link registerSubForm} - e.g. from a {@link Pacem.Components.Scaffolding.PacemChildFormElement}
|
|
512
|
+
* in `childform.ts`), drives submission ({@link submit}) and reset ({@link reset}), and - when `autogenerate`
|
|
513
|
+
* is `true` and `metadata` is provided - builds its own field markup from a {@link TypeMetadata}/
|
|
514
|
+
* {@link PropertyMetadata} description instead of requiring hand-authored markup.
|
|
515
|
+
*/
|
|
450
516
|
let PacemFormElement = class PacemFormElement extends PacemFormRelevantElement {
|
|
451
517
|
constructor() {
|
|
452
518
|
super('form');
|
|
519
|
+
/** Gets or sets the HTTP method used by the auto-generated fetcher. Defaults to `POST`. */
|
|
453
520
|
this.method = pacemCore.Net.HttpMethod.Post;
|
|
454
521
|
this._emitter = null;
|
|
455
522
|
this._buttons = { submit: undefined, reset: undefined };
|
|
@@ -608,6 +675,7 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
608
675
|
return this._buttons;
|
|
609
676
|
}
|
|
610
677
|
#fetching;
|
|
678
|
+
/** @readonly Gets whether a submission is currently in flight; also reflected as the `pacem-fetching` CSS class. */
|
|
611
679
|
get fetching() {
|
|
612
680
|
return this.#fetching;
|
|
613
681
|
}
|
|
@@ -789,6 +857,11 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
789
857
|
}
|
|
790
858
|
return Promise.resolve(false);
|
|
791
859
|
}
|
|
860
|
+
/**
|
|
861
|
+
* Validates a single named field, or - when `name` is omitted - every field of this form and its
|
|
862
|
+
* sub-forms, running each field's registered validators and updating their `valid`/`invalid` state.
|
|
863
|
+
* @param name Optional name of a single field to validate; validates the whole form (recursively) when omitted.
|
|
864
|
+
*/
|
|
792
865
|
// @Concurrent()
|
|
793
866
|
validate(name) {
|
|
794
867
|
if (!pacemCore.Utils.isNullOrEmpty(name)) {
|
|
@@ -887,6 +960,11 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
887
960
|
this.valid = valid;
|
|
888
961
|
}
|
|
889
962
|
;
|
|
963
|
+
/**
|
|
964
|
+
* Registers a nested {@link PacemFormElement} (e.g. rendered by a `PacemChildFormElement`, see
|
|
965
|
+
* `childform.ts`) so its fields' validity/dirtyness roll up into this form's own {@link valid}/{@link dirty}.
|
|
966
|
+
* @param form Sub-form to enroll
|
|
967
|
+
*/
|
|
890
968
|
registerSubForm(form) {
|
|
891
969
|
let arr = this._subForms;
|
|
892
970
|
if (arr.indexOf(form) == -1) {
|
|
@@ -896,6 +974,10 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
896
974
|
this._checkDirtyness();
|
|
897
975
|
}
|
|
898
976
|
}
|
|
977
|
+
/**
|
|
978
|
+
* Removes a previously-registered nested form; its fields no longer influence this form's {@link valid}/{@link dirty}.
|
|
979
|
+
* @param form Sub-form to remove
|
|
980
|
+
*/
|
|
899
981
|
unregisterSubForm(form) {
|
|
900
982
|
let arr = this._subForms, ndx = arr.indexOf(form);
|
|
901
983
|
if (ndx >= 0) {
|
|
@@ -905,6 +987,11 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
905
987
|
this._checkDirtyness();
|
|
906
988
|
}
|
|
907
989
|
}
|
|
990
|
+
/**
|
|
991
|
+
* Registers a field's {@link PacemModel} under `name`, so it is included in submission ({@link FormSubmitEventArgs#fields}), validation, dirty/valid roll-up and reset. Typically called by the field itself (see `PacemModelElement._registerFieldConditionally` in `types-components.ts`) rather than directly.
|
|
992
|
+
* @param name Field name to register under
|
|
993
|
+
* @param model Field implementing {@link PacemModel}
|
|
994
|
+
*/
|
|
908
995
|
registerField(name, model) {
|
|
909
996
|
var container = this._fields;
|
|
910
997
|
if (container[name] != model) {
|
|
@@ -918,6 +1005,11 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
918
1005
|
this._checkDirtyness();
|
|
919
1006
|
}
|
|
920
1007
|
}
|
|
1008
|
+
/**
|
|
1009
|
+
* Removes a previously-registered field.
|
|
1010
|
+
* @param name Field name to remove
|
|
1011
|
+
* @param check Whether to re-check the form's overall validity/dirtyness afterwards (default `true`)
|
|
1012
|
+
*/
|
|
921
1013
|
unregisterField(name, check = true) {
|
|
922
1014
|
var container = this._fields, current = container[name];
|
|
923
1015
|
if (current instanceof HTMLElement) {
|
|
@@ -929,6 +1021,11 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
929
1021
|
this._checkDirtyness();
|
|
930
1022
|
}
|
|
931
1023
|
}
|
|
1024
|
+
/**
|
|
1025
|
+
* Registers a {@link Validator} (typically a {@link PacemBaseValidatorElement}) against the named field, so it participates in that field's validation. Typically called by the validator itself rather than directly.
|
|
1026
|
+
* @param name Name of the field being validated
|
|
1027
|
+
* @param validator Validator to enroll
|
|
1028
|
+
*/
|
|
932
1029
|
registerValidator(name, validator) {
|
|
933
1030
|
var container = this._validators[name] = this._validators[name] || [], index = container.indexOf(validator);
|
|
934
1031
|
if (index == -1) {
|
|
@@ -941,6 +1038,11 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
941
1038
|
this._checkFieldValidity(name);
|
|
942
1039
|
}
|
|
943
1040
|
}
|
|
1041
|
+
/**
|
|
1042
|
+
* Removes a previously-registered validator from the named field.
|
|
1043
|
+
* @param name Name of the field the validator was registered against
|
|
1044
|
+
* @param validator Validator to remove
|
|
1045
|
+
*/
|
|
944
1046
|
unregisterValidator(name, validator) {
|
|
945
1047
|
this._unregisterValidator(name, validator, true);
|
|
946
1048
|
}
|
|
@@ -1024,7 +1126,17 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
1024
1126
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1025
1127
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1026
1128
|
};
|
|
1129
|
+
/** Attached-property key used to stash a field's pristine value on the element itself (see {@link PacemModelElement.originalValue}). */
|
|
1027
1130
|
const ORIGINAL_VALUE_FIELD = 'pacem:model:original-value';
|
|
1131
|
+
/**
|
|
1132
|
+
* Base class for any element that behaves as a bindable, form-aware model value: it registers itself by
|
|
1133
|
+
* `name` with the ancestor {@link PacemFormElement} (found via {@link PacemFormRelevantElement}), tracks
|
|
1134
|
+
* `dirty`/`valid` state (reflected as `pacem-dirty`/`pacem-invalid` CSS classes), and remembers the value it
|
|
1135
|
+
* had when activated/set-pristine so {@link reset} can restore it.
|
|
1136
|
+
*
|
|
1137
|
+
* Concrete input/selection fields don't extend this directly - see {@link PacemBaseElement}, the abstract
|
|
1138
|
+
* subclass that adds readonly/required/focus/keyboard handling on top of it.
|
|
1139
|
+
*/
|
|
1028
1140
|
class PacemModelElement extends PacemFormRelevantElement {
|
|
1029
1141
|
viewActivatedCallback() {
|
|
1030
1142
|
super.viewActivatedCallback();
|
|
@@ -1090,22 +1202,26 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
1090
1202
|
form.unregisterField(name);
|
|
1091
1203
|
super.disconnectedCallback();
|
|
1092
1204
|
}
|
|
1205
|
+
/** @readonly The `value` this element had the last time it was activated or explicitly marked pristine (via {@link setPristine}); what {@link reset} restores. */
|
|
1093
1206
|
get originalValue() {
|
|
1094
1207
|
return pacemCore.CustomElementUtils.getAttachedPropertyValue(this, ORIGINAL_VALUE_FIELD);
|
|
1095
1208
|
}
|
|
1096
1209
|
_setAsOriginalValue(v) {
|
|
1097
1210
|
pacemCore.CustomElementUtils.setAttachedPropertyValue(this, ORIGINAL_VALUE_FIELD, v);
|
|
1098
1211
|
}
|
|
1212
|
+
/** Restores {@link value} to {@link originalValue} and clears {@link dirty}. */
|
|
1099
1213
|
reset() {
|
|
1100
1214
|
this.value = this.originalValue;
|
|
1101
1215
|
// then
|
|
1102
1216
|
this.dirty = false;
|
|
1103
1217
|
}
|
|
1218
|
+
/** Marks the current `value` as the new baseline for {@link reset}/{@link originalValue} and clears {@link dirty}. */
|
|
1104
1219
|
setPristine() {
|
|
1105
1220
|
this._setAsOriginalValue(this.value);
|
|
1106
1221
|
//
|
|
1107
1222
|
this.dirty = false;
|
|
1108
1223
|
}
|
|
1224
|
+
/** Marks this field as `dirty`. */
|
|
1109
1225
|
setDirty() {
|
|
1110
1226
|
this.dirty = true;
|
|
1111
1227
|
}
|
|
@@ -1135,6 +1251,16 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
1135
1251
|
__decorate$I([
|
|
1136
1252
|
pacemCore.Watch({ converter: pacemCore.PropertyConverters.String })
|
|
1137
1253
|
], PacemModelElement.prototype, "name", void 0);
|
|
1254
|
+
/**
|
|
1255
|
+
* Base class for editable form fields: it adds `required`/`autofocus`/`readonly`/`placeholder` state, focus
|
|
1256
|
+
* and keyboard handling (Esc to revert, Enter submit prevention), and the plumbing that wires the
|
|
1257
|
+
* `focus`/`blur`/`change`/`keydown`/`keyup` handlers onto whichever native {@link inputFields} a derived
|
|
1258
|
+
* class exposes.
|
|
1259
|
+
*
|
|
1260
|
+
* Not extended directly by concrete fields either - see {@link PacemBaseInputElement} (in `input.ts`) for
|
|
1261
|
+
* `<input>`/`<textarea>`-backed fields, and {@link PacemDataSourceElement} for datasource-driven ones
|
|
1262
|
+
* (lists, selects, radio groups, ...).
|
|
1263
|
+
*/
|
|
1138
1264
|
class PacemBaseElement extends PacemModelElement {
|
|
1139
1265
|
constructor() {
|
|
1140
1266
|
super(...arguments);
|
|
@@ -1205,6 +1331,7 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
1205
1331
|
compareValuePropertyValues(old, val) {
|
|
1206
1332
|
return pacemCore.DefaultComparer(old, val);
|
|
1207
1333
|
}
|
|
1334
|
+
/** @overridable Whether pressing Enter within this field should be prevented from submitting an ancestor form. Defaults to `false`. */
|
|
1208
1335
|
get preventKeyboardSubmit() {
|
|
1209
1336
|
return false;
|
|
1210
1337
|
}
|
|
@@ -1338,12 +1465,18 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
1338
1465
|
__decorate$I([
|
|
1339
1466
|
pacemCore.Watch({ converter: pacemCore.PropertyConverters.String })
|
|
1340
1467
|
], PacemBaseElement.prototype, "placeholder", void 0);
|
|
1468
|
+
/**
|
|
1469
|
+
* Scaffolding-specific counterpart of `@pacem/pacem-ui`'s `PacemItemElement`: a base class for elements that
|
|
1470
|
+
* register themselves against an ancestor {@link PacemItemsContainerBaseElement} (found via
|
|
1471
|
+
* {@link findContainer}) on activation, and unregister on disconnect. Extended by {@link PacemDataItemElement}.
|
|
1472
|
+
*/
|
|
1341
1473
|
class PacemItemElement extends pacemCore.Components.PacemElement {
|
|
1342
1474
|
#container;
|
|
1343
|
-
/** @overridable */
|
|
1475
|
+
/** @overridable Locates the ancestor items-container this item registers against. Defaults to the nearest {@link PacemItemsContainerBaseElement}. */
|
|
1344
1476
|
findContainer() {
|
|
1345
1477
|
return pacemCore.CustomElementUtils.findAncestor(this, n => n instanceof PacemItemsContainerBaseElement);
|
|
1346
1478
|
}
|
|
1479
|
+
/** @readonly Gets the items-container this item is currently registered with, if any. */
|
|
1347
1480
|
get container() {
|
|
1348
1481
|
return this.#container;
|
|
1349
1482
|
}
|
|
@@ -1361,6 +1494,12 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
1361
1494
|
super.disconnectedCallback();
|
|
1362
1495
|
}
|
|
1363
1496
|
}
|
|
1497
|
+
/**
|
|
1498
|
+
* Base class for form fields that also act as a registry of {@link PacemItemElement} children (e.g. a
|
|
1499
|
+
* datasource-backed selection field whose options are declared, not just databound). Combines
|
|
1500
|
+
* {@link PacemBaseElement}'s field behavior with `ItemsContainer<TItem>`'s registration API.
|
|
1501
|
+
* See {@link PacemDataSourceElement} for the concrete specialization holding {@link PacemDataItemElement}s.
|
|
1502
|
+
*/
|
|
1364
1503
|
class PacemItemsContainerBaseElement extends PacemBaseElement {
|
|
1365
1504
|
/**
|
|
1366
1505
|
* Registers a new item among the items.
|
|
@@ -1395,6 +1534,7 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
1395
1534
|
__decorate$I([
|
|
1396
1535
|
pacemCore.Watch( /* can only be databound or assigned at runtime */)
|
|
1397
1536
|
], PacemItemsContainerBaseElement.prototype, "items", void 0);
|
|
1537
|
+
/** A single, declaratively-authored option (`<p-data-item>`) of a {@link PacemDataSourceElement}, as an alternative to a databound `datasource` array. */
|
|
1398
1538
|
let PacemDataItemElement = class PacemDataItemElement extends PacemItemElement {
|
|
1399
1539
|
};
|
|
1400
1540
|
__decorate$I([
|
|
@@ -1429,6 +1569,13 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
1429
1569
|
PacemDataItemElement = __decorate$I([
|
|
1430
1570
|
pacemCore.CustomElement({ tagName: pacemCore.P + '-data-item' })
|
|
1431
1571
|
], PacemDataItemElement);
|
|
1572
|
+
/**
|
|
1573
|
+
* Base class for datasource-driven selection fields (lists, dropdowns, radio/checkbox groups, autocomplete,
|
|
1574
|
+
* ...): adapts a raw `datasource` (an array of arbitrary entities, or declared {@link PacemDataItemElement}
|
|
1575
|
+
* children registered via {@link PacemItemsContainerBaseElement}) into a normalized {@link DataSource}, and
|
|
1576
|
+
* provides the value/view-value mapping and selection-matching logic (single or, when `multipleChoice` is
|
|
1577
|
+
* `true`, multi-select) that concrete subclasses build their UI on top of.
|
|
1578
|
+
*/
|
|
1432
1579
|
class PacemDataSourceElement extends PacemItemsContainerBaseElement {
|
|
1433
1580
|
constructor(multipleChoice = false) {
|
|
1434
1581
|
super();
|
|
@@ -1459,9 +1606,11 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
1459
1606
|
}
|
|
1460
1607
|
return flag;
|
|
1461
1608
|
}
|
|
1609
|
+
/** @overridable Maps a raw `datasource` array into its {@link DataSource} representation via {@link mapEntityToItem}. */
|
|
1462
1610
|
buildAdaptedDatasource(ds = this.datasource) {
|
|
1463
1611
|
return ds && ds.map(i => this.mapEntityToItem(i));
|
|
1464
1612
|
}
|
|
1613
|
+
/** Recomputes {@link adaptedDatasource} and, if the current `value` no longer matches any item, calls {@link handleDatasourceMismatch}. Debounced. */
|
|
1465
1614
|
databind(datasource = this.buildAdaptedDatasource(this.datasource)) {
|
|
1466
1615
|
if (pacemCore.Utils.isNull(datasource) && pacemCore.Utils.isNull(this.adaptedDatasource))
|
|
1467
1616
|
return;
|
|
@@ -1470,6 +1619,7 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
1470
1619
|
if (pacemCore.Utils.isNullOrEmpty(ds.filter(i => this.isDataSourceItemSelected(i))))
|
|
1471
1620
|
this.handleDatasourceMismatch(ds);
|
|
1472
1621
|
}
|
|
1622
|
+
/** @overridable Called by {@link databind} when the current `value` matches none of the adapted `datasource` items. Defaults to clearing `value`. */
|
|
1473
1623
|
handleDatasourceMismatch(datasource) {
|
|
1474
1624
|
this.value = undefined;
|
|
1475
1625
|
}
|
|
@@ -1519,6 +1669,7 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
1519
1669
|
return false;
|
|
1520
1670
|
}
|
|
1521
1671
|
}
|
|
1672
|
+
/** @overridable Extracts the selectable `value` out of a raw datasource entity (via {@link valueProperty}, or `entity.value` for a {@link PacemDataItemElement}). */
|
|
1522
1673
|
mapEntityToValue(entity) {
|
|
1523
1674
|
if (entity == null) {
|
|
1524
1675
|
throw 'entity cannot be null';
|
|
@@ -1534,6 +1685,7 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
1534
1685
|
}
|
|
1535
1686
|
return value;
|
|
1536
1687
|
}
|
|
1688
|
+
/** @overridable Extracts the display text out of a raw datasource entity (via {@link textProperty}, or `entity.label`/`entity.value` for a {@link PacemDataItemElement}). */
|
|
1537
1689
|
mapEntityToViewValue(entity) {
|
|
1538
1690
|
if (entity == null)
|
|
1539
1691
|
throw 'entity cannot be null';
|
|
@@ -1548,6 +1700,7 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
1548
1700
|
}
|
|
1549
1701
|
return viewValue;
|
|
1550
1702
|
}
|
|
1703
|
+
/** @overridable Adapts a raw datasource entity into its normalized {@link DataSourceItem} shape, using {@link mapEntityToValue}, {@link mapEntityToViewValue} and {@link disabledProperty}. */
|
|
1551
1704
|
mapEntityToItem(entity) {
|
|
1552
1705
|
if (entity == null) {
|
|
1553
1706
|
throw 'entity cannot be null';
|
|
@@ -1631,7 +1784,9 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
1631
1784
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1632
1785
|
};
|
|
1633
1786
|
//namespace Pacem.Components.Scaffolding {
|
|
1787
|
+
/** Markup fragment for a `pacem-char-count` companion element, meant to be spliced into a `@CustomElement` template so a text field can display its own character counter. */
|
|
1634
1788
|
const CHAR_COUNTER_CHILD = `<${pacemCore.P}-char-count hide="{{ :host.readonly || !(:host.minlength > 0 || :host.maxlength > 0) }}" minlength="{{ :host.minlength }}" maxlength="{{ :host.maxlength }}" string="{{ :host.value }}"></${pacemCore.P}-char-count>`;
|
|
1789
|
+
/** Displays how many characters {@link string} contains, relative to {@link minlength}/{@link maxlength}, flagging validity via CSS class. */
|
|
1635
1790
|
let PacemCharCountElement = class PacemCharCountElement extends pacemCore.Components.PacemElement {
|
|
1636
1791
|
_isValid(v) {
|
|
1637
1792
|
const l = this._length(v);
|
|
@@ -1680,6 +1835,7 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
1680
1835
|
super('contenteditablechange', { html: html });
|
|
1681
1836
|
}
|
|
1682
1837
|
}
|
|
1838
|
+
/** Base class for {@link PacemContenteditableElement} toolbar/command items, registered as {@link PacemItemElement} children of the editor. */
|
|
1683
1839
|
class PacemContenteditableCommandElement extends PacemItemElement {
|
|
1684
1840
|
constructor() {
|
|
1685
1841
|
super(...arguments);
|
|
@@ -1736,6 +1892,7 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
1736
1892
|
function isElement(node) {
|
|
1737
1893
|
return node?.nodeType == Node.ELEMENT_NODE;
|
|
1738
1894
|
}
|
|
1895
|
+
/** Rich-text (`contenteditable`) field, hosting {@link PacemContenteditableCommandElement} toolbar commands and tracking an undo/redo {@link history}. */
|
|
1739
1896
|
let PacemContenteditableElement = class PacemContenteditableElement extends PacemItemsContainerBaseElement {
|
|
1740
1897
|
constructor() {
|
|
1741
1898
|
super('rich text editor');
|
|
@@ -1816,6 +1973,7 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
1816
1973
|
//this._workspace = document.createElement('div');
|
|
1817
1974
|
}
|
|
1818
1975
|
#history;
|
|
1976
|
+
/** @readonly Gets the undo/redo history service tracking this editor's HTML content. */
|
|
1819
1977
|
get history() {
|
|
1820
1978
|
return this.#history;
|
|
1821
1979
|
}
|
|
@@ -1995,6 +2153,7 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
1995
2153
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1996
2154
|
};
|
|
1997
2155
|
//namespace Pacem.Components.Scaffolding {
|
|
2156
|
+
/** Base class for the toolbar button-shaped contenteditable commands (bold, align, link, wrap, ...), sharing icon/shortcut/tooltip/active-state behavior. */
|
|
1998
2157
|
class PacemContenteditableButtonCommandElement extends PacemContenteditableCommandElement {
|
|
1999
2158
|
cleanUp(_) {
|
|
2000
2159
|
// do nothing
|
|
@@ -2036,6 +2195,7 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
2036
2195
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2037
2196
|
};
|
|
2038
2197
|
//namespace Pacem.Components.Scaffolding {
|
|
2198
|
+
/** Toolbar button undoing or redoing the last change tracked by the contenteditable host's history. */
|
|
2039
2199
|
let PacemContenteditableHistoryCommandElement = class PacemContenteditableHistoryCommandElement extends PacemContenteditableButtonCommandElement {
|
|
2040
2200
|
exec() {
|
|
2041
2201
|
return new Promise((resolve, _) => {
|
|
@@ -2099,6 +2259,7 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
2099
2259
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2100
2260
|
};
|
|
2101
2261
|
//namespace Pacem.Components.Scaffolding {
|
|
2262
|
+
/** Toolbar button creating or removing a hyperlink (`<a>`) around the current selection. */
|
|
2102
2263
|
let PacemContenteditableLinkCommandElement = class PacemContenteditableLinkCommandElement extends PacemContenteditableButtonCommandElement {
|
|
2103
2264
|
isRelevant(range) {
|
|
2104
2265
|
return !pacemCore.Utils.isNull(ContenteditableUtils.findSurroundingNode(range, HTMLAnchorElement));
|
|
@@ -2189,6 +2350,7 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
2189
2350
|
});
|
|
2190
2351
|
});
|
|
2191
2352
|
}
|
|
2353
|
+
/** Toolbar button inserting a (rescalable) picture into the contenteditable host, either by file picker or by pasted/dropped image file. */
|
|
2192
2354
|
let PacemContenteditableImageCommandElement = class PacemContenteditableImageCommandElement extends PacemContenteditableButtonCommandElement {
|
|
2193
2355
|
constructor() {
|
|
2194
2356
|
super(...arguments);
|
|
@@ -2368,6 +2530,7 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
2368
2530
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2369
2531
|
};
|
|
2370
2532
|
//namespace Pacem.Components.Scaffolding {
|
|
2533
|
+
/** Well-known `document.execCommand` commands supported out-of-the-box by {@link PacemContenteditableExecCommandElement}. */
|
|
2371
2534
|
var KnownExecCommand;
|
|
2372
2535
|
(function (KnownExecCommand) {
|
|
2373
2536
|
KnownExecCommand["Bold"] = "bold";
|
|
@@ -2443,6 +2606,7 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
2443
2606
|
return ['none'];
|
|
2444
2607
|
}
|
|
2445
2608
|
}
|
|
2609
|
+
/** Toolbar button applying a native `document.execCommand`-backed formatting command (bold, italic, lists, ...) to the contenteditable host. */
|
|
2446
2610
|
let PacemContenteditableExecCommandElement = class PacemContenteditableExecCommandElement extends PacemContenteditableButtonCommandElement {
|
|
2447
2611
|
_matchRelevance(range, arg) {
|
|
2448
2612
|
const found = (typeof arg === 'object') ?
|
|
@@ -2528,7 +2692,14 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
2528
2692
|
&& element.hasAttribute('role')
|
|
2529
2693
|
&& element.attributes['role'].value === 'presenter';
|
|
2530
2694
|
}
|
|
2695
|
+
/** Watches a contenteditable host for insertion/removal of elements matching a given selector (e.g. inert `[contenteditable=false]` islands), notifying a callback for each match, recursively. */
|
|
2531
2696
|
class ContenteditableDOMObserver {
|
|
2697
|
+
/**
|
|
2698
|
+
* Initializes the observer, immediately scanning the given container and then watching it for further mutations.
|
|
2699
|
+
* @param contentElement The contenteditable container to observe.
|
|
2700
|
+
* @param mutationCallback Invoked for each matching node found, added or removed.
|
|
2701
|
+
* @param selector CSS selector used to filter relevant nodes.
|
|
2702
|
+
*/
|
|
2532
2703
|
constructor(contentElement, mutationCallback, selector = '*[contenteditable=false]') {
|
|
2533
2704
|
this.#callback = mutationCallback;
|
|
2534
2705
|
this.#selector = selector;
|
|
@@ -2564,6 +2735,7 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
2564
2735
|
}
|
|
2565
2736
|
contentElement.querySelectorAll(this.#selector).forEach(el => this.#callback(el, true));
|
|
2566
2737
|
}
|
|
2738
|
+
/** Stops observing and notifies the callback, as a removal, for every currently matching node. */
|
|
2567
2739
|
dispose() {
|
|
2568
2740
|
this._disposeContainer(this.#contentElement);
|
|
2569
2741
|
}
|
|
@@ -2572,7 +2744,9 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
2572
2744
|
#contentElement;
|
|
2573
2745
|
#mutationObserver;
|
|
2574
2746
|
}
|
|
2747
|
+
/** Collection of static DOM/Range helper methods shared by the contenteditable command elements. */
|
|
2575
2748
|
class ContenteditableUtils {
|
|
2749
|
+
/** Builds the default toolbar dashboard (undo/redo, formatting, alignment, link and image commands) as a detached fragment. */
|
|
2576
2750
|
static getDefaultDashboard() {
|
|
2577
2751
|
const frag = new DocumentFragment();
|
|
2578
2752
|
const toolbar0 = document.createElement('div');
|
|
@@ -2637,9 +2811,17 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
2637
2811
|
}
|
|
2638
2812
|
return node;
|
|
2639
2813
|
}
|
|
2814
|
+
/**
|
|
2815
|
+
* Seeks for the nearest surrounding block-level element of a given Selection's range.
|
|
2816
|
+
* @param range
|
|
2817
|
+
*/
|
|
2640
2818
|
static findSurroundingBlockElement(range) {
|
|
2641
2819
|
return this.findSurroundingNode(range, ContenteditableUtils.isBlockElement);
|
|
2642
2820
|
}
|
|
2821
|
+
/**
|
|
2822
|
+
* Retrieves the sibling block-level elements (e.g. paragraphs) touched by a given Selection's range.
|
|
2823
|
+
* @param range
|
|
2824
|
+
*/
|
|
2643
2825
|
static findSurroundingSiblingBlockElements(range) {
|
|
2644
2826
|
let output = [];
|
|
2645
2827
|
if (isRoot(range.startContainer)) {
|
|
@@ -2679,6 +2861,10 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
2679
2861
|
}
|
|
2680
2862
|
return started ? output : (root instanceof Element && !isRoot(root) ? [root] : []);
|
|
2681
2863
|
}
|
|
2864
|
+
/**
|
|
2865
|
+
* Retrieves the top-level (direct children of the contenteditable root) elements spanned by a given Selection's range.
|
|
2866
|
+
* @param range
|
|
2867
|
+
*/
|
|
2682
2868
|
static findContainingRootElements(range) {
|
|
2683
2869
|
const range1 = range.cloneRange(), range2 = range.cloneRange();
|
|
2684
2870
|
range1.collapse(true);
|
|
@@ -2690,9 +2876,18 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
2690
2876
|
}
|
|
2691
2877
|
return retval;
|
|
2692
2878
|
}
|
|
2879
|
+
/**
|
|
2880
|
+
* Checks whether the given node is an `Element` with a block-level (non-`inline*`) computed display.
|
|
2881
|
+
* @param node
|
|
2882
|
+
*/
|
|
2693
2883
|
static isBlockElement(node) {
|
|
2694
2884
|
return node instanceof Element && !getComputedStyle(node).display.startsWith('inline');
|
|
2695
2885
|
}
|
|
2886
|
+
/**
|
|
2887
|
+
* Selects a node (or its contents, when `inside` is `true`) and applies the resulting range to the current document Selection.
|
|
2888
|
+
* @param node
|
|
2889
|
+
* @param inside
|
|
2890
|
+
*/
|
|
2696
2891
|
static select(node, inside = false) {
|
|
2697
2892
|
const range = document.createRange();
|
|
2698
2893
|
if (!inside) {
|
|
@@ -2708,6 +2903,11 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
2708
2903
|
selection.addRange(range);
|
|
2709
2904
|
return range;
|
|
2710
2905
|
}
|
|
2906
|
+
/**
|
|
2907
|
+
* Copies all attributes from one element onto another.
|
|
2908
|
+
* @param to
|
|
2909
|
+
* @param from
|
|
2910
|
+
*/
|
|
2711
2911
|
static copyAttributes(to, from) {
|
|
2712
2912
|
const attrs = from.attributes;
|
|
2713
2913
|
for (let j = 0; j < attrs.length; j++) {
|
|
@@ -2741,6 +2941,7 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
2741
2941
|
function getAlignIcon(align) {
|
|
2742
2942
|
return 'format_align_' + align;
|
|
2743
2943
|
}
|
|
2944
|
+
/** Toolbar button applying a text-alignment (left/center/right/justify) style to the block(s) touched by the current selection. */
|
|
2744
2945
|
let PacemContenteditableAlignCommandElement = class PacemContenteditableAlignCommandElement extends PacemContenteditableButtonCommandElement {
|
|
2745
2946
|
isRelevant(range) {
|
|
2746
2947
|
const els = ContenteditableUtils.findSurroundingSiblingBlockElements(range);
|
|
@@ -2819,6 +3020,7 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
2819
3020
|
}
|
|
2820
3021
|
return { result: false };
|
|
2821
3022
|
}
|
|
3023
|
+
/** Dropdown command inserting an inert (`contenteditable=false`) placeholder token, picked from a suggestable datasource, into the contenteditable host. */
|
|
2822
3024
|
let PacemContenteditablePlaceholderElement = class PacemContenteditablePlaceholderElement extends PacemContenteditableCommandElement {
|
|
2823
3025
|
constructor() {
|
|
2824
3026
|
super(...arguments);
|
|
@@ -2955,6 +3157,7 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
2955
3157
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2956
3158
|
};
|
|
2957
3159
|
//namespace Pacem.Components.Scaffolding {
|
|
3160
|
+
/** Toolbar button wrapping (or, if already applied, unwrapping) the block(s) touched by the current selection with a given tag (e.g. `blockquote`, `h1`). */
|
|
2958
3161
|
let PacemContenteditableWrapCommandElement = class PacemContenteditableWrapCommandElement extends PacemContenteditableButtonCommandElement {
|
|
2959
3162
|
isRelevant(range) {
|
|
2960
3163
|
return !pacemCore.Utils.isNull(ContenteditableUtils.findSurroundingNode(range, this.tagname));
|
|
@@ -3065,6 +3268,7 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
3065
3268
|
}
|
|
3066
3269
|
return header;
|
|
3067
3270
|
}
|
|
3271
|
+
/** Utility 12-month grid picker, used internally by {@link PacemCalendarPickerElement} to pick a month within {@link viewYear}. */
|
|
3068
3272
|
let PacemCalendarMonthPickerElement = class PacemCalendarMonthPickerElement extends pacemCore.Components.PacemElement {
|
|
3069
3273
|
propertyChangedCallback(name, old, val, first) {
|
|
3070
3274
|
super.propertyChangedCallback(name, old, val, first);
|
|
@@ -3113,6 +3317,7 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
3113
3317
|
template: `<div class="${pacemCore.PCSS}-month-picker">${buildMonthGrid()}</div>`
|
|
3114
3318
|
})
|
|
3115
3319
|
], PacemCalendarMonthPickerElement);
|
|
3320
|
+
/** Dispatched by {@link PacemCalendarPickerElement} when its clear button is used to unselect the current date. */
|
|
3116
3321
|
class CalendarDateUnselectEvent extends pacemUi.Components.UI.DateSelectEvent {
|
|
3117
3322
|
constructor() {
|
|
3118
3323
|
super(void 0);
|
|
@@ -3132,6 +3337,7 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
3132
3337
|
const mod = y % 10;
|
|
3133
3338
|
return y - mod;
|
|
3134
3339
|
}
|
|
3340
|
+
/** Utility grid picker of {@link YEARS_IN_RANGE} years, used internally by {@link PacemCalendarPickerElement} to pick a year within the range containing {@link viewYear}. */
|
|
3135
3341
|
let PacemCalendarYearPickerElement = class PacemCalendarYearPickerElement extends pacemCore.Components.PacemElement {
|
|
3136
3342
|
propertyChangedCallback(name, old, val, first) {
|
|
3137
3343
|
super.propertyChangedCallback(name, old, val, first);
|
|
@@ -3187,9 +3393,11 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
3187
3393
|
}
|
|
3188
3394
|
return `<${pacemCore.P}-panel hide="{{ :host.viewmode !== 'calendar' }}" class="calendar-header">${header}</${pacemCore.P}-panel>`;
|
|
3189
3395
|
}
|
|
3396
|
+
/** {@link PacemBaseInputElement}-alike field that pops up a `pacem-calendar` (with month/year zoom levels) to pick a `Date` value. */
|
|
3190
3397
|
let PacemCalendarPickerElement = class PacemCalendarPickerElement extends PacemBaseElement {
|
|
3191
3398
|
constructor() {
|
|
3192
3399
|
super(...arguments);
|
|
3400
|
+
/** Gets or sets which picker is currently shown in the dropdown: the day calendar, the month grid, or the year grid. */
|
|
3193
3401
|
this.viewmode = 'calendar';
|
|
3194
3402
|
this.#locked = false;
|
|
3195
3403
|
this._swipeHandler = (e) => {
|
|
@@ -3522,9 +3730,11 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
3522
3730
|
convert: (attr) => attr === 'true' ? true : (attr === 'false' ? false : attr),
|
|
3523
3731
|
convertBack: (prop) => prop.toString()
|
|
3524
3732
|
};
|
|
3733
|
+
/** {@link PacemBaseElement}-based single checkbox field, mapping its checked state to {@link trueValue}/{@link falseValue}. */
|
|
3525
3734
|
let PacemCheckboxElement = class PacemCheckboxElement extends PacemBaseElement {
|
|
3526
3735
|
constructor() {
|
|
3527
3736
|
super('checkbox');
|
|
3737
|
+
/** Gets or sets the label displayed next to the checkbox (and used as the read-only view value when checked). */
|
|
3528
3738
|
this.caption = '';
|
|
3529
3739
|
this._key = '_' + pacemCore.Utils.uniqueCode();
|
|
3530
3740
|
}
|
|
@@ -3628,6 +3838,7 @@ disabled="{{ (#${uid}.suddenValidation && (!(#${uid}.valid && #${uid}.dirty))) |
|
|
|
3628
3838
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
3629
3839
|
};
|
|
3630
3840
|
//namespace Pacem.Components.Scaffolding {
|
|
3841
|
+
/** Renders {@link PacemDataSourceElement#datasource} as a list of `pacem-checkbox` items, producing an array `value` of the checked items' mapped values. */
|
|
3631
3842
|
let PacemCheckboxListElement = class PacemCheckboxListElement extends PacemDataSourceElement {
|
|
3632
3843
|
acceptValue(val) {
|
|
3633
3844
|
// no need to implement
|
|
@@ -3950,17 +4161,24 @@ on-${pacemCore.PropertyChangeEventName}=":host._selectionChanged($event, ^index,
|
|
|
3950
4161
|
// super('datetimechange', { date: date });
|
|
3951
4162
|
// }
|
|
3952
4163
|
//}
|
|
4164
|
+
/** {@link PacemBaseElement}-based field composing a set of `pacem-select` dropdowns (year/month/day and, depending on {@link precision}, time) into a single `Date` value. */
|
|
3953
4165
|
let PacemDatetimePickerElement = class PacemDatetimePickerElement extends PacemBaseElement {
|
|
3954
4166
|
constructor() {
|
|
3955
4167
|
super();
|
|
4168
|
+
/** Gets or sets the granularity of the picker: date only, or including hours/minutes ('minute') or hours/minutes/seconds ('second'). */
|
|
3956
4169
|
this.precision = 'day';
|
|
3957
4170
|
this._months = [];
|
|
4171
|
+
/** Internal: datasource of selectable days for the current {@link year}/{@link month}. */
|
|
3958
4172
|
this._dates = [];
|
|
3959
4173
|
this._a24 = [];
|
|
3960
4174
|
this._a60 = [];
|
|
4175
|
+
/** Internal: datasource of selectable years, computed from {@link min}/{@link max}. */
|
|
3961
4176
|
this._years = [];
|
|
4177
|
+
/** Internal: the hours select's current value. */
|
|
3962
4178
|
this.hours = '00';
|
|
4179
|
+
/** Internal: the minutes select's current value. */
|
|
3963
4180
|
this.minutes = '00';
|
|
4181
|
+
/** Internal: the seconds select's current value. */
|
|
3964
4182
|
this.seconds = '00';
|
|
3965
4183
|
}
|
|
3966
4184
|
get inputFields() {
|
|
@@ -4240,6 +4458,13 @@ on-${pacemCore.PropertyChangeEventName}=":host._selectionChanged($event, ^index,
|
|
|
4240
4458
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
4241
4459
|
};
|
|
4242
4460
|
// TODO: add warning state
|
|
4461
|
+
/**
|
|
4462
|
+
* Base class for all `p-*-validator` elements: registers/unregisters itself against the ancestor
|
|
4463
|
+
* {@link PacemFormElement} field named by `watch`, and turns the abstract {@link evaluate} logic into the
|
|
4464
|
+
* `Validator` contract's `validate` (short-circuiting to valid when `disabled`). Concrete validators only
|
|
4465
|
+
* need to implement {@link evaluate}; the field's own error UI reads `invalid`/`errorMessage` off the
|
|
4466
|
+
* element (see {@link BASIC_VALIDATOR_TEMPLATE}).
|
|
4467
|
+
*/
|
|
4243
4468
|
class PacemBaseValidatorElement extends PacemFormRelevantElement {
|
|
4244
4469
|
constructor() {
|
|
4245
4470
|
super();
|
|
@@ -4273,6 +4498,7 @@ on-${pacemCore.PropertyChangeEventName}=":host._selectionChanged($event, ^index,
|
|
|
4273
4498
|
}
|
|
4274
4499
|
}
|
|
4275
4500
|
#easer;
|
|
4501
|
+
/** Asks the owning {@link PacemFormElement} to re-validate the watched field on the next animation frame; call after a configuration property (e.g. `min`/`max`/`pattern`) changes so the field re-evaluates against the new rule. */
|
|
4276
4502
|
triggerFormFieldValidation() {
|
|
4277
4503
|
const form = this.form, watch = this.watch;
|
|
4278
4504
|
if (!pacemCore.Utils.isNull(form) && !pacemCore.Utils.isNullOrEmpty(watch)) {
|
|
@@ -4282,6 +4508,7 @@ on-${pacemCore.PropertyChangeEventName}=":host._selectionChanged($event, ^index,
|
|
|
4282
4508
|
});
|
|
4283
4509
|
}
|
|
4284
4510
|
}
|
|
4511
|
+
/** Validates `val` against this validator's rule; always resolves `true` (skips {@link evaluate}) when the validator is `disabled`. */
|
|
4285
4512
|
validate(val) {
|
|
4286
4513
|
if (this.disabled) {
|
|
4287
4514
|
return pacemCore.Utils.fromResult(true);
|
|
@@ -4298,11 +4525,13 @@ on-${pacemCore.PropertyChangeEventName}=":host._selectionChanged($event, ^index,
|
|
|
4298
4525
|
__decorate$s([
|
|
4299
4526
|
pacemCore.Watch({ emit: false, reflectBack: true, converter: pacemCore.PropertyConverters.String })
|
|
4300
4527
|
], PacemBaseValidatorElement.prototype, "watch", void 0);
|
|
4528
|
+
/** Default shadow-DOM template shared by every built-in `p-*-validator`: a `<p-span>` (exposed as the `error-message` part) shown only while `invalid`, displaying `errorMessage`. */
|
|
4301
4529
|
const BASIC_VALIDATOR_TEMPLATE = `<${pacemCore.P}-span part="error-message" hide="{{ !:host.invalid }}" text="{{ :host.errorMessage }}"></${pacemCore.P}-span>`;
|
|
4302
4530
|
// #region TEXTUAL
|
|
4303
4531
|
function isValueEmpty(val) {
|
|
4304
4532
|
return pacemCore.Utils.isNullOrEmpty(val);
|
|
4305
4533
|
}
|
|
4534
|
+
/** Validates that a field's value is not empty (`p-required-validator`). */
|
|
4306
4535
|
let PacemRequiredValidatorElement = class PacemRequiredValidatorElement extends PacemBaseValidatorElement {
|
|
4307
4536
|
evaluate(val) {
|
|
4308
4537
|
let retval = !isValueEmpty(val);
|
|
@@ -4312,6 +4541,7 @@ on-${pacemCore.PropertyChangeEventName}=":host._selectionChanged($event, ^index,
|
|
|
4312
4541
|
PacemRequiredValidatorElement = __decorate$s([
|
|
4313
4542
|
pacemCore.CustomElement({ tagName: pacemCore.P + '-required-validator', template: BASIC_VALIDATOR_TEMPLATE, shadow: pacemCore.Defaults.USE_SHADOW_ROOT })
|
|
4314
4543
|
], PacemRequiredValidatorElement);
|
|
4544
|
+
/** Validates that a field's (non-empty) value matches a regular expression (`p-regex-validator`). */
|
|
4315
4545
|
let PacemRegexValidatorElement = class PacemRegexValidatorElement extends PacemBaseValidatorElement {
|
|
4316
4546
|
propertyChangedCallback(name, old, val, first) {
|
|
4317
4547
|
super.propertyChangedCallback(name, old, val, first);
|
|
@@ -4333,6 +4563,7 @@ on-${pacemCore.PropertyChangeEventName}=":host._selectionChanged($event, ^index,
|
|
|
4333
4563
|
PacemRegexValidatorElement = __decorate$s([
|
|
4334
4564
|
pacemCore.CustomElement({ tagName: pacemCore.P + '-regex-validator', template: BASIC_VALIDATOR_TEMPLATE, shadow: pacemCore.Defaults.USE_SHADOW_ROOT })
|
|
4335
4565
|
], PacemRegexValidatorElement);
|
|
4566
|
+
/** Validates that a field's (non-empty) value's string length falls within `[min, max]` (`p-length-validator`). */
|
|
4336
4567
|
let PacemLengthValidatorElement = class PacemLengthValidatorElement extends PacemBaseValidatorElement {
|
|
4337
4568
|
propertyChangedCallback(name, old, val, first) {
|
|
4338
4569
|
super.propertyChangedCallback(name, old, val, first);
|
|
@@ -4363,6 +4594,7 @@ on-${pacemCore.PropertyChangeEventName}=":host._selectionChanged($event, ^index,
|
|
|
4363
4594
|
], PacemLengthValidatorElement);
|
|
4364
4595
|
// #endregion
|
|
4365
4596
|
// #region NUMERIC/ORDINAL
|
|
4597
|
+
/** Validates that a field's (non-empty) numeric or date value falls within `[min, max]` (`p-range-validator`); dates (parsed via `Utils.parseDate`) are compared by their timestamp. */
|
|
4366
4598
|
let PacemRangeValidatorElement = class PacemRangeValidatorElement extends PacemBaseValidatorElement {
|
|
4367
4599
|
propertyChangedCallback(name, old, val, first) {
|
|
4368
4600
|
super.propertyChangedCallback(name, old, val, first);
|
|
@@ -4402,6 +4634,7 @@ on-${pacemCore.PropertyChangeEventName}=":host._selectionChanged($event, ^index,
|
|
|
4402
4634
|
], PacemRangeValidatorElement);
|
|
4403
4635
|
// #endregion
|
|
4404
4636
|
// #region COMPLEX
|
|
4637
|
+
/** Validates a field's (non-empty) value against another (non-empty) value `to`, using the given comparison `operator` (`p-compare-validator`); dates are compared by their timestamp. */
|
|
4405
4638
|
let PacemCompareValidatorElement = class PacemCompareValidatorElement extends PacemBaseValidatorElement {
|
|
4406
4639
|
propertyChangedCallback(name, old, val, first) {
|
|
4407
4640
|
super.propertyChangedCallback(name, old, val, first);
|
|
@@ -4456,6 +4689,7 @@ on-${pacemCore.PropertyChangeEventName}=":host._selectionChanged($event, ^index,
|
|
|
4456
4689
|
pacemCore.CustomElement({ tagName: pacemCore.P + '-compare-validator', template: BASIC_VALIDATOR_TEMPLATE, shadow: pacemCore.Defaults.USE_SHADOW_ROOT })
|
|
4457
4690
|
], PacemCompareValidatorElement);
|
|
4458
4691
|
// #endregion
|
|
4692
|
+
/** Validates a {@link BinaryValue}/file-name (non-empty) upload against an optional filename `pattern` and/or `maxSize` in bytes (`p-binary-validator`). */
|
|
4459
4693
|
let PacemBinaryValidatorElement = class PacemBinaryValidatorElement extends PacemBaseValidatorElement {
|
|
4460
4694
|
propertyChangedCallback(name, old, val, first) {
|
|
4461
4695
|
super.propertyChangedCallback(name, old, val, first);
|
|
@@ -4489,6 +4723,13 @@ on-${pacemCore.PropertyChangeEventName}=":host._selectionChanged($event, ^index,
|
|
|
4489
4723
|
PacemBinaryValidatorElement = __decorate$s([
|
|
4490
4724
|
pacemCore.CustomElement({ tagName: pacemCore.P + '-binary-validator', template: BASIC_VALIDATOR_TEMPLATE, shadow: pacemCore.Defaults.USE_SHADOW_ROOT })
|
|
4491
4725
|
], PacemBinaryValidatorElement);
|
|
4726
|
+
/**
|
|
4727
|
+
* Validates a field's (non-empty) value by calling a remote `url` (`p-async-validator`), sending it - along
|
|
4728
|
+
* with any extra `parameters` - as a request parameter named after {@link PacemBaseValidatorElement#watch}.
|
|
4729
|
+
* The response is considered valid when it is the literal text `'true'`, or a fetched JSON payload whose API
|
|
4730
|
+
* result (see `Utils.getApiResult`) is truthy; anything else (including a failed fetch) is invalid.
|
|
4731
|
+
* Debounces requests by 1 second and memoizes the last request/result to avoid redundant round-trips.
|
|
4732
|
+
*/
|
|
4492
4733
|
let PacemAsyncValidatorElement = class PacemAsyncValidatorElement extends PacemBaseValidatorElement {
|
|
4493
4734
|
constructor() {
|
|
4494
4735
|
super(...arguments);
|
|
@@ -4608,6 +4849,7 @@ on-${pacemCore.PropertyChangeEventName}=":host._selectionChanged($event, ^index,
|
|
|
4608
4849
|
template: BASIC_VALIDATOR_TEMPLATE + `<${pacemCore.P}-fetch autofetch="false" throttle="true" credentials="{{ :host.fetchCredentials }}" headers="{{ :host.fetchHeaders }}"></${pacemCore.P}-fetch>`, shadow: pacemCore.Defaults.USE_SHADOW_ROOT
|
|
4609
4850
|
})
|
|
4610
4851
|
], PacemAsyncValidatorElement);
|
|
4852
|
+
/** Validates a field's (non-empty) value by deferring entirely to the externally-controlled {@link isValid} flag (`p-custom-validator`), for validation logic that doesn't fit the other built-in validators. */
|
|
4611
4853
|
let PacemCustomValidatorElement = class PacemCustomValidatorElement extends PacemBaseValidatorElement {
|
|
4612
4854
|
propertyChangedCallback(name, old, val, first) {
|
|
4613
4855
|
super.propertyChangedCallback(name, old, val, first);
|
|
@@ -4650,6 +4892,11 @@ on-${pacemCore.PropertyChangeEventName}=":host._selectionChanged($event, ^index,
|
|
|
4650
4892
|
function isValidatorFactory(v) {
|
|
4651
4893
|
return 'attributes' in v && typeof v.attributes === 'function';
|
|
4652
4894
|
}
|
|
4895
|
+
/**
|
|
4896
|
+
* Renders a single editing field (label, input, validators, tooltip) for {@link entity}'s property described by {@link metadata},
|
|
4897
|
+
* dynamically choosing and building up the concrete input element (e.g. `pacem-input-text`, `pacem-select`, `pacem-checkbox`, ...)
|
|
4898
|
+
* based on the metadata's `dataType`/`ui` hints. Used internally by `pacem-form` for autogenerated forms.
|
|
4899
|
+
*/
|
|
4653
4900
|
let PacemFormFieldElement = class PacemFormFieldElement extends PacemFormRelevantElement {
|
|
4654
4901
|
constructor(_md = new pacemUi.Components.UI.MarkdownService()) {
|
|
4655
4902
|
super();
|
|
@@ -4663,12 +4910,15 @@ on-${pacemCore.PropertyChangeEventName}=":host._selectionChanged($event, ^index,
|
|
|
4663
4910
|
};
|
|
4664
4911
|
this._key = '_' + pacemCore.Utils.uniqueCode();
|
|
4665
4912
|
}
|
|
4913
|
+
/** @readonly Gets this field's unique key, used to derive DOM ids for the label/input/fetcher. */
|
|
4666
4914
|
get key() {
|
|
4667
4915
|
return this._key;
|
|
4668
4916
|
}
|
|
4917
|
+
/** @readonly Gets the inner `pacem-fetch` element used to retrieve remotely-sourced datasources for this field. */
|
|
4669
4918
|
get fetcher() {
|
|
4670
4919
|
return this._fetcher;
|
|
4671
4920
|
}
|
|
4921
|
+
/** @readonly Gets the concrete input element built for this field (e.g. `pacem-input-text`, `pacem-select`, ...). */
|
|
4672
4922
|
get field() {
|
|
4673
4923
|
return this._field;
|
|
4674
4924
|
}
|
|
@@ -5697,6 +5947,7 @@ css-class="{{ {'${pacemCore.PCSS}-fetching': ::_fetcher.fetching, '${pacemCore.P
|
|
|
5697
5947
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
5698
5948
|
};
|
|
5699
5949
|
const MIN_LENGTH = 3;
|
|
5950
|
+
/** {@link PacemBaseElement}-based field pairing an address `pacem-suggest` (forward geocoding) with a draggable map marker (reverse geocoding) to pick an {@link Address}. */
|
|
5700
5951
|
let PacemGeolocateElement = class PacemGeolocateElement extends PacemBaseElement {
|
|
5701
5952
|
constructor() {
|
|
5702
5953
|
super(...arguments);
|
|
@@ -5906,6 +6157,10 @@ css-class="{{ {'${pacemCore.PCSS}-fetching': ::_fetcher.fetching, '${pacemCore.P
|
|
|
5906
6157
|
const HIERARCHYITEM_MOVE_CSSCLASS = 'item-move';
|
|
5907
6158
|
const HIERARCHYITEM_MOVE_ICON = 'drag_indicator';
|
|
5908
6159
|
const DEFAULT_PARENTSPROPERTY = 'parents';
|
|
6160
|
+
/**
|
|
6161
|
+
* {@link PacemBaseElement}-based field for editing a DAG-like parent/child hierarchy over {@link datasource}: items are
|
|
6162
|
+
* arranged level-by-level and linked/unlinked via drag-drop, producing an array `value` of `{ [valueProperty]: any, parents: any[] }`.
|
|
6163
|
+
*/
|
|
5909
6164
|
let PacemHierarchyElement = class PacemHierarchyElement extends PacemBaseElement {
|
|
5910
6165
|
getViewValue(value) {
|
|
5911
6166
|
return '';
|
|
@@ -5917,6 +6172,7 @@ css-class="{{ {'${pacemCore.PCSS}-fetching': ::_fetcher.fetching, '${pacemCore.P
|
|
|
5917
6172
|
super();
|
|
5918
6173
|
this.#bindings = new Map();
|
|
5919
6174
|
this.#dropTargets = new Map();
|
|
6175
|
+
/** Gets or sets the caption of the balloon button used to unlink a parent/child relation. */
|
|
5920
6176
|
this.unlinkCaption = 'Delete';
|
|
5921
6177
|
this._binderClickHandler = (evt) => {
|
|
5922
6178
|
const origType = evt.originalEvent.type;
|
|
@@ -6396,16 +6652,30 @@ css-class="{{ {'${pacemCore.PCSS}-fetching': ::_fetcher.fetching, '${pacemCore.P
|
|
|
6396
6652
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6397
6653
|
};
|
|
6398
6654
|
//namespace Pacem.Components.Scaffolding {
|
|
6655
|
+
/** When a {@link PacemBaseInputElement} propagates its native input's value to the `value` property: on every keystroke (`Input`), or only once the field loses focus (`Blur`). */
|
|
6399
6656
|
var ChangePolicy;
|
|
6400
6657
|
(function (ChangePolicy) {
|
|
6401
6658
|
ChangePolicy["Input"] = "input";
|
|
6402
6659
|
ChangePolicy["Blur"] = "blur";
|
|
6403
6660
|
})(ChangePolicy || (ChangePolicy = {}));
|
|
6661
|
+
/** Attached-property key used to mark a native `<input>`/`<textarea>` as already wired up, so re-registration doesn't double-attach listeners (see {@link PacemBaseInputElement#registerInputFields}). */
|
|
6404
6662
|
const INPUT_FIELD_ACTIVATED_PROP = 'pacem:scaffolding:input_field';
|
|
6663
|
+
/**
|
|
6664
|
+
* Base class for fields backed by one or more native `<input>`/`<textarea>` elements ({@link inputField}):
|
|
6665
|
+
* wires `input`/`focus` listeners onto them, applies `changePolicy`/`debounce` to decide when the native
|
|
6666
|
+
* value is read back into {@link PacemModelElement#value} (via {@link getValue}), and optionally
|
|
6667
|
+
* auto-selects the field's content on focus.
|
|
6668
|
+
*
|
|
6669
|
+
* Extended by {@link PacemOrdinalInputElement} (numeric/date-like inputs) and
|
|
6670
|
+
* {@link PacemTextualInputElement} (text-like inputs); further specialized by the concrete `input-*.ts`
|
|
6671
|
+
* elements in this package (e.g. text, number, date, password, ...).
|
|
6672
|
+
*/
|
|
6405
6673
|
class PacemBaseInputElement extends PacemBaseElement {
|
|
6406
6674
|
constructor() {
|
|
6407
6675
|
super(...arguments);
|
|
6676
|
+
/** Gets or sets how long to wait, after the native input changes, before propagating the value: `false` (default, propagate on the next animation frame), `true` (propagate via `requestAnimationFrame`), or a number of milliseconds to debounce by. */
|
|
6408
6677
|
this.debounce = false;
|
|
6678
|
+
/** Gets or sets when the native input's value gets read back into {@link PacemModelElement#value}: on every `input` event, or only on `blur`. Defaults to {@link ChangePolicy.Input}. */
|
|
6409
6679
|
this.changePolicy = ChangePolicy.Input;
|
|
6410
6680
|
this._focusHandler = (evt) => {
|
|
6411
6681
|
if (!this.autoselect) {
|
|
@@ -6436,6 +6706,7 @@ css-class="{{ {'${pacemCore.PCSS}-fetching': ::_fetcher.fetching, '${pacemCore.P
|
|
|
6436
6706
|
this.inputField.value = pacemCore.Utils.isNullOrEmpty(val) ? '' : val;
|
|
6437
6707
|
}
|
|
6438
6708
|
}
|
|
6709
|
+
/** @readonly Gets the first (usually only) native input element among {@link PacemBaseElement#inputFields}. */
|
|
6439
6710
|
get inputField() {
|
|
6440
6711
|
return this.inputFields[0];
|
|
6441
6712
|
}
|
|
@@ -6540,6 +6811,11 @@ css-class="{{ {'${pacemCore.PCSS}-fetching': ::_fetcher.fetching, '${pacemCore.P
|
|
|
6540
6811
|
__decorate$o([
|
|
6541
6812
|
pacemCore.Watch({ emit: false, converter: pacemCore.PropertyConverters.Boolean })
|
|
6542
6813
|
], PacemBaseInputElement.prototype, "autoselect", void 0);
|
|
6814
|
+
/**
|
|
6815
|
+
* Base class for numeric/ordinal native inputs (e.g. `number`, `range`, `date`-like fields): adds
|
|
6816
|
+
* `min`/`max`/`step`, mirrored onto the native input's own attributes, and parses its `value` attribute as
|
|
6817
|
+
* a float.
|
|
6818
|
+
*/
|
|
6543
6819
|
class PacemOrdinalInputElement extends PacemBaseInputElement {
|
|
6544
6820
|
convertValueAttributeToProperty(attr) {
|
|
6545
6821
|
return parseFloat(attr);
|
|
@@ -6572,6 +6848,11 @@ css-class="{{ {'${pacemCore.PCSS}-fetching': ::_fetcher.fetching, '${pacemCore.P
|
|
|
6572
6848
|
}
|
|
6573
6849
|
})
|
|
6574
6850
|
], PacemOrdinalInputElement.prototype, "step", void 0);
|
|
6851
|
+
/**
|
|
6852
|
+
* Base class for text-like native inputs (e.g. `text`, `password`, `textarea` fields): adds
|
|
6853
|
+
* `pattern`/`minlength`/`maxlength`, mirrored onto the native input's own attributes, and treats an empty
|
|
6854
|
+
* string `value` as `null`.
|
|
6855
|
+
*/
|
|
6575
6856
|
class PacemTextualInputElement extends PacemBaseInputElement {
|
|
6576
6857
|
convertValueAttributeToProperty(attr) {
|
|
6577
6858
|
return attr;
|
|
@@ -6610,10 +6891,13 @@ css-class="{{ {'${pacemCore.PCSS}-fetching': ::_fetcher.fetching, '${pacemCore.P
|
|
|
6610
6891
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6611
6892
|
};
|
|
6612
6893
|
//namespace Pacem.Components.Scaffolding {
|
|
6894
|
+
/** {@link PacemBaseInputElement} rendering one single-character `<input>` per position (e.g. OTP/verification codes), joining them into a single string `value`. */
|
|
6613
6895
|
let PacemCharsInputElement = class PacemCharsInputElement extends PacemBaseInputElement {
|
|
6614
6896
|
constructor() {
|
|
6615
6897
|
super();
|
|
6898
|
+
/** Gets or sets how many single-character inputs to render. */
|
|
6616
6899
|
this.charCount = 6;
|
|
6900
|
+
/** Gets or sets how the entered characters are transformed/displayed: as-is, forced to a case, or masked like a password. */
|
|
6617
6901
|
this.inputTransform = 'none';
|
|
6618
6902
|
this._itemCreateHandler = (e) => {
|
|
6619
6903
|
const { dom, index } = e.detail;
|
|
@@ -6792,6 +7076,7 @@ css-class="{{ {'${pacemCore.PCSS}-fetching': ::_fetcher.fetching, '${pacemCore.P
|
|
|
6792
7076
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6793
7077
|
};
|
|
6794
7078
|
//namespace Pacem.Components.Scaffolding {
|
|
7079
|
+
/** {@link PacemBaseElement}-based field pairing a native color picker with an alpha (0-100) slider, producing a hex/rgba color string `value`. */
|
|
6795
7080
|
let PacemColorInputElement = class PacemColorInputElement extends PacemBaseElement {
|
|
6796
7081
|
acceptValue(val) {
|
|
6797
7082
|
const parsed = this._parseValue(val);
|
|
@@ -6836,7 +7121,7 @@ css-class="{{ {'${pacemCore.PCSS}-fetching': ::_fetcher.fetching, '${pacemCore.P
|
|
|
6836
7121
|
return value;
|
|
6837
7122
|
}
|
|
6838
7123
|
get inputFields() {
|
|
6839
|
-
return [this._tint, this._alpha];
|
|
7124
|
+
return [this._tint, this._alpha].filter(e => !pacemCore.Utils.isNull(e));
|
|
6840
7125
|
}
|
|
6841
7126
|
};
|
|
6842
7127
|
__decorate$m([
|
|
@@ -6869,21 +7154,27 @@ css-class="{{ {'${pacemCore.PCSS}-fetching': ::_fetcher.fetching, '${pacemCore.P
|
|
|
6869
7154
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6870
7155
|
};
|
|
6871
7156
|
//namespace Pacem.Components.Scaffolding {
|
|
7157
|
+
/** {@link PacemTextualInputElement} for an `<input type="email">`, whose read-only view renders as a `mailto:` link. */
|
|
6872
7158
|
let PacemEmailInputElement = class PacemEmailInputElement extends PacemTextualInputElement {
|
|
6873
7159
|
toggleReadonlyView(readonly) {
|
|
6874
|
-
this.
|
|
6875
|
-
|
|
7160
|
+
const input = this._input, anchor = this._anchor;
|
|
7161
|
+
if (!pacemCore.Utils.isNull(input))
|
|
7162
|
+
input.hidden = readonly;
|
|
7163
|
+
if (!pacemCore.Utils.isNull(anchor))
|
|
7164
|
+
anchor.hidden = !readonly;
|
|
6876
7165
|
}
|
|
6877
7166
|
get inputFields() {
|
|
6878
|
-
return
|
|
7167
|
+
return pacemCore.Utils.isNull(this._input)
|
|
7168
|
+
? []
|
|
7169
|
+
: [this._input];
|
|
6879
7170
|
}
|
|
6880
7171
|
};
|
|
6881
7172
|
__decorate$l([
|
|
6882
7173
|
pacemCore.ViewChild('input[type=email]')
|
|
6883
|
-
], PacemEmailInputElement.prototype, "
|
|
7174
|
+
], PacemEmailInputElement.prototype, "_input", void 0);
|
|
6884
7175
|
__decorate$l([
|
|
6885
7176
|
pacemCore.ViewChild(pacemCore.P + '-a')
|
|
6886
|
-
], PacemEmailInputElement.prototype, "
|
|
7177
|
+
], PacemEmailInputElement.prototype, "_anchor", void 0);
|
|
6887
7178
|
PacemEmailInputElement = __decorate$l([
|
|
6888
7179
|
pacemCore.CustomElement({
|
|
6889
7180
|
tagName: pacemCore.P + '-input-email',
|
|
@@ -6897,18 +7188,22 @@ css-class="{{ {'${pacemCore.PCSS}-fetching': ::_fetcher.fetching, '${pacemCore.P
|
|
|
6897
7188
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6898
7189
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6899
7190
|
};
|
|
7191
|
+
/** Name of the {@link FileUploadEvent} dispatched by {@link PacemUploadElement} while/after a chunked upload progresses. */
|
|
6900
7192
|
const FileUploadEventName = 'fileupload';
|
|
7193
|
+
/** Name of the {@link FileChangeEvent} dispatched by {@link PacemUploadElement} whenever the selected file(s)/directory change. */
|
|
6901
7194
|
const FileChangeEventName = 'filechange';
|
|
6902
7195
|
class StoragePickEvent extends pacemCore.CustomTypedEvent {
|
|
6903
7196
|
constructor(file) {
|
|
6904
7197
|
super('pick', file);
|
|
6905
7198
|
}
|
|
6906
7199
|
}
|
|
7200
|
+
/** Dispatched by {@link PacemUploadElement} to report chunked-upload progress/completion. */
|
|
6907
7201
|
class FileUploadEvent extends pacemCore.CustomTypedEvent {
|
|
6908
7202
|
constructor(file) {
|
|
6909
7203
|
super(FileUploadEventName, file);
|
|
6910
7204
|
}
|
|
6911
7205
|
}
|
|
7206
|
+
/** Dispatched by {@link PacemUploadElement} whenever the user picks (or clears) file(s)/a directory. */
|
|
6912
7207
|
class FileChangeEvent extends pacemCore.CustomTypedEvent {
|
|
6913
7208
|
constructor(file) {
|
|
6914
7209
|
super(FileChangeEventName, file);
|
|
@@ -6939,20 +7234,30 @@ css-class="{{ {'${pacemCore.PCSS}-fetching': ::_fetcher.fetching, '${pacemCore.P
|
|
|
6939
7234
|
return stats;
|
|
6940
7235
|
}
|
|
6941
7236
|
/**
|
|
6942
|
-
* PacemUploader Component
|
|
7237
|
+
* PacemUploader Component: {@link PacemBaseElement}-based field to pick and (optionally chunk-)upload file(s)/a directory to {@link url},
|
|
7238
|
+
* or defer to the File System Access API pickers depending on {@link selectMode}.
|
|
6943
7239
|
*/
|
|
6944
7240
|
let PacemUploadElement = class PacemUploadElement extends PacemBaseElement {
|
|
6945
7241
|
constructor(_tweener = new pacemCore.Animations.TweenService()) {
|
|
6946
7242
|
super();
|
|
6947
7243
|
this._tweener = _tweener;
|
|
7244
|
+
/** Gets or sets the caption of the "undo" button, shown while an upload with {@link url} set is in progress. */
|
|
6948
7245
|
this.undoCaption = 'undo';
|
|
7246
|
+
/** Gets or sets the caption of the "retry" button, shown after a {@link failed} upload. */
|
|
6949
7247
|
this.retryCaption = 'retry';
|
|
7248
|
+
/** Gets or sets the caption of the "clear" button. */
|
|
6950
7249
|
this.clearCaption = 'clear';
|
|
7250
|
+
/** @readonly Gets whether an upload is currently in progress. */
|
|
6951
7251
|
this.uploading = false;
|
|
7252
|
+
/** @readonly Gets the total size (in bytes) of the file(s) currently being uploaded. */
|
|
6952
7253
|
this.size = 0;
|
|
7254
|
+
/** @readonly Gets the current upload progress, from 0 to 100. */
|
|
6953
7255
|
this.percentage = .0;
|
|
7256
|
+
/** @readonly Gets whether the current upload has completed. */
|
|
6954
7257
|
this.complete = false;
|
|
7258
|
+
/** @readonly Gets whether the current upload chunk request failed (enabling the retry button). */
|
|
6955
7259
|
this.failed = false;
|
|
7260
|
+
/** @readonly Gets whether the selected file failed {@link pattern}/{@link maxSize} validation. */
|
|
6956
7261
|
this.invalidFile = false;
|
|
6957
7262
|
this._fields = {
|
|
6958
7263
|
'parallelism': 3,
|
|
@@ -7012,11 +7317,14 @@ css-class="{{ {'${pacemCore.PCSS}-fetching': ::_fetcher.fetching, '${pacemCore.P
|
|
|
7012
7317
|
}
|
|
7013
7318
|
return 'filter_none';
|
|
7014
7319
|
}
|
|
7320
|
+
/** @readonly Gets the raw blob currently being (or last) uploaded. */
|
|
7015
7321
|
get blob() {
|
|
7016
7322
|
return this._fields.blob;
|
|
7017
7323
|
}
|
|
7018
7324
|
get inputFields() {
|
|
7019
|
-
return
|
|
7325
|
+
return pacemCore.Utils.isNull(this._fileupload)
|
|
7326
|
+
? []
|
|
7327
|
+
: [this._fileupload];
|
|
7020
7328
|
}
|
|
7021
7329
|
getViewValue(val) {
|
|
7022
7330
|
const value = this._localValue || val;
|
|
@@ -7587,18 +7895,21 @@ css-class="{{ {'${pacemCore.PCSS}-fetching': ::_fetcher.fetching, '${pacemCore.P
|
|
|
7587
7895
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7588
7896
|
};
|
|
7589
7897
|
//namespace Pacem.Components.Scaffolding {
|
|
7898
|
+
/** {@link PacemTextualInputElement} wrapping an `<input type="hidden">`, for values that must round-trip without a visible UI. */
|
|
7590
7899
|
let PacemHiddenInputElement = class PacemHiddenInputElement extends PacemTextualInputElement {
|
|
7591
7900
|
constructor() {
|
|
7592
7901
|
super();
|
|
7593
7902
|
}
|
|
7594
7903
|
toggleReadonlyView(readonly) { }
|
|
7595
7904
|
get inputFields() {
|
|
7596
|
-
return
|
|
7905
|
+
return pacemCore.Utils.isNull(this._input)
|
|
7906
|
+
? []
|
|
7907
|
+
: [this._input];
|
|
7597
7908
|
}
|
|
7598
7909
|
};
|
|
7599
7910
|
__decorate$j([
|
|
7600
7911
|
pacemCore.ViewChild('input[type=hidden]')
|
|
7601
|
-
], PacemHiddenInputElement.prototype, "
|
|
7912
|
+
], PacemHiddenInputElement.prototype, "_input", void 0);
|
|
7602
7913
|
PacemHiddenInputElement = __decorate$j([
|
|
7603
7914
|
pacemCore.CustomElement({ tagName: pacemCore.P + '-input-hidden', template: '<input type="hidden" />', shadow: pacemCore.Defaults.USE_SHADOW_ROOT })
|
|
7604
7915
|
], PacemHiddenInputElement);
|
|
@@ -7611,6 +7922,7 @@ css-class="{{ {'${pacemCore.PCSS}-fetching': ::_fetcher.fetching, '${pacemCore.P
|
|
|
7611
7922
|
};
|
|
7612
7923
|
//namespace Pacem.Components.Scaffolding {
|
|
7613
7924
|
const getUserMediaFunctions = pacemCore.Utils.getUserMediaFunctions();
|
|
7925
|
+
/** The current stage of {@link PacemSnapshotElement}'s capture workflow: idle/upload-or-camera choice, live webcam preview, or reviewing the captured image before confirming. */
|
|
7614
7926
|
var SnapshotStep;
|
|
7615
7927
|
(function (SnapshotStep) {
|
|
7616
7928
|
SnapshotStep["Start"] = "start";
|
|
@@ -7622,14 +7934,17 @@ css-class="{{ {'${pacemCore.PCSS}-fetching': ::_fetcher.fetching, '${pacemCore.P
|
|
|
7622
7934
|
super('confirmsnapshot', { buffer });
|
|
7623
7935
|
}
|
|
7624
7936
|
}
|
|
7937
|
+
/** A `<p-snapshot>` field: a {@link PacemBaseElement} image-capture control that lets the user upload a file or, when a webcam is available, take a live snapshot (with an optional 3s timer); its `value` is the resulting data-URL string. */
|
|
7625
7938
|
let PacemSnapshotElement = class PacemSnapshotElement extends PacemBaseElement {
|
|
7626
7939
|
constructor() {
|
|
7627
7940
|
super(...arguments);
|
|
7628
7941
|
this._resizeHandler = (evt) => {
|
|
7629
7942
|
this._renderValue();
|
|
7630
7943
|
};
|
|
7944
|
+
/** Gets or sets the current step of the capture workflow. Defaults to {@link SnapshotStep.Start}. */
|
|
7631
7945
|
this.step = SnapshotStep.Start;
|
|
7632
7946
|
/*const*/ this._canUseWebcam = getUserMediaFunctions.length > 0;
|
|
7947
|
+
/** Seconds left before the timed shutter fires; `0` outside of a timed countdown. */
|
|
7633
7948
|
this._countdown = 0;
|
|
7634
7949
|
this._webcamInitialized = false;
|
|
7635
7950
|
this._grabberChangeHandler = (e) => {
|
|
@@ -7933,18 +8248,26 @@ css-class="{{ {
|
|
|
7933
8248
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7934
8249
|
};
|
|
7935
8250
|
//namespace Pacem.Components.Scaffolding {
|
|
8251
|
+
/** A single image entry (full-size and thumbnail sources) offered as a pick candidate by {@link PacemEditImageElement}. */
|
|
7936
8252
|
class Picture {
|
|
7937
8253
|
}
|
|
8254
|
+
/** Name of the {@link ImageFetchRequestEvent} dispatched by {@link PacemEditImageElement}/{@link PacemImageInputElement} to request a page of pictures. */
|
|
7938
8255
|
const ImageFetchRequestEventName = 'imagefetchrequest';
|
|
8256
|
+
/** Dispatched to request a page of {@link Picture}s (e.g. on scroll, or when the search hint changes); handlers are expected to respond by setting `imageSet`. */
|
|
7939
8257
|
class ImageFetchRequestEvent extends pacemCore.CustomTypedEvent {
|
|
7940
8258
|
constructor(args) {
|
|
7941
8259
|
super(ImageFetchRequestEventName, args, { bubbles: true /*, scoped: false */ });
|
|
7942
8260
|
}
|
|
7943
8261
|
}
|
|
8262
|
+
/**
|
|
8263
|
+
* Picture-picker panel: lets the user search/browse a fetched {@link imageSet}, upload a new full-size/thumbnail pair, or take a
|
|
8264
|
+
* snapshot, resolving `value` to the chosen picture's source. Hosted inside a dialog by {@link PacemImageInputElement}.
|
|
8265
|
+
*/
|
|
7944
8266
|
let PacemEditImageElement = class PacemEditImageElement extends pacemCore.Components.PacemElement {
|
|
7945
8267
|
constructor() {
|
|
7946
8268
|
super(...arguments);
|
|
7947
8269
|
this._index = 0;
|
|
8270
|
+
/** Gets or sets the search hint typed by the user, triggering a fresh {@link ImageFetchRequestEvent} when it changes. */
|
|
7948
8271
|
this.hint = '';
|
|
7949
8272
|
}
|
|
7950
8273
|
_uploaderPropertyChangedCallback(evt) {
|
|
@@ -8115,6 +8438,10 @@ css-class="{{ {
|
|
|
8115
8438
|
</${pacemCore.P}-panel>`
|
|
8116
8439
|
})
|
|
8117
8440
|
], PacemEditImageElement);
|
|
8441
|
+
/**
|
|
8442
|
+
* {@link PacemBaseElement}-based field showing an image preview with edit/clear buttons; editing opens a dialog hosting a
|
|
8443
|
+
* {@link PacemEditImageElement} to pick/upload/snapshot a new picture, while `value` also accepts a directly-typed URL.
|
|
8444
|
+
*/
|
|
8118
8445
|
let PacemImageInputElement = class PacemImageInputElement extends PacemBaseElement {
|
|
8119
8446
|
constructor() {
|
|
8120
8447
|
super(...arguments);
|
|
@@ -8318,13 +8645,16 @@ css-class="{{ {
|
|
|
8318
8645
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
8319
8646
|
};
|
|
8320
8647
|
//namespace Pacem.Components.Scaffolding {
|
|
8648
|
+
/** {@link PacemOrdinalInputElement} for an `<input type="number">`, formatting its read-only view value via {@link format}. */
|
|
8321
8649
|
let PacemNumberInputElement = class PacemNumberInputElement extends PacemOrdinalInputElement {
|
|
8322
8650
|
toggleReadonlyView(readonly) {
|
|
8323
8651
|
this._span.hidden = !readonly;
|
|
8324
8652
|
this._input.hidden = readonly;
|
|
8325
8653
|
}
|
|
8326
8654
|
get inputFields() {
|
|
8327
|
-
return
|
|
8655
|
+
return pacemCore.Utils.isNull(this._input)
|
|
8656
|
+
? []
|
|
8657
|
+
: [this._input];
|
|
8328
8658
|
}
|
|
8329
8659
|
getViewValue(val) {
|
|
8330
8660
|
return this.value != null ? this._format(this.value) : undefined;
|
|
@@ -8374,6 +8704,7 @@ css-class="{{ {
|
|
|
8374
8704
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
8375
8705
|
};
|
|
8376
8706
|
//namespace Pacem.Components.Scaffolding {
|
|
8707
|
+
/** {@link PacemTextualInputElement} for an `<input type="password">`, with a toggle to reveal/hide the entered text and a masked read-only view. */
|
|
8377
8708
|
let PacemPasswordInputElement = class PacemPasswordInputElement extends PacemTextualInputElement {
|
|
8378
8709
|
constructor() {
|
|
8379
8710
|
super();
|
|
@@ -8385,7 +8716,9 @@ css-class="{{ {
|
|
|
8385
8716
|
};
|
|
8386
8717
|
}
|
|
8387
8718
|
get inputFields() {
|
|
8388
|
-
return
|
|
8719
|
+
return pacemCore.Utils.isNull(this._input)
|
|
8720
|
+
? []
|
|
8721
|
+
: [this._input];
|
|
8389
8722
|
}
|
|
8390
8723
|
viewActivatedCallback() {
|
|
8391
8724
|
super.viewActivatedCallback();
|
|
@@ -8401,6 +8734,7 @@ css-class="{{ {
|
|
|
8401
8734
|
this._toggler.removeEventListener('mousedown', this._togglerMousedownHandler, false);
|
|
8402
8735
|
}
|
|
8403
8736
|
}
|
|
8737
|
+
/** Toggles the native input between `password` (masked) and `text` (revealed) type. */
|
|
8404
8738
|
toggleVisibility() {
|
|
8405
8739
|
const current = this._input.type;
|
|
8406
8740
|
this._input.type = current === 'password' ? 'text' : 'password';
|
|
@@ -8442,12 +8776,15 @@ ${CHAR_COUNTER_CHILD}<span class="${pacemCore.PCSS}-readonly"><${pacemCore.P}-te
|
|
|
8442
8776
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
8443
8777
|
};
|
|
8444
8778
|
//namespace Pacem.Components.Scaffolding {
|
|
8779
|
+
/** A `<p-input-search>` field: a {@link PacemTextualInputElement} backed by a native `<input type="search">`. */
|
|
8445
8780
|
let PacemSearchInputElement = class PacemSearchInputElement extends PacemTextualInputElement {
|
|
8446
8781
|
constructor() {
|
|
8447
8782
|
super();
|
|
8448
8783
|
}
|
|
8449
8784
|
get inputFields() {
|
|
8450
|
-
return
|
|
8785
|
+
return pacemCore.Utils.isNull(this._input)
|
|
8786
|
+
? []
|
|
8787
|
+
: [this._input];
|
|
8451
8788
|
}
|
|
8452
8789
|
toggleReadonlyView(readonly) {
|
|
8453
8790
|
// no readonly view provided.
|
|
@@ -8455,7 +8792,7 @@ ${CHAR_COUNTER_CHILD}<span class="${pacemCore.PCSS}-readonly"><${pacemCore.P}-te
|
|
|
8455
8792
|
};
|
|
8456
8793
|
__decorate$e([
|
|
8457
8794
|
pacemCore.ViewChild('input[type=search]')
|
|
8458
|
-
], PacemSearchInputElement.prototype, "
|
|
8795
|
+
], PacemSearchInputElement.prototype, "_input", void 0);
|
|
8459
8796
|
PacemSearchInputElement = __decorate$e([
|
|
8460
8797
|
pacemCore.CustomElement({ tagName: pacemCore.P + '-input-search', template: '<input type="search" class="' + pacemCore.PCSS + '-input" />', shadow: pacemCore.Defaults.USE_SHADOW_ROOT })
|
|
8461
8798
|
], PacemSearchInputElement);
|
|
@@ -8467,24 +8804,30 @@ ${CHAR_COUNTER_CHILD}<span class="${pacemCore.PCSS}-readonly"><${pacemCore.P}-te
|
|
|
8467
8804
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
8468
8805
|
};
|
|
8469
8806
|
//namespace Pacem.Components.Scaffolding {
|
|
8807
|
+
/** A `<p-input-tel>` field: a {@link PacemTextualInputElement} backed by a native `<input type="tel">`, whose readonly view renders as a clickable `tel:` link. */
|
|
8470
8808
|
let PacemTelInputElement = class PacemTelInputElement extends PacemTextualInputElement {
|
|
8471
8809
|
constructor() {
|
|
8472
8810
|
super();
|
|
8473
8811
|
}
|
|
8474
8812
|
toggleReadonlyView(readonly) {
|
|
8475
|
-
this.
|
|
8476
|
-
|
|
8813
|
+
const input = this._input, anchor = this._anchor;
|
|
8814
|
+
if (!pacemCore.Utils.isNull(input))
|
|
8815
|
+
input.hidden = readonly;
|
|
8816
|
+
if (!pacemCore.Utils.isNull(anchor))
|
|
8817
|
+
anchor.hidden = !readonly;
|
|
8477
8818
|
}
|
|
8478
8819
|
get inputFields() {
|
|
8479
|
-
return
|
|
8820
|
+
return pacemCore.Utils.isNull(this._input)
|
|
8821
|
+
? []
|
|
8822
|
+
: [this._input];
|
|
8480
8823
|
}
|
|
8481
8824
|
};
|
|
8482
8825
|
__decorate$d([
|
|
8483
8826
|
pacemCore.ViewChild('input[type=tel]')
|
|
8484
|
-
], PacemTelInputElement.prototype, "
|
|
8827
|
+
], PacemTelInputElement.prototype, "_input", void 0);
|
|
8485
8828
|
__decorate$d([
|
|
8486
8829
|
pacemCore.ViewChild(pacemCore.P + '-a')
|
|
8487
|
-
], PacemTelInputElement.prototype, "
|
|
8830
|
+
], PacemTelInputElement.prototype, "_anchor", void 0);
|
|
8488
8831
|
PacemTelInputElement = __decorate$d([
|
|
8489
8832
|
pacemCore.CustomElement({ tagName: pacemCore.P + '-input-tel', template: `<input type="tel" class="${pacemCore.PCSS}-input" /><${pacemCore.P}-a class="${pacemCore.PCSS}-readonly" disabled="{{ $pacem.isNullOrEmpty(:host.value) }}" href="{{ 'tel:'+ :host.value }}"><${pacemCore.P}-text text="{{ :host.viewValue }}"></${pacemCore.P}-text></${pacemCore.P}-a>`, shadow: pacemCore.Defaults.USE_SHADOW_ROOT })
|
|
8490
8833
|
], PacemTelInputElement);
|
|
@@ -8496,6 +8839,7 @@ ${CHAR_COUNTER_CHILD}<span class="${pacemCore.PCSS}-readonly"><${pacemCore.P}-te
|
|
|
8496
8839
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
8497
8840
|
};
|
|
8498
8841
|
//namespace Pacem.Components.Scaffolding {
|
|
8842
|
+
/** A `<p-input-text>` field: a {@link PacemTextualInputElement} backed by a native `<input type="text">`, with an optional character counter. */
|
|
8499
8843
|
let PacemTextInputElement = class PacemTextInputElement extends PacemTextualInputElement {
|
|
8500
8844
|
constructor() {
|
|
8501
8845
|
super();
|
|
@@ -8505,7 +8849,9 @@ ${CHAR_COUNTER_CHILD}<span class="${pacemCore.PCSS}-readonly"><${pacemCore.P}-te
|
|
|
8505
8849
|
this._input.hidden = readonly;
|
|
8506
8850
|
}
|
|
8507
8851
|
get inputFields() {
|
|
8508
|
-
return
|
|
8852
|
+
return pacemCore.Utils.isNull(this._input)
|
|
8853
|
+
? []
|
|
8854
|
+
: [this._input];
|
|
8509
8855
|
}
|
|
8510
8856
|
};
|
|
8511
8857
|
__decorate$c([
|
|
@@ -8529,24 +8875,30 @@ ${CHAR_COUNTER_CHILD}<span class="${pacemCore.PCSS}-readonly"><${pacemCore.P}-te
|
|
|
8529
8875
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
8530
8876
|
};
|
|
8531
8877
|
//namespace Pacem.Components.Scaffolding {
|
|
8878
|
+
/** A `<p-input-url>` field: a {@link PacemTextualInputElement} backed by a native `<input type="url">`, whose readonly view renders as a clickable link opening in a new tab. */
|
|
8532
8879
|
let PacemUrlInputElement = class PacemUrlInputElement extends PacemTextualInputElement {
|
|
8533
8880
|
constructor() {
|
|
8534
8881
|
super();
|
|
8535
8882
|
}
|
|
8536
8883
|
toggleReadonlyView(readonly) {
|
|
8537
|
-
this.
|
|
8538
|
-
|
|
8884
|
+
const input = this._input, anchor = this._anchor;
|
|
8885
|
+
if (!pacemCore.Utils.isNull(input))
|
|
8886
|
+
input.hidden = readonly;
|
|
8887
|
+
if (!pacemCore.Utils.isNull(anchor))
|
|
8888
|
+
anchor.hidden = !readonly;
|
|
8539
8889
|
}
|
|
8540
8890
|
get inputFields() {
|
|
8541
|
-
return
|
|
8891
|
+
return pacemCore.Utils.isNull(this._input)
|
|
8892
|
+
? []
|
|
8893
|
+
: [this._input];
|
|
8542
8894
|
}
|
|
8543
8895
|
};
|
|
8544
8896
|
__decorate$b([
|
|
8545
8897
|
pacemCore.ViewChild('input[type=url]')
|
|
8546
|
-
], PacemUrlInputElement.prototype, "
|
|
8898
|
+
], PacemUrlInputElement.prototype, "_input", void 0);
|
|
8547
8899
|
__decorate$b([
|
|
8548
8900
|
pacemCore.ViewChild(pacemCore.P + '-a')
|
|
8549
|
-
], PacemUrlInputElement.prototype, "
|
|
8901
|
+
], PacemUrlInputElement.prototype, "_anchor", void 0);
|
|
8550
8902
|
PacemUrlInputElement = __decorate$b([
|
|
8551
8903
|
pacemCore.CustomElement({ tagName: pacemCore.P + '-input-url', template: `<input type="url" class="${pacemCore.PCSS}-input" />${CHAR_COUNTER_CHILD}<${pacemCore.P}-a class="${pacemCore.PCSS}-readonly" disabled="{{ $pacem.isNullOrEmpty(:host.value) }}" href="{{ :host.value }}" target="_blank"><${pacemCore.P}-text text="{{ :host.viewValue }}"></${pacemCore.P}-text></${pacemCore.P}-a>`, shadow: pacemCore.Defaults.USE_SHADOW_ROOT })
|
|
8552
8904
|
], PacemUrlInputElement);
|
|
@@ -8558,11 +8910,14 @@ ${CHAR_COUNTER_CHILD}<span class="${pacemCore.PCSS}-readonly"><${pacemCore.P}-te
|
|
|
8558
8910
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
8559
8911
|
};
|
|
8560
8912
|
//namespace Pacem.Components.Scaffolding {
|
|
8913
|
+
/** Default tile-layer URL template used by {@link PacemLatLngElement} when {@link LatLngOptions.tiles} isn't set (currently empty, i.e. the map adapter's own default applies). */
|
|
8561
8914
|
const DEFAULT_TILES = "";
|
|
8915
|
+
/** Default map attribution string used by {@link PacemLatLngElement} when {@link LatLngOptions.attribution} isn't set (currently empty, i.e. the map adapter's own default applies). */
|
|
8562
8916
|
const DEFAULT_ATTRIBUTION = "";
|
|
8563
8917
|
//const TILES = `//api.mapbox.com/styles/v1/cmerighi/ciwz1gib7002l2prvgpi724nk/tiles/256/{z}/{x}/{y}?access_token=pk.eyJ1IjoiY21lcmlnaGkiLCJhIjoiY2lsZHIxdGJmMDAxOHc4bHowamxpZ2Z2OCJ9.7I7ndF-rAkx_1Sqi0bw3Ew`;
|
|
8564
8918
|
//const ATTRIBUTION = `Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://mapbox.com">Mapbox</a>`
|
|
8565
8919
|
const REVERSE_GEOCODE_URL = 'https://nominatim.openstreetmap.org/reverse';
|
|
8920
|
+
/** A `<p-latlng>` field: a {@link PacemBaseElement} coordinate picker combining paired lat/lng number inputs with an interactive, draggable-marker map (Leaflet/OSM, Azure Maps or Google Maps) and reverse-geocoded address preview. */
|
|
8566
8921
|
let PacemLatLngElement = class PacemLatLngElement extends PacemBaseElement {
|
|
8567
8922
|
convertValueAttributeToProperty(attr) {
|
|
8568
8923
|
const regexArray = /^\s*([+-]?\d+\.?\d+)[,\s]\s*([+-]?\d+\.?\d+)\s*$/.exec(attr);
|
|
@@ -8740,10 +9095,12 @@ ${CHAR_COUNTER_CHILD}<span class="${pacemCore.PCSS}-readonly"><${pacemCore.P}-te
|
|
|
8740
9095
|
function pullEmpty() {
|
|
8741
9096
|
return { name: '', value: '' };
|
|
8742
9097
|
}
|
|
9098
|
+
/** A `<p-namevalue-list>` field: a {@link PacemBaseElement} editor for a repeatable list of name/value string pairs, whose `value` is either an array of {@link NameValuePair}s or, when {@link PacemNameValueListElement#dictionary} is set, a plain `{ [name]: value }` object. */
|
|
8743
9099
|
let PacemNameValueListElement = class PacemNameValueListElement extends PacemBaseElement {
|
|
8744
9100
|
constructor() {
|
|
8745
9101
|
super(...arguments);
|
|
8746
9102
|
this.inputFields = [];
|
|
9103
|
+
/** Internal editable rows, mirrored to/from `value` depending on {@link dictionary}. */
|
|
8747
9104
|
this._bag = [];
|
|
8748
9105
|
}
|
|
8749
9106
|
toggleReadonlyView(readonly) {
|
|
@@ -8869,6 +9226,7 @@ ${CHAR_COUNTER_CHILD}<span class="${pacemCore.PCSS}-readonly"><${pacemCore.P}-te
|
|
|
8869
9226
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
8870
9227
|
};
|
|
8871
9228
|
//namespace Pacem.Components.Scaffolding {
|
|
9229
|
+
/** A `<p-property-picker>` field: a {@link PacemBaseElement} wrapping a {@link PacemSelectElement} whose datasource is auto-populated with the (recursively flattened) watched property names of a `target` element. */
|
|
8872
9230
|
let PacemPropertyPickerElement = class PacemPropertyPickerElement extends PacemBaseElement {
|
|
8873
9231
|
get inputFields() {
|
|
8874
9232
|
return [this._select];
|
|
@@ -8951,6 +9309,7 @@ ${CHAR_COUNTER_CHILD}<span class="${pacemCore.PCSS}-readonly"><${pacemCore.P}-te
|
|
|
8951
9309
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
8952
9310
|
};
|
|
8953
9311
|
//namespace Pacem.Components.Scaffolding {
|
|
9312
|
+
/** A `<p-radio>` field: a {@link PacemBaseElement} wrapping a single native `<input type="radio">` with a caption label; its `value` is the radio's native value when {@link selected}, otherwise `undefined`. Used standalone or as the item template driven by {@link PacemRadioListElement}. */
|
|
8954
9313
|
let PacemRadioElement = class PacemRadioElement extends PacemBaseElement {
|
|
8955
9314
|
convertValueAttributeToProperty(attr) {
|
|
8956
9315
|
return attr;
|
|
@@ -9028,6 +9387,7 @@ ${CHAR_COUNTER_CHILD}<span class="${pacemCore.PCSS}-readonly"><${pacemCore.P}-te
|
|
|
9028
9387
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
9029
9388
|
};
|
|
9030
9389
|
//namespace Pacem.Components.Scaffolding {
|
|
9390
|
+
/** A `<p-radio-list>` field: a {@link PacemDataSourceElement} rendering the datasource as a group of mutually-exclusive `<p-radio>` buttons. */
|
|
9031
9391
|
let PacemRadioListElement = class PacemRadioListElement extends PacemDataSourceElement {
|
|
9032
9392
|
acceptValue(val) {
|
|
9033
9393
|
// no need to implement
|
|
@@ -9096,9 +9456,11 @@ on-${pacemCore.PropertyChangeEventName}=":host._selectionChanged($event, ^index,
|
|
|
9096
9456
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
9097
9457
|
};
|
|
9098
9458
|
//namespace Pacem.Components.Scaffolding {
|
|
9459
|
+
/** A `<p-select>` field: a {@link PacemDataSourceElement} rendering the datasource as a native `<select>` dropdown. */
|
|
9099
9460
|
let PacemSelectElement = class PacemSelectElement extends PacemDataSourceElement {
|
|
9100
9461
|
constructor() {
|
|
9101
9462
|
super(...arguments);
|
|
9463
|
+
/** Gets or sets whether an extra, empty/placeholder `<option>` is prepended to the rendered choices. Defaults to `true`. */
|
|
9102
9464
|
this.emptyOption = true;
|
|
9103
9465
|
}
|
|
9104
9466
|
toggleReadonlyView(readonly) {
|
|
@@ -9108,7 +9470,9 @@ on-${pacemCore.PropertyChangeEventName}=":host._selectionChanged($event, ^index,
|
|
|
9108
9470
|
// no actual need to be idem-potent...
|
|
9109
9471
|
// (take care in future)
|
|
9110
9472
|
get inputFields() {
|
|
9111
|
-
return
|
|
9473
|
+
return pacemCore.Utils.isNull(this._select)
|
|
9474
|
+
? []
|
|
9475
|
+
: [this._select];
|
|
9112
9476
|
}
|
|
9113
9477
|
_manageDom(evt) {
|
|
9114
9478
|
const args = evt.detail, item = args.item;
|
|
@@ -9221,6 +9585,7 @@ on-${pacemCore.PropertyChangeEventName}=":host._selectionChanged($event, ^index,
|
|
|
9221
9585
|
};
|
|
9222
9586
|
//namespace Pacem.Components.Scaffolding {
|
|
9223
9587
|
// TODO: exploit 202x features like https://developer.mozilla.org/en-US/docs/Web/CSS/offset-path or https://developer.chrome.com/blog/anchor-positioning-api
|
|
9588
|
+
/** A `<p-slider>` field: a {@link PacemBaseElement} numeric range control with a draggable thumb, keyboard support, and an optional tooltip-style thumb label; its `value` is a number between `min` and `max`. */
|
|
9224
9589
|
let PacemSliderElement = class PacemSliderElement extends PacemBaseElement {
|
|
9225
9590
|
constructor() {
|
|
9226
9591
|
super(...arguments);
|
|
@@ -9508,6 +9873,7 @@ on-${pacemCore.PropertyChangeEventName}=":host._selectionChanged($event, ^index,
|
|
|
9508
9873
|
}
|
|
9509
9874
|
const BALLOON_POPUP_DELAY = 100;
|
|
9510
9875
|
const BALLOON_POPOUT_DELAY = 0;
|
|
9876
|
+
/** A `<p-suggest>` field: a {@link PacemDataSourceElement} autocomplete/typeahead text input, backed by a native `<input type="text">` and a dropdown balloon of filtered, highlighted suggestions; optionally accepts free-typed values not present in the datasource. */
|
|
9511
9877
|
let PacemSuggestElement = class PacemSuggestElement extends PacemDataSourceElement {
|
|
9512
9878
|
constructor() {
|
|
9513
9879
|
super(...arguments);
|
|
@@ -10053,6 +10419,7 @@ class="button-flat icon-rotate ${pacemCore.PCSS}-anim anim-pop anim-sudden anim-
|
|
|
10053
10419
|
super('tagadd', { value: value });
|
|
10054
10420
|
}
|
|
10055
10421
|
}
|
|
10422
|
+
/** A single `<p-tag>` chip: displays a label and a remove button, dispatching a `remove` event (after an out-transition) when dismissed. Rendered by {@link PacemTagsElement} for each item in its `value`. */
|
|
10056
10423
|
let PacemTagElement = class PacemTagElement extends pacemCore.Components.PacemElement {
|
|
10057
10424
|
propertyChangedCallback(name, old, val, first) {
|
|
10058
10425
|
super.propertyChangedCallback(name, old, val, first);
|
|
@@ -10091,6 +10458,7 @@ class="button-flat icon-rotate ${pacemCore.PCSS}-anim anim-pop anim-sudden anim-
|
|
|
10091
10458
|
<${pacemCore.P}-button on-click=":host._remove()"></${pacemCore.P}-button>`
|
|
10092
10459
|
})
|
|
10093
10460
|
], PacemTagElement);
|
|
10461
|
+
/** A `<p-tags>` field: a {@link PacemDataSourceElement} editor rendering `value` as a list of removable {@link PacemTagElement} chips, plus a {@link PacemSuggestElement} for picking (or, when {@link allowNew} is set, typing) new tags to add. */
|
|
10094
10462
|
let PacemTagsElement = class PacemTagsElement extends PacemDataSourceElement {
|
|
10095
10463
|
constructor() {
|
|
10096
10464
|
super(true);
|
|
@@ -10214,10 +10582,13 @@ class="button-flat icon-rotate ${pacemCore.PCSS}-anim anim-pop anim-sudden anim-
|
|
|
10214
10582
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
10215
10583
|
};
|
|
10216
10584
|
//namespace Pacem.Components.Scaffolding {
|
|
10585
|
+
/** A `<p-textarea>` field: a {@link PacemTextualInputElement} backed by a native `<textarea>`, with an optional character counter. */
|
|
10217
10586
|
let PacemTextAreaElement = class PacemTextAreaElement extends PacemTextualInputElement {
|
|
10218
10587
|
constructor() {
|
|
10219
10588
|
super(...arguments);
|
|
10589
|
+
/** Gets or sets the native `<textarea>`'s `rows` attribute. Defaults to `5`. */
|
|
10220
10590
|
this.rows = 5;
|
|
10591
|
+
/** Gets or sets the native `<textarea>`'s `cols` attribute. Defaults to `50`. */
|
|
10221
10592
|
this.cols = 50;
|
|
10222
10593
|
}
|
|
10223
10594
|
/** @override */
|
|
@@ -10225,11 +10596,16 @@ class="button-flat icon-rotate ${pacemCore.PCSS}-anim anim-pop anim-sudden anim-
|
|
|
10225
10596
|
return true;
|
|
10226
10597
|
}
|
|
10227
10598
|
toggleReadonlyView(readonly) {
|
|
10228
|
-
this.
|
|
10229
|
-
|
|
10599
|
+
const input = this._input, span = this._span;
|
|
10600
|
+
if (!pacemCore.Utils.isNull(input))
|
|
10601
|
+
input.hidden = readonly;
|
|
10602
|
+
if (!pacemCore.Utils.isNull(span))
|
|
10603
|
+
span.hidden = !readonly;
|
|
10230
10604
|
}
|
|
10231
10605
|
get inputFields() {
|
|
10232
|
-
return
|
|
10606
|
+
return pacemCore.Utils.isNull(this._input)
|
|
10607
|
+
? []
|
|
10608
|
+
: [this._input];
|
|
10233
10609
|
}
|
|
10234
10610
|
propertyChangedCallback(name, old, val, first) {
|
|
10235
10611
|
super.propertyChangedCallback(name, old, val, first);
|
|
@@ -10262,15 +10638,18 @@ class="button-flat icon-rotate ${pacemCore.PCSS}-anim anim-pop anim-sudden anim-
|
|
|
10262
10638
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
10263
10639
|
};
|
|
10264
10640
|
//namespace Pacem.Components.Scaffolding {
|
|
10641
|
+
/** A `<p-textarea-markdown>` field: a {@link PacemTextualInputElement} backed by a native `<textarea>` for editing Markdown text, whose readonly view renders the value as HTML via {@link Components.UI.MarkdownService}. */
|
|
10265
10642
|
let PacemMarkdownTextAreaElement = class PacemMarkdownTextAreaElement extends PacemTextualInputElement {
|
|
10266
10643
|
constructor(_md = new pacemUi.Components.UI.MarkdownService()) {
|
|
10267
10644
|
super();
|
|
10268
10645
|
this._md = _md;
|
|
10646
|
+
/** Gets or sets the native `<textarea>`'s `rows` attribute. Defaults to `5`. */
|
|
10269
10647
|
this.rows = 5;
|
|
10648
|
+
/** Gets or sets the native `<textarea>`'s `cols` attribute. Defaults to `50`. */
|
|
10270
10649
|
this.cols = 50;
|
|
10271
10650
|
this._keydownHandler = (evt) => {
|
|
10272
10651
|
if (evt.keyCode === 9 /* tab */) {
|
|
10273
|
-
const input = this.
|
|
10652
|
+
const input = this._input, value = input.value;
|
|
10274
10653
|
var ndx = input.selectionStart;
|
|
10275
10654
|
input.value = value.substr(0, ndx) + ' ' + value.substr(ndx);
|
|
10276
10655
|
pacemCore.preventDefaultHandler(evt);
|
|
@@ -10278,14 +10657,17 @@ class="button-flat icon-rotate ${pacemCore.PCSS}-anim anim-pop anim-sudden anim-
|
|
|
10278
10657
|
};
|
|
10279
10658
|
}
|
|
10280
10659
|
toggleReadonlyView(readonly) {
|
|
10281
|
-
this.
|
|
10660
|
+
if (!pacemCore.Utils.isNull(this._input))
|
|
10661
|
+
this._input.hidden = readonly;
|
|
10282
10662
|
}
|
|
10283
10663
|
/** @override */
|
|
10284
10664
|
get preventKeyboardSubmit() {
|
|
10285
10665
|
return true;
|
|
10286
10666
|
}
|
|
10287
10667
|
get inputFields() {
|
|
10288
|
-
return
|
|
10668
|
+
return pacemCore.Utils.isNull(this._input)
|
|
10669
|
+
? []
|
|
10670
|
+
: [this._input];
|
|
10289
10671
|
}
|
|
10290
10672
|
getViewValue(val) {
|
|
10291
10673
|
return this._md.toHtml(val);
|
|
@@ -10302,11 +10684,11 @@ class="button-flat icon-rotate ${pacemCore.PCSS}-anim anim-pop anim-sudden anim-
|
|
|
10302
10684
|
}
|
|
10303
10685
|
viewActivatedCallback() {
|
|
10304
10686
|
super.viewActivatedCallback();
|
|
10305
|
-
this.
|
|
10687
|
+
this._input.addEventListener("keydown", this._keydownHandler, false);
|
|
10306
10688
|
}
|
|
10307
10689
|
disconnectedCallback() {
|
|
10308
|
-
this.
|
|
10309
|
-
this.
|
|
10690
|
+
this._input &&
|
|
10691
|
+
this._input.removeEventListener("keydown", this._keydownHandler, false);
|
|
10310
10692
|
super.disconnectedCallback();
|
|
10311
10693
|
}
|
|
10312
10694
|
};
|
|
@@ -10318,7 +10700,7 @@ class="button-flat icon-rotate ${pacemCore.PCSS}-anim anim-pop anim-sudden anim-
|
|
|
10318
10700
|
], PacemMarkdownTextAreaElement.prototype, "cols", void 0);
|
|
10319
10701
|
__decorate([
|
|
10320
10702
|
pacemCore.ViewChild('textarea')
|
|
10321
|
-
], PacemMarkdownTextAreaElement.prototype, "
|
|
10703
|
+
], PacemMarkdownTextAreaElement.prototype, "_input", void 0);
|
|
10322
10704
|
__decorate([
|
|
10323
10705
|
pacemCore.ViewChild(`div.${pacemCore.PCSS}-readonly`)
|
|
10324
10706
|
], PacemMarkdownTextAreaElement.prototype, "_markdown", void 0);
|