@eui/core 22.0.0-alpha.11 → 22.0.0-alpha.13

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.
@@ -3147,12 +3147,12 @@
3147
3147
  },
3148
3148
  {
3149
3149
  "name": "Schema",
3150
- "id": "interface-Schema-817c4b549cc3eab9fcf4936acab2e71182d90a4480369f5c003cbbda10792efa587ad99d65acf049f64e7030e32589e4fabc4a6d7a5621e4fe54725ef91dc9e8-21",
3151
- "file": "packages/core/schematics/migrate-to-standalone/index.ts",
3150
+ "id": "interface-Schema-cac2ac952d8245647e8a48b450e8f127a36bcffb394cf2cd81fe9c0810ed02c19e5e1629dbf29a68a5c6f675aed99570e9ac04ae470e13315e20c92cc0c6c453-21",
3151
+ "file": "packages/core/schematics/migrate-to-signals/index.ts",
3152
3152
  "deprecated": false,
3153
3153
  "deprecationMessage": "",
3154
3154
  "type": "interface",
3155
- "sourceCode": "import { parseTemplate, TmplAstElement, TmplAstNode } from '@angular/compiler';\nimport { DirEntry, Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\nimport * as ts from 'typescript';\nimport { logDryRun, logDryRunNote } from '../utils/dry-run';\n\ninterface ModuleMapping {\n importPath: string;\n selectors: Record<string, string>;\n}\n\nconst MODULE_MAPPINGS: Record<string, ModuleMapping> = {\n EuiAccordionModule: {\n importPath: '@eui/components/eui-accordion',\n selectors: {\n 'eui-accordion': 'EuiAccordionComponent',\n 'eui-accordion-item': 'EuiAccordionItemComponent',\n euiAccordionItemHeader: 'EuiAccordionItemHeaderDirective',\n },\n },\n EuiAlertModule: {\n importPath: '@eui/components/eui-alert',\n selectors: {\n 'eui-alert': 'EuiAlertComponent',\n euiAlert: 'EuiAlertComponent',\n 'eui-alert-title': 'EuiAlertTitleComponent',\n },\n },\n EuiAutocompleteModule: {\n importPath: '@eui/components/eui-autocomplete',\n selectors: {\n 'eui-autocomplete': 'EuiAutocompleteComponent',\n euiAutocomplete: 'EuiAutocompleteComponent',\n 'eui-autocomplete-option': 'EuiAutocompleteOptionComponent',\n 'eui-autocomplete-option-group': 'EuiAutocompleteOptionGroupComponent',\n 'eui-autocomplete-panel': 'EuiAutocompletePanelComponent',\n },\n },\n EuiAvatarModule: {\n importPath: '@eui/components/eui-avatar',\n selectors: {\n 'eui-avatar': 'EuiAvatarComponent',\n euiAvatar: 'EuiAvatarComponent',\n },\n },\n EuiBadgeModule: {\n importPath: '@eui/components/eui-badge',\n selectors: {\n 'eui-badge': 'EuiBadgeComponent',\n euiBadge: 'EuiBadgeComponent',\n },\n },\n EuiBlockContentModule: {\n importPath: '@eui/components/eui-block-content',\n selectors: {\n 'eui-block-content': 'EuiBlockContentComponent',\n },\n },\n EuiBreadcrumbModule: {\n importPath: '@eui/components/eui-breadcrumb',\n selectors: {\n 'eui-breadcrumb': 'EuiBreadcrumbComponent',\n },\n },\n EuiButtonModule: {\n importPath: '@eui/components/eui-button',\n selectors: {\n euiButton: 'EuiButtonComponent',\n },\n },\n EuiButtonGroupModule: {\n importPath: '@eui/components/eui-button-group',\n selectors: {\n 'eui-button-group': 'EuiButtonGroupComponent',\n },\n },\n EuiCardModule: {\n importPath: '@eui/components/eui-card',\n selectors: {\n 'eui-card': 'EuiCardComponent',\n 'eui-card-header': 'EuiCardHeaderComponent',\n 'eui-card-header-title': 'EuiCardHeaderTitleComponent',\n 'eui-card-content': 'EuiCardContentComponent',\n 'eui-card-footer': 'EuiCardFooterComponent',\n 'eui-card-media': 'EuiCardMediaComponent',\n },\n },\n EuiChipModule: {\n importPath: '@eui/components/eui-chip',\n selectors: {\n 'eui-chip': 'EuiChipComponent',\n euiChip: 'EuiChipComponent',\n },\n },\n EuiChipListModule: {\n importPath: '@eui/components/eui-chip-list',\n selectors: {\n 'eui-chip-list': 'EuiChipListComponent',\n },\n },\n EuiChipGroupModule: {\n importPath: '@eui/components/eui-chip-group',\n selectors: {\n 'eui-chip-group': 'EuiChipGroupComponent',\n },\n },\n EuiDashboardCardModule: {\n importPath: '@eui/components/eui-dashboard-card',\n selectors: {\n 'eui-dashboard-card': 'EuiDashboardCardComponent',\n 'eui-dashboard-card-content': 'EuiDashboardCardContentComponent',\n 'eui-dashboard-card-content-header': 'EuiDashboardCardContentHeaderComponent',\n 'eui-dashboard-card-content-body': 'EuiDashboardCardContentBodyComponent',\n 'eui-dashboard-card-content-footer': 'EuiDashboardCardContentFooterComponent',\n },\n },\n EuiDashboardButtonModule: {\n importPath: '@eui/components/eui-dashboard-card',\n selectors: {\n 'eui-dashboard-card': 'EuiDashboardCardComponent',\n 'eui-dashboard-card-content': 'EuiDashboardCardContentComponent',\n 'eui-dashboard-card-content-header': 'EuiDashboardCardContentHeaderComponent',\n 'eui-dashboard-card-content-body': 'EuiDashboardCardContentBodyComponent',\n 'eui-dashboard-card-content-footer': 'EuiDashboardCardContentFooterComponent',\n },\n },\n EuiDatepickerModule: {\n importPath: '@eui/components/eui-datepicker',\n selectors: {\n 'eui-datepicker': 'EuiDatepickerComponent',\n },\n },\n EuiDateRangeSelectorModule: {\n importPath: '@eui/components/eui-date-range-selector',\n selectors: {\n 'eui-date-range-selector': 'EuiDateRangeSelectorComponent',\n },\n },\n EuiDialogModule: {\n importPath: '@eui/components/eui-dialog',\n selectors: {\n 'eui-dialog': 'EuiDialogComponent',\n 'eui-dialog-header': 'EuiDialogHeaderDirective',\n 'eui-dialog-footer': 'EuiDialogFooterDirective',\n 'eui-dialog-container': 'EuiDialogContainerComponent',\n },\n },\n EuiDisableContentModule: {\n importPath: '@eui/components/eui-disable-content',\n selectors: {\n 'eui-disable-content': 'EuiDisableContentComponent',\n },\n },\n EuiDiscussionThreadModule: {\n importPath: '@eui/components/eui-discussion-thread',\n selectors: {\n 'eui-discussion-thread': 'EuiDiscussionThreadComponent',\n 'eui-discussion-thread-item': 'EuiDiscussionThreadItemComponent',\n },\n },\n EuiDropdownModule: {\n importPath: '@eui/components/eui-dropdown',\n selectors: {\n 'eui-dropdown': 'EuiDropdownComponent',\n },\n },\n EuiFeedbackMessageModule: {\n importPath: '@eui/components/eui-feedback-message',\n selectors: {\n 'eui-feedback-message': 'EuiFeedbackMessageComponent',\n },\n },\n EuiFieldsetModule: {\n importPath: '@eui/components/eui-fieldset',\n selectors: {\n 'eui-fieldset': 'EuiFieldsetComponent',\n euiFieldsetLabelRightContent: 'EuiFieldsetLabelRightContentTagDirective',\n euiFieldsetLabelExtraContent: 'EuiFieldsetLabelExtraContentTagDirective',\n },\n },\n EuiFileUploadModule: {\n importPath: '@eui/components/eui-file-upload',\n selectors: {\n 'eui-file-upload': 'EuiFileUploadComponent',\n },\n },\n EuiGrowlModule: {\n importPath: '@eui/components/eui-growl',\n selectors: {\n 'eui-growl': 'EuiGrowlComponent',\n },\n },\n EuiIconModule: {\n importPath: '@eui/components/eui-icon',\n selectors: {\n 'eui-icon-svg': 'EuiIconSvgComponent',\n euiIconSvg: 'EuiIconSvgComponent',\n },\n },\n EuiIconButtonModule: {\n importPath: '@eui/components/eui-icon-button',\n selectors: {\n 'eui-icon-button': 'EuiIconButtonComponent',\n },\n },\n EuiIconToggleModule: {\n importPath: '@eui/components/eui-icon-toggle',\n selectors: {\n 'eui-icon-toggle': 'EuiIconToggleComponent',\n },\n },\n EuiInputCheckboxModule: {\n importPath: '@eui/components/eui-input-checkbox',\n selectors: {\n euiInputCheckBox: 'EuiInputCheckboxComponent',\n },\n },\n EuiInputGroupModule: {\n importPath: '@eui/components/eui-input-group',\n selectors: {\n euiInputGroup: 'EuiInputGroupComponent',\n 'eui-input-group-addon': 'EuiInputGroupAddOnComponent',\n euiInputGroupAddOn: 'EuiInputGroupAddOnComponent',\n 'eui-input-group-addon-item': 'EuiInputGroupAddOnItemComponent',\n euiInputGroupAddOnItem: 'EuiInputGroupAddOnItemComponent',\n },\n },\n EuiInputNumberModule: {\n importPath: '@eui/components/eui-input-number',\n selectors: {\n euiInputNumber: 'EuiInputNumberComponent',\n },\n },\n EuiInputRadioModule: {\n importPath: '@eui/components/eui-input-radio',\n selectors: {\n euiInputRadio: 'EuiInputRadioComponent',\n },\n },\n EuiInputTextModule: {\n importPath: '@eui/components/eui-input-text',\n selectors: {\n euiInputText: 'EuiInputTextComponent',\n },\n },\n EuiLabelModule: {\n importPath: '@eui/components/eui-label',\n selectors: {\n 'eui-label': 'EuiLabelComponent',\n euiLabel: 'EuiLabelComponent',\n },\n },\n EuiListModule: {\n importPath: '@eui/components/eui-list',\n selectors: {\n 'eui-list': 'EuiListComponent',\n euiList: 'EuiListComponent',\n 'eui-list-item': 'EuiListItemComponent',\n euiListItem: 'EuiListItemComponent',\n },\n },\n EuiMenuModule: {\n importPath: '@eui/components/eui-menu',\n selectors: {\n 'eui-menu': 'EuiMenuComponent',\n 'eui-menu-item': 'EuiMenuItemComponent',\n },\n },\n EuiMessageBoxModule: {\n importPath: '@eui/components/eui-message-box',\n selectors: {\n 'eui-message-box': 'EuiMessageBoxComponent',\n 'eui-message-box-footer': 'EuiMessageBoxFooterDirective',\n },\n },\n EuiOverlayModule: {\n importPath: '@eui/components/eui-overlay',\n selectors: {\n 'eui-overlay': 'EuiOverlayComponent',\n },\n },\n EuiPageModule: {\n importPath: '@eui/components/eui-page',\n selectors: {\n 'eui-page': 'EuiPageComponent',\n },\n },\n EuiPaginatorModule: {\n importPath: '@eui/components/eui-paginator',\n selectors: {\n 'eui-paginator': 'EuiPaginatorComponent',\n },\n },\n EuiPopoverModule: {\n importPath: '@eui/components/eui-popover',\n selectors: {\n 'eui-popover': 'EuiPopoverComponent',\n },\n },\n EuiProgressBarModule: {\n importPath: '@eui/components/eui-progress-bar',\n selectors: {\n 'eui-progress-bar': 'EuiProgressBarComponent',\n },\n },\n EuiProgressCircleModule: {\n importPath: '@eui/components/eui-progress-circle',\n selectors: {\n 'eui-progress-circle': 'EuiProgressCircleComponent',\n },\n },\n EuiSelectModule: {\n importPath: '@eui/components/eui-select',\n selectors: {\n euiSelect: 'EuiSelectComponent',\n },\n },\n EuiSidebarMenuModule: {\n importPath: '@eui/components/eui-sidebar-menu',\n selectors: {\n 'eui-sidebar-menu': 'EuiSidebarMenuComponent',\n },\n },\n EuiSkeletonModule: {\n importPath: '@eui/components/eui-skeleton',\n selectors: {\n 'eui-skeleton': 'EuiSkeletonComponent',\n },\n },\n EuiSlideToggleModule: {\n importPath: '@eui/components/eui-slide-toggle',\n selectors: {\n 'eui-slide-toggle': 'EuiSlideToggleComponent',\n },\n },\n EuiTableModule: {\n importPath: '@eui/components/eui-table',\n selectors: {\n 'eui-table': 'EuiTableComponent',\n euiTable: 'EuiTableComponent',\n 'eui-table-filter': 'EuiTableFilterComponent',\n isSortable: 'EuiTableSortableColComponent',\n isStickyCol: 'EuiTableStickyColDirective',\n isHeaderSelectable: 'EuiTableSelectableHeaderComponent',\n isDataSelectable: 'EuiTableSelectableRowComponent',\n isExpandableRow: 'EuiTableExpandableRowDirective',\n },\n },\n EuiTableV2Module: {\n importPath: '@eui/components/eui-table',\n selectors: {\n 'eui-table': 'EuiTableComponent',\n euiTable: 'EuiTableComponent',\n 'eui-table-filter': 'EuiTableFilterComponent',\n isSortable: 'EuiTableSortableColComponent',\n isStickyCol: 'EuiTableStickyColDirective',\n isHeaderSelectable: 'EuiTableSelectableHeaderComponent',\n isDataSelectable: 'EuiTableSelectableRowComponent',\n isExpandableRow: 'EuiTableExpandableRowDirective',\n },\n },\n EuiTabsModule: {\n importPath: '@eui/components/eui-tabs',\n selectors: {\n 'eui-tabs': 'EuiTabsComponent',\n 'eui-tab': 'EuiTabComponent',\n 'eui-tab-header': 'EuiTabHeaderComponent',\n 'eui-tab-body': 'EuiTabBodyComponent',\n },\n },\n EuiTextAreaModule: {\n importPath: '@eui/components/eui-textarea',\n selectors: {\n euiTextArea: 'EuiTextareaComponent',\n },\n },\n EuiTimelineModule: {\n importPath: '@eui/components/eui-timeline',\n selectors: {\n 'eui-timeline': 'EuiTimelineComponent',\n 'eui-timeline-item': 'EuiTimelineItemComponent',\n },\n },\n EuiTimepickerModule: {\n importPath: '@eui/components/eui-timepicker',\n selectors: {\n 'eui-timepicker': 'EuiTimepickerComponent',\n },\n },\n EuiTreeModule: {\n importPath: '@eui/components/eui-tree',\n selectors: {\n 'eui-tree': 'EuiTreeComponent',\n },\n },\n EuiTreeListModule: {\n importPath: '@eui/components/eui-tree-list',\n selectors: {\n 'eui-tree-list': 'EuiTreeListComponent',\n 'eui-tree-list-item': 'EuiTreeListItemComponent',\n },\n },\n EuiUserProfileModule: {\n importPath: '@eui/components/eui-user-profile',\n selectors: {\n 'eui-user-profile': 'EuiUserProfileComponent',\n },\n },\n EuiWizardModule: {\n importPath: '@eui/components/eui-wizard',\n selectors: {\n 'eui-wizard': 'EuiWizardComponent',\n 'eui-wizard-step': 'EuiWizardStepComponent',\n },\n },\n EuiTooltipDirectiveModule: {\n importPath: '@eui/components/directives',\n selectors: {\n euiTooltip: 'EuiTooltipDirective',\n },\n },\n EuiTemplateDirectiveModule: {\n importPath: '@eui/components/directives',\n selectors: {\n euiTemplate: 'EuiTemplateDirective',\n },\n },\n EuiResizableDirectiveModule: {\n importPath: '@eui/components/directives',\n selectors: {\n euiResizable: 'EuiResizableDirective',\n 'eui-resizable': 'EuiResizableComponent',\n },\n },\n EuiMaxLengthDirectiveModule: {\n importPath: '@eui/components/directives',\n selectors: {\n euiEditorMaxlength: 'EuiMaxLengthDirective',\n },\n },\n EuiTruncatePipeModule: {\n importPath: '@eui/components/pipes',\n selectors: {\n euiTruncate: 'EuiTruncatePipe',\n },\n },\n EuiLayoutModule: {\n importPath: '@eui/components/layout',\n selectors: {\n 'eui-app': 'EuiAppComponent',\n 'eui-header': 'EuiHeaderComponent',\n 'eui-footer': 'EuiFooterComponent',\n 'eui-toolbar': 'EuiToolbarComponent',\n 'eui-sidebar-toggle': 'EuiSidebarToggleComponent',\n },\n },\n};\n\ninterface Schema {\n path?: string;\n dryRun?: boolean;\n}\n\nexport function migrateToStandalone(options: Schema = {}): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const scanPath = options.path ? '/' + options.path.replace(/^\\.?\\//, '').replace(/\\/$/, '') : '';\n const allModuleNames = Object.keys(MODULE_MAPPINGS);\n\n visitDir(tree.getDir(scanPath || '/'), (path) => {\n const buffer = tree.read(path);\n if (!buffer) return;\n\n const source = buffer.toString('utf-8');\n if (!allModuleNames.some((m) => source.includes(m))) return;\n\n const sourceFile = ts.createSourceFile(path, source, ts.ScriptTarget.Latest, true);\n const componentDecorators = findComponentDecorators(sourceFile);\n\n for (const decorator of componentDecorators) {\n const importsNode = findImportsArrayNode(decorator);\n if (!importsNode) continue;\n\n const currentSource = tree.read(path)!.toString('utf-8');\n const modulesInArray = allModuleNames.filter((m) => hasModuleInArray(importsNode, m, source));\n if (modulesInArray.length === 0) continue;\n\n const templateSelectors = getTemplateSelectors(tree, path, decorator, source);\n const replacements = buildReplacements(modulesInArray, templateSelectors);\n if (replacements.size === 0) continue;\n\n const result = applyReplacements(currentSource, path, replacements);\n if (options.dryRun) {\n logDryRun(context, `Would replace module imports with standalone imports in ${path}`);\n } else {\n tree.overwrite(path, result);\n }\n }\n });\n\n context.logger.info('Migration to standalone imports complete.');\n if (options.dryRun) {\n logDryRunNote(context);\n }\n return tree;\n };\n}\n\nfunction visitDir(dir: DirEntry, callback: (path: string) => void): void {\n for (const file of dir.subfiles) {\n if (file.endsWith('.d.ts')) continue;\n if (!file.endsWith('.ts')) continue;\n callback(`${dir.path}/${file}`);\n }\n for (const sub of dir.subdirs) {\n if (sub === 'node_modules' || sub === 'dist') continue;\n visitDir(dir.dir(sub), callback);\n }\n}\n\nfunction buildReplacements(moduleNames: string[], templateSelectors: Set<string>): Map<string, { components: string[]; importPath: string }> {\n const map = new Map<string, { components: string[]; importPath: string }>();\n\n for (const moduleName of moduleNames) {\n const mapping = MODULE_MAPPINGS[moduleName];\n const components: string[] = [];\n\n for (const [selector, component] of Object.entries(mapping.selectors)) {\n if (templateSelectors.has(selector)) {\n components.push(component);\n }\n }\n\n if (components.length > 0) {\n map.set(moduleName, { components: [...new Set(components)].sort(), importPath: mapping.importPath });\n }\n }\n\n return map;\n}\n\nfunction findComponentDecorators(sourceFile: ts.SourceFile): ts.Decorator[] {\n const decorators: ts.Decorator[] = [];\n const visit = (node: ts.Node): void => {\n if (ts.isClassDeclaration(node)) {\n const decs = ts.getDecorators(node);\n if (decs) {\n for (const dec of decs) {\n if (ts.isCallExpression(dec.expression) && ts.isIdentifier(dec.expression.expression) && dec.expression.expression.text === 'Component') {\n decorators.push(dec);\n }\n }\n }\n }\n ts.forEachChild(node, visit);\n };\n visit(sourceFile);\n return decorators;\n}\n\nfunction findImportsArrayNode(decorator: ts.Decorator): ts.ArrayLiteralExpression | undefined {\n const call = decorator.expression as ts.CallExpression;\n const metadata = call.arguments[0];\n if (!ts.isObjectLiteralExpression(metadata)) return undefined;\n\n for (const prop of metadata.properties) {\n if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name) && prop.name.text === 'imports') {\n if (ts.isArrayLiteralExpression(prop.initializer)) {\n return prop.initializer;\n }\n }\n }\n return undefined;\n}\n\nfunction hasModuleInArray(array: ts.ArrayLiteralExpression, moduleName: string, source: string): boolean {\n return array.elements.some((el) => source.slice(el.getStart(), el.getEnd()).trim() === moduleName);\n}\n\nfunction getTemplateSelectors(tree: Tree, tsPath: string, decorator: ts.Decorator, source: string): Set<string> {\n const call = decorator.expression as ts.CallExpression;\n const metadata = call.arguments[0] as ts.ObjectLiteralExpression;\n const allSelectors = Object.values(MODULE_MAPPINGS).flatMap((m) => Object.keys(m.selectors));\n\n for (const prop of metadata.properties) {\n if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name) && prop.name.text === 'template') {\n const init = prop.initializer;\n if (ts.isStringLiteral(init) || ts.isNoSubstitutionTemplateLiteral(init)) {\n return findSelectorsInTemplate(init.text, allSelectors);\n }\n }\n }\n\n for (const prop of metadata.properties) {\n if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name) && prop.name.text === 'templateUrl') {\n if (ts.isStringLiteral(prop.initializer)) {\n const dir = tsPath.substring(0, tsPath.lastIndexOf('/'));\n const templateBuffer = tree.read(`${dir}/${prop.initializer.text}`);\n if (templateBuffer) {\n return findSelectorsInTemplate(templateBuffer.toString('utf-8'), allSelectors);\n }\n }\n }\n }\n\n return new Set();\n}\n\nfunction findSelectorsInTemplate(html: string, knownSelectors: string[]): Set<string> {\n const selectors = new Set<string>();\n const parsed = parseTemplate(html, '', { preserveWhitespaces: true });\n\n const visit = (nodes: TmplAstNode[]): void => {\n for (const node of nodes) {\n if (node instanceof TmplAstElement) {\n if (knownSelectors.includes(node.name)) selectors.add(node.name);\n for (const attr of node.attributes) {\n if (knownSelectors.includes(attr.name)) selectors.add(attr.name);\n }\n visit(node.children);\n }\n }\n };\n visit(parsed.nodes);\n return selectors;\n}\n\nfunction applyReplacements(source: string, filePath: string, replacements: Map<string, { components: string[]; importPath: string }>): string {\n const sourceFile = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true);\n let result = replaceInImportsArray(source, sourceFile, replacements);\n result = updateEsImports(result, filePath, replacements);\n return result;\n}\n\nfunction replaceInImportsArray(source: string, sourceFile: ts.SourceFile, replacements: Map<string, { components: string[]; importPath: string }>): string {\n let result = source;\n const visit = (node: ts.Node): void => {\n if (ts.isClassDeclaration(node)) {\n const decs = ts.getDecorators(node);\n if (!decs) return;\n for (const dec of decs) {\n if (!ts.isCallExpression(dec.expression) || !ts.isIdentifier(dec.expression.expression) || dec.expression.expression.text !== 'Component') continue;\n const metadata = dec.expression.arguments[0];\n if (!ts.isObjectLiteralExpression(metadata)) continue;\n for (const prop of metadata.properties) {\n if (!ts.isPropertyAssignment(prop) || !ts.isIdentifier(prop.name) || prop.name.text !== 'imports') continue;\n if (!ts.isArrayLiteralExpression(prop.initializer)) continue;\n const newElements = prop.initializer.elements\n .map((el) => {\n const text = result.slice(el.getStart(sourceFile), el.getEnd()).trim();\n const replacement = replacements.get(text);\n return replacement ? replacement.components.join(', ') : text;\n })\n .join(', ');\n result = result.slice(0, prop.initializer.getStart(sourceFile) + 1) + newElements + result.slice(prop.initializer.getEnd() - 1);\n }\n }\n }\n ts.forEachChild(node, visit);\n };\n visit(sourceFile);\n return result;\n}\n\nfunction updateEsImports(source: string, filePath: string, replacements: Map<string, { components: string[]; importPath: string }>): string {\n let result = source;\n\n for (const [moduleName, { components, importPath }] of replacements) {\n const sf = ts.createSourceFile(filePath, result, ts.ScriptTarget.Latest, true);\n\n for (const stmt of sf.statements) {\n if (!ts.isImportDeclaration(stmt) || !stmt.importClause?.namedBindings || !ts.isNamedImports(stmt.importClause.namedBindings)) continue;\n const namedBindings = stmt.importClause.namedBindings;\n const importNames = namedBindings.elements.map((el) => el.name.text);\n if (!importNames.includes(moduleName)) continue;\n\n const moduleSpecifier = (stmt.moduleSpecifier as ts.StringLiteral).text;\n const remaining = importNames.filter((n) => n !== moduleName);\n const toAdd = components.filter((c) => !importNames.includes(c));\n\n if (moduleSpecifier === importPath) {\n const newNames = [...remaining, ...toAdd].sort();\n const newClause = `{ ${newNames.join(', ')} }`;\n result = result.slice(0, namedBindings.getStart(sf)) + newClause + result.slice(namedBindings.getEnd());\n } else {\n if (remaining.length > 0) {\n const newClause = `{ ${remaining.join(', ')} }`;\n result = result.slice(0, namedBindings.getStart(sf)) + newClause + result.slice(namedBindings.getEnd());\n } else {\n result = result.slice(0, stmt.getStart(sf)) + result.slice(stmt.getEnd()).replace(/^\\r?\\n/, '');\n }\n\n if (toAdd.length > 0) {\n const updatedSf = ts.createSourceFile(filePath, result, ts.ScriptTarget.Latest, true);\n const existing = updatedSf.statements.find(\n (s) => ts.isImportDeclaration(s) && ts.isStringLiteral(s.moduleSpecifier) && s.moduleSpecifier.text === importPath,\n ) as ts.ImportDeclaration | undefined;\n\n if (existing?.importClause?.namedBindings && ts.isNamedImports(existing.importClause.namedBindings)) {\n const existingNames = existing.importClause.namedBindings.elements.map((el) => el.name.text);\n const allNames = [...new Set([...existingNames, ...toAdd])].sort();\n const newClause = `{ ${allNames.join(', ')} }`;\n result = result.slice(0, existing.importClause.namedBindings.getStart(updatedSf)) + newClause + result.slice(existing.importClause.namedBindings.getEnd());\n } else {\n const newImport = `import { ${toAdd.join(', ')} } from '${importPath}';\\n`;\n result = newImport + result;\n }\n }\n }\n break;\n }\n }\n\n return result;\n}\n",
3155
+ "sourceCode": "import { DirEntry, Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\nimport { parseTemplate, TmplAstElement, TmplAstNode } from '@angular/compiler';\nimport * as ts from 'typescript';\nimport { logDryRun, logDryRunNote } from '../utils/dry-run';\nimport { EUI_SIGNAL_MAP, EUI_SELECTOR_TO_CLASS } from './signal-map';\n\ninterface Schema {\n path?: string;\n dryRun?: boolean;\n}\n\ninterface Edit {\n start: number;\n end: number;\n replacement: string;\n}\n\n/**\n * Migrates consumer code that accesses EUI component instances programmatically.\n *\n * When EUI migrated @Input() → input(), @ViewChild() → viewChild(), and\n * @ContentChild() → contentChild(), properties that were plain class fields\n * became signal getters. Consumers who access them via @ViewChild need to\n * change `comp.prop` to `comp.prop()`.\n *\n * This schematic:\n * 1. Finds @ViewChild / @ContentChild fields typed as EUI component classes\n * 2. Resolves untyped @ViewChild('refName') by reading the component template\n * and matching #refName to an EUI element tag/selector\n * 3. Tracks which local variable names hold EUI component references (incl. aliases)\n * 4. Rewrites property accesses on those references: `ref.prop` → `ref.prop()`\n * (only for properties listed in the signal map)\n * 5. Does NOT touch template bindings — those are unaffected by signal migrations\n */\nexport function migrateToSignals(options: Schema = {}): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const scanPath = options.path ? '/' + options.path.replace(/^\\.?\\//, '').replace(/\\/$/, '') : '';\n let fileCount = 0;\n let propCount = 0;\n\n visitDir(tree.getDir(scanPath || '/'), (path) => {\n if (!path.endsWith('.ts')) return;\n // Skip spec files — test code may use different patterns\n if (path.endsWith('.spec.ts')) return;\n\n const buffer = tree.read(path);\n if (!buffer) return;\n\n const original = buffer.toString('utf-8');\n\n // Fast bail: file must mention at least one EUI class name or have\n // ViewChild/ContentChild with string refs (which might reference EUI elements)\n if (!hasEuiReference(original) && !hasStringRefQuery(original)) return;\n\n const result = migrateTypeScript(original, path, tree, context); if (result.source !== original) {\n if (options.dryRun) {\n logDryRun(context, `Would migrate ${result.editCount} signal property access(es) in ${path}`);\n } else {\n tree.overwrite(path, result.source);\n }\n fileCount++;\n propCount += result.editCount;\n }\n });\n\n context.logger.info(`Migrated ${propCount} property access(es) to signal getters in ${fileCount} file(s).`);\n if (options.dryRun) {\n logDryRunNote(context);\n }\n return tree;\n };\n}\n\n/** Quick check: does the file reference any EUI class name from the signal map? */\nfunction hasEuiReference(source: string): boolean {\n for (const className of Object.keys(EUI_SIGNAL_MAP)) {\n if (source.includes(className)) return true;\n }\n return false;\n}\n\n/** Quick check: does the file have @ViewChild('...') or @ContentChild('...') with string refs? */\nfunction hasStringRefQuery(source: string): boolean {\n return /(@ViewChild|@ContentChild|@ViewChildren|@ContentChildren)\\s*\\(\\s*['\"]/.test(source);\n}\n\ninterface MigrateResult {\n source: string;\n editCount: number;\n}\n\nfunction migrateTypeScript(source: string, filePath: string, tree: Tree, context: SchematicContext): MigrateResult {\n const sourceFile = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n const edits: Edit[] = [];\n\n // Phase 0: Build template ref map (#refName → EUI class name) from the component's template\n const templateRefMap = buildTemplateRefMap(sourceFile, source, filePath, tree);\n\n // Phase 1: Collect all variables/properties typed as EUI classes\n const euiRefs = collectEuiReferences(sourceFile, source, templateRefMap);\n\n if (euiRefs.size === 0) {\n return { source, editCount: 0 };\n }\n\n // Phase 2: Find property accesses on those references and rewrite signal props\n const visitNode = (node: ts.Node): void => {\n // Match: ref.prop (PropertyAccessExpression)\n if (ts.isPropertyAccessExpression(node)) {\n const rewrite = tryRewritePropertyAccess(node, euiRefs, sourceFile, source);\n if (rewrite) {\n edits.push(rewrite);\n }\n }\n ts.forEachChild(node, visitNode);\n };\n\n ts.forEachChild(sourceFile, visitNode);\n\n if (edits.length === 0) {\n return { source, editCount: 0 };\n }\n\n return {\n source: applyEdits(source, edits),\n editCount: edits.length,\n };\n}\n\n/**\n * Scans the source file for class properties or variables typed as EUI component classes.\n * Returns a map: localName → Set of signal property names.\n *\n * Handles:\n * @ViewChild(EuiXxxComponent) name: EuiXxxComponent;\n * @ViewChild(EuiXxxComponent) name!: EuiXxxComponent;\n * @ViewChild('ref') name: EuiXxxComponent;\n * @ContentChild(EuiXxxComponent) name: EuiXxxComponent;\n * @ViewChild('ref') name: ElementRef; (resolved via template #ref → EUI selector)\n * someVar: EuiXxxComponent; (typed class field, even without decorator)\n * const alias = this.viewChildRef; (alias tracking)\n */\nfunction collectEuiReferences(\n sourceFile: ts.SourceFile,\n source: string,\n templateRefMap: Map<string, string>,\n): Map<string, ReadonlySet<string>> {\n const refs = new Map<string, ReadonlySet<string>>();\n\n // Pass 1: collect directly-typed references\n const visitDirect = (node: ts.Node): void => {\n // Class property declarations\n if (ts.isPropertyDeclaration(node) && node.name && ts.isIdentifier(node.name)) {\n const euiClass = resolveEuiClassName(node, sourceFile, templateRefMap);\n if (euiClass && EUI_SIGNAL_MAP[euiClass]) {\n refs.set(node.name.text, EUI_SIGNAL_MAP[euiClass]);\n }\n }\n\n // Variable declarations (const x: EuiXxxComponent = ...)\n if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name)) {\n const typeName = getTypeAnnotationName(node.type);\n if (typeName && EUI_SIGNAL_MAP[typeName]) {\n refs.set(node.name.text, EUI_SIGNAL_MAP[typeName]);\n }\n }\n\n // Parameter declarations (method(ref: EuiXxxComponent))\n if (ts.isParameter(node) && ts.isIdentifier(node.name)) {\n const typeName = getTypeAnnotationName(node.type);\n if (typeName && EUI_SIGNAL_MAP[typeName]) {\n refs.set(node.name.text, EUI_SIGNAL_MAP[typeName]);\n }\n }\n\n ts.forEachChild(node, visitDirect);\n };\n\n ts.forEachChild(sourceFile, visitDirect);\n\n // Pass 2: track aliases — variables assigned from already-tracked references\n // e.g. const alias = this.viewChildRef; or const alias = someParam;\n const visitAlias = (node: ts.Node): void => {\n if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name) && node.initializer) {\n // Skip if already tracked (has explicit type annotation)\n if (refs.has(node.name.text)) {\n ts.forEachChild(node, visitAlias);\n return;\n }\n\n const aliasedRef = resolveRefName(node.initializer);\n if (aliasedRef && refs.has(aliasedRef)) {\n refs.set(node.name.text, refs.get(aliasedRef)!);\n }\n }\n\n ts.forEachChild(node, visitAlias);\n };\n\n ts.forEachChild(sourceFile, visitAlias);\n return refs;\n}\n\n/**\n * Resolves the EUI class name from a property declaration.\n * Checks: type annotation → decorator class argument → template ref map.\n */\nfunction resolveEuiClassName(\n node: ts.PropertyDeclaration,\n sourceFile: ts.SourceFile,\n templateRefMap: Map<string, string>,\n): string | null {\n // Check type annotation first\n const typeName = getTypeAnnotationName(node.type);\n if (typeName && EUI_SIGNAL_MAP[typeName]) {\n return typeName;\n }\n\n // Check generic type argument: ElementRef<EuiXxxComponent>\n if (node.type && ts.isTypeReferenceNode(node.type) && node.type.typeArguments?.length) {\n const genericArg = getTypeAnnotationName(node.type.typeArguments[0]);\n if (genericArg && EUI_SIGNAL_MAP[genericArg]) {\n return genericArg;\n }\n }\n\n // Check decorator arguments: @ViewChild(EuiXxxComponent) or @ViewChild('refName')\n if (node.modifiers) {\n for (const modifier of node.modifiers) {\n if (!ts.isDecorator(modifier)) continue;\n if (!ts.isCallExpression(modifier.expression)) continue;\n\n const decoratorName = getDecoratorName(modifier.expression);\n if (!decoratorName) continue;\n if (!['ViewChild', 'ViewChildren', 'ContentChild', 'ContentChildren'].includes(decoratorName)) continue;\n\n const args = modifier.expression.arguments;\n if (args.length > 0) {\n const firstArg = args[0];\n\n // @ViewChild(EuiXxxComponent) — class reference\n if (ts.isIdentifier(firstArg) && EUI_SIGNAL_MAP[firstArg.text]) {\n return firstArg.text;\n }\n\n // @ViewChild('refName') — string template ref, resolve via template\n if (ts.isStringLiteralLike(firstArg)) {\n const refName = firstArg.text;\n const euiClass = templateRefMap.get(refName);\n if (euiClass && EUI_SIGNAL_MAP[euiClass]) {\n return euiClass;\n }\n }\n }\n }\n }\n\n return null;\n}\n\nfunction getDecoratorName(callExpr: ts.CallExpression): string | null {\n if (ts.isIdentifier(callExpr.expression)) {\n return callExpr.expression.text;\n }\n return null;\n}\n\nfunction getTypeAnnotationName(typeNode: ts.TypeNode | undefined): string | null {\n if (!typeNode) return null;\n if (ts.isTypeReferenceNode(typeNode) && ts.isIdentifier(typeNode.typeName)) {\n return typeNode.typeName.text;\n }\n return null;\n}\n\n/**\n * Checks if a property access `ref.prop` should be rewritten to `ref.prop()`.\n *\n * We rewrite if:\n * - `ref` is tracked in euiRefs\n * - `prop` is in the signal set for that EUI class\n * - The access is NOT already a call expression (not `ref.prop()` or `ref.prop(args)`)\n * - The access is NOT a write target (not `ref.prop = value`)\n * - The access is NOT a template binding argument (those are unaffected)\n */\nfunction tryRewritePropertyAccess(\n node: ts.PropertyAccessExpression,\n euiRefs: Map<string, ReadonlySet<string>>,\n sourceFile: ts.SourceFile,\n source: string,\n): Edit | null {\n const propName = node.name.text;\n\n // Resolve the reference name — handle `this.ref.prop` and `ref.prop`\n const refName = resolveRefName(node.expression);\n if (!refName) return null;\n\n const signalProps = euiRefs.get(refName);\n if (!signalProps || !signalProps.has(propName)) return null;\n\n // Skip if parent is already a call expression on this property: ref.prop(...)\n if (ts.isCallExpression(node.parent) && node.parent.expression === node) {\n return null;\n }\n\n // Skip if this is the left side of an assignment: ref.prop = value\n if (ts.isBinaryExpression(node.parent) &&\n node.parent.operatorToken.kind === ts.SyntaxKind.EqualsToken &&\n node.parent.left === node) {\n return null;\n }\n\n // Skip if this is a compound assignment: ref.prop += value, ref.prop &&= value, etc.\n if (ts.isBinaryExpression(node.parent) && isAssignmentOperator(node.parent.operatorToken.kind) && node.parent.left === node) {\n return null;\n }\n\n // Skip if this is used with delete: delete ref.prop\n if (ts.isDeleteExpression(node.parent) && node.parent.expression === node) {\n return null;\n }\n\n // Skip if inside a typeof: typeof ref.prop\n if (ts.isTypeOfExpression(node.parent) && node.parent.expression === node) {\n return null;\n }\n\n // Skip property access chains that go deeper: ref.prop.something → ref.prop().something\n // This IS correct — we still want to add ()\n\n // Rewrite: insert () after the property name\n const end = node.name.getEnd();\n return {\n start: end,\n end: end,\n replacement: '()',\n };\n}\n\nfunction isAssignmentOperator(kind: ts.SyntaxKind): boolean {\n return kind >= ts.SyntaxKind.FirstAssignment && kind <= ts.SyntaxKind.LastAssignment;\n}\n\n/**\n * Resolves a reference name from an expression.\n * Handles: `ref`, `this.ref`, `this._ref`\n */\nfunction resolveRefName(expr: ts.Expression): string | null {\n // Direct identifier: ref.prop\n if (ts.isIdentifier(expr)) {\n return expr.text;\n }\n\n // this.ref.prop\n if (ts.isPropertyAccessExpression(expr) && expr.expression.kind === ts.SyntaxKind.ThisKeyword) {\n return expr.name.text;\n }\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Template ref resolution\n// ---------------------------------------------------------------------------\n\n/**\n * Builds a map of template reference variable names (#ref) to EUI class names.\n *\n * Parses the component's template (inline or external) and finds elements like:\n * <eui-alert #myAlert> → myAlert → EuiAlertComponent\n * <input euiAutocomplete #ac> → ac → EuiAutocompleteComponent\n *\n * Returns Map<refName, euiClassName>.\n */\nfunction buildTemplateRefMap(\n sourceFile: ts.SourceFile,\n source: string,\n filePath: string,\n tree: Tree,\n): Map<string, string> {\n const refMap = new Map<string, string>();\n\n // Find @Component decorator\n const componentMeta = findComponentMetadata(sourceFile, source);\n if (!componentMeta) return refMap;\n\n let templateSource: string | null = null;\n\n if (componentMeta.inlineTemplate !== null) {\n templateSource = componentMeta.inlineTemplate;\n } else if (componentMeta.templateUrl) {\n // Resolve templateUrl relative to the TS file\n const dir = filePath.substring(0, filePath.lastIndexOf('/'));\n const templatePath = `${dir}/${componentMeta.templateUrl}`;\n const buffer = tree.read(templatePath);\n if (buffer) {\n templateSource = buffer.toString('utf-8');\n }\n }\n\n if (!templateSource) return refMap;\n\n // Parse the template and collect #refs\n try {\n const parsed = parseTemplate(templateSource, '', { preserveWhitespaces: true });\n collectTemplateRefs(parsed.nodes, refMap);\n } catch {\n // Template parse failure — silently skip (might be malformed or use third-party syntax)\n }\n\n return refMap;\n}\n\n/**\n * Extracts @Component metadata: templateUrl or inline template content.\n */\nfunction findComponentMetadata(\n sourceFile: ts.SourceFile,\n source: string,\n): { templateUrl: string | null; inlineTemplate: string | null } | null {\n let result: { templateUrl: string | null; inlineTemplate: string | null } | null = null;\n\n const visit = (node: ts.Node): void => {\n if (result) return;\n\n if (ts.isDecorator(node) && ts.isCallExpression(node.expression)) {\n const name = getDecoratorName(node.expression);\n if (name !== 'Component') {\n ts.forEachChild(node, visit);\n return;\n }\n\n const args = node.expression.arguments;\n if (args.length === 0 || !ts.isObjectLiteralExpression(args[0])) {\n ts.forEachChild(node, visit);\n return;\n }\n\n const meta: { templateUrl: string | null; inlineTemplate: string | null } = {\n templateUrl: null,\n inlineTemplate: null,\n };\n\n for (const prop of args[0].properties) {\n if (!ts.isPropertyAssignment(prop) || !ts.isIdentifier(prop.name)) continue;\n\n if (prop.name.text === 'templateUrl') {\n const init = unwrapExpression(prop.initializer);\n if (ts.isStringLiteralLike(init)) {\n meta.templateUrl = init.text;\n }\n }\n\n if (prop.name.text === 'template') {\n const init = unwrapExpression(prop.initializer);\n if (ts.isStringLiteralLike(init)) {\n meta.inlineTemplate = init.text;\n } else if (ts.isNoSubstitutionTemplateLiteral(init)) {\n meta.inlineTemplate = init.text;\n }\n }\n }\n\n result = meta;\n return;\n }\n\n ts.forEachChild(node, visit);\n };\n\n ts.forEachChild(sourceFile, visit);\n return result;\n}\n\nfunction unwrapExpression(expression: ts.Expression): ts.Expression {\n let current = expression;\n while (ts.isParenthesizedExpression(current)) current = current.expression;\n return current;\n}\n\n/**\n * Recursively walks template AST nodes, collecting #refName → EUI class name mappings.\n *\n * For each element with a template reference (#ref), we try to resolve its EUI class:\n * 1. Match element tag name against EUI_SELECTOR_TO_CLASS (e.g. 'eui-alert' → EuiAlertComponent)\n * 2. Match element attributes against attribute selectors (e.g. [euiAutocomplete] → EuiAutocompleteComponent)\n */\nfunction collectTemplateRefs(nodes: TmplAstNode[], refMap: Map<string, string>): void {\n for (const node of nodes) {\n if (node instanceof TmplAstElement) {\n if (node.references && node.references.length > 0) {\n const euiClass = resolveElementToEuiClass(node);\n if (euiClass) {\n for (const ref of node.references) {\n refMap.set(ref.name, euiClass);\n }\n }\n }\n collectTemplateRefs(node.children, refMap);\n }\n }\n}\n\n/**\n * Given a template element, resolves it to an EUI class name by checking:\n * 1. Tag name: <eui-alert> → look up 'eui-alert' in EUI_SELECTOR_TO_CLASS\n * 2. Attribute selectors: <input euiAutocomplete> → look up 'input[euiAutocomplete]' or '[euiAutocomplete]'\n */\nfunction resolveElementToEuiClass(element: TmplAstElement): string | null {\n const tag = element.name;\n\n // Direct tag match: eui-alert, eui-dialog, etc.\n if (EUI_SELECTOR_TO_CLASS[tag]) {\n return EUI_SELECTOR_TO_CLASS[tag];\n }\n\n // Attribute selector match: check all attributes against known patterns\n const allAttrNames = [\n ...element.attributes.map((a) => a.name),\n ...element.inputs.map((i) => i.name),\n ];\n\n for (const attrName of allAttrNames) {\n // Try tag[attr] pattern first (e.g. 'button[euiButton]', 'input[euiAutocomplete]')\n const tagAttrSelector = `${tag}[${attrName}]`;\n if (EUI_SELECTOR_TO_CLASS[tagAttrSelector]) {\n return EUI_SELECTOR_TO_CLASS[tagAttrSelector];\n }\n\n // Try [attr] pattern (e.g. '[euiTooltip]', '[euiLoading]')\n const attrSelector = `[${attrName}]`;\n if (EUI_SELECTOR_TO_CLASS[attrSelector]) {\n return EUI_SELECTOR_TO_CLASS[attrSelector];\n }\n }\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Edit helpers\n// ---------------------------------------------------------------------------\n\nfunction applyEdits(source: string, edits: Edit[]): string {\n const unique = deduplicateEdits(edits);\n let result = source;\n for (const edit of unique.sort((a, b) => b.start - a.start)) {\n result = result.slice(0, edit.start) + edit.replacement + result.slice(edit.end);\n }\n return result;\n}\n\nfunction deduplicateEdits(edits: Edit[]): Edit[] {\n const seen = new Map<string, Edit>();\n for (const edit of edits) {\n const key = `${edit.start}:${edit.end}`;\n seen.set(key, edit);\n }\n return Array.from(seen.values());\n}\n\nfunction visitDir(dir: DirEntry, callback: (path: string) => void): void {\n for (const file of dir.subfiles) {\n if (file.endsWith('.d.ts')) continue;\n if (!file.endsWith('.ts')) continue;\n callback(`${dir.path}/${file}`);\n }\n for (const sub of dir.subdirs) {\n if (sub === 'node_modules' || sub === 'dist') continue;\n visitDir(dir.dir(sub), callback);\n }\n}\n",
3156
3156
  "displayName": "Schema",
3157
3157
  "properties": [
3158
3158
  {
@@ -3164,7 +3164,7 @@
3164
3164
  "indexKey": "",
3165
3165
  "optional": true,
3166
3166
  "description": "",
3167
- "line": 460,
3167
+ "line": 9,
3168
3168
  "rawdescription": "\n"
3169
3169
  },
3170
3170
  {
@@ -3176,7 +3176,7 @@
3176
3176
  "indexKey": "",
3177
3177
  "optional": true,
3178
3178
  "description": "",
3179
- "line": 459,
3179
+ "line": 8,
3180
3180
  "rawdescription": "\n"
3181
3181
  }
3182
3182
  ],
@@ -3194,12 +3194,12 @@
3194
3194
  },
