@limetech/lime-elements 40.21.1 → 40.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/cjs/language-s0bKUCvO.js +58 -0
  3. package/dist/cjs/lime-elements.cjs.js +1 -1
  4. package/dist/cjs/limel-action-bar_3.cjs.entry.js +2 -2
  5. package/dist/cjs/limel-ai-avatar.cjs.entry.js +2 -2
  6. package/dist/cjs/limel-badge_7.cjs.entry.js +2 -2
  7. package/dist/cjs/limel-callout.cjs.entry.js +2 -2
  8. package/dist/cjs/limel-chart.cjs.entry.js +524 -76
  9. package/dist/cjs/limel-chip-set.cjs.entry.js +2 -2
  10. package/dist/cjs/limel-chip_2.cjs.entry.js +2 -2
  11. package/dist/cjs/limel-code-diff.cjs.entry.js +2 -2
  12. package/dist/cjs/limel-code-editor.cjs.entry.js +2 -2
  13. package/dist/cjs/limel-collapsible-section.cjs.entry.js +2 -2
  14. package/dist/cjs/limel-date-picker.cjs.entry.js +1 -1
  15. package/dist/cjs/limel-dock.cjs.entry.js +2 -2
  16. package/dist/cjs/limel-drag-handle_2.cjs.entry.js +2 -2
  17. package/dist/cjs/limel-email-viewer.cjs.entry.js +2 -2
  18. package/dist/cjs/limel-file-viewer.cjs.entry.js +2 -2
  19. package/dist/cjs/limel-file.cjs.entry.js +2 -2
  20. package/dist/cjs/limel-flatpickr-adapter.cjs.entry.js +2 -2
  21. package/dist/cjs/limel-form.cjs.entry.js +202 -15
  22. package/dist/cjs/limel-list-item.cjs.entry.js +2 -2
  23. package/dist/cjs/limel-pagination-jump.cjs.entry.js +2 -2
  24. package/dist/cjs/limel-pagination.cjs.entry.js +14 -26
  25. package/dist/cjs/limel-picker.cjs.entry.js +2 -2
  26. package/dist/cjs/limel-profile-picture.cjs.entry.js +2 -2
  27. package/dist/cjs/limel-prosemirror-adapter.cjs.entry.js +2 -2
  28. package/dist/cjs/limel-resize-handle.cjs.entry.js +2 -2
  29. package/dist/cjs/limel-side-panel.cjs.entry.js +2 -2
  30. package/dist/cjs/limel-slider.cjs.entry.js +2 -2
  31. package/dist/cjs/limel-snackbar.cjs.entry.js +2 -2
  32. package/dist/cjs/limel-table.cjs.entry.js +2 -2
  33. package/dist/cjs/limel-text-editor-link-menu.cjs.entry.js +2 -2
  34. package/dist/cjs/loader.cjs.js +1 -1
  35. package/dist/cjs/{translations-CqJEWcfw.js → translations-JLP5icQ9.js} +1 -1
  36. package/dist/collection/components/chart/chart.js +116 -45
  37. package/dist/collection/components/chart/format.js +302 -0
  38. package/dist/collection/components/chart/options.js +26 -14
  39. package/dist/collection/components/chart/scale.js +132 -19
  40. package/dist/collection/components/form/filled-defaults.js +132 -0
  41. package/dist/collection/components/form/form.js +93 -15
  42. package/dist/collection/components/form/form.test-schemas.js +50 -0
  43. package/dist/collection/components/pagination/pagination.js +13 -25
  44. package/dist/collection/util/language.js +29 -0
  45. package/dist/esm/language-VamkUr90.js +55 -0
  46. package/dist/esm/lime-elements.js +1 -1
  47. package/dist/esm/limel-action-bar_3.entry.js +2 -2
  48. package/dist/esm/limel-ai-avatar.entry.js +2 -2
  49. package/dist/esm/limel-badge_7.entry.js +2 -2
  50. package/dist/esm/limel-callout.entry.js +2 -2
  51. package/dist/esm/limel-chart.entry.js +524 -76
  52. package/dist/esm/limel-chip-set.entry.js +2 -2
  53. package/dist/esm/limel-chip_2.entry.js +2 -2
  54. package/dist/esm/limel-code-diff.entry.js +2 -2
  55. package/dist/esm/limel-code-editor.entry.js +2 -2
  56. package/dist/esm/limel-collapsible-section.entry.js +2 -2
  57. package/dist/esm/limel-date-picker.entry.js +1 -1
  58. package/dist/esm/limel-dock.entry.js +2 -2
  59. package/dist/esm/limel-drag-handle_2.entry.js +2 -2
  60. package/dist/esm/limel-email-viewer.entry.js +2 -2
  61. package/dist/esm/limel-file-viewer.entry.js +2 -2
  62. package/dist/esm/limel-file.entry.js +2 -2
  63. package/dist/esm/limel-flatpickr-adapter.entry.js +2 -2
  64. package/dist/esm/limel-form.entry.js +202 -15
  65. package/dist/esm/limel-list-item.entry.js +2 -2
  66. package/dist/esm/limel-pagination-jump.entry.js +2 -2
  67. package/dist/esm/limel-pagination.entry.js +14 -26
  68. package/dist/esm/limel-picker.entry.js +2 -2
  69. package/dist/esm/limel-profile-picture.entry.js +2 -2
  70. package/dist/esm/limel-prosemirror-adapter.entry.js +2 -2
  71. package/dist/esm/limel-resize-handle.entry.js +2 -2
  72. package/dist/esm/limel-side-panel.entry.js +2 -2
  73. package/dist/esm/limel-slider.entry.js +2 -2
  74. package/dist/esm/limel-snackbar.entry.js +2 -2
  75. package/dist/esm/limel-table.entry.js +2 -2
  76. package/dist/esm/limel-text-editor-link-menu.entry.js +2 -2
  77. package/dist/esm/loader.js +1 -1
  78. package/dist/esm/{translations-kct5Kybu.js → translations-D9ZGrMhe.js} +1 -1
  79. package/dist/lime-elements/lime-elements.esm.js +1 -1
  80. package/dist/lime-elements/{p-6e9eeb0a.entry.js → p-0a7cbdc3.entry.js} +1 -1
  81. package/dist/lime-elements/{p-d35d2859.entry.js → p-0f96e94d.entry.js} +1 -1
  82. package/dist/lime-elements/{p-a7be03e1.entry.js → p-1a0c5e45.entry.js} +1 -1
  83. package/dist/lime-elements/{p-5e408c27.entry.js → p-401d5c92.entry.js} +1 -1
  84. package/dist/lime-elements/{p-6d2d25b9.entry.js → p-430db3b9.entry.js} +1 -1
  85. package/dist/lime-elements/{p-a6c6a31b.entry.js → p-43b62587.entry.js} +1 -1
  86. package/dist/lime-elements/{p-958396b5.entry.js → p-48dccb83.entry.js} +1 -1
  87. package/dist/lime-elements/{p-814b4934.entry.js → p-5c918155.entry.js} +1 -1
  88. package/dist/lime-elements/{p-22e9e327.entry.js → p-66101ed6.entry.js} +1 -1
  89. package/dist/lime-elements/{p-d8559847.entry.js → p-7ab72b52.entry.js} +1 -1
  90. package/dist/lime-elements/{p-7af83877.entry.js → p-8d9a2a22.entry.js} +1 -1
  91. package/dist/lime-elements/{p-55fa19ae.entry.js → p-8de4f0f3.entry.js} +1 -1
  92. package/dist/lime-elements/p-8e80a884.entry.js +56 -0
  93. package/dist/lime-elements/{p-bffb5ed2.entry.js → p-99984c66.entry.js} +1 -1
  94. package/dist/lime-elements/{p-56e2fa48.entry.js → p-9d46f720.entry.js} +1 -1
  95. package/dist/lime-elements/{p-68bbb8dd.entry.js → p-9e2b426c.entry.js} +1 -1
  96. package/dist/lime-elements/{p-Dzp8dXTo.js → p-C9dBa_Im.js} +1 -1
  97. package/dist/lime-elements/p-VamkUr90.js +1 -0
  98. package/dist/lime-elements/{p-3ac39bd5.entry.js → p-b1c7033b.entry.js} +2 -2
  99. package/dist/lime-elements/{p-47fe76a8.entry.js → p-b5451350.entry.js} +1 -1
  100. package/dist/lime-elements/{p-9edd79a8.entry.js → p-c75f3b0d.entry.js} +1 -1
  101. package/dist/lime-elements/{p-4c080cd9.entry.js → p-ca4247c4.entry.js} +1 -1
  102. package/dist/lime-elements/{p-1a7d1d2b.entry.js → p-d53421af.entry.js} +1 -1
  103. package/dist/lime-elements/{p-6d9b89db.entry.js → p-d8901e39.entry.js} +1 -1
  104. package/dist/lime-elements/{p-933ffaa8.entry.js → p-d89553b3.entry.js} +1 -1
  105. package/dist/lime-elements/{p-496b2437.entry.js → p-d93b8ce0.entry.js} +1 -1
  106. package/dist/lime-elements/{p-23067836.entry.js → p-e97340c4.entry.js} +1 -1
  107. package/dist/lime-elements/{p-7b87e547.entry.js → p-ec0c113d.entry.js} +1 -1
  108. package/dist/lime-elements/{p-9f0575fd.entry.js → p-f197000b.entry.js} +4 -4
  109. package/dist/lime-elements/{p-07f3565b.entry.js → p-f6bc6658.entry.js} +1 -1
  110. package/dist/lime-elements/{p-9b2623fe.entry.js → p-f71fbc9e.entry.js} +1 -1
  111. package/dist/lime-elements/{p-7fcd48c6.entry.js → p-fa1aa440.entry.js} +1 -1
  112. package/dist/types/components/chart/chart.d.ts +32 -7
  113. package/dist/types/components/chart/chart.types.d.ts +15 -1
  114. package/dist/types/components/chart/format.d.ts +54 -0
  115. package/dist/types/components/chart/options.d.ts +3 -4
  116. package/dist/types/components/chart/scale.d.ts +39 -7
  117. package/dist/types/components/form/filled-defaults.d.ts +12 -0
  118. package/dist/types/components/form/form.d.ts +17 -0
  119. package/dist/types/components/form/form.test-schemas.d.ts +2 -0
  120. package/dist/types/components/pagination/pagination.d.ts +6 -12
  121. package/dist/types/components.d.ts +51 -8
  122. package/dist/types/util/language.d.ts +19 -0
  123. package/package.json +3 -3
  124. package/dist/cjs/language-v-MMS6ym.js +0 -28
  125. package/dist/esm/language-ChagAaNf.js +0 -26
  126. package/dist/lime-elements/p-7d6a12fe.entry.js +0 -56
  127. package/dist/lime-elements/p-ChagAaNf.js +0 -1
