cedar-embeddable-editor 2.0.18 → 2.0.20

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/CHANGELOG.md CHANGED
@@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [2.0.20] - 2026-10-05
9
+
10
+ Aligns with `cedar-model-typescript-library@1.0.16`.
11
+
12
+ - Includes paragraph character limits, every stored constraint problem stated at its field in each language, checked host value shapes, read-only guards and immediate lookup cancellation.
13
+
14
+ ## [2.0.19] - 2026-10-02
15
+
16
+ Aligns with `cedar-model-typescript-library@1.0.15`.
17
+
18
+ - Includes `reveal` for taking the user to a field, data quality problems located by the entries that hold them, and stored problems shown at their fields.
19
+
8
20
  ## [2.0.18] - 2026-09-26
9
21
 
10
22
  Aligns with `cedar-model-typescript-library@1.0.15`.
@@ -21,6 +33,17 @@ Aligns with `cedar-model-typescript-library@1.0.13`.
21
33
 
22
34
  ### Added
23
35
 
36
+ - `reveal(location, options)` on `cedar-embeddable-editor`, which takes the user to a field or
37
+ element: it turns to the field's page, moves each repeating field or element above it to the
38
+ named entry, opens the panels around it, scrolls it into view and focuses its control.
39
+ `{ focus: false }` scrolls without taking focus. It resolves to whether the field could be
40
+ shown, and changes nothing when it cannot. A problem from the data quality report is itself a
41
+ location, so a host listing the problems can pass each one straight to `reveal`.
42
+ - `occurrences` on each data quality problem: the entry of each repeating field or element along
43
+ its path, outermost first. A path alone names one place per entry of everything above it, so a
44
+ host could not say which entry held a bad value. The same bad value in two entries is now two
45
+ problems.
46
+
24
47
  - A second element, `cedar-embeddable-field`, registered by the same bundle. It renders one field's
25
48
  control and nothing of the form around it, for a host that holds a field artifact rather
26
49
  than a template — a designer collecting a default value, above all. The value goes in and
@@ -44,6 +67,18 @@ Aligns with `cedar-model-typescript-library@1.0.13`.
44
67
 
45
68
  ### Changed
46
69
 
70
+ - A field shows what is wrong with a value loaded from a stored instance as soon as the form opens.
71
+ The error states waited for the control to be edited or touched, so a field the data quality
72
+ report listed as invalid showed nothing. An empty required field still waits, until the user
73
+ edits it or is taken to it with `reveal`.
74
+ - The data quality report states at the field the problems no control can find: a stored choice
75
+ that is not one of the options, a term missing its label or its IRI, an authority identifier
76
+ that is not a valid IRI, and a list longer than its `maxItems`. A list shorter than its
77
+ `minItems` is stated once the user is taken to it.
78
+ - The data quality report no longer reports `missingProperty`. It described a repeating field or
79
+ element absent from the instance CEE read, which CEE writes out as an empty list, so it warned
80
+ about a defect that saving removed and that no field could show.
81
+
47
82
  - A numeric field's type constraint and a temporal field's errors follow the configured
48
83
  language. The numeric sentence was English written into the validator, and the temporal
49
84
  widget printed the data quality report's diagnostics, such as `Granularity is year, but the
@@ -83,8 +118,20 @@ Aligns with `cedar-model-typescript-library@1.0.13`.
83
118
  - Compact YAML downloads retain the template's root ID but omit the IDs of nested fields and
84
119
  elements. Full YAML downloads continue to carry the complete identity tree.
85
120
 
121
+ - The form's header sets CEE's name and version stamp beside the mark rather than beneath it, so
122
+ the identity is no taller than the mark. Beside a title with a description, the identity and the
123
+ template's version and status keep to the top of the row, level with the title. At 520px or
124
+ narrower they take a row of their own above the title, which then has the full width.
125
+
126
+ - Every text box carries `autocomplete="off"`. A browser otherwise listed beneath a field what had
127
+ been typed into any box with the same name or id, and Angular Material gives each input an id
128
+ such as `mat-input-3`, so the list could hold values from an unrelated form.
129
+
86
130
  ### Fixed
87
131
 
132
+ - `minItems` and `maxItems` on a repeating field inside a repeating element are checked in
133
+ every entry of the element. They were checked in the entry on screen, so the report changed
134
+ with the page the user had moved to.
88
135
  - Reassigning `cedar-embeddable-field.fieldObject` recreates the control even when the field type
89
136
  stays the same, so validators and other initialized settings follow the new artifact.
90
137
  - `cedar-embeddable-field` emits `valueChange` when validity changes even if the normalized value
