@koobiq/components 20.3.0 → 20.3.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 (95) hide show
  1. package/accordion/accordion.scss +4 -1
  2. package/accordion/index.d.ts +36 -12
  3. package/alert/index.d.ts +8 -0
  4. package/breadcrumbs/index.d.ts +2 -0
  5. package/button-toggle/button-toggle-tokens.scss +14 -0
  6. package/button-toggle/button-toggle.scss +75 -3
  7. package/core/index.d.ts +33 -1
  8. package/core/styles/common/_select.scss +98 -3
  9. package/core/styles/typography/_typography.scss +8 -0
  10. package/ellipsis-center/index.d.ts +35 -2
  11. package/fesm2022/koobiq-components-accordion.mjs +143 -44
  12. package/fesm2022/koobiq-components-accordion.mjs.map +1 -1
  13. package/fesm2022/koobiq-components-alert.mjs +17 -1
  14. package/fesm2022/koobiq-components-alert.mjs.map +1 -1
  15. package/fesm2022/koobiq-components-autocomplete.mjs +2 -2
  16. package/fesm2022/koobiq-components-autocomplete.mjs.map +1 -1
  17. package/fesm2022/koobiq-components-breadcrumbs.mjs +8 -3
  18. package/fesm2022/koobiq-components-breadcrumbs.mjs.map +1 -1
  19. package/fesm2022/koobiq-components-button-toggle.mjs +2 -2
  20. package/fesm2022/koobiq-components-button-toggle.mjs.map +1 -1
  21. package/fesm2022/koobiq-components-code-block.mjs +10 -5
  22. package/fesm2022/koobiq-components-code-block.mjs.map +1 -1
  23. package/fesm2022/koobiq-components-core.mjs +52 -11
  24. package/fesm2022/koobiq-components-core.mjs.map +1 -1
  25. package/fesm2022/koobiq-components-dropdown.mjs +2 -2
  26. package/fesm2022/koobiq-components-dropdown.mjs.map +1 -1
  27. package/fesm2022/koobiq-components-ellipsis-center.mjs +77 -22
  28. package/fesm2022/koobiq-components-ellipsis-center.mjs.map +1 -1
  29. package/fesm2022/koobiq-components-file-upload.mjs +7 -7
  30. package/fesm2022/koobiq-components-file-upload.mjs.map +1 -1
  31. package/fesm2022/koobiq-components-filter-bar.mjs +76 -41
  32. package/fesm2022/koobiq-components-filter-bar.mjs.map +1 -1
  33. package/fesm2022/koobiq-components-form-field.mjs +13 -7
  34. package/fesm2022/koobiq-components-form-field.mjs.map +1 -1
  35. package/fesm2022/koobiq-components-list.mjs +3 -3
  36. package/fesm2022/koobiq-components-list.mjs.map +1 -1
  37. package/fesm2022/koobiq-components-markdown.mjs +6 -2
  38. package/fesm2022/koobiq-components-markdown.mjs.map +1 -1
  39. package/fesm2022/koobiq-components-modal.mjs +60 -11
  40. package/fesm2022/koobiq-components-modal.mjs.map +1 -1
  41. package/fesm2022/koobiq-components-select.mjs +99 -12
  42. package/fesm2022/koobiq-components-select.mjs.map +1 -1
  43. package/fesm2022/koobiq-components-sidebar.mjs +5 -1
  44. package/fesm2022/koobiq-components-sidebar.mjs.map +1 -1
  45. package/fesm2022/koobiq-components-sidepanel.mjs +25 -6
  46. package/fesm2022/koobiq-components-sidepanel.mjs.map +1 -1
  47. package/fesm2022/koobiq-components-tabs.mjs +10 -6
  48. package/fesm2022/koobiq-components-tabs.mjs.map +1 -1
  49. package/fesm2022/koobiq-components-time-range.mjs +388 -74
  50. package/fesm2022/koobiq-components-time-range.mjs.map +1 -1
  51. package/fesm2022/koobiq-components-timezone.mjs +2 -2
  52. package/fesm2022/koobiq-components-timezone.mjs.map +1 -1
  53. package/fesm2022/koobiq-components-title.mjs +15 -3
  54. package/fesm2022/koobiq-components-title.mjs.map +1 -1
  55. package/fesm2022/koobiq-components-tree-select.mjs +3 -3
  56. package/fesm2022/koobiq-components-tree-select.mjs.map +1 -1
  57. package/fesm2022/koobiq-components-tree.mjs +14 -4
  58. package/fesm2022/koobiq-components-tree.mjs.map +1 -1
  59. package/file-upload/file-upload.scss +11 -0
  60. package/file-upload/index.d.ts +1 -1
  61. package/file-upload/multiple-file-upload.component.scss +15 -3
  62. package/file-upload/single-file-upload.component.scss +10 -2
  63. package/filter-bar/filter-bar-tokens.scss +2 -1
  64. package/filter-bar/index.d.ts +25 -4
  65. package/filter-bar/pipes/base-pipe.scss +13 -6
  66. package/filter-bar/pipes/pipe-input.scss +3 -1
  67. package/form-field/index.d.ts +1 -3
  68. package/link/_link-theme.scss +50 -15
  69. package/markdown/index.d.ts +2 -0
  70. package/modal/index.d.ts +17 -8
  71. package/navbar/_navbar-item_horizontal.scss +5 -0
  72. package/package.json +3 -3
  73. package/prebuilt-themes/dark-theme.css +1 -1
  74. package/prebuilt-themes/light-theme.css +1 -1
  75. package/prebuilt-themes/theme.css +1 -1
  76. package/schematics/migrations/alert-signals/index.js +4 -1
  77. package/schematics/migrations/autocomplete-panel-width-auto/index.js +3 -34
  78. package/schematics/migrations/empty-state-size-attr/index.js +3 -34
  79. package/schematics/migrations/filter-bar-signals/index.js +4 -1
  80. package/schematics/migrations/loader-overlay-size-attr/index.js +3 -34
  81. package/schematics/migrations/v20-upgrade/index.js +4 -1
  82. package/schematics/ng-add/index.js +1 -1
  83. package/schematics/utils/angular-parsing.js +11 -12
  84. package/schematics/utils/package-config.js +5 -4
  85. package/schematics/utils/typescript.js +24 -0
  86. package/select/_select-theme.scss +9 -1
  87. package/select/index.d.ts +12 -2
  88. package/select/select.scss +13 -0
  89. package/sidebar/index.d.ts +1 -0
  90. package/sidepanel/index.d.ts +9 -0
  91. package/tabs/index.d.ts +1 -1
  92. package/time-range/index.d.ts +140 -5
  93. package/time-range/time-range.scss +16 -1
  94. package/title/index.d.ts +10 -2
  95. package/tree/index.d.ts +1 -0