@@ -0,0 +1,132 @@
1
+ import { isEmpty, isEqual, isPlainObject } from "lodash-es";
2
+ /**
3
+ * The value without the defaults that were filled into the value the form was
4
+ * given, as long as they still hold their default. A default the user changed
5
+ * stays, and so do the defaults of what the user added, such as a list item.
6
+ *
7
+ * @param value - the value the form holds, with the defaults filled in
8
+ * @param filled - the value the form was given, with the defaults filled in
9
+ * @param given - the value the form was given
10
+ * @returns the value without the defaults that were filled in
11
+ */
12
+ export function withoutFilledDefaults(value, filled, given) {
13
+ // A change can bring in objects that hold nothing, which mean nothing
14
+ if (isPlainObject(value)) {
15
+ return withoutFilledProperties(value, isPlainObject(filled) ? filled : {}, given);
16
+ }
17
+ if (Array.isArray(value)) {
18
+ return withoutFilledItems(value, Array.isArray(filled) ? filled : [], given);
19
+ }
20
+ return given === undefined && isEqual(value, filled) ? undefined : value;
21
+ }
22
+ function withoutFilledProperties(value, filled, given) {
23
+ const givenProperties = isPlainObject(given)
24
+ ? given
25
+ : {};
26
+ // In the order they were given, so a saved value keeps its key order
27
+ const keys = new Set([
28
+ ...Object.keys(givenProperties),
29
+ ...Object.keys(value),
30
+ ]);
31
+ const result = {};
32
+ for (const key of keys) {
33
+ if (!Object.hasOwn(value, key)) {
34
+ continue;
35
+ }
36
+ const kept = withoutFilledDefaults(value[key], filled[key], givenProperties[key]);
37
+ if (kept !== undefined) {
38
+ result[key] = kept;
39
+ }
40
+ }
41
+ return isEmpty(result) && given == null ? given : result;
42
+ }
43
+ // Items are paired with the ones the form was given by content, so a removed
44
+ // or moved item does not shift the others onto the defaults of their
45
+ // neighbors. An item that no longer equals any of them is paired with the one
46
+ // it has the most in common with, so an edited item still loses its defaults
47
+ function withoutFilledItems(items, filled, given) {
48
+ // A list that was not given is a default as a whole: once the user
49
+ // changes it, it is the user's
50
+ if (!Array.isArray(given)) {
51
+ return isEqual(items, filled) ? given : items;
52
+ }
53
+ const givenItems = given;
54
+ const matches = pairItems(items, filled);
55
+ const result = [];
56
+ for (const [index, item] of items.entries()) {
57
+ const match = matches.get(index);
58
+ if (match === undefined) {
59
+ result.push(item);
60
+ continue;
61
+ }
62
+ const kept = withoutFilledDefaults(item, filled[match], givenItems[match]);
63
+ if (kept !== undefined) {
64
+ result.push(kept);
65
+ }
66
+ }
67
+ return result;
68
+ }
69
+ function pairItems(items, filled) {
70
+ const matches = new Map();
71
+ const unmatched = new Set(filled.keys());
72
+ const pair = (index, match) => {
73
+ matches.set(index, match);
74
+ unmatched.delete(match);
75
+ };
76
+ for (const [index, item] of items.entries()) {
77
+ if (unmatched.has(index) && isEqual(item, filled[index])) {
78
+ pair(index, index);
79
+ }
80
+ }
81
+ for (const [index, item] of items.entries()) {
82
+ if (matches.has(index)) {
83
+ continue;
84
+ }
85
+ const same = [...unmatched].find((i) => isEqual(item, filled[i]));
86
+ if (same !== undefined) {
87
+ pair(index, same);
88
+ }
89
+ }
90
+ for (const [index, item] of items.entries()) {
91
+ if (matches.has(index)) {
92
+ continue;
93
+ }
94
+ const closest = findClosest(item, filled, unmatched);
95
+ if (closest !== undefined) {
96
+ pair(index, closest);
97
+ }
98
+ }
99
+ return matches;
100
+ }
101
+ // The one item that shares the most equal properties, if it shares any at
102
+ // all. When several share as many there is no telling which the item was, and
103
+ // it is left as it is, since a kept default means the same as a missing one
104
+ // while a lost value does not
105
+ function findClosest(item, filled, candidates) {
106
+ if (!isPlainObject(item)) {
107
+ return undefined;
108
+ }
109
+ let closest;
110
+ let best = 0;
111
+ let isTied = false;
112
+ for (const candidate of candidates) {
113
+ const score = sharedProperties(item, filled[candidate]);
114
+ if (score === best) {
115
+ isTied = true;
116
+ continue;
117
+ }
118
+ if (score < best) {
119
+ continue;
120
+ }
121
+ best = score;
122
+ closest = candidate;
123
+ isTied = false;
124
+ }
125
+ return isTied ? undefined : closest;
126
+ }
127
+ function sharedProperties(item, other) {
128
+ if (!isPlainObject(other)) {
129
+ return 0;
130
+ }
131
+ return Object.entries(item).filter(([key, value]) => isEqual(value, other[key])).length;
132
+ }
@@ -14,6 +14,7 @@ import { h, } from "@stencil/core";
14
14
  import React from "react";
