@synergy-design-system/mcp 2.6.1 → 2.8.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 (78) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/dist/utilities/storybook/scraper.js +14 -3
  3. package/metadata/checksum.txt +1 -1
  4. package/metadata/packages/components/components/syn-alert/component.styles.ts +126 -26
  5. package/metadata/packages/components/components/syn-alert/component.ts +1 -2
  6. package/metadata/packages/components/components/syn-checkbox/component.angular.ts +13 -0
  7. package/metadata/packages/components/components/syn-checkbox/component.styles.ts +99 -39
  8. package/metadata/packages/components/components/syn-checkbox/component.ts +13 -10
  9. package/metadata/packages/components/components/syn-checkbox/component.vue +5 -0
  10. package/metadata/packages/components/components/syn-combobox/component.angular.ts +13 -0
  11. package/metadata/packages/components/components/syn-combobox/component.styles.ts +216 -193
  12. package/metadata/packages/components/components/syn-combobox/component.ts +68 -39
  13. package/metadata/packages/components/components/syn-combobox/component.vue +5 -0
  14. package/metadata/packages/components/components/syn-file/component.angular.ts +13 -0
  15. package/metadata/packages/components/components/syn-file/component.styles.ts +20 -3
  16. package/metadata/packages/components/components/syn-file/component.ts +19 -5
  17. package/metadata/packages/components/components/syn-file/component.vue +5 -0
  18. package/metadata/packages/components/components/syn-input/component.ts +1 -2
  19. package/metadata/packages/components/components/syn-popup/component.styles.ts +24 -17
  20. package/metadata/packages/components/components/syn-popup/component.ts +1 -2
  21. package/metadata/packages/components/components/syn-radio/component.angular.ts +13 -0
  22. package/metadata/packages/components/components/syn-radio/component.styles.ts +91 -29
  23. package/metadata/packages/components/components/syn-radio/component.ts +19 -10
  24. package/metadata/packages/components/components/syn-radio/component.vue +5 -0
  25. package/metadata/packages/components/components/syn-radio-group/component.styles.ts +30 -9
  26. package/metadata/packages/components/components/syn-radio-group/component.ts +61 -32
  27. package/metadata/packages/components/components/syn-range/component.angular.ts +13 -0
  28. package/metadata/packages/components/components/syn-range/component.styles.ts +27 -3
  29. package/metadata/packages/components/components/syn-range/component.ts +17 -5
  30. package/metadata/packages/components/components/syn-range/component.vue +5 -0
  31. package/metadata/packages/components/components/syn-select/component.angular.ts +13 -0
  32. package/metadata/packages/components/components/syn-select/component.styles.ts +222 -151
  33. package/metadata/packages/components/components/syn-select/component.ts +30 -15
  34. package/metadata/packages/components/components/syn-select/component.vue +5 -0
  35. package/metadata/packages/components/components/syn-switch/component.angular.ts +13 -0
  36. package/metadata/packages/components/components/syn-switch/component.styles.ts +145 -63
  37. package/metadata/packages/components/components/syn-switch/component.ts +16 -4
  38. package/metadata/packages/components/components/syn-switch/component.vue +5 -0
  39. package/metadata/packages/components/components/syn-textarea/component.styles.ts +55 -27
  40. package/metadata/packages/components/components/syn-textarea/component.ts +1 -3
  41. package/metadata/packages/components/components/syn-tooltip/component.styles.ts +15 -10
  42. package/metadata/packages/components/components/syn-tooltip/component.ts +13 -5
  43. package/metadata/packages/components/components/syn-validate/component.angular.ts +9 -0
  44. package/metadata/packages/components/components/syn-validate/component.react.ts +8 -0
  45. package/metadata/packages/components/components/syn-validate/component.ts +106 -8
  46. package/metadata/packages/components/components/syn-validate/component.vue +9 -0
  47. package/metadata/packages/components/static/CHANGELOG.md +43 -0
  48. package/metadata/packages/tokens/CHANGELOG.md +33 -0
  49. package/metadata/packages/tokens/dark.css +7 -1
  50. package/metadata/packages/tokens/index.js +31 -1
  51. package/metadata/packages/tokens/light.css +7 -1
  52. package/metadata/packages/tokens/sick2018_dark.css +7 -1
  53. package/metadata/packages/tokens/sick2018_light.css +7 -1
  54. package/metadata/packages/tokens/sick2025_dark.css +7 -1
  55. package/metadata/packages/tokens/sick2025_light.css +7 -1
  56. package/metadata/static/components/syn-checkbox/docs.md +36 -0
  57. package/metadata/static/components/syn-combobox/docs.md +138 -0
  58. package/metadata/static/components/syn-file/docs.md +24 -0
  59. package/metadata/static/components/syn-input/docs.md +1 -1
  60. package/metadata/static/components/syn-radio/docs.md +21 -0
  61. package/metadata/static/components/syn-radio-group/docs.md +46 -0
  62. package/metadata/static/components/syn-range/docs.md +19 -0
  63. package/metadata/static/components/syn-select/docs.md +81 -0
  64. package/metadata/static/components/syn-switch/docs.md +22 -0
  65. package/metadata/static/components/syn-textarea/docs.md +1 -1
  66. package/metadata/static/components/syn-tooltip/docs.md +73 -0
  67. package/metadata/static/components/syn-validate/docs.md +33 -6
  68. package/package.json +4 -4
  69. package/metadata/packages/components/components/syn-alert/component.custom.styles.ts +0 -136
  70. package/metadata/packages/components/components/syn-checkbox/component.custom.styles.ts +0 -86
  71. package/metadata/packages/components/components/syn-combobox/component.custom.styles.ts +0 -122
  72. package/metadata/packages/components/components/syn-popup/component.custom.styles.ts +0 -18
  73. package/metadata/packages/components/components/syn-radio/component.custom.styles.ts +0 -86
  74. package/metadata/packages/components/components/syn-radio-group/component.custom.styles.ts +0 -25
  75. package/metadata/packages/components/components/syn-select/component.custom.styles.ts +0 -175
  76. package/metadata/packages/components/components/syn-switch/component.custom.styles.ts +0 -141
  77. package/metadata/packages/components/components/syn-textarea/component.custom.styles.ts +0 -48
  78. package/metadata/packages/components/components/syn-tooltip/component.custom.styles.ts +0 -13