3195
3195
  {
3196
3196
  "name": "Schema",
3197
- "id": "interface-Schema-cac2ac952d8245647e8a48b450e8f127a36bcffb394cf2cd81fe9c0810ed02c19e5e1629dbf29a68a5c6f675aed99570e9ac04ae470e13315e20c92cc0c6c453-22",
3198
- "file": "packages/core/schematics/migrate-to-signals/index.ts",
3197
+ "id": "interface-Schema-817c4b549cc3eab9fcf4936acab2e71182d90a4480369f5c003cbbda10792efa587ad99d65acf049f64e7030e32589e4fabc4a6d7a5621e4fe54725ef91dc9e8-22",
3198
+ "file": "packages/core/schematics/migrate-to-standalone/index.ts",
3199
3199
  "deprecated": false,
3200
3200
  "deprecationMessage": "",
3201
3201
  "type": "interface",
3202
- "sourceCode": "import { DirEntry, Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\nimport { parseTemplate, TmplAstElement, TmplAstNode } from '@angular/compiler';\nimport * as ts from 'typescript';\nimport { logDryRun, logDryRunNote } from '../utils/dry-run';\nimport { EUI_SIGNAL_MAP, EUI_SELECTOR_TO_CLASS } from './signal-map';\n\ninterface Schema {\n path?: string;\n dryRun?: boolean;\n}\n\ninterface Edit {\n start: number;\n end: number;\n replacement: string;\n}\n\n/**\n * Migrates consumer code that accesses EUI component instances programmatically.\n *\n * When EUI migrated @Input() → input(), @ViewChild() → viewChild(), and\n * @ContentChild() → contentChild(), properties that were plain class fields\n * became signal getters. Consumers who access them via @ViewChild need to\n * change `comp.prop` to `comp.prop()`.\n *\n * This schematic:\n * 1. Finds @ViewChild / @ContentChild fields typed as EUI component classes\n * 2. Resolves untyped @ViewChild('refName') by reading the component template\n * and matching #refName to an EUI element tag/selector\n * 3. Tracks which local variable names hold EUI component references (incl. aliases)\n * 4. Rewrites property accesses on those references: `ref.prop` → `ref.prop()`\n * (only for properties listed in the signal map)\n * 5. Does NOT touch template bindings — those are unaffected by signal migrations\n */\nexport function migrateToSignals(options: Schema = {}): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const scanPath = options.path ? '/' + options.path.replace(/^\\.?\\//, '').replace(/\\/$/, '') : '';\n let fileCount = 0;\n let propCount = 0;\n\n visitDir(tree.getDir(scanPath || '/'), (path) => {\n if (!path.endsWith('.ts')) return;\n // Skip spec files — test code may use different patterns\n if (path.endsWith('.spec.ts')) return;\n\n const buffer = tree.read(path);\n if (!buffer) return;\n\n const original = buffer.toString('utf-8');\n\n // Fast bail: file must mention at least one EUI class name or have\n // ViewChild/ContentChild with string refs (which might reference EUI elements)\n if (!hasEuiReference(original) && !hasStringRefQuery(original)) return;\n\n const result = migrateTypeScript(original, path, tree, context); if (result.source !== original) {\n if (options.dryRun) {\n logDryRun(context, `Would migrate ${result.editCount} signal property access(es) in ${path}`);\n } else {\n tree.overwrite(path, result.source);\n }\n fileCount++;\n propCount += result.editCount;\n }\n });\n\n context.logger.info(`Migrated ${propCount} property access(es) to signal getters in ${fileCount} file(s).`);\n if (options.dryRun) {\n logDryRunNote(context);\n }\n return tree;\n };\n}\n\n/** Quick check: does the file reference any EUI class name from the signal map? */\nfunction hasEuiReference(source: string): boolean {\n for (const className of Object.keys(EUI_SIGNAL_MAP)) {\n if (source.includes(className)) return true;\n }\n return false;\n}\n\n/** Quick check: does the file have @ViewChild('...') or @ContentChild('...') with string refs? */\nfunction hasStringRefQuery(source: string): boolean {\n return /(@ViewChild|@ContentChild|@ViewChildren|@ContentChildren)\\s*\\(\\s*['\"]/.test(source);\n}\n\ninterface MigrateResult {\n source: string;\n editCount: number;\n}\n\nfunction migrateTypeScript(source: string, filePath: string, tree: Tree, context: SchematicContext): MigrateResult {\n const sourceFile = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n const edits: Edit[] = [];\n\n // Phase 0: Build template ref map (#refName → EUI class name) from the component's template\n const templateRefMap = buildTemplateRefMap(sourceFile, source, filePath, tree);\n\n // Phase 1: Collect all variables/properties typed as EUI classes\n const euiRefs = collectEuiReferences(sourceFile, source, templateRefMap);\n\n if (euiRefs.size === 0) {\n return { source, editCount: 0 };\n }\n\n // Phase 2: Find property accesses on those references and rewrite signal props\n const visitNode = (node: ts.Node): void => {\n // Match: ref.prop (PropertyAccessExpression)\n if (ts.isPropertyAccessExpression(node)) {\n const rewrite = tryRewritePropertyAccess(node, euiRefs, sourceFile, source);\n if (rewrite) {\n edits.push(rewrite);\n }\n }\n ts.forEachChild(node, visitNode);\n };\n\n ts.forEachChild(sourceFile, visitNode);\n\n if (edits.length === 0) {\n return { source, editCount: 0 };\n }\n\n return {\n source: applyEdits(source, edits),\n editCount: edits.length,\n };\n}\n\n/**\n * Scans the source file for class properties or variables typed as EUI component classes.\n * Returns a map: localName → Set of signal property names.\n *\n * Handles:\n * @ViewChild(EuiXxxComponent) name: EuiXxxComponent;\n * @ViewChild(EuiXxxComponent) name!: EuiXxxComponent;\n * @ViewChild('ref') name: EuiXxxComponent;\n * @ContentChild(EuiXxxComponent) name: EuiXxxComponent;\n * @ViewChild('ref') name: ElementRef; (resolved via template #ref → EUI selector)\n * someVar: EuiXxxComponent; (typed class field, even without decorator)\n * const alias = this.viewChildRef; (alias tracking)\n */\nfunction collectEuiReferences(\n sourceFile: ts.SourceFile,\n source: string,\n templateRefMap: Map<string, string>,\n): Map<string, ReadonlySet<string>> {\n const refs = new Map<string, ReadonlySet<string>>();\n\n // Pass 1: collect directly-typed references\n const visitDirect = (node: ts.Node): void => {\n // Class property declarations\n if (ts.isPropertyDeclaration(node) && node.name && ts.isIdentifier(node.name)) {\n const euiClass = resolveEuiClassName(node, sourceFile, templateRefMap);\n if (euiClass && EUI_SIGNAL_MAP[euiClass]) {\n refs.set(node.name.text, EUI_SIGNAL_MAP[euiClass]);\n }\n }\n\n // Variable declarations (const x: EuiXxxComponent = ...)\n if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name)) {\n const typeName = getTypeAnnotationName(node.type);\n if (typeName && EUI_SIGNAL_MAP[typeName]) {\n refs.set(node.name.text, EUI_SIGNAL_MAP[typeName]);\n }\n }\n\n // Parameter declarations (method(ref: EuiXxxComponent))\n if (ts.isParameter(node) && ts.isIdentifier(node.name)) {\n const typeName = getTypeAnnotationName(node.type);\n if (typeName && EUI_SIGNAL_MAP[typeName]) {\n refs.set(node.name.text, EUI_SIGNAL_MAP[typeName]);\n }\n }\n\n ts.forEachChild(node, visitDirect);\n };\n\n ts.forEachChild(sourceFile, visitDirect);\n\n // Pass 2: track aliases — variables assigned from already-tracked references\n // e.g. const alias = this.viewChildRef; or const alias = someParam;\n const visitAlias = (node: ts.Node): void => {\n if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name) && node.initializer) {\n // Skip if already tracked (has explicit type annotation)\n if (refs.has(node.name.text)) {\n ts.forEachChild(node, visitAlias);\n return;\n }\n\n const aliasedRef = resolveRefName(node.initializer);\n if (aliasedRef && refs.has(aliasedRef)) {\n refs.set(node.name.text, refs.get(aliasedRef)!);\n }\n }\n\n ts.forEachChild(node, visitAlias);\n };\n\n ts.forEachChild(sourceFile, visitAlias);\n return refs;\n}\n\n/**\n * Resolves the EUI class name from a property declaration.\n * Checks: type annotation → decorator class argument → template ref map.\n */\nfunction resolveEuiClassName(\n node: ts.PropertyDeclaration,\n sourceFile: ts.SourceFile,\n templateRefMap: Map<string, string>,\n): string | null {\n // Check type annotation first\n const typeName = getTypeAnnotationName(node.type);\n if (typeName && EUI_SIGNAL_MAP[typeName]) {\n return typeName;\n }\n\n // Check generic type argument: ElementRef<EuiXxxComponent>\n if (node.type && ts.isTypeReferenceNode(node.type) && node.type.typeArguments?.length) {\n const genericArg = getTypeAnnotationName(node.type.typeArguments[0]);\n if (genericArg && EUI_SIGNAL_MAP[genericArg]) {\n return genericArg;\n }\n }\n\n // Check decorator arguments: @ViewChild(EuiXxxComponent) or @ViewChild('refName')\n if (node.modifiers) {\n for (const modifier of node.modifiers) {\n if (!ts.isDecorator(modifier)) continue;\n if (!ts.isCallExpression(modifier.expression)) continue;\n\n const decoratorName = getDecoratorName(modifier.expression);\n if (!decoratorName) continue;\n if (!['ViewChild', 'ViewChildren', 'ContentChild', 'ContentChildren'].includes(decoratorName)) continue;\n\n const args = modifier.expression.arguments;\n if (args.length > 0) {\n const firstArg = args[0];\n\n // @ViewChild(EuiXxxComponent) — class reference\n if (ts.isIdentifier(firstArg) && EUI_SIGNAL_MAP[firstArg.text]) {\n return firstArg.text;\n }\n\n // @ViewChild('refName') — string template ref, resolve via template\n if (ts.isStringLiteralLike(firstArg)) {\n const refName = firstArg.text;\n const euiClass = templateRefMap.get(refName);\n if (euiClass && EUI_SIGNAL_MAP[euiClass]) {\n return euiClass;\n }\n }\n }\n }\n }\n\n return null;\n}\n\nfunction getDecoratorName(callExpr: ts.CallExpression): string | null {\n if (ts.isIdentifier(callExpr.expression)) {\n return callExpr.expression.text;\n }\n return null;\n}\n\nfunction getTypeAnnotationName(typeNode: ts.TypeNode | undefined): string | null {\n if (!typeNode) return null;\n if (ts.isTypeReferenceNode(typeNode) && ts.isIdentifier(typeNode.typeName)) {\n return typeNode.typeName.text;\n }\n return null;\n}\n\n/**\n * Checks if a property access `ref.prop` should be rewritten to `ref.prop()`.\n *\n * We rewrite if:\n * - `ref` is tracked in euiRefs\n * - `prop` is in the signal set for that EUI class\n * - The access is NOT already a call expression (not `ref.prop()` or `ref.prop(args)`)\n * - The access is NOT a write target (not `ref.prop = value`)\n * - The access is NOT a template binding argument (those are unaffected)\n */\nfunction tryRewritePropertyAccess(\n node: ts.PropertyAccessExpression,\n euiRefs: Map<string, ReadonlySet<string>>,\n sourceFile: ts.SourceFile,\n source: string,\n): Edit | null {\n const propName = node.name.text;\n\n // Resolve the reference name — handle `this.ref.prop` and `ref.prop`\n const refName = resolveRefName(node.expression);\n if (!refName) return null;\n\n const signalProps = euiRefs.get(refName);\n if (!signalProps || !signalProps.has(propName)) return null;\n\n // Skip if parent is already a call expression on this property: ref.prop(...)\n if (ts.isCallExpression(node.parent) && node.parent.expression === node) {\n return null;\n }\n\n // Skip if this is the left side of an assignment: ref.prop = value\n if (ts.isBinaryExpression(node.parent) &&\n node.parent.operatorToken.kind === ts.SyntaxKind.EqualsToken &&\n node.parent.left === node) {\n return null;\n }\n\n // Skip if this is a compound assignment: ref.prop += value, ref.prop &&= value, etc.\n if (ts.isBinaryExpression(node.parent) && isAssignmentOperator(node.parent.operatorToken.kind) && node.parent.left === node) {\n return null;\n }\n\n // Skip if this is used with delete: delete ref.prop\n if (ts.isDeleteExpression(node.parent) && node.parent.expression === node) {\n return null;\n }\n\n // Skip if inside a typeof: typeof ref.prop\n if (ts.isTypeOfExpression(node.parent) && node.parent.expression === node) {\n return null;\n }\n\n // Skip property access chains that go deeper: ref.prop.something → ref.prop().something\n // This IS correct — we still want to add ()\n\n // Rewrite: insert () after the property name\n const end = node.name.getEnd();\n return {\n start: end,\n end: end,\n replacement: '()',\n };\n}\n\nfunction isAssignmentOperator(kind: ts.SyntaxKind): boolean {\n return kind >= ts.SyntaxKind.FirstAssignment && kind <= ts.SyntaxKind.LastAssignment;\n}\n\n/**\n * Resolves a reference name from an expression.\n * Handles: `ref`, `this.ref`, `this._ref`\n */\nfunction resolveRefName(expr: ts.Expression): string | null {\n // Direct identifier: ref.prop\n if (ts.isIdentifier(expr)) {\n return expr.text;\n }\n\n // this.ref.prop\n if (ts.isPropertyAccessExpression(expr) && expr.expression.kind === ts.SyntaxKind.ThisKeyword) {\n return expr.name.text;\n }\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Template ref resolution\n// ---------------------------------------------------------------------------\n\n/**\n * Builds a map of template reference variable names (#ref) to EUI class names.\n *\n * Parses the component's template (inline or external) and finds elements like:\n * <eui-alert #myAlert> → myAlert → EuiAlertComponent\n * <input euiAutocomplete #ac> → ac → EuiAutocompleteComponent\n *\n * Returns Map<refName, euiClassName>.\n */\nfunction buildTemplateRefMap(\n sourceFile: ts.SourceFile,\n source: string,\n filePath: string,\n tree: Tree,\n): Map<string, string> {\n const refMap = new Map<string, string>();\n\n // Find @Component decorator\n const componentMeta = findComponentMetadata(sourceFile, source);\n if (!componentMeta) return refMap;\n\n let templateSource: string | null = null;\n\n if (componentMeta.inlineTemplate !== null) {\n templateSource = componentMeta.inlineTemplate;\n } else if (componentMeta.templateUrl) {\n // Resolve templateUrl relative to the TS file\n const dir = filePath.substring(0, filePath.lastIndexOf('/'));\n const templatePath = `${dir}/${componentMeta.templateUrl}`;\n const buffer = tree.read(templatePath);\n if (buffer) {\n templateSource = buffer.toString('utf-8');\n }\n }\n\n if (!templateSource) return refMap;\n\n // Parse the template and collect #refs\n try {\n const parsed = parseTemplate(templateSource, '', { preserveWhitespaces: true });\n collectTemplateRefs(parsed.nodes, refMap);\n } catch {\n // Template parse failure — silently skip (might be malformed or use third-party syntax)\n }\n\n return refMap;\n}\n\n/**\n * Extracts @Component metadata: templateUrl or inline template content.\n */\nfunction findComponentMetadata(\n sourceFile: ts.SourceFile,\n source: string,\n): { templateUrl: string | null; inlineTemplate: string | null } | null {\n let result: { templateUrl: string | null; inlineTemplate: string | null } | null = null;\n\n const visit = (node: ts.Node): void => {\n if (result) return;\n\n if (ts.isDecorator(node) && ts.isCallExpression(node.expression)) {\n const name = getDecoratorName(node.expression);\n if (name !== 'Component') {\n ts.forEachChild(node, visit);\n return;\n }\n\n const args = node.expression.arguments;\n if (args.length === 0 || !ts.isObjectLiteralExpression(args[0])) {\n ts.forEachChild(node, visit);\n return;\n }\n\n const meta: { templateUrl: string | null; inlineTemplate: string | null } = {\n templateUrl: null,\n inlineTemplate: null,\n };\n\n for (const prop of args[0].properties) {\n if (!ts.isPropertyAssignment(prop) || !ts.isIdentifier(prop.name)) continue;\n\n if (prop.name.text === 'templateUrl') {\n const init = unwrapExpression(prop.initializer);\n if (ts.isStringLiteralLike(init)) {\n meta.templateUrl = init.text;\n }\n }\n\n if (prop.name.text === 'template') {\n const init = unwrapExpression(prop.initializer);\n if (ts.isStringLiteralLike(init)) {\n meta.inlineTemplate = init.text;\n } else if (ts.isNoSubstitutionTemplateLiteral(init)) {\n meta.inlineTemplate = init.text;\n }\n }\n }\n\n result = meta;\n return;\n }\n\n ts.forEachChild(node, visit);\n };\n\n ts.forEachChild(sourceFile, visit);\n return result;\n}\n\nfunction unwrapExpression(expression: ts.Expression): ts.Expression {\n let current = expression;\n while (ts.isParenthesizedExpression(current)) current = current.expression;\n return current;\n}\n\n/**\n * Recursively walks template AST nodes, collecting #refName → EUI class name mappings.\n *\n * For each element with a template reference (#ref), we try to resolve its EUI class:\n * 1. Match element tag name against EUI_SELECTOR_TO_CLASS (e.g. 'eui-alert' → EuiAlertComponent)\n * 2. Match element attributes against attribute selectors (e.g. [euiAutocomplete] → EuiAutocompleteComponent)\n */\nfunction collectTemplateRefs(nodes: TmplAstNode[], refMap: Map<string, string>): void {\n for (const node of nodes) {\n if (node instanceof TmplAstElement) {\n if (node.references && node.references.length > 0) {\n const euiClass = resolveElementToEuiClass(node);\n if (euiClass) {\n for (const ref of node.references) {\n refMap.set(ref.name, euiClass);\n }\n }\n }\n collectTemplateRefs(node.children, refMap);\n }\n }\n}\n\n/**\n * Given a template element, resolves it to an EUI class name by checking:\n * 1. Tag name: <eui-alert> → look up 'eui-alert' in EUI_SELECTOR_TO_CLASS\n * 2. Attribute selectors: <input euiAutocomplete> → look up 'input[euiAutocomplete]' or '[euiAutocomplete]'\n */\nfunction resolveElementToEuiClass(element: TmplAstElement): string | null {\n const tag = element.name;\n\n // Direct tag match: eui-alert, eui-dialog, etc.\n if (EUI_SELECTOR_TO_CLASS[tag]) {\n return EUI_SELECTOR_TO_CLASS[tag];\n }\n\n // Attribute selector match: check all attributes against known patterns\n const allAttrNames = [\n ...element.attributes.map((a) => a.name),\n ...element.inputs.map((i) => i.name),\n ];\n\n for (const attrName of allAttrNames) {\n // Try tag[attr] pattern first (e.g. 'button[euiButton]', 'input[euiAutocomplete]')\n const tagAttrSelector = `${tag}[${attrName}]`;\n if (EUI_SELECTOR_TO_CLASS[tagAttrSelector]) {\n return EUI_SELECTOR_TO_CLASS[tagAttrSelector];\n }\n\n // Try [attr] pattern (e.g. '[euiTooltip]', '[euiLoading]')\n const attrSelector = `[${attrName}]`;\n if (EUI_SELECTOR_TO_CLASS[attrSelector]) {\n return EUI_SELECTOR_TO_CLASS[attrSelector];\n }\n }\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Edit helpers\n// ---------------------------------------------------------------------------\n\nfunction applyEdits(source: string, edits: Edit[]): string {\n const unique = deduplicateEdits(edits);\n let result = source;\n for (const edit of unique.sort((a, b) => b.start - a.start)) {\n result = result.slice(0, edit.start) + edit.replacement + result.slice(edit.end);\n }\n return result;\n}\n\nfunction deduplicateEdits(edits: Edit[]): Edit[] {\n const seen = new Map<string, Edit>();\n for (const edit of edits) {\n const key = `${edit.start}:${edit.end}`;\n seen.set(key, edit);\n }\n return Array.from(seen.values());\n}\n\nfunction visitDir(dir: DirEntry, callback: (path: string) => void): void {\n for (const file of dir.subfiles) {\n if (file.endsWith('.d.ts')) continue;\n if (!file.endsWith('.ts')) continue;\n callback(`${dir.path}/${file}`);\n }\n for (const sub of dir.subdirs) {\n if (sub === 'node_modules' || sub === 'dist') continue;\n visitDir(dir.dir(sub), callback);\n }\n}\n",
3202
+ "sourceCode": "import { parseTemplate, TmplAstElement, TmplAstNode } from '@angular/compiler';\nimport { DirEntry, Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\nimport * as ts from 'typescript';\nimport { logDryRun, logDryRunNote } from '../utils/dry-run';\n\ninterface ModuleMapping {\n importPath: string;\n selectors: Record<string, string>;\n}\n\nconst MODULE_MAPPINGS: Record<string, ModuleMapping> = {\n EuiAccordionModule: {\n importPath: '@eui/components/eui-accordion',\n selectors: {\n 'eui-accordion': 'EuiAccordionComponent',\n 'eui-accordion-item': 'EuiAccordionItemComponent',\n euiAccordionItemHeader: 'EuiAccordionItemHeaderDirective',\n },\n },\n EuiAlertModule: {\n importPath: '@eui/components/eui-alert',\n selectors: {\n 'eui-alert': 'EuiAlertComponent',\n euiAlert: 'EuiAlertComponent',\n 'eui-alert-title': 'EuiAlertTitleComponent',\n },\n },\n EuiAutocompleteModule: {\n importPath: '@eui/components/eui-autocomplete',\n selectors: {\n 'eui-autocomplete': 'EuiAutocompleteComponent',\n euiAutocomplete: 'EuiAutocompleteComponent',\n 'eui-autocomplete-option': 'EuiAutocompleteOptionComponent',\n 'eui-autocomplete-option-group': 'EuiAutocompleteOptionGroupComponent',\n 'eui-autocomplete-panel': 'EuiAutocompletePanelComponent',\n },\n },\n EuiAvatarModule: {\n importPath: '@eui/components/eui-avatar',\n selectors: {\n 'eui-avatar': 'EuiAvatarComponent',\n euiAvatar: 'EuiAvatarComponent',\n },\n },\n EuiBadgeModule: {\n importPath: '@eui/components/eui-badge',\n selectors: {\n 'eui-badge': 'EuiBadgeComponent',\n euiBadge: 'EuiBadgeComponent',\n },\n },\n EuiBlockContentModule: {\n importPath: '@eui/components/eui-block-content',\n selectors: {\n 'eui-block-content': 'EuiBlockContentComponent',\n },\n },\n EuiBreadcrumbModule: {\n importPath: '@eui/components/eui-breadcrumb',\n selectors: {\n 'eui-breadcrumb': 'EuiBreadcrumbComponent',\n },\n },\n EuiButtonModule: {\n importPath: '@eui/components/eui-button',\n selectors: {\n euiButton: 'EuiButtonComponent',\n },\n },\n EuiButtonGroupModule: {\n importPath: '@eui/components/eui-button-group',\n selectors: {\n 'eui-button-group': 'EuiButtonGroupComponent',\n },\n },\n EuiCardModule: {\n importPath: '@eui/components/eui-card',\n selectors: {\n 'eui-card': 'EuiCardComponent',\n 'eui-card-header': 'EuiCardHeaderComponent',\n 'eui-card-header-title': 'EuiCardHeaderTitleComponent',\n 'eui-card-content': 'EuiCardContentComponent',\n 'eui-card-footer': 'EuiCardFooterComponent',\n 'eui-card-media': 'EuiCardMediaComponent',\n },\n },\n EuiChipModule: {\n importPath: '@eui/components/eui-chip',\n selectors: {\n 'eui-chip': 'EuiChipComponent',\n euiChip: 'EuiChipComponent',\n },\n },\n EuiChipListModule: {\n importPath: '@eui/components/eui-chip-list',\n selectors: {\n 'eui-chip-list': 'EuiChipListComponent',\n },\n },\n EuiChipGroupModule: {\n importPath: '@eui/components/eui-chip-group',\n selectors: {\n 'eui-chip-group': 'EuiChipGroupComponent',\n },\n },\n EuiDashboardCardModule: {\n importPath: '@eui/components/eui-dashboard-card',\n selectors: {\n 'eui-dashboard-card': 'EuiDashboardCardComponent',\n 'eui-dashboard-card-content': 'EuiDashboardCardContentComponent',\n 'eui-dashboard-card-content-header': 'EuiDashboardCardContentHeaderComponent',\n 'eui-dashboard-card-content-body': 'EuiDashboardCardContentBodyComponent',\n 'eui-dashboard-card-content-footer': 'EuiDashboardCardContentFooterComponent',\n },\n },\n EuiDashboardButtonModule: {\n importPath: '@eui/components/eui-dashboard-card',\n selectors: {\n 'eui-dashboard-card': 'EuiDashboardCardComponent',\n 'eui-dashboard-card-content': 'EuiDashboardCardContentComponent',\n 'eui-dashboard-card-content-header': 'EuiDashboardCardContentHeaderComponent',\n 'eui-dashboard-card-content-body': 'EuiDashboardCardContentBodyComponent',\n 'eui-dashboard-card-content-footer': 'EuiDashboardCardContentFooterComponent',\n },\n },\n EuiDatepickerModule: {\n importPath: '@eui/components/eui-datepicker',\n selectors: {\n 'eui-datepicker': 'EuiDatepickerComponent',\n },\n },\n EuiDateRangeSelectorModule: {\n importPath: '@eui/components/eui-date-range-selector',\n selectors: {\n 'eui-date-range-selector': 'EuiDateRangeSelectorComponent',\n },\n },\n EuiDialogModule: {\n importPath: '@eui/components/eui-dialog',\n selectors: {\n 'eui-dialog': 'EuiDialogComponent',\n 'eui-dialog-header': 'EuiDialogHeaderDirective',\n 'eui-dialog-footer': 'EuiDialogFooterDirective',\n 'eui-dialog-container': 'EuiDialogContainerComponent',\n },\n },\n EuiDisableContentModule: {\n importPath: '@eui/components/eui-disable-content',\n selectors: {\n 'eui-disable-content': 'EuiDisableContentComponent',\n },\n },\n EuiDiscussionThreadModule: {\n importPath: '@eui/components/eui-discussion-thread',\n selectors: {\n 'eui-discussion-thread': 'EuiDiscussionThreadComponent',\n 'eui-discussion-thread-item': 'EuiDiscussionThreadItemComponent',\n },\n },\n EuiDropdownModule: {\n importPath: '@eui/components/eui-dropdown',\n selectors: {\n 'eui-dropdown': 'EuiDropdownComponent',\n },\n },\n EuiFeedbackMessageModule: {\n importPath: '@eui/components/eui-feedback-message',\n selectors: {\n 'eui-feedback-message': 'EuiFeedbackMessageComponent',\n },\n },\n EuiFieldsetModule: {\n importPath: '@eui/components/eui-fieldset',\n selectors: {\n 'eui-fieldset': 'EuiFieldsetComponent',\n euiFieldsetLabelRightContent: 'EuiFieldsetLabelRightContentTagDirective',\n euiFieldsetLabelExtraContent: 'EuiFieldsetLabelExtraContentTagDirective',\n },\n },\n EuiFileUploadModule: {\n importPath: '@eui/components/eui-file-upload',\n selectors: {\n 'eui-file-upload': 'EuiFileUploadComponent',\n },\n },\n EuiGrowlModule: {\n importPath: '@eui/components/eui-growl',\n selectors: {\n 'eui-growl': 'EuiGrowlComponent',\n },\n },\n EuiIconModule: {\n importPath: '@eui/components/eui-icon',\n selectors: {\n 'eui-icon-svg': 'EuiIconSvgComponent',\n euiIconSvg: 'EuiIconSvgComponent',\n },\n },\n EuiIconButtonModule: {\n importPath: '@eui/components/eui-icon-button',\n selectors: {\n 'eui-icon-button': 'EuiIconButtonComponent',\n },\n },\n EuiIconToggleModule: {\n importPath: '@eui/components/eui-icon-toggle',\n selectors: {\n 'eui-icon-toggle': 'EuiIconToggleComponent',\n },\n },\n EuiInputCheckboxModule: {\n importPath: '@eui/components/eui-input-checkbox',\n selectors: {\n euiInputCheckBox: 'EuiInputCheckboxComponent',\n },\n },\n EuiInputGroupModule: {\n importPath: '@eui/components/eui-input-group',\n selectors: {\n euiInputGroup: 'EuiInputGroupComponent',\n 'eui-input-group-addon': 'EuiInputGroupAddOnComponent',\n euiInputGroupAddOn: 'EuiInputGroupAddOnComponent',\n 'eui-input-group-addon-item': 'EuiInputGroupAddOnItemComponent',\n euiInputGroupAddOnItem: 'EuiInputGroupAddOnItemComponent',\n },\n },\n EuiInputNumberModule: {\n importPath: '@eui/components/eui-input-number',\n selectors: {\n euiInputNumber: 'EuiInputNumberComponent',\n },\n },\n EuiInputRadioModule: {\n importPath: '@eui/components/eui-input-radio',\n selectors: {\n euiInputRadio: 'EuiInputRadioComponent',\n },\n },\n EuiInputTextModule: {\n importPath: '@eui/components/eui-input-text',\n selectors: {\n euiInputText: 'EuiInputTextComponent',\n },\n },\n EuiLabelModule: {\n importPath: '@eui/components/eui-label',\n selectors: {\n 'eui-label': 'EuiLabelComponent',\n euiLabel: 'EuiLabelComponent',\n },\n },\n EuiListModule: {\n importPath: '@eui/components/eui-list',\n selectors: {\n 'eui-list': 'EuiListComponent',\n euiList: 'EuiListComponent',\n 'eui-list-item': 'EuiListItemComponent',\n euiListItem: 'EuiListItemComponent',\n },\n },\n EuiMenuModule: {\n importPath: '@eui/components/eui-menu',\n selectors: {\n 'eui-menu': 'EuiMenuComponent',\n 'eui-menu-item': 'EuiMenuItemComponent',\n },\n },\n EuiMessageBoxModule: {\n importPath: '@eui/components/eui-message-box',\n selectors: {\n 'eui-message-box': 'EuiMessageBoxComponent',\n 'eui-message-box-footer': 'EuiMessageBoxFooterDirective',\n },\n },\n EuiOverlayModule: {\n importPath: '@eui/components/eui-overlay',\n selectors: {\n 'eui-overlay': 'EuiOverlayComponent',\n },\n },\n EuiPageModule: {\n importPath: '@eui/components/eui-page',\n selectors: {\n 'eui-page': 'EuiPageComponent',\n },\n },\n EuiPaginatorModule: {\n importPath: '@eui/components/eui-paginator',\n selectors: {\n 'eui-paginator': 'EuiPaginatorComponent',\n },\n },\n EuiPopoverModule: {\n importPath: '@eui/components/eui-popover',\n selectors: {\n 'eui-popover': 'EuiPopoverComponent',\n },\n },\n EuiProgressBarModule: {\n importPath: '@eui/components/eui-progress-bar',\n selectors: {\n 'eui-progress-bar': 'EuiProgressBarComponent',\n },\n },\n EuiProgressCircleModule: {\n importPath: '@eui/components/eui-progress-circle',\n selectors: {\n 'eui-progress-circle': 'EuiProgressCircleComponent',\n },\n },\n EuiSelectModule: {\n importPath: '@eui/components/eui-select',\n selectors: {\n euiSelect: 'EuiSelectComponent',\n },\n },\n EuiSidebarMenuModule: {\n importPath: '@eui/components/eui-sidebar-menu',\n selectors: {\n 'eui-sidebar-menu': 'EuiSidebarMenuComponent',\n },\n },\n EuiSkeletonModule: {\n importPath: '@eui/components/eui-skeleton',\n selectors: {\n 'eui-skeleton': 'EuiSkeletonComponent',\n },\n },\n EuiSlideToggleModule: {\n importPath: '@eui/components/eui-slide-toggle',\n selectors: {\n 'eui-slide-toggle': 'EuiSlideToggleComponent',\n },\n },\n EuiTableModule: {\n importPath: '@eui/components/eui-table',\n selectors: {\n 'eui-table': 'EuiTableComponent',\n euiTable: 'EuiTableComponent',\n 'eui-table-filter': 'EuiTableFilterComponent',\n isSortable: 'EuiTableSortableColComponent',\n isStickyCol: 'EuiTableStickyColDirective',\n isHeaderSelectable: 'EuiTableSelectableHeaderComponent',\n isDataSelectable: 'EuiTableSelectableRowComponent',\n isExpandableRow: 'EuiTableExpandableRowDirective',\n },\n },\n EuiTableV2Module: {\n importPath: '@eui/components/eui-table',\n selectors: {\n 'eui-table': 'EuiTableComponent',\n euiTable: 'EuiTableComponent',\n 'eui-table-filter': 'EuiTableFilterComponent',\n isSortable: 'EuiTableSortableColComponent',\n isStickyCol: 'EuiTableStickyColDirective',\n isHeaderSelectable: 'EuiTableSelectableHeaderComponent',\n isDataSelectable: 'EuiTableSelectableRowComponent',\n isExpandableRow: 'EuiTableExpandableRowDirective',\n },\n },\n EuiTabsModule: {\n importPath: '@eui/components/eui-tabs',\n selectors: {\n 'eui-tabs': 'EuiTabsComponent',\n 'eui-tab': 'EuiTabComponent',\n 'eui-tab-header': 'EuiTabHeaderComponent',\n 'eui-tab-body': 'EuiTabBodyComponent',\n },\n },\n EuiTextAreaModule: {\n importPath: '@eui/components/eui-textarea',\n selectors: {\n euiTextArea: 'EuiTextareaComponent',\n },\n },\n EuiTimelineModule: {\n importPath: '@eui/components/eui-timeline',\n selectors: {\n 'eui-timeline': 'EuiTimelineComponent',\n 'eui-timeline-item': 'EuiTimelineItemComponent',\n },\n },\n EuiTimepickerModule: {\n importPath: '@eui/components/eui-timepicker',\n selectors: {\n 'eui-timepicker': 'EuiTimepickerComponent',\n },\n },\n EuiTreeModule: {\n importPath: '@eui/components/eui-tree',\n selectors: {\n 'eui-tree': 'EuiTreeComponent',\n },\n },\n EuiTreeListModule: {\n importPath: '@eui/components/eui-tree-list',\n selectors: {\n 'eui-tree-list': 'EuiTreeListComponent',\n 'eui-tree-list-item': 'EuiTreeListItemComponent',\n },\n },\n EuiUserProfileModule: {\n importPath: '@eui/components/eui-user-profile',\n selectors: {\n 'eui-user-profile': 'EuiUserProfileComponent',\n },\n },\n EuiWizardModule: {\n importPath: '@eui/components/eui-wizard',\n selectors: {\n 'eui-wizard': 'EuiWizardComponent',\n 'eui-wizard-step': 'EuiWizardStepComponent',\n },\n },\n EuiTooltipDirectiveModule: {\n importPath: '@eui/components/directives',\n selectors: {\n euiTooltip: 'EuiTooltipDirective',\n },\n },\n EuiTemplateDirectiveModule: {\n importPath: '@eui/components/directives',\n selectors: {\n euiTemplate: 'EuiTemplateDirective',\n },\n },\n EuiResizableDirectiveModule: {\n importPath: '@eui/components/directives',\n selectors: {\n euiResizable: 'EuiResizableDirective',\n 'eui-resizable': 'EuiResizableComponent',\n },\n },\n EuiMaxLengthDirectiveModule: {\n importPath: '@eui/components/directives',\n selectors: {\n euiEditorMaxlength: 'EuiMaxLengthDirective',\n },\n },\n EuiTruncatePipeModule: {\n importPath: '@eui/components/pipes',\n selectors: {\n euiTruncate: 'EuiTruncatePipe',\n },\n },\n EuiLayoutModule: {\n importPath: '@eui/components/layout',\n selectors: {\n 'eui-app': 'EuiAppComponent',\n 'eui-header': 'EuiHeaderComponent',\n 'eui-footer': 'EuiFooterComponent',\n 'eui-toolbar': 'EuiToolbarComponent',\n 'eui-sidebar-toggle': 'EuiSidebarToggleComponent',\n },\n },\n};\n\ninterface Schema {\n path?: string;\n dryRun?: boolean;\n}\n\nexport function migrateToStandalone(options: Schema = {}): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const scanPath = options.path ? '/' + options.path.replace(/^\\.?\\//, '').replace(/\\/$/, '') : '';\n const allModuleNames = Object.keys(MODULE_MAPPINGS);\n\n visitDir(tree.getDir(scanPath || '/'), (path) => {\n const buffer = tree.read(path);\n if (!buffer) return;\n\n const source = buffer.toString('utf-8');\n if (!allModuleNames.some((m) => source.includes(m))) return;\n\n const sourceFile = ts.createSourceFile(path, source, ts.ScriptTarget.Latest, true);\n const componentDecorators = findComponentDecorators(sourceFile);\n\n for (const decorator of componentDecorators) {\n const importsNode = findImportsArrayNode(decorator);\n if (!importsNode) continue;\n\n const currentSource = tree.read(path)!.toString('utf-8');\n const modulesInArray = allModuleNames.filter((m) => hasModuleInArray(importsNode, m, source));\n if (modulesInArray.length === 0) continue;\n\n const templateSelectors = getTemplateSelectors(tree, path, decorator, source);\n const replacements = buildReplacements(modulesInArray, templateSelectors);\n if (replacements.size === 0) continue;\n\n const result = applyReplacements(currentSource, path, replacements);\n if (options.dryRun) {\n logDryRun(context, `Would replace module imports with standalone imports in ${path}`);\n } else {\n tree.overwrite(path, result);\n }\n }\n });\n\n context.logger.info('Migration to standalone imports complete.');\n if (options.dryRun) {\n logDryRunNote(context);\n }\n return tree;\n };\n}\n\nfunction visitDir(dir: DirEntry, callback: (path: string) => void): void {\n for (const file of dir.subfiles) {\n if (file.endsWith('.d.ts')) continue;\n if (!file.endsWith('.ts')) continue;\n callback(`${dir.path}/${file}`);\n }\n for (const sub of dir.subdirs) {\n if (sub === 'node_modules' || sub === 'dist') continue;\n visitDir(dir.dir(sub), callback);\n }\n}\n\nfunction buildReplacements(moduleNames: string[], templateSelectors: Set<string>): Map<string, { components: string[]; importPath: string }> {\n const map = new Map<string, { components: string[]; importPath: string }>();\n\n for (const moduleName of moduleNames) {\n const mapping = MODULE_MAPPINGS[moduleName];\n const components: string[] = [];\n\n for (const [selector, component] of Object.entries(mapping.selectors)) {\n if (templateSelectors.has(selector)) {\n components.push(component);\n }\n }\n\n if (components.length > 0) {\n map.set(moduleName, { components: [...new Set(components)].sort(), importPath: mapping.importPath });\n }\n }\n\n return map;\n}\n\nfunction findComponentDecorators(sourceFile: ts.SourceFile): ts.Decorator[] {\n const decorators: ts.Decorator[] = [];\n const visit = (node: ts.Node): void => {\n if (ts.isClassDeclaration(node)) {\n const decs = ts.getDecorators(node);\n if (decs) {\n for (const dec of decs) {\n if (ts.isCallExpression(dec.expression) && ts.isIdentifier(dec.expression.expression) && dec.expression.expression.text === 'Component') {\n decorators.push(dec);\n }\n }\n }\n }\n ts.forEachChild(node, visit);\n };\n visit(sourceFile);\n return decorators;\n}\n\nfunction findImportsArrayNode(decorator: ts.Decorator): ts.ArrayLiteralExpression | undefined {\n const call = decorator.expression as ts.CallExpression;\n const metadata = call.arguments[0];\n if (!ts.isObjectLiteralExpression(metadata)) return undefined;\n\n for (const prop of metadata.properties) {\n if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name) && prop.name.text === 'imports') {\n if (ts.isArrayLiteralExpression(prop.initializer)) {\n return prop.initializer;\n }\n }\n }\n return undefined;\n}\n\nfunction hasModuleInArray(array: ts.ArrayLiteralExpression, moduleName: string, source: string): boolean {\n return array.elements.some((el) => source.slice(el.getStart(), el.getEnd()).trim() === moduleName);\n}\n\nfunction getTemplateSelectors(tree: Tree, tsPath: string, decorator: ts.Decorator, source: string): Set<string> {\n const call = decorator.expression as ts.CallExpression;\n const metadata = call.arguments[0] as ts.ObjectLiteralExpression;\n const allSelectors = Object.values(MODULE_MAPPINGS).flatMap((m) => Object.keys(m.selectors));\n\n for (const prop of metadata.properties) {\n if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name) && prop.name.text === 'template') {\n const init = prop.initializer;\n if (ts.isStringLiteral(init) || ts.isNoSubstitutionTemplateLiteral(init)) {\n return findSelectorsInTemplate(init.text, allSelectors);\n }\n }\n }\n\n for (const prop of metadata.properties) {\n if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name) && prop.name.text === 'templateUrl') {\n if (ts.isStringLiteral(prop.initializer)) {\n const dir = tsPath.substring(0, tsPath.lastIndexOf('/'));\n const templateBuffer = tree.read(`${dir}/${prop.initializer.text}`);\n if (templateBuffer) {\n return findSelectorsInTemplate(templateBuffer.toString('utf-8'), allSelectors);\n }\n }\n }\n }\n\n return new Set();\n}\n\nfunction findSelectorsInTemplate(html: string, knownSelectors: string[]): Set<string> {\n const selectors = new Set<string>();\n const parsed = parseTemplate(html, '', { preserveWhitespaces: true });\n\n const visit = (nodes: TmplAstNode[]): void => {\n for (const node of nodes) {\n if (node instanceof TmplAstElement) {\n if (knownSelectors.includes(node.name)) selectors.add(node.name);\n for (const attr of node.attributes) {\n if (knownSelectors.includes(attr.name)) selectors.add(attr.name);\n }\n visit(node.children);\n }\n }\n };\n visit(parsed.nodes);\n return selectors;\n}\n\nfunction applyReplacements(source: string, filePath: string, replacements: Map<string, { components: string[]; importPath: string }>): string {\n const sourceFile = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true);\n let result = replaceInImportsArray(source, sourceFile, replacements);\n result = updateEsImports(result, filePath, replacements);\n return result;\n}\n\nfunction replaceInImportsArray(source: string, sourceFile: ts.SourceFile, replacements: Map<string, { components: string[]; importPath: string }>): string {\n let result = source;\n const visit = (node: ts.Node): void => {\n if (ts.isClassDeclaration(node)) {\n const decs = ts.getDecorators(node);\n if (!decs) return;\n for (const dec of decs) {\n if (!ts.isCallExpression(dec.expression) || !ts.isIdentifier(dec.expression.expression) || dec.expression.expression.text !== 'Component') continue;\n const metadata = dec.expression.arguments[0];\n if (!ts.isObjectLiteralExpression(metadata)) continue;\n for (const prop of metadata.properties) {\n if (!ts.isPropertyAssignment(prop) || !ts.isIdentifier(prop.name) || prop.name.text !== 'imports') continue;\n if (!ts.isArrayLiteralExpression(prop.initializer)) continue;\n const newElements = prop.initializer.elements\n .map((el) => {\n const text = result.slice(el.getStart(sourceFile), el.getEnd()).trim();\n const replacement = replacements.get(text);\n return replacement ? replacement.components.join(', ') : text;\n })\n .join(', ');\n result = result.slice(0, prop.initializer.getStart(sourceFile) + 1) + newElements + result.slice(prop.initializer.getEnd() - 1);\n }\n }\n }\n ts.forEachChild(node, visit);\n };\n visit(sourceFile);\n return result;\n}\n\nfunction updateEsImports(source: string, filePath: string, replacements: Map<string, { components: string[]; importPath: string }>): string {\n let result = source;\n\n for (const [moduleName, { components, importPath }] of replacements) {\n const sf = ts.createSourceFile(filePath, result, ts.ScriptTarget.Latest, true);\n\n for (const stmt of sf.statements) {\n if (!ts.isImportDeclaration(stmt) || !stmt.importClause?.namedBindings || !ts.isNamedImports(stmt.importClause.namedBindings)) continue;\n const namedBindings = stmt.importClause.namedBindings;\n const importNames = namedBindings.elements.map((el) => el.name.text);\n if (!importNames.includes(moduleName)) continue;\n\n const moduleSpecifier = (stmt.moduleSpecifier as ts.StringLiteral).text;\n const remaining = importNames.filter((n) => n !== moduleName);\n const toAdd = components.filter((c) => !importNames.includes(c));\n\n if (moduleSpecifier === importPath) {\n const newNames = [...remaining, ...toAdd].sort();\n const newClause = `{ ${newNames.join(', ')} }`;\n result = result.slice(0, namedBindings.getStart(sf)) + newClause + result.slice(namedBindings.getEnd());\n } else {\n if (remaining.length > 0) {\n const newClause = `{ ${remaining.join(', ')} }`;\n result = result.slice(0, namedBindings.getStart(sf)) + newClause + result.slice(namedBindings.getEnd());\n } else {\n result = result.slice(0, stmt.getStart(sf)) + result.slice(stmt.getEnd()).replace(/^\\r?\\n/, '');\n }\n\n if (toAdd.length > 0) {\n const updatedSf = ts.createSourceFile(filePath, result, ts.ScriptTarget.Latest, true);\n const existing = updatedSf.statements.find(\n (s) => ts.isImportDeclaration(s) && ts.isStringLiteral(s.moduleSpecifier) && s.moduleSpecifier.text === importPath,\n ) as ts.ImportDeclaration | undefined;\n\n if (existing?.importClause?.namedBindings && ts.isNamedImports(existing.importClause.namedBindings)) {\n const existingNames = existing.importClause.namedBindings.elements.map((el) => el.name.text);\n const allNames = [...new Set([...existingNames, ...toAdd])].sort();\n const newClause = `{ ${allNames.join(', ')} }`;\n result = result.slice(0, existing.importClause.namedBindings.getStart(updatedSf)) + newClause + result.slice(existing.importClause.namedBindings.getEnd());\n } else {\n const newImport = `import { ${toAdd.join(', ')} } from '${importPath}';\\n`;\n result = newImport + result;\n }\n }\n }\n break;\n }\n }\n\n return result;\n}\n",
3203
3203
  "displayName": "Schema",
3204
3204
  "properties": [
3205
3205
  {
@@ -3211,7 +3211,7 @@
3211
3211
  "indexKey": "",
3212
3212
  "optional": true,
3213
3213
  "description": "",
3214
- "line": 9,
3214
+ "line": 460,
3215
3215
  "rawdescription": "\n"
3216
3216
  },
3217
3217
  {
@@ -3223,7 +3223,7 @@
3223
3223
  "indexKey": "",
3224
3224
  "optional": true,
3225
3225
  "description": "",
3226
- "line": 8,
3226
+ "line": 459,
3227
3227
  "rawdescription": "\n"
3228
3228
  }
3229
3229
  ],
@@ -36709,7 +36709,7 @@
36709
36709
  },
