igniteui-angular 22.2.0-rc.0 → 22.2.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/README.md +1 -1
  2. package/button-group/README.md +42 -9
  3. package/calendar/README.md +30 -20
  4. package/card/README.md +1 -1
  5. package/fesm2022/igniteui-angular-accordion.mjs +7 -7
  6. package/fesm2022/igniteui-angular-action-strip.mjs +11 -22
  7. package/fesm2022/igniteui-angular-action-strip.mjs.map +1 -1
  8. package/fesm2022/igniteui-angular-avatar.mjs +7 -7
  9. package/fesm2022/igniteui-angular-badge.mjs +7 -7
  10. package/fesm2022/igniteui-angular-banner.mjs +10 -10
  11. package/fesm2022/igniteui-angular-bottom-nav.mjs +22 -22
  12. package/fesm2022/igniteui-angular-button-group.mjs +32 -35
  13. package/fesm2022/igniteui-angular-button-group.mjs.map +1 -1
  14. package/fesm2022/igniteui-angular-calendar.mjs +132 -180
  15. package/fesm2022/igniteui-angular-calendar.mjs.map +1 -1
  16. package/fesm2022/igniteui-angular-card.mjs +47 -58
  17. package/fesm2022/igniteui-angular-card.mjs.map +1 -1
  18. package/fesm2022/igniteui-angular-carousel.mjs +22 -22
  19. package/fesm2022/igniteui-angular-chat-extras.mjs +6 -6
  20. package/fesm2022/igniteui-angular-chat.mjs +12 -12
  21. package/fesm2022/igniteui-angular-checkbox.mjs +7 -7
  22. package/fesm2022/igniteui-angular-chips.mjs +10 -10
  23. package/fesm2022/igniteui-angular-combo.mjs +69 -67
  24. package/fesm2022/igniteui-angular-combo.mjs.map +1 -1
  25. package/fesm2022/igniteui-angular-core.mjs +139 -92
  26. package/fesm2022/igniteui-angular-core.mjs.map +1 -1
  27. package/fesm2022/igniteui-angular-date-picker.mjs +53 -70
  28. package/fesm2022/igniteui-angular-date-picker.mjs.map +1 -1
  29. package/fesm2022/igniteui-angular-dialog.mjs +13 -13
  30. package/fesm2022/igniteui-angular-directives.mjs +194 -194
  31. package/fesm2022/igniteui-angular-drop-down.mjs +29 -29
  32. package/fesm2022/igniteui-angular-expansion-panel.mjs +28 -28
  33. package/fesm2022/igniteui-angular-grids-core.mjs +737 -661
  34. package/fesm2022/igniteui-angular-grids-core.mjs.map +1 -1
  35. package/fesm2022/igniteui-angular-grids-grid.mjs +49 -49
  36. package/fesm2022/igniteui-angular-grids-hierarchical-grid.mjs +37 -37
  37. package/fesm2022/igniteui-angular-grids-lite.mjs +25 -17
  38. package/fesm2022/igniteui-angular-grids-lite.mjs.map +1 -1
  39. package/fesm2022/igniteui-angular-grids-pivot-grid.mjs +80 -80
  40. package/fesm2022/igniteui-angular-grids-pivot-grid.mjs.map +1 -1
  41. package/fesm2022/igniteui-angular-grids-tree-grid.mjs +55 -55
  42. package/fesm2022/igniteui-angular-icon.mjs +10 -10
  43. package/fesm2022/igniteui-angular-input-group.mjs +59 -55
  44. package/fesm2022/igniteui-angular-input-group.mjs.map +1 -1
  45. package/fesm2022/igniteui-angular-list.mjs +40 -40
  46. package/fesm2022/igniteui-angular-navbar.mjs +13 -13
  47. package/fesm2022/igniteui-angular-navigation-drawer.mjs +43 -38
  48. package/fesm2022/igniteui-angular-navigation-drawer.mjs.map +1 -1
  49. package/fesm2022/igniteui-angular-paginator.mjs +19 -19
  50. package/fesm2022/igniteui-angular-progressbar.mjs +19 -19
  51. package/fesm2022/igniteui-angular-query-builder.mjs +22 -22
  52. package/fesm2022/igniteui-angular-radio.mjs +25 -21
  53. package/fesm2022/igniteui-angular-radio.mjs.map +1 -1
  54. package/fesm2022/igniteui-angular-select.mjs +29 -33
  55. package/fesm2022/igniteui-angular-select.mjs.map +1 -1
  56. package/fesm2022/igniteui-angular-simple-combo.mjs +9 -9
  57. package/fesm2022/igniteui-angular-simple-combo.mjs.map +1 -1
  58. package/fesm2022/igniteui-angular-slider.mjs +28 -28
  59. package/fesm2022/igniteui-angular-snackbar.mjs +7 -7
  60. package/fesm2022/igniteui-angular-splitter.mjs +13 -13
  61. package/fesm2022/igniteui-angular-stepper.mjs +34 -34
  62. package/fesm2022/igniteui-angular-switch.mjs +7 -7
  63. package/fesm2022/igniteui-angular-tabs.mjs +34 -34
  64. package/fesm2022/igniteui-angular-time-picker.mjs +26 -36
  65. package/fesm2022/igniteui-angular-time-picker.mjs.map +1 -1
  66. package/fesm2022/igniteui-angular-toast.mjs +7 -7
  67. package/fesm2022/igniteui-angular-tree.mjs +28 -28
  68. package/fesm2022/igniteui-angular-virtual-scroll.mjs +497 -145
  69. package/fesm2022/igniteui-angular-virtual-scroll.mjs.map +1 -1
  70. package/migrations/common/UpdateChanges.d.ts +56 -0
  71. package/migrations/common/UpdateChanges.js +366 -38
  72. package/migrations/common/UpdateChanges.spec.js +829 -0
  73. package/migrations/migration-collection.json +1 -1
  74. package/migrations/update-22_2_0/index.js +145 -0
  75. package/migrations/update-22_2_0/index.spec.js +206 -0
  76. package/navigation-drawer/README.md +1 -1
  77. package/package.json +3 -3
  78. package/schematics/tsconfig.tsbuildinfo +1 -1
  79. package/skills/igniteui-angular-components/SKILL.md +9 -5
  80. package/skills/igniteui-angular-components/references/form-controls.md +1 -1
  81. package/skills/igniteui-angular-components/references/mcp-setup.md +14 -2
  82. package/skills/igniteui-angular-figma-to-app/SKILL.md +112 -525
  83. package/skills/igniteui-angular-figma-to-app/references/asset-extraction.md +49 -75
  84. package/skills/igniteui-angular-figma-to-app/references/design-provenance.md +201 -0
  85. package/skills/igniteui-angular-figma-to-app/references/design-token-bridge.md +175 -52
  86. package/skills/igniteui-angular-figma-to-app/references/figma-component-map.md +153 -99
  87. package/skills/igniteui-angular-figma-to-app/references/figma-exploration.md +226 -0
  88. package/skills/igniteui-angular-figma-to-app/references/mcp-setup.md +71 -105
  89. package/skills/igniteui-angular-figma-to-app/references/project-setup.md +63 -0
  90. package/skills/igniteui-angular-figma-to-app/references/theme-generation.md +120 -0
  91. package/skills/igniteui-angular-figma-to-app/references/validation-patterns.md +48 -50
  92. package/skills/igniteui-angular-generate-from-image-design/SKILL.md +11 -7
  93. package/skills/igniteui-angular-grids/SKILL.md +7 -3
  94. package/skills/igniteui-angular-grids/references/editing.md +1 -2
  95. package/skills/igniteui-angular-grids/references/grid-migration.md +1 -1
  96. package/skills/igniteui-angular-theming/SKILL.md +9 -5
  97. package/skills/igniteui-angular-theming/references/mcp-setup.md +12 -2
  98. package/types/igniteui-angular-button-group.d.ts +49 -34
  99. package/types/igniteui-angular-calendar.d.ts +33 -50
  100. package/types/igniteui-angular-card.d.ts +12 -17
  101. package/types/igniteui-angular-combo.d.ts +6 -0
  102. package/types/igniteui-angular-core.d.ts +25 -8
  103. package/types/igniteui-angular-grids-core.d.ts +48 -4
  104. package/types/igniteui-angular-grids-lite.d.ts +5 -1
  105. package/types/igniteui-angular-grids-pivot-grid.d.ts +1 -1
  106. package/types/igniteui-angular-input-group.d.ts +17 -3
  107. package/types/igniteui-angular-navigation-drawer.d.ts +1 -0
  108. package/types/igniteui-angular-radio.d.ts +5 -0
  109. package/types/igniteui-angular-time-picker.d.ts +0 -1
  110. package/types/igniteui-angular-virtual-scroll.d.ts +41 -13
  111. package/virtual-scroll/README.md +32 -1
