@siemens/element-ng 51.2.0 → 51.3.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 (29) hide show
  1. package/README.md +2 -2
  2. package/fesm2022/siemens-element-ng-datepicker.mjs +13 -3
  3. package/fesm2022/siemens-element-ng-datepicker.mjs.map +1 -1
  4. package/fesm2022/siemens-element-ng-filtered-search.mjs +7 -3
  5. package/fesm2022/siemens-element-ng-filtered-search.mjs.map +1 -1
  6. package/fesm2022/siemens-element-ng-form.mjs +4 -4
  7. package/fesm2022/siemens-element-ng-form.mjs.map +1 -1
  8. package/fesm2022/siemens-element-ng-number-input.mjs +3 -2
  9. package/fesm2022/siemens-element-ng-number-input.mjs.map +1 -1
  10. package/fesm2022/siemens-element-ng-popover.mjs +16 -5
  11. package/fesm2022/siemens-element-ng-popover.mjs.map +1 -1
  12. package/fesm2022/siemens-element-ng-tree-view.mjs +15 -10
  13. package/fesm2022/siemens-element-ng-tree-view.mjs.map +1 -1
  14. package/fesm2022/siemens-element-ng-typeahead.mjs +9 -0
  15. package/fesm2022/siemens-element-ng-typeahead.mjs.map +1 -1
  16. package/package.json +5 -5
  17. package/schematics/migrations/data/attribute-selectors.js +8 -1
  18. package/schematics/migrations/data/element-selectors.js +7 -1
  19. package/schematics/migrations/data/symbol-renaming.js +10 -0
  20. package/schematics/migrations/utilities/attribute-selector.migration.js +26 -10
  21. package/schematics/migrations/utilities/element-selector.migration.js +25 -15
  22. package/schematics/migrations/utilities/symbol-renaming.migration.js +90 -3
  23. package/schematics/utils/template-edit-utils.js +9 -0
  24. package/types/siemens-element-ng-datepicker.d.ts +6 -1
  25. package/types/siemens-element-ng-form.d.ts +1 -1
  26. package/types/siemens-element-ng-number-input.d.ts +2 -2
  27. package/types/siemens-element-ng-popover.d.ts +1 -1
  28. package/types/siemens-element-ng-tree-view.d.ts +1 -0
  29. package/types/siemens-element-ng-typeahead.d.ts +7 -0
@@ -4,16 +4,18 @@
4
4
  */
5
5
  import * as ts from 'typescript';
6
6
  import { EmitHint } from 'typescript';
7
- import { findImportSpecifier } from '../../utils/index.js';
7
+ import { findImportSpecifier, getImportSpecifiers } from '../../utils/index.js';
8
+ import { removeImportSpecifiers } from './import-removal.js';
8
9
  export const applySymbolRenamingMigration = (context, changes) => {
9
10
  const { discoveredSourceFile, recorder } = context;
10
11
  if (!changes?.length) {
11
12
  return;
12
13
  }
13
- const { sourceFile } = discoveredSourceFile;
14
+ const { sourceFile, typeChecker } = discoveredSourceFile;
14
15
  const changeInstructions = [
15
16
  ...renameIdentifier({
16
17
  sourceFile,
18
+ typeChecker,
17
19
  renamingInstructions: changes
18
20
  })
19
21
  ];
@@ -26,7 +28,7 @@ export const applySymbolRenamingMigration = (context, changes) => {
26
28
  recorder.insertLeft(changeInstruction.start, printer.printNode(EmitHint.Unspecified, changeInstruction.newNode, sourceFile));
27
29
  }
28
30
  };
