@koobiq/components 21.0.1 → 21.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) hide show
  1. package/badge/_badge-theme.scss +31 -0
  2. package/breadcrumbs/breadcrumbs.scss +5 -1
  3. package/checkbox/_checkbox-theme.scss +0 -17
  4. package/checkbox/checkbox-tokens.scss +0 -4
  5. package/code-block/_code-block-theme.scss +7 -6
  6. package/code-block/code-block-tokens.scss +8 -4
  7. package/code-block/code-block.scss +54 -32
  8. package/content-panel/content-panel-header.scss +2 -3
  9. package/content-panel/content-panel.scss +3 -0
  10. package/core/selection/pseudo-checkbox/pseudo-checkbox-tokens.scss +0 -2
  11. package/fesm2022/koobiq-components-accordion.mjs +4 -4
  12. package/fesm2022/koobiq-components-accordion.mjs.map +1 -1
  13. package/fesm2022/koobiq-components-actions-panel.mjs +10 -2
  14. package/fesm2022/koobiq-components-actions-panel.mjs.map +1 -1
  15. package/fesm2022/koobiq-components-app-switcher.mjs +1 -1
  16. package/fesm2022/koobiq-components-app-switcher.mjs.map +1 -1
  17. package/fesm2022/koobiq-components-badge.mjs +2 -2
  18. package/fesm2022/koobiq-components-badge.mjs.map +1 -1
  19. package/fesm2022/koobiq-components-breadcrumbs.mjs +2 -2
  20. package/fesm2022/koobiq-components-breadcrumbs.mjs.map +1 -1
  21. package/fesm2022/koobiq-components-button-toggle.mjs +1 -1
  22. package/fesm2022/koobiq-components-button-toggle.mjs.map +1 -1
  23. package/fesm2022/koobiq-components-checkbox.mjs +18 -8
  24. package/fesm2022/koobiq-components-checkbox.mjs.map +1 -1
  25. package/fesm2022/koobiq-components-clamped-text.mjs +78 -10
  26. package/fesm2022/koobiq-components-clamped-text.mjs.map +1 -1
  27. package/fesm2022/koobiq-components-code-block.mjs +63 -379
  28. package/fesm2022/koobiq-components-code-block.mjs.map +1 -1
  29. package/fesm2022/koobiq-components-content-panel.mjs +4 -4
  30. package/fesm2022/koobiq-components-content-panel.mjs.map +1 -1
  31. package/fesm2022/koobiq-components-core.mjs +300 -37
  32. package/fesm2022/koobiq-components-core.mjs.map +1 -1
  33. package/fesm2022/koobiq-components-datepicker.mjs +151 -60
  34. package/fesm2022/koobiq-components-datepicker.mjs.map +1 -1
  35. package/fesm2022/koobiq-components-divider.mjs +3 -3
  36. package/fesm2022/koobiq-components-divider.mjs.map +1 -1
  37. package/fesm2022/koobiq-components-dropdown.mjs +3 -3
  38. package/fesm2022/koobiq-components-dropdown.mjs.map +1 -1
  39. package/fesm2022/koobiq-components-file-upload.mjs +17 -8
  40. package/fesm2022/koobiq-components-file-upload.mjs.map +1 -1
  41. package/fesm2022/koobiq-components-filter-bar.mjs +115 -36
  42. package/fesm2022/koobiq-components-filter-bar.mjs.map +1 -1
  43. package/fesm2022/koobiq-components-flag.mjs +3 -3
  44. package/fesm2022/koobiq-components-flag.mjs.map +1 -1
  45. package/fesm2022/koobiq-components-form-field.mjs +90 -27
  46. package/fesm2022/koobiq-components-form-field.mjs.map +1 -1
  47. package/fesm2022/koobiq-components-icon.mjs +2 -2
  48. package/fesm2022/koobiq-components-icon.mjs.map +1 -1
  49. package/fesm2022/koobiq-components-inline-edit.mjs +19 -2
  50. package/fesm2022/koobiq-components-inline-edit.mjs.map +1 -1
  51. package/fesm2022/koobiq-components-input.mjs +76 -17
  52. package/fesm2022/koobiq-components-input.mjs.map +1 -1
  53. package/fesm2022/koobiq-components-list.mjs +1 -1
  54. package/fesm2022/koobiq-components-list.mjs.map +1 -1
  55. package/fesm2022/koobiq-components-modal.mjs +3 -3
  56. package/fesm2022/koobiq-components-modal.mjs.map +1 -1
  57. package/fesm2022/koobiq-components-navbar.mjs +86 -25
  58. package/fesm2022/koobiq-components-navbar.mjs.map +1 -1
  59. package/fesm2022/koobiq-components-notification-center.mjs +4 -4
  60. package/fesm2022/koobiq-components-notification-center.mjs.map +1 -1
  61. package/fesm2022/koobiq-components-overflow-items.mjs +116 -38
  62. package/fesm2022/koobiq-components-overflow-items.mjs.map +1 -1
  63. package/fesm2022/koobiq-components-popover.mjs +86 -7
  64. package/fesm2022/koobiq-components-popover.mjs.map +1 -1
  65. package/fesm2022/koobiq-components-radio.mjs +41 -19
  66. package/fesm2022/koobiq-components-radio.mjs.map +1 -1
  67. package/fesm2022/koobiq-components-search-expandable.mjs +29 -17
  68. package/fesm2022/koobiq-components-search-expandable.mjs.map +1 -1
  69. package/fesm2022/koobiq-components-select.mjs +49 -12
  70. package/fesm2022/koobiq-components-select.mjs.map +1 -1
  71. package/fesm2022/koobiq-components-sidepanel.mjs +198 -186
  72. package/fesm2022/koobiq-components-sidepanel.mjs.map +1 -1
  73. package/fesm2022/koobiq-components-splitter.mjs +49 -25
  74. package/fesm2022/koobiq-components-splitter.mjs.map +1 -1
  75. package/fesm2022/koobiq-components-tabs.mjs +30 -11
  76. package/fesm2022/koobiq-components-tabs.mjs.map +1 -1
  77. package/fesm2022/koobiq-components-tags.mjs +1 -1
  78. package/fesm2022/koobiq-components-tags.mjs.map +1 -1
  79. package/fesm2022/koobiq-components-textarea.mjs +28 -11
  80. package/fesm2022/koobiq-components-textarea.mjs.map +1 -1
  81. package/fesm2022/koobiq-components-time-range.mjs +2 -2
  82. package/fesm2022/koobiq-components-time-range.mjs.map +1 -1
  83. package/fesm2022/koobiq-components-timepicker.mjs +71 -16
  84. package/fesm2022/koobiq-components-timepicker.mjs.map +1 -1
  85. package/fesm2022/koobiq-components-timezone.mjs +2 -2
  86. package/fesm2022/koobiq-components-timezone.mjs.map +1 -1
  87. package/fesm2022/koobiq-components-toast.mjs +2 -2
  88. package/fesm2022/koobiq-components-toast.mjs.map +1 -1
  89. package/fesm2022/koobiq-components-toggle.mjs +25 -9
  90. package/fesm2022/koobiq-components-toggle.mjs.map +1 -1
  91. package/fesm2022/koobiq-components-tooltip.mjs +90 -17
  92. package/fesm2022/koobiq-components-tooltip.mjs.map +1 -1
  93. package/fesm2022/koobiq-components-top-bar.mjs +27 -7
  94. package/fesm2022/koobiq-components-top-bar.mjs.map +1 -1
  95. package/fesm2022/koobiq-components-tree-select.mjs +4 -4
  96. package/fesm2022/koobiq-components-tree-select.mjs.map +1 -1
  97. package/fesm2022/koobiq-components-tree.mjs +71 -27
  98. package/fesm2022/koobiq-components-tree.mjs.map +1 -1
  99. package/file-upload/_file-upload-theme.scss +0 -12
  100. package/file-upload/file-upload-tokens.scss +0 -1
  101. package/file-upload/file-upload.scss +0 -1
  102. package/filter-bar/_filter-bar-theme.scss +7 -8
  103. package/filter-bar/filter-bar.scss +0 -1
  104. package/filter-bar/pipes/base-pipe.scss +36 -2
  105. package/filter-bar/pipes/pipe-multi-tree-select.scss +27 -0
  106. package/form-field/_fieldset-theme.scss +2 -7
  107. package/form-field/_form-field-theme.scss +9 -22
  108. package/form-field/_hint-theme.scss +20 -0
  109. package/form-field/fieldset-tokens.scss +0 -1
  110. package/form-field/fieldset.scss +0 -3
  111. package/form-field/form-field-tokens.scss +1 -1
  112. package/form-field/form-field.scss +9 -0
  113. package/form-field/hint-tokens.scss +3 -0
  114. package/modal/modal.scss +2 -0
  115. package/navbar/_navbar-item_vertical.scss +48 -2
  116. package/navbar/_navbar-theme.scss +11 -3
  117. package/navbar/navbar-item.scss +17 -0
  118. package/navbar/navbar-tokens.scss +3 -0
  119. package/package.json +4 -4
  120. package/popover/popover.scss +1 -1
  121. package/radio/_radio-theme.scss +0 -30
  122. package/radio/radio-tokens.scss +0 -2
  123. package/schematics/migrations/deprecated-icons/README.md +21 -5
  124. package/schematics/migrations/deprecated-icons/index.cjs +8 -22
  125. package/schematics/migrations/deprecated-icons/schema.json +1 -1
  126. package/schematics/migrations/icons-replacement/README.md +16 -2
  127. package/schematics/migrations/icons-replacement/index.cjs +18 -16
  128. package/schematics/migrations/icons-replacement/schema.json +12 -3
  129. package/schematics/migrations/new-icons-pack/README.md +37 -25
  130. package/schematics/migrations/new-icons-pack/index.cjs +22 -32
  131. package/schematics/migrations/new-icons-pack/replacement.json +2 -14
  132. package/schematics/migrations/new-icons-pack/schema.json +3 -3
  133. package/schematics/ng-add/index.cjs +4 -4
  134. package/schematics/utils/custom-data.cjs +64 -0
  135. package/schematics/utils/icon-migration.cjs +9 -3
  136. package/schematics/utils/messages.cjs +4 -0
  137. package/schematics/utils/package-config.cjs +19 -0
  138. package/select/select.scss +7 -0
  139. package/tabs/_tabs-common.scss +23 -0
  140. package/textarea/textarea-tokens.scss +4 -1
  141. package/toast/toast.component.scss +1 -0
  142. package/toggle/_toggle-theme.scss +0 -17
  143. package/tooltip/tooltip.scss +1 -1
  144. package/top-bar/top-bar-tokens.scss +1 -0
  145. package/top-bar/top-bar.scss +10 -0
  146. package/types/koobiq-components-accordion.d.ts +25 -0
  147. package/types/koobiq-components-button-toggle.d.ts +6 -0
  148. package/types/koobiq-components-checkbox.d.ts +30 -0
  149. package/types/koobiq-components-clamped-text.d.ts +16 -3
  150. package/types/koobiq-components-code-block.d.ts +17 -3
  151. package/types/koobiq-components-core.d.ts +226 -13
  152. package/types/koobiq-components-datepicker.d.ts +28 -1
  153. package/types/koobiq-components-divider.d.ts +28 -10
  154. package/types/koobiq-components-dropdown.d.ts +19 -0
  155. package/types/koobiq-components-filter-bar.d.ts +77 -4
  156. package/types/koobiq-components-flag.d.ts +18 -0
  157. package/types/koobiq-components-form-field.d.ts +87 -6
  158. package/types/koobiq-components-icon.d.ts +15 -0
  159. package/types/koobiq-components-inline-edit.d.ts +8 -1
  160. package/types/koobiq-components-input.d.ts +22 -3
  161. package/types/koobiq-components-list.d.ts +6 -0
  162. package/types/koobiq-components-modal.d.ts +7 -0
  163. package/types/koobiq-components-navbar.d.ts +71 -7
  164. package/types/koobiq-components-notification-center.d.ts +13 -0
  165. package/types/koobiq-components-overflow-items.d.ts +26 -2
  166. package/types/koobiq-components-popover.d.ts +38 -3
  167. package/types/koobiq-components-radio.d.ts +30 -0
  168. package/types/koobiq-components-search-expandable.d.ts +10 -0
  169. package/types/koobiq-components-select.d.ts +36 -4
  170. package/types/koobiq-components-sidepanel.d.ts +52 -1
  171. package/types/koobiq-components-splitter.d.ts +13 -4
  172. package/types/koobiq-components-tabs.d.ts +4 -0
  173. package/types/koobiq-components-tags.d.ts +6 -0
  174. package/types/koobiq-components-textarea.d.ts +9 -2
  175. package/types/koobiq-components-timepicker.d.ts +15 -0
  176. package/types/koobiq-components-toggle.d.ts +30 -0
  177. package/types/koobiq-components-tooltip.d.ts +55 -10
  178. package/types/koobiq-components-top-bar.d.ts +11 -3
  179. package/types/koobiq-components-tree-select.d.ts +12 -0
  180. package/types/koobiq-components-tree.d.ts +37 -2