@@ -312,7 +312,7 @@
312
312
  },
313
313
  "migration-61": {
314
314
  "version": "22.2.0",
315
- "description": "Removes scrollbar-theme properties with no effect under the standard scrollbar properties",
315
+ "description": "Removes scrollbar-theme properties with no effect under the standard scrollbar properties and replaces the removed button group multiSelection input with selectionMode",
316
316
  "factory": "./update-22_2_0"
317
317
  },
318
318
  "migration-62": {
@@ -1,4 +1,37 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
36
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
37
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -9,10 +42,122 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
42
  });
10
43
  };
11
44
  Object.defineProperty(exports, "__esModule", { value: true });
45
+ const path = __importStar(require("path"));
46
+ const ts = __importStar(require("typescript"));
12
47
  const UpdateChanges_1 = require("../common/UpdateChanges");
48
+ const util_1 = require("../common/util");
49
+ // use bare specifier to escape the schematics encapsulation for the dynamic import:
50
+ const import_helper_cjs_1 = require("igniteui-angular/migrations/common/import-helper.cjs");
13
51
  const version = '22.2.0';
14
52
  exports.default = () => (host, context) => __awaiter(void 0, void 0, void 0, function* () {
15
53
  context.logger.info(`Applying migration for Ignite UI for Angular to version ${version}`);
54
+ const { HtmlParser } = yield (0, import_helper_cjs_1.nativeImport)('@angular/compiler');
16
55
  const update = new UpdateChanges_1.UpdateChanges(__dirname, host, context);
17
56
  update.applyChanges();
57
+ migrateButtonGroupMultiSelection(host, context, update, new HtmlParser());
58
+ });
59
+ // IgxButtonGroupComponent: the deprecated `multiSelection` input is replaced by `selectionMode`
60
+ const MULTI_SELECTION = ['[multiSelection]', 'multiSelection'];
61
+ const getSelectionMode = (name, value) => {
62
+ const expression = value.trim();
63
+ if (name === 'multiSelection') {
64
+ return expression === 'true' ? `selectionMode="multi"` : '';
65
+ }
66
+ if (expression === 'true') {
67
+ return `[selectionMode]="'multi'"`;
68
+ }
69
+ if (expression === 'false' || !expression) {
70
+ return '';
71
+ }
72
+ return `[selectionMode]="(${expression}) ? 'multi' : 'single'"`;
73
+ };
74
+ /** Returns the changes, relative to `content`, replacing `multiSelection` on the button groups in a template. */
75
+ const getTemplateChanges = (parser, content, url) => (0, util_1.findElementNodes)(parser.parse(content, url).rootNodes, 'igx-buttongroup')
76
+ .flatMap(node => (0, util_1.getAttribute)(node, MULTI_SELECTION))
77
+ .map(attr => {
78
+ const text = getSelectionMode(attr.name, attr.value);
79
+ let start = attr.sourceSpan.start.offset;
80
+ // drop the whitespace separating a removed attribute from the previous one
81
+ while (!text && start > 0 && /\s/.test(content[start - 1])) {
82
+ start--;
83
+ }
84
+ return { start, end: attr.sourceSpan.end.offset, text };
18
85
  });