15
15
  import { createRoot } from "react-dom/client";
16
16
  import JSONSchemaForm from "@rjsf/core";
17
+ import { getDefaultFormState, } from "@rjsf/utils";
17
18
  import { isHeadingLevel } from "../../util/heading-level";
18
19
  import { ArrayFieldTemplate, ArrayFieldItemTemplate, FieldTemplate, ObjectFieldTemplate, } from "./templates";
19
20
  import { SchemaField as CustomSchemaField } from "./fields/schema-field";
@@ -23,7 +24,17 @@ import { widgets } from "./widgets";
23
24
  import { rjsfValidator } from "./validator";
24
25
  import { isEqual, mapValues } from "lodash-es";
25
26
  import { showField, stopShowingField } from "./show-field";
27
+ import { withoutFilledDefaults } from "./filled-defaults";
26
28
  import { HeadingLevelContext } from "./templates/heading-level";
29
+ // `@rjsf/core` v6 treats a `const` inside `oneOf`/`anyOf` as a default and
30
+ // auto-selects the first option, so an optional enum can never be left empty
31
+ // (clearing it just gets repopulated on the next render). `skipOneOf` keeps this
32
+ // off for enums while still applying genuine `default` values, matching the
33
+ // pre-v6 behavior.
34
+ const FILL_DEFAULTS = {
35
+ constAsDefaults: 'skipOneOf',
36
+ requiredBooleanDefault: 'skip',
37
+ };
27
38
  /**
28
39
  * @exampleComponent limel-example-form
29
40
  * @exampleComponent limel-example-nested-form
@@ -44,6 +55,7 @@ import { HeadingLevelContext } from "./templates/heading-level";
44
55
  * @exampleComponent limel-example-code-editor-form
45
56
  * @exampleComponent limel-example-form-highlighted-field
46
57
  * @exampleComponent limel-example-form-heading-level
58
+ * @exampleComponent limel-example-form-include-defaults
47
59
  */
