@ng-zen/cli 22.4.1 → 22.5.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.
- package/README.md +37 -3
- package/eslint-config/index.js +130 -0
- package/package.json +14 -1
- package/schematics/ng-add/eslint-config.js +87 -0
- package/schematics/ng-add/eslint-config.js.map +1 -0
- package/schematics/ng-add/eslint-config.ts +98 -0
- package/schematics/ng-add/icon-library/icon-library.js +2 -1
- package/schematics/ng-add/icon-library/icon-library.js.map +1 -1
- package/schematics/ng-add/icon-library/icon-library.ts +2 -1
- package/schematics/ng-add/index.js +14 -2
- package/schematics/ng-add/index.js.map +1 -1
- package/schematics/ng-add/index.ts +14 -3
- package/schematics/ng-add/schema.js.map +1 -1
- package/schematics/ng-add/schema.json +5 -0
- package/schematics/ng-add/schema.ts +1 -0
- package/schematics/ui/files/avatar/avatar.ts +1 -1
- package/schematics/ui/files/checkbox/checkbox.stories.ts +1 -1
- package/schematics/ui/files/checkbox/checkbox.ts +2 -2
- package/schematics/ui/files/dialog/dialog.service.stories.ts +3 -3
- package/schematics/ui/files/dialog/dialog.service.ts +2 -2
- package/schematics/ui/files/dialog/dialog.spec.ts +6 -6
- package/schematics/ui/files/dialog/dialog.ts +1 -1
- package/schematics/ui/files/form-control/form-control.ts +5 -5
- package/schematics/ui/files/icon/icon.ts +5 -5
- package/schematics/ui/files/input/input.stories.ts +4 -4
- package/schematics/ui/files/input/input.ts +1 -1
- package/schematics/ui/files/pin/index.ts +3 -0
- package/schematics/ui/files/pin/pin-item.spec.ts +151 -0
- package/schematics/ui/files/pin/pin-item.ts +115 -0
- package/schematics/ui/files/pin/pin.spec.ts +153 -0
- package/schematics/ui/files/pin/pin.stories.ts +164 -0
- package/schematics/ui/files/pin/pin.ts +49 -0
- package/schematics/ui/files/pin/pin.types.ts +15 -0
- package/schematics/ui/files/popover/popover.spec.ts +10 -7
- package/schematics/ui/files/popover/popover.stories.ts +1 -1
- package/schematics/ui/files/radio/radio.stories.ts +3 -3
- package/schematics/ui/files/radio/radio.ts +3 -3
- package/schematics/ui/files/switch/switch.stories.ts +1 -1
- package/schematics/ui/index.js +2 -4
- package/schematics/ui/index.js.map +1 -1
- package/schematics/ui/index.ts +2 -4
- package/schematics/ui/schema.js.map +1 -1
- package/schematics/ui/schema.json +1 -0
- package/schematics/ui/schema.ts +1 -0
- package/utils/apply-file-template.util.js.map +1 -1
- package/utils/apply-file-template.util.ts +3 -3
package/README.md
CHANGED
|
@@ -81,9 +81,10 @@ export class MyComponent {}
|
|
|
81
81
|
3. [CLI Usage & Options](#-cli-usage--options)
|
|
82
82
|
4. [Available UIs](#-available-uis)
|
|
83
83
|
5. [Customization](#-customization)
|
|
84
|
-
6. [
|
|
85
|
-
7. [
|
|
86
|
-
8. [
|
|
84
|
+
6. [ESLint Configuration](#-eslint-configuration)
|
|
85
|
+
7. [Philosophy & Architecture](#-philosophy--architecture)
|
|
86
|
+
8. [Community & Contributions](#-community--contributions)
|
|
87
|
+
9. [Documentation & Links](#-documentation--links)
|
|
87
88
|
|
|
88
89
|
## ✨ Features
|
|
89
90
|
|
|
@@ -166,6 +167,7 @@ ng generate @ng-zen/cli:ui --ui button input --stories
|
|
|
166
167
|
| ----------- | ---------------------------- | ------------------------------------------------------------------------- |
|
|
167
168
|
| **Button** | Interactive buttons | Primary/secondary variants, loading states, icons |
|
|
168
169
|
| **Dialog** | Native modal dialogs | Native dialog element, service API, size variants, backdrop config |
|
|
170
|
+
| **Pin** | Anchor-positioned overlay | CSS Anchor Positioning, TemplateRef content, position and offset controls |
|
|
169
171
|
| **Popover** | Native Popover API directive | Template/string content, placements, click toggle, CSS anchor positioning |
|
|
170
172
|
|
|
171
173
|
## 🎨 Customization
|
|
@@ -188,6 +190,38 @@ Every generated component utilizes CSS variables for immediate theming without t
|
|
|
188
190
|
|
|
189
191
|
For structural changes (e.g., modifying the default `0.625rem` border radius or internal padding), simply edit the generated `.scss` files in your `./ui` directory.
|
|
190
192
|
|
|
193
|
+
## 🔧 ESLint Configuration
|
|
194
|
+
|
|
195
|
+
ng-zen provides a flat ESLint config for UI components and generated files.
|
|
196
|
+
|
|
197
|
+
**Auto-setup** during `ng add`:
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
ng add @ng-zen/cli
|
|
201
|
+
# → Prompt: "ESLint config detected. Update it for ng-zen UI components?"
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
It adds `@ng-zen/cli/eslint-config` to your `eslint.config.*` and spreads it into the `defineConfig` array. This enforces the `zen` prefix on component selectors and relaxes rules for `.stories.ts` / `.spec.ts` files generated inside `ui/` directories.
|
|
205
|
+
|
|
206
|
+
**Manual setup** (if you declined the prompt):
|
|
207
|
+
|
|
208
|
+
```ts
|
|
209
|
+
import ngZen from '@ng-zen/cli/eslint-config';
|
|
210
|
+
|
|
211
|
+
export default defineConfig([...otherConfigs, ...ngZen]);
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
**Custom path or rules** — use the named exports for fine-grained control:
|
|
215
|
+
|
|
216
|
+
```ts
|
|
217
|
+
import ngZen from '@ng-zen/cli/eslint-config';
|
|
218
|
+
|
|
219
|
+
export default defineConfig([
|
|
220
|
+
ngZen.createNgZenConfig({ uiFiles: 'src/app/shared/components' }),
|
|
221
|
+
...ngZen.generatedFiles,
|
|
222
|
+
]);
|
|
223
|
+
```
|
|
224
|
+
|
|
191
225
|
## 🏛️ Philosophy & Architecture
|
|
192
226
|
|
|
193
227
|
### Perfect For
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
const { defineConfig } = require('eslint/config');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Config block for UI components inside a `ui/` directory.
|
|
6
|
+
*
|
|
7
|
+
* Enforces:
|
|
8
|
+
* - `zen` prefix for component selectors (`element`, `kebab-case`)
|
|
9
|
+
* - `zen` prefix for directive selectors (`attribute`, `camelCase`)
|
|
10
|
+
* - At most 2 classes per file
|
|
11
|
+
*
|
|
12
|
+
* @type {import('eslint').Linter.Config}
|
|
13
|
+
*/
|
|
14
|
+
const uiComponent = {
|
|
15
|
+
files: ['**/ui/**/*.ts'],
|
|
16
|
+
rules: {
|
|
17
|
+
'@angular-eslint/directive-selector': ['error', { type: 'attribute', prefix: 'zen', style: 'camelCase' }],
|
|
18
|
+
'@angular-eslint/component-selector': ['error', { type: 'element', prefix: 'zen', style: 'kebab-case' }],
|
|
19
|
+
'max-classes-per-file': ['error', 2],
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Config block for generated files — specs, tests, and Storybook stories.
|
|
25
|
+
*
|
|
26
|
+
* Relaxes strict rules that are impractical for test/story files:
|
|
27
|
+
* disables `explicit-function-return-type`, `no-unsafe-*`, `max-classes-per-file`,
|
|
28
|
+
* `no-empty-function`, `require-await`, `unbound-method`, and `no-floating-promises`.
|
|
29
|
+
*
|
|
30
|
+
* @type {import('eslint').Linter.Config}
|
|
31
|
+
*/
|
|
32
|
+
const generatedFiles = {
|
|
33
|
+
files: ['**/ui/**/*.spec.ts', '**/ui/**/*.test.ts', '**/ui/**/*.stories.ts'],
|
|
34
|
+
rules: {
|
|
35
|
+
'@typescript-eslint/unbound-method': 'off',
|
|
36
|
+
'@typescript-eslint/no-unsafe-return': 'off',
|
|
37
|
+
'@typescript-eslint/no-unsafe-call': 'off',
|
|
38
|
+
'@typescript-eslint/no-unsafe-member-access': 'off',
|
|
39
|
+
'@typescript-eslint/no-unsafe-assignment': 'off',
|
|
40
|
+
'@typescript-eslint/no-floating-promises': 'off',
|
|
41
|
+
'@typescript-eslint/no-empty-function': 'off',
|
|
42
|
+
'@typescript-eslint/explicit-function-return-type': 'off',
|
|
43
|
+
'@typescript-eslint/require-await': 'off',
|
|
44
|
+
'max-classes-per-file': 'off',
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Creates a custom UI component config block with a custom file glob.
|
|
50
|
+
*
|
|
51
|
+
* @param {Object} [options]
|
|
52
|
+
* @param {string | string[]} [options.uiFiles] - Glob pattern(s) for UI component files.
|
|
53
|
+
* Uses the same format as the `files` property in flat config.
|
|
54
|
+
* @returns {import('eslint').Linter.Config} A config block with the same rules as
|
|
55
|
+
* uiComponent but scoped to the provided file pattern.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```ts
|
|
59
|
+
* createNgZenConfig({ uiFiles: 'libs/my-ui' })
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
function createNgZenConfig(options = {}) {
|
|
63
|
+
const { uiFiles = ['**/ui/**/*.ts'] } = options;
|
|
64
|
+
return { ...uiComponent, files: [uiFiles].flat() };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* ng-zen ESLint flat config.
|
|
69
|
+
*
|
|
70
|
+
* ## Default import
|
|
71
|
+
*
|
|
72
|
+
* Import the whole array of flat configs:
|
|
73
|
+
* ```ts
|
|
74
|
+
* import ngZen from '@ng-zen/cli/eslint-config';
|
|
75
|
+
* export default defineConfig([...ngZen]);
|
|
76
|
+
* ```
|
|
77
|
+
*
|
|
78
|
+
* ## Named properties
|
|
79
|
+
*
|
|
80
|
+
* | Property | Returns | Description |
|
|
81
|
+
* |---|---|---|
|
|
82
|
+
* | `.uiComponent` | `Config` | Rules for UI component files. Override `files` / `rules` via spread. |
|
|
83
|
+
* | `.generatedFiles` | `Config` | Rules for generated files (stories, spec, test). |
|
|
84
|
+
* | `.createNgZenConfig(opts)` | `Config` | Helper — same rules as uiComponent with a custom file glob. |
|
|
85
|
+
*
|
|
86
|
+
* ## Custom path
|
|
87
|
+
*
|
|
88
|
+
* By default, UI component files are detected via a glob pattern targeting any `ui` directory
|
|
89
|
+
* (glob: `**` + `/ui/` + `**` + `/*`). If your components live in a different location, choose one of the
|
|
90
|
+
* approaches below instead of the default `...ngZen` spread.
|
|
91
|
+
*
|
|
92
|
+
* @example <caption>Custom UI path</caption>
|
|
93
|
+
* ```ts
|
|
94
|
+
* import ngZen from '@ng-zen/cli/eslint-config';
|
|
95
|
+
* export default defineConfig([
|
|
96
|
+
* ngZen.createNgZenConfig({ uiFiles: 'src/app/shared/ui' }),
|
|
97
|
+
* ...ngZen.generatedFiles,
|
|
98
|
+
* ]);
|
|
99
|
+
* ```
|
|
100
|
+
*
|
|
101
|
+
* @example <caption>Override prefix or rules</caption>
|
|
102
|
+
* ```ts
|
|
103
|
+
* import ngZen from '@ng-zen/cli/eslint-config';
|
|
104
|
+
* export default defineConfig([
|
|
105
|
+
* {
|
|
106
|
+
* files: ['libs/my-ui'],
|
|
107
|
+
* rules: {
|
|
108
|
+
* ...ngZen.uiComponent.rules,
|
|
109
|
+
* '@angular-eslint/component-selector': ['error', { type: 'element', prefix: ['app', 'zen'], style: 'kebab-case' }],
|
|
110
|
+
* },
|
|
111
|
+
* },
|
|
112
|
+
* ...ngZen.generatedFiles,
|
|
113
|
+
* ]);
|
|
114
|
+
* ```
|
|
115
|
+
*
|
|
116
|
+
* @type {import('eslint').Linter.FlatConfig[] &
|
|
117
|
+
* {
|
|
118
|
+
* uiComponent: import('eslint').Linter.Config,
|
|
119
|
+
* generatedFiles: import('eslint').Linter.Config,
|
|
120
|
+
* createNgZenConfig: (options?: { uiFiles?: string | string[] }) => import('eslint').Linter.Config
|
|
121
|
+
* }
|
|
122
|
+
* }
|
|
123
|
+
*/
|
|
124
|
+
const config = Object.assign(defineConfig([uiComponent, generatedFiles]), {
|
|
125
|
+
uiComponent,
|
|
126
|
+
generatedFiles,
|
|
127
|
+
createNgZenConfig,
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
module.exports = config;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ng-zen/cli",
|
|
3
|
-
"version": "22.
|
|
3
|
+
"version": "22.5.0",
|
|
4
4
|
"description": "Angular CLI generator for creating fully customizable UI components.",
|
|
5
5
|
"license": "BSD-2-Clause",
|
|
6
6
|
"private": false,
|
|
@@ -59,6 +59,7 @@
|
|
|
59
59
|
"form-control",
|
|
60
60
|
"icon",
|
|
61
61
|
"input",
|
|
62
|
+
"pin",
|
|
62
63
|
"popover",
|
|
63
64
|
"radio",
|
|
64
65
|
"skeleton",
|
|
@@ -68,8 +69,20 @@
|
|
|
68
69
|
"ng-add": {
|
|
69
70
|
"save": "devDependencies"
|
|
70
71
|
},
|
|
72
|
+
"exports": {
|
|
73
|
+
"./eslint-config": "./eslint-config/index.js",
|
|
74
|
+
"./package.json": "./package.json"
|
|
75
|
+
},
|
|
71
76
|
"schematics": "./schematics/collection.json",
|
|
72
77
|
"packageManager": "pnpm@10.24.0",
|
|
78
|
+
"pnpm": {
|
|
79
|
+
"peerDependencyRules": {
|
|
80
|
+
"allowedVersions": {
|
|
81
|
+
"typescript": "6",
|
|
82
|
+
"chokidar": "5"
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
},
|
|
73
86
|
"dependencies": {
|
|
74
87
|
"@angular-devkit/core": "^22.0.1",
|
|
75
88
|
"@angular-devkit/schematics": "^22.0.1",
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.findEslintConfig = findEslintConfig;
|
|
4
|
+
exports.logEslintManualInstructions = logEslintManualInstructions;
|
|
5
|
+
exports.updateEslintConfig = updateEslintConfig;
|
|
6
|
+
function findEslintConfig(tree) {
|
|
7
|
+
for (const name of ['eslint.config.js', 'eslint.config.mjs', 'eslint.config.ts']) {
|
|
8
|
+
if (tree.exists(name))
|
|
9
|
+
return name;
|
|
10
|
+
}
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
function detectFormat(code) {
|
|
14
|
+
return code.includes('require(') || code.includes('module.exports') ? 'cjs' : 'esm';
|
|
15
|
+
}
|
|
16
|
+
function getImportStatement(code) {
|
|
17
|
+
if (detectFormat(code) === 'cjs') {
|
|
18
|
+
return "const ngZen = require('@ng-zen/cli/eslint-config');\n";
|
|
19
|
+
}
|
|
20
|
+
return "import ngZen from '@ng-zen/cli/eslint-config';\n";
|
|
21
|
+
}
|
|
22
|
+
function addImport(code) {
|
|
23
|
+
if (code.includes('@ng-zen/cli/eslint-config'))
|
|
24
|
+
return code;
|
|
25
|
+
const statement = getImportStatement(code);
|
|
26
|
+
if (detectFormat(code) === 'cjs') {
|
|
27
|
+
const lastRequire = code.lastIndexOf('\nconst ');
|
|
28
|
+
if (lastRequire < 0)
|
|
29
|
+
return code;
|
|
30
|
+
const insertAt = code.indexOf('\n', lastRequire + 1) + 1;
|
|
31
|
+
return code.slice(0, insertAt) + statement + code.slice(insertAt);
|
|
32
|
+
}
|
|
33
|
+
const importEnd = code.lastIndexOf('\nimport ');
|
|
34
|
+
const insertAt = importEnd > 0 ? code.indexOf('\n', importEnd + 1) + 1 : code.indexOf('\n') + 1;
|
|
35
|
+
return code.slice(0, insertAt) + statement + code.slice(insertAt);
|
|
36
|
+
}
|
|
37
|
+
function spreadConfig(code) {
|
|
38
|
+
const defineConfigMatch = /defineConfig\(\s*\[([\s\S]*?)\]\s*\)/.exec(code);
|
|
39
|
+
if (!defineConfigMatch)
|
|
40
|
+
return code;
|
|
41
|
+
const existingArray = defineConfigMatch[0];
|
|
42
|
+
if (existingArray.includes('...ngZen'))
|
|
43
|
+
return code;
|
|
44
|
+
const newArray = existingArray.replace(/\]\s*\)$/, ', ...ngZen,\n ])');
|
|
45
|
+
return code.replace(existingArray, newArray);
|
|
46
|
+
}
|
|
47
|
+
function logEslintManualInstructions() {
|
|
48
|
+
return (tree, context) => {
|
|
49
|
+
const configPath = findEslintConfig(tree);
|
|
50
|
+
if (!configPath)
|
|
51
|
+
return tree;
|
|
52
|
+
context.logger.info('');
|
|
53
|
+
context.logger.info('⚠️ To add ng-zen ESLint config manually:');
|
|
54
|
+
context.logger.info(' 1. Run: npm install -D @ng-zen/cli');
|
|
55
|
+
context.logger.info(' 2. In eslint.config.js, add:');
|
|
56
|
+
context.logger.info(" import ngZen from '@ng-zen/cli/eslint-config';");
|
|
57
|
+
context.logger.info(' // then spread ...ngZen into the defineConfig array');
|
|
58
|
+
context.logger.info(' See: Manual Configuration page in Storybook');
|
|
59
|
+
return tree;
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function updateEslintConfig() {
|
|
63
|
+
return (tree, context) => {
|
|
64
|
+
const configPath = findEslintConfig(tree);
|
|
65
|
+
if (!configPath) {
|
|
66
|
+
context.logger.info('ℹ️ No flat ESLint config found — skip ESLint update');
|
|
67
|
+
return tree;
|
|
68
|
+
}
|
|
69
|
+
let code = tree.read(configPath).toString('utf-8');
|
|
70
|
+
if (!code.includes('defineConfig')) {
|
|
71
|
+
context.logger.warn('⚠️ ESLint config does not use defineConfig — skip automatic update');
|
|
72
|
+
return tree;
|
|
73
|
+
}
|
|
74
|
+
const hadImport = code.includes('@ng-zen/cli/eslint-config');
|
|
75
|
+
code = addImport(code);
|
|
76
|
+
code = spreadConfig(code);
|
|
77
|
+
tree.overwrite(configPath, code);
|
|
78
|
+
if (hadImport) {
|
|
79
|
+
context.logger.info('✅ ESLint config already has @ng-zen/cli config — ensured it is in defineConfig array');
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
context.logger.info('✅ Added @ng-zen/cli/eslint-config to ESLint config');
|
|
83
|
+
}
|
|
84
|
+
return tree;
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=eslint-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eslint-config.js","sourceRoot":"","sources":["../../../../../src/schematics/ng-add/eslint-config.ts"],"names":[],"mappings":"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","sourcesContent":["import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\n\ntype ModuleFormat = 'cjs' | 'esm';\n\nexport function findEslintConfig(tree: Tree): string | null {\n for (const name of ['eslint.config.js', 'eslint.config.mjs', 'eslint.config.ts']) {\n if (tree.exists(name)) return name;\n }\n return null;\n}\n\nfunction detectFormat(code: string): ModuleFormat {\n return code.includes('require(') || code.includes('module.exports') ? 'cjs' : 'esm';\n}\n\nfunction getImportStatement(code: string): string {\n if (detectFormat(code) === 'cjs') {\n return \"const ngZen = require('@ng-zen/cli/eslint-config');\\n\";\n }\n return \"import ngZen from '@ng-zen/cli/eslint-config';\\n\";\n}\n\nfunction addImport(code: string): string {\n if (code.includes('@ng-zen/cli/eslint-config')) return code;\n\n const statement = getImportStatement(code);\n\n if (detectFormat(code) === 'cjs') {\n const lastRequire = code.lastIndexOf('\\nconst ');\n if (lastRequire < 0) return code;\n const insertAt = code.indexOf('\\n', lastRequire + 1) + 1;\n return code.slice(0, insertAt) + statement + code.slice(insertAt);\n }\n\n const importEnd = code.lastIndexOf('\\nimport ');\n const insertAt = importEnd > 0 ? code.indexOf('\\n', importEnd + 1) + 1 : code.indexOf('\\n') + 1;\n return code.slice(0, insertAt) + statement + code.slice(insertAt);\n}\n\nfunction spreadConfig(code: string): string {\n const defineConfigMatch = /defineConfig\\(\\s*\\[([\\s\\S]*?)\\]\\s*\\)/.exec(code);\n if (!defineConfigMatch) return code;\n\n const existingArray = defineConfigMatch[0];\n if (existingArray.includes('...ngZen')) return code;\n\n const newArray = existingArray.replace(/\\]\\s*\\)$/, ', ...ngZen,\\n ])');\n return code.replace(existingArray, newArray);\n}\n\nexport function logEslintManualInstructions(): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const configPath = findEslintConfig(tree);\n if (!configPath) return tree;\n\n context.logger.info('');\n context.logger.info('⚠️ To add ng-zen ESLint config manually:');\n context.logger.info(' 1. Run: npm install -D @ng-zen/cli');\n context.logger.info(' 2. In eslint.config.js, add:');\n context.logger.info(\" import ngZen from '@ng-zen/cli/eslint-config';\");\n context.logger.info(' // then spread ...ngZen into the defineConfig array');\n context.logger.info(' See: Manual Configuration page in Storybook');\n\n return tree;\n };\n}\n\nexport function updateEslintConfig(): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const configPath = findEslintConfig(tree);\n\n if (!configPath) {\n context.logger.info('ℹ️ No flat ESLint config found — skip ESLint update');\n return tree;\n }\n\n let code = tree.read(configPath)!.toString('utf-8');\n\n if (!code.includes('defineConfig')) {\n context.logger.warn('⚠️ ESLint config does not use defineConfig — skip automatic update');\n return tree;\n }\n\n const hadImport = code.includes('@ng-zen/cli/eslint-config');\n code = addImport(code);\n code = spreadConfig(code);\n\n tree.overwrite(configPath, code);\n\n if (hadImport) {\n context.logger.info('✅ ESLint config already has @ng-zen/cli config — ensured it is in defineConfig array');\n } else {\n context.logger.info('✅ Added @ng-zen/cli/eslint-config to ESLint config');\n }\n\n return tree;\n };\n}\n"]}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';
|
|
2
|
+
|
|
3
|
+
type ModuleFormat = 'cjs' | 'esm';
|
|
4
|
+
|
|
5
|
+
export function findEslintConfig(tree: Tree): string | null {
|
|
6
|
+
for (const name of ['eslint.config.js', 'eslint.config.mjs', 'eslint.config.ts']) {
|
|
7
|
+
if (tree.exists(name)) return name;
|
|
8
|
+
}
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function detectFormat(code: string): ModuleFormat {
|
|
13
|
+
return code.includes('require(') || code.includes('module.exports') ? 'cjs' : 'esm';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function getImportStatement(code: string): string {
|
|
17
|
+
if (detectFormat(code) === 'cjs') {
|
|
18
|
+
return "const ngZen = require('@ng-zen/cli/eslint-config');\n";
|
|
19
|
+
}
|
|
20
|
+
return "import ngZen from '@ng-zen/cli/eslint-config';\n";
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function addImport(code: string): string {
|
|
24
|
+
if (code.includes('@ng-zen/cli/eslint-config')) return code;
|
|
25
|
+
|
|
26
|
+
const statement = getImportStatement(code);
|
|
27
|
+
|
|
28
|
+
if (detectFormat(code) === 'cjs') {
|
|
29
|
+
const lastRequire = code.lastIndexOf('\nconst ');
|
|
30
|
+
if (lastRequire < 0) return code;
|
|
31
|
+
const insertAt = code.indexOf('\n', lastRequire + 1) + 1;
|
|
32
|
+
return code.slice(0, insertAt) + statement + code.slice(insertAt);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const importEnd = code.lastIndexOf('\nimport ');
|
|
36
|
+
const insertAt = importEnd > 0 ? code.indexOf('\n', importEnd + 1) + 1 : code.indexOf('\n') + 1;
|
|
37
|
+
return code.slice(0, insertAt) + statement + code.slice(insertAt);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function spreadConfig(code: string): string {
|
|
41
|
+
const defineConfigMatch = /defineConfig\(\s*\[([\s\S]*?)\]\s*\)/.exec(code);
|
|
42
|
+
if (!defineConfigMatch) return code;
|
|
43
|
+
|
|
44
|
+
const existingArray = defineConfigMatch[0];
|
|
45
|
+
if (existingArray.includes('...ngZen')) return code;
|
|
46
|
+
|
|
47
|
+
const newArray = existingArray.replace(/\]\s*\)$/, ', ...ngZen,\n ])');
|
|
48
|
+
return code.replace(existingArray, newArray);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function logEslintManualInstructions(): Rule {
|
|
52
|
+
return (tree: Tree, context: SchematicContext) => {
|
|
53
|
+
const configPath = findEslintConfig(tree);
|
|
54
|
+
if (!configPath) return tree;
|
|
55
|
+
|
|
56
|
+
context.logger.info('');
|
|
57
|
+
context.logger.info('⚠️ To add ng-zen ESLint config manually:');
|
|
58
|
+
context.logger.info(' 1. Run: npm install -D @ng-zen/cli');
|
|
59
|
+
context.logger.info(' 2. In eslint.config.js, add:');
|
|
60
|
+
context.logger.info(" import ngZen from '@ng-zen/cli/eslint-config';");
|
|
61
|
+
context.logger.info(' // then spread ...ngZen into the defineConfig array');
|
|
62
|
+
context.logger.info(' See: Manual Configuration page in Storybook');
|
|
63
|
+
|
|
64
|
+
return tree;
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function updateEslintConfig(): Rule {
|
|
69
|
+
return (tree: Tree, context: SchematicContext) => {
|
|
70
|
+
const configPath = findEslintConfig(tree);
|
|
71
|
+
|
|
72
|
+
if (!configPath) {
|
|
73
|
+
context.logger.info('ℹ️ No flat ESLint config found — skip ESLint update');
|
|
74
|
+
return tree;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
let code = tree.read(configPath)!.toString('utf-8');
|
|
78
|
+
|
|
79
|
+
if (!code.includes('defineConfig')) {
|
|
80
|
+
context.logger.warn('⚠️ ESLint config does not use defineConfig — skip automatic update');
|
|
81
|
+
return tree;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const hadImport = code.includes('@ng-zen/cli/eslint-config');
|
|
85
|
+
code = addImport(code);
|
|
86
|
+
code = spreadConfig(code);
|
|
87
|
+
|
|
88
|
+
tree.overwrite(configPath, code);
|
|
89
|
+
|
|
90
|
+
if (hadImport) {
|
|
91
|
+
context.logger.info('✅ ESLint config already has @ng-zen/cli config — ensured it is in defineConfig array');
|
|
92
|
+
} else {
|
|
93
|
+
context.logger.info('✅ Added @ng-zen/cli/eslint-config to ESLint config');
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return tree;
|
|
97
|
+
};
|
|
98
|
+
}
|
|
@@ -16,7 +16,8 @@ function installIconLibrary() {
|
|
|
16
16
|
}
|
|
17
17
|
function logIconLibraryManualInstructions() {
|
|
18
18
|
return (tree, context) => {
|
|
19
|
-
context.logger.info('
|
|
19
|
+
context.logger.info('');
|
|
20
|
+
context.logger.info('⚠️ To use <zen-icon>, install an SVG icon library (one-time setup):');
|
|
20
21
|
context.logger.info(' - Recommended: @hugeicons/core-free-icons');
|
|
21
22
|
context.logger.info(' - Or use any other SVG icon library and pass icons via the [icon] input.');
|
|
22
23
|
return tree;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"icon-library.js","sourceRoot":"","sources":["../../../../../../src/schematics/ng-add/icon-library/icon-library.ts"],"names":[],"mappings":";;AAMA,gDAWC;AAED,
|
|
1
|
+
{"version":3,"file":"icon-library.js","sourceRoot":"","sources":["../../../../../../src/schematics/ng-add/icon-library/icon-library.ts"],"names":[],"mappings":";;AAMA,gDAWC;AAED,4EASC;AA3BD,4DAA0E;AAC1E,2EAAoF;AAEpF,qDAAqD;AAErD,SAAgB,kBAAkB;IAChC,OAAO,CAAC,IAAU,EAAE,OAAyB,EAAE,EAAE;QAC/C,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;QAEnE,IAAA,uCAAwB,EAAC,IAAI,EAAE,kCAAiB,CAAC,CAAC;QAClD,OAAO,CAAC,OAAO,CAAC,IAAI,8BAAsB,EAAE,CAAC,CAAC;QAE9C,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,8DAA8D,CAAC,CAAC;QAEpF,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;AACJ,CAAC;AAED,SAAgB,gCAAgC;IAC9C,OAAO,CAAC,IAAU,EAAE,OAAyB,EAAE,EAAE;QAC/C,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACxB,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,qEAAqE,CAAC,CAAC;QAC3F,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;QACnE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,4EAA4E,CAAC,CAAC;QAElG,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\nimport { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';\nimport { addPackageJsonDependency } from '@schematics/angular/utility/dependencies';\n\nimport { HugeiconsCoreFree } from './icon-libraries';\n\nexport function installIconLibrary(): Rule {\n return (tree: Tree, context: SchematicContext) => {\n context.logger.info('📦 Installing @hugeicons/core-free-icons...');\n\n addPackageJsonDependency(tree, HugeiconsCoreFree);\n context.addTask(new NodePackageInstallTask());\n\n context.logger.info('✅ @hugeicons/core-free-icons has been added to your project.');\n\n return tree;\n };\n}\n\nexport function logIconLibraryManualInstructions(): Rule {\n return (tree: Tree, context: SchematicContext) => {\n context.logger.info('');\n context.logger.info('⚠️ To use <zen-icon>, install an SVG icon library (one-time setup):');\n context.logger.info(' - Recommended: @hugeicons/core-free-icons');\n context.logger.info(' - Or use any other SVG icon library and pass icons via the [icon] input.');\n\n return tree;\n };\n}\n"]}
|
|
@@ -19,7 +19,8 @@ export function installIconLibrary(): Rule {
|
|
|
19
19
|
|
|
20
20
|
export function logIconLibraryManualInstructions(): Rule {
|
|
21
21
|
return (tree: Tree, context: SchematicContext) => {
|
|
22
|
-
context.logger.info('
|
|
22
|
+
context.logger.info('');
|
|
23
|
+
context.logger.info('⚠️ To use <zen-icon>, install an SVG icon library (one-time setup):');
|
|
23
24
|
context.logger.info(' - Recommended: @hugeicons/core-free-icons');
|
|
24
25
|
context.logger.info(' - Or use any other SVG icon library and pass icons via the [icon] input.');
|
|
25
26
|
|
|
@@ -1,14 +1,26 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ngAdd = ngAdd;
|
|
4
|
+
const schematics_1 = require("@angular-devkit/schematics");
|
|
5
|
+
const eslint_config_1 = require("./eslint-config");
|
|
4
6
|
const icon_library_1 = require("./icon-library");
|
|
5
7
|
function ngAdd(options) {
|
|
6
8
|
return (tree, context) => {
|
|
7
9
|
context.logger.info('🔧 Setting up ng-zen...');
|
|
10
|
+
const rules = [];
|
|
8
11
|
if (options.installIconLibrary) {
|
|
9
|
-
|
|
12
|
+
rules.push((0, icon_library_1.installIconLibrary)());
|
|
10
13
|
}
|
|
11
|
-
|
|
14
|
+
else {
|
|
15
|
+
rules.push((0, icon_library_1.logIconLibraryManualInstructions)());
|
|
16
|
+
}
|
|
17
|
+
if (options.updateEslint) {
|
|
18
|
+
rules.push((0, eslint_config_1.updateEslintConfig)());
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
rules.push((0, eslint_config_1.logEslintManualInstructions)());
|
|
22
|
+
}
|
|
23
|
+
return (0, schematics_1.chain)(rules)(tree, context);
|
|
12
24
|
};
|
|
13
25
|
}
|
|
14
26
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/schematics/ng-add/index.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/schematics/ng-add/index.ts"],"names":[],"mappings":";;AAMA,sBAoBC;AA1BD,2DAAyD;AAEzD,mDAAkF;AAClF,iDAAsF;AAGtF,SAAgB,KAAK,CAAC,OAAe;IACnC,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE;QACvB,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;QAE/C,MAAM,KAAK,GAAW,EAAE,CAAC;QAEzB,IAAI,OAAO,CAAC,kBAAkB,EAAE,CAAC;YAC/B,KAAK,CAAC,IAAI,CAAC,IAAA,iCAAkB,GAAE,CAAC,CAAC;QACnC,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,IAAA,+CAAgC,GAAE,CAAC,CAAC;QACjD,CAAC;QAED,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;YACzB,KAAK,CAAC,IAAI,CAAC,IAAA,kCAAkB,GAAE,CAAC,CAAC;QACnC,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,IAAA,2CAA2B,GAAE,CAAC,CAAC;QAC5C,CAAC;QAED,OAAO,IAAA,kBAAK,EAAC,KAAK,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACrC,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import { chain, Rule } from '@angular-devkit/schematics';\n\nimport { logEslintManualInstructions, updateEslintConfig } from './eslint-config';\nimport { installIconLibrary, logIconLibraryManualInstructions } from './icon-library';\nimport { Schema } from './schema';\n\nexport function ngAdd(options: Schema): Rule {\n return (tree, context) => {\n context.logger.info('🔧 Setting up ng-zen...');\n\n const rules: Rule[] = [];\n\n if (options.installIconLibrary) {\n rules.push(installIconLibrary());\n } else {\n rules.push(logIconLibraryManualInstructions());\n }\n\n if (options.updateEslint) {\n rules.push(updateEslintConfig());\n } else {\n rules.push(logEslintManualInstructions());\n }\n\n return chain(rules)(tree, context);\n };\n}\n"]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { Rule } from '@angular-devkit/schematics';
|
|
1
|
+
import { chain, Rule } from '@angular-devkit/schematics';
|
|
2
2
|
|
|
3
|
+
import { logEslintManualInstructions, updateEslintConfig } from './eslint-config';
|
|
3
4
|
import { installIconLibrary, logIconLibraryManualInstructions } from './icon-library';
|
|
4
5
|
import { Schema } from './schema';
|
|
5
6
|
|
|
@@ -7,10 +8,20 @@ export function ngAdd(options: Schema): Rule {
|
|
|
7
8
|
return (tree, context) => {
|
|
8
9
|
context.logger.info('🔧 Setting up ng-zen...');
|
|
9
10
|
|
|
11
|
+
const rules: Rule[] = [];
|
|
12
|
+
|
|
10
13
|
if (options.installIconLibrary) {
|
|
11
|
-
|
|
14
|
+
rules.push(installIconLibrary());
|
|
15
|
+
} else {
|
|
16
|
+
rules.push(logIconLibraryManualInstructions());
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (options.updateEslint) {
|
|
20
|
+
rules.push(updateEslintConfig());
|
|
21
|
+
} else {
|
|
22
|
+
rules.push(logEslintManualInstructions());
|
|
12
23
|
}
|
|
13
24
|
|
|
14
|
-
return
|
|
25
|
+
return chain(rules)(tree, context);
|
|
15
26
|
};
|
|
16
27
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../../../src/schematics/ng-add/schema.ts"],"names":[],"mappings":"","sourcesContent":["export interface Schema {\n installIconLibrary?: boolean;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../../../src/schematics/ng-add/schema.ts"],"names":[],"mappings":"","sourcesContent":["export interface Schema {\n installIconLibrary?: boolean;\n updateEslint?: boolean;\n}\n"]}
|
|
@@ -8,6 +8,11 @@
|
|
|
8
8
|
"installIconLibrary": {
|
|
9
9
|
"type": "boolean",
|
|
10
10
|
"x-prompt": "Would you like to install @hugeicons/core-free-icons? This package provides the icon set for zen-icon component. You can also install it manually later."
|
|
11
|
+
},
|
|
12
|
+
"updateEslint": {
|
|
13
|
+
"type": "boolean",
|
|
14
|
+
"x-prompt": "ESLint config detected. Update it for ng-zen UI components? This adds zen prefix rules and relaxes rules for stories/spec files.",
|
|
15
|
+
"default": true
|
|
11
16
|
}
|
|
12
17
|
}
|
|
13
18
|
}
|
|
@@ -81,7 +81,7 @@ export const WithSignalForm: Story = {
|
|
|
81
81
|
template: `
|
|
82
82
|
<div style="display: flex; flex-direction: column; gap: 0.5rem;">
|
|
83
83
|
<div style="display: flex; align-items: center; gap: 0.25rem">
|
|
84
|
-
<zen-checkbox [formField]="form.agree"
|
|
84
|
+
<zen-checkbox id="agree" [formField]="form.agree" />
|
|
85
85
|
<label for="agree">I agree to the terms</label>
|
|
86
86
|
</div>
|
|
87
87
|
@if (form.agree().invalid()) {
|
|
@@ -39,13 +39,13 @@ import { ZenFormControl } from '../form-control';
|
|
|
39
39
|
selector: 'zen-checkbox',
|
|
40
40
|
template: `
|
|
41
41
|
<input
|
|
42
|
+
#inputElement
|
|
43
|
+
type="checkbox"
|
|
42
44
|
[attr.aria-disabled]="disabled()"
|
|
43
45
|
[attr.aria-invalid]="invalid() || null"
|
|
44
46
|
[checked]="value()"
|
|
45
47
|
[disabled]="disabled()"
|
|
46
48
|
(change)="onInput(inputElement.checked)"
|
|
47
|
-
#inputElement
|
|
48
|
-
type="checkbox"
|
|
49
49
|
/>
|
|
50
50
|
@if (inputElement.indeterminate) {
|
|
51
51
|
─
|
|
@@ -67,8 +67,8 @@ See [GitHub](https://github.com/kstepien3/ng-zen), [MDN Dialog Element](https://
|
|
|
67
67
|
template: `
|
|
68
68
|
<p>{{ message() }}</p>
|
|
69
69
|
<div style="display: flex; gap: 0.5rem; margin-top: 1rem; justify-content: end">
|
|
70
|
-
<button
|
|
71
|
-
<button (click)="confirmClick.emit('confirmed!')"
|
|
70
|
+
<button color="danger" variant="filled" zen-btn (click)="cancel()">Cancel</button>
|
|
71
|
+
<button zen-btn (click)="confirmClick.emit('confirmed!')">Confirm</button>
|
|
72
72
|
</div>
|
|
73
73
|
`,
|
|
74
74
|
standalone: true,
|
|
@@ -90,7 +90,7 @@ class DemoDialogContent {
|
|
|
90
90
|
// eslint-disable-next-line @angular-eslint/component-selector
|
|
91
91
|
selector: 'app-service-demo',
|
|
92
92
|
template: `
|
|
93
|
-
<button (click)="openDialog()"
|
|
93
|
+
<button zen-btn (click)="openDialog()">Open via Service</button>
|
|
94
94
|
`,
|
|
95
95
|
standalone: true,
|
|
96
96
|
imports: [ZenButton],
|
|
@@ -62,7 +62,7 @@ interface DialogConfig<T, TInputs = ComponentInputs<T>, TOutputs = ComponentOutp
|
|
|
62
62
|
|
|
63
63
|
/** Reference to an opened dialog. Provides `close()` and `componentInstance`. */
|
|
64
64
|
class DialogRef<T> {
|
|
65
|
-
|
|
65
|
+
componentInstance!: T;
|
|
66
66
|
|
|
67
67
|
constructor(private readonly closeFn: () => void) {}
|
|
68
68
|
|
|
@@ -130,7 +130,7 @@ class ZenDialogService {
|
|
|
130
130
|
|
|
131
131
|
this.dialogRef.instance.open.set(true);
|
|
132
132
|
|
|
133
|
-
const { inputs, outputs, ...inputMappings } = config
|
|
133
|
+
const { inputs, outputs, ...inputMappings } = config ?? {};
|
|
134
134
|
|
|
135
135
|
for (const [key, value] of Object.entries(inputMappings)) {
|
|
136
136
|
if (value !== undefined) {
|