@@ -1,3 +1,4 @@
1
+ /* eslint-disable lit-a11y/click-events-have-key-events */
1
2
  /* eslint-disable no-param-reassign */
2
3
  /* eslint-disable no-underscore-dangle */
3
4
  import type { CSSResultGroup, PropertyValues, TemplateResult } from 'lit';
@@ -14,7 +15,6 @@ import { waitForEvent } from '../../internal/event.js';
14
15
  import { watch } from '../../internal/watch.js';
15
16
  import componentStyles from '../../styles/component.styles.js';
16
17
  import formControlStyles from '../../styles/form-control.styles.js';
17
- import formControlCustomStyles from '../../styles/form-control.custom.styles.js';
18
18
  import SynergyElement from '../../internal/synergy-element.js';
19
19
  import SynIcon from '../icon/icon.component.js';
20
20
  import SynPopup from '../popup/popup.component.js';
@@ -23,7 +23,6 @@ import SynOption from '../option/option.component.js';
23
23
  import type SynOptGroup from '../optgroup/optgroup.js';
24
24
  import SynTag from '../tag/tag.component.js';
25
25
  import styles from './combobox.styles.js';
26
- import customStyles from './combobox.custom.styles.js';
27
26
  import {
28
27
  checkValueBelongsToOption,
29
28
  createOptionFromDifferentTypes, filterOnlyOptgroups, getAllOptions, getAssignedElementsForSlot,
@@ -103,8 +102,6 @@ export default class SynCombobox extends SynergyElement implements SynergyFormCo
103
102
  componentStyles,
104
103
  formControlStyles,
105
104
  styles,
106
- formControlCustomStyles,
107
- customStyles,
108
105
  ];
109
106
 
110
107
  static dependencies = {
@@ -215,6 +212,9 @@ export default class SynCombobox extends SynergyElement implements SynergyFormCo
215
212
  /** Disables the combobox control. */
216
213
  @property({ reflect: true, type: Boolean }) disabled = false;
217
214
 
215
+ /** Sets the combobox to a readonly state. */
216
+ @property({ reflect: true, type: Boolean }) readonly = false;
217
+
218
218
  /** Adds a clear button when the combobox is not empty. */
219
219
  @property({ type: Boolean }) clearable = false;
220
220
 
@@ -674,6 +674,12 @@ export default class SynCombobox extends SynergyElement implements SynergyFormCo
674
674
  }