48
60
  export class Form {
49
61
  constructor() {
@@ -73,6 +85,18 @@ export class Form {
73
85
  * which keeps untouched required-empty fields silent.
74
86
  */
75
87
  this.revealErrors = false;
88
+ /**
89
+ * Set to `false` to leave the defaults of the schema out of the value,
90
+ * so that it stays as it was given until the user changes something. The
91
+ * form still shows the defaults. A default the user changes is in the
92
+ * value from then on, and so are the defaults that a change brings in,
93
+ * such as those of a new list item or of fields that depend on the
94
+ * changed one. Pass the value the form emits back in as `value`.
95
+ * The form validates what it shows, defaults included. When the user
96
+ * changes everything back, the value is what the form was given, also
97
+ * when that is `null` or `undefined`.
98
+ */
99
+ this.includeDefaults = true;
76
100
  this.isValid = true;
77
101
  this.initialized = false;
78
102
  this.handleChange = this.handleChange.bind(this);
@@ -82,8 +106,17 @@ export class Form {
82
106
  this.initialize();
83
107
  }
84
108
  componentWillLoad() {
109
+ this.currentValue = this.value;
85
110
  this.warnIfHeadingLevelIsInvalid();
86
111
  }
112
+ handleValueChange() {
113
+ // The host usually hands back the value the form emitted, as a new
114
+ // object, which is not a new value to leave the defaults out of
115
+ if (!isEqual(this.value, this.currentValue)) {
116
+ this.givenValue = undefined;
117
+ }
118
+ this.currentValue = this.value;
119
+ }
87
120
  componentDidLoad() {
88
121
  this.initialize();
89
122
  this.showHighlightedField();
@@ -125,7 +158,7 @@ export class Form {
125
158
  this.initialized = false;
126
159
  }
127
160
  render() {
128
- return h("div", { key: '549ba8cd825aadedc4ec9e696f6d03bee028cb89', class: "root" });
161
+ return h("div", { key: 'a50619f8a46a7e3b3ca5ade698141f22cfdd704f', class: "root" });
129
162
  }
130
163
  reactRender() {
131
164
  if (!this.root) {
@@ -138,21 +171,12 @@ export class Form {
138
171
  : 1,
139
172
  }, React.createElement(JSONSchemaForm, {
140
173
  schema: this.prepareSchema(this.schema),
141
- formData: this.value,
174
+ formData: this.currentValue,
142
175
  onChange: this.handleChange,
143
176
  widgets: widgets,
144
177
  validator: rjsfValidator,
145
178
  liveValidate: 'onChange',
146
- // `@rjsf/core` v6 treats a `const` inside `oneOf`/`anyOf`
147
- // as a default and auto-selects the first option, so an
148
- // optional enum can never be left empty (clearing it just
149
- // gets repopulated on the next render). `skipOneOf` keeps
150
- // this off for enums while still applying genuine
151
- // `default` values, matching the pre-v6 behavior.
152
- experimental_defaultFormStateBehavior: {
153
- constAsDefaults: 'skipOneOf',
154
- requiredBooleanDefault: 'skip',
155
- },
179
+ experimental_defaultFormStateBehavior: FILL_DEFAULTS,
156
180
  showErrorList: false,
157
181
  extraErrors: this.getExtraErrors(this.errors),
158
182
  templates: {
@@ -186,11 +210,42 @@ export class Form {
186
210
  return this.host.shadowRoot.querySelector('.root');
187
211
  }
188
212
  handleChange(event) {
189
- this.change.emit(event.formData);
213
+ if (this.includeDefaults) {
214
+ this.currentValue = event.formData;
215
+ this.change.emit(event.formData);
216
+ return;
217
+ }
218
+ const { given, filled } = this.getGivenValue();
219
+ this.givenValue.held = event.formData;
220
+ const value = withoutFilledDefaults(event.formData, filled, given);
221
+ if (isEqual(value, this.currentValue)) {
222
+ // What the form holds changed, even though the value did not
223
+ this.emitValidationStatus(event.errors);
224
+ return;
225
+ }
226
+ this.currentValue = value;
227
+ this.change.emit(this.currentValue);
190
228
  }
191
- validateFormData() {
229
+ getGivenValue() {
192
230
  var _a;
193
- const { errors } = rjsfValidator.validateFormData((_a = this.value) !== null && _a !== void 0 ? _a : {}, this.prepareSchema(this.schema));
231
+ const schema = this.prepareSchema(this.schema);
232
+ if (((_a = this.givenValue) === null || _a === void 0 ? void 0 : _a.schemaId) !== schema.$id) {
233
+ const filled = getDefaultFormState(rjsfValidator, schema, this.currentValue, schema, false, FILL_DEFAULTS);
234
+ this.givenValue = {
235
+ schemaId: schema.$id,
236
+ given: this.currentValue,
237
+ filled,
238
+ held: filled,
239
+ };
240
+ }
241
+ return this.givenValue;
242
+ }
243
+ validateFormData() {
244
+ // With the defaults left out of the value, the form holds more than it
245
+ const value = this.includeDefaults
246
+ ? this.value
247
+ : this.getGivenValue().held;
248
+ const { errors } = rjsfValidator.validateFormData(value !== null && value !== void 0 ? value : {}, this.prepareSchema(this.schema));
194
249
  this.emitValidationStatus(errors);
195
250
  }
196
251
  /**
@@ -465,6 +520,26 @@ export class Form {
465
520
  "attribute": "reveal-errors",
466
521
  "defaultValue": "false"
467
522
  },
523
+ "includeDefaults": {
524
+ "type": "boolean",
525
+ "mutable": false,
526
+ "complexType": {
527
+ "original": "boolean",
528
+ "resolved": "boolean",
529
+ "references": {}
530
+ },
531
+ "required": false,
532
+ "optional": false,
533
+ "docs": {
534
+ "tags": [],
535
+ "text": "Set to `false` to leave the defaults of the schema out of the value,\nso that it stays as it was given until the user changes something. The\nform still shows the defaults. A default the user changes is in the\nvalue from then on, and so are the defaults that a change brings in,\nsuch as those of a new list item or of fields that depend on the\nchanged one. Pass the value the form emits back in as `value`.\nThe form validates what it shows, defaults included. When the user\nchanges everything back, the value is what the form was given, also\nwhen that is `null` or `undefined`."
536
+ },
537
+ "getter": false,
538
+ "setter": false,
539
+ "reflect": false,
540
+ "attribute": "include-defaults",
541
+ "defaultValue": "true"
542
+ },
468
543
  "highlightedField": {
469
544
  "type": "unknown",
470
545
  "mutable": false,
@@ -535,6 +610,9 @@ export class Form {
535
610
  static get elementRef() { return "host"; }
536
611
  static get watchers() {
537
612
  return [{
613
+ "propName": "value",
614
+ "methodName": "handleValueChange"
615
+ }, {
538
616
  "propName": "headingLevel",
539
617
  "methodName": "handleHeadingLevelChange"
540
618
  }, {
@@ -896,3 +896,53 @@ export const untitledRowSchema = {
896
896
  },
897
897
  },
898
898
  };
899
+ export const dependencyWithDefaultsSchema = {
900
+ type: 'object',
901
+ properties: {
902
+ columns: { type: 'integer', title: 'Columns', default: 5 },
903
+ limetype: { type: 'string', title: 'Limetype' },
904
+ },
905
+ dependencies: {
906
+ limetype: {
907
+ properties: {
908
+ propertyName: {
909
+ type: 'string',
910
+ title: 'Name property',
911
+ default: 'name',
912
+ },
913
+ },
914
+ },
915
+ },
916
+ };
917
+ export const dependencyWithChangingDefaultSchema = {
918
+ type: 'object',
919
+ properties: {
920
+ limetype: { type: 'string', title: 'Limetype' },
921
+ },
922
+ dependencies: {
923
+ limetype: {
924
+ oneOf: [
925
+ {
926
+ properties: {
927
+ limetype: { const: 'person' },
928
+ propertyName: {
929
+ type: 'string',
930
+ title: 'Name property',
931
+ default: 'name',
932
+ },
933
+ },
934
+ },
935
+ {
936
+ properties: {
937
+ limetype: { const: 'company' },
938
+ propertyName: {
939
+ type: 'string',
940
+ title: 'Name property',
941
+ default: 'companyName',
942
+ },
943
+ },
944
+ },
945
+ ],
946
+ },
947
+ },
948
+ };
@@ -1,7 +1,7 @@
1
1
  import { h, Host, } from "@stencil/core";
2
2
  import translate from "../../global/translations";
3
3
  import { createRandomString } from "../../util/random-string";
4
- import { getPrimarySubtag } from "../../util/language";
4
+ import { getSupportedLocale } from "../../util/language";
5
5
  import { getPageSlots } from "./pagination.util";
6
6
  const FIRST_PAGE = 1;
7
7
  const DEFAULT_PAGE_SIZE = 100;
@@ -304,7 +304,7 @@ export class Pagination {
304
304
  }
305
305
  render() {
306
306
  const { slots } = this.view;
307
- return (h(Host, { key: '924becb588f7d773572b61865b9dd79b14171153' }, h("nav", { key: 'f517b62cf0107c912d576f08e9d99594f868be44', "aria-label": this.translate('pagination.label'), "aria-busy": this.loading ? 'true' : null }, this.renderArrow('previous'), slots.map((slot, index) => this.renderSlot(slot, index)), this.renderArrow('next')), h("span", { key: '21758520849acfe32f43e86570fe60a040cf2748', class: "live-region", "aria-live": "polite" }, this.liveMessage)));
307
+ return (h(Host, { key: '7c47cdc658859b4cd8199ef92ebd9bc48275a8ae' }, h("nav", { key: '3bba45547a7183a4b1df58294a56788f9b2e078f', "aria-label": this.translate('pagination.label'), "aria-busy": this.loading ? 'true' : null }, this.renderArrow('previous'), slots.map((slot, index) => this.renderSlot(slot, index)), this.renderArrow('next')), h("span", { key: '60fff33d8e135b1605d0a0f68b6c1ede1b571281', class: "live-region", "aria-live": "polite" }, this.liveMessage)));
308
308
  }
309
309
  /**
310
310
  * Without a count we know where the user is but not how far the set goes,
@@ -620,9 +620,7 @@ export class Pagination {
620
620
  }
621
621
  /**
622
622
  * What the jump form is given, so that the one warning about a language
623
- * this browser cannot write numbers in describes both of us. A tag it
624
- * accepts but does not support, `zz`, resolves to the viewer's own locale
625
- * rather than throwing, so asking the formatter is the only way to know.
623
+ * this browser cannot write numbers in describes both of us.
626
624
  */
627
625
  get languageForNumbers() {
628
626
  var _a;
@@ -630,31 +628,21 @@ export class Pagination {
630
628
  return this.settledLanguage;
631
629
  }
632
630
  /**
633
- * `Intl.NumberFormat` throws on a language it cannot parse, and this is
634
- * called from `render`, so an unusable one would leave the control drawing
635
- * nothing at all — the single state a user cannot click their way out of.
636
- * `src/util/language.ts` states the rule this keeps.
637
- *
638
- * A tag it cannot parse throws; a well-formed tag it does not support, like
639
- * `zz`, does not — it quietly resolves to whatever locale the machine runs
640
- * in. Both end up formatting numbers in something other than what was
641
- * asked for, so both are worth saying out loud.
631
+ * This is called from `render`, so a language that `Intl` cannot write
632
+ * numbers in must not throw, or the control would draw nothing at all —
633
+ * the single state a user cannot click their way out of.
634
+ * `getSupportedLocale` in `src/util/language.ts` decides which languages
635
+ * those are.
642
636
  *
643
637
  * @returns a formatter, in the given language where that is possible
644
638
  */
645
639
  createNumberFormat() {
646
640
  const { language } = this;
647
- try {
648
- const format = new Intl.NumberFormat(language);
649
- const resolved = format.resolvedOptions().locale;
650
- if (getPrimarySubtag(resolved) === getPrimarySubtag(language)) {
651
- this.warnedAbout.delete('language');
652
- this.settledLanguage = language;
653
- return format;
654
- }
655
- }
656
- catch (_a) {
657
- // Fall through to the warning below.
641
+ const locale = getSupportedLocale(language);
642
+ if (locale) {
643
+ this.warnedAbout.delete('language');
644
+ this.settledLanguage = language;
645
+ return new Intl.NumberFormat(locale);
658
646
  }
659
647
  this.warnOnce('language', language, () => `\`language\` must be one this browser can write numbers in, but was ${JSON.stringify(language)}. Using ${FALLBACK_LANGUAGE}.`);
660
648
  // Where the translations land for the same unusable value, rather than
@@ -22,3 +22,32 @@ export function getPrimarySubtag(language) {
22
22
  }
23
23
  return language.toLowerCase().split('-', 1)[0];
24
24
  }
25
+ /**
26
+ * The locale that `Intl` writes numbers and dates in for `language`, or
27
+ * `undefined` when it cannot write in that language. `Intl` throws on a
28
+ * tag it cannot read, such as `sv_SE`, and quietly uses the viewer's own
29
+ * locale for one it does not know, such as `zz`. A component that writes in
30
+ * its `language` while it renders checks it here, and falls back to English
31
+ * when this gives `undefined`.
32
+ *
33
+ * Examples:
34
+ * - "sv" => "sv"
35
+ * - "SV-se" => "sv-SE"
36
+ * - "sv_SE" => undefined
37
+ * - "zz" => undefined
38
+ * - undefined => undefined
39
+ *
40
+ * @param language - the language to write in
41
+ * @returns the locale, or `undefined`
42
+ */
43
+ export function getSupportedLocale(language) {
44
+ if (typeof language !== 'string') {
45
+ return;
46
+ }
47
+ try {
48
+ return Intl.NumberFormat.supportedLocalesOf(language)[0];
49
+ }
50
+ catch (_a) {
51
+ return;
52
+ }
53
+ }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Reduce a language to the primary subtag that our language maps are keyed by.
3
+ *
4
+ * A `language` prop is typed, but a custom element takes whatever string an
5
+ * attribute carries — commonly a full BCP 47 tag such as `nb-NO`, since a host
6
+ * application often derives the language from `document.documentElement.lang`.
7
+ * Anything that is not a string must resolve rather than throw, so that an
8
+ * unexpected value can never break a component's render.
9
+ *
10
+ * Examples:
11
+ * - "nb" => "nb"
12
+ * - "nb-NO" => "nb"
13
+ * - "SV-SE" => "sv"
14
+ * - undefined => ""
15
+ *
16
+ * @param language - the language to reduce
17
+ * @returns the lower-cased primary subtag, or an empty string
18
+ */
19
+ function getPrimarySubtag(language) {
20
+ if (typeof language !== 'string') {
21
+ return '';
22
+ }
23
+ return language.toLowerCase().split('-', 1)[0];
24
+ }
25
+ /**
26
+ * The locale that `Intl` writes numbers and dates in for `language`, or
27
+ * `undefined` when it cannot write in that language. `Intl` throws on a
28
+ * tag it cannot read, such as `sv_SE`, and quietly uses the viewer's own
29
+ * locale for one it does not know, such as `zz`. A component that writes in
30
+ * its `language` while it renders checks it here, and falls back to English
31
+ * when this gives `undefined`.
32
+ *
33
+ * Examples:
34
+ * - "sv" => "sv"
35
+ * - "SV-se" => "sv-SE"
36
+ * - "sv_SE" => undefined
37
+ * - "zz" => undefined
38
+ * - undefined => undefined
39
+ *
40
+ * @param language - the language to write in
41
+ * @returns the locale, or `undefined`
42
+ */
43
+ function getSupportedLocale(language) {
44
+ if (typeof language !== 'string') {
45
+ return;
46
+ }
47
+ try {
48
+ return Intl.NumberFormat.supportedLocalesOf(language)[0];
49
+ }
50
+ catch (_a) {
51
+ return;
52
+ }
53
+ }
54
+
55
+ export { getPrimarySubtag as a, getSupportedLocale as g };