@ethlete/core 5.0.0-next.7 ā 5.0.0-next.71
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.
- package/CHANGELOG.md +849 -0
- package/README.md +28 -4
- package/design/interactive-styles.ts +5 -0
- package/design/theme-css.js +392 -0
- package/design/theme-css.ts +547 -0
- package/fesm2022/ethlete-core.mjs +9357 -5667
- package/fesm2022/ethlete-core.mjs.map +1 -1
- package/generators/devtools-about/generator.js +122 -0
- package/generators/devtools-about/schema.json +25 -0
- package/generators/generators.json +41 -5
- package/generators/migrate-color-theme-variants/color-theme-variants.js +136 -0
- package/generators/migrate-color-theme-variants/migration.js +46 -0
- package/generators/migrate-color-theme-variants/schema.json +26 -0
- package/generators/migrate-create-destroy/create-destroy.js +317 -0
- package/generators/migrate-create-destroy/migration.js +46 -0
- package/generators/migrate-create-destroy/schema.json +26 -0
- package/generators/migrate-legacy-color-themes/legacy-color-themes.js +123 -0
- package/generators/migrate-legacy-color-themes/migration.js +93 -0
- package/generators/migrate-legacy-color-themes/schema.json +26 -0
- package/generators/migrate-provider-shape/migration-scope.js +35 -0
- package/generators/migrate-provider-shape/migration.js +50 -0
- package/generators/migrate-provider-shape/provider-shape.js +284 -0
- package/generators/migrate-provider-shape/schema.json +26 -0
- package/generators/migrate-surface-interaction-swatch/interaction-swatch.js +63 -0
- package/generators/migrate-surface-interaction-swatch/migration.js +36 -0
- package/generators/migrate-surface-interaction-swatch/schema.json +26 -0
- package/generators/migrate-to-v5/apply-replacements.js +14 -0
- package/generators/migrate-to-v5/color-naming.js +124 -0
- package/generators/migrate-to-v5/create-provider.js +67 -55
- package/generators/migrate-to-v5/migration-files.js +13 -0
- package/generators/migrate-to-v5/migration.js +33 -19
- package/generators/migrate-to-v5/removed-exports.js +161 -0
- package/generators/migrate-to-v5/router-state-service.js +125 -330
- package/generators/migrate-to-v5/schema.json +22 -0
- package/generators/migrate-to-v5/service-classes.js +108 -0
- package/generators/migrate-to-v5/sync-observable-consumers.js +80 -0
- package/generators/migrate-to-v5/viewport-service.js +226 -491
- package/generators/tailwind-4-color-theme/generator.js +411 -0
- package/generators/tailwind-4-color-theme/schema.json +44 -0
- package/generators/tailwind-4-surface-theme/generator.js +379 -0
- package/generators/tailwind-4-surface-theme/schema.json +48 -0
- package/migrations/legacy-color-themes.md +38 -0
- package/migrations/seo-directive-removed.md +81 -0
- package/migrations/surface-theme-regenerate.md +20 -0
- package/migrations.json +59 -0
- package/package.json +38 -21
- package/src/lib/animations/easing-tokens-styles.component.css +155 -0
- package/src/lib/providers/visually-hidden-styles.component.css +13 -0
- package/src/lib/resize-handles/resize-handles.component.css +137 -0
- package/src/lib/theming/color-interactive-styles.component.css +147 -0
- package/src/lib/theming/surface-interactive-styles.component.css +42 -0
- package/types/ethlete-core.d.ts +3842 -2205
- package/generators/tailwind-4-theme/generator.js +0 -514
- package/generators/tailwind-4-theme/schema.json +0 -32
|
@@ -1,38 +1,65 @@
|
|
|
1
|
-
import { logger } from '@nx/devkit';
|
|
2
1
|
import * as ts from 'typescript';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
// Recursively find all TypeScript files
|
|
7
|
-
function findTsFiles(dir) {
|
|
8
|
-
const children = tree.children(dir);
|
|
9
|
-
for (const child of children) {
|
|
10
|
-
const path = dir === '.' ? child : `${dir}/${child}`;
|
|
11
|
-
if (tree.isFile(path)) {
|
|
12
|
-
if (path.endsWith('.ts') && !path.includes('node_modules') && !path.endsWith('.spec.ts')) {
|
|
13
|
-
tsFiles.push(path);
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
else {
|
|
17
|
-
findTsFiles(path);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
findTsFiles('.');
|
|
2
|
+
import { collectFiles } from './migration-files.js';
|
|
3
|
+
export default async function migrateCreateProvider(tree, scope) {
|
|
4
|
+
const review = [];
|
|
22
5
|
let filesModified = 0;
|
|
23
|
-
for (const filePath of
|
|
24
|
-
const
|
|
25
|
-
|
|
6
|
+
for (const filePath of collectFiles(tree, scope, ['.ts'])) {
|
|
7
|
+
const reexportsModified = migrateCreateProviderReexports(tree, filePath, review);
|
|
8
|
+
const wasModified = migrateCreateProviderInFile(tree, filePath) || reexportsModified;
|
|
9
|
+
if (wasModified)
|
|
26
10
|
filesModified++;
|
|
27
|
-
logger.log(` ā ${filePath}`);
|
|
28
|
-
}
|
|
29
11
|
}
|
|
30
|
-
|
|
31
|
-
|
|
12
|
+
return { filesChanged: filesModified, review };
|
|
13
|
+
}
|
|
14
|
+
function migrateCreateProviderReexports(tree, filePath, review) {
|
|
15
|
+
const content = tree.read(filePath, 'utf-8');
|
|
16
|
+
if (!content || !content.includes('createProvider'))
|
|
17
|
+
return false;
|
|
18
|
+
const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);
|
|
19
|
+
const edits = [];
|
|
20
|
+
for (const statement of sourceFile.statements) {
|
|
21
|
+
if (!ts.isImportDeclaration(statement) && !ts.isExportDeclaration(statement))
|
|
22
|
+
continue;
|
|
23
|
+
if (!statement.moduleSpecifier || !ts.isStringLiteral(statement.moduleSpecifier))
|
|
24
|
+
continue;
|
|
25
|
+
if (statement.moduleSpecifier.text !== '@ethlete/cdk')
|
|
26
|
+
continue;
|
|
27
|
+
if (ts.isImportDeclaration(statement)) {
|
|
28
|
+
const bindings = statement.importClause?.namedBindings;
|
|
29
|
+
if (bindings && ts.isNamespaceImport(bindings) && content.includes(`${bindings.name.text}.createProvider`)) {
|
|
30
|
+
review.push(`${filePath}: ${bindings.name.text}.createProvider is used through a namespace import of @ethlete/cdk. Switch it to createProvider from @ethlete/core manually.`);
|
|
31
|
+
}
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
const clause = statement.exportClause;
|
|
35
|
+
if (!clause) {
|
|
36
|
+
review.push(`${filePath}: "export * from '@ethlete/cdk'" may re-export createProvider. Re-export it from @ethlete/core manually.`);
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (ts.isNamespaceExport(clause))
|
|
40
|
+
continue;
|
|
41
|
+
const isCreateProvider = (element) => (element.propertyName?.text ?? element.name.text) === 'createProvider';
|
|
42
|
+
const moved = clause.elements.filter(isCreateProvider);
|
|
43
|
+
if (moved.length === 0)
|
|
44
|
+
continue;
|
|
45
|
+
const rest = clause.elements.filter((element) => !isCreateProvider(element));
|
|
46
|
+
const typeOnly = statement.isTypeOnly ? 'type ' : '';
|
|
47
|
+
const lines = [
|
|
48
|
+
...(rest.length > 0
|
|
49
|
+
? [`export ${typeOnly}{ ${rest.map((el) => el.getText(sourceFile)).join(', ')} } from '@ethlete/cdk';`]
|
|
50
|
+
: []),
|
|
51
|
+
`export ${typeOnly}{ ${moved.map((el) => el.getText(sourceFile)).join(', ')} } from '@ethlete/core';`,
|
|
52
|
+
];
|
|
53
|
+
edits.push({ start: statement.getStart(sourceFile), end: statement.getEnd(), text: lines.join('\n') });
|
|
32
54
|
}
|
|
33
|
-
|
|
34
|
-
|
|
55
|
+
if (edits.length === 0)
|
|
56
|
+
return false;
|
|
57
|
+
let updatedContent = content;
|
|
58
|
+
for (const edit of edits.reverse()) {
|
|
59
|
+
updatedContent = updatedContent.slice(0, edit.start) + edit.text + updatedContent.slice(edit.end);
|
|
35
60
|
}
|
|
61
|
+
tree.write(filePath, updatedContent);
|
|
62
|
+
return true;
|
|
36
63
|
}
|
|
37
64
|
function migrateCreateProviderInFile(tree, filePath) {
|
|
38
65
|
const content = tree.read(filePath, 'utf-8');
|
|
@@ -40,35 +67,30 @@ function migrateCreateProviderInFile(tree, filePath) {
|
|
|
40
67
|
return false;
|
|
41
68
|
const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);
|
|
42
69
|
let cdkImport;
|
|
43
|
-
let coreImport;
|
|
44
70
|
let hasCreateProviderInCdk = false;
|
|
45
|
-
|
|
71
|
+
let createProviderImport = 'createProvider';
|
|
46
72
|
for (const statement of sourceFile.statements) {
|
|
47
73
|
if (ts.isImportDeclaration(statement) && ts.isStringLiteral(statement.moduleSpecifier)) {
|
|
48
74
|
const modulePath = statement.moduleSpecifier.text;
|
|
49
75
|
if (modulePath === '@ethlete/cdk') {
|
|
50
76
|
cdkImport = statement;
|
|
51
77
|
if (statement.importClause?.namedBindings && ts.isNamedImports(statement.importClause.namedBindings)) {
|
|
52
|
-
|
|
78
|
+
const specifier = statement.importClause.namedBindings.elements.find((element) => (element.propertyName?.text ?? element.name.text) === 'createProvider');
|
|
79
|
+
hasCreateProviderInCdk = !!specifier;
|
|
80
|
+
createProviderImport = specifier?.getText(sourceFile) ?? createProviderImport;
|
|
53
81
|
}
|
|
54
82
|
}
|
|
55
|
-
else if (modulePath === '@ethlete/core') {
|
|
56
|
-
coreImport = statement;
|
|
57
|
-
}
|
|
58
83
|
}
|
|
59
84
|
}
|
|
60
|
-
// If createProvider is not imported from @ethlete/cdk, nothing to do
|
|
61
85
|
if (!hasCreateProviderInCdk)
|
|
62
86
|
return false;
|
|
63
87
|
let updatedContent = content;
|
|
64
|
-
// Remove createProvider from @ethlete/cdk import
|
|
65
88
|
if (cdkImport && cdkImport.importClause?.namedBindings && ts.isNamedImports(cdkImport.importClause.namedBindings)) {
|
|
66
89
|
const namedBindings = cdkImport.importClause.namedBindings;
|
|
67
|
-
const otherImports = namedBindings.elements.filter((element) => element.name.text !== 'createProvider');
|
|
90
|
+
const otherImports = namedBindings.elements.filter((element) => (element.propertyName?.text ?? element.name.text) !== 'createProvider');
|
|
68
91
|
const importStart = cdkImport.getStart(sourceFile);
|
|
69
92
|
const importEnd = cdkImport.getEnd();
|
|
70
93
|
if (otherImports.length === 0) {
|
|
71
|
-
// Remove entire import line including newline
|
|
72
94
|
let lineStart = importStart;
|
|
73
95
|
while (lineStart > 0 && content[lineStart - 1] !== '\n') {
|
|
74
96
|
lineStart--;
|
|
@@ -83,15 +105,12 @@ function migrateCreateProviderInFile(tree, filePath) {
|
|
|
83
105
|
updatedContent = content.slice(0, lineStart) + content.slice(lineEnd);
|
|
84
106
|
}
|
|
85
107
|
else {
|
|
86
|
-
|
|
87
|
-
const newImports = otherImports.map((el) => el.name.text).join(', ');
|
|
108
|
+
const newImports = otherImports.map((el) => el.getText(sourceFile)).join(', ');
|
|
88
109
|
const newImportText = `import { ${newImports} } from '@ethlete/cdk';`;
|
|
89
110
|
updatedContent = content.slice(0, importStart) + newImportText + content.slice(importEnd);
|
|
90
111
|
}
|
|
91
112
|
}
|
|
92
|
-
// Re-parse after first modification
|
|
93
113
|
const intermediateSourceFile = ts.createSourceFile(filePath, updatedContent, ts.ScriptTarget.Latest, true);
|
|
94
|
-
// Find @ethlete/core import in the updated content
|
|
95
114
|
let updatedCoreImport;
|
|
96
115
|
for (const statement of intermediateSourceFile.statements) {
|
|
97
116
|
if (ts.isImportDeclaration(statement) && ts.isStringLiteral(statement.moduleSpecifier)) {
|
|
@@ -101,26 +120,22 @@ function migrateCreateProviderInFile(tree, filePath) {
|
|
|
101
120
|
}
|
|
102
121
|
}
|
|
103
122
|
}
|
|
104
|
-
// Add createProvider to @ethlete/core import
|
|
105
123
|
if (updatedCoreImport?.importClause?.namedBindings &&
|
|
106
124
|
ts.isNamedImports(updatedCoreImport.importClause.namedBindings)) {
|
|
107
125
|
const namedBindings = updatedCoreImport.importClause.namedBindings;
|
|
108
|
-
|
|
109
|
-
const hasCreateProvider = namedBindings.elements.some((element) => element.name.text === 'createProvider');
|
|
126
|
+
const hasCreateProvider = namedBindings.elements.some((element) => (element.propertyName?.text ?? element.name.text) === 'createProvider');
|
|
110
127
|
if (!hasCreateProvider) {
|
|
111
128
|
const importStart = updatedCoreImport.getStart(intermediateSourceFile);
|
|
112
129
|
const importEnd = updatedCoreImport.getEnd();
|
|
113
|
-
const existingImports = namedBindings.elements.map((el) => el.
|
|
114
|
-
const allImports = [...existingImports,
|
|
130
|
+
const existingImports = namedBindings.elements.map((el) => el.getText(intermediateSourceFile));
|
|
131
|
+
const allImports = [...existingImports, createProviderImport].sort();
|
|
115
132
|
const newImportText = `import { ${allImports.join(', ')} } from '@ethlete/core';`;
|
|
116
133
|
updatedContent = updatedContent.slice(0, importStart) + newImportText + updatedContent.slice(importEnd);
|
|
117
134
|
}
|
|
118
135
|
}
|
|
119
136
|
else {
|
|
120
|
-
// Add new import from @ethlete/core at the top
|
|
121
137
|
const firstImportIndex = updatedContent.indexOf('import');
|
|
122
138
|
if (firstImportIndex !== -1) {
|
|
123
|
-
// Add after other imports
|
|
124
139
|
let insertPosition;
|
|
125
140
|
let lastImportEnd = firstImportIndex;
|
|
126
141
|
for (const statement of intermediateSourceFile.statements) {
|
|
@@ -132,7 +147,6 @@ function migrateCreateProviderInFile(tree, filePath) {
|
|
|
132
147
|
}
|
|
133
148
|
}
|
|
134
149
|
insertPosition = lastImportEnd;
|
|
135
|
-
// Find end of line
|
|
136
150
|
while (insertPosition < updatedContent.length && updatedContent[insertPosition] !== '\n') {
|
|
137
151
|
insertPosition++;
|
|
138
152
|
}
|
|
@@ -141,12 +155,11 @@ function migrateCreateProviderInFile(tree, filePath) {
|
|
|
141
155
|
}
|
|
142
156
|
updatedContent =
|
|
143
157
|
updatedContent.slice(0, insertPosition) +
|
|
144
|
-
|
|
158
|
+
`import { ${createProviderImport} } from '@ethlete/core';\n` +
|
|
145
159
|
updatedContent.slice(insertPosition);
|
|
146
160
|
}
|
|
147
161
|
else {
|
|
148
|
-
|
|
149
|
-
updatedContent = "import { createProvider } from '@ethlete/core';\n\n" + updatedContent;
|
|
162
|
+
updatedContent = `import { ${createProviderImport} } from '@ethlete/core';\n\n` + updatedContent;
|
|
150
163
|
}
|
|
151
164
|
}
|
|
152
165
|
if (updatedContent !== content) {
|
|
@@ -155,4 +168,3 @@ function migrateCreateProviderInFile(tree, filePath) {
|
|
|
155
168
|
}
|
|
156
169
|
return false;
|
|
157
170
|
}
|
|
158
|
-
//# sourceMappingURL=create-provider.js.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { createMigrationScope } from '../migrate-provider-shape/migration-scope.js';
|
|
2
|
+
const SKIPPED_DIRECTORIES = new Set(['node_modules', 'dist', '.git', '.angular', '.nx']);
|
|
3
|
+
export const collectFiles = (tree, scope, extensions) => {
|
|
4
|
+
const files = [];
|
|
5
|
+
(scope ?? createMigrationScope(tree, {})).visit(tree, (filePath) => {
|
|
6
|
+
if (filePath.split('/').some((segment) => SKIPPED_DIRECTORIES.has(segment)))
|
|
7
|
+
return;
|
|
8
|
+
if (!extensions.some((extension) => filePath.endsWith(extension)))
|
|
9
|
+
return;
|
|
10
|
+
files.push(filePath);
|
|
11
|
+
});
|
|
12
|
+
return files;
|
|
13
|
+
};
|
|
@@ -1,28 +1,42 @@
|
|
|
1
|
-
import { formatFiles } from '@nx/devkit';
|
|
1
|
+
import { formatFiles, logger } from '@nx/devkit';
|
|
2
|
+
import { createMigrationScope, } from '../migrate-provider-shape/migration-scope.js';
|
|
3
|
+
import migrateColorNaming from './color-naming.js';
|
|
2
4
|
import migrateCreateProvider from './create-provider.js';
|
|
5
|
+
import reportRemovedExports from './removed-exports.js';
|
|
3
6
|
import migrateRouterStateService from './router-state-service.js';
|
|
4
7
|
import migrateViewportService from './viewport-service.js';
|
|
5
8
|
export default async function migrate(tree, schema) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
9
|
+
const scope = createMigrationScope(tree, schema);
|
|
10
|
+
logger.info('\nš Starting core v5 migration...');
|
|
11
|
+
logger.info(` Scope: ${scope.describe()}`);
|
|
12
|
+
const transforms = [
|
|
13
|
+
{ label: 'ViewportService', enabled: schema.migrateViewportService !== false, run: migrateViewportService },
|
|
14
|
+
{ label: 'createProvider', enabled: schema.migrateCreateProvider !== false, run: migrateCreateProvider },
|
|
15
|
+
{
|
|
16
|
+
label: 'RouterStateService',
|
|
17
|
+
enabled: schema.migrateRouterStateService !== false,
|
|
18
|
+
run: migrateRouterStateService,
|
|
19
|
+
},
|
|
20
|
+
{ label: 'Theme ā color naming', enabled: schema.migrateColorNaming !== false, run: migrateColorNaming },
|
|
21
|
+
{ label: 'Removed exports', enabled: schema.reportRemovedExports !== false, run: reportRemovedExports },
|
|
22
|
+
];
|
|
23
|
+
const reports = [];
|
|
24
|
+
for (const transform of transforms) {
|
|
25
|
+
if (!transform.enabled)
|
|
26
|
+
continue;
|
|
27
|
+
logger.info(` ⢠${transform.label}...`);
|
|
28
|
+
reports.push([transform.label, await transform.run(tree, scope)]);
|
|
20
29
|
}
|
|
21
30
|
if (!schema.skipFormat) {
|
|
22
|
-
console.log(' ⢠Formatting files...');
|
|
23
31
|
await formatFiles(tree);
|
|
24
32
|
}
|
|
25
|
-
|
|
33
|
+
logger.info('\nSummary:');
|
|
34
|
+
for (const [label, report] of reports) {
|
|
35
|
+
const review = report.review.length > 0 ? `, ${report.review.length} to review manually` : '';
|
|
36
|
+
logger.info(` ⢠${label}: ${report.filesChanged} file(s) changed${review}`);
|
|
37
|
+
for (const message of report.review) {
|
|
38
|
+
logger.warn(` ā ${message}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
logger.info('\nā
Migration completed. Review the diff before committing.');
|
|
26
42
|
}
|
|
27
|
-
//#endregion
|
|
28
|
-
//# sourceMappingURL=migration.js.map
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import * as ts from 'typescript';
|
|
2
|
+
import { collectFiles } from './migration-files.js';
|
|
3
|
+
export const REMOVED_EXPORTS = new Map([
|
|
4
|
+
...['Memo', 'MemoConfig', 'MemoResolver', 'MapLike'].map((name) => [name, 'together with the @Memo decorator and has no replacement.']),
|
|
5
|
+
...[
|
|
6
|
+
'createProps',
|
|
7
|
+
'createHostProps',
|
|
8
|
+
'createPropHandlers',
|
|
9
|
+
'createSetup',
|
|
10
|
+
'createDependencyStash',
|
|
11
|
+
'createElementDictionary',
|
|
12
|
+
'bindProps',
|
|
13
|
+
'unbindProps',
|
|
14
|
+
'PropsDirective',
|
|
15
|
+
'templateComputed',
|
|
16
|
+
'ComponentType',
|
|
17
|
+
'AnyTemplateType',
|
|
18
|
+
'TemplateRefWithContext',
|
|
19
|
+
'ComponentTypeWithInputs',
|
|
20
|
+
'StringTemplate',
|
|
21
|
+
'NgTemplateTemplate',
|
|
22
|
+
'ComponentTemplate',
|
|
23
|
+
'Props',
|
|
24
|
+
'PropsAttachedElements',
|
|
25
|
+
'PropsAttachedElementsInternal',
|
|
26
|
+
'PropsInternal',
|
|
27
|
+
'CreatePropsOptions',
|
|
28
|
+
'HostProps',
|
|
29
|
+
'PropHandlers',
|
|
30
|
+
'BindPropsOptions',
|
|
31
|
+
'UnbindPropsOptions',
|
|
32
|
+
].map((name) => [name, 'together with the props module and has no replacement.']),
|
|
33
|
+
...['LetDirective', 'LetContext'].map((name) => [
|
|
34
|
+
name,
|
|
35
|
+
"in v5. Use Angular's `@let`. `@ethlete/cdk:migrate-to-v5` rewrites `*etLet` templates; without the cdk, rewrite them by hand.",
|
|
36
|
+
]),
|
|
37
|
+
...['IsActiveElementDirective', 'IS_ACTIVE_ELEMENT', 'IsElementDirective', 'IS_ELEMENT'].map((name) => [
|
|
38
|
+
name,
|
|
39
|
+
'in v5. Inside a scrollable, use `ScrollableIsActiveChildDirective`; `@ethlete/cdk:migrate-to-v5` rewrites it.',
|
|
40
|
+
]),
|
|
41
|
+
...['ObserveResizeDirective', 'ResizeObserverService', 'ResizeObserverFactory', 'createResizeObservable'].map((name) => [name, 'in v5. Use `signalElementDimensions()`.']),
|
|
42
|
+
...['ObserveContentDirective', 'ContentObserverService', 'MutationObserverFactory', 'createMutationObservable'].map((name) => [name, 'in v5. Use `signalElementMutations()`.']),
|
|
43
|
+
...[
|
|
44
|
+
'ObserveVisibilityDirective',
|
|
45
|
+
'OBSERVE_VISIBILITY_TOKEN',
|
|
46
|
+
'ObserveVisibilityChange',
|
|
47
|
+
'IntersectionObserverService',
|
|
48
|
+
'IntersectionObserverFactory',
|
|
49
|
+
'getIntersectionInfo',
|
|
50
|
+
'signalVisibilityChangeClasses',
|
|
51
|
+
].map((name) => [name, 'in v5. Use `signalElementIntersection()`.']),
|
|
52
|
+
...[
|
|
53
|
+
'ObserveScrollStateDirective',
|
|
54
|
+
'OBSERVE_SCROLL_STATE',
|
|
55
|
+
'ScrollObserverFirstElementDirective',
|
|
56
|
+
'ScrollObserverLastElementDirective',
|
|
57
|
+
'ScrollObserverIgnoreTargetDirective',
|
|
58
|
+
'SCROLL_OBSERVER_FIRST_ELEMENT_CLASS',
|
|
59
|
+
'SCROLL_OBSERVER_IGNORE_TARGET_CLASS',
|
|
60
|
+
'SCROLL_OBSERVER_LAST_ELEMENT_CLASS',
|
|
61
|
+
'SCROLL_OBSERVER_OBSERVING_FIRST_ELEMENT_CLASS',
|
|
62
|
+
'SCROLL_OBSERVER_OBSERVING_LAST_ELEMENT_CLASS',
|
|
63
|
+
'ScrollObserverScrollState',
|
|
64
|
+
'ObservedScrollableChild',
|
|
65
|
+
'areScrollStatesEqual',
|
|
66
|
+
].map((name) => [
|
|
67
|
+
name,
|
|
68
|
+
'in v5. Use `signalElementScrollState()`, or `ScrollableScrollState` of the `@ethlete/components` scrollable.',
|
|
69
|
+
]),
|
|
70
|
+
...['CursorDragScrollDirective', 'CURSOR_DRAG_SCROLLING_CLASS', 'CURSOR_DRAG_SCROLLING_PREPARED_CLASS'].map((name) => [name, 'in v5. Use `useCursorDragScroll()`.']),
|
|
71
|
+
...['RootBoundaryDirective', 'ROOT_BOUNDARY_TOKEN'].map((name) => [name, 'in v5. Use `provideBoundaryElement()`.']),
|
|
72
|
+
...['DelayableDirective', 'DELAYABLE_TOKEN'].map((name) => [name, 'in v5. Use `provideInfinityQueryResponseDelay()` from `@ethlete/query`.']),
|
|
73
|
+
...[
|
|
74
|
+
'SeoDirective',
|
|
75
|
+
'SEO_DIRECTIVE_TOKEN',
|
|
76
|
+
'SeoConfig',
|
|
77
|
+
'mergeSeoConfig',
|
|
78
|
+
'OpenGraph',
|
|
79
|
+
'TwitterCard',
|
|
80
|
+
'FacebookCard',
|
|
81
|
+
'AlternateLink',
|
|
82
|
+
].map((name) => [name, 'in v5. Use the `apply*Binding` functions; the SEO guide has a per-key migration table.']),
|
|
83
|
+
...['AnimatedOverlayDirective', 'AnimatedOverlayComponentBase'].map((name) => [
|
|
84
|
+
name,
|
|
85
|
+
'in v5. It moved to `@ethlete/cdk`; `@ethlete/components` overlays use the overlay strategy controller.',
|
|
86
|
+
]),
|
|
87
|
+
...[
|
|
88
|
+
'SelectionModel',
|
|
89
|
+
'ActiveSelectionModel',
|
|
90
|
+
'SelectionModelBinding',
|
|
91
|
+
'SelectionModelOptionValueFn',
|
|
92
|
+
'SelectionModelPropertyPath',
|
|
93
|
+
'SelectionModelTypes',
|
|
94
|
+
].map((name) => [name, 'in v5. It moved into the `@ethlete/cdk` select and has no public replacement.']),
|
|
95
|
+
...['FocusVisibleService'].map((name) => [name, 'in v5. Use `injectFocusVisibleTracker()`.']),
|
|
96
|
+
...['createMediaQueryObservable'].map((name) => [name, 'in v5. Use `injectBreakpointIsMatched()` or the other media query signals.']),
|
|
97
|
+
...['createReactiveBindings', 'ReactiveAttributes', 'ReactiveBindingResult'].map((name) => [name, 'in v5. Use `signalHostClasses()` / `signalHostAttributes()`.']),
|
|
98
|
+
...['debouncedControlValueSignal', 'DebouncedControlValueSignalOptions'].map((name) => [name, 'in v5. Debounce the `controlValueSignal()` value with `toObservable()` and `debounceTime()`.']),
|
|
99
|
+
...['ProviderResult', 'RootProviderResult', 'StaticProviderResult', 'CreateProviderOptions'].map((name) => [
|
|
100
|
+
name,
|
|
101
|
+
'in v5. It belonged to the removed `create*Provider` factories, which `@ethlete/core:migrate-provider-shape` rewrites.',
|
|
102
|
+
]),
|
|
103
|
+
...['VIEWPORT_CONFIG'].map((name) => [name, 'in v5. Use `provideViewportConfig()`.']),
|
|
104
|
+
...[
|
|
105
|
+
'ClickObserverService',
|
|
106
|
+
'ClickObserverFactory',
|
|
107
|
+
'DebugDirective',
|
|
108
|
+
'DEBUG_TOKEN',
|
|
109
|
+
'HostDirective',
|
|
110
|
+
'MaybeObservable',
|
|
111
|
+
'Primitive',
|
|
112
|
+
'Reference',
|
|
113
|
+
'Size',
|
|
114
|
+
'Validators',
|
|
115
|
+
'isEmptyArray',
|
|
116
|
+
'isObjectArray',
|
|
117
|
+
'isPrimitiveArray',
|
|
118
|
+
'ScrollEnhancementsConfig',
|
|
119
|
+
'SmartBlockScrollStrategy',
|
|
120
|
+
].map((name) => [name, 'in v5. It has no replacement.']),
|
|
121
|
+
]);
|
|
122
|
+
const ET_PROPS_ATTRIBUTE = /\betProps\b/;
|
|
123
|
+
export default async function reportRemovedExports(tree, scope) {
|
|
124
|
+
const review = [];
|
|
125
|
+
for (const filePath of collectFiles(tree, scope, ['.ts', '.html'])) {
|
|
126
|
+
const messages = filePath.endsWith('.ts') ? findRemovedImports(tree, filePath) : findEtPropsUsage(tree, filePath);
|
|
127
|
+
review.push(...messages.map((message) => `${filePath}: ${message}`));
|
|
128
|
+
}
|
|
129
|
+
return { filesChanged: 0, review };
|
|
130
|
+
}
|
|
131
|
+
function findRemovedImports(tree, filePath) {
|
|
132
|
+
const content = tree.read(filePath, 'utf-8');
|
|
133
|
+
if (!content || !content.includes('@ethlete/core'))
|
|
134
|
+
return [];
|
|
135
|
+
const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);
|
|
136
|
+
const messages = [];
|
|
137
|
+
for (const statement of sourceFile.statements) {
|
|
138
|
+
if (!ts.isImportDeclaration(statement) && !ts.isExportDeclaration(statement))
|
|
139
|
+
continue;
|
|
140
|
+
const specifier = statement.moduleSpecifier;
|
|
141
|
+
if (!specifier || !ts.isStringLiteral(specifier) || specifier.text !== '@ethlete/core')
|
|
142
|
+
continue;
|
|
143
|
+
const bindings = ts.isImportDeclaration(statement) ? statement.importClause?.namedBindings : statement.exportClause;
|
|
144
|
+
if (!bindings || ts.isNamespaceImport(bindings) || ts.isNamespaceExport(bindings))
|
|
145
|
+
continue;
|
|
146
|
+
for (const element of bindings.elements) {
|
|
147
|
+
const name = (element.propertyName ?? element.name).text;
|
|
148
|
+
const successor = REMOVED_EXPORTS.get(name);
|
|
149
|
+
if (successor) {
|
|
150
|
+
messages.push(`${name} was removed from @ethlete/core ${successor}`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return messages;
|
|
155
|
+
}
|
|
156
|
+
function findEtPropsUsage(tree, filePath) {
|
|
157
|
+
const content = tree.read(filePath, 'utf-8');
|
|
158
|
+
if (!content || !ET_PROPS_ATTRIBUTE.test(content))
|
|
159
|
+
return [];
|
|
160
|
+
return ['[etProps] (PropsDirective) was removed from @ethlete/core together with the props module.'];
|
|
161
|
+
}
|