86
+ const applyTemplateChanges = (content, changes) => [...changes]
87
+ .sort((a, b) => b.start - a.start)
88
+ .reduce((result, c) => result.substring(0, c.start) + c.text + result.substring(c.end), content);
89
+ /** Returns the metadata object literals of the `@Component` decorators in a source file. */
90
+ const getComponentMetadata = (sourceFile) => {
91
+ const metadata = [];
92
+ const visit = (node) => {
93
+ if (ts.isDecorator(node) && ts.isCallExpression(node.expression)
94
+ && ts.isIdentifier(node.expression.expression) && node.expression.expression.text === 'Component') {
95
+ const [arg] = node.expression.arguments;
96
+ if (arg && ts.isObjectLiteralExpression(arg)) {
97
+ metadata.push(arg);
98
+ }
99
+ }
100
+ ts.forEachChild(node, visit);
101
+ };
102
+ visit(sourceFile);
103
+ return metadata;
104
+ };
105
+ const getMetadataProperty = (metadata, name) => {
106
+ var _a;
107
+ return (_a = metadata.properties
108
+ .filter(ts.isPropertyAssignment)
109
+ .find(p => (ts.isIdentifier(p.name) || ts.isStringLiteral(p.name)) && p.name.text === name)) === null || _a === void 0 ? void 0 : _a.initializer;
110
+ };
111
+ const migrateButtonGroupMultiSelection = (host, context, update, parser) => {
112
+ // `templateFiles` only lists `*.component.html` files, so also collect the `templateUrl` of every component
113
+ const templateFiles = new Set(update.templateFiles);
114
+ for (const tsPath of update.tsFiles) {
115
+ const content = host.read(tsPath).toString();
116
+ if (!content.includes('@Component')) {
117
+ continue;
118
+ }
119
+ const sourceFile = ts.createSourceFile(tsPath, content, ts.ScriptTarget.Latest, true);
120
+ const changes = [];
121
+ for (const metadata of getComponentMetadata(sourceFile)) {
122
+ const templateUrl = getMetadataProperty(metadata, 'templateUrl');
123
+ if (templateUrl && ts.isStringLiteralLike(templateUrl)) {
124
+ const templatePath = path.posix.join(path.posix.dirname(tsPath), templateUrl.text);
125
+ if (host.exists(templatePath)) {
126
+ templateFiles.add(templatePath);
127
+ }
128
+ }
129
+ const template = getMetadataProperty(metadata, 'template');
130
+ if (!template || !template.getText(sourceFile).includes('multiSelection')) {
131
+ continue;
132
+ }
133
+ if (!ts.isStringLiteral(template) && !ts.isNoSubstitutionTemplateLiteral(template)) {
134
+ context.logger.warn(`${tsPath}: replace the removed IgxButtonGroupComponent multiSelection input with selectionMode manually.`);
135
+ continue;
136
+ }
137
+ // work on the raw source text between the quotes, so that the template offsets match the file ones
138
+ const quote = content[template.getStart(sourceFile)];
139
+ const start = template.getStart(sourceFile) + 1;
140
+ const raw = content.substring(start, template.getEnd() - 1);
141
+ for (const change of getTemplateChanges(parser, raw, tsPath)) {
142
+ changes.push({
143
+ start: change.start + start,
144
+ end: change.end + start,
145
+ text: quote === '`' ? change.text : change.text.split(quote).join(`\\${quote}`)
146
+ });
147
+ }
148
+ }
149
+ if (changes.length) {
150
+ host.overwrite(tsPath, applyTemplateChanges(content, changes));
151
+ }
152
+ }
153
+ for (const templatePath of templateFiles) {
154
+ const content = host.read(templatePath).toString();
155
+ if (!content.includes('multiSelection')) {
156
+ continue;
157
+ }
158
+ const changes = getTemplateChanges(parser, content, templatePath);
159
+ if (changes.length) {
160
+ host.overwrite(templatePath, applyTemplateChanges(content, changes));
161
+ }
162
+ }
163
+ };
@@ -77,6 +77,79 @@ describe(`Update to ${version}`, () => {
77
77
  const tree = yield schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree);
78
78
  expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(content);
79
79
  }));
