@design-factory/angular 21.0.0-next.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/LICENSE +26 -0
- package/README.md +3 -0
- package/fesm2022/design-factory-angular-accordion.mjs +55 -0
- package/fesm2022/design-factory-angular-accordion.mjs.map +1 -0
- package/fesm2022/design-factory-angular-config.mjs +22 -0
- package/fesm2022/design-factory-angular-config.mjs.map +1 -0
- package/fesm2022/design-factory-angular-drawer.mjs +297 -0
- package/fesm2022/design-factory-angular-drawer.mjs.map +1 -0
- package/fesm2022/design-factory-angular-internals.mjs +111 -0
- package/fesm2022/design-factory-angular-internals.mjs.map +1 -0
- package/fesm2022/design-factory-angular-sidenav.mjs +1354 -0
- package/fesm2022/design-factory-angular-sidenav.mjs.map +1 -0
- package/fesm2022/design-factory-angular.mjs +12 -0
- package/fesm2022/design-factory-angular.mjs.map +1 -0
- package/package.json +59 -0
- package/schematics/collection.json +10 -0
- package/schematics/ng-add/index.d.ts +3 -0
- package/schematics/ng-add/index.js +65 -0
- package/schematics/ng-add/schema.d.ts +6 -0
- package/schematics/ng-add/schema.js +2 -0
- package/schematics/ng-add/schema.json +15 -0
- package/types/design-factory-angular-accordion.d.ts +47 -0
- package/types/design-factory-angular-config.d.ts +24 -0
- package/types/design-factory-angular-drawer.d.ts +136 -0
- package/types/design-factory-angular-internals.d.ts +83 -0
- package/types/design-factory-angular-sidenav.d.ts +367 -0
- package/types/design-factory-angular.d.ts +6 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
Copyright Amadeus SAS
|
|
2
|
+
|
|
3
|
+
Redistribution and use in source and binary forms, with or without modification,
|
|
4
|
+
are permitted provided that the following conditions are met:
|
|
5
|
+
|
|
6
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
7
|
+
list of conditions and the following disclaimer.
|
|
8
|
+
|
|
9
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
10
|
+
this list of conditions and the following disclaimer in the documentation and/or
|
|
11
|
+
other materials provided with the distribution.
|
|
12
|
+
|
|
13
|
+
3. Neither the name of the copyright holder nor the names of its contributors
|
|
14
|
+
may be used to endorse or promote products derived from this software without
|
|
15
|
+
specific prior written permission.
|
|
16
|
+
|
|
17
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
18
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
19
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
20
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
21
|
+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
22
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
23
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
24
|
+
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
25
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
26
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/README.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { provideDfComponentConfig, injectDfComponentConfig } from '@design-factory/angular/internals';
|
|
2
|
+
import * as i0 from '@angular/core';
|
|
3
|
+
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
|
4
|
+
|
|
5
|
+
// the key of the accordion config in the global DF config
|
|
6
|
+
const ACCORDION_CONFIG_KEY = 'accordion';
|
|
7
|
+
/**
|
|
8
|
+
* Provides the configuration for the accordion component.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* \@Component({
|
|
13
|
+
* providers: [provideDfAccordionConfig({ closeOthers: true })]
|
|
14
|
+
* })
|
|
15
|
+
* export class MyHomeComponent {}
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* @param config - Partial configuration or a function that receives the parent configuration and returns a partial configuration.
|
|
19
|
+
*/
|
|
20
|
+
const provideDfAccordionConfig = provideDfComponentConfig(ACCORDION_CONFIG_KEY);
|
|
21
|
+
/**
|
|
22
|
+
* Injects the configuration for the accordion component.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* \@Component({
|
|
27
|
+
* providers: [provideDfAccordionConfig()]
|
|
28
|
+
* })
|
|
29
|
+
* export class MyAccordionComponent {
|
|
30
|
+
* readonly accordionConfig = injectDfAccordionConfig();
|
|
31
|
+
* }
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* @returns A writable signal containing the accordion configuration.
|
|
35
|
+
*/
|
|
36
|
+
const injectDfAccordionConfig = injectDfComponentConfig(ACCORDION_CONFIG_KEY);
|
|
37
|
+
|
|
38
|
+
class DfAccordionComponent {
|
|
39
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: DfAccordionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
40
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: DfAccordionComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: ``, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
41
|
+
}
|
|
42
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: DfAccordionComponent, decorators: [{
|
|
43
|
+
type: Component,
|
|
44
|
+
args: [{
|
|
45
|
+
template: ``,
|
|
46
|
+
changeDetection: ChangeDetectionStrategy.OnPush
|
|
47
|
+
}]
|
|
48
|
+
}] });
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Generated bundle index. Do not edit.
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
export { ACCORDION_CONFIG_KEY, DfAccordionComponent, injectDfAccordionConfig, provideDfAccordionConfig };
|
|
55
|
+
//# sourceMappingURL=design-factory-angular-accordion.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"design-factory-angular-accordion.mjs","sources":["../../accordion/accordion.config.ts","../../accordion/accordion.ts","../../accordion/design-factory-angular-accordion.ts"],"sourcesContent":["import { injectDfComponentConfig, provideDfComponentConfig } from '@design-factory/angular/internals';\n\n// TODO to fill\nexport type DfAccordionConfig = {\n /**\n * example prop\n */\n closeOthers: boolean;\n};\n\n// the key of the accordion config in the global DF config\nexport const ACCORDION_CONFIG_KEY = 'accordion' as const;\n\n/**\n * Provides the configuration for the accordion component.\n *\n * @example\n * ```ts\n * \\@Component({\n * providers: [provideDfAccordionConfig({ closeOthers: true })]\n * })\n * export class MyHomeComponent {}\n * ```\n *\n * @param config - Partial configuration or a function that receives the parent configuration and returns a partial configuration.\n */\nexport const provideDfAccordionConfig = provideDfComponentConfig<DfAccordionConfig>(ACCORDION_CONFIG_KEY);\n\n/**\n * Injects the configuration for the accordion component.\n *\n * @example\n * ```ts\n * \\@Component({\n * providers: [provideDfAccordionConfig()]\n * })\n * export class MyAccordionComponent {\n * readonly accordionConfig = injectDfAccordionConfig();\n * }\n * ```\n *\n * @returns A writable signal containing the accordion configuration.\n */\nexport const injectDfAccordionConfig = injectDfComponentConfig<DfAccordionConfig>(ACCORDION_CONFIG_KEY);\n","import { ChangeDetectionStrategy, Component } from '@angular/core';\n\n@Component({\n template: ``,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class DfAccordionComponent {}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;AAUA;AACO,MAAM,oBAAoB,GAAG;AAEpC;;;;;;;;;;;;AAYG;MACU,wBAAwB,GAAG,wBAAwB,CAAoB,oBAAoB;AAExG;;;;;;;;;;;;;;AAcG;MACU,uBAAuB,GAAG,uBAAuB,CAAoB,oBAAoB;;MCrCzF,oBAAoB,CAAA;8GAApB,oBAAoB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;AAApB,IAAA,SAAA,IAAA,CAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,oBAAoB,wEAHrB,CAAA,CAAE,EAAA,QAAA,EAAA,IAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA,CAAA;;2FAGD,oBAAoB,EAAA,UAAA,EAAA,CAAA;kBAJhC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,CAAA,CAAE;oBACZ,eAAe,EAAE,uBAAuB,CAAC;AAC1C,iBAAA;;;ACLD;;AAEG;;;;"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { toAngularWritableSignal } from '@agnos-ui/angular-headless';
|
|
2
|
+
import '@design-factory/angular/accordion';
|
|
3
|
+
import { provideWidgetsConfig, injectWidgetsConfig } from '@design-factory/angular/internals';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* TODO write clear and simple doc
|
|
7
|
+
*/
|
|
8
|
+
const provideDfConfig = (config) => provideWidgetsConfig(typeof config === 'function' ? config : (parentConfig) => ({ ...parentConfig, ...(config ?? {}) }));
|
|
9
|
+
/**
|
|
10
|
+
* TODO write clear and simple doc
|
|
11
|
+
*/
|
|
12
|
+
const injectDFConfig = () => {
|
|
13
|
+
const widgetsConfigStore = injectWidgetsConfig();
|
|
14
|
+
return toAngularWritableSignal(widgetsConfigStore.own$);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Generated bundle index. Do not edit.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
export { injectDFConfig, provideDfConfig };
|
|
22
|
+
//# sourceMappingURL=design-factory-angular-config.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"design-factory-angular-config.mjs","sources":["../../config/config.ts","../../config/design-factory-angular-config.ts"],"sourcesContent":["import { toAngularWritableSignal, type WidgetsConfigStore, type Partial2Levels } from '@agnos-ui/angular-headless';\nimport type { FactoryProvider } from '@angular/core';\nimport { ACCORDION_CONFIG_KEY, DfAccordionConfig } from '@design-factory/angular/accordion';\nimport { provideWidgetsConfig, injectWidgetsConfig } from '@design-factory/angular/internals';\n\n/**\n * The configuration type for config-customizable DF components.\n */\nexport type DfConfig = {\n [ACCORDION_CONFIG_KEY]: DfAccordionConfig;\n};\n\n/**\n * TODO write clear and simple doc\n */\nexport const provideDfConfig = (\n config?: Partial2Levels<DfConfig> | ((parentConfig: Partial2Levels<DfConfig>) => Partial2Levels<DfConfig>)\n): FactoryProvider =>\n provideWidgetsConfig(\n typeof config === 'function' ? config : (parentConfig) => ({ ...parentConfig, ...(config ?? {}) })\n );\n\n/**\n * TODO write clear and simple doc\n */\nexport const injectDFConfig = () => {\n const widgetsConfigStore = injectWidgetsConfig() as WidgetsConfigStore<DfConfig>;\n return toAngularWritableSignal(widgetsConfigStore.own$);\n};\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;AAYA;;AAEG;AACI,MAAM,eAAe,GAAG,CAC7B,MAA0G,KAE1G,oBAAoB,CAClB,OAAO,MAAM,KAAK,UAAU,GAAG,MAAM,GAAG,CAAC,YAAY,MAAM,EAAE,GAAG,YAAY,EAAE,IAAI,MAAM,IAAI,EAAE,CAAC,EAAE,CAAC;AAGtG;;AAEG;AACI,MAAM,cAAc,GAAG,MAAK;AACjC,IAAA,MAAM,kBAAkB,GAAG,mBAAmB,EAAkC;AAChF,IAAA,OAAO,uBAAuB,CAAC,kBAAkB,CAAC,IAAI,CAAC;AACzD;;AC5BA;;AAEG;;;;"}
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import { createDrawer, createSimpleClassTransition, createNavManager, UseDirective, UseMultiDirective } from '@agnos-ui/angular-headless';
|
|
2
|
+
import { fadeTransition } from '@agnos-ui/core-bootstrap';
|
|
3
|
+
import { isPlatformBrowser } from '@angular/common';
|
|
4
|
+
import * as i0 from '@angular/core';
|
|
5
|
+
import { input, model, output, inject, PLATFORM_ID, booleanAttribute, linkedSignal, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
6
|
+
import { toSignal } from '@angular/core/rxjs-interop';
|
|
7
|
+
import { AgnosWidgetDirective, callWidgetFactory } from '@design-factory/angular/internals';
|
|
8
|
+
import { DfMedia } from '@design-factory/design-factory';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Utility method to check if the user agent is a mobile device
|
|
12
|
+
*
|
|
13
|
+
* @param userAgent - The user agent string to check
|
|
14
|
+
* @returns `true` if the user agent corresponds to a mobile device, `false` otherwise
|
|
15
|
+
*/
|
|
16
|
+
function isMobileUserAgent(userAgent) {
|
|
17
|
+
return /mobile|android|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(userAgent);
|
|
18
|
+
}
|
|
19
|
+
class DfDrawerComponent extends AgnosWidgetDirective {
|
|
20
|
+
constructor() {
|
|
21
|
+
const widget = callWidgetFactory(createDrawer, {
|
|
22
|
+
defaultConfig: {
|
|
23
|
+
className: '',
|
|
24
|
+
bodyScroll: true,
|
|
25
|
+
backdrop: false,
|
|
26
|
+
transition: createSimpleClassTransition({
|
|
27
|
+
showClasses: ['show']
|
|
28
|
+
}),
|
|
29
|
+
backdropTransition: fadeTransition
|
|
30
|
+
},
|
|
31
|
+
events: {
|
|
32
|
+
onSizeChange: (size) => {
|
|
33
|
+
this.size.set(size);
|
|
34
|
+
this.sizeChange.emit(size);
|
|
35
|
+
},
|
|
36
|
+
onVisibleChange: (visible) => {
|
|
37
|
+
this.visibleChange.emit(visible);
|
|
38
|
+
},
|
|
39
|
+
onMinimizedChange: (isMinimized) => {
|
|
40
|
+
this.minimizedChange.emit(isMinimized);
|
|
41
|
+
},
|
|
42
|
+
onMaximizedChange: (isMaximized) => {
|
|
43
|
+
this.maximizedChange.emit(isMaximized);
|
|
44
|
+
},
|
|
45
|
+
onResizingChange: (isResizing) => {
|
|
46
|
+
this.resizingChange.emit(isResizing);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
super(widget);
|
|
51
|
+
/**
|
|
52
|
+
* CSS classes to be applied on the widget main container
|
|
53
|
+
*
|
|
54
|
+
* @defaultValue ``
|
|
55
|
+
*/
|
|
56
|
+
this.className = input('', ...(ngDevMode ? [{ debugName: "className" }] : []));
|
|
57
|
+
/**
|
|
58
|
+
* If `true` allows body scrolling when the drawer is open.
|
|
59
|
+
*
|
|
60
|
+
* @defaultValue `false`
|
|
61
|
+
*/
|
|
62
|
+
this.bodyScroll = input(false, ...(ngDevMode ? [{ debugName: "bodyScroll" }] : []));
|
|
63
|
+
/**
|
|
64
|
+
* If `true` displays the backdrop element and disables the body scrolling, otherwise the body of the document is navigable
|
|
65
|
+
*
|
|
66
|
+
* @defaultValue `true`
|
|
67
|
+
*/
|
|
68
|
+
this.backdrop = input(true, ...(ngDevMode ? [{ debugName: "backdrop" }] : []));
|
|
69
|
+
/**
|
|
70
|
+
* Which element should contain the drawer and backdrop DOM elements.
|
|
71
|
+
* If it is not null, the drawer and backdrop DOM elements are moved to the specified container.
|
|
72
|
+
* Otherwise, they stay where the widget is located.
|
|
73
|
+
*
|
|
74
|
+
* @defaultValue
|
|
75
|
+
* ```ts
|
|
76
|
+
* typeof window !== 'undefined' ? document.body : null
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
this.container = input(null, ...(ngDevMode ? [{ debugName: "container" }] : []));
|
|
80
|
+
/**
|
|
81
|
+
* The size of the drawer in pixels.
|
|
82
|
+
*
|
|
83
|
+
* @defaultValue `300`
|
|
84
|
+
*/
|
|
85
|
+
this.size = model(300, ...(ngDevMode ? [{ debugName: "size" }] : []));
|
|
86
|
+
/**
|
|
87
|
+
* If `true`, the drawer can be resized by the user.
|
|
88
|
+
*
|
|
89
|
+
* @defaultValue `false`
|
|
90
|
+
*/
|
|
91
|
+
this.resizable = input(false, ...(ngDevMode ? [{ debugName: "resizable" }] : []));
|
|
92
|
+
/**
|
|
93
|
+
* If `true`, the drawer is shown; otherwise, it is hidden.
|
|
94
|
+
*
|
|
95
|
+
* @defaultValue `false`
|
|
96
|
+
*/
|
|
97
|
+
this.visible = input(false, ...(ngDevMode ? [{ debugName: "visible" }] : []));
|
|
98
|
+
/**
|
|
99
|
+
* An event emitted when the width is changed.
|
|
100
|
+
*
|
|
101
|
+
* Event payload is equal to the newly selected width.
|
|
102
|
+
*
|
|
103
|
+
* @defaultValue
|
|
104
|
+
* ```ts
|
|
105
|
+
* () => {}
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
this.sizeChange = output();
|
|
109
|
+
/**
|
|
110
|
+
* Event to be triggered when the visible property changes.
|
|
111
|
+
*
|
|
112
|
+
* @param visible - new value of the visible propery
|
|
113
|
+
*
|
|
114
|
+
* @defaultValue
|
|
115
|
+
* ```ts
|
|
116
|
+
* () => {}
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
this.visibleChange = output();
|
|
120
|
+
/**
|
|
121
|
+
* Event to be triggered when the minimized state changes.
|
|
122
|
+
*
|
|
123
|
+
* @defaultValue
|
|
124
|
+
* ```ts
|
|
125
|
+
* () => {}
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
128
|
+
this.minimizedChange = output();
|
|
129
|
+
/**
|
|
130
|
+
* Event to be triggered when the maximized state changes.
|
|
131
|
+
*
|
|
132
|
+
* @defaultValue
|
|
133
|
+
* ```ts
|
|
134
|
+
* () => {}
|
|
135
|
+
* ```
|
|
136
|
+
*/
|
|
137
|
+
this.maximizedChange = output();
|
|
138
|
+
/**
|
|
139
|
+
* Event to be triggered when the user start or stop moving the drawer.
|
|
140
|
+
*
|
|
141
|
+
* @defaultValue
|
|
142
|
+
* ```ts
|
|
143
|
+
* () => {}
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
this.resizingChange = output();
|
|
147
|
+
this.navManager = createNavManager();
|
|
148
|
+
this.navManagerConfig = {
|
|
149
|
+
keys: {
|
|
150
|
+
Home: this.navManager.focusFirst,
|
|
151
|
+
End: this.navManager.focusLast
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
/**
|
|
155
|
+
* Event to be triggered when the minimum size is reached.
|
|
156
|
+
*
|
|
157
|
+
* @defaultValue `null`
|
|
158
|
+
*/
|
|
159
|
+
this.minSize = output();
|
|
160
|
+
/**
|
|
161
|
+
* Event to be triggered when the maximum size is reached.
|
|
162
|
+
*
|
|
163
|
+
* @defaultValue `null`
|
|
164
|
+
*/
|
|
165
|
+
this.maxSize = output();
|
|
166
|
+
this.isSmallScreen = toSignal(inject(DfMedia).getObservable(['sm', 'xs']), { initialValue: false });
|
|
167
|
+
this.isMediumScreen = toSignal(inject(DfMedia).getObservable(['md']), { initialValue: false });
|
|
168
|
+
this.isLargeUpScreen = toSignal(inject(DfMedia).getObservable(['lg', 'xl', 'xxl', 'xxxl']), {
|
|
169
|
+
initialValue: false
|
|
170
|
+
});
|
|
171
|
+
this.isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
|
|
172
|
+
/**
|
|
173
|
+
* Flag to enable mobile device detection for responsive behavior
|
|
174
|
+
* @default true
|
|
175
|
+
*/
|
|
176
|
+
this.enableMobile = input(true, { ...(ngDevMode ? { debugName: "enableMobile" } : {}), transform: booleanAttribute });
|
|
177
|
+
/**
|
|
178
|
+
* Flag to indicate if the drawer is minimized
|
|
179
|
+
*/
|
|
180
|
+
this.isMinimized = linkedSignal(() => {
|
|
181
|
+
// in mobile devices, the default value is true (hiding the drawer) and does not track changes to the screen size
|
|
182
|
+
if (this.isMobileDevice) {
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
// in desktop, we track the large screen signal in order to reset the minimized state
|
|
186
|
+
// it allows resizing the window and have a more user-friendly behavior
|
|
187
|
+
return !this.isLargeUpScreen();
|
|
188
|
+
}, ...(ngDevMode ? [{ debugName: "isMinimized" }] : []));
|
|
189
|
+
this.isMobileDevice = (() => {
|
|
190
|
+
if (this.isBrowser) {
|
|
191
|
+
return this.enableMobile() && isMobileUserAgent(navigator.userAgent);
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
// SSR: try to get request if available
|
|
195
|
+
try {
|
|
196
|
+
const request = inject(Request, { optional: true });
|
|
197
|
+
if (request && 'headers' in request) {
|
|
198
|
+
const userAgent = request.headers.get('user-agent') || '';
|
|
199
|
+
return this.enableMobile() && isMobileUserAgent(userAgent);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
// Request token not available or not in SSR context
|
|
204
|
+
}
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
})();
|
|
208
|
+
}
|
|
209
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: DfDrawerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
210
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: DfDrawerComponent, isStandalone: true, selector: "df-drawer", inputs: { className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, bodyScroll: { classPropertyName: "bodyScroll", publicName: "bodyScroll", isSignal: true, isRequired: false, transformFunction: null }, backdrop: { classPropertyName: "backdrop", publicName: "backdrop", isSignal: true, isRequired: false, transformFunction: null }, container: { classPropertyName: "container", publicName: "container", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, resizable: { classPropertyName: "resizable", publicName: "resizable", isSignal: true, isRequired: false, transformFunction: null }, visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null }, enableMobile: { classPropertyName: "enableMobile", publicName: "enableMobile", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { size: "sizeChange", sizeChange: "sizeChange", visibleChange: "visibleChange", minimizedChange: "minimizedChange", maximizedChange: "maximizedChange", resizingChange: "resizingChange", minSize: "minSize", maxSize: "maxSize" }, usesInheritance: true, ngImport: i0, template: `
|
|
211
|
+
<div
|
|
212
|
+
class="df-drawer d-flex"
|
|
213
|
+
[class]="_agnosWidget.state.className()"
|
|
214
|
+
[class.show]="_agnosWidget.state.visible()"
|
|
215
|
+
[auUseMulti]="[_agnosWidget.directives.drawerPortalDirective, _agnosWidget.directives.drawerDirective]"
|
|
216
|
+
[style.--df-drawer-size]="size() !== null ? size() + 'px' : ''"
|
|
217
|
+
>
|
|
218
|
+
<ng-content />
|
|
219
|
+
@if (_agnosWidget.state.resizable()) {
|
|
220
|
+
<div class="df-drawer-splitter" tabindex="-1" [auUse]="_agnosWidget.directives.splitterDirective">
|
|
221
|
+
<button
|
|
222
|
+
#splitterHandle
|
|
223
|
+
class="btn btn-outline-primary df-btn-icononly df-drawer-splitter-handle"
|
|
224
|
+
[class.df-btn-outline-neutral-mirror]="isMediumScreen() && !isMinimized()"
|
|
225
|
+
i18n-aria-label="@@df.drawer.resize.ariaLabel"
|
|
226
|
+
aria-label="Resize drawer"
|
|
227
|
+
[auUse]="[navManager.directive, navManagerConfig]"
|
|
228
|
+
>
|
|
229
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 192 512" fill="currentColor">
|
|
230
|
+
<path
|
|
231
|
+
d="M16 32C7.2 32 0 39.2 0 48L0 464c0 8.8 7.2 16 16 16s16-7.2 16-16L32 48c0-8.8-7.2-16-16-16zm160 0c-8.8 0-16 7.2-16 16l0 416c0 8.8 7.2 16 16 16s16-7.2 16-16l0-416c0-8.8-7.2-16-16-16z"
|
|
232
|
+
/>
|
|
233
|
+
</svg>
|
|
234
|
+
</button>
|
|
235
|
+
</div>
|
|
236
|
+
}
|
|
237
|
+
</div>
|
|
238
|
+
@if (!_agnosWidget.state.backdropHidden()) {
|
|
239
|
+
<div
|
|
240
|
+
class="df-drawer-backdrop"
|
|
241
|
+
[class.show]="_agnosWidget.state.visible()"
|
|
242
|
+
[auUseMulti]="[_agnosWidget.directives.backdropPortalDirective, _agnosWidget.directives.backdropDirective]"
|
|
243
|
+
></div>
|
|
244
|
+
}
|
|
245
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: UseDirective, selector: "[auUse]", inputs: ["auUse"] }, { kind: "directive", type: UseMultiDirective, selector: "[auUseMulti]", inputs: ["auUseMulti"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
246
|
+
}
|
|
247
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: DfDrawerComponent, decorators: [{
|
|
248
|
+
type: Component,
|
|
249
|
+
args: [{
|
|
250
|
+
selector: 'df-drawer',
|
|
251
|
+
imports: [UseDirective, UseMultiDirective],
|
|
252
|
+
template: `
|
|
253
|
+
<div
|
|
254
|
+
class="df-drawer d-flex"
|
|
255
|
+
[class]="_agnosWidget.state.className()"
|
|
256
|
+
[class.show]="_agnosWidget.state.visible()"
|
|
257
|
+
[auUseMulti]="[_agnosWidget.directives.drawerPortalDirective, _agnosWidget.directives.drawerDirective]"
|
|
258
|
+
[style.--df-drawer-size]="size() !== null ? size() + 'px' : ''"
|
|
259
|
+
>
|
|
260
|
+
<ng-content />
|
|
261
|
+
@if (_agnosWidget.state.resizable()) {
|
|
262
|
+
<div class="df-drawer-splitter" tabindex="-1" [auUse]="_agnosWidget.directives.splitterDirective">
|
|
263
|
+
<button
|
|
264
|
+
#splitterHandle
|
|
265
|
+
class="btn btn-outline-primary df-btn-icononly df-drawer-splitter-handle"
|
|
266
|
+
[class.df-btn-outline-neutral-mirror]="isMediumScreen() && !isMinimized()"
|
|
267
|
+
i18n-aria-label="@@df.drawer.resize.ariaLabel"
|
|
268
|
+
aria-label="Resize drawer"
|
|
269
|
+
[auUse]="[navManager.directive, navManagerConfig]"
|
|
270
|
+
>
|
|
271
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 192 512" fill="currentColor">
|
|
272
|
+
<path
|
|
273
|
+
d="M16 32C7.2 32 0 39.2 0 48L0 464c0 8.8 7.2 16 16 16s16-7.2 16-16L32 48c0-8.8-7.2-16-16-16zm160 0c-8.8 0-16 7.2-16 16l0 416c0 8.8 7.2 16 16 16s16-7.2 16-16l0-416c0-8.8-7.2-16-16-16z"
|
|
274
|
+
/>
|
|
275
|
+
</svg>
|
|
276
|
+
</button>
|
|
277
|
+
</div>
|
|
278
|
+
}
|
|
279
|
+
</div>
|
|
280
|
+
@if (!_agnosWidget.state.backdropHidden()) {
|
|
281
|
+
<div
|
|
282
|
+
class="df-drawer-backdrop"
|
|
283
|
+
[class.show]="_agnosWidget.state.visible()"
|
|
284
|
+
[auUseMulti]="[_agnosWidget.directives.backdropPortalDirective, _agnosWidget.directives.backdropDirective]"
|
|
285
|
+
></div>
|
|
286
|
+
}
|
|
287
|
+
`,
|
|
288
|
+
changeDetection: ChangeDetectionStrategy.OnPush
|
|
289
|
+
}]
|
|
290
|
+
}], ctorParameters: () => [], propDecorators: { className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], bodyScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "bodyScroll", required: false }] }], backdrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "backdrop", required: false }] }], container: [{ type: i0.Input, args: [{ isSignal: true, alias: "container", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }, { type: i0.Output, args: ["sizeChange"] }], resizable: [{ type: i0.Input, args: [{ isSignal: true, alias: "resizable", required: false }] }], visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: false }] }], sizeChange: [{ type: i0.Output, args: ["sizeChange"] }], visibleChange: [{ type: i0.Output, args: ["visibleChange"] }], minimizedChange: [{ type: i0.Output, args: ["minimizedChange"] }], maximizedChange: [{ type: i0.Output, args: ["maximizedChange"] }], resizingChange: [{ type: i0.Output, args: ["resizingChange"] }], minSize: [{ type: i0.Output, args: ["minSize"] }], maxSize: [{ type: i0.Output, args: ["maxSize"] }], enableMobile: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableMobile", required: false }] }] } });
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Generated bundle index. Do not edit.
|
|
294
|
+
*/
|
|
295
|
+
|
|
296
|
+
export { DfDrawerComponent };
|
|
297
|
+
//# sourceMappingURL=design-factory-angular-drawer.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"design-factory-angular-drawer.mjs","sources":["../../drawer/drawer.ts","../../drawer/design-factory-angular-drawer.ts"],"sourcesContent":["import type { DrawerWidget, NavManagerItemConfig } from '@agnos-ui/angular-headless';\nimport {\n createDrawer,\n createNavManager,\n createSimpleClassTransition,\n UseDirective,\n UseMultiDirective\n} from '@agnos-ui/angular-headless';\nimport { fadeTransition } from '@agnos-ui/core-bootstrap';\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n inject,\n input,\n linkedSignal,\n model,\n output,\n PLATFORM_ID\n} from '@angular/core';\nimport { toSignal } from '@angular/core/rxjs-interop';\nimport { AgnosWidgetDirective, callWidgetFactory } from '@design-factory/angular/internals';\nimport { DfMedia } from '@design-factory/design-factory';\n\n/**\n * Utility method to check if the user agent is a mobile device\n *\n * @param userAgent - The user agent string to check\n * @returns `true` if the user agent corresponds to a mobile device, `false` otherwise\n */\nfunction isMobileUserAgent(userAgent: string): boolean {\n return /mobile|android|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(userAgent);\n}\n\n@Component({\n selector: 'df-drawer',\n imports: [UseDirective, UseMultiDirective],\n template: `\n <div\n class=\"df-drawer d-flex\"\n [class]=\"_agnosWidget.state.className()\"\n [class.show]=\"_agnosWidget.state.visible()\"\n [auUseMulti]=\"[_agnosWidget.directives.drawerPortalDirective, _agnosWidget.directives.drawerDirective]\"\n [style.--df-drawer-size]=\"size() !== null ? size() + 'px' : ''\"\n >\n <ng-content />\n @if (_agnosWidget.state.resizable()) {\n <div class=\"df-drawer-splitter\" tabindex=\"-1\" [auUse]=\"_agnosWidget.directives.splitterDirective\">\n <button\n #splitterHandle\n class=\"btn btn-outline-primary df-btn-icononly df-drawer-splitter-handle\"\n [class.df-btn-outline-neutral-mirror]=\"isMediumScreen() && !isMinimized()\"\n i18n-aria-label=\"@@df.drawer.resize.ariaLabel\"\n aria-label=\"Resize drawer\"\n [auUse]=\"[navManager.directive, navManagerConfig]\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 192 512\" fill=\"currentColor\">\n <path\n d=\"M16 32C7.2 32 0 39.2 0 48L0 464c0 8.8 7.2 16 16 16s16-7.2 16-16L32 48c0-8.8-7.2-16-16-16zm160 0c-8.8 0-16 7.2-16 16l0 416c0 8.8 7.2 16 16 16s16-7.2 16-16l0-416c0-8.8-7.2-16-16-16z\"\n />\n </svg>\n </button>\n </div>\n }\n </div>\n @if (!_agnosWidget.state.backdropHidden()) {\n <div\n class=\"df-drawer-backdrop\"\n [class.show]=\"_agnosWidget.state.visible()\"\n [auUseMulti]=\"[_agnosWidget.directives.backdropPortalDirective, _agnosWidget.directives.backdropDirective]\"\n ></div>\n }\n `,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class DfDrawerComponent extends AgnosWidgetDirective<DrawerWidget> {\n /**\n * CSS classes to be applied on the widget main container\n *\n * @defaultValue ``\n */\n readonly className = input<string>('');\n /**\n * If `true` allows body scrolling when the drawer is open.\n *\n * @defaultValue `false`\n */\n readonly bodyScroll = input<boolean>(false);\n /**\n * If `true` displays the backdrop element and disables the body scrolling, otherwise the body of the document is navigable\n *\n * @defaultValue `true`\n */\n readonly backdrop = input<boolean>(true);\n /**\n * Which element should contain the drawer and backdrop DOM elements.\n * If it is not null, the drawer and backdrop DOM elements are moved to the specified container.\n * Otherwise, they stay where the widget is located.\n *\n * @defaultValue\n * ```ts\n * typeof window !== 'undefined' ? document.body : null\n * ```\n */\n readonly container = input<HTMLElement | null>(null);\n /**\n * The size of the drawer in pixels.\n *\n * @defaultValue `300`\n */\n readonly size = model<number | null>(300);\n /**\n * If `true`, the drawer can be resized by the user.\n *\n * @defaultValue `false`\n */\n readonly resizable = input<boolean>(false);\n /**\n * If `true`, the drawer is shown; otherwise, it is hidden.\n *\n * @defaultValue `false`\n */\n readonly visible = input<boolean>(false);\n\n /**\n * An event emitted when the width is changed.\n *\n * Event payload is equal to the newly selected width.\n *\n * @defaultValue\n * ```ts\n * () => {}\n * ```\n */\n readonly sizeChange = output<number | null>();\n /**\n * Event to be triggered when the visible property changes.\n *\n * @param visible - new value of the visible propery\n *\n * @defaultValue\n * ```ts\n * () => {}\n * ```\n */\n readonly visibleChange = output<boolean>();\n\n /**\n * Event to be triggered when the minimized state changes.\n *\n * @defaultValue\n * ```ts\n * () => {}\n * ```\n */\n readonly minimizedChange = output<boolean>();\n\n /**\n * Event to be triggered when the maximized state changes.\n *\n * @defaultValue\n * ```ts\n * () => {}\n * ```\n */\n readonly maximizedChange = output<boolean>();\n\n /**\n * Event to be triggered when the user start or stop moving the drawer.\n *\n * @defaultValue\n * ```ts\n * () => {}\n * ```\n */\n readonly resizingChange = output<boolean>();\n\n protected readonly navManager = createNavManager();\n\n protected readonly navManagerConfig: NavManagerItemConfig = {\n keys: {\n Home: this.navManager.focusFirst,\n End: this.navManager.focusLast\n }\n };\n\n /**\n * Event to be triggered when the minimum size is reached.\n *\n * @defaultValue `null`\n */\n readonly minSize = output<void>();\n\n /**\n * Event to be triggered when the maximum size is reached.\n *\n * @defaultValue `null`\n */\n readonly maxSize = output<void>();\n\n protected readonly isSmallScreen = toSignal(inject(DfMedia).getObservable(['sm', 'xs']), { initialValue: false });\n protected readonly isMediumScreen = toSignal(inject(DfMedia).getObservable(['md']), { initialValue: false });\n protected readonly isLargeUpScreen = toSignal(inject(DfMedia).getObservable(['lg', 'xl', 'xxl', 'xxxl']), {\n initialValue: false\n });\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n\n /**\n * Flag to enable mobile device detection for responsive behavior\n * @default true\n */\n readonly enableMobile = input(true, { transform: booleanAttribute });\n\n /**\n * Flag to indicate if the drawer is minimized\n */\n readonly isMinimized = linkedSignal(() => {\n // in mobile devices, the default value is true (hiding the drawer) and does not track changes to the screen size\n if (this.isMobileDevice) {\n return true;\n }\n // in desktop, we track the large screen signal in order to reset the minimized state\n // it allows resizing the window and have a more user-friendly behavior\n return !this.isLargeUpScreen();\n });\n\n protected readonly isMobileDevice = (() => {\n if (this.isBrowser) {\n return this.enableMobile() && isMobileUserAgent(navigator.userAgent);\n } else {\n // SSR: try to get request if available\n try {\n const request = inject(Request, { optional: true });\n if (request && 'headers' in request) {\n const userAgent = request.headers.get('user-agent') || '';\n return this.enableMobile() && isMobileUserAgent(userAgent);\n }\n } catch {\n // Request token not available or not in SSR context\n }\n return false;\n }\n })();\n\n constructor() {\n const widget = callWidgetFactory(createDrawer, {\n defaultConfig: {\n className: '',\n bodyScroll: true,\n backdrop: false,\n transition: createSimpleClassTransition({\n showClasses: ['show']\n }),\n backdropTransition: fadeTransition\n },\n events: {\n onSizeChange: (size) => {\n this.size.set(size);\n this.sizeChange.emit(size);\n },\n onVisibleChange: (visible) => {\n this.visibleChange.emit(visible);\n },\n onMinimizedChange: (isMinimized) => {\n this.minimizedChange.emit(isMinimized);\n },\n onMaximizedChange: (isMaximized) => {\n this.maximizedChange.emit(isMaximized);\n },\n onResizingChange: (isResizing) => {\n this.resizingChange.emit(isResizing);\n }\n }\n });\n super(widget);\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { widgetsConfigFactory, createWidgetsConfig, toAngularWritableSignal } from '@agnos-ui/angular-headless';
|
|
2
|
+
import { asWritable, computed } from '@amadeus-it-group/tansu';
|
|
3
|
+
import * as i0 from '@angular/core';
|
|
4
|
+
import { InjectionToken, Directive } from '@angular/core';
|
|
5
|
+
|
|
6
|
+
const widgetFactories = widgetsConfigFactory(new InjectionToken('dfConfig', {
|
|
7
|
+
providedIn: 'root',
|
|
8
|
+
factory: () => createWidgetsConfig()
|
|
9
|
+
}));
|
|
10
|
+
const provideWidgetsConfig = widgetFactories.provideWidgetsConfig;
|
|
11
|
+
const injectWidgetsConfig = widgetFactories.injectWidgetsConfig;
|
|
12
|
+
/**
|
|
13
|
+
* Creates and initializes a widget using the provided factory and configuration options.
|
|
14
|
+
*
|
|
15
|
+
* The resulting widget can be easily hooked into the lifecycle of an Angular component through {@link BaseWidgetDirective}.
|
|
16
|
+
*
|
|
17
|
+
* @template W - The type of the widget.
|
|
18
|
+
* @param factory - The factory function to create the widget.
|
|
19
|
+
* @param options - The options for creating the widget.
|
|
20
|
+
* @param options.defaultConfig - The default configuration for the widget.
|
|
21
|
+
* @param options.events - The event handlers for the widget.
|
|
22
|
+
* @param options.slotTemplates - A function that returns the slot templates for the widget.
|
|
23
|
+
* @param options.slotChildren - A function that returns the slot children for the widget.
|
|
24
|
+
* @param options.afterInit - A callback function to be called after the widget is initialized.
|
|
25
|
+
* @returns The initialized widget.
|
|
26
|
+
*/
|
|
27
|
+
const callWidgetFactory = widgetFactories.callWidgetFactory;
|
|
28
|
+
/**
|
|
29
|
+
* Utility to provide configuration for a specific DF component.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* export const provideDfCollapseConfig = provideDfComponentConfig<DfCollapseConfig>(COLLAPSE_CONFIG_KEY);
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* @param componentKey the key of the component in the global configuration
|
|
37
|
+
* @returns the component config provider
|
|
38
|
+
*/
|
|
39
|
+
const provideDfComponentConfig = (componentKey) => {
|
|
40
|
+
return (config) => {
|
|
41
|
+
const typedProvideWidgetsConfig = provideWidgetsConfig;
|
|
42
|
+
return typedProvideWidgetsConfig((prevConfig) => ({
|
|
43
|
+
...prevConfig,
|
|
44
|
+
[componentKey]: {
|
|
45
|
+
...(prevConfig?.[componentKey] ?? {}),
|
|
46
|
+
...(typeof config === 'function' ? config(prevConfig?.[componentKey] ?? {}) : (config ?? {}))
|
|
47
|
+
}
|
|
48
|
+
}));
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Utility to inject writable configuration for a specific DF component.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* export const injectDfCollapseConfig = injectDfComponentConfig<DfCollapseConfig>(COLLAPSE_CONFIG_KEY);
|
|
57
|
+
* ```
|
|
58
|
+
*
|
|
59
|
+
* @param componentKey the key of the component in the global configuration
|
|
60
|
+
* @returns the inject function that returns the writable component configuration
|
|
61
|
+
*/
|
|
62
|
+
const injectDfComponentConfig = (componentKey) => () => {
|
|
63
|
+
const widgetsConfigStore = injectWidgetsConfig();
|
|
64
|
+
const componentConfigStore = asWritable(computed(() => widgetsConfigStore.own$()[componentKey] ?? {}), (newConfig) => {
|
|
65
|
+
widgetsConfigStore.own$.update((currentConfig) => ({ ...currentConfig, [componentKey]: newConfig }));
|
|
66
|
+
});
|
|
67
|
+
return toAngularWritableSignal(componentConfigStore);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* An abstract base class for widget directives, providing common functionality
|
|
72
|
+
* for Angular components that interact with widgets.
|
|
73
|
+
*
|
|
74
|
+
* @template W - The type of the widget.
|
|
75
|
+
*/
|
|
76
|
+
class AgnosWidgetDirective {
|
|
77
|
+
// eslint-disable-next-line @angular-eslint/prefer-inject
|
|
78
|
+
constructor(_agnosWidget) {
|
|
79
|
+
this._agnosWidget = _agnosWidget;
|
|
80
|
+
}
|
|
81
|
+
/** @internal */
|
|
82
|
+
ngOnChanges(changes) {
|
|
83
|
+
const patchData = {};
|
|
84
|
+
for (const [key, simpleChange] of Object.entries(changes)) {
|
|
85
|
+
if (simpleChange !== undefined) {
|
|
86
|
+
patchData[key] = simpleChange.currentValue;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
this._agnosWidget.patch(patchData);
|
|
90
|
+
}
|
|
91
|
+
/** @internal */
|
|
92
|
+
ngOnInit() {
|
|
93
|
+
this._agnosWidget.ngInit();
|
|
94
|
+
}
|
|
95
|
+
/** @internal */
|
|
96
|
+
ngAfterContentChecked() {
|
|
97
|
+
this._agnosWidget.updateSlots();
|
|
98
|
+
}
|
|
99
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AgnosWidgetDirective, deps: "invalid", target: i0.ɵɵFactoryTarget.Directive }); }
|
|
100
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.6", type: AgnosWidgetDirective, isStandalone: true, usesOnChanges: true, ngImport: i0 }); }
|
|
101
|
+
}
|
|
102
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AgnosWidgetDirective, decorators: [{
|
|
103
|
+
type: Directive
|
|
104
|
+
}], ctorParameters: () => [{ type: undefined }] });
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Generated bundle index. Do not edit.
|
|
108
|
+
*/
|
|
109
|
+
|
|
110
|
+
export { AgnosWidgetDirective, callWidgetFactory, injectDfComponentConfig, injectWidgetsConfig, provideDfComponentConfig, provideWidgetsConfig };
|
|
111
|
+
//# sourceMappingURL=design-factory-angular-internals.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"design-factory-angular-internals.mjs","sources":["../../internals/config.ts","../../internals/widget.directive.ts","../../internals/design-factory-angular-internals.ts"],"sourcesContent":["import type { WidgetsConfigStore } from '@agnos-ui/angular-headless';\nimport { createWidgetsConfig, toAngularWritableSignal, widgetsConfigFactory } from '@agnos-ui/angular-headless';\nimport { asWritable, computed, type ReadableSignal } from '@amadeus-it-group/tansu';\nimport type { FactoryProvider } from '@angular/core';\nimport { InjectionToken } from '@angular/core';\n\nconst widgetFactories = widgetsConfigFactory(\n new InjectionToken<WidgetsConfigStore<unknown>>('dfConfig', {\n providedIn: 'root',\n factory: () => createWidgetsConfig()\n })\n);\n\nexport const provideWidgetsConfig = widgetFactories.provideWidgetsConfig;\n\nexport const injectWidgetsConfig = widgetFactories.injectWidgetsConfig;\n\n/**\n * Creates and initializes a widget using the provided factory and configuration options.\n *\n * The resulting widget can be easily hooked into the lifecycle of an Angular component through {@link BaseWidgetDirective}.\n *\n * @template W - The type of the widget.\n * @param factory - The factory function to create the widget.\n * @param options - The options for creating the widget.\n * @param options.defaultConfig - The default configuration for the widget.\n * @param options.events - The event handlers for the widget.\n * @param options.slotTemplates - A function that returns the slot templates for the widget.\n * @param options.slotChildren - A function that returns the slot children for the widget.\n * @param options.afterInit - A callback function to be called after the widget is initialized.\n * @returns The initialized widget.\n */\nexport const callWidgetFactory = widgetFactories.callWidgetFactory;\n\n/**\n * Utility to provide configuration for a specific DF component.\n *\n * @example\n * ```typescript\n * export const provideDfCollapseConfig = provideDfComponentConfig<DfCollapseConfig>(COLLAPSE_CONFIG_KEY);\n * ```\n *\n * @param componentKey the key of the component in the global configuration\n * @returns the component config provider\n */\nexport const provideDfComponentConfig = <T>(componentKey: string) => {\n return (config?: Partial<T> | ((prevConfig: Partial<T>) => Partial<T>)) => {\n const typedProvideWidgetsConfig = provideWidgetsConfig as (\n adaptParentConfig?: (parentConfig: { [componentKey]?: Partial<T> }) => { [componentKey]?: Partial<T> }\n ) => FactoryProvider;\n return typedProvideWidgetsConfig((prevConfig) => ({\n ...prevConfig,\n [componentKey]: {\n ...(prevConfig?.[componentKey] ?? {}),\n ...(typeof config === 'function' ? config(prevConfig?.[componentKey] ?? {}) : (config ?? {}))\n }\n }));\n };\n};\n\n/**\n * Utility to inject writable configuration for a specific DF component.\n *\n * @example\n * ```typescript\n * export const injectDfCollapseConfig = injectDfComponentConfig<DfCollapseConfig>(COLLAPSE_CONFIG_KEY);\n * ```\n *\n * @param componentKey the key of the component in the global configuration\n * @returns the inject function that returns the writable component configuration\n */\nexport const injectDfComponentConfig =\n <T>(componentKey: string) =>\n () => {\n const widgetsConfigStore = injectWidgetsConfig() as WidgetsConfigStore<{ [componentKey]?: Partial<T> }>;\n const componentConfigStore = asWritable(\n computed(() => widgetsConfigStore.own$()[componentKey] ?? {}) as ReadableSignal<Partial<T>>,\n (newConfig: Partial<T>) => {\n widgetsConfigStore.own$.update((currentConfig) => ({ ...currentConfig, [componentKey]: newConfig }));\n }\n );\n return toAngularWritableSignal(componentConfigStore);\n };\n","import { AngularWidget, Widget } from '@agnos-ui/angular-headless';\nimport { AfterContentChecked, Directive, OnChanges, OnInit, SimpleChanges } from '@angular/core';\n\n/**\n * An abstract base class for widget directives, providing common functionality\n * for Angular components that interact with widgets.\n *\n * @template W - The type of the widget.\n */\n@Directive()\nexport abstract class AgnosWidgetDirective<W extends Widget> implements OnChanges, OnInit, AfterContentChecked {\n // eslint-disable-next-line @angular-eslint/prefer-inject\n constructor(protected readonly _agnosWidget: AngularWidget<W>) {}\n\n /** @internal */\n ngOnChanges(changes: SimpleChanges): void {\n const patchData: any = {};\n for (const [key, simpleChange] of Object.entries(changes)) {\n if (simpleChange !== undefined) {\n patchData[key] = simpleChange.currentValue;\n }\n }\n this._agnosWidget.patch(patchData);\n }\n\n /** @internal */\n ngOnInit(): void {\n this._agnosWidget.ngInit();\n }\n\n /** @internal */\n ngAfterContentChecked(): void {\n this._agnosWidget.updateSlots();\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;AAMA,MAAM,eAAe,GAAG,oBAAoB,CAC1C,IAAI,cAAc,CAA8B,UAAU,EAAE;AAC1D,IAAA,UAAU,EAAE,MAAM;AAClB,IAAA,OAAO,EAAE,MAAM,mBAAmB;AACnC,CAAA,CAAC,CACH;AAEM,MAAM,oBAAoB,GAAG,eAAe,CAAC;AAE7C,MAAM,mBAAmB,GAAG,eAAe,CAAC;AAEnD;;;;;;;;;;;;;;AAcG;AACI,MAAM,iBAAiB,GAAG,eAAe,CAAC;AAEjD;;;;;;;;;;AAUG;AACI,MAAM,wBAAwB,GAAG,CAAI,YAAoB,KAAI;IAClE,OAAO,CAAC,MAA8D,KAAI;QACxE,MAAM,yBAAyB,GAAG,oBAEd;AACpB,QAAA,OAAO,yBAAyB,CAAC,CAAC,UAAU,MAAM;AAChD,YAAA,GAAG,UAAU;YACb,CAAC,YAAY,GAAG;gBACd,IAAI,UAAU,GAAG,YAAY,CAAC,IAAI,EAAE,CAAC;gBACrC,IAAI,OAAO,MAAM,KAAK,UAAU,GAAG,MAAM,CAAC,UAAU,GAAG,YAAY,CAAC,IAAI,EAAE,CAAC,IAAI,MAAM,IAAI,EAAE,CAAC;AAC7F;AACF,SAAA,CAAC,CAAC;AACL,IAAA,CAAC;AACH;AAEA;;;;;;;;;;AAUG;AACI,MAAM,uBAAuB,GAClC,CAAI,YAAoB,KACxB,MAAK;AACH,IAAA,MAAM,kBAAkB,GAAG,mBAAmB,EAAyD;IACvG,MAAM,oBAAoB,GAAG,UAAU,CACrC,QAAQ,CAAC,MAAM,kBAAkB,CAAC,IAAI,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,CAA+B,EAC3F,CAAC,SAAqB,KAAI;QACxB,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,aAAa,MAAM,EAAE,GAAG,aAAa,EAAE,CAAC,YAAY,GAAG,SAAS,EAAE,CAAC,CAAC;AACtG,IAAA,CAAC,CACF;AACD,IAAA,OAAO,uBAAuB,CAAC,oBAAoB,CAAC;AACtD;;AC/EF;;;;;AAKG;MAEmB,oBAAoB,CAAA;;AAExC,IAAA,WAAA,CAA+B,YAA8B,EAAA;QAA9B,IAAA,CAAA,YAAY,GAAZ,YAAY;IAAqB;;AAGhE,IAAA,WAAW,CAAC,OAAsB,EAAA;QAChC,MAAM,SAAS,GAAQ,EAAE;AACzB,QAAA,KAAK,MAAM,CAAC,GAAG,EAAE,YAAY,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;AACzD,YAAA,IAAI,YAAY,KAAK,SAAS,EAAE;AAC9B,gBAAA,SAAS,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC,YAAY;YAC5C;QACF;AACA,QAAA,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,SAAS,CAAC;IACpC;;IAGA,QAAQ,GAAA;AACN,QAAA,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE;IAC5B;;IAGA,qBAAqB,GAAA;AACnB,QAAA,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE;IACjC;8GAvBoB,oBAAoB,EAAA,IAAA,EAAA,SAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;kGAApB,oBAAoB,EAAA,YAAA,EAAA,IAAA,EAAA,aAAA,EAAA,IAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA,CAAA;;2FAApB,oBAAoB,EAAA,UAAA,EAAA,CAAA;kBADzC;;;ACTD;;AAEG;;;;"}
|