36710
36710
  {
36711
36711
  "name": "visitDir",
36712
- "file": "packages/core/schematics/migrate-to-standalone/index.ts",
36712
+ "file": "packages/core/schematics/migrate-to-signals/index.ts",
36713
36713
  "ctype": "miscellaneous",
36714
36714
  "subtype": "function",
36715
36715
  "coverageIgnore": false,
@@ -36754,7 +36754,7 @@
36754
36754
  },
36755
36755
  {
36756
36756
  "name": "visitDir",
36757
- "file": "packages/core/schematics/migrate-to-signals/index.ts",
36757
+ "file": "packages/core/schematics/migrate-to-standalone/index.ts",
36758
36758
  "ctype": "miscellaneous",
36759
36759
  "subtype": "function",
36760
36760
  "coverageIgnore": false,
package/docs/llms.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  # eui documentation
2
2
 
3
- > Generated by compodoc 2.0.0 at 2026-09-22T13:52:08.286Z, llm-md export.
3
+ > Generated by compodoc 2.0.0 at 2026-09-22T19:44:31.689Z, llm-md export.
4
4
 
5
5
  ## Modules
6
6
 
@@ -1146,7 +1146,7 @@ Properties:
1146
1146
 
1147
1147
  ### Schema
1148
1148
 
1149
- File: `packages/core/schematics/migrate-eui-chip/index.ts`
1149
+ File: `packages/core/schematics/migrate-eui-chip-list/index.ts`
1150
1150
 
1151
1151
  Properties:
1152
1152
  - `dryRun?: boolean`
@@ -1154,7 +1154,7 @@ Properties:
1154
1154
 
1155
1155
  ### Schema
1156
1156
 
1157
- File: `packages/core/schematics/migrate-eui-chip-list/index.ts`
1157
+ File: `packages/core/schematics/migrate-eui-chip/index.ts`
1158
1158
 
1159
1159
  Properties:
1160
1160
  - `dryRun?: boolean`
@@ -1596,10 +1596,10 @@ Properties:
1596
1596
  Defined in `packages/core/schematics/migrate-to-signals/index.ts`
1597
1597
  - `isAvatarElement(element: TmplAstElement): boolean`
1598
1598
  Defined in `packages/core/schematics/migrate-eui-avatar/index.ts`
1599
- - `isChipElement(element: TmplAstElement): boolean`
1600
- Defined in `packages/core/schematics/migrate-eui-chip/index.ts`
1601
1599
  - `isChipElement(element: TmplAstElement): boolean`
1602
1600
  Defined in `packages/core/schematics/migrate-eui-chip-list/index.ts`
1601
+ - `isChipElement(element: TmplAstElement): boolean`
1602
+ Defined in `packages/core/schematics/migrate-eui-chip/index.ts`
1603
1603
  - `isChipListElement(element: TmplAstElement): boolean`
1604
1604
  Defined in `packages/core/schematics/migrate-eui-chip-list/index.ts`
1605
1605
  - `isComponentMetadataProperty(node): boolean`
@@ -1736,10 +1736,10 @@ Properties:
1736
1736
  Defined in `packages/core/schematics/migrate-eui-avatar/index.ts`
1737
1737
  - `migrateInlineTemplates(source: string): string`
1738
1738
  Defined in `packages/core/schematics/migrate-eui-button/index.ts`
1739
- - `migrateInlineTemplates(source: string): string`
1740
- Defined in `packages/core/schematics/migrate-eui-chip/index.ts`
1741
1739
  - `migrateInlineTemplates(source: string): string`
1742
1740
  Defined in `packages/core/schematics/migrate-eui-chip-list/index.ts`
1741
+ - `migrateInlineTemplates(source: string): string`
1742
+ Defined in `packages/core/schematics/migrate-eui-chip/index.ts`
1743
1743
  - `migrateInlineTemplates(source: string): string`
1744
1744
  Defined in `packages/core/schematics/migrate-eui-discussion-thread/index.ts`
1745
1745
  - `migrateInlineTemplates(source: string): string`
@@ -1766,10 +1766,10 @@ Properties:
1766
1766
  Defined in `packages/core/schematics/migrate-eui-avatar/index.ts`
1767
1767
  - `migrateTemplate(source: string): string`
1768
1768
  Defined in `packages/core/schematics/migrate-eui-button/index.ts`
1769
- - `migrateTemplate(source: string): string`
1770
- Defined in `packages/core/schematics/migrate-eui-chip/index.ts`
1771
1769
  - `migrateTemplate(source: string): string`
1772
1770
  Defined in `packages/core/schematics/migrate-eui-chip-list/index.ts`
1771
+ - `migrateTemplate(source: string): string`
1772
+ Defined in `packages/core/schematics/migrate-eui-chip/index.ts`
1773
1773
  - `migrateTemplate(source: string): string`
1774
1774
  Defined in `packages/core/schematics/migrate-eui-discussion-thread/index.ts`
1775
1775
  - `migrateTemplate(source: string): string`
@@ -1912,10 +1912,10 @@ Properties:
1912
1912
  Defined in `packages/core/schematics/migrate-eui-avatar/index.ts`
1913
1913
  - `visitDir(dir: DirEntry, callback): void`
1914
1914
  Defined in `packages/core/schematics/migrate-eui-button/index.ts`
1915
- - `visitDir(dir: DirEntry, callback): void`
1916
- Defined in `packages/core/schematics/migrate-eui-chip/index.ts`
1917
1915
  - `visitDir(dir: DirEntry, callback): void`
1918
1916
  Defined in `packages/core/schematics/migrate-eui-chip-list/index.ts`
1917
+ - `visitDir(dir: DirEntry, callback): void`
1918
+ Defined in `packages/core/schematics/migrate-eui-chip/index.ts`
1919
1919
  - `visitDir(dir: DirEntry, callback): void`
1920
1920
  Defined in `packages/core/schematics/migrate-eui-discussion-thread/index.ts`
1921
1921
  - `visitDir(dir: DirEntry, callback): void`
@@ -1952,10 +1952,10 @@ Properties:
1952
1952
  Defined in `packages/core/schematics/migrate-eui-avatar/index.ts`
1953
1953
  - `visitNodes(nodes, edits): void`
1954
1954
  Defined in `packages/core/schematics/migrate-eui-button/index.ts`
1955
- - `visitNodes(nodes, removals): void`
1956
- Defined in `packages/core/schematics/migrate-eui-chip/index.ts`
1957
1955
  - `visitNodes(nodes, source: string, edits): void`
1958
1956
  Defined in `packages/core/schematics/migrate-eui-chip-list/index.ts`
1957
+ - `visitNodes(nodes, removals): void`
1958
+ Defined in `packages/core/schematics/migrate-eui-chip/index.ts`
1959
1959
  - `visitNodes(nodes, source: string, removals): void`
1960
1960
  Defined in `packages/core/schematics/migrate-eui-discussion-thread/index.ts`
1961
1961
  - `visitNodes(nodes, edits): void`
@@ -2313,10 +2313,10 @@ Properties:
2313
2313
  Defined in `packages/core/schematics/migrate-eui-alert/index.ts`
2314
2314
  - `REMOVED_INPUTS: unknown = new Set(['isFlat'])`
2315
2315
  Defined in `packages/core/schematics/migrate-eui-avatar/index.ts`
2316
- - `REMOVED_INPUTS: unknown = new Set(['isSquared'])`
2317
- Defined in `packages/core/schematics/migrate-eui-chip/index.ts`
2318
2316
  - `REMOVED_INPUTS: unknown = new Set(['maxVisibleChipsCount', 'isMaxVisibleChipsOpened', 'toggleLinkMoreLabel', 'toggleLinkLessLabel', 'isChipsSorted', 'chipsSortOrder'])`
2319
2317
  Defined in `packages/core/schematics/migrate-eui-chip-list/index.ts`
2318
+ - `REMOVED_INPUTS: unknown = new Set(['isSquared'])`
2319
+ Defined in `packages/core/schematics/migrate-eui-chip/index.ts`
2320
2320
  - `REMOVED_INPUTS: unknown = new Set(['type'])`
2321
2321
  Defined in `packages/core/schematics/migrate-eui-popover/index.ts`
2322
2322
  - `REMOVED_INPUTS: unknown = new Set(['euiTableBordered', 'isHoverable', 'defaultMultiOrder', 'paginable'])`
@@ -513,10 +513,10 @@
513
513
  <a href="#isAvatarElement" title="packages/core/schematics/migrate-eui-avatar/index.ts" class="reference-link "><span class="reference-badge reference-badge--function" aria-hidden="true">F</span><span class="reference-link-label"><b>isAvatarElement</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
514
514
  </li>
515
515
  <li>
516
- <a href="#isChipElement" title="packages/core/schematics/migrate-eui-chip/index.ts" class="reference-link "><span class="reference-badge reference-badge--function" aria-hidden="true">F</span><span class="reference-link-label"><b>isChipElement</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
516
+ <a href="#isChipElement" title="packages/core/schematics/migrate-eui-chip-list/index.ts" class="reference-link "><span class="reference-badge reference-badge--function" aria-hidden="true">F</span><span class="reference-link-label"><b>isChipElement</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
517
517
  </li>
518
518
  <li>
519
- <a href="#isChipElement" title="packages/core/schematics/migrate-eui-chip-list/index.ts" class="reference-link "><span class="reference-badge reference-badge--function" aria-hidden="true">F</span><span class="reference-link-label"><b>isChipElement</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
519
+ <a href="#isChipElement" title="packages/core/schematics/migrate-eui-chip/index.ts" class="reference-link "><span class="reference-badge reference-badge--function" aria-hidden="true">F</span><span class="reference-link-label"><b>isChipElement</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
520
520
  </li>
521
521
  <li>
522
522
  <a href="#isChipListElement" title="packages/core/schematics/migrate-eui-chip-list/index.ts" class="reference-link "><span class="reference-badge reference-badge--function" aria-hidden="true">F</span><span class="reference-link-label"><b>isChipListElement</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
@@ -723,10 +723,10 @@
723
723
  <a href="#migrateInlineTemplates" title="packages/core/schematics/migrate-eui-button/index.ts" class="reference-link "><span class="reference-badge reference-badge--function" aria-hidden="true">F</span><span class="reference-link-label"><b>migrateInlineTemplates</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
724
724
  </li>
725
725
  <li>
726
- <a href="#migrateInlineTemplates" title="packages/core/schematics/migrate-eui-chip/index.ts" class="reference-link "><span class="reference-badge reference-badge--function" aria-hidden="true">F</span><span class="reference-link-label"><b>migrateInlineTemplates</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
726
+ <a href="#migrateInlineTemplates" title="packages/core/schematics/migrate-eui-chip-list/index.ts" class="reference-link "><span class="reference-badge reference-badge--function" aria-hidden="true">F</span><span class="reference-link-label"><b>migrateInlineTemplates</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
727
727
  </li>
728
728
  <li>
729
- <a href="#migrateInlineTemplates" title="packages/core/schematics/migrate-eui-chip-list/index.ts" class="reference-link "><span class="reference-badge reference-badge--function" aria-hidden="true">F</span><span class="reference-link-label"><b>migrateInlineTemplates</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
729
+ <a href="#migrateInlineTemplates" title="packages/core/schematics/migrate-eui-chip/index.ts" class="reference-link "><span class="reference-badge reference-badge--function" aria-hidden="true">F</span><span class="reference-link-label"><b>migrateInlineTemplates</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
730
730
  </li>
731
731
  <li>
732
732
  <a href="#migrateInlineTemplates" title="packages/core/schematics/migrate-eui-discussion-thread/index.ts" class="reference-link "><span class="reference-badge reference-badge--function" aria-hidden="true">F</span><span class="reference-link-label"><b>migrateInlineTemplates</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
@@ -768,10 +768,10 @@
768
768
  <a href="#migrateTemplate" title="packages/core/schematics/migrate-eui-button/index.ts" class="reference-link "><span class="reference-badge reference-badge--function" aria-hidden="true">F</span><span class="reference-link-label"><b>migrateTemplate</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
769
769
  </li>
770
770
  <li>
771
- <a href="#migrateTemplate" title="packages/core/schematics/migrate-eui-chip/index.ts" class="reference-link "><span class="reference-badge reference-badge--function" aria-hidden="true">F</span><span class="reference-link-label"><b>migrateTemplate</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
771
+ <a href="#migrateTemplate" title="packages/core/schematics/migrate-eui-chip-list/index.ts" class="reference-link "><span class="reference-badge reference-badge--function" aria-hidden="true">F</span><span class="reference-link-label"><b>migrateTemplate</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
772
772
  </li>
773
773
  <li>
774
- <a href="#migrateTemplate" title="packages/core/schematics/migrate-eui-chip-list/index.ts" class="reference-link "><span class="reference-badge reference-badge--function" aria-hidden="true">F</span><span class="reference-link-label"><b>migrateTemplate</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
774
+ <a href="#migrateTemplate" title="packages/core/schematics/migrate-eui-chip/index.ts" class="reference-link "><span class="reference-badge reference-badge--function" aria-hidden="true">F</span><span class="reference-link-label"><b>migrateTemplate</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
775
775
  </li>
776
776
  <li>
777
777
  <a href="#migrateTemplate" title="packages/core/schematics/migrate-eui-discussion-thread/index.ts" class="reference-link "><span class="reference-badge reference-badge--function" aria-hidden="true">F</span><span class="reference-link-label"><b>migrateTemplate</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
@@ -987,10 +987,10 @@
987
987
  <a href="#visitDir" title="packages/core/schematics/migrate-eui-button/index.ts" class="reference-link "><span class="reference-badge reference-badge--function" aria-hidden="true">F</span><span class="reference-link-label"><b>visitDir</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
988
988
  </li>
989
989
  <li>
990
- <a href="#visitDir" title="packages/core/schematics/migrate-eui-chip/index.ts" class="reference-link "><span class="reference-badge reference-badge--function" aria-hidden="true">F</span><span class="reference-link-label"><b>visitDir</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
990
+ <a href="#visitDir" title="packages/core/schematics/migrate-eui-chip-list/index.ts" class="reference-link "><span class="reference-badge reference-badge--function" aria-hidden="true">F</span><span class="reference-link-label"><b>visitDir</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
991
991
  </li>
992
992
  <li>
993
- <a href="#visitDir" title="packages/core/schematics/migrate-eui-chip-list/index.ts" class="reference-link "><span class="reference-badge reference-badge--function" aria-hidden="true">F</span><span class="reference-link-label"><b>visitDir</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
993
+ <a href="#visitDir" title="packages/core/schematics/migrate-eui-chip/index.ts" class="reference-link "><span class="reference-badge reference-badge--function" aria-hidden="true">F</span><span class="reference-link-label"><b>visitDir</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
994
994
  </li>
995
995
  <li>
996
996
  <a href="#visitDir" title="packages/core/schematics/migrate-eui-discussion-thread/index.ts" class="reference-link "><span class="reference-badge reference-badge--function" aria-hidden="true">F</span><span class="reference-link-label"><b>visitDir</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
@@ -1047,10 +1047,10 @@
1047
1047
  <a href="#visitNodes" title="packages/core/schematics/migrate-eui-button/index.ts" class="reference-link "><span class="reference-badge reference-badge--function" aria-hidden="true">F</span><span class="reference-link-label"><b>visitNodes</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
1048
1048
  </li>
1049
1049
  <li>
1050
- <a href="#visitNodes" title="packages/core/schematics/migrate-eui-chip/index.ts" class="reference-link "><span class="reference-badge reference-badge--function" aria-hidden="true">F</span><span class="reference-link-label"><b>visitNodes</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
1050
+ <a href="#visitNodes" title="packages/core/schematics/migrate-eui-chip-list/index.ts" class="reference-link "><span class="reference-badge reference-badge--function" aria-hidden="true">F</span><span class="reference-link-label"><b>visitNodes</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
1051
1051
  </li>
1052
1052
  <li>
1053
- <a href="#visitNodes" title="packages/core/schematics/migrate-eui-chip-list/index.ts" class="reference-link "><span class="reference-badge reference-badge--function" aria-hidden="true">F</span><span class="reference-link-label"><b>visitNodes</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
1053
+ <a href="#visitNodes" title="packages/core/schematics/migrate-eui-chip/index.ts" class="reference-link "><span class="reference-badge reference-badge--function" aria-hidden="true">F</span><span class="reference-link-label"><b>visitNodes</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
1054
1054
  </li>
1055
1055
  <li>
1056
1056
  <a href="#visitNodes" title="packages/core/schematics/migrate-eui-discussion-thread/index.ts" class="reference-link "><span class="reference-badge reference-badge--function" aria-hidden="true">F</span><span class="reference-link-label"><b>visitNodes</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
@@ -525,10 +525,10 @@
525
525
  <a href="#REMOVED_INPUTS" title="packages/core/schematics/migrate-eui-avatar/index.ts" class="reference-link "><span class="reference-badge reference-badge--variable" aria-hidden="true">V</span><span class="reference-link-label"><b>REMOVED_INPUTS</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
526
526
  </li>
527
527
  <li>
528
- <a href="#REMOVED_INPUTS" title="packages/core/schematics/migrate-eui-chip/index.ts" class="reference-link "><span class="reference-badge reference-badge--variable" aria-hidden="true">V</span><span class="reference-link-label"><b>REMOVED_INPUTS</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
528
+ <a href="#REMOVED_INPUTS" title="packages/core/schematics/migrate-eui-chip-list/index.ts" class="reference-link "><span class="reference-badge reference-badge--variable" aria-hidden="true">V</span><span class="reference-link-label"><b>REMOVED_INPUTS</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
529
529
  </li>
530
530
  <li>
531
- <a href="#REMOVED_INPUTS" title="packages/core/schematics/migrate-eui-chip-list/index.ts" class="reference-link "><span class="reference-badge reference-badge--variable" aria-hidden="true">V</span><span class="reference-link-label"><b>REMOVED_INPUTS</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
531
+ <a href="#REMOVED_INPUTS" title="packages/core/schematics/migrate-eui-chip/index.ts" class="reference-link "><span class="reference-badge reference-badge--variable" aria-hidden="true">V</span><span class="reference-link-label"><b>REMOVED_INPUTS</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
532
532
  </li>
533
533
  <li>
534
534
  <a href="#REMOVED_INPUTS" title="packages/core/schematics/migrate-eui-popover/index.ts" class="reference-link "><span class="reference-badge reference-badge--variable" aria-hidden="true">V</span><span class="reference-link-label"><b>REMOVED_INPUTS</b>&nbsp;&nbsp;&nbsp;(packages/.../index.ts)</span></a>
@@ -128,7 +128,7 @@
128
128
  </ol>
129
129
  <ul class="properties-list">
130
130
  <li>
131
- <b>Version</b> : 22.0.0-alpha.11</li>
131
+ <b>Version</b> : 22.0.0-alpha.13</li>
132
132
  </ul>
133
133
 
134
134
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eui/core",
3
- "version": "22.0.0-alpha.11",
3
+ "version": "22.0.0-alpha.13",
4
4
  "tag": "next",
5
5
  "description": "eUI core package - holding UI components for Desktop applications",
6
6
  "homepage": "https://eui.ecdevops.eu",
@@ -10,7 +10,7 @@
10
10
  "url": "https://sdlc.webcloud.ec.europa.eu/csdr/eui/eui.git"
11
11
  },
12
12
  "peerDependencies": {
13
- "@eui/base": "22.0.0-alpha.11",
13
+ "@eui/base": "22.0.0-alpha.13",
14
14
  "rxjs": "^7.8.0",
15
15
  "extend": "^3.0.2",
16
16
  "localforage": "^1.10.0",