80
+ it('should keep the brackets balanced when the theme is nested in another call', () => __awaiter(void 0, void 0, void 0, function* () {
81
+ appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `.selection-area {
82
+ @include scrollbar(scrollbar-theme($sb-size: 6px));
83
+ }
84
+
85
+ igx-grid {
86
+ @include scrollbar(scrollbar-theme($sb-thumb-bg-color: blue, $sb-size: 16px));
87
+ }`);
88
+ const tree = yield schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree);
89
+ expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`.selection-area {
90
+ @include scrollbar(scrollbar-theme());
91
+ }
92
+
93
+ igx-grid {
94
+ @include scrollbar(scrollbar-theme($sb-thumb-bg-color: blue));
95
+ }`);
96
+ }));
97
+ it('should migrate a theme call that is not terminated by a semicolon', () => __awaiter(void 0, void 0, void 0, function* () {
98
+ appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$my-scrollbar: scrollbar-theme(
99
+ $sb-size: 16px,
100
+ $sb-thumb-bg-color: blue
101
+ )`);
102
+ const tree = yield schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree);
103
+ expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$my-scrollbar: scrollbar-theme(
104
+ $sb-thumb-bg-color: blue
105
+ )`);
106
+ }));
107
+ it('should keep a retained property when a comment in the argument list holds an apostrophe', () => __awaiter(void 0, void 0, void 0, function* () {
108
+ appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$my-scrollbar: scrollbar-theme($sb-size: 6px /* user's size */, $sb-thumb-bg-color: red);`);
109
+ const tree = yield schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree);
110
+ expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$my-scrollbar: scrollbar-theme( $sb-thumb-bg-color: red);`);
111
+ }));
112
+ it('should remove the properties that follow a comment holding an apostrophe', () => __awaiter(void 0, void 0, void 0, function* () {
113
+ appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$my-scrollbar: scrollbar-theme(
114
+ $sb-size: 16px, // don't need this anymore
115
+ $sb-thumb-bg-color: blue,
116
+ $sb-corner-bg: gray
117
+ );`);
118
+ const tree = yield schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree);
119
+ expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$my-scrollbar: scrollbar-theme( // don't need this anymore
120
+ $sb-thumb-bg-color: blue
121
+ );`);
122
+ }));
123
+ it('should migrate a theme below a comment glued to a closing brace', () => __awaiter(void 0, void 0, void 0, function* () {
124
+ appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `.selection-area {
125
+ color: red;
126
+ }// don't set $sb-size here
127
+
128
+ $my-scrollbar: scrollbar-theme($sb-size: 16px, $sb-thumb-bg-color: blue);`);
129
+ const tree = yield schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree);
130
+ expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`.selection-area {
131
+ color: red;
132
+ }// don't set $sb-size here
133
+
134
+ $my-scrollbar: scrollbar-theme( $sb-thumb-bg-color: blue);`);
135
+ }));
136
+ it('should migrate a theme preceded on the same line by a protocol-relative url()', () => __awaiter(void 0, void 0, void 0, function* () {
137
+ appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `.a { background: url(//cdn.example.com/bg.png); $my: scrollbar-theme($sb-size: 16px, $sb-thumb-bg-color: red); }`);
138
+ const tree = yield schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree);
139
+ expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`.a { background: url(//cdn.example.com/bg.png); $my: scrollbar-theme( $sb-thumb-bg-color: red); }`);
140
+ }));
141
+ it('should not rewrite a mixin or a function declared with the theme name', () => __awaiter(void 0, void 0, void 0, function* () {
142
+ const content = `@mixin scrollbar-theme($sb-size: 16px) {
143
+ width: $sb-size;
144
+ }
145
+
146
+ @function scrollbar-theme($sb-size: 6px) {
147
+ @return ($size: $sb-size);
148
+ }`;
149
+ appTree.create(`/testSrc/appPrefix/component/test.component.scss`, content);
150
+ const tree = yield schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree);
151
+ expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(content);
152
+ }));
80
153
  it('should not touch same-named properties on other themes', () => __awaiter(void 0, void 0, void 0, function* () {
81
154
  const content = `$my-grid: grid-theme(
82
155
  $sb-size: 16px
@@ -85,4 +158,137 @@ describe(`Update to ${version}`, () => {
85
158
  const tree = yield schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree);
86
159
  expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(content);
87
160
  }));
161
+ it('should replace button group multiSelection bound to true with selectionMode multi', () => __awaiter(void 0, void 0, void 0, function* () {
162
+ appTree.create(`/testSrc/appPrefix/component/test.component.html`, `<igx-buttongroup [multiSelection]="true" [values]="buttons"></igx-buttongroup>
163
+ <igx-buttongroup [values]="buttons" [multiSelection]='true'></igx-buttongroup>`);
164
+ const tree = yield schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree);
165
+ expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(`<igx-buttongroup [selectionMode]="'multi'" [values]="buttons"></igx-buttongroup>
166
+ <igx-buttongroup [values]="buttons" [selectionMode]="'multi'"></igx-buttongroup>`);
167
+ }));
168
+ it('should remove button group multiSelection bound to false', () => __awaiter(void 0, void 0, void 0, function* () {
169
+ appTree.create(`/testSrc/appPrefix/component/test.component.html`, `<igx-buttongroup [multiSelection]="false">
170
+ <button igxButton>Button 1</button>
171
+ </igx-buttongroup>
172
+ <igx-buttongroup [values]="buttons"
173
+ [multiSelection]="false"></igx-buttongroup>`);
174
+ const tree = yield schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree);
175
+ expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(`<igx-buttongroup>
176
+ <button igxButton>Button 1</button>
177
+ </igx-buttongroup>
178
+ <igx-buttongroup [values]="buttons"></igx-buttongroup>`);
179
+ }));
180
+ it('should convert button group multiSelection bound to an expression to a selectionMode expression', () => __awaiter(void 0, void 0, void 0, function* () {
181
+ appTree.create(`/testSrc/appPrefix/component/test.component.html`, `<igx-buttongroup [multiSelection]="isMulti" [values]="buttons"></igx-buttongroup>`);
182
+ const tree = yield schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree);
183
+ expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(`<igx-buttongroup [selectionMode]="(isMulti) ? 'multi' : 'single'" [values]="buttons"></igx-buttongroup>`);
184
+ }));
185
+ it('should replace static button group multiSelection attributes', () => __awaiter(void 0, void 0, void 0, function* () {
186
+ appTree.create(`/testSrc/appPrefix/component/test.component.html`, `<igx-buttongroup multiSelection="true" [values]="buttons"></igx-buttongroup>
187
+ <igx-buttongroup multiSelection="false" [values]="buttons"></igx-buttongroup>
188
+ <igx-buttongroup multiSelection [values]="buttons"></igx-buttongroup>`);
189
+ const tree = yield schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree);
190
+ expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(`<igx-buttongroup selectionMode="multi" [values]="buttons"></igx-buttongroup>
191
+ <igx-buttongroup [values]="buttons"></igx-buttongroup>
192
+ <igx-buttongroup [values]="buttons"></igx-buttongroup>`);
193
+ }));
194
+ it('should replace button group multiSelection in inline component templates', () => __awaiter(void 0, void 0, void 0, function* () {
195
+ appTree.create(`/testSrc/appPrefix/component/inline.component.ts`, `import { Component } from '@angular/core';
196
+
197
+ @Component({
198
+ selector: 'app-inline',
199
+ template: \`
200
+ <igx-buttongroup [multiSelection]="true" [values]="buttons"></igx-buttongroup>
201
+ <igx-buttongroup [values]="buttons" multiSelection="false"></igx-buttongroup>
202
+ <igx-buttongroup [multiSelection]="mode === 'multi'"></igx-buttongroup>
203
+ \`
204
+ })
205
+ export class InlineComponent { }
206
+
207
+ @Component({
208
+ selector: 'app-quoted',
209
+ template: '<igx-buttongroup [multiSelection]="true"></igx-buttongroup>'
210
+ })
211
+ export class QuotedComponent { }`);
212
+ const tree = yield schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree);
213
+ expect(tree.readContent('/testSrc/appPrefix/component/inline.component.ts')).toEqual(`import { Component } from '@angular/core';
214
+
215
+ @Component({
216
+ selector: 'app-inline',
217
+ template: \`
218
+ <igx-buttongroup [selectionMode]="'multi'" [values]="buttons"></igx-buttongroup>
219
+ <igx-buttongroup [values]="buttons"></igx-buttongroup>
220
+ <igx-buttongroup [selectionMode]="(mode === 'multi') ? 'multi' : 'single'"></igx-buttongroup>
221
+ \`
222
+ })
223
+ export class InlineComponent { }
224
+
225
+ @Component({
226
+ selector: 'app-quoted',
227
+ template: '<igx-buttongroup [selectionMode]="\\'multi\\'"></igx-buttongroup>'
228
+ })
229
+ export class QuotedComponent { }`);
230
+ }));
231
+ it('should warn about and not modify inline templates with interpolations', () => __awaiter(void 0, void 0, void 0, function* () {
232
+ const content = `import { Component } from '@angular/core';
233
+
234
+ const mode = 'true';
235
+
236
+ @Component({
237
+ selector: 'app-interpolated',
238
+ template: \`<igx-buttongroup [multiSelection]="\${mode}"></igx-buttongroup>\`
239
+ })
240
+ export class InterpolatedComponent { }`;
241
+ appTree.create(`/testSrc/appPrefix/component/interpolated.component.ts`, content);
242
+ const warnings = [];
243
+ const subscription = schematicRunner.logger.subscribe(entry => {
244
+ if (entry.level === 'warn') {
245
+ warnings.push(entry.message);
246
+ }
247
+ });
248
+ const tree = yield schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree);
249
+ subscription.unsubscribe();
250
+ expect(tree.readContent('/testSrc/appPrefix/component/interpolated.component.ts')).toEqual(content);
251
+ expect(warnings).toEqual([
252
+ '/testSrc/appPrefix/component/interpolated.component.ts: replace the removed IgxButtonGroupComponent multiSelection input with selectionMode manually.'
253
+ ]);
254
+ }));
255
+ it('should replace button group multiSelection in templateUrl files not named component.html', () => __awaiter(void 0, void 0, void 0, function* () {
256
+ const component = `import { Component } from '@angular/core';
257
+
258
+ @Component({
259
+ selector: 'app-toolbar',
260
+ templateUrl: './toolbar.html'
261
+ })
262
+ export class ToolbarComponent { }`;
263
+ appTree.create(`/testSrc/appPrefix/component/toolbar.ts`, component);
264
+ appTree.create(`/testSrc/appPrefix/component/toolbar.html`, `<igx-buttongroup [multiSelection]="true" [values]="buttons"></igx-buttongroup>`);
265
+ const tree = yield schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree);
266
+ expect(tree.readContent('/testSrc/appPrefix/component/toolbar.html')).toEqual(`<igx-buttongroup [selectionMode]="'multi'" [values]="buttons"></igx-buttongroup>`);
267
+ expect(tree.readContent('/testSrc/appPrefix/component/toolbar.ts')).toEqual(component);
268
+ }));
269
+ it('should migrate a component.html template referenced through templateUrl once', () => __awaiter(void 0, void 0, void 0, function* () {
270
+ appTree.create(`/testSrc/appPrefix/component/test.component.ts`, `import { Component } from '@angular/core';
271
+
272
+ @Component({
273
+ selector: 'app-test',
274
+ templateUrl: './test.component.html'
275
+ })
276
+ export class TestComponent { }`);
277
+ appTree.create(`/testSrc/appPrefix/component/test.component.html`, `<igx-buttongroup [values]="buttons" [multiSelection]="false" alignment="vertical"></igx-buttongroup>`);
278
+ const tree = yield schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree);
279
+ expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(`<igx-buttongroup [values]="buttons" alignment="vertical"></igx-buttongroup>`);
280
+ }));
281
+ it('should not modify html files that are not component templates', () => __awaiter(void 0, void 0, void 0, function* () {
282
+ const content = `<igx-buttongroup [multiSelection]="true"></igx-buttongroup>`;
283
+ appTree.create(`/testSrc/appPrefix/component/snippet.html`, content);
284
+ const tree = yield schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree);
285
+ expect(tree.readContent('/testSrc/appPrefix/component/snippet.html')).toEqual(content);
286
+ }));
287
+ it('should not touch multiSelection on elements other than the button group', () => __awaiter(void 0, void 0, void 0, function* () {
288
+ const content = `<igx-buttongroup selectionMode="multi"></igx-buttongroup>
289
+ <my-list [multiSelection]="true"></my-list>`;
290
+ appTree.create(`/testSrc/appPrefix/component/test.component.html`, content);
291
+ const tree = yield schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree);
292
+ expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(content);
293
+ }));
88
294
  });
