@ng-zen/cli 21.0.0 → 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.
- package/CHANGELOG.md +22 -0
- package/README.md +27 -25
- package/package.json +15 -12
- package/schematics/collection.json +5 -5
- package/schematics/dependency-manager/index.js +1 -1
- package/schematics/dependency-manager/index.js.map +1 -1
- package/schematics/dependency-manager/index.ts +1 -1
- package/schematics/dependency-manager/utils/get-dependencies.js.map +1 -1
- package/schematics/dependency-manager/utils/get-dependencies.ts +2 -2
- package/schematics/{components → ui}/files/alert/alert.stories.ts +1 -1
- package/schematics/{components → ui}/files/avatar/avatar.stories.ts +3 -3
- package/schematics/{components → ui}/files/button/button.stories.ts +1 -1
- package/schematics/{components → ui}/files/checkbox/checkbox.stories.ts +1 -1
- package/schematics/{components → ui}/files/divider/divider.stories.ts +2 -2
- package/schematics/{components → ui}/files/form-control/form-control.stories.ts +1 -1
- package/schematics/{components → ui}/files/icon/icon.stories.ts +1 -1
- package/schematics/{components → ui}/files/input/input.stories.ts +1 -1
- package/schematics/ui/files/popover/host/popover-host.scss +76 -0
- package/schematics/ui/files/popover/host/popover-host.spec.ts +20 -0
- package/schematics/ui/files/popover/host/popover-host.ts +38 -0
- package/schematics/ui/files/popover/index.ts +1 -0
- package/schematics/ui/files/popover/popover-positions.type.ts +13 -0
- package/schematics/ui/files/popover/popover.spec.ts +171 -0
- package/schematics/ui/files/popover/popover.stories.ts +66 -0
- package/schematics/ui/files/popover/popover.ts +130 -0
- package/schematics/{components → ui}/files/radio/radio.stories.ts +1 -1
- package/schematics/{components → ui}/files/skeleton/skeleton.stories.ts +1 -1
- package/schematics/{components → ui}/files/switch/switch.stories.ts +1 -1
- package/schematics/{components → ui}/files/textarea/textarea.stories.ts +1 -1
- package/schematics/ui/index.js +27 -0
- package/schematics/ui/index.js.map +1 -0
- package/schematics/ui/index.ts +31 -0
- package/schematics/ui/schema.js.map +1 -0
- package/schematics/{components → ui}/schema.json +15 -6
- package/schematics/{components → ui}/schema.ts +3 -2
- package/schematics/{components → ui}/templates/README.md.template +3 -3
- package/services/selected-elements.js.map +1 -1
- package/services/selected-elements.ts +2 -2
- package/types/files-config.js.map +1 -1
- package/types/files-config.ts +2 -2
- package/types/generator-schema-base.js.map +1 -1
- package/types/generator-schema-base.ts +2 -1
- package/types/schematics-folder.js.map +1 -1
- package/types/schematics-folder.ts +2 -2
- package/utils/apply-file-template.util.js.map +1 -1
- package/utils/apply-file-template.util.ts +1 -1
- package/schematics/components/index.js +0 -16
- package/schematics/components/index.js.map +0 -1
- package/schematics/components/index.ts +0 -16
- package/schematics/components/schema.js.map +0 -1
- /package/schematics/{components → ui}/files/alert/alert.scss +0 -0
- /package/schematics/{components → ui}/files/alert/alert.spec.ts +0 -0
- /package/schematics/{components → ui}/files/alert/alert.ts +0 -0
- /package/schematics/{components → ui}/files/alert/index.ts +0 -0
- /package/schematics/{components → ui}/files/avatar/avatar.scss +0 -0
- /package/schematics/{components → ui}/files/avatar/avatar.spec.ts +0 -0
- /package/schematics/{components → ui}/files/avatar/avatar.ts +0 -0
- /package/schematics/{components → ui}/files/avatar/index.ts +0 -0
- /package/schematics/{components → ui}/files/button/button.scss +0 -0
- /package/schematics/{components → ui}/files/button/button.spec.ts +0 -0
- /package/schematics/{components → ui}/files/button/button.ts +0 -0
- /package/schematics/{components → ui}/files/button/index.ts +0 -0
- /package/schematics/{components → ui}/files/checkbox/checkbox.scss +0 -0
- /package/schematics/{components → ui}/files/checkbox/checkbox.spec.ts +0 -0
- /package/schematics/{components → ui}/files/checkbox/checkbox.ts +0 -0
- /package/schematics/{components → ui}/files/checkbox/index.ts +0 -0
- /package/schematics/{components → ui}/files/divider/divider.scss +0 -0
- /package/schematics/{components → ui}/files/divider/divider.spec.ts +0 -0
- /package/schematics/{components → ui}/files/divider/divider.ts +0 -0
- /package/schematics/{components → ui}/files/divider/index.ts +0 -0
- /package/schematics/{components → ui}/files/form-control/form-control.spec.ts +0 -0
- /package/schematics/{components → ui}/files/form-control/form-control.ts +0 -0
- /package/schematics/{components → ui}/files/form-control/index.ts +0 -0
- /package/schematics/{components → ui}/files/icon/icon.spec.ts +0 -0
- /package/schematics/{components → ui}/files/icon/icon.ts +0 -0
- /package/schematics/{components → ui}/files/icon/index.ts +0 -0
- /package/schematics/{components → ui}/files/input/index.ts +0 -0
- /package/schematics/{components → ui}/files/input/input.scss +0 -0
- /package/schematics/{components → ui}/files/input/input.spec.ts +0 -0
- /package/schematics/{components → ui}/files/input/input.ts +0 -0
- /package/schematics/{components → ui}/files/radio/index.ts +0 -0
- /package/schematics/{components → ui}/files/radio/radio.registry.ts +0 -0
- /package/schematics/{components → ui}/files/radio/radio.scss +0 -0
- /package/schematics/{components → ui}/files/radio/radio.spec.ts +0 -0
- /package/schematics/{components → ui}/files/radio/radio.ts +0 -0
- /package/schematics/{components → ui}/files/skeleton/index.ts +0 -0
- /package/schematics/{components → ui}/files/skeleton/skeleton.scss +0 -0
- /package/schematics/{components → ui}/files/skeleton/skeleton.spec.ts +0 -0
- /package/schematics/{components → ui}/files/skeleton/skeleton.ts +0 -0
- /package/schematics/{components → ui}/files/switch/index.ts +0 -0
- /package/schematics/{components → ui}/files/switch/switch.scss +0 -0
- /package/schematics/{components → ui}/files/switch/switch.spec.ts +0 -0
- /package/schematics/{components → ui}/files/switch/switch.ts +0 -0
- /package/schematics/{components → ui}/files/textarea/index.ts +0 -0
- /package/schematics/{components → ui}/files/textarea/textarea.scss +0 -0
- /package/schematics/{components → ui}/files/textarea/textarea.spec.ts +0 -0
- /package/schematics/{components → ui}/files/textarea/textarea.ts +0 -0
- /package/schematics/{components → ui}/schema.js +0 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { Component, provideZonelessChangeDetection, TemplateRef, ViewChild } from '@angular/core';
|
|
2
|
+
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
3
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
4
|
+
|
|
5
|
+
import { ZenPopover } from './popover';
|
|
6
|
+
|
|
7
|
+
@Component({
|
|
8
|
+
template: `
|
|
9
|
+
<button [zenPopover]="content" id="trigger-btn" zenPopoverPlacement="bottom">Trigger</button>
|
|
10
|
+
|
|
11
|
+
<ng-template #content>Popover content</ng-template>
|
|
12
|
+
`,
|
|
13
|
+
standalone: true,
|
|
14
|
+
imports: [ZenPopover],
|
|
15
|
+
})
|
|
16
|
+
class TemplateBottomComponent {
|
|
17
|
+
@ViewChild('content', { static: true }) content!: TemplateRef<unknown>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@Component({
|
|
21
|
+
template: `
|
|
22
|
+
<button [zenPopover]="content" id="trigger-btn" zenPopoverPlacement="left">Trigger</button>
|
|
23
|
+
|
|
24
|
+
<ng-template #content>Popover content</ng-template>
|
|
25
|
+
`,
|
|
26
|
+
standalone: true,
|
|
27
|
+
imports: [ZenPopover],
|
|
28
|
+
})
|
|
29
|
+
class TemplateLeftComponent {
|
|
30
|
+
@ViewChild('content', { static: true }) content!: TemplateRef<unknown>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@Component({
|
|
34
|
+
template: `
|
|
35
|
+
<button [zenPopover]="'String content'" id="trigger-btn">Trigger</button>
|
|
36
|
+
`,
|
|
37
|
+
standalone: true,
|
|
38
|
+
imports: [ZenPopover],
|
|
39
|
+
})
|
|
40
|
+
class StringContentComponent {}
|
|
41
|
+
|
|
42
|
+
function getPopoverHostEl(fixture: ComponentFixture<unknown>): HTMLElement | null {
|
|
43
|
+
return fixture.nativeElement.querySelector('[popover="auto"]') as HTMLElement | null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
describe('ZenPopover', () => {
|
|
47
|
+
beforeEach(() => {
|
|
48
|
+
HTMLElement.prototype.showPopover = vi.fn();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
describe('TemplateRef content', () => {
|
|
52
|
+
beforeEach(async () => {
|
|
53
|
+
await TestBed.configureTestingModule({
|
|
54
|
+
imports: [TemplateBottomComponent],
|
|
55
|
+
providers: [provideZonelessChangeDetection()],
|
|
56
|
+
}).compileComponents();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('does not create another host on second click while open', () => {
|
|
60
|
+
const fixture = TestBed.createComponent(TemplateBottomComponent);
|
|
61
|
+
fixture.detectChanges();
|
|
62
|
+
|
|
63
|
+
const trigger = fixture.nativeElement.querySelector('#trigger-btn') as HTMLButtonElement;
|
|
64
|
+
|
|
65
|
+
trigger.click();
|
|
66
|
+
fixture.detectChanges();
|
|
67
|
+
|
|
68
|
+
const host1 = getPopoverHostEl(fixture)!;
|
|
69
|
+
expect(host1).toBeTruthy();
|
|
70
|
+
|
|
71
|
+
trigger.click();
|
|
72
|
+
fixture.detectChanges();
|
|
73
|
+
|
|
74
|
+
expect(fixture.nativeElement.querySelectorAll('[popover="auto"]').length).toBe(1);
|
|
75
|
+
expect(getPopoverHostEl(fixture)).toBe(host1);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('creates host on click and calls showPopover()', () => {
|
|
79
|
+
const fixture = TestBed.createComponent(TemplateBottomComponent);
|
|
80
|
+
fixture.detectChanges();
|
|
81
|
+
|
|
82
|
+
fixture.nativeElement.querySelector('#trigger-btn').click();
|
|
83
|
+
fixture.detectChanges();
|
|
84
|
+
|
|
85
|
+
const host = getPopoverHostEl(fixture)!;
|
|
86
|
+
expect(host.showPopover).toHaveBeenCalledTimes(1);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('renders TemplateRef content into host', () => {
|
|
90
|
+
const fixture = TestBed.createComponent(TemplateBottomComponent);
|
|
91
|
+
fixture.detectChanges();
|
|
92
|
+
|
|
93
|
+
fixture.nativeElement.querySelector('#trigger-btn').click();
|
|
94
|
+
fixture.detectChanges();
|
|
95
|
+
|
|
96
|
+
expect(getPopoverHostEl(fixture)!.textContent).toContain('Popover content');
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('passes placement to host as data-placement (bottom)', () => {
|
|
100
|
+
const fixture = TestBed.createComponent(TemplateBottomComponent);
|
|
101
|
+
fixture.detectChanges();
|
|
102
|
+
|
|
103
|
+
fixture.nativeElement.querySelector('#trigger-btn').click();
|
|
104
|
+
fixture.detectChanges();
|
|
105
|
+
|
|
106
|
+
expect(getPopoverHostEl(fixture)!.getAttribute('data-placement')).toBe('bottom');
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('sets anchor styles on trigger and host', () => {
|
|
110
|
+
const fixture = TestBed.createComponent(TemplateBottomComponent);
|
|
111
|
+
fixture.detectChanges();
|
|
112
|
+
|
|
113
|
+
const trigger = fixture.nativeElement.querySelector('#trigger-btn') as HTMLButtonElement;
|
|
114
|
+
trigger.click();
|
|
115
|
+
fixture.detectChanges();
|
|
116
|
+
|
|
117
|
+
const host = getPopoverHostEl(fixture)!;
|
|
118
|
+
|
|
119
|
+
expect(trigger.style.getPropertyValue('anchor-name')).toMatch(/^--anchor-/);
|
|
120
|
+
expect(host.style.getPropertyValue('position-anchor')).toBe(trigger.style.getPropertyValue('anchor-name'));
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('destroys host when beforetoggle closes', () => {
|
|
124
|
+
const fixture = TestBed.createComponent(TemplateBottomComponent);
|
|
125
|
+
fixture.detectChanges();
|
|
126
|
+
|
|
127
|
+
fixture.nativeElement.querySelector('#trigger-btn').click();
|
|
128
|
+
fixture.detectChanges();
|
|
129
|
+
|
|
130
|
+
const host = getPopoverHostEl(fixture)!;
|
|
131
|
+
|
|
132
|
+
const ev = new Event('beforetoggle');
|
|
133
|
+
Object.defineProperty(ev, 'newState', { value: 'closed' });
|
|
134
|
+
|
|
135
|
+
host.dispatchEvent(ev);
|
|
136
|
+
fixture.detectChanges();
|
|
137
|
+
|
|
138
|
+
expect(getPopoverHostEl(fixture)).toBeNull();
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('reflects placement as data-placement (left)', async () => {
|
|
143
|
+
await TestBed.configureTestingModule({
|
|
144
|
+
imports: [TemplateLeftComponent],
|
|
145
|
+
providers: [provideZonelessChangeDetection()],
|
|
146
|
+
}).compileComponents();
|
|
147
|
+
|
|
148
|
+
const fixture = TestBed.createComponent(TemplateLeftComponent);
|
|
149
|
+
fixture.detectChanges();
|
|
150
|
+
|
|
151
|
+
fixture.nativeElement.querySelector('#trigger-btn').click();
|
|
152
|
+
fixture.detectChanges();
|
|
153
|
+
|
|
154
|
+
expect(getPopoverHostEl(fixture)!.getAttribute('data-placement')).toBe('left');
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it('renders string content as text node in host', async () => {
|
|
158
|
+
await TestBed.configureTestingModule({
|
|
159
|
+
imports: [StringContentComponent],
|
|
160
|
+
providers: [provideZonelessChangeDetection()],
|
|
161
|
+
}).compileComponents();
|
|
162
|
+
|
|
163
|
+
const fixture = TestBed.createComponent(StringContentComponent);
|
|
164
|
+
fixture.detectChanges();
|
|
165
|
+
|
|
166
|
+
fixture.nativeElement.querySelector('#trigger-btn').click();
|
|
167
|
+
fixture.detectChanges();
|
|
168
|
+
|
|
169
|
+
expect(getPopoverHostEl(fixture)!.textContent).toContain('String content');
|
|
170
|
+
});
|
|
171
|
+
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { argsToTemplate, Meta, moduleMetadata, StoryObj } from '@storybook/angular';
|
|
2
|
+
|
|
3
|
+
import { ZenButton } from '../button';
|
|
4
|
+
import { ZenPopover } from './popover';
|
|
5
|
+
import type { PopoverPlacement } from './popover-positions.type';
|
|
6
|
+
|
|
7
|
+
type Story = StoryObj<ZenPopover>;
|
|
8
|
+
|
|
9
|
+
const meta = {
|
|
10
|
+
title: 'Ui/Popover',
|
|
11
|
+
component: ZenPopover,
|
|
12
|
+
decorators: [
|
|
13
|
+
moduleMetadata({
|
|
14
|
+
imports: [ZenButton, ZenPopover],
|
|
15
|
+
}),
|
|
16
|
+
],
|
|
17
|
+
argTypes: {
|
|
18
|
+
placement: {
|
|
19
|
+
name: 'zenPopoverPlacement',
|
|
20
|
+
control: 'select',
|
|
21
|
+
options: [
|
|
22
|
+
'top',
|
|
23
|
+
'top-start',
|
|
24
|
+
'top-end',
|
|
25
|
+
'bottom',
|
|
26
|
+
'bottom-start',
|
|
27
|
+
'bottom-end',
|
|
28
|
+
'left',
|
|
29
|
+
'left-start',
|
|
30
|
+
'left-end',
|
|
31
|
+
'right',
|
|
32
|
+
'right-start',
|
|
33
|
+
'right-end',
|
|
34
|
+
] satisfies PopoverPlacement[],
|
|
35
|
+
table: {
|
|
36
|
+
category: 'inputs',
|
|
37
|
+
type: {
|
|
38
|
+
summary: 'string',
|
|
39
|
+
},
|
|
40
|
+
defaultValue: {
|
|
41
|
+
summary: 'top' satisfies PopoverPlacement,
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
id: { control: 'text', table: { defaultValue: { summary: 'zen-popover-*X*' } } },
|
|
46
|
+
content: { name: 'zenPopover', control: 'text' },
|
|
47
|
+
},
|
|
48
|
+
args: {
|
|
49
|
+
placement: 'top',
|
|
50
|
+
id: 'zen-popover-story',
|
|
51
|
+
content: 'This is a popover',
|
|
52
|
+
},
|
|
53
|
+
} satisfies Meta<ZenPopover>;
|
|
54
|
+
|
|
55
|
+
export default meta;
|
|
56
|
+
|
|
57
|
+
export const Default: Story = {
|
|
58
|
+
render: ({ content, placement, ...args }) => ({
|
|
59
|
+
props: args,
|
|
60
|
+
template: `
|
|
61
|
+
<button zen-btn [zenPopover]="'${content as string}'" [zenPopoverPlacement]="'${placement}'" ${argsToTemplate(args)}>
|
|
62
|
+
Toggle
|
|
63
|
+
</button>
|
|
64
|
+
`,
|
|
65
|
+
}),
|
|
66
|
+
};
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ComponentRef,
|
|
3
|
+
Directive,
|
|
4
|
+
effect,
|
|
5
|
+
ElementRef,
|
|
6
|
+
EmbeddedViewRef,
|
|
7
|
+
inject,
|
|
8
|
+
input,
|
|
9
|
+
Renderer2,
|
|
10
|
+
TemplateRef,
|
|
11
|
+
ViewContainerRef,
|
|
12
|
+
} from '@angular/core';
|
|
13
|
+
|
|
14
|
+
import { ZenPopoverHost } from './host/popover-host';
|
|
15
|
+
import { PopoverPlacement } from './popover-positions.type';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* ZenPopover is a reusable popover directive built on the native Popover API.
|
|
19
|
+
* It provides a consistent, themeable popover surface with CSS-based positioning,
|
|
20
|
+
* animations, and multiple trigger modes.
|
|
21
|
+
*
|
|
22
|
+
* ### Limitations (arrow)
|
|
23
|
+
* ZenPopover may use CSS fallback positioning (e.g. via `position-try-fallbacks`) to keep the
|
|
24
|
+
* popover inside the viewport. Today CSS doesn’t provide a stable, cross-browser way to detect
|
|
25
|
+
* which fallback placement was ultimately chosen, so an “arrow” implemented with `::before/::after`
|
|
26
|
+
* can’t be reliably synchronized with the final placement without extra JavaScript.
|
|
27
|
+
* A CSS-only solution becomes possible with Anchored Container Queries (e.g. `container-type: anchored`
|
|
28
|
+
* and `@container anchored(fallback: ...)`) where supported.
|
|
29
|
+
*
|
|
30
|
+
* @see https://developer.chrome.com/blog/anchored-container-queries
|
|
31
|
+
*
|
|
32
|
+
* ### CSS Custom Properties
|
|
33
|
+
* You can customize the popover using CSS custom properties (see component styles/docs).
|
|
34
|
+
*
|
|
35
|
+
* @author Konrad Stępień
|
|
36
|
+
* @license {@link https://github.com/kstepien3/ng-zen/blob/master/LICENSE|BSD-2-Clause}
|
|
37
|
+
* @see [GitHub](https://github.com/kstepien3/ng-zen)
|
|
38
|
+
* @see [MDN Popover API](https://developer.mozilla.org/en-US/docs/Web/API/Popover_API)
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
type HostProperties = keyof ZenPopoverHost;
|
|
42
|
+
|
|
43
|
+
@Directive({
|
|
44
|
+
selector: '[zenPopover]',
|
|
45
|
+
standalone: true,
|
|
46
|
+
host: {
|
|
47
|
+
'(click)': 'togglePopover()',
|
|
48
|
+
},
|
|
49
|
+
})
|
|
50
|
+
export class ZenPopover {
|
|
51
|
+
private static uniqueId = 0;
|
|
52
|
+
|
|
53
|
+
/** Content to display inside the popover. Can be a `string` or a `TemplateRef`.*/
|
|
54
|
+
readonly content = input.required<TemplateRef<unknown> | string>({ alias: 'zenPopover' });
|
|
55
|
+
/** Placement of the popover relative to the trigger element. Defaults to `top`.*/
|
|
56
|
+
readonly placement = input<PopoverPlacement>('top', { alias: 'zenPopoverPlacement' });
|
|
57
|
+
/** The HTML id attribute is used to specify a unique id for an HTML element.*/
|
|
58
|
+
readonly id = input<string>(`zen-popover-${ZenPopover.uniqueId++}`);
|
|
59
|
+
|
|
60
|
+
private hostRef: ComponentRef<ZenPopoverHost> | null = null;
|
|
61
|
+
private viewRef: EmbeddedViewRef<unknown> | null = null;
|
|
62
|
+
|
|
63
|
+
private unlistenToggle: (() => void) | null = null;
|
|
64
|
+
|
|
65
|
+
private readonly anchorName = `--anchor-${this.id()}`;
|
|
66
|
+
|
|
67
|
+
private readonly vcr = inject(ViewContainerRef);
|
|
68
|
+
private readonly renderer = inject(Renderer2);
|
|
69
|
+
private readonly triggerEl = inject(ElementRef).nativeElement;
|
|
70
|
+
|
|
71
|
+
constructor() {
|
|
72
|
+
effect(onCleanup => {
|
|
73
|
+
onCleanup(() => {
|
|
74
|
+
this.destroyPopover();
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
protected togglePopover(): void {
|
|
80
|
+
if (this.hostRef) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const popoverEl = this.createHost();
|
|
85
|
+
this.renderContent(popoverEl);
|
|
86
|
+
this.unlistenToggle = this.renderer.listen(popoverEl, 'beforetoggle', (event: ToggleEvent) => {
|
|
87
|
+
if (event.newState === 'closed') {
|
|
88
|
+
this.destroyPopover();
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
popoverEl.showPopover();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
private createHost(): HTMLElement {
|
|
96
|
+
this.renderer.setStyle(this.triggerEl, 'anchor-name', this.anchorName);
|
|
97
|
+
|
|
98
|
+
this.hostRef = this.vcr.createComponent(ZenPopoverHost);
|
|
99
|
+
this.hostRef.setInput('id' satisfies HostProperties, this.id());
|
|
100
|
+
this.hostRef.setInput('placement' satisfies HostProperties, this.placement());
|
|
101
|
+
|
|
102
|
+
const popoverEl = this.hostRef.location.nativeElement as HTMLElement;
|
|
103
|
+
this.renderer.setStyle(popoverEl, 'position-anchor', this.anchorName);
|
|
104
|
+
|
|
105
|
+
return popoverEl;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
private renderContent(popoverEl: HTMLElement) {
|
|
109
|
+
const contentValue = this.content();
|
|
110
|
+
if (contentValue instanceof TemplateRef) {
|
|
111
|
+
this.viewRef = contentValue.createEmbeddedView({});
|
|
112
|
+
this.renderer.appendChild(popoverEl, this.viewRef.rootNodes[0]);
|
|
113
|
+
} else {
|
|
114
|
+
this.renderer.appendChild(popoverEl, this.renderer.createText(contentValue));
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
private destroyPopover() {
|
|
119
|
+
if (this.unlistenToggle) {
|
|
120
|
+
this.unlistenToggle();
|
|
121
|
+
this.unlistenToggle = null;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
this.viewRef?.destroy();
|
|
125
|
+
this.hostRef?.destroy();
|
|
126
|
+
this.viewRef = null;
|
|
127
|
+
this.hostRef = null;
|
|
128
|
+
this.vcr.clear();
|
|
129
|
+
}
|
|
130
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.uiGenerator = uiGenerator;
|
|
4
|
+
const core_1 = require("@angular-devkit/core");
|
|
5
|
+
const schematics_1 = require("@angular-devkit/schematics");
|
|
6
|
+
const workspace_1 = require("@schematics/angular/utility/workspace");
|
|
7
|
+
const utils_1 = require("../../utils");
|
|
8
|
+
const DEFAULT_GENERATION_PATH = 'ui'; // src/app/ui
|
|
9
|
+
function uiGenerator({ ui, project, ...options }) {
|
|
10
|
+
return async (tree) => {
|
|
11
|
+
const workspace = await (0, workspace_1.getWorkspace)(tree);
|
|
12
|
+
const projectName = project || workspace.extensions['defaultProject'];
|
|
13
|
+
const projectObj = workspace.projects.get(projectName);
|
|
14
|
+
if (!projectObj) {
|
|
15
|
+
throw new Error(`Project "${projectName}" not found in workspace.`);
|
|
16
|
+
}
|
|
17
|
+
if (options.path === undefined) {
|
|
18
|
+
options.path = ((0, workspace_1.buildDefaultPath)(projectObj) + '/' + DEFAULT_GENERATION_PATH);
|
|
19
|
+
}
|
|
20
|
+
const workingDirectory = (0, core_1.normalize)((0, core_1.join)(options.currentDirectory, options.path));
|
|
21
|
+
return (0, schematics_1.chain)([
|
|
22
|
+
...(0, utils_1.applyFileTemplateUtil)(ui, { ...options, path: workingDirectory }),
|
|
23
|
+
(0, schematics_1.schematic)('dependency-manager', {}),
|
|
24
|
+
]);
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/schematics/ui/index.ts"],"names":[],"mappings":";;AASA,kCAqBC;AA9BD,+CAA6D;AAC7D,2DAA0E;AAC1E,qEAAuF;AAEvF,uCAAoD;AAGpD,MAAM,uBAAuB,GAAG,IAAI,CAAC,CAAC,aAAa;AAEnD,SAAgB,WAAW,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,OAAO,EAAa;IAChE,OAAO,KAAK,EAAE,IAAU,EAAE,EAAE;QAC1B,MAAM,SAAS,GAAG,MAAM,IAAA,wBAAY,EAAC,IAAI,CAAC,CAAC;QAC3C,MAAM,WAAW,GAAG,OAAO,IAAK,SAAS,CAAC,UAAU,CAAC,gBAAgB,CAAY,CAAC;QAClF,MAAM,UAAU,GAAG,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAEvD,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CAAC,YAAY,WAAW,2BAA2B,CAAC,CAAC;QACtE,CAAC;QAED,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC/B,OAAO,CAAC,IAAI,GAAG,CAAC,IAAA,4BAAgB,EAAC,UAAU,CAAC,GAAG,GAAG,GAAG,uBAAuB,CAAS,CAAC;QACxF,CAAC;QAED,MAAM,gBAAgB,GAAG,IAAA,gBAAS,EAAC,IAAA,WAAI,EAAC,OAAO,CAAC,gBAAgB,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QAEjF,OAAO,IAAA,kBAAK,EAAC;YACX,GAAG,IAAA,6BAAqB,EAAC,EAAE,EAAE,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC;YACpE,IAAA,sBAAS,EAAC,oBAAoB,EAAE,EAAE,CAAC;SACpC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import { join, normalize, Path } from '@angular-devkit/core';\nimport { chain, Rule, schematic, Tree } from '@angular-devkit/schematics';\nimport { buildDefaultPath, getWorkspace } from '@schematics/angular/utility/workspace';\n\nimport { applyFileTemplateUtil } from '../../utils';\nimport { Schema as UiOptions } from './schema';\n\nconst DEFAULT_GENERATION_PATH = 'ui'; // src/app/ui\n\nexport function uiGenerator({ ui, project, ...options }: UiOptions): Rule {\n return async (tree: Tree) => {\n const workspace = await getWorkspace(tree);\n const projectName = project || (workspace.extensions['defaultProject'] as string);\n const projectObj = workspace.projects.get(projectName);\n\n if (!projectObj) {\n throw new Error(`Project \"${projectName}\" not found in workspace.`);\n }\n\n if (options.path === undefined) {\n options.path = (buildDefaultPath(projectObj) + '/' + DEFAULT_GENERATION_PATH) as Path;\n }\n\n const workingDirectory = normalize(join(options.currentDirectory, options.path));\n\n return chain([\n ...applyFileTemplateUtil(ui, { ...options, path: workingDirectory }),\n schematic('dependency-manager', {}),\n ]);\n };\n}\n"]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { join, normalize, Path } from '@angular-devkit/core';
|
|
2
|
+
import { chain, Rule, schematic, Tree } from '@angular-devkit/schematics';
|
|
3
|
+
import { buildDefaultPath, getWorkspace } from '@schematics/angular/utility/workspace';
|
|
4
|
+
|
|
5
|
+
import { applyFileTemplateUtil } from '../../utils';
|
|
6
|
+
import { Schema as UiOptions } from './schema';
|
|
7
|
+
|
|
8
|
+
const DEFAULT_GENERATION_PATH = 'ui'; // src/app/ui
|
|
9
|
+
|
|
10
|
+
export function uiGenerator({ ui, project, ...options }: UiOptions): Rule {
|
|
11
|
+
return async (tree: Tree) => {
|
|
12
|
+
const workspace = await getWorkspace(tree);
|
|
13
|
+
const projectName = project || (workspace.extensions['defaultProject'] as string);
|
|
14
|
+
const projectObj = workspace.projects.get(projectName);
|
|
15
|
+
|
|
16
|
+
if (!projectObj) {
|
|
17
|
+
throw new Error(`Project "${projectName}" not found in workspace.`);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (options.path === undefined) {
|
|
21
|
+
options.path = (buildDefaultPath(projectObj) + '/' + DEFAULT_GENERATION_PATH) as Path;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const workingDirectory = normalize(join(options.currentDirectory, options.path));
|
|
25
|
+
|
|
26
|
+
return chain([
|
|
27
|
+
...applyFileTemplateUtil(ui, { ...options, path: workingDirectory }),
|
|
28
|
+
schematic('dependency-manager', {}),
|
|
29
|
+
]);
|
|
30
|
+
};
|
|
31
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../../../src/schematics/ui/schema.ts"],"names":[],"mappings":"","sourcesContent":["import { GeneratorSchemaBase } from '../../types';\n\nexport type UiType =\n | 'alert'\n | 'avatar'\n | 'button'\n | 'checkbox'\n | 'divider'\n | 'form-control'\n | 'icon'\n | 'input'\n | 'popover'\n | 'radio'\n | 'skeleton'\n | 'switch'\n | 'textarea';\n\nexport interface Schema extends GeneratorSchemaBase {\n ui: UiType[];\n}\n"]}
|
|
@@ -16,15 +16,23 @@
|
|
|
16
16
|
"readOnly": true
|
|
17
17
|
},
|
|
18
18
|
"path": {
|
|
19
|
-
"description": "
|
|
19
|
+
"description": "The path at which to create the component file, relative to the current workspace. If not provided, components will be generated in the 'ui' folder within the project's source directory (e.g., src/app/ui).",
|
|
20
20
|
"type": "string",
|
|
21
|
+
"format": "path",
|
|
21
22
|
"$default": {
|
|
22
23
|
"$source": "argv",
|
|
23
24
|
"index": 0
|
|
24
25
|
}
|
|
25
26
|
},
|
|
26
|
-
"
|
|
27
|
-
"description": "
|
|
27
|
+
"project": {
|
|
28
|
+
"description": "The name of the project",
|
|
29
|
+
"type": "string",
|
|
30
|
+
"$default": {
|
|
31
|
+
"$source": "projectName"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"ui": {
|
|
35
|
+
"description": "Select elements to generate",
|
|
28
36
|
"type": "array",
|
|
29
37
|
"items": {
|
|
30
38
|
"type": "string",
|
|
@@ -37,6 +45,7 @@
|
|
|
37
45
|
"form-control",
|
|
38
46
|
"icon",
|
|
39
47
|
"input",
|
|
48
|
+
"popover",
|
|
40
49
|
"radio",
|
|
41
50
|
"skeleton",
|
|
42
51
|
"switch",
|
|
@@ -45,13 +54,13 @@
|
|
|
45
54
|
},
|
|
46
55
|
"multiselect": true,
|
|
47
56
|
"minItems": 1,
|
|
48
|
-
"x-prompt": "Which
|
|
57
|
+
"x-prompt": "Which ui elements should be generated?"
|
|
49
58
|
},
|
|
50
59
|
"stories": {
|
|
51
|
-
"description": "Include
|
|
60
|
+
"description": "Include stories for better documentation and testing",
|
|
52
61
|
"type": "boolean",
|
|
53
62
|
"default": false
|
|
54
63
|
}
|
|
55
64
|
},
|
|
56
|
-
"required": ["
|
|
65
|
+
"required": ["ui"]
|
|
57
66
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { GeneratorSchemaBase } from '../../types';
|
|
2
2
|
|
|
3
|
-
export type
|
|
3
|
+
export type UiType =
|
|
4
4
|
| 'alert'
|
|
5
5
|
| 'avatar'
|
|
6
6
|
| 'button'
|
|
@@ -9,11 +9,12 @@ export type ComponentType =
|
|
|
9
9
|
| 'form-control'
|
|
10
10
|
| 'icon'
|
|
11
11
|
| 'input'
|
|
12
|
+
| 'popover'
|
|
12
13
|
| 'radio'
|
|
13
14
|
| 'skeleton'
|
|
14
15
|
| 'switch'
|
|
15
16
|
| 'textarea';
|
|
16
17
|
|
|
17
18
|
export interface Schema extends GeneratorSchemaBase {
|
|
18
|
-
|
|
19
|
+
ui: UiType[];
|
|
19
20
|
}
|
|
@@ -8,14 +8,14 @@ Generated by `@ng-zen/cli` on <%= localeDate %>
|
|
|
8
8
|
|
|
9
9
|
<%= classify(name) %> component was generated by
|
|
10
10
|
```bash
|
|
11
|
-
ng generate @ng-zen/cli:
|
|
11
|
+
ng generate @ng-zen/cli:ui --ui <%= name %>
|
|
12
12
|
```
|
|
13
13
|
|
|
14
14
|
This component is part of a larger set of UI components aimed at enhancing and streamlining the development process in Angular applications.
|
|
15
15
|
|
|
16
16
|
More information you can find here
|
|
17
17
|
```bash
|
|
18
|
-
ng generate @ng-zen/cli:
|
|
18
|
+
ng generate @ng-zen/cli:ui --help
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
## Installation
|
|
@@ -27,7 +27,7 @@ ng add @ng-zen/cli
|
|
|
27
27
|
|
|
28
28
|
then you can generate components via
|
|
29
29
|
```bash
|
|
30
|
-
ng generate @ng-zen/cli:
|
|
30
|
+
ng generate @ng-zen/cli:ui
|
|
31
31
|
```
|
|
32
32
|
|
|
33
33
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selected-elements.js","sourceRoot":"","sources":["../../../../src/services/selected-elements.ts"],"names":[],"mappings":";;;AAEA,qFAAqF;AACxE,QAAA,gBAAgB,
|
|
1
|
+
{"version":3,"file":"selected-elements.js","sourceRoot":"","sources":["../../../../src/services/selected-elements.ts"],"names":[],"mappings":";;;AAEA,qFAAqF;AACxE,QAAA,gBAAgB,GAAa,EAAE,CAAC","sourcesContent":["import { UiType } from '../schematics/ui/schema';\n\n// add selected elements to this array, then values are available in other schematics\nexport const selectedElements: UiType[] = [];\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { UiType } from '../schematics/ui/schema';
|
|
2
2
|
|
|
3
3
|
// add selected elements to this array, then values are available in other schematics
|
|
4
|
-
export const selectedElements:
|
|
4
|
+
export const selectedElements: UiType[] = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"files-config.js","sourceRoot":"","sources":["../../../../src/types/files-config.ts"],"names":[],"mappings":"","sourcesContent":["import { NodeDependencyType } from '@schematics/angular/utility/dependencies';\n\nimport {
|
|
1
|
+
{"version":3,"file":"files-config.js","sourceRoot":"","sources":["../../../../src/types/files-config.ts"],"names":[],"mappings":"","sourcesContent":["import { NodeDependencyType } from '@schematics/angular/utility/dependencies';\n\nimport { UiType } from '../schematics/ui/schema';\n\ntype Kind = Record<NodeDependencyType, Record<string, string>>;\n\nexport type FilesConfig = Record<UiType, Partial<Kind>>;\n"]}
|
package/types/files-config.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { NodeDependencyType } from '@schematics/angular/utility/dependencies';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { UiType } from '../schematics/ui/schema';
|
|
4
4
|
|
|
5
5
|
type Kind = Record<NodeDependencyType, Record<string, string>>;
|
|
6
6
|
|
|
7
|
-
export type FilesConfig = Record<
|
|
7
|
+
export type FilesConfig = Record<UiType, Partial<Kind>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generator-schema-base.js","sourceRoot":"","sources":["../../../../src/types/generator-schema-base.ts"],"names":[],"mappings":"","sourcesContent":["import { Path } from '@angular-devkit/core';\n\nexport interface GeneratorSchemaBase {\n currentDirectory: Path;\n path
|
|
1
|
+
{"version":3,"file":"generator-schema-base.js","sourceRoot":"","sources":["../../../../src/types/generator-schema-base.ts"],"names":[],"mappings":"","sourcesContent":["import { Path } from '@angular-devkit/core';\n\nexport interface GeneratorSchemaBase {\n currentDirectory: Path;\n path?: Path;\n stories: boolean;\n project?: string;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schematics-folder.js","sourceRoot":"","sources":["../../../../src/types/schematics-folder.ts"],"names":[],"mappings":"","sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"schematics-folder.js","sourceRoot":"","sources":["../../../../src/types/schematics-folder.ts"],"names":[],"mappings":"","sourcesContent":["import { UiType } from '../schematics/ui/schema';\n\nexport type SchematicsFolder = UiType;\n"]}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { UiType } from '../schematics/ui/schema';
|
|
2
2
|
|
|
3
|
-
export type SchematicsFolder =
|
|
3
|
+
export type SchematicsFolder = UiType;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apply-file-template.util.js","sourceRoot":"","sources":["../../../../src/utils/apply-file-template.util.ts"],"names":[],"mappings":";;AAkBA,sDASC;AA3BD,+CAA0D;AAC1D,2DAA8G;AAE9G,qEAAiE;AAGjE,MAAM,mBAAmB,GAAG,CAAC,MAAc,EAAE,IAAY,EAAU,EAAE,CAAC;IACpE,IAAA,2BAAc,EAAC;QACb,IAAI,EAAE,MAAM;QACZ,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,cAAc,EAAE;QACvC,GAAG,cAAO;KACX,CAAC;IACF,IAAA,iBAAI,EAAC,IAAA,gBAAS,EAAC,GAAG,IAAI,IAAI,MAAM,EAAE,CAAC,CAAC;CACrC,CAAC;AAEF,MAAM,YAAY,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,IAAA,kBAAK,EAAC,IAAA,gBAAG,EAAC,aAAa,CAAC,EAAE,KAAK,CAAC,CAAC;AACzE,MAAM,cAAc,GAAG,CAAC,OAAgB,EAAE,EAAE,CAAC,IAAA,mBAAM,EAAC,QAAQ,CAAC,EAAE,CAAC,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC;AAE9G,SAAgB,qBAAqB,CAAC,OAA2B,EAAE,MAA2B;IAC5F,oCAAgB,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC;IAClC,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE;QAC1B,MAAM,KAAK,GAAG,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"apply-file-template.util.js","sourceRoot":"","sources":["../../../../src/utils/apply-file-template.util.ts"],"names":[],"mappings":";;AAkBA,sDASC;AA3BD,+CAA0D;AAC1D,2DAA8G;AAE9G,qEAAiE;AAGjE,MAAM,mBAAmB,GAAG,CAAC,MAAc,EAAE,IAAY,EAAU,EAAE,CAAC;IACpE,IAAA,2BAAc,EAAC;QACb,IAAI,EAAE,MAAM;QACZ,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,cAAc,EAAE;QACvC,GAAG,cAAO;KACX,CAAC;IACF,IAAA,iBAAI,EAAC,IAAA,gBAAS,EAAC,GAAG,IAAI,IAAI,MAAM,EAAE,CAAC,CAAC;CACrC,CAAC;AAEF,MAAM,YAAY,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,IAAA,kBAAK,EAAC,IAAA,gBAAG,EAAC,aAAa,CAAC,EAAE,KAAK,CAAC,CAAC;AACzE,MAAM,cAAc,GAAG,CAAC,OAAgB,EAAE,EAAE,CAAC,IAAA,mBAAM,EAAC,QAAQ,CAAC,EAAE,CAAC,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC;AAE9G,SAAgB,qBAAqB,CAAC,OAA2B,EAAE,MAA2B;IAC5F,oCAAgB,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC;IAClC,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE;QAC1B,MAAM,KAAK,GAAG,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,IAAc,CAAC,CAAC;QAEjE,MAAM,YAAY,GAAG,IAAA,kBAAK,EAAC,IAAA,gBAAG,EAAC,WAAW,MAAM,EAAE,CAAC,EAAE,CAAC,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC;QAEjG,OAAO,IAAA,kBAAK,EAAC,CAAC,YAAY,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,sBAAS,CAAC,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { normalize, strings } from '@angular-devkit/core';\nimport { apply, applyTemplates, chain, filter, mergeWith, move, Rule, url } from '@angular-devkit/schematics';\n\nimport { selectedElements } from '../services/selected-elements';\nimport { GeneratorSchemaBase, SchematicsFolder } from '../types';\n\nconst createTemplateRules = (folder: string, path: string): Rule[] => [\n applyTemplates({\n name: folder,\n localeDate: new Date().toLocaleString(),\n ...strings,\n }),\n move(normalize(`${path}/${folder}`)),\n];\n\nconst getTemplates = (rules: Rule[]) => apply(url(`./templates`), rules);\nconst includeStories = (include: boolean) => filter(filePath => include || !filePath.endsWith('.stories.ts'));\n\nexport function applyFileTemplateUtil(folders: SchematicsFolder[], config: GeneratorSchemaBase): Rule[] {\n selectedElements.push(...folders);\n return folders.map(folder => {\n const RULES = createTemplateRules(folder, config.path as string);\n\n const folderSource = apply(url(`./files/${folder}`), [includeStories(config.stories), ...RULES]);\n\n return chain([folderSource, getTemplates(RULES)].map(mergeWith));\n });\n}\n"]}
|
|
@@ -19,7 +19,7 @@ const includeStories = (include: boolean) => filter(filePath => include || !file
|
|
|
19
19
|
export function applyFileTemplateUtil(folders: SchematicsFolder[], config: GeneratorSchemaBase): Rule[] {
|
|
20
20
|
selectedElements.push(...folders);
|
|
21
21
|
return folders.map(folder => {
|
|
22
|
-
const RULES = createTemplateRules(folder, config.path);
|
|
22
|
+
const RULES = createTemplateRules(folder, config.path as string);
|
|
23
23
|
|
|
24
24
|
const folderSource = apply(url(`./files/${folder}`), [includeStories(config.stories), ...RULES]);
|
|
25
25
|
|