@oicl/openbridge-webcomponents-full-bundle 2.0.0-next.124 → 2.0.0-next.125

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 (40) hide show
  1. package/bundle/openbridge-webcomponents.bundle.js +72 -15
  2. package/bundle/openbridge-webcomponents.bundle.js.map +1 -1
  3. package/custom-elements.json +19 -0
  4. package/dist/components/keyboard-full/keyboard-full.d.ts +5 -0
  5. package/dist/components/keyboard-full/keyboard-full.d.ts.map +1 -1
  6. package/dist/components/keyboard-full/keyboard-full.js +15 -8
  7. package/dist/components/keyboard-full/keyboard-full.js.map +1 -1
  8. package/dist/components/number-input-field/number-input-field.css.js +19 -0
  9. package/dist/components/number-input-field/number-input-field.css.js.map +1 -1
  10. package/dist/components/number-input-field/number-input-field.d.ts.map +1 -1
  11. package/dist/components/number-input-field/number-input-field.js +3 -0
  12. package/dist/components/number-input-field/number-input-field.js.map +1 -1
  13. package/dist/components/text-input-field/text-input-field.css.js +19 -0
  14. package/dist/components/text-input-field/text-input-field.css.js.map +1 -1
  15. package/dist/components/text-input-field/text-input-field.d.ts.map +1 -1
  16. package/dist/components/text-input-field/text-input-field.js +2 -1
  17. package/dist/components/text-input-field/text-input-field.js.map +1 -1
  18. package/dist/navigation-instruments/bearing-indicator/bearing-indicator.css.js +6 -2
  19. package/dist/navigation-instruments/bearing-indicator/bearing-indicator.css.js.map +1 -1
  20. package/dist/navigation-instruments/compass-indicator/compass-indicator.css.js +6 -2
  21. package/dist/navigation-instruments/compass-indicator/compass-indicator.css.js.map +1 -1
  22. package/dist/navigation-instruments/gauge-horizontal/gauge-horizontal.d.ts.map +1 -1
  23. package/dist/navigation-instruments/gauge-horizontal/gauge-horizontal.js +1 -1
  24. package/dist/navigation-instruments/gauge-horizontal/gauge-horizontal.js.map +1 -1
  25. package/dist/navigation-instruments/gauge-vertical/gauge-vertical.d.ts.map +1 -1
  26. package/dist/navigation-instruments/gauge-vertical/gauge-vertical.js +1 -1
  27. package/dist/navigation-instruments/gauge-vertical/gauge-vertical.js.map +1 -1
  28. package/package.json +1 -1
  29. package/src/components/keyboard-full/keyboard-full.spec.ts +132 -0
  30. package/src/components/keyboard-full/keyboard-full.ts +16 -14
  31. package/src/components/number-input-field/number-input-field.spec.ts +37 -0
  32. package/src/components/number-input-field/number-input-field.stories.ts +23 -0
  33. package/src/components/number-input-field/number-input-field.ts +5 -0
  34. package/src/components/text-input-field/text-input-field.spec.ts +29 -0
  35. package/src/components/text-input-field/text-input-field.ts +5 -1
  36. package/src/mixins/base-input-field.css +18 -0
  37. package/src/navigation-instruments/bearing-indicator/bearing-indicator.css +3 -0
  38. package/src/navigation-instruments/compass-indicator/compass-indicator.css +3 -0
  39. package/src/navigation-instruments/gauge-horizontal/gauge-horizontal.ts +3 -1
  40. package/src/navigation-instruments/gauge-vertical/gauge-vertical.ts +3 -1
@@ -352,4 +352,41 @@ describe('obc-number-input-field', () => {
352
352
  expect(event.defaultPrevented).toBe(false);
353
353
  });
354
354
  });
355
+
356
+ describe('readonly', () => {
357
+ beforeEach(async () => {
358
+ el.groupSeparator = ' ';
359
+ el.decimalSeparator = '.';
360
+ el.value = 1234.5;
361
+ el.readonly = true;
362
+ await el.updateComplete;
363
+ });
364
+
365
+ it('marks the native input readonly', () => {
366
+ expect(input.readOnly).toBe(true);
367
+ });
368
+
369
+ it('flags the wrapper so the hover and pressed states are suppressed', () => {
370
+ const wrapper = el.shadowRoot!.querySelector('.wrapper') as HTMLElement;
371
+ expect(wrapper.classList.contains('readonly')).toBe(true);
372
+ });
373
+
374
+ it('keeps the grouped display on focus', async () => {
375
+ const before = input.value;
376
+ input.focus();
377
+ await el.updateComplete;
378
+
379
+ expect(input.value).toBe(before);
380
+ expect(input.value).toContain(' ');
381
+ });
382
+
383
+ it('keeps its value across a focus/blur round trip', async () => {
384
+ input.focus();
385
+ await el.updateComplete;
386
+ input.blur();
387
+ await el.updateComplete;
388
+
389
+ expect(el.value).toBe(1234.5);
390
+ });
391
+ });
355
392
  });