@@ -7,13 +7,13 @@ var utils_angularParsing = require('../../utils/angular-parsing.cjs');
7
7
  var utils_iconMigration = require('../../utils/icon-migration.cjs');
8
8
  var utils_messages = require('../../utils/messages.cjs');
9
9
  var utils_packageConfig = require('../../utils/package-config.cjs');
10
+ var utils_projectFiles = require('../../utils/project-files.cjs');
10
11
  var migrations_deprecatedIcons_data = require('./data.cjs');
11
12
  require('typescript');
12
13
  require('../../utils/ast.cjs');
13
14
  require('../../utils/typescript.cjs');
14
15
  require('@angular-devkit/schematics');
15
16
  require('@schematics/angular/utility');
16
- require('../../utils/project-files.cjs');
17
17
 
18
18
  function _interopNamespaceDefault(e) {
19
19
  var n = Object.create(null);
@@ -38,30 +38,20 @@ const iconsFontImportRule = "@use '@koobiq/icons/fonts/kbq-icons';";
38
38
  const migrationData = {
39
39
  valueAttrs: ['kbq-icon', 'kbq-icon-item', 'kbq-icon-button'],
40
40
  scope: migrations_deprecatedIcons_data.scope,
41
- scopeClassInList: 'remove',
41
+ scopeClassInList: 'rename',
42
+ scopeClassOnIconHost: 'remove',
42
43
  icons: migrations_deprecatedIcons_data.iconsMapping.map(({ replace, replaceWith }) => ({ from: replace, to: replaceWith })),
43
44
  rescopeUnknownValues: true
44
45
  };
45
46
  function deprecatedIcons(options) {
46
- let targetDir;
47
47
  return async (tree, context) => {
48
48
  const { project, fix, stylesExt } = options;
49
- try {
50
- const projectDefinition = await utils_packageConfig.setupOptions(project, tree);
51
- targetDir = projectDefinition ? tree.getDir(projectDefinition.root) : tree;
52
- }
53
- catch {
54
- targetDir = tree;
55
- }
49
+ const targetDir = await utils_packageConfig.resolveTargetDir(project, tree);
56
50
  const { logger } = context;
57
51
  const tokenMap = utils_iconMigration.buildIconTokenMap(migrationData);
58
- // Unlike a `class` list (where the bare scope token is simply dropped, e.g.
59
- // `class="pt-icons"` -> `class=""`), a stylesheet selector renames the scope class itself
60
- // (e.g. `.pt-icons` -> `.kbq`) rather than removing it.
61
- const styleTokenMap = new Map(tokenMap).set(migrationData.scope.from, migrationData.scope.to);
62
52
  // Precompiled once and reused across every .ts/style file below, instead of rebuilding
63
53
  // every regex per file.
64
- const stylePatterns = utils_iconMigration.buildIconTokenPatterns(styleTokenMap, migrationData.scope.from);
54
+ const stylePatterns = utils_iconMigration.buildIconTokenPatterns(tokenMap, migrationData.scope.from);
65
55
  const onFound = (filePath, found) => {
66
56
  const parsedFilePath = path__namespace.relative(__dirname, `.${filePath}`).replace(/\\/g, '/');
67
57
  utils_messages.logMessage(logger, [
@@ -74,11 +64,7 @@ function deprecatedIcons(options) {
74
64
  const templatePaths = [];
75
65
  const tsPaths = [];
76
66
  const stylePaths = [];
77
- // if project property not provided, skip files in node_modules & dist
78
- targetDir.visit((filePath) => {
79
- if (filePath.includes('node_modules') || filePath.includes('/dist/')) {
80
- return;
81
- }
67
+ utils_projectFiles.visitProjectFiles(targetDir, (filePath) => {
82
68
  if (filePath.endsWith('.html')) {
83
69
  templatePaths.push(filePath);
84
70
  }
@@ -110,8 +96,8 @@ function deprecatedIcons(options) {
110
96
  }
111
97
  }
112
98
  // check if icon styles from new scope should be included in styles file
113
- targetDir.visit((filePath, entry) => {
114
- if (filePath.endsWith(stylesExt) && !entry?.content.toString()?.includes(iconsFontImportRule)) {
99
+ utils_projectFiles.visitProjectFiles(targetDir, (filePath, entry) => {
100
+ if (filePath.endsWith(stylesExt) && !entry.content.toString()?.includes(iconsFontImportRule)) {
115
101
  const parsedFilePath = path__namespace.relative(__dirname, `.${filePath}`).replace(/\\/g, '/');
116
102
  utils_messages.logMessage(logger, [
117
103
  parsedFilePath,
@@ -6,7 +6,7 @@
6
6
  "properties": {
7
7
  "project": {
8
8
  "type": "string",
9
- "description": "Name of the project",
9
+ "description": "Name of the project, or a folder to migrate (e.g. ./libs). Without it the whole workspace is migrated",
10
10
  "$default": {
11
11
  "$source": "projectName"
12
12
  }
@@ -6,6 +6,20 @@ This schematic provides migration for new icons naming attribute. It includes:
6
6
 
7
7
  [Params](schema.ts)
8
8
 
9
+ `--project` takes a project name or a folder such as `./libs`; without it the whole workspace is migrated.
10
+ `node_modules` and `dist` are always skipped.
11
+
12
+ The built-in mapping applies unless `--custom-data-path` points at a JSON file of your own, resolved from the
13
+ workspace root (then as an absolute path); a missing file stops the run. The shape is the one `new-icons-pack`
14
+ reads; a name matches anywhere it occurs, so it can be written with or without the `kbq-` prefix:
15
+
16
+ ```json
17
+ [{ "replace": "bolt-circle_16", "replaceWith": "circle-bolt_16" }]
18
+ ```
19
+
20
+ `--replacement-data-path` is the deprecated name of the option: it still works, resolved from the project root
21
+ or the folder first, and so do files of `{ "from", "to" }` pairs; both print a warning.
22
+
9
23
  #### Usage for Angular Cli:
10
24
 
11
25
  Apply for project and log file path and icon name should be replaced
@@ -17,7 +31,7 @@ ng g @koobiq/components:icons-replacement --project "<your project>"
17
31
  - with custom icon replacement mapping:
18
32
 
19
33
  ```shell
20
- ng g @koobiq/components:icons-replacement --project "<your project>" --replacement-data-path "<path-as-json>"
34
+ ng g @koobiq/components:icons-replacement --project "<your project>" --custom-data-path "<path-as-json>"
21
35
  ```
22
36
 
23
37
  Apply for project and replace icon name.
@@ -35,7 +49,7 @@ nx g @koobiq/components:icons-replacement --project "<your project>"
35
49
  - with custom icon replacement mapping:
36
50
 
37
51
  ```shell
38
- nx g @koobiq/components:icons-replacement --project "<your project>" --replacement-data-path "<path-as-json>"
52
+ nx g @koobiq/components:icons-replacement --project "<your project>" --custom-data-path "<path-as-json>"
39
53
  ```
40
54
 
41
55
  ### Run locally
@@ -3,12 +3,14 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var path = require('path');
6
+ var utils_customData = require('../../utils/custom-data.cjs');
6
7
  var utils_messages = require('../../utils/messages.cjs');
7
8
  var utils_packageConfig = require('../../utils/package-config.cjs');
9
+ var utils_projectFiles = require('../../utils/project-files.cjs');
8
10
  var migrations_iconsReplacement_data = require('./data.cjs');
9
11
  require('@angular-devkit/schematics');
12
+ require('fs');
10
13
  require('@schematics/angular/utility');
11
- require('../../utils/project-files.cjs');
12
14
 
13
15
  const replaceIcons = (contentToBeUpdated, replacementData) => {
14
16
  let res = contentToBeUpdated;
@@ -43,24 +45,25 @@ const processIconReplacement = ({ fileContent, filePath, fix, logger, replacemen
43
45
  return { fileContent, changed: false, errors: [] };
44
46
  }
45
47
  };
46
- const resolveReplacementData = (projectRootPath, tree, customReplacementDataPath) => {
47
- if (customReplacementDataPath) {
48
- const replacementData = tree.get(`${projectRootPath}/${customReplacementDataPath}`);
49
- if (!replacementData)
50
- return migrations_iconsReplacement_data.iconReplacementData;
51
- return JSON.parse(replacementData.content.toString());
52
- }
53
- return migrations_iconsReplacement_data.iconReplacementData;
54
- };
55
48
  function migrate(options) {
56
49
  return async (tree, context) => {
57
50
  const { logger } = context;
58
- const { project, allowed, fix, replacementDataPath } = options;
59
- const projectDefinition = await utils_packageConfig.setupOptions(project, tree);
60
- const replacementData = resolveReplacementData(projectDefinition.root, tree, replacementDataPath);
61
- tree.getDir(projectDefinition.root).visit((filePath, entry) => {
51
+ const { project, allowed, fix, customDataPath, replacementDataPath } = options;
52
+ const targetDir = await utils_packageConfig.resolveTargetDir(project, tree);
53
+ if (replacementDataPath && customDataPath) {
54
+ logger.warn('--replacement-data-path is deprecated and ignored next to --custom-data-path.');
55
+ }
56
+ const dataPath = customDataPath ?? replacementDataPath;
57
+ const bases = customDataPath ? undefined : [targetDir.path, '/'];
58
+ const replacementData = dataPath
59
+ ? utils_customData.readCustomIconMapping(tree, dataPath, logger, bases)
60
+ : migrations_iconsReplacement_data.iconReplacementData;
61
+ logger.info(dataPath
62
+ ? `Icon mapping: ${replacementData.length} entries from '${dataPath}'.`
63
+ : `Icon mapping: the built-in one, ${replacementData.length} entries (--custom-data-path overrides it).`);
64
+ utils_projectFiles.visitProjectFiles(targetDir, (filePath, entry) => {
62
65
  if (allowed.length === 0 || allowed.some((ext) => filePath.endsWith(ext))) {
63
- const initialContent = entry?.content.toString();
66
+ const initialContent = entry.content.toString();
64
67
  if (!initialContent)
65
68
  return;
66
69
  const { fileContent, changed } = processIconReplacement({
@@ -82,4 +85,3 @@ exports.default = migrate;
82
85
  exports.logReplacement = logReplacement;
83
86
  exports.processIconReplacement = processIconReplacement;
84
87
  exports.replaceIcons = replaceIcons;
85
- exports.resolveReplacementData = resolveReplacementData;
@@ -6,7 +6,7 @@
6
6
  "properties": {
7
7
  "project": {
8
8
  "type": "string",
9
- "description": "Name of the project",
9
+ "description": "Name of the project, or a folder to migrate (e.g. ./libs). Without it the whole workspace is migrated",
10
10
  "$default": {
11
11
  "$source": "projectName"
12
12
  }
@@ -18,15 +18,24 @@
18
18
  },
19
19
  "allowed": {
20
20
  "type": "array",
21
- "default": [".html", ".ts", ".scss"],
21
+ "default": [
22
+ ".html",
23
+ ".ts",
24
+ ".scss"
25
+ ],
22
26
  "items": {
23
27
  "type": "string"
24
28
  },
25
29
  "description": "Allowed file extensions to check"
26
30
  },
31
+ "customDataPath": {
32
+ "type": "string",
33
+ "description": "JSON file with an icon mapping that replaces the built-in one, an array of { \"replace\": \"<old>\", \"replaceWith\": \"<new>\" }, resolved from the workspace root"
34
+ },
27
35
  "replacementDataPath": {
28
36
  "type": "string",
29
- "description": "Custom replacement data path. Will be used as relative to `project.root`"
37
+ "description": "Deprecated, use customDataPath. Resolved from the project root or the folder first",
38
+ "x-deprecated": "Use --custom-data-path, resolved from the workspace root."
30
39
  }
31
40
  }
32
41
  }
@@ -3,7 +3,9 @@
3
3
  This schematic provides migration for update icons pack. It includes:
4
4
 
5
5
  - Change prefixes from `mc` to `kbq` for TS, HTML, and styles
6
- - Update icon names for updated/removed icons according to [mapping](data.ts)
6
+ - Update icon names for updated/removed icons according to [mapping](data.ts), in the values of `kbq-icon`,
7
+ `kbq-icon-item`, `kbq-icon-button` and of their `mc-*` counterparts (`mc-icon="mc-search_16"` →
8
+ `mc-icon="kbq-magnifying-glass_16"`; the attribute names themselves are left alone)
7
9
  - Fix icons package prefix in styles
8
10
  - Optionally use custom migration and replacement data
9
11
 
@@ -27,16 +29,32 @@ and can still be rewritten.
27
29
  regardless of `updatePrefix`; the option only gates the _bare_ scope-word rename (`mc` → `kbq`) there. In
28
30
  templates/TS, icon-attribute values are always matched regardless of `updatePrefix`.
29
31
 
30
- #### `--custom-icon-replacement-path`
32
+ #### Data
31
33
 
32
- The expected file shape changed. It's still a JSON array of `{ "replace": ..., "replaceWith": ... }` objects,
33
- but each entry is now interpreted as a bare scope-word pair (e.g. `{ "replace": "mc", "replaceWith": "kbq" }`,
34
- with no leading/trailing hyphen) rather than a whole-file regex fragment like `kbq-icon="mc-` — the AST-based
35
- matcher no longer needs per-context fragments. A file still written in the old fragment style, or a malformed
36
- one, is detected and ignored with a warning (falling back to the default `mc` → `kbq` scope) rather than being
37
- silently misapplied or crashing. [`replacement.json`](replacement.json) is kept in its old fragment shape for
38
- backward compatibility with anyone already pointing at it — **don't** pass it via `--custom-icon-replacement-path`
39
- as-is (see the fallback warning above); copy it into your own file and rewrite it in the new shape instead.
34
+ Everything the migration needs is built in: the icon-name mapping ([`data.ts`](data.ts)) and the `mc` → `kbq`
35
+ scope. Run it without the custom-data options — the log says which data it runs on. The options are for a
36
+ mapping or a scope of your own, not for passing the shipped files back in.
37
+
38
+ `--custom-data-path` takes the icon-name mapping, an array of `replace`/`replaceWith` pairs written with the
39
+ `kbq-` prefix (the `mc-` form of each name is matched as well):
40
+
41
+ ```json
42
+ [{ "replace": "kbq-add-to-list_16", "replaceWith": "kbq-file-plus-o_16" }]
43
+ ```
44
+
45
+ The same option and shape are read by `icons-replacement`. A file of `{ "from", "to" }` pairs, the shape
46
+ `icons-replacement` used to read, is still accepted with a warning.
47
+
48
+ `--custom-icon-replacement-path` takes the scope pair, bare words with no hyphen:
49
+
50
+ ```json
51
+ [{ "replace": "mc", "replaceWith": "kbq" }]
52
+ ```
53
+
54
+ [`migration.json`](migration.json) and [`replacement.json`](replacement.json) hold the built-in data in these
55
+ shapes, so they can be copied as a starting point. A path is resolved from the workspace root first, then as an
56
+ absolute path or one relative to the current directory; a missing file stops the run. A scope file still
57
+ written in the old fragment shape (`kbq-icon="mc-`) is ignored with a warning, and the built-in scope applies.
40
58
 
41
59
  ---
42
60
 
@@ -48,20 +66,17 @@ The schematic supports the following options:
48
66
  Applies fixes automatically without prompting.
49
67
 
50
68
  - **`--project`** (`string`)
51
- Target Angular/Nx project name.
69
+ Target Angular/Nx project name, or a folder such as `./libs`. Without it the whole workspace is migrated;
70
+ `node_modules` and `dist` are always skipped.
52
71
 
53
72
  - **`--update-prefix`** (`boolean`)
54
73
  Whether to change icon prefixes during migration.
55
74
 
56
75
  - **`--custom-data-path`** (`string`)
57
- Path to a custom migration data file.
58
- When provided, use `migration.json` file as a default.
59
- Use this option if you want to override the default icon mapping data.
76
+ JSON file with an icon-name mapping that replaces the built-in one (see [Data](#data)).
60
77
 
61
78
  - **`--custom-icon-replacement-path`** (`string`)
62
- Path to a custom icon attributes replacement file.
63
- When provided, use `replacement.json` file as a default.
64
- Use this option to customize how icon attributes are replaced during migration.
79
+ JSON file with a scope pair that replaces the built-in `mc` → `kbq` (see [Data](#data)).
65
80
 
66
81
  The schema definition can be found in [`schema.ts`](schema.ts).
67
82
 
@@ -71,22 +86,19 @@ The schema definition can be found in [`schema.ts`](schema.ts).
71
86
 
72
87
  ```shell
73
88
  ng g @koobiq/components:new-icons-pack --fix=true --project "<your project>"
89
+ ng g @koobiq/components:new-icons-pack --fix=true --project ./libs
74
90
  ```
75
91
 
76
92
  #### Angular CLI with custom data
77
93
 
78
94
  ```shell
79
95
  ng g @koobiq/components:new-icons-pack \
80
- --custom-data-path migration.json \
81
- --custom-icon-replacement-path my-replacement.json \
96
+ --custom-data-path my-icons.json \
97
+ --custom-icon-replacement-path my-scope.json \
82
98
  --fix=true \
83
99
  --project "<your-project>"
84
100
  ```
85
101
 
86
- `migration.json` is the shipped icon-name mapping and can be used as-is. `my-replacement.json` is a file you
87
- write yourself, in the new bare scope-word-pair shape described above — **not** the shipped
88
- [`replacement.json`](replacement.json), which is still in the legacy shape.
89
-
90
102
  #### Nx
91
103
 
92
104
  ```shell
@@ -97,8 +109,8 @@ nx g @koobiq/components:new-icons-pack --fix=true --project "<your project>"
97
109
 
98
110
  ```shell
99
111
  nx g @koobiq/components:new-icons-pack \
100
- --custom-data-path migration.json \
101
- --custom-icon-replacement-path my-replacement.json \
112
+ --custom-data-path my-icons.json \
113
+ --custom-icon-replacement-path my-scope.json \
102
114
  --fix=true \
103
115
  --project "<your-project>"
104
116
  ```
@@ -2,19 +2,20 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var fs = require('fs');
6
5
  var path = require('path');
7
6
  var utils_angularParsing = require('../../utils/angular-parsing.cjs');
7
+ var utils_customData = require('../../utils/custom-data.cjs');
8
8
  var utils_iconMigration = require('../../utils/icon-migration.cjs');
9
9
  var utils_messages = require('../../utils/messages.cjs');
10
10
  var utils_packageConfig = require('../../utils/package-config.cjs');
11
+ var utils_projectFiles = require('../../utils/project-files.cjs');
11
12
  var migrations_newIconsPack_data = require('./data.cjs');
12
13
  require('typescript');
13
14
  require('../../utils/ast.cjs');
14
15
  require('../../utils/typescript.cjs');
15
16
  require('@angular-devkit/schematics');
17
+ require('fs');
16
18
  require('@schematics/angular/utility');
17
- require('../../utils/project-files.cjs');
18
19
 
19
20
  function _interopNamespaceDefault(e) {
20
21
  var n = Object.create(null);
@@ -35,11 +36,6 @@ function _interopNamespaceDefault(e) {
35
36
 
36
37
  var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
37
38
 
38
- function readJsonFile(filePath) {
39
- const absolutePath = path__namespace.resolve(filePath);
40
- const fileContents = fs.readFileSync(absolutePath, 'utf-8');
41
- return JSON.parse(fileContents);
42
- }
43
39
  // A bare word: no leading/trailing hyphen, no empty hyphen-separated segment (rejects e.g. `mc-`,
44
40
  // which is otherwise the most natural — and wrong, per the new engine's key-building — way to
45
41
  // write a "prefix" pair).
@@ -85,32 +81,35 @@ function resolveScope(entries, fallback, logger) {
85
81
  return { from: valid.replace, to: valid.replaceWith };
86
82
  }
87
83
  function newIconsPack(options) {
88
- let targetDir;
89
84
  return async (tree, context) => {
90
85
  const { project, fix, stylesExt, updatePrefix = true, customDataPath, customIconReplacementPath } = options;
91
86
  const { logger } = context;
92
- const resolvedData = customDataPath ? readJsonFile(customDataPath) : migrations_newIconsPack_data.newIconsPackData;
87
+ const resolvedData = customDataPath
88
+ ? utils_customData.readCustomIconMapping(tree, customDataPath, logger)
89
+ : migrations_newIconsPack_data.newIconsPackData.map(({ replace, replaceWith }) => ({ from: replace, to: replaceWith }));
93
90
  const resolvedScope = customIconReplacementPath
94
- ? resolveScope(readJsonFile(customIconReplacementPath), migrations_newIconsPack_data.scope, logger)
91
+ ? resolveScope(utils_customData.readCustomJson(tree, customIconReplacementPath), migrations_newIconsPack_data.scope, logger)
95
92
  : migrations_newIconsPack_data.scope;
96
- try {
97
- const projectDefinition = await utils_packageConfig.setupOptions(project, tree);
98
- targetDir = projectDefinition ? tree.getDir(projectDefinition.root) : tree;
99
- }
100
- catch {
101
- targetDir = tree;
102
- }
93
+ logger.info([
94
+ customDataPath
95
+ ? `Icon mapping: ${resolvedData.length} entries from '${customDataPath}'.`
96
+ : `Icon mapping: the built-in one, ${resolvedData.length} entries (--custom-data-path overrides it).`,
97
+ customIconReplacementPath
98
+ ? `Scope: ${resolvedScope.from} -> ${resolvedScope.to}, from '${customIconReplacementPath}'.`
99
+ : `Scope: ${resolvedScope.from} -> ${resolvedScope.to}, the built-in one (--custom-icon-replacement-path overrides it).`
100
+ ].join('\n'));
101
+ const targetDir = await utils_packageConfig.resolveTargetDir(project, tree);
103
102
  const migrationData = {
104
- valueAttrs: ['kbq-icon', 'kbq-icon-item', 'kbq-icon-button'],
103
+ valueAttrs: ['kbq-icon', 'kbq-icon-item', 'kbq-icon-button', 'mc-icon', 'mc-icon-item', 'mc-icon-button'],
105
104
  scope: resolvedScope,
106
105
  scopeClassInList: 'rename',
107
106
  // `replace`/`replaceWith` are always authored under `CANONICAL_ICON_DATA_SCOPE`
108
107
  // ('kbq-'), regardless of the scope this run is migrating *to* — falls back to
109
108
  // stripping the target scope for a custom data file that doesn't follow that
110
109
  // convention.
111
- icons: resolvedData.map(({ replace, replaceWith }) => ({
112
- from: stripScopePrefix(replace, [CANONICAL_ICON_DATA_SCOPE, resolvedScope.to, resolvedScope.from]),
113
- to: stripScopePrefix(replaceWith, [CANONICAL_ICON_DATA_SCOPE, resolvedScope.to])
110
+ icons: resolvedData.map(({ from, to }) => ({
111
+ from: stripScopePrefix(from, [CANONICAL_ICON_DATA_SCOPE, resolvedScope.to, resolvedScope.from]),
112
+ to: stripScopePrefix(to, [CANONICAL_ICON_DATA_SCOPE, resolvedScope.to])
114
113
  })),
115
114
  // Only the attribute-value path (`kbq-icon="mc-<anything>"`) rescopes suffixes that
116
115
  // aren't a known icon name; class lists/bindings/strings/styles stay exact-token-only.
@@ -145,11 +144,7 @@ function newIconsPack(options) {
145
144
  const tsPaths = [];
146
145
  const markdownPaths = [];
147
146
  // Update templates & components
148
- targetDir.visit((filePath) => {
149
- // if project property not provided, skip files in node_modules & dist
150
- if (filePath.includes('node_modules') || filePath.includes('/dist/')) {
151
- return;
152
- }
147
+ utils_projectFiles.visitProjectFiles(targetDir, (filePath) => {
153
148
  if (filePath.endsWith('.html')) {
154
149
  templatePaths.push(filePath);
155
150
  }
@@ -181,12 +176,7 @@ function newIconsPack(options) {
181
176
  }
182
177
  // update styles — icon-name renames always apply; `updatePrefix` only adds the bare
183
178
  // scope-word rename (see `styleAndMarkdownTokenMap` above).
184
- targetDir.visit((filePath) => {
185
- // if project property not provided, styles in node_modules are still skipped, same as
186
- // every other file type above
187
- if (filePath.includes('node_modules')) {
188
- return;
189
- }
179
+ utils_projectFiles.visitProjectFiles(targetDir, (filePath) => {
190
180
  if (!filePath.endsWith(stylesExt)) {
191
181
  return;
192
182
  }
@@ -1,18 +1,6 @@
1
1
  [
2
2
  {
3
- "replace": "class=\"mc mc-icon",
4
- "replaceWith": "class=\"kbq mc-icon"
5
- },
6
- {
7
- "replace": "class=\"mc ",
8
- "replaceWith": "class=\"kbq "
9
- },
10
- {
11
- "replace": "class: 'mc mc-icon",
12
- "replaceWith": "class: 'kbq mc-icon"
13
- },
14
- {
15
- "replace": " mc ",
16
- "replaceWith": " kbq "
3
+ "replace": "mc",
4
+ "replaceWith": "kbq"
17
5
  }
18
6
  ]
@@ -6,7 +6,7 @@
6
6
  "properties": {
7
7
  "project": {
8
8
  "type": "string",
9
- "description": "Name of the project",
9
+ "description": "Name of the project, or a folder to migrate (e.g. ./libs). Without it the whole workspace is migrated",
10
10
  "$default": {
11
11
  "$source": "projectName"
12
12
  }
@@ -28,11 +28,11 @@
28
28
  },
29
29
  "customDataPath": {
30
30
  "type": "string",
31
- "description": "Use this option to specify styles extension preferred in your project"
31
+ "description": "JSON file with the icon mapping, an array of { \"replace\": \"kbq-<old>\", \"replaceWith\": \"kbq-<new>\" }, relative to the workspace root. Without it the built-in mapping is used"
32
32
  },
33
33
  "customIconReplacementPath": {
34
34
  "type": "string",
35
- "description": "Use this option to specify styles extension preferred in your project"
35
+ "description": "JSON file with the scope pair, [{ \"replace\": \"mc\", \"replaceWith\": \"kbq\" }], relative to the workspace root. Without it the scope is mc -> kbq"
36
36
  }
37
37
  }
38
38
  }
@@ -62,7 +62,7 @@ function ssrSuggestion() {
62
62
  function fontsSuggestion() {
63
63
  return [
64
64
  'Koobiq recommends the Inter and JetBrains Mono fonts.',
65
- 'See https://koobiq.io/en/main/typography for installation options (Fontsource or Google Fonts CDN).'
65
+ 'See https://koobiq.io/en/main/typography for installation options (npm packages or self-hosted files).'
66
66
  ];
67
67
  }
68
68
 
@@ -184,15 +184,15 @@ function ngAdd(options) {
184
184
  }
185
185
  // Installing dependencies
186
186
  utils_packageConfig.addPackageToPackageJson(tree, '@angular/cdk', "^21.2.14");
187
- utils_packageConfig.addPackageToPackageJson(tree, '@koobiq/angular-luxon-adapter', "^21.0.1");
187
+ utils_packageConfig.addPackageToPackageJson(tree, '@koobiq/angular-luxon-adapter', "^21.1.0");
188
188
  // `@koobiq/angular-luxon-adapter` is a wrapper: it extends `LuxonDateAdapter` from the base
189
189
  // package and re-exports its formats, both as value imports. That makes the base a mandatory
190
190
  // peer of the wrapper, and installing a package without its mandatory peers only works on
191
191
  // npm — Yarn leaves them out, so the application ends up unable to resolve the adapter.
192
192
  utils_packageConfig.addPackageToPackageJson(tree, '@koobiq/luxon-date-adapter', "^3.5.1");
193
- utils_packageConfig.addPackageToPackageJson(tree, '@koobiq/date-formatter', "^3.5.1");
193
+ utils_packageConfig.addPackageToPackageJson(tree, '@koobiq/date-formatter', "^3.7.0");
194
194
  utils_packageConfig.addPackageToPackageJson(tree, '@koobiq/date-adapter', "^3.5.1");
195
- utils_packageConfig.addPackageToPackageJson(tree, '@koobiq/icons', "^12.4.0");
195
+ utils_packageConfig.addPackageToPackageJson(tree, '@koobiq/icons', "^12.5.0");
196
196
  utils_packageConfig.addPackageToPackageJson(tree, '@koobiq/design-tokens', "^4.1.0");
197
197
  utils_packageConfig.addPackageToPackageJson(tree, 'luxon', "^3.7.2");
198
198
  // `overlayscrollbars` is a mandatory peer too: `@koobiq/components/scrollbar` imports it
@@ -0,0 +1,64 @@
1
+ 'use strict';
2
+
3
+ var schematics = require('@angular-devkit/schematics');
4
+ var fs = require('fs');
5
+ var path = require('path');
6
+
7
+ function _interopNamespaceDefault(e) {
8
+ var n = Object.create(null);
9
+ if (e) {
10
+ Object.keys(e).forEach(function (k) {
11
+ if (k !== 'default') {
12
+ var d = Object.getOwnPropertyDescriptor(e, k);
13
+ Object.defineProperty(n, k, d.get ? d : {
14
+ enumerable: true,
15
+ get: function () { return e[k]; }
16
+ });
17
+ }
18
+ });
19
+ }
20
+ n.default = e;
21
+ return Object.freeze(n);
22
+ }
23
+
24
+ var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
25
+
26
+ const MAPPING_EXAMPLE = '[{ "replace": "kbq-add-to-list_16", "replaceWith": "kbq-file-plus-o_16" }]';
27
+ function readCustomJson(tree, filePath, bases = ['/']) {
28
+ for (const base of bases) {
29
+ const candidate = path__namespace.posix.join(base, filePath);
30
+ if (tree.exists(candidate)) {
31
+ return JSON.parse(tree.readText(candidate));
32
+ }
33
+ }
34
+ const absolutePath = path__namespace.resolve(filePath);
35
+ if (!fs.existsSync(absolutePath)) {
36
+ throw new schematics.SchematicsException(`Unable to find '${filePath}' in the workspace or at '${absolutePath}'`);
37
+ }
38
+ return JSON.parse(fs.readFileSync(absolutePath, 'utf-8'));
39
+ }
40
+ function readCustomIconMapping(tree, filePath, logger, bases) {
41
+ const entries = readCustomJson(tree, filePath, bases);
42
+ const invalid = () => new schematics.SchematicsException(`'${filePath}' must hold a JSON array of icon pairs, for example ${MAPPING_EXAMPLE}`);
43
+ if (!Array.isArray(entries)) {
44
+ throw invalid();
45
+ }
46
+ let legacyShape = false;
47
+ const pairs = entries.map((entry) => {
48
+ if (typeof entry?.replace === 'string' && typeof entry?.replaceWith === 'string') {
49
+ return { from: entry.replace, to: entry.replaceWith };
50
+ }
51
+ if (typeof entry?.from === 'string' && typeof entry?.to === 'string') {
52
+ legacyShape = true;
53
+ return { from: entry.from, to: entry.to };
54
+ }
55
+ throw invalid();
56
+ });
57
+ if (legacyShape) {
58
+ logger.warn(`'${filePath}' uses the deprecated { "from", "to" } pairs; write them as { "replace", "replaceWith" }, for example ${MAPPING_EXAMPLE}`);
59
+ }
60
+ return pairs;
61
+ }
62
+
63
+ exports.readCustomIconMapping = readCustomIconMapping;
64
+ exports.readCustomJson = readCustomJson;
@@ -178,6 +178,9 @@ function createIconTemplateTransform(data, tokenMap, opts) {
178
178
  utils_ast.visitAll(visitor, parsed.tree.rootNodes);
179
179
  const edits = [];
180
180
  const allFound = [];
181
+ const iconHostTokenMap = data.scopeClassOnIconHost === undefined || data.scopeClassOnIconHost === data.scopeClassInList
182
+ ? tokenMap
183
+ : new Map(tokenMap).set(data.scope.from, data.scopeClassOnIconHost === 'remove' ? null : data.scope.to);
181
184
  const resolveValueToken = (token) => {
182
185
  if (tokenMap.has(token)) {
183
186
  return tokenMap.get(token);
@@ -191,6 +194,9 @@ function createIconTemplateTransform(data, tokenMap, opts) {
191
194
  opts.warn(`${message}${(fileName && ' File: ' + fileName) || ''}`);
192
195
  };
193
196
  for (const el of visitor.elementsToMigrate) {
197
+ const classTokenMap = el.attrs.some((attr) => data.valueAttrs.includes(utils_ast.getSimpleAttributeName(attr.name)))
198
+ ? iconHostTokenMap
199
+ : tokenMap;
194
200
  for (const attr of el.attrs) {
195
201
  if (!attr.valueSpan) {
196
202
  continue;
@@ -223,7 +229,7 @@ function createIconTemplateTransform(data, tokenMap, opts) {
223
229
  }
224
230
  if (simpleName === 'class' && !attr.name.startsWith('[')) {
225
231
  const found = [];
226
- const newValue = utils_ast.replaceTokenList(attr.value, exactTokenLookup(tokenMap, found));
232
+ const newValue = utils_ast.replaceTokenList(attr.value, exactTokenLookup(classTokenMap, found));
227
233
  if (newValue !== undefined) {
228
234
  edits.push({
229
235
  start: attr.valueSpan.start.offset,
@@ -235,8 +241,8 @@ function createIconTemplateTransform(data, tokenMap, opts) {
235
241
  continue;
236
242
  }
237
243
  const bindingToken = utils_ast.getClassBindingToken(simpleName);
238
- if (bindingToken !== undefined && tokenMap.has(bindingToken)) {
239
- const replacement = tokenMap.get(bindingToken);
244
+ if (bindingToken !== undefined && classTokenMap.has(bindingToken)) {
245
+ const replacement = classTokenMap.get(bindingToken);
240
246
  if (replacement) {
241
247
  const newSimpleName = simpleName.replace(new RegExp(`\\.${escapeRegExp(bindingToken)}$`), `.${replacement}`);
242
248
  const newName = attr.name.startsWith('[') ? `[${newSimpleName}]` : newSimpleName;
@@ -3,6 +3,9 @@
3
3
  function noProject(project) {
4
4
  return `Unable to find project '${project}' in the workspace`;
5
5
  }
6
+ function noProjectOrDirectory(project) {
7
+ return `'${project}' is neither a project of the workspace nor a folder of it`;
8
+ }
6
9
  const logMessage = (logger, content) => {
7
10
  logger.warn('-------------------------');
8
11
  logger.warn(content.join('\n'));
@@ -11,3 +14,4 @@ const logMessage = (logger, content) => {
11
14
 
12
15
  exports.logMessage = logMessage;
13
16
  exports.noProject = noProject;
17
+ exports.noProjectOrDirectory = noProjectOrDirectory;