29
- function* renameIdentifier({ sourceFile, renamingInstructions }) {
31
+ function* renameIdentifier({ sourceFile, typeChecker, renamingInstructions }) {
30
32
  for (const node of sourceFile.statements) {
31
33
  if (!ts.isImportDeclaration(node) || !ts.isStringLiteral(node.moduleSpecifier)) {
32
34
  continue;
@@ -38,6 +40,10 @@ function* renameIdentifier({ sourceFile, renamingInstructions }) {
38
40
  if (!(node.importClause?.namedBindings && ts.isNamedImports(node.importClause.namedBindings))) {
39
41
  continue;
40
42
  }
43
+ if (!renamingInstruction.toModule) {
44
+ yield* renameSymbolsInPlace(sourceFile, typeChecker, node, renamingInstruction);
45
+ continue;
46
+ }
41
47
  // Find all symbols from this import that need to be renamed/moved
42
48
  const symbolsToProcess = [];
43
49
  for (const { replace, replaceWith } of renamingInstruction.symbolRenamings) {
@@ -126,3 +132,84 @@ function* renameIdentifier({ sourceFile, renamingInstructions }) {
126
132
  }
127
133
  }
128
134
  }
135
+ function* renameSymbolsInPlace(sourceFile, typeChecker, declaration, instruction) {
136
+ const importClause = declaration.importClause;
137
+ const bindings = importClause.namedBindings;
138
+ const replacements = new Map();
139
+ const references = new Map();
140
+ const redundantImports = [];
141
+ for (const specifier of bindings.elements) {
142
+ const importedName = specifier.propertyName ?? specifier.name;
143
+ const rename = instruction.symbolRenamings.find(change => change.replace === importedName.text);
144
+ if (!rename) {
145
+ continue;
146
+ }
147
+ // Aliases keep their local name and only change the imported symbol.
148
+ if (specifier.propertyName) {
149
+ replacements.set(specifier, rename.replaceWith);
150
+ continue;
151
+ }
152
+ const existingImport = getImportSpecifiers(sourceFile, declaration.moduleSpecifier.text, rename.replaceWith).find(candidate => {
153
+ const isTypeOnly = candidate.isTypeOnly || candidate.parent.parent.isTypeOnly;
154
+ return !isTypeOnly || specifier.isTypeOnly || importClause.isTypeOnly;
155
+ });
156
+ if (existingImport) {
157
+ redundantImports.push(specifier);
158
+ }
159
+ else {
160
+ replacements.set(specifier, rename.replaceWith);
161
+ }
162
+ const symbol = typeChecker.getSymbolAtLocation(specifier.name);
163
+ if (symbol) {
164
+ references.set(symbol, existingImport?.name.text ?? rename.replaceWith);
165
+ }
166
+ }
167
+ if (redundantImports.length) {
168
+ const edit = removeImportSpecifiers(sourceFile, declaration, redundantImports);
169
+ const remaining = bindings.elements.filter(specifier => !redundantImports.includes(specifier));
170
+ const updatedBindings = ts.factory.updateNamedImports(bindings, remaining.map(specifier => {
171
+ const replacement = replacements.get(specifier);
172
+ if (!replacement) {
173
+ return specifier;
174
+ }
175
+ return ts.factory.updateImportSpecifier(specifier, specifier.isTypeOnly, specifier.propertyName ? ts.factory.createIdentifier(replacement) : undefined, specifier.propertyName ? specifier.name : ts.factory.createIdentifier(replacement));
176
+ }));
177
+ yield {
178
+ start: edit.start,
179
+ width: edit.width,
180
+ newNode: edit.newNode
181
+ ? ts.factory.updateImportDeclaration(declaration, declaration.modifiers, ts.factory.updateImportClause(importClause, importClause.isTypeOnly, importClause.name, updatedBindings), declaration.moduleSpecifier, declaration.attributes)
182
+ : ts.factory.createIdentifier('')
183
+ };
184
+ }
185
+ else {
186
+ for (const [specifier, replacement] of replacements) {
187
+ const importedName = specifier.propertyName ?? specifier.name;
188
+ yield {
189
+ start: importedName.getStart(),
190
+ width: importedName.getWidth(),
191
+ newNode: ts.factory.createIdentifier(replacement)
192
+ };
193
+ }
194
+ }
195
+ const visit = function* (node) {
196
+ if (ts.isImportDeclaration(node)) {
197
+ return;
198
+ }
199
+ if (ts.isIdentifier(node)) {
200
+ const symbol = typeChecker.getSymbolAtLocation(node);
201
+ const replacement = symbol && references.get(symbol);
202
+ if (replacement) {
203
+ yield {
204
+ start: node.getStart(),
205
+ width: node.getWidth(),
206
+ newNode: ts.factory.createIdentifier(replacement)
207
+ };
208
+ }
209
+ }
210
+ for (const child of node.getChildren()) {
211
+ yield* visit(child);
212
+ }
213
+ };
214
+ yield* visit(sourceFile);
215
+ }
@@ -33,3 +33,12 @@ export const removeAttribute = (template, attribute, offset, recorder) => {
33
33
  const removeStart = start > 0 && /\s/.test(template[start - 1] ?? '') ? start - 1 : start;
34
34
  recorder.remove(removeStart + offset, end - removeStart);
35
35
  };
36
+ /** Removes static attributes and property/attribute bindings with the given names. */
37
+ export const removeAttributesFromElement = (template, element, names, offset, recorder) => {
38
+ for (const attribute of element.attrs) {
39
+ const matches = names.some(name => [name, `[${name}]`, `attr.${name}`, `[attr.${name}]`].includes(attribute.name));
40
+ if (matches) {
41
+ removeAttribute(template, attribute, offset, recorder);
42
+ }
43
+ }
44
+ };
@@ -217,7 +217,7 @@ declare class SiDateInputDirective implements ControlValueAccessor, OnChanges, V
217
217
  registerOnTouched(fn: () => void): void;
218
218
  registerOnValidatorChange(fn: () => void): void;
219
219
  setDisabledState(isDisabled: boolean): void;
220
- writeValue(value?: Date | string): void;
220
+ writeValue(value?: Date | string | null): void;
221
221
  private updateNativeValue;
222
222
  /**
223
223
  * Handles `input` events on the input element.
@@ -920,6 +920,11 @@ declare class SiTimepickerComponent implements ControlValueAccessor, Validator,
920
920
  * Holds the time as date object that is presented by this control.
921
921
  */
922
922
  private time?;
923
+ /**
924
+ * Whether `null` was emitted due to an incomplete or invalid input.
925
+ * The next valid time must be emitted, even if it equals the previous `time`.
926
+ */
927
+ private invalidTimeEmitted;
923
928
  private periodDefaults;
924
929
  constructor();
925
930
  writeValue(obj?: Date | string): void;
@@ -388,7 +388,7 @@ declare class SiFormFieldsetComponent {
388
388
  /** @internal */
389
389
  readonly hasOnlyRadios: _angular_core.Signal<boolean>;
390
390
  protected readonly errors: _angular_core.Signal<readonly _siemens_element_ng_form.SiFormError[]>;
391
- protected readonly touched: _angular_core.Signal<boolean>;
391
+ protected readonly showErrors: _angular_core.Signal<boolean>;
392
392
  protected readonly isRequired: _angular_core.Signal<boolean>;
393
393
  protected readonly labelId: string;
394
394
  /** @internal */
@@ -26,7 +26,7 @@ declare class SiNumberInputComponent implements OnChanges, ControlValueAccessor,
26
26
  */
27
27
  readonly step: _angular_core.InputSignal<number | "any">;
28
28
  /** The value */
29
- readonly value: _angular_core.InputSignal<number | undefined>;
29
+ readonly value: _angular_core.InputSignal<number | null | undefined>;
30
30
  /** Optional unit label */
31
31
  readonly unit: _angular_core.InputSignal<string | undefined>;
32
32
  /**
@@ -104,7 +104,7 @@ declare class SiNumberInputComponent implements OnChanges, ControlValueAccessor,
104
104
  /** @internal */
105
105
  setDisabledState(isDisabled: boolean): void;
106
106
  /** @internal */
107
- writeValue(value: number | undefined): void;
107
+ writeValue(value: number | null | undefined): void;
108
108
  /** @internal */
109
109
  validate(control: AbstractControl): ValidationErrors | null;
110
110
  /** @internal */
@@ -13,7 +13,7 @@ declare class SiPopoverDirective implements OnDestroy {
13
13
  */
14
14
  readonly siPopover: _angular_core.InputSignal<TranslatableString | TemplateRef<unknown> | undefined>;
15
15
  /**
16
- * The placement of the popover. One of 'top', 'start', end', 'bottom'
16
+ * The placement of the popover. One of 'top', 'start', 'end', 'bottom'
17
17
  *
18
18
  * @defaultValue 'auto'
19
19
  */
@@ -372,6 +372,7 @@ declare class SiTreeViewComponent implements OnInit, OnChanges, OnDestroy, After
372
372
  */
373
373
  private virtualRoot;
374
374
  private readonly _items;
375
+ protected readonly svgIcons: Record<"elementExpandAll" | "elementCollapseAll", string>;
375
376
  private updateTreeItemDefaults;
376
377
  /**
377
378
  * @internal
@@ -337,6 +337,13 @@ declare class SiTypeaheadDirective implements OnChanges, OnDestroy {
337
337
  private readonly unprocessedSearch;
338
338
  constructor();
339
339
  ngOnChanges(changes: SimpleChanges<this>): void;
340
+ /**
341
+ * @internal
342
+ *
343
+ * Updates the position of the typeahead overlay when already rendered.
344
+ * This can be useful if the input position/dimension changed.
345
+ */
346
+ updateOverlayPosition(): void;
340
347
  protected onBlur(): void;
341
348
  protected onInput(event: Event): void;
342
349
  protected onKeydownEscape(): void;