@@ -58,7 +58,7 @@ The navigation drawer can either sit above content or be pinned alongside it and
58
58
  |:----------|:----:|:------|
59
59
  | `id`| string | Unique identifier of the Grid. ID required to register with provided `IgxNavigationService` allow directives to target the control from other template files. |
60
60
  | `position` | string | Position of the Navigation Drawer. Can be "left"(default) or "right". Only has effect when not pinned.|
61
- | `enableGestures`| boolean | Enables the use of touch gestures to manipulate the drawer - such as swipe/pan from edge to open, swipe toggle and pan drag. |
61
+ | `enableGestures`| boolean | Enables the use of touch gestures to manipulate the drawer - such as swipe/pan from edge to open, swipe toggle and pan drag. Swipes require a recognized horizontal pan; movement that stays below 5 px does not toggle the drawer. |
62
62
  | `isOpen` | boolean | State of the drawer. |
63
63
  | `pin` | boolean | When pinned the drawer is relatively positioned instead of sitting above content. May require additional layout styling. |
64
64
  | `pinThreshold` | number | Minimum device width required for automatic pin to be toggled. Default is 1024, can be set to a falsy value to disable this behavior. |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "igniteui-angular",
3
- "version": "22.2.0-rc.0",
3
+ "version": "22.2.0-rc.2",
4
4
  "description": "Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps",
5
5
  "author": "Infragistics",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -84,8 +84,8 @@
84
84
  "@angular/core": "22",
85
85
  "@angular/animations": "22",
86
86
  "@angular/forms": "22",
87
- "igniteui-webcomponents": "~7.3.0",
88
- "igniteui-grid-lite": "~0.10.0"
87
+ "igniteui-webcomponents": "~7.4.0",
88
+ "igniteui-grid-lite": "~0.11.0"
89
89
  },
90
90
  "peerDependenciesMeta": {
91
91
  "igniteui-webcomponents": {