@@ -38,6 +38,11 @@ const meta: Meta<typeof ObcNumberInputField> = {
38
38
  control: {type: 'boolean'},
39
39
  description: 'Disables the input field',
40
40
  },
41
+ readonly: {
42
+ control: {type: 'boolean'},
43
+ description:
44
+ 'Makes the value selectable and copyable but not editable, and removes the hover and pressed states',
45
+ },
41
46
  error: {
42
47
  control: {type: 'boolean'},
43
48
  description: 'Displays error styling and sets aria-invalid',
@@ -105,6 +110,7 @@ const meta: Meta<typeof ObcNumberInputField> = {
105
110
  .textAlign=${args.textAlign ?? ObcNumberInputFieldTextAlign.Right}
106
111
  .size=${args.size ?? ObcNumberInputFieldSize.Regular}
107
112
  ?disabled=${args.disabled}
113
+ ?readonly=${args.readonly}
108
114
  ?error=${args.error}
109
115
  .errorText=${args.errorText ?? ''}
110
116
  ?hasLeadingIcon=${args.hasLeadingIcon}
@@ -352,6 +358,23 @@ export const Disabled: Story = {
352
358
  },
353
359
  };
354
360
 
361
+ export const Readonly: Story = {
362
+ args: {
363
+ value: 50,
364
+ unit: '%',
365
+ label: 'Throttle Position',
366
+ readonly: true,
367
+ },
368
+ parameters: {
369
+ docs: {
370
+ description: {
371
+ story:
372
+ 'Read-only fields allow selection and copying but prevent editing.',
373
+ },
374
+ },
375
+ },
376
+ };
377
+
355
378
  export const Error: Story = {
356
379
  args: {
357
380
  value: 999,
@@ -204,6 +204,9 @@ export class ObcNumberInputField extends LitElement {
204
204
 
205
205
  private onFocus() {
206
206
  this.hasFocus = true;
207
+ // A read-only field has nothing to edit, so it keeps its formatted display
208
+ // instead of switching to the ungrouped editing representation.
209
+ if (this.readonly) return;
207
210
  const source = this.displayOverride || this.displayText;
208
211
  this.displayText = removeGroupingFromDisplay(
209
212
  source,
@@ -214,6 +217,7 @@ export class ObcNumberInputField extends LitElement {
214
217
 
215
218
  private onBlur() {
216
219
  this.hasFocus = false;
220
+ if (this.readonly) return;
217
221
  this.commitDisplay();
218
222
  if (!valuesEqual(this.value, this.lastCommittedValue)) {
219
223
  this.lastCommittedValue = this.value;
@@ -443,6 +447,7 @@ export class ObcNumberInputField extends LitElement {
443
447
  [`size-${this.size}`]: true,
444
448
  error: this.error,
445
449
  disabled: this.disabled,
450
+ readonly: this.readonly,
446
451
  empty: this.isEmpty,
447
452
  helpertext: hasHelperOrError,
448
453
  haslabel: Boolean(this.label),
@@ -263,5 +263,34 @@ describe('obc-text-input-field', () => {
263
263
  expect(input.value).toBe('');
264
264
  expect(el.value).toBe('');
265
265
  });
266
+
267
+ it('is hidden when readonly, since clearing is an edit', async () => {
268
+ el.readonly = true;
269
+ await el.updateComplete;
270
+
271
+ expect(el.shadowRoot!.querySelector('.trailing-icon-button')).toBeNull();
272
+ });
273
+ });
274
+
275
+ describe('readonly', () => {
276
+ beforeEach(async () => {
277
+ el.readonly = true;
278
+ await el.updateComplete;
279
+ });
280
+
281
+ it('marks the native input readonly', () => {
282
+ expect(input.readOnly).toBe(true);
283
+ });
284
+
285
+ it('flags the wrapper so the hover and pressed states are suppressed', () => {
286
+ const wrapper = el.shadowRoot!.querySelector('.wrapper') as HTMLElement;
287
+ expect(wrapper.classList.contains('readonly')).toBe(true);
288
+ });
289
+
290
+ it('stays focusable so the value can be read and copied', () => {
291
+ input.focus();
292
+
293
+ expect(el.shadowRoot!.activeElement).toBe(input);
294
+ });
266
295
  });
267
296
  });
@@ -246,7 +246,10 @@ export class ObcTextInputField extends LitElement {
246
246
  const hasHelperOrError =
247
247
  Boolean(this.helperText) || Boolean(this.error && this.errorText);
248
248
  const showClearButton =
249
- this.hasClearButton && this.value.length > 0 && !this.disabled;
249
+ this.hasClearButton &&
250
+ this.value.length > 0 &&
251
+ !this.disabled &&
252
+ !this.readonly;
250
253
  const isPasswordField = this.type === HTMLInputTypeAttribute.Password;
251
254
  const showPasswordToggle = isPasswordField && !this.disabled;
252
255
  const isClearButtonVisible = showClearButton && !showPasswordToggle;
@@ -272,6 +275,7 @@ export class ObcTextInputField extends LitElement {
272
275
  [`size-${this.size}`]: true,
273
276
  error: this.error,
274
277
  disabled: this.disabled,
278
+ readonly: this.readonly,
275
279
  empty: this.isEmpty,
276
280
  helpertext: hasHelperOrError,
277
281
  haslabel: Boolean(this.label),
@@ -40,6 +40,20 @@
40
40
  }
41
41
  }
42
42
 
43
+ /* A read-only field is still focusable and selectable, but it accepts no
44
+ edits — so it must not advertise the hover/pressed affordances that
45
+ `@mixin style` renders. Zeroing --obc-can-hover makes the mixin's hover
46
+ colour-mix collapse back onto the enabled colours; the pressed state has
47
+ no such switch and is restored explicitly. */
48
+ &.readonly {
49
+ --obc-can-hover: 0;
50
+ }
51
+
52
+ &.readonly:not(.disabled):active .input-field-container {
53
+ border-color: var(--normal-enabled-border-color);
54
+ background: var(--normal-enabled-background-color);
55
+ }
56
+
43
57
  &.helpertext,
44
58
  &.haslabel {
45
59
  flex-direction: column;
@@ -51,6 +65,10 @@
51
65
  background: var(--container-background-color);
52
66
  }
53
67
 
68
+ &.readonly.empty:not(.disabled):active .input-field-container {
69
+ background: var(--container-background-color);
70
+ }
71
+
54
72
  &.empty:not(.disabled):focus-within .input-field-container {
55
73
  background: var(--normal-enabled-background-color);
56
74
  }
@@ -0,0 +1,3 @@
1
+ svg {
2
+ display: block;
3
+ }
@@ -0,0 +1,3 @@
1
+ svg {
2
+ display: block;
3
+ }
@@ -327,7 +327,9 @@ export class ObcGaugeHorizontal extends SetpointMixin(LitElement, {
327
327
  height=${this.fixedAspectRatio ? '100%' : `${viewBox.height}px`}
328
328
  viewBox="${viewBox.x} ${viewBox.y} ${viewBox.width} ${viewBox.height}"
329
329
  preserveAspectRatio="${preserveAspectRatio}"
330
- style="--scale: ${this.fixedAspectRatio ? this._scale : 1};"
330
+ style="--scale: ${this.fixedAspectRatio
331
+ ? this._scale
332
+ : 1}; display: block;"
331
333
  part="svg"
332
334
  >
333
335
  ${parts.barContainer} ${parts.barFill} ${parts.scaleBackground}
@@ -327,7 +327,9 @@ export class ObcGaugeVertical extends SetpointMixin(LitElement, {
327
327
  height=${this.fixedAspectRatio ? '100%' : `${this.height}px`}
328
328
  viewBox="${viewBox.x} ${viewBox.y} ${viewBox.width} ${viewBox.height}"
329
329
  preserveAspectRatio="${preserveAspectRatio}"
330
- style="--scale: ${this.fixedAspectRatio ? this._scale : 1};"
330
+ style="--scale: ${this.fixedAspectRatio
331
+ ? this._scale
332
+ : 1}; display: block;"
331
333
  part="svg"
332
334
  >
333
335
  ${parts.barContainer} ${parts.barFill} ${parts.scaleBackground}