@@ -2,37 +2,15 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var node_path = require('node:path');
6
- var process = require('node:process');
7
- var ts = require('typescript');
8
5
  var utils_angularParsing = require('../../utils/angular-parsing.js');
9
6
  var utils_packageConfig = require('../../utils/package-config.js');
10
7
  var utils_typescript = require('../../utils/typescript.js');
11
- require('path');
8
+ require('typescript');
12
9
  require('../../utils/ast.js');
13
10
  require('@angular-devkit/schematics');
14
11
  require('@schematics/angular/utility');
15
12
  require('../../utils/messages.js');
16
13
 
17
- function _interopNamespaceDefault(e) {
18
- var n = Object.create(null);
19
- if (e) {
20
- Object.keys(e).forEach(function (k) {
21
- if (k !== 'default') {
22
- var d = Object.getOwnPropertyDescriptor(e, k);
23
- Object.defineProperty(n, k, d.get ? d : {
24
- enumerable: true,
25
- get: function () { return e[k]; }
26
- });
27
- }
28
- });
29
- }
30
- n.default = e;
31
- return Object.freeze(n);
32
- }
33
-
34
- var process__namespace = /*#__PURE__*/_interopNamespaceDefault(process);
35
-
36
14
  const migrationData = {
37
15
  elementName: 'kbq-autocomplete',
38
16
  attrs: {
@@ -48,20 +26,11 @@ const migrationData = {
48
26
  function migrate(options) {
49
27
  return async (tree, context) => {
50
28
  const { project } = options;
51
- const { tsPaths, templatePaths, projectDefinition } = await utils_packageConfig.getParsingInfo(project, tree);
52
- const program = ts.createProgram(Array.from(tsPaths, (item) => node_path.resolve(projectDefinition.root, `.${item}`)), {
53
- baseUrl: projectDefinition.root,
54
- rootDir: projectDefinition.root,
55
- _enableTemplateTypeChecker: true, // Required for the template type checker to work.
56
- compileNonExportedClasses: true, // We want to migrate non-exported classes too.
57
- // Avoid checking libraries to speed up the migration.
58
- skipLibCheck: true,
59
- skipDefaultLibCheck: true
60
- });
29
+ const { tsPaths, templatePaths } = await utils_packageConfig.getParsingInfo(project, tree);
61
30
  // Update external html
62
31
  await utils_angularParsing.migrateTemplate(tree, Array.from(templatePaths), context, migrationData);
63
32
  // Update inline html
64
- await utils_angularParsing.migrateTs(tree, program.getSourceFiles().filter((sourceFile) => utils_typescript.canMigrateFile(sourceFile, program)), process__namespace.cwd(), context, migrationData);
33
+ await utils_angularParsing.migrateTs(tree, utils_typescript.readSourceFiles(tree, tsPaths), context, migrationData);
65
34
  context.logger.warn('Warning! Run linter in updated files since line breaks or indents may be broken.');
66
35
  };
67
36
  }
@@ -2,37 +2,15 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var node_path = require('node:path');
6
- var process = require('node:process');
7
- var ts = require('typescript');
8
5
  var utils_angularParsing = require('../../utils/angular-parsing.js');
9
6
  var utils_packageConfig = require('../../utils/package-config.js');
10
7
  var utils_typescript = require('../../utils/typescript.js');
11
- require('path');
8
+ require('typescript');
12
9
  require('../../utils/ast.js');
13
10
  require('@angular-devkit/schematics');
14
11
  require('@schematics/angular/utility');
15
12
  require('../../utils/messages.js');
16
13
 
17
- function _interopNamespaceDefault(e) {
18
- var n = Object.create(null);
19
- if (e) {
20
- Object.keys(e).forEach(function (k) {
21
- if (k !== 'default') {
22
- var d = Object.getOwnPropertyDescriptor(e, k);
23
- Object.defineProperty(n, k, d.get ? d : {
24
- enumerable: true,
25
- get: function () { return e[k]; }
26
- });
27
- }
28
- });
29
- }
30
- n.default = e;
31
- return Object.freeze(n);
32
- }
33
-
34
- var process__namespace = /*#__PURE__*/_interopNamespaceDefault(process);
35
-
36
14
  const migrationData = {
37
15
  elementName: 'kbq-empty-state',
38
16
  attrs: {
@@ -52,20 +30,11 @@ const migrationData = {
52
30
  function migrate(options) {
53
31
  return async (tree, context) => {
54
32
  const { project } = options;
55
- const { tsPaths, templatePaths, projectDefinition } = await utils_packageConfig.getParsingInfo(project, tree);
56
- const program = ts.createProgram(Array.from(tsPaths, (item) => node_path.resolve(projectDefinition.root, `.${item}`)), {
57
- baseUrl: projectDefinition.root,
58
- rootDir: projectDefinition.root,
59
- _enableTemplateTypeChecker: true, // Required for the template type checker to work.
60
- compileNonExportedClasses: true, // We want to migrate non-exported classes too.
61
- // Avoid checking libraries to speed up the migration.
62
- skipLibCheck: true,
63
- skipDefaultLibCheck: true
64
- });
33
+ const { tsPaths, templatePaths } = await utils_packageConfig.getParsingInfo(project, tree);
65
34
  // Update external html
66
35
  await utils_angularParsing.migrateTemplate(tree, Array.from(templatePaths), context, migrationData);
67
36
  // Update inline html
68
- await utils_angularParsing.migrateTs(tree, program.getSourceFiles().filter((sourceFile) => utils_typescript.canMigrateFile(sourceFile, program)), process__namespace.cwd(), context, migrationData);
37
+ await utils_angularParsing.migrateTs(tree, utils_typescript.readSourceFiles(tree, tsPaths), context, migrationData);
69
38
  context.logger.warn('Warning! Run linter in updated files since line breaks or indents maybe be broken.');
70
39
  };
71
40
  }
@@ -262,7 +262,10 @@ function referencesFilterBar(content) {
262
262
  }
263
263
  function filterBarSignals(options) {
264
264
  return async (tree, context) => {
265
- const { project, fix } = options;
265
+ const { project } = options;
266
+ // `ng update` invokes migrations with no options at all, and migrations.json declares no schema, so the
267
+ // schema default never reaches us — applying the fix is the intended behaviour there.
268
+ const fix = options.fix ?? true;
266
269
  const projectDefinition = await utils_packageConfig.setupOptions(project, tree);
267
270
  const root = projectDefinition?.root ?? '';
268
271
  const rootDir = root ? tree.getDir(root) : tree.root;
@@ -2,37 +2,15 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var node_path = require('node:path');
6
- var process = require('node:process');
7
- var ts = require('typescript');
8
5
  var utils_angularParsing = require('../../utils/angular-parsing.js');
9
6
  var utils_packageConfig = require('../../utils/package-config.js');
10
7
  var utils_typescript = require('../../utils/typescript.js');
11
- require('path');
8
+ require('typescript');
12
9
  require('../../utils/ast.js');
13
10
  require('@angular-devkit/schematics');
14
11
  require('@schematics/angular/utility');
15
12
  require('../../utils/messages.js');
16
13
 
17
- function _interopNamespaceDefault(e) {
18
- var n = Object.create(null);
19
- if (e) {
20
- Object.keys(e).forEach(function (k) {
21
- if (k !== 'default') {
22
- var d = Object.getOwnPropertyDescriptor(e, k);
23
- Object.defineProperty(n, k, d.get ? d : {
24
- enumerable: true,
25
- get: function () { return e[k]; }
26
- });
27
- }
28
- });
29
- }
30
- n.default = e;
31
- return Object.freeze(n);
32
- }
33
-
34
- var process__namespace = /*#__PURE__*/_interopNamespaceDefault(process);
35
-
36
14
  const migrationData = {
37
15
  elementName: 'kbq-loader-overlay',
38
16
  attrs: {
@@ -52,20 +30,11 @@ const migrationData = {
52
30
  function migrate(options) {
53
31
  return async (tree, context) => {
54
32
  const { project } = options;
55
- const { tsPaths, templatePaths, projectDefinition } = await utils_packageConfig.getParsingInfo(project, tree);
56
- const program = ts.createProgram(Array.from(tsPaths, (item) => node_path.resolve(projectDefinition.root, `.${item}`)), {
57
- baseUrl: projectDefinition.root,
58
- rootDir: projectDefinition.root,
59
- _enableTemplateTypeChecker: true, // Required for the template type checker to work.
60
- compileNonExportedClasses: true, // We want to migrate non-exported classes too.
61
- // Avoid checking libraries to speed up the migration.
62
- skipLibCheck: true,
63
- skipDefaultLibCheck: true
64
- });
33
+ const { tsPaths, templatePaths } = await utils_packageConfig.getParsingInfo(project, tree);
65
34
  // Update external html
66
35
  await utils_angularParsing.migrateTemplate(tree, Array.from(templatePaths), context, migrationData);
67
36
  // Update inline html
68
- await utils_angularParsing.migrateTs(tree, program.getSourceFiles().filter((sourceFile) => utils_typescript.canMigrateFile(sourceFile, program)), process__namespace.cwd(), context, migrationData);
37
+ await utils_angularParsing.migrateTs(tree, utils_typescript.readSourceFiles(tree, tsPaths), context, migrationData);
69
38
  context.logger.warn('Warning! Run linter in updated files since line breaks or indents maybe be broken.');
70
39
  };
71
40
  }
@@ -158,7 +158,10 @@ function pickReplacements(filePath) {
158
158
  }
159
159
  function v20Upgrade(options) {
160
160
  return async (tree, context) => {
161
- const { project, fix } = options;
161
+ const { project } = options;
162
+ // `ng update` invokes migrations with no options at all, and migrations.json declares no schema, so the
163
+ // schema default never reaches us — applying the fix is the intended behaviour there.
164
+ const fix = options.fix ?? true;
162
165
  const projectDefinition = await utils_packageConfig.setupOptions(project, tree);
163
166
  const root = projectDefinition?.root ?? '';
164
167
  const rootDir = root ? tree.getDir(root) : tree.root;
@@ -27,7 +27,7 @@ function ngAdd(options) {
27
27
  }
28
28
  // Installing dependencies
29
29
  utils_packageConfig.addPackageToPackageJson(tree, '@angular/cdk', "^20.2.14");
30
- utils_packageConfig.addPackageToPackageJson(tree, '@koobiq/angular-luxon-adapter', "^20.3.0");
30
+ utils_packageConfig.addPackageToPackageJson(tree, '@koobiq/angular-luxon-adapter', "^20.3.2");
31
31
  utils_packageConfig.addPackageToPackageJson(tree, '@koobiq/date-formatter', "^3.5.1");
32
32
  utils_packageConfig.addPackageToPackageJson(tree, '@koobiq/date-adapter', "^3.5.1");
33
33
  utils_packageConfig.addPackageToPackageJson(tree, '@koobiq/icons', "^12.2.0");
@@ -1,6 +1,5 @@
1
1
  'use strict';
2
2
 
3
- var path = require('path');
4
3
  var ts = require('typescript');
5
4
  var utils_ast = require('./ast.js');
6
5
  var utils_typescript = require('./typescript.js');
@@ -47,7 +46,7 @@ async function migrateTemplate(tree, filePaths, context, migrationData) {
47
46
  * @param context
48
47
  * @param transform
49
48
  */
50
- async function migrateTsWithTransform(tree, sourceFiles, basePath, context, transform) {
49
+ async function migrateTsWithTransform(tree, sourceFiles, context, transform) {
51
50
  // run and track changed components
52
51
  const analysis = new Map();
53
52
  for (const sourceFile of sourceFiles) {
@@ -56,16 +55,15 @@ async function migrateTsWithTransform(tree, sourceFiles, basePath, context, tran
56
55
  });
57
56
  }
58
57
  // update source file
59
- for (const path$1 of analysis.keys()) {
60
- const file = analysis.get(path$1);
58
+ for (const path of analysis.keys()) {
59
+ const file = analysis.get(path);
61
60
  const ranges = file.getSortedRanges();
62
- const relativePath = path.relative(basePath, path$1);
63
- const content = tree.readText(relativePath);
64
- const update = tree.beginUpdate(relativePath);
61
+ const content = tree.readText(path);
62
+ const update = tree.beginUpdate(path);
65
63
  for (const { start, end } of ranges) {
66
64
  const template = content.slice(start, end);
67
65
  const length = (end ?? content.length) - start;
68
- const { fileContent, changed, errors } = await transform(template, relativePath);
66
+ const { fileContent, changed, errors } = await transform(template, path);
69
67
  if (changed) {
70
68
  update.remove(start, length);
71
69
  update.insertLeft(start, fileContent);
@@ -81,12 +79,11 @@ async function migrateTsWithTransform(tree, sourceFiles, basePath, context, tran
81
79
  * Update typescript file if classes with @Component decorator and `template` property exists
82
80
  * @param tree
83
81
  * @param sourceFiles
84
- * @param basePath
85
82
  * @param context
86
83
  * @param migrationData
87
84
  */
88
- async function migrateTs(tree, sourceFiles, basePath, context, migrationData) {
89
- return migrateTsWithTransform(tree, sourceFiles, basePath, context, (template, fileName) => transformTemplateAttributes(template, fileName, migrationData));
85
+ async function migrateTs(tree, sourceFiles, context, migrationData) {
86
+ return migrateTsWithTransform(tree, sourceFiles, context, (template, fileName) => transformTemplateAttributes(template, fileName, migrationData));
90
87
  }
91
88
  /**
92
89
  * Analyzes the decorators of a given class declaration to find and save
@@ -158,9 +155,11 @@ async function transformTemplateAttributes(template, fileName, migrationData) {
158
155
  : `Element has value "${cleanAttrValue}" with no matching replacement. Check the code and change value on your own.${(fileName && ' File: ' + fileName) || ''}`);
159
156
  continue;
160
157
  }
158
+ // The author's quote is kept: inside a "…" TS literal only single quotes are valid.
159
+ const quote = template[migrationAttr.valueSpan.start.offset - 1] === "'" ? "'" : '"';
161
160
  updatedTemplate =
162
161
  updatedTemplate.slice(0, migrationAttr.keySpan.start.offset - offset) +
163
- `${migrationData.attrs.key.to}="${updatedAttrValue}"` +
162
+ `${migrationData.attrs.key.to}=${quote}${updatedAttrValue}${quote}` +
164
163
  updatedTemplate.slice(migrationAttr.valueSpan.end.offset + 1 - offset, updatedTemplate.length);
165
164
  offset += migrationAttr.name.length - migrationData.attrs.key.to.length;
166
165
  offset += migrationAttr.value.length - updatedAttrValue.length;
@@ -60,10 +60,11 @@ async function getParsingInfo(project, tree) {
60
60
  const tsPaths = new Set();
61
61
  const templatePaths = new Set();
62
62
  const projectDefinition = await setupOptions(project, tree);
63
- if (!projectDefinition) {
64
- throw new schematics.SchematicsException(utils_messages.noProject('no project'));
65
- }
66
- tree.getDir(projectDefinition.root).visit((filePath) => {
63
+ // `ng update` passes no options at all, so without a project the whole workspace is migrated.
64
+ const root = projectDefinition?.root;
65
+ (root ? tree.getDir(root) : tree.root).visit((filePath) => {
66
+ if (filePath.includes('node_modules') || filePath.includes('/dist/'))
67
+ return;
67
68
  if (filePath.endsWith('.ts')) {
68
69
  tsPaths.add(filePath);
69
70
  }
@@ -54,6 +54,29 @@ function collectInlineTemplateRanges(sourceFile) {
54
54
  });
55
55
  return ranges;
56
56
  }
57
+ /**
58
+ * Parses the given tree files into source files.
59
+ *
60
+ * The callers only walk decorators and inline templates, so no program is built: one rooted at paths
61
+ * that live in the tree rather than on disk resolves none of them and returns the default libraries
62
+ * instead — around 490 declaration files per run, and not one project source.
63
+ */
64
+ function readSourceFiles(tree, paths) {
65
+ const sourceFiles = [];
66
+ for (const path of paths) {
67
+ if (path.endsWith('.d.ts'))
68
+ continue;
69
+ // Without the BOM, as readText and the update recorder that later edit the file see it.
70
+ const content = tree
71
+ .read(path)
72
+ ?.toString()
73
+ .replace(/^\uFEFF/, '');
74
+ if (content !== undefined) {
75
+ sourceFiles.push(ts.createSourceFile(path, content, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS));
76
+ }
77
+ }
78
+ return sourceFiles;
79
+ }
57
80
  function canMigrateFile(sourceFile, program) {
58
81
  // We shouldn't migrate .d.ts files, files from an external library or type checking files.
59
82
  return !(sourceFile.fileName.endsWith('.ngtypecheck.ts') ||
@@ -212,4 +235,5 @@ exports.forEachClass = forEachClass;
212
235
  exports.forEachStringLiteral = forEachStringLiteral;
213
236
  exports.getClassWithUpdatedDecorator = getClassWithUpdatedDecorator;
214
237
  exports.parseTemplate = parseTemplate;
238
+ exports.readSourceFiles = readSourceFiles;
215
239
  exports.updateDecoratorProperty = updateDecoratorProperty;
@@ -1,4 +1,5 @@
1
1
  @use '../core/styles/common/popup' as *;
2
+ @use '../core/styles/common/select' as *;
2
3
  @use '../core/styles/theming/theming' as *;
3
4
  @use '../core/styles/common/tokens' as *;
4
5
 
@@ -39,6 +40,8 @@
39
40
  & .kbq-select__footer {
40
41
  border-color: var(--kbq-divider-color, var(--kbq-line-contrast-less));
41
42
  }
43
+
44
+ @include kbq-select-footer-item-theme();
42
45
  }
43
46
 
44
47
  .kbq-select__search-container {
@@ -55,7 +58,12 @@
55
58
  @include kbq-typography-level-to-styles-css-variables(typography, text-normal);
56
59
  }
57
60
 
58
- .kbq-select__panel {
61
+ // The footer's action row is projected as a native `button`, whose user-agent `font` shorthand resets
62
+ // the stylistic sets and the letter spacing the panel puts on every option. Inheriting the individual
63
+ // longhands cannot undo that, so the row takes the level in full, as `.kbq-button` and
64
+ // `.kbq-dropdown-item` do.
65
+ .kbq-select__panel,
66
+ .kbq-select__footer-item {
59
67
  @include kbq-typography-level-to-styles-css-variables(typography, text-normal);
60
68
  }
61
69
  }
package/select/index.d.ts CHANGED
@@ -150,6 +150,7 @@ declare class KbqSelect extends KbqAbstractSelect implements AfterContentInit, O
150
150
  private readonly _changeDetectorRef;
151
151
  private readonly _ngZone;
152
152
  private readonly _renderer;
153
+ private readonly interactivityChecker;
153
154
  defaultErrorStateMatcher: ErrorStateMatcher;
154
155
  elementRef: ElementRef<HTMLElement>;
155
156
  private overlayContainer;
@@ -629,7 +630,7 @@ declare class KbqSelect extends KbqAbstractSelect implements AfterContentInit, O
629
630
  * Sets up the overlay dimensions based on trigger size and configured options.
630
631
  */
631
632
  openPanel(): void;
632
- /** Closes the overlay panel and focuses the host element. */
633
+ /** Closes the overlay panel. */
633
634
  close(): void;
634
635
  /**
635
636
  * Sets the select's value. Part of the ControlValueAccessor interface
@@ -725,6 +726,15 @@ declare class KbqSelect extends KbqAbstractSelect implements AfterContentInit, O
725
726
  * @param $event The mouse event to handle.
726
727
  */
727
728
  handleClick($event: MouseEvent): void;
729
+ /** Whether TAB should stop on a footer control. */
730
+ private isFooterTabStop;
731
+ /**
732
+ * Moves focus to the footer control next to `current` — the first one when focus is still outside the
733
+ * footer — and reports whether it landed. Every element is offered to `InteractivityChecker` rather
734
+ * than matched against a hand-written selector, which would drift from what the browser considers a
735
+ * tab stop.
736
+ */
737
+ private focusNextInFooter;
728
738
  /** @docs-private */
729
739
  setSelectedOptionsByClick(option: KbqOption): void;
730
740
  /** @docs-private */
@@ -865,7 +875,7 @@ declare class KbqSelect extends KbqAbstractSelect implements AfterContentInit, O
865
875
 
866
876
  declare class KbqSelectModule {
867
877
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<KbqSelectModule, never>;
868
- static ɵmod: _angular_core.ɵɵNgModuleDeclaration<KbqSelectModule, never, [typeof i1.OverlayModule, typeof i2.KbqOptionModule, typeof i3.KbqIconModule, typeof i4.KbqTagsModule, typeof i5.KbqToolTipModule, typeof i2.KbqSelectSearch, typeof i2.KbqSelectFooter, typeof i2.KbqSelectMatcher, typeof i2.KbqSelectTrigger, typeof i2.KbqSelectSearchEmptyResult, typeof i6.NgTemplateOutlet, typeof i7.A11yModule, typeof KbqSelect, typeof KbqOptionTooltip, typeof KbqSelectLoading, typeof KbqSelectError, typeof KbqSelectNoOptions, typeof KbqSelectErrorText], [typeof KbqSelect, typeof KbqOptionTooltip, typeof i2.KbqOptionModule, typeof i2.KbqSelectSearch, typeof i2.KbqSelectFooter, typeof i2.KbqSelectMatcher, typeof i2.KbqSelectTrigger, typeof i2.KbqSelectSearchEmptyResult, typeof KbqSelectLoading, typeof i11.KbqFormFieldModule, typeof KbqSelectError, typeof KbqSelectNoOptions, typeof KbqSelectErrorText]>;
878
+ static ɵmod: _angular_core.ɵɵNgModuleDeclaration<KbqSelectModule, never, [typeof i1.OverlayModule, typeof i2.KbqOptionModule, typeof i3.KbqIconModule, typeof i4.KbqTagsModule, typeof i5.KbqToolTipModule, typeof i2.KbqSelectSearch, typeof i2.KbqSelectFooter, typeof i2.KbqSelectFooterItem, typeof i2.KbqSelectMatcher, typeof i2.KbqSelectTrigger, typeof i2.KbqSelectSearchEmptyResult, typeof i6.NgTemplateOutlet, typeof i7.A11yModule, typeof KbqSelect, typeof KbqOptionTooltip, typeof KbqSelectLoading, typeof KbqSelectError, typeof KbqSelectNoOptions, typeof KbqSelectErrorText], [typeof KbqSelect, typeof KbqOptionTooltip, typeof i2.KbqOptionModule, typeof i2.KbqSelectSearch, typeof i2.KbqSelectFooter, typeof i2.KbqSelectFooterItem, typeof i2.KbqSelectMatcher, typeof i2.KbqSelectTrigger, typeof i2.KbqSelectSearchEmptyResult, typeof KbqSelectLoading, typeof i11.KbqFormFieldModule, typeof KbqSelectError, typeof KbqSelectNoOptions, typeof KbqSelectErrorText]>;
869
879
  static ɵinj: _angular_core.ɵɵInjectorDeclaration<KbqSelectModule>;
870
880
  }
871
881
 
@@ -14,6 +14,19 @@
14
14
  & .kbq-select__footer {
15
15
  @extend %kbq-select-footer;
16
16
  }
17
+
18
+ & .kbq-select__footer-item {
19
+ @extend %kbq-select-footer-item;
20
+ }
21
+
22
+ // A menu-style action lines up with the options above it, so the footer drops to the list's own
23
+ // inset and lets the row's padding cover the rest. Kept here rather than in `%kbq-select-footer`,
24
+ // which the dropdown and the autocomplete also extend without ever styling the row itself. No child
25
+ // combinator: the content query behind the row is `descendants: true`, so wrapping it must not
26
+ // silently leave the inset behind.
27
+ & .kbq-select__footer:has(.kbq-select__footer-item) {
28
+ --kbq-select-footer-size-padding-horizontal: var(--kbq-size-xxs);
29
+ }
17
30
  }
18
31
 
19
32
  .kbq-select__content {
@@ -37,6 +37,7 @@ declare class KbqSidebar implements OnDestroy, AfterContentInit {
37
37
  protected readonly document: Document;
38
38
  private readonly renderer;
39
39
  private readonly changeDetectorRef;
40
+ private readonly destroyRef;
40
41
  private readonly isBrowser;
41
42
  get opened(): boolean;
42
43
  set opened(value: boolean);
@@ -155,6 +155,7 @@ declare class KbqSidepanelClose implements OnInit, OnChanges {
155
155
  sidepanelRef: KbqSidepanelRef<any, any>;
156
156
  private elementRef;
157
157
  private sidepanelService;
158
+ private readonly renderer;
158
159
  sidepanelResult: any;
159
160
  readonly kbqSidepanelClose: i0.InputSignal<any>;
160
161
  ngOnInit(): void;
@@ -250,6 +251,14 @@ declare class KbqSidepanelService implements OnDestroy {
250
251
  private closeSidepanels;
251
252
  private getOpenedSidepanelsWithSamePosition;
252
253
  private updateAnimationState;
254
+ /**
255
+ * Moves a sidepanel into `state`, unless it is closing already.
256
+ *
257
+ * The exit animation is what disposes the overlay, so interrupting it with another state leaves the
258
+ * sidepanel in the DOM and in `openedSidepanels` for good — which is what closing a stack of them as
259
+ * a group used to do to the panels underneath.
260
+ */
261
+ private setAnimationState;
253
262
  /**
254
263
  * Removes a sidepanel from the array of open sidepanels.
255
264
  * @param sidepanelRef Sidepanel to be removed.
package/tabs/index.d.ts CHANGED
@@ -37,6 +37,7 @@ type KbqTabBodyOriginState = 'left' | 'right';
37
37
  declare class KbqTabBody implements OnInit, OnDestroy {
38
38
  private readonly elementRef;
39
39
  private readonly dir;
40
+ private readonly destroyRef;
40
41
  /** The shifted index position of the tab body, where zero represents the active center tab. */
41
42
  set position(position: number);
42
43
  /** Tab body position state. Used by the animation trigger for the current state. */
@@ -94,7 +95,6 @@ declare class KbqTabBodyPortal extends CdkPortalOutlet implements OnInit, OnDest
94
95
  private centeringSub;
95
96
  /** Subscription to events for when the tab body finishes leaving from center position. */
96
97
  private leavingSub;
97
- constructor();
98
98
  /** Set initial visibility or set up subscription for changing visibility. */
99
99
  ngOnInit(): void;
100
100
  /** Clean up centering subscription. */