package/README.md CHANGED
@@ -39,9 +39,9 @@ gives the input properties, the output properties, and the change event a host
39
39
  reads.
40
40
 
41
41
  For the design rationale, the architecture, and deployments in research
42
- platforms, see [*Author Once, Publish Everywhere: Portable Metadata Authoring
43
- with the CEDAR Embeddable Editor*](https://doi.org/10.5334/dsj-2026-002),
44
- published in the *Data Science Journal* (2026).
42
+ platforms, see [_Author Once, Publish Everywhere: Portable Metadata Authoring
43
+ with the CEDAR Embeddable Editor_](https://doi.org/10.5334/dsj-2026-002),
44
+ published in the _Data Science Journal_ (2026).
45
45
 
46
46
  ## Installing
47
47
 
@@ -124,13 +124,57 @@ takes the same page apart step by step, and
124
124
  [Embedding in a Framework](https://metadatacenter.readthedocs.io/en/latest/cedar-embeddable-editor/frameworks/)
125
125
  covers Angular, React, and Ember.
126
126
 
127
+ A dialog host can set `previewMode: true` in either read-only or editable mode
128
+ to omit CEE's identity header and use compact, content-sized form spacing. Template
129
+ descriptions and page navigation remain available. `readOnlyMode` independently
130
+ controls whether values can be edited. Ordinary embeds retain their existing layout.
131
+
132
+ Trial hosts such as Workspace “Try out” and CED’s editable preview set
133
+ `suppressEmptyFieldErrors: true`. Clearing a control then hides its error state and
134
+ messages even after blur. Nonempty invalid values and incomplete temporal values still
135
+ show errors. This affects presentation only: required fields remain invalid in the quality
136
+ report. Ordinary metadata editing leaves the option off.
137
+
138
+ ## Validation
139
+
140
+ Read `dataQualityReport` for the whole instance, including nested and off-screen
141
+ occurrences. Each problem has a code, `severity` (`warning` or `error`), a field
142
+ `path` and occurrence indices. Pass a field problem to `reveal(problem)` to reach it.
143
+
144
+ Missing required answers, insufficient occurrences and unnamed attribute rows are
145
+ warnings. Invalid values, malformed incoming data and unfinished edits are errors.
146
+ Either makes `isValid` false; the host decides whether saving is allowed. A required
147
+ field must be answered in every existing containing element. A repeating field
148
+ needs at least one answer within each such element.
149
+
150
+ The report includes unfinished date/time and attribute-name edits, and `change`
151
+ fires when metadata **or the report** changes. Invalid imported field IRIs and
152
+ well-shaped numeric, temporal and IRI defaults remain available for correction.
153
+ Terminology membership and server-side validation remain the host's responsibility.
154
+
127
155
  ## Embedding a Single Field
128
156
 
129
- The bundle registers a second element. `<cedar-embeddable-field>` renders one field's
130
- control — the same control the editor renders for that field, from the same component
131
- — and nothing of the form around it: no label, no description, no card. A host that
132
- holds a field artifact rather than a template puts this where the control belongs and
133
- draws the rest itself.
157
+ The bundle registers a second element. `<cedar-embeddable-field>` renders one field
158
+ from its artifact. In editable mode it supplies the same bare control CEE uses,
159
+ so a host such as CED can place it in its own form.
160
+
161
+ With `config = { readOnlyMode: true }`, CEF owns the full presentation: label,
162
+ field type, description, constraints, choices, sources and declared defaults where
163
+ present. The type is named by the icon beside the label. A supplied value is shown
164
+ read-only. CEE uses the same field presentation, so preview hosts only need to supply
165
+ the artifact and their dialog shell.
166
+
167
+ Set `previewMode: true` with `readOnlyMode: true` when the host supplies the field name
168
+ in its own header. CEF then omits its header, and with it the type icon, while
169
+ retaining the description and value or specification. A host whose header leaves out
170
+ the type, such as the Workspace's preview, also sets `showFieldType: true`.
171
+ CEF then states the type above the description, with the icon its header would have
172
+ drawn (for example, `Paragraph`). A host whose header already shows the type, as CED's
173
+ field cards do, leaves it unset.
174
+
175
+ Read-only controls have no placeholder text, and fields without constraints draw empty
176
+ boxes. Static fields show their content. A standalone page break is described without
177
+ creating pagination.
134
178
 
135
179
  Designing a template is what this is for. An author giving a field a default value
136
180
  needs somewhere to type it, and the box that collects one has to be the control the
@@ -192,6 +236,20 @@ field?.addEventListener('valueChange', (event: CustomEvent<CedarEmbeddableFieldC
192
236
  the control afresh — the field being designed changes type under its author's hand.
193
237
  `config` takes one assignment, as the editor's does. A value of a kind the field
194
238
  cannot hold is reported through `eventHandler` and ignored rather than coerced.
239
+ Malformed runtime payloads are also rejected, including assignments made before the
240
+ field arrives. Accepted values and artifacts are copied; host mutation after an
241
+ assignment does not change the editor. Getters and events return detached values.
242
+
243
+ A numeric value has the shape `{ kind: 'number', value: number | string }`.
244
+ Ordinary numbers remain numbers. When converting to a JavaScript number would lose
245
+ significant digits or exceed its range, CEF returns the exact numeric string instead:
246
+ `9007199254740993` and `0.1234567890123456789` retain every digit. Both forms may be
247
+ assigned back through `value`. Constraint validity remains a separate result.
248
+
249
+ Read-only mode guards user mutations in the controller, including late callbacks
250
+ and structural edits. Explicit host `value` assignments still work. Controlled-term
251
+ and external-authority searches cancel on a new query, a read-only transition, or
252
+ widget destruction; an old response cannot overwrite a newer query.
195
253
 
196
254
  Requiredness and cardinality belong to a field's deployment inside a template, and
197
255
  this element deploys nothing, so the value it acquires is single and is allowed to be
@@ -385,3 +443,12 @@ for all available settings.
385
443
 
386
444
  3. In your browser, navigate to `http://localhost:4400/`. The app will
387
445
  automatically reload if you change any of the source files.
446
+
447
+ The host lifecycle matrix in
448
+ `src/app/modules/shared/components/wrapper-lifecycle-matrix.spec.ts` crosses three input
449
+ arrival orders, host mutation, one or two simultaneous numeric/lookup wrapper pairs,
450
+ ordinary/large-integer/precise-decimal values, initial/late/no read-only state,
451
+ and superseded lookup success/error/completion (324 cases). It runs in `npm test`
452
+ with real wrappers, artifact coordination, controllers and lookup streams; rendering
453
+ and HTTP are substituted. The Angular coordinator suite separately verifies rendered
454
+ controls, simultaneous wrappers, host events and malformed assignments.
@@ -4,6 +4,6 @@
4
4
  "main.js",
5
5
  "polyfills.js"
6
6
  ],
7
- "bytes": 2182095,
8
- "sha256": "b37efb9f7c3e893b74d2a4a7eaf784fcbd7b0b54586f25a93f6c8d7c596ad73c"
7
+ "bytes": 2228152,
8
+ "sha256": "7fdb1fbd1a59b2cdc77e6c6d54716398809d6f3438ebe2c99272fde0e5a38647"
9
9
  }
@@ -4,6 +4,6 @@
4
4
  "main.js",
5
5
  "polyfills.js"
6
6
  ],
7
- "bytes": 2365905,
8
- "sha256": "8e62f446b41da71eaf8c46be9818a78e66639d3b2de7e170de7a06edb991b121"
7
+ "bytes": 2350430,
8
+ "sha256": "9cc4c9cb9e669d79bba195fdaaa3df9ea11228d54896783bc00ccd21e542d619"
9
9
  }
@@ -45,6 +45,16 @@ export type CeeConfigKey = keyof CeeConfig;
45
45
  */
46
46
  export interface CeeConfig {
47
47
  showTemplateDescription?: boolean;
48
+ /** Embedding with a host-provided heading, in either read-only or editable mode. Hides CEE's identity header or CEF's field header; keeps descriptions and controls. */
49
+ previewMode?: boolean;
50
+ /**
51
+ * For a read-only CEF preview whose host heading does not name the field's type. The hidden header
52
+ * carried the icon that names it, so CEF states the type above the description instead, with that
53
+ * icon. A host whose own heading already shows the type leaves this unset.
54
+ */
55
+ showFieldType?: boolean;
56
+ /** Keep empty trial fields quiet without changing validity or nonempty-value errors. */
57
+ suppressEmptyFieldErrors?: boolean;
48
58
  /**
49
59
  * Renders the form without editing controls.
50
60
  *
@@ -147,10 +157,22 @@ export interface CeeTemplateAndInstance {
147
157
  * TypeScript host could not read either without a cast.
148
158
  */
149
159
  export interface CeeValidationProblem {
160
+ /** Missing answers are warnings; invalid values and unfinished edits are errors. Both affect isValid. */
161
+ severity: 'warning' | 'error';
150
162
  /** Machine-readable code, e.g. `numberType` or `temporalGranularity`. */
151
163
  code: string;
152
164
  /** Path to the offending value, outermost first. */
153
165
  path: string[];
166
+ /**
167
+ * The entry taken at each repeating field or element along `path`, outermost first.
168
+ *
169
+ * A path names one place per entry of everything above it that repeats, and this
170
+ * says which entry holds the problem. A problem about a whole list, such as
171
+ * `minItems`, names the entries above the list and none of its own; a `required`
172
+ * problem names the containing elements whose requirement is unfilled. Pass the problem to
173
+ * `reveal` to take the user to it.
174
+ */
175
+ occurrences: number[];
154
176
  /** The field's property name, which is the last path segment. */
155
177
  field: string;
156
178
  /** The field's declared `_ui.inputType`, or null where it declares none. */
@@ -160,6 +182,31 @@ export interface CeeValidationProblem {
160
182
  /** The value that failed, when there is one. */
161
183
  value?: unknown;
162
184
  }
185
+ /**
186
+ * A place on the form: a field or element, in particular entries of what repeats.
187
+ *
188
+ * A `CeeValidationProblem` is one, so a host can pass a problem straight to `reveal`.
189
+ */
190
+ export interface CeeLocation {
191
+ /** Component path from the template root, as a problem's `path` gives it. */
192
+ path: string[];
193
+ /**
194
+ * The entry to show at each repeating field or element along `path`, outermost first.
195
+ *
196
+ * Optional, and may be shorter than the repeating components along the path: those
197
+ * it does not reach stay on the entry they show.
198
+ */
199
+ occurrences?: number[];
200
+ }
201
+ /** What a host may ask of `reveal` beyond showing the field. */
202
+ export interface CeeRevealOptions {
203
+ /**
204
+ * Whether to move keyboard focus to the field's control. Defaults to true. A host
205
+ * keeping focus in its own controls, such as a designer showing the field it has
206
+ * selected, passes false.
207
+ */
208
+ focus?: boolean;
209
+ }
163
210
  /**
164
211
  * What CEE thinks of the instance currently in the form.
165
212
  *
@@ -179,15 +226,15 @@ export interface CeeDataQualityReport {
179
226
  /**
180
227
  * How many of those the instance fills.
181
228
  *
182
- * A requirement is met when any occurrence carries a value, so this is
183
- * unaffected by which page the form is showing.
229
+ * A required field needs at least one value in every existing containing element.
230
+ * This is unaffected by which occurrence the form is showing.
184
231
  */
185
232
  nonNullRequiredFieldValueCount: number;
186
233
  /**
187
234
  * Validation problems.
188
235
  *
189
- * Includes one `required` problem for each unsatisfied required field
190
- * declaration, while the two counters retain their existing aggregate view.
236
+ * Includes a located `required` warning for each containing element with an
237
+ * unanswered requirement. The two counters count declarations, not occurrences.
191
238
  */
192
239
  problems: CeeValidationProblem[];
193
240
  /** True when every required field is filled and no constraint is violated. */
@@ -313,12 +360,35 @@ export interface CedarEmbeddableEditorElement extends HTMLElement {
313
360
  * Replacing one is traced, so a page whose messages stop arriving can see why.
314
361
  */
315
362
  eventHandler: CeeEventHandler;
316
- /** The instance as CEDAR JSON. Read-only. */
363
+ /**
364
+ * The instance as CEDAR JSON. Read-only.
365
+ *
366
+ * An empty object while the editor holds no artifact. An input it refuses because it is not a
367
+ * readable CEDAR artifact leaves it holding none, so a host that assigns a template on its own, or a
368
+ * template and instance together through `templateAndInstanceObject`, reads an empty object straight
369
+ * after the assignment as a refusal. An instance assigned on its own is held while it waits for a
370
+ * template, so a template refused after it leaves this holding the instance. The refusal's reason
371
+ * goes to the event handler's `error`.
372
+ */
317
373
  readonly currentMetadata: CeeJsonObject;
318
374
  /** The instance as CEDAR YAML. Read-only. */
319
375
  readonly currentMetadataYaml: string;
320
376
  /** What CEE thinks of the instance. Read-only. */
321
377
  readonly dataQualityReport: CeeDataQualityReport;
378
+ /**
379
+ * Take the user to a field or element, and resolve whether it could be shown.
380
+ *
381
+ * Turns to the field's page, moves each repeating field or element above it to the
382
+ * named entry, opens the panels around it, scrolls it into view and focuses its
383
+ * control. A field the user is taken to also states an unanswered requirement, which
384
+ * a field nobody has reached keeps quiet.
385
+ *
386
+ * Resolves false, having changed nothing, for a path the template does not declare,
387
+ * a hidden field, or an entry that does not exist. A repeating element with no
388
+ * entries stops the reveal at the element, since nothing inside it is on the form.
389
+ * Available once the element is in the document and has a template.
390
+ */
391
+ readonly reveal: (location: CeeLocation, options?: CeeRevealOptions) => Promise<boolean>;
322
392
  }
323
393
  /**
324
394
  * What one field holds, in the terms its own type is written in.
@@ -331,7 +401,7 @@ export interface CedarEmbeddableEditorElement extends HTMLElement {
331
401
  * Embeddable Designer's single `defaultValue: string` has.
332
402
  *
333
403
  * `none` is an unfilled field. It is also what a numeric field reports while it holds
334
- * something that is not yet a number, `3.` on the way to `3.5`; `valid` on the change
404
+ * something that is not yet a number, `-` on the way to `-3.5`; `valid` on the change
335
405
  * detail separates that from empty.
336
406
  */
337
407
  export type CedarEmbeddableFieldValue = {
@@ -342,10 +412,10 @@ export type CedarEmbeddableFieldValue = {
342
412
  kind: 'literal';
343
413
  value: string;
344
414
  }
345
- /** A numeric field, once what it holds is a finite number. */
415
+ /** A numeric field. Exact decimal strings preserve values a JavaScript number would round. */
346
416
  | {
347
417
  kind: 'number';
348
- value: number;
418
+ value: number | string;
349
419
  }
350
420
  /** A date or time, as the ISO literal its granularity calls for. */
351
421
  | {
@@ -380,28 +450,26 @@ export interface CedarEmbeddableFieldChangeDetail {
380
450
  *
381
451
  * The subset of `CeeConfig` that describes a field rather than the form around one.
382
452
  * The keys left out — the download menu, the expand controls, the template
383
- * description — settle what an editor draws around its fields, and this element draws
384
- * nothing around its own.
453
+ * description — settle what an editor draws around a whole form. Field labels and
454
+ * descriptions belong to this element in read-only mode.
385
455
  */
386
- export type CedarEmbeddableFieldConfig = Pick<CeeConfig, 'readOnlyMode' | 'trustTemplateRichText' | 'terminologyBaseUrl' | 'bridgeBaseUrl' | 'defaultLanguage' | 'fallbackLanguage' | 'languageMapPathPrefix'>;
456
+ export type CedarEmbeddableFieldConfig = Pick<CeeConfig, 'readOnlyMode' | 'previewMode' | 'showFieldType' | 'suppressEmptyFieldErrors' | 'trustTemplateRichText' | 'terminologyBaseUrl' | 'bridgeBaseUrl' | 'defaultLanguage' | 'fallbackLanguage' | 'languageMapPathPrefix'>;
387
457
  /**
388
458
  * One field's control, as a host sees it.
389
459
  *
390
- * Registered as `cedar-embeddable-field`. It renders exactly the widget the editor
391
- * renders for that field — the same component, not a second implementation — and
392
- * reports what the widget holds. Around it there is nothing: no label, no description,
393
- * no card. A host that has a field artifact and wants a value for it draws its own
394
- * surroundings and puts this where the control goes.
460
+ * Registered as `cedar-embeddable-field`. Editable, it renders the same bare value
461
+ * control as CEE, for a host that supplies its own surrounding form.
395
462
  *
396
- * Read-only is the presentation half of the same element. Editable, the field is a
397
- * control to fill in; read-only with nothing in it, the widget is replaced by a
398
- * statement of what the field will accept, which is what the editor shows when it
399
- * renders a template nobody has filled in yet.
463
+ * Read-only, it owns the complete field presentation shared with CEE: label, type,
464
+ * description and applicable constraints, choices, sources and defaults. A supplied
465
+ * value remains visible and cannot be edited. Static content is also described;
466
+ * a standalone page break has a label and type but does not create pagination.
400
467
  *
401
- * A field artifact carries no requiredness and no cardinality — both belong to a
402
- * field's deployment in a template, and this element deploys nothing — so the value
403
- * it acquires is single and is allowed to be absent. That is what makes it usable for
404
- * a default value, which is optional by definition.
468
+ * Cardinality belongs to a field's deployment in a template, and this element deploys
469
+ * nothing, so the value it acquires is single. Requiredness is the field's own: an
470
+ * artifact that states `requiredValue: true` has an empty value reported as missing,
471
+ * unless the host sets `suppressEmptyFieldErrors`. CED writes a field on its own with
472
+ * `requiredValue: false`, which is what leaves a default value free to be empty.
405
473
  */
406
474
  export interface CedarEmbeddableFieldElement extends HTMLElement {
407
475
  /** Typed value event; the inherited overloads still handle every other DOM event. */