675
675
  };
676
676
 
677
+ private handleFormControlClick() {
678
+ if (this.readonly) {
679
+ this.displayInput.focus();
680
+ }
681
+ }
682
+
677
683
  private handleLabelClick() {
678
684
  this.displayInput.focus();
679
685
  }
@@ -683,7 +689,7 @@ export default class SynCombobox extends SynergyElement implements SynergyFormCo
683
689
 
684
690
  this.valueHasChanged = true;
685
691
 
686
- if (!this.disabled) {
692
+ if (!this.disabled && !this.readonly) {
687
693
  this.toggleOptionSelection(option, false);
688
694
  this.selectionChanged();
689
695
 
@@ -701,7 +707,7 @@ export default class SynCombobox extends SynergyElement implements SynergyFormCo
701
707
  const isIconButton = path.some(el => el instanceof Element && el.tagName.toLowerCase() === 'syn-icon-button');
702
708
 
703
709
  // Ignore disabled controls and clicks on tags (remove buttons)
704
- if (this.disabled || isIconButton) {
710
+ if (this.disabled || this.readonly || isIconButton) {
705
711
  return;
706
712
  }
707
713
 
@@ -963,9 +969,23 @@ export default class SynCombobox extends SynergyElement implements SynergyFormCo
963
969
  this.lastOptions = [...this.selectedOptions];
964
970
 
965
971
  // Update validity and display label
972
+ // Make sure to still show the display label if we are in multiple and readonly mode
966
973
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
967
974
  this.updateComplete.then(() => {
968
- this.displayLabel = this.multiple ? '' : this.selectedOptions[0]?.getTextLabel() ?? this.displayLabel;
975
+ let newLabel = this.displayLabel;
976
+
977
+ if (this.multiple && this.readonly) {
978
+ // For multiple and readonly, we want to show the labels of the selected options, otherwise we would just show the value which is not useful in readonly mode and multiple mode
979
+ newLabel = this.selectedOptions.map(opt => opt.getTextLabel()).join(', ');
980
+ } else if (this.multiple && !this.readonly) {
981
+ // For multiple and not readonly, we want to show the typed in value instead of the selected options, otherwise the user would not see what they typed in if they select an option which is not ideal. Showing the selected options is also not ideal in this case, because it would just be a long list of options which is not useful. So we show the typed in value which is more useful in this case. If there are no options selected, we want to show an empty string instead of the typed in value, because the typed in value is not valid in this case and showing it would be confusing.
982
+ newLabel = '';
983
+ } else {
984
+ // For single, we want to show the label of the selected option, if there is one, otherwise we show the typed in value which is already in displayLabel. This is also needed for `restricted` comboboxes, because if the user types in an invalid value, we want to show that value instead of the label of the selected option which would be confusing. If there are no options selected and no typed in value, we want to show an empty string instead of the label of the selected option, because showing the label of the selected option would be confusing in this case.
985
+ newLabel = this.selectedOptions[0]?.getTextLabel() ?? this.displayLabel;
986
+ }
987
+
988
+ this.displayLabel = newLabel;
969
989
  this.formControlController.updateValidity();
970
990
  });
971
991
  }
@@ -991,17 +1011,22 @@ export default class SynCombobox extends SynergyElement implements SynergyFormCo
991
1011
  this.createComboboxOptionsFromQuery(this.displayLabel);
992
1012
  }
993
1013
 
994
- @watch('disabled', { waitUntilFirstUpdate: true })
1014
+ @watch(['disabled', 'readonly'], { waitUntilFirstUpdate: true })
995
1015
  handleDisabledChange() {
996
1016
  // Disabled form controls are always valid
997
- this.formControlController.setValidity(this.disabled);
998
-
999
- // Close the listbox when the control is disabled
1000
1017
  if (this.disabled) {
1018
+ this.formControlController.setValidity(this.disabled);
1019
+ }
1020
+
1021
+ // Close the listbox when the control is disabled or readonly
1022
+ if (this.disabled || this.readonly) {
1001
1023
  this.open = false;
1002
1024
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
1003
1025
  this.handleOpenChange();
1004
1026
  }
1027
+
1028
+ // Recalculate display label when readonly changes
1029
+ this.selectionChanged();
1005
1030
  }
1006
1031
 
1007
1032
  @watch('delimiter')
@@ -1026,7 +1051,7 @@ export default class SynCombobox extends SynergyElement implements SynergyFormCo
1026
1051
 
1027
1052
  @watch('open', { waitUntilFirstUpdate: true })
1028
1053
  async handleOpenChange() {
1029
- if (this.open && !this.disabled) {
1054
+ if (this.open && (!this.disabled && !this.readonly)) {
1030
1055
  if (this.numberFilteredOptions === 0 && !this.restricted && !this.multiple) {
1031
1056
  // Don't open the listbox if there are no options and it is not restricted or multiple
1032
1057
  this.open = false;
@@ -1069,7 +1094,7 @@ export default class SynCombobox extends SynergyElement implements SynergyFormCo
1069
1094
  * appropriate filtered options, a syn-error is emitted and the listbox stays closed.
1070
1095
  */
1071
1096
  async show() {
1072
- if (this.open || this.disabled) {
1097
+ if (this.open || this.disabled || this.readonly) {
1073
1098
  this.open = false;
1074
1099
  return undefined;
1075
1100
  }
@@ -1080,7 +1105,7 @@ export default class SynCombobox extends SynergyElement implements SynergyFormCo
1080
1105
 
1081
1106
  /** Hides the listbox. */
1082
1107
  async hide() {
1083
- if (!this.open || this.disabled) {
1108
+ if (!this.open || this.disabled || this.readonly) {
1084
1109
  this.open = false;
1085
1110
  return undefined;
1086
1111
  }
@@ -1466,7 +1491,7 @@ export default class SynCombobox extends SynergyElement implements SynergyFormCo
1466
1491
  hasValue = this.value !== undefined && this.value !== null && typeof this.value === 'number';
1467
1492
  }
1468
1493
 
1469
- const hasClearIcon = this.clearable && !this.disabled && hasValue;
1494
+ const hasClearIcon = this.clearable && (!this.disabled && !this.readonly) && hasValue;
1470
1495
  const isPlaceholderVisible = this.placeholder && !hasValue;
1471
1496
  const tagsVisible = this.multiple && this.selectedOptions.length > 0;
1472
1497
 
@@ -1474,13 +1499,14 @@ export default class SynCombobox extends SynergyElement implements SynergyFormCo
1474
1499
  <div
1475
1500
  part="form-control"
1476
1501
  class=${classMap({
1477
- 'form-control': true,
1478
- 'form-control--has-help-text': hasHelpText,
1479
- 'form-control--has-label': hasLabel,
1480
- 'form-control--large': this.size === 'large',
1481
- 'form-control--medium': this.size === 'medium',
1482
- 'form-control--small': this.size === 'small',
1483
- })}
1502
+ 'form-control': true,
1503
+ 'form-control--has-help-text': hasHelpText,
1504
+ 'form-control--has-label': hasLabel,
1505
+ 'form-control--large': this.size === 'large',
1506
+ 'form-control--medium': this.size === 'medium',
1507
+ 'form-control--small': this.size === 'small',
1508
+ })}
1509
+ @click=${this.handleFormControlClick}
1484
1510
  >
1485
1511
  <label
1486
1512
  id="label"
@@ -1495,20 +1521,21 @@ export default class SynCombobox extends SynergyElement implements SynergyFormCo
1495
1521
  <div part="form-control-input" class="form-control-input">
1496
1522
  <syn-popup
1497
1523
  class=${classMap({
1498
- combobox: true,
1499
- 'combobox--bottom': this.placement === 'bottom',
1500
- 'combobox--disabled': this.disabled,
1501
- 'combobox--focused': this.hasFocus,
1502
- 'combobox--large': this.size === 'large',
1503
- 'combobox--medium': this.size === 'medium',
1504
- 'combobox--multiple': this.multiple,
1505
- 'combobox--open': this.open,
1506
- 'combobox--placeholder-visible': isPlaceholderVisible,
1507
- 'combobox--small': this.size === 'small',
1508
- 'combobox--standard': true,
1509
- 'combobox--tags-visible': tagsVisible,
1510
- 'combobox--top': this.placement === 'top',
1511
- })}
1524
+ combobox: true,
1525
+ 'combobox--bottom': this.placement === 'bottom',
1526
+ 'combobox--disabled': this.disabled,
1527
+ 'combobox--focused': this.hasFocus,
1528
+ 'combobox--large': this.size === 'large',
1529
+ 'combobox--medium': this.size === 'medium',
1530
+ 'combobox--multiple': this.multiple,
1531
+ 'combobox--open': this.open,
1532
+ 'combobox--placeholder-visible': isPlaceholderVisible,
1533
+ 'combobox--readonly': this.readonly,
1534
+ 'combobox--small': this.size === 'small',
1535
+ 'combobox--standard': true,
1536
+ 'combobox--tags-visible': tagsVisible,
1537
+ 'combobox--top': this.placement === 'top',
1538
+ })}
1512
1539
  placement=${`${this.placement}-start`}
1513
1540
  flip
1514
1541
  shift
@@ -1526,7 +1553,7 @@ export default class SynCombobox extends SynergyElement implements SynergyFormCo
1526
1553
  >
1527
1554
  <slot part="prefix" name="prefix" class="combobox__prefix"></slot>
1528
1555
 
1529
- ${this.multiple ? html`<div part="tags" class="combobox__tags">${this.tags}</div>` : ''}
1556
+ ${this.multiple && !this.readonly ? html`<div part="tags" class="combobox__tags">${this.tags}</div>` : ''}
1530
1557
 
1531
1558
  <input
1532
1559
  part="display-input"
@@ -1534,6 +1561,7 @@ export default class SynCombobox extends SynergyElement implements SynergyFormCo
1534
1561
  type="text"
1535
1562
  placeholder=${this.placeholder}
1536
1563
  .disabled=${this.disabled}
1564
+ .readOnly=${this.readonly}
1537
1565
  .value=${this.displayLabel}
1538
1566
  autocomplete="off"
1539
1567
  spellcheck="false"
@@ -1559,6 +1587,7 @@ export default class SynCombobox extends SynergyElement implements SynergyFormCo
1559
1587
  class="combobox__value-input"
1560
1588
  type="text"
1561
1589
  ?disabled=${this.disabled}
1590
+ ?readonly=${this.readonly}
1562
1591
  ?required=${this.required}
1563
1592
  .value=${Array.isArray(this.value) ? this.value.join(', ') : this.value?.toString()}
1564
1593
  tabindex="-1"
@@ -1568,7 +1597,7 @@ export default class SynCombobox extends SynergyElement implements SynergyFormCo
1568
1597
  />
1569
1598
 
1570
1599
  ${hasClearIcon
1571
- ? html`
1600
+ ? html`
1572
1601
  <button
1573
1602
  part="clear-button"
1574
1603
  class="combobox__clear"
@@ -1583,7 +1612,7 @@ export default class SynCombobox extends SynergyElement implements SynergyFormCo
1583
1612
  </slot>
1584
1613
  </button>
1585
1614
  `
1586
- : ''}
1615
+ : ''}
1587
1616
 
1588
1617
  <slot name="suffix" part="suffix" class="combobox__suffix"></slot>
1589
1618
 
@@ -112,6 +112,11 @@ const props = defineProps<{
112
112
  */
113
113
  disabled?: SynCombobox['disabled'];
114
114
 
115
+ /**
116
+ * Sets the combobox to a readonly state.
117
+ */
118
+ readonly?: SynCombobox['readonly'];
119
+
115
120
  /**
116
121
  * Adds a clear button when the combobox is not empty.
117
122
  */
@@ -209,6 +209,19 @@ If you need to display HTML, use the `help-text` slot instead.
209
209
  return this.nativeElement.disabled;
210
210
  }
211
211
 
212
+ /**
213
+ * Sets the file control to a readonly state.
214
+ */
215
+ @Input()
216
+ set readonly(v: '' | SynFile['readonly']) {
217
+ this._ngZone.runOutsideAngular(
218
+ () => (this.nativeElement.readonly = v === '' || v),
219
+ );
220
+ }
221
+ get readonly(): SynFile['readonly'] {
222
+ return this.nativeElement.readonly;
223
+ }
224
+
212
225
  /**
213
226
  * Draw the file control as a drop area
214
227
  */
@@ -152,6 +152,23 @@ export default css`
152
152
  font-size: var(--syn-spacing-4x-large)
153
153
  }
154
154
 
155
+ /* #1173: Readonly Styles */
156
+ :host([readonly]) .button::part(base) {
157
+ background: var(--syn-readonly-background-color);
158
+ color: var(--syn-readonly-indicator-color);
159
+ }
160
+
161
+ :host([readonly]) .droparea__text strong {
162
+ color: var(--syn-readonly-color-text);
163
+ }
164
+
165
+ :host([readonly]) .droparea {
166
+ --highlight-color: var(--syn-readonly-icon-color);
167
+
168
+ background: var(--syn-readonly-background-color);
169
+ border: var(--syn-input-border-width) solid var(--syn-readonly-background-color);
170
+ }
171
+
155
172
  /* Disabled Styles */
156
173
  :host([disabled]) .droparea,
157
174
  :host([disabled]) .input__value {
@@ -159,13 +176,13 @@ export default css`
159
176
  opacity: var(--syn-input-disabled-opacity);
160
177
  }
161
178
 
162
- :host(:not([disabled])) .form-control--user-dragging .droparea {
179
+ :host(:not([disabled]):not([readonly])) .form-control--user-dragging .droparea {
163
180
  background: var(--syn-color-primary-50);
164
181
  border: var(--syn-input-border-width) solid var(--syn-interactive-emphasis-color);
165
182
  cursor: pointer;
166
183
  }
167
184
 
168
- :host(:not([disabled])) .droparea:not(:focus-visible):hover {
185
+ :host(:not([disabled]):not([readonly])) .droparea:not(:focus-visible):hover {
169
186
  --highlight-color: var(--syn-interactive-emphasis-color-hover);
170
187
 
171
188
  border: var(--syn-input-border-width) dashed var(--syn-input-border-color-hover);
@@ -174,7 +191,7 @@ export default css`
174
191
 
175
192
  /* Validation */
176
193
  /* stylelint-disable-next-line no-descending-specificity */
177
- :host([data-user-invalid]:not([disabled])) .droparea {
194
+ :host([data-user-invalid]:not([disabled]):not([readonly])) .droparea {
178
195
  border: var(--syn-input-border-width) dashed var(--syn-input-focus-ring-error);
179
196
  }
180
197
  `;
@@ -11,7 +11,6 @@ import { FormControlController } from '../../internal/form.js';
11
11
  import { HasSlotController } from '../../internal/slot.js';
12
12
  import componentStyles from '../../styles/component.styles.js';
13
13
  import formControlStyles from '../../styles/form-control.styles.js';
14
- import formControlCustomStyles from '../../styles/form-control.custom.styles.js';
15
14
  import SynergyElement from '../../internal/synergy-element.js';
16
15
  import SynButton from '../button/button.component.js';
17
16
  import SynIcon from '../icon/icon.component.js';
@@ -72,7 +71,6 @@ export default class SynFile extends SynergyElement implements SynergyFormContro
72
71
  static styles: CSSResultGroup = [
73
72
  componentStyles,
74
73
  formControlStyles,
75
- formControlCustomStyles,
76
74
  styles,
77
75
  ];
78
76
 
@@ -159,6 +157,9 @@ export default class SynFile extends SynergyElement implements SynergyFormContro
159
157
  /** Disables the file control. */
160
158
  @property({ reflect: true, type: Boolean }) disabled = false;
161
159
 
160
+ /** Sets the file control to a readonly state. */
161
+ @property({ reflect: true, type: Boolean }) readonly = false;
162
+
162
163
  /** Draw the file control as a drop area */
163
164
  @property({ type: Boolean }) droparea = false;
164
165
 
@@ -362,12 +363,22 @@ export default class SynFile extends SynergyElement implements SynergyFormContro
362
363
  private handleDragOver(e: DragEvent) {
363
364
  e.preventDefault();
364
365
  e.stopPropagation();
366
+
367
+ if (this.disabled || this.readonly) {
368
+ return;
369
+ }
370
+
365
371
  this.userIsDragging = true;
366
372
  }
367
373
 
368
374
  private handleDragLeave(e: DragEvent) {
369
375
  e.preventDefault();
370
376
  e.stopPropagation();
377
+
378
+ if (this.disabled || this.readonly) {
379
+ return;
380
+ }
381
+
371
382
  this.userIsDragging = false;
372
383
  }
373
384
 
@@ -376,6 +387,10 @@ export default class SynFile extends SynergyElement implements SynergyFormContro
376
387
  e.preventDefault();
377
388
  e.stopPropagation();
378
389
 
390
+ if (this.disabled || this.readonly) {
391
+ return;
392
+ }
393
+
379
394
  if (!e.dataTransfer) {
380
395
  return;
381
396
  }
@@ -507,7 +522,7 @@ export default class SynFile extends SynergyElement implements SynergyFormContro
507
522
  <syn-button
508
523
  class="button"
509
524
  @click=${this.handleClick}
510
- ?disabled=${this.disabled}
525
+ ?disabled=${this.disabled || this.readonly}
511
526
  exportparts="base:button__base"
512
527
  part="button"
513
528
  size=${this.size}
@@ -522,7 +537,6 @@ export default class SynFile extends SynergyElement implements SynergyFormContro
522
537
  /* eslint-enable @typescript-eslint/unbound-method */
523
538
 
524
539
  /* eslint-disable @typescript-eslint/unbound-method */
525
- // eslint-disable-next-line complexity
526
540
  render() {
527
541
  const hasLabel = this.label || !!this.hasSlotController.test('label');
528
542
  const hasHelpText = this.helpText ? true : !!this.hasSlotController.test('help-text');
@@ -589,7 +603,7 @@ export default class SynFile extends SynergyElement implements SynergyFormContro
589
603
  aria-describedby="help-text"
590
604
  @change=${this.handleChange}
591
605
  class="input__control"
592
- ?disabled=${this.disabled}
606
+ ?disabled=${this.disabled || this.readonly}
593
607
  id="input"
594
608
  @invalid=${this.handleInvalid}
595
609
  ?multiple=${this.multiple}
@@ -115,6 +115,11 @@ If you need to display HTML, use the `help-text` slot instead.
115
115
  */
116
116
  disabled?: SynFile['disabled'];
117
117
 
118
+ /**
119
+ * Sets the file control to a readonly state.
120
+ */
121
+ readonly?: SynFile['readonly'];
122
+
118
123
  /**
119
124
  * Draw the file control as a drop area
120
125
  */
@@ -11,7 +11,6 @@ import { property, query, state } from 'lit/decorators.js';
11
11
  import { watch } from '../../internal/watch.js';
12
12
  import componentStyles from '../../styles/component.styles.js';
13
13
  import formControlStyles from '../../styles/form-control.styles.js';
14
- import formControlCustomStyles from '../../styles/form-control.custom.styles.js';
15
14
  import SynergyElement from '../../internal/synergy-element.js';
16
15
  import SynIcon from '../icon/icon.component.js';
17
16
  import SynDivider from '../divider/divider.component.js';
@@ -79,7 +78,7 @@ import { enableDefaultSettings } from '../../utilities/defaultSettings/decorator
79
78
  */
80
79
  @enableDefaultSettings('SynInput')
81
80
  export default class SynInput extends SynergyElement implements SynergyFormControl {
82
- static styles: CSSResultGroup = [componentStyles, formControlStyles, styles, formControlCustomStyles, customStyles];
81
+ static styles: CSSResultGroup = [componentStyles, formControlStyles, styles, customStyles];
83
82
  static dependencies = {
84
83
  'syn-icon': SynIcon,
85
84
  'syn-divider': SynDivider
@@ -1,8 +1,6 @@
1
- /* eslint-disable */
2
1
  import { css } from 'lit';
3
2
 
4
3
  export default css`
5
- /* stylelint-disable */
6
4
  :host {
7
5
  --arrow-color: var(--syn-color-neutral-1000);
8
6
  --arrow-size: 6px;
@@ -18,10 +16,22 @@ export default css`
18
16
  }
19
17
 
20
18
  .popup {
21
- position: absolute;
22
19
  isolation: isolate;
23
- max-width: var(--auto-size-available-width, none);
24
20
  max-height: var(--auto-size-available-height, none);
21
+ max-width: var(--auto-size-available-width, none);
22
+ position: absolute;
23
+
24
+ :where(&) {
25
+ background: unset;
26
+ border: unset;
27
+ color: unset;
28
+ height: unset;
29
+ inset: unset;
30
+ margin: unset;
31
+ overflow: unset;
32
+ padding: unset;
33
+ width: unset;
34
+ }
25
35
  }
26
36
 
27
37
  .popup--fixed {
@@ -33,31 +43,28 @@ export default css`
33
43
  }
34
44
 
35
45
  .popup__arrow {
36
- position: absolute;
37
- width: calc(var(--arrow-size-diagonal) * 2);
46
+ background: var(--arrow-color);
38
47
  height: calc(var(--arrow-size-diagonal) * 2);
48
+ position: absolute;
39
49
  rotate: 45deg;
40
- background: var(--arrow-color);
50
+ width: calc(var(--arrow-size-diagonal) * 2);
41
51
  z-index: -1;
42
52
  }
43
53
 
44
54
  /* Hover bridge */
45
- .popup-hover-bridge:not(.popup-hover-bridge--visible) {
46
- display: none;
47
- }
48
-
49
55
  .popup-hover-bridge {
50
- position: fixed;
51
- z-index: calc(var(--syn-z-index-dropdown) - 1);
52
- top: 0;
53
- right: 0;
54
- bottom: 0;
55
- left: 0;
56
56
  clip-path: polygon(
57
57
  var(--hover-bridge-top-left-x, 0) var(--hover-bridge-top-left-y, 0),
58
58
  var(--hover-bridge-top-right-x, 0) var(--hover-bridge-top-right-y, 0),
59
59
  var(--hover-bridge-bottom-right-x, 0) var(--hover-bridge-bottom-right-y, 0),
60
60
  var(--hover-bridge-bottom-left-x, 0) var(--hover-bridge-bottom-left-y, 0)
61
61
  );
62
+ inset: 0;
63
+ position: fixed;
64
+ z-index: calc(var(--syn-z-index-dropdown) - 1);
65
+ }
66
+
67
+ .popup-hover-bridge:not(.popup-hover-bridge--visible) {
68
+ display: none;
62
69
  }
63
70
  `;
@@ -9,7 +9,6 @@ import { property, query } from 'lit/decorators.js';
9
9
  import componentStyles from '../../styles/component.styles.js';
10
10
  import SynergyElement from '../../internal/synergy-element.js';
11
11
  import styles from './popup.styles.js';
12
- import customStyles from './popup.custom.styles.js';
13
12
  import type { CSSResultGroup } from 'lit';
14
13
 
15
14
  const SUPPORTS_POPOVER = globalThis?.HTMLElement?.prototype.hasOwnProperty('popover');
@@ -58,7 +57,7 @@ function isVirtualElement(e: unknown): e is VirtualElement {
58
57
  * available when using `auto-size`.
59
58
  */
60
59
  export default class SynPopup extends SynergyElement {
61
- static styles: CSSResultGroup = [componentStyles, styles, customStyles];
60
+ static styles: CSSResultGroup = [componentStyles, styles];
62
61
 
63
62
  private anchorEl: Element | VirtualElement | null;
64
63
  private cleanup: ReturnType<typeof autoUpdate> | undefined;
@@ -94,6 +94,19 @@ attribute can typically be omitted.
94
94
  return this.nativeElement.disabled;
95
95
  }
96
96
 
97
+ /**
98
+ * Sets the radio to a readonly state.
99
+ */
100
+ @Input()
101
+ set readonly(v: '' | SynRadio['readonly']) {
102
+ this._ngZone.runOutsideAngular(
103
+ () => (this.nativeElement.readonly = v === '' || v),
104
+ );
105
+ }
106
+ get readonly(): SynRadio['readonly'] {
107
+ return this.nativeElement.readonly;
108
+ }
109
+
97
110
  /**
98
111
  * Emitted when the control loses focus.
99
112
  */