@ng-formworks/cssframework 15.2.7

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 ADDED
@@ -0,0 +1,28 @@
1
+ # @ng-formworks/cssframework
2
+
3
+ This module is a dependency of the [ng-formworks project][npm_core_ver] and not intended to be consumed independently see [@ng-formworks/core][npm_core_ver] for more details.
4
+ Below is information regarding the development tasks and not related to the module's installation, it should automatically be installed when a framework module is installed.
5
+
6
+ ## Code scaffolding
7
+
8
+ Run `ng generate component component-name --project @ng-formworks/cssframework` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project @ng-formworks/cssframework`.
9
+ > Note: Don't forget to add `--project @ng-formworks/cssframework` or else it will be added to the default project in your `angular.json` file.
10
+
11
+ ## Build
12
+
13
+ Run `ng build @ng-formworks/cssframework` to build the project. The build artifacts will be stored in the `dist/` directory.
14
+
15
+ ## Publishing
16
+
17
+ After building your library with `ng build @ng-formworks/cssframework`, go to the dist folder `cd dist/@ng-formworks/cssframework` and run `npm publish`.
18
+
19
+ ## Running unit tests
20
+
21
+ Run `ng test @ng-formworks/cssframework` to execute the unit tests via [Karma](https://karma-runner.github.io).
22
+
23
+ ## Further help
24
+
25
+ To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.
26
+
27
+
28
+ [npm_core_ver]:https://www.npmjs.com/package/@ng-formworks/core
@@ -0,0 +1,12 @@
1
+ {
2
+ "$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
3
+ "dest": "../../dist/@ng-formworks/cssframework",
4
+ "lib": {
5
+ "entryFile": "src/public-api.ts"
6
+ },
7
+ "assets": ["./assets"],
8
+ "allowedNonPeerDependencies": [
9
+ "lodash-es",
10
+ "@ng-formworks/core"
11
+ ]
12
+ }
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@ng-formworks/cssframework",
3
+ "version": "15.2.7",
4
+ "description": "Angular ng-formworks - JSON Schema Form builder cssframework",
5
+ "author": "https://github.com/zahmo/ng-formworks/graphs/contributors",
6
+ "keywords": [
7
+ "Angular",
8
+ "ng",
9
+ "Angular15",
10
+ "Angular 15",
11
+ "Angular16",
12
+ "Angular 16",
13
+ "Angular17",
14
+ "Angular 17",
15
+ "ng15",
16
+ "ng16",
17
+ "ng17",
18
+ "JSON Schema",
19
+ "form",
20
+ "forms",
21
+ "form builder",
22
+ "form themes",
23
+ "form generator",
24
+ "ajsf",
25
+ "ng-formworks",
26
+ "ng formworks",
27
+ "formworks",
28
+ "angular json schema form"
29
+ ],
30
+ "license": "MIT",
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "git+https://github.com/zahmo/ng-formworks"
34
+ },
35
+ "bugs": {
36
+ "url": "https://github.com/zahmo/ng-formworks/issues"
37
+ },
38
+ "private": false,
39
+ "peerDependencies": {
40
+ "@angular/common": "^17.0.0",
41
+ "@angular/core": "^17.0.0"
42
+ },
43
+ "dependencies": {
44
+ "tslib": "^2.3.0",
45
+ "@ng-formworks/core": "~15.2.7"
46
+ },
47
+ "devDependencies": {
48
+ "@types/lodash-es": "^4.17.6"
49
+ },
50
+ "sideEffects": false
51
+ }
@@ -0,0 +1,67 @@
1
+ <div [attr.data-bs-theme]="theme" [attr.data-theme]="theme" [class]="options?.htmlClass || ''" [class.has-feedback]="options?.feedback && options?.isInputWidget &&
2
+ (formControl?.dirty || options?.feedbackOnRender)" [class.has-error]="options?.enableErrorState && formControl?.errors &&
3
+ (formControl?.dirty || options?.feedbackOnRender)" [class.has-success]="options?.enableSuccessState && !formControl?.errors &&
4
+ (formControl?.dirty || options?.feedbackOnRender)">
5
+
6
+ <button *ngIf="showRemoveButton" [class]="widgetStyles.__remove_item__" type="button" (click)="removeItem()">
7
+ <span aria-hidden="true">&times;</span>
8
+ <span [class]="widgetStyles.__screen_reader__">Close</span>
9
+ </button>
10
+ <div *ngIf="options?.messageLocation === 'top'">
11
+ <p *ngIf="options?.helpBlock" [class]="widgetStyles.__help_block__" [innerHTML]="options?.helpBlock"></p>
12
+ </div>
13
+
14
+ <label *ngIf="options?.title && layoutNode?.type !== 'tab'" [attr.for]="'control' + layoutNode?._id" [class]="options?.labelHtmlClass || ''" [class.sr-only]="options?.notitle" [innerHTML]="options?.title"></label>
15
+ <p *ngIf="layoutNode?.type === 'submit' && jsf?.formOptions?.fieldsRequired">
16
+ <strong [class]="widgetStyles.__required_asterisk__">*</strong> = required fields
17
+ </p>
18
+ <div [class.input-group]="options?.fieldAddonLeft || options?.fieldAddonRight">
19
+ <span *ngIf="options?.fieldAddonLeft" [class]="widgetStyles.__field_addon_left__" [innerHTML]="options?.fieldAddonLeft"></span>
20
+
21
+ <select-widget-widget [layoutNode]="widgetLayoutNode" [dataIndex]="dataIndex" [layoutIndex]="layoutIndex"></select-widget-widget>
22
+
23
+ <span *ngIf="options?.fieldAddonRight" [class]="widgetStyles.__field_addon_right__" [innerHTML]="options?.fieldAddonRight"></span>
24
+ </div>
25
+
26
+ <span *ngIf="options?.feedback && options?.isInputWidget &&
27
+ !options?.fieldAddonRight && !layoutNode.arrayItem &&
28
+ (formControl?.dirty || options?.feedbackOnRender)" [class.glyphicon-ok]="options?.enableSuccessState && !formControl?.errors" [class.glyphicon-remove]="options?.enableErrorState && formControl?.errors" aria-hidden="true" class="form-control-feedback glyphicon"></span>
29
+ <div *ngIf="options?.messageLocation !== 'top'">
30
+ <p *ngIf="options?.helpBlock" [class]="widgetStyles.__help_block__" [innerHTML]="options?.helpBlock"></p>
31
+ </div>
32
+
33
+ </div>
34
+
35
+ <div *ngIf="debug && debugOutput">debug:
36
+ <pre>{{debugOutput}}</pre>
37
+ </div>
38
+
39
+ <!--
40
+ <div class="btn input input-bordered input-primary w-full max-w-xs
41
+ btn-neutral
42
+ btn-primary
43
+ btn-secondary
44
+ btn-accent
45
+ btn-info
46
+ btn-success
47
+ btn-warning
48
+ btn-error
49
+ btn-ghost
50
+ btn-link
51
+ btn-outline
52
+ btn-active
53
+ btn-disabled
54
+ glass
55
+ no-animation
56
+ btn-lg
57
+ btn-md
58
+ btn-sm
59
+ btn-xs
60
+ btn-wide
61
+ btn-block
62
+ btn-circle
63
+ btn-square
64
+ hidden
65
+ ">defs al</div>
66
+ -->
67
+ <!--<input type="text" placeholder="Type here" class="input input-bordered input-primary w-full max-w-xs" />-->
@@ -0,0 +1,45 @@
1
+ :host ::ng-deep {
2
+ .list-group-item .form-control-feedback {
3
+ top: 40px;
4
+ }
5
+ .checkbox,
6
+ .radio {
7
+ margin-top: 0;
8
+ margin-bottom: 0;
9
+ }
10
+ .checkbox-inline,
11
+ .checkbox-inline+.checkbox-inline,
12
+ .checkbox-inline+.radio-inline,
13
+ .radio-inline,
14
+ .radio-inline+.radio-inline,
15
+ .radio-inline+.checkbox-inline {
16
+ margin-left: 0;
17
+ margin-right: 10px;
18
+ }
19
+ .checkbox-inline:last-child,
20
+ .radio-inline:last-child {
21
+ margin-right: 0;
22
+ }
23
+ .ng-invalid.ng-touched {
24
+ border: 1px solid #f44336;
25
+ }
26
+ }
27
+
28
+ .checkbox-inline,
29
+ .checkbox-inline+.checkbox-inline,
30
+ .checkbox-inline+.radio-inline,
31
+ .radio-inline,
32
+ .radio-inline+.radio-inline,
33
+ .radio-inline+.checkbox-inline {
34
+ margin-left: 0;
35
+ margin-right: 10px;
36
+ }
37
+
38
+ .checkbox-inline:last-child,
39
+ .radio-inline:last-child {
40
+ margin-right: 0;
41
+ }
42
+
43
+ .ng-invalid.ng-touched {
44
+ border: 1px solid #f44336;
45
+ }
@@ -0,0 +1,21 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { CssFrameworkComponent } from './css-framework.component';
4
+
5
+ describe('CssFrameworkComponent', () => {
6
+ let component: CssFrameworkComponent;
7
+ let fixture: ComponentFixture<CssFrameworkComponent>;
8
+
9
+ beforeEach(() => {
10
+ TestBed.configureTestingModule({
11
+ declarations: [CssFrameworkComponent]
12
+ });
13
+ fixture = TestBed.createComponent(CssFrameworkComponent);
14
+ component = fixture.componentInstance;
15
+ fixture.detectChanges();
16
+ });
17
+
18
+ it('should create', () => {
19
+ expect(component).toBeTruthy();
20
+ });
21
+ });
@@ -0,0 +1,304 @@
1
+ import { ChangeDetectorRef, Component, Input, OnChanges, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
2
+ import { FrameworkLibraryService, JsonSchemaFormService, addClasses, inArray } from '@ng-formworks/core';
3
+ import _, { cloneDeep, map } from 'lodash';
4
+ import { Subscription } from 'rxjs';
5
+ import { css_fw } from './css-framework.defs';
6
+ import { CssframeworkService } from './css-framework.service';
7
+
8
+ @Component({
9
+ selector: 'css-framework',
10
+ templateUrl: './css-framework.component.html',
11
+ styleUrls: ['./css-framework.component.scss'],
12
+ encapsulation: ViewEncapsulation.None
13
+ })
14
+ export class CssFrameworkComponent implements OnInit, OnChanges,OnDestroy {
15
+ frameworkInitialized = false;
16
+ widgetOptions: any; // Options passed to child widget
17
+ widgetLayoutNode: any; // layoutNode passed to child widget
18
+ options: any; // Options used in this framework
19
+ formControl: any = null;
20
+ debugOutput: any = '';
21
+ debug: any = '';
22
+ parentArray: any = null;
23
+ isOrderable = false;
24
+ @Input() layoutNode: any;
25
+ @Input() layoutIndex: number[];
26
+ @Input() dataIndex: number[];
27
+
28
+ @Input() widgetStyles: css_fw.widgetstyles;
29
+
30
+
31
+
32
+
33
+
34
+ //TODO-move to ng-formworks/core utility.functions.ts
35
+ applyCssClasses(type, widgetOptions, styleOptions) {
36
+ //console.log("applyCssClasses for type:"+type);
37
+ let cssClasses = this.widgetStyles[type];
38
+ if (!cssClasses || _.isEmpty(cssClasses) ) {
39
+ cssClasses = this.widgetStyles.default;
40
+ }
41
+ Object.keys(cssClasses).forEach(catName => {
42
+ let classList = cssClasses[catName];
43
+
44
+ if (classList.length) {
45
+ widgetOptions[catName] = addClasses(widgetOptions[catName], classList);
46
+ }
47
+ if (styleOptions) {
48
+ widgetOptions[catName] = addClasses(widgetOptions[catName], styleOptions);
49
+ }
50
+
51
+ })
52
+ }
53
+
54
+ flattenWidgetStyles(wstyles:css_fw.widgetstyles){
55
+ var flattened:any={};
56
+ let ignore=['__themes__'];
57
+ Object.keys(wstyles).forEach(wkey=>{
58
+ let wstyle=wstyles[wkey];
59
+ if(ignore.indexOf(wkey)>=0){
60
+ flattened[wkey]=wstyle;
61
+ return;
62
+ }
63
+ if(_.isArray(wstyle)){
64
+
65
+ flattened[wkey]=wstyle.join(" ");
66
+ }
67
+ if(_.isObject(wstyle)){//is csscategories
68
+ flattened[wkey]=flattened[wkey]||{};
69
+ Object.keys(wstyle).forEach(catName=>{
70
+ let cssCat=wstyle[catName];
71
+
72
+ if(_.isArray(cssCat)){
73
+ flattened[wkey][catName]=cssCat.join(" ");
74
+ }else{
75
+ flattened[wkey][catName]=cssCat;
76
+ }
77
+ })
78
+ }
79
+ if(_.isString(wstyle)){
80
+ flattened[wkey]=wstyle;
81
+ }
82
+ })
83
+ return flattened
84
+ }
85
+
86
+ defaultStyling:css_fw.widgetstyles={
87
+ array:{},
88
+ default:{fieldHtmlClass: "cssfw-form-control"},
89
+ __themes__:[{name:'notheme',text:'None'}],
90
+ __remove_item__:"cssfw-remove-item",
91
+ __array_item_nonref__:{
92
+ "htmlClass": "cssfw-array-item-nonref"
93
+ },
94
+ __active__:{activeClass:"cssfw-active"},
95
+ __array__:{htmlClass:"cssfw-array"},
96
+ __control_label__:{labelHtmlClass:"cssfw-control-label"},
97
+ __form_group__:{htmlClass: "cssfw-form-group"},
98
+ __field_addon_left__:"cssfw-addon-left",
99
+ __field_addon_right__:"cssfw-addon-right",
100
+ __help_block__:"cssfw-help-block",
101
+ __required_asterisk__:"cssfw-required-astersisk",
102
+ __screen_reader__: "cssfw-screen-reader"
103
+
104
+ }
105
+
106
+
107
+
108
+
109
+ theme:string
110
+ frameworkThemeSubs:Subscription;
111
+ constructor(
112
+ public changeDetector: ChangeDetectorRef,
113
+ public jsf: JsonSchemaFormService,
114
+ public jsfFLService:FrameworkLibraryService,
115
+ public cssFWService:CssframeworkService
116
+ /*@Inject(CSS_FRAMEWORK_CFG ) fwcfg: css_fw.frameworkcfg*/
117
+
118
+ ) {
119
+
120
+ let activeFramework:any=this.jsfFLService.activeFramework;
121
+ let fwcfg=activeFramework.config||{};
122
+ this.widgetStyles = Object.assign(this.defaultStyling,fwcfg.widgetstyles);
123
+ let defaultTheme=this.widgetStyles.__themes__[0];
124
+ let defaultThemeName=cssFWService.activeRequestedTheme||defaultTheme.name;
125
+ this.theme=this.options?.theme|| defaultThemeName;
126
+ this.frameworkThemeSubs=cssFWService.frameworkTheme$.subscribe(newTheme=>{
127
+ this.theme=newTheme;
128
+ })
129
+
130
+ }
131
+
132
+ ngOnDestroy(): void {
133
+ this.frameworkThemeSubs.unsubscribe();
134
+ this.frameworkThemeSubs=null;
135
+ }
136
+
137
+
138
+ get showRemoveButton(): boolean {
139
+ if (!this.options.removable || this.options.readonly ||
140
+ this.layoutNode.type === '$ref'
141
+ ) {
142
+ return false;
143
+ }
144
+ if (this.layoutNode.recursiveReference) {
145
+ return true;
146
+ }
147
+ if (!this.layoutNode.arrayItem || !this.parentArray) {
148
+ return false;
149
+ }
150
+ // If array length <= minItems, don't allow removing any items
151
+ return this.parentArray.items.length - 1 <= this.parentArray.options.minItems ? false :
152
+ // For removable list items, allow removing any item
153
+ this.layoutNode.arrayItemType === 'list' ? true :
154
+ // For removable tuple items, only allow removing last item in list
155
+ this.layoutIndex[this.layoutIndex.length - 1] === this.parentArray.items.length - 2;
156
+ }
157
+
158
+ ngOnInit() {
159
+ this.initializeFramework();
160
+ if (this.layoutNode.arrayItem && this.layoutNode.type !== '$ref') {
161
+ this.parentArray = this.jsf.getParentNode(this);
162
+ if (this.parentArray) {
163
+ this.isOrderable = this.layoutNode.arrayItemType === 'list' &&
164
+ !this.options.readonly && this.parentArray.options.orderable;
165
+ }
166
+ }
167
+ }
168
+
169
+ ngOnChanges() {
170
+ if (!this.frameworkInitialized) {
171
+ this.initializeFramework();
172
+ }
173
+ }
174
+
175
+ initializeFramework() {
176
+ if (this.layoutNode) {
177
+ this.options = cloneDeep(this.layoutNode.options);
178
+ this.widgetLayoutNode = {
179
+ ...this.layoutNode,
180
+ options: cloneDeep(this.layoutNode.options)
181
+ };
182
+ this.widgetOptions = this.widgetLayoutNode.options;
183
+ this.formControl = this.jsf.getFormControl(this);
184
+
185
+ this.options.isInputWidget = inArray(this.layoutNode.type, [
186
+ 'button', 'checkbox', 'checkboxes-inline', 'checkboxes', 'color',
187
+ 'date', 'datetime-local', 'datetime', 'email', 'file', 'hidden',
188
+ 'image', 'integer', 'month', 'number', 'password', 'radio',
189
+ 'radiobuttons', 'radios-inline', 'radios', 'range', 'reset', 'search',
190
+ 'select', 'submit', 'tel', 'text', 'textarea', 'time', 'url', 'week'
191
+ ]);
192
+
193
+ this.options.title = this.setTitle();
194
+
195
+ this.options.htmlClass =
196
+ addClasses(this.options.htmlClass, 'schema-form-' + this.layoutNode.type);
197
+
198
+
199
+ if (this.layoutNode.type === 'array') {
200
+ this.options.htmlClass = addClasses(this.options.htmlClass, this.widgetStyles.__array__.htmlClass);
201
+ } else if (this.layoutNode.arrayItem && this.layoutNode.type !== '$ref') {
202
+ this.options.htmlClass = addClasses(this.options.htmlClass, this.widgetStyles.__array_item_nonref__.htmlClass);
203
+ } else {
204
+ this.options.htmlClass = addClasses(this.options.htmlClass, this.widgetStyles.__form_group__.htmlClass);
205
+ }
206
+
207
+
208
+ /*
209
+ this.options.htmlClass =
210
+ this.layoutNode.type === 'array' ?
211
+ addClasses(this.options.htmlClass, ['border','shadow-md','p-1']) :
212
+ this.layoutNode.arrayItem && this.layoutNode.type !== '$ref' ?
213
+ addClasses(this.options.htmlClass, ['border','shadow-md','p-1']) :
214
+ addClasses(this.options.htmlClass, 'mb-1');
215
+ */
216
+
217
+ /*
218
+ this.options.htmlClass =
219
+ this.layoutNode.type === 'array' ?
220
+ addClasses(this.options.htmlClass, this.widgetStyles.array.htmlClass):
221
+ this.layoutNode.arrayItem && this.layoutNode.type !== '$ref' ?
222
+ addClasses(this.options.htmlClass, this.widgetStyles.__array_item_nonref__.htmlClass):
223
+ addClasses(this.options.htmlClass, this.widgetStyles.__form_group__.htmlClass);
224
+ */
225
+
226
+ this.widgetOptions.htmlClass = '';
227
+ this.options.labelHtmlClass =
228
+ addClasses(this.options.labelHtmlClass, this.widgetStyles.__control_label__.labelHtmlClass);
229
+ this.widgetOptions.activeClass =
230
+ addClasses(this.widgetOptions.activeClass, this.widgetStyles.__active__.activeClass);
231
+ this.options.fieldAddonLeft =
232
+ this.options.fieldAddonLeft || this.options.prepend;
233
+ this.options.fieldAddonRight =
234
+ this.options.fieldAddonRight || this.options.append;
235
+
236
+ // Add asterisk to titles if required
237
+ if (this.options.title && this.layoutNode.type !== 'tab' &&
238
+ !this.options.notitle && this.options.required &&
239
+ !this.options.title.includes('*')
240
+ ) {
241
+ let required_asterisk_class=this.widgetStyles.__required_asterisk__||'text-danger'
242
+ this.options.title += ` <strong class="${required_asterisk_class}">*</strong>`;
243
+ }
244
+ if (this.layoutNode.type == 'optionfieldset') {
245
+ this.options.messageLocation = 'top';
246
+ }
247
+ // Set miscelaneous styles and settings for each control type
248
+ this.applyCssClasses(this.layoutNode.type, this.widgetOptions, this.options.style);
249
+ if (this.formControl) {
250
+ this.updateHelpBlock(this.formControl.status);
251
+ this.formControl.statusChanges.subscribe(status => this.updateHelpBlock(status));
252
+
253
+ if (this.options.debug) {
254
+ const vars: any[] = [];
255
+ this.debugOutput = map(vars, thisVar => JSON.stringify(thisVar, null, 2)).join('\n');
256
+ }
257
+ }
258
+ this.frameworkInitialized = true;
259
+ }
260
+
261
+ }
262
+
263
+ updateHelpBlock(status) {
264
+ this.options.helpBlock = status === 'INVALID' &&
265
+ this.options.enableErrorState && this.formControl.errors &&
266
+ (this.formControl.dirty || this.options.feedbackOnRender) ?
267
+ this.jsf.formatErrors(this.formControl.errors, this.options.validationMessages) :
268
+ this.options.description || this.options.help || null;
269
+ }
270
+
271
+ setTitle(): string {
272
+ switch (this.layoutNode.type) {
273
+ case 'button':
274
+ case 'checkbox':
275
+ case 'section':
276
+ case 'help':
277
+ case 'msg':
278
+ case 'submit':
279
+ case 'message':
280
+ case 'tabarray':
281
+ case 'tabs':
282
+ case '$ref':
283
+ return null;
284
+ case 'advancedfieldset':
285
+ this.widgetOptions.expandable = true;
286
+ this.widgetOptions.title = 'Advanced options';
287
+ return null;
288
+ case 'authfieldset':
289
+ this.widgetOptions.expandable = true;
290
+ this.widgetOptions.title = 'Authentication settings';
291
+ return null;
292
+ case 'fieldset':
293
+ this.widgetOptions.title = this.options.title;
294
+ return null;
295
+ default:
296
+ this.widgetOptions.title = null;
297
+ return this.jsf.setItemTitle(this);
298
+ }
299
+ }
300
+
301
+ removeItem() {
302
+ this.jsf.removeItem(this);
303
+ }
304
+ }
@@ -0,0 +1,78 @@
1
+ import { InjectionToken } from "@angular/core";
2
+
3
+ export const CSS_FRAMEWORK_CFG = new InjectionToken<css_fw.frameworkcfg>('CSS_FRAMEWORK_CFG');
4
+
5
+ export namespace css_fw{
6
+
7
+ export type themeKV=
8
+ {
9
+ name:string,
10
+ text:string
11
+ }
12
+
13
+ export class csscategories{
14
+ fieldHtmlClass?:string|string[]
15
+ labelHtmlClass?:string|string[]
16
+ htmlClass?:string|string[]
17
+ itemLabelHtmlClass?:string|string[]
18
+ activeClass?:string|string[]
19
+ }
20
+
21
+ export type widgetstyles={
22
+ '$ref'?:csscategories,
23
+ 'alt-date'?:csscategories,
24
+ 'alt-datetime'?:csscategories,
25
+ __themes__?:themeKV[],
26
+ __array_item_nonref__:csscategories,
27
+ __form_group__:csscategories,
28
+ __control_label__:csscategories,
29
+ __active__:csscategories,
30
+ __required_asterisk__:string,
31
+ __array__:csscategories,
32
+ '__remove_item__':string,
33
+ __help_block__:string,
34
+ __field_addon_left__:string
35
+ __field_addon_right__:string,
36
+ __screen_reader__:string,
37
+ array:csscategories,
38
+ authfieldset?:csscategories,
39
+ advancedfieldset?:csscategories,
40
+ button?:csscategories,
41
+ checkbox?:csscategories,
42
+ checkboxes?:csscategories,
43
+ checkboxbuttons?:csscategories,
44
+ 'checkboxes-inline'?:csscategories,
45
+ date?:csscategories,
46
+ 'datetime-local'?:csscategories,
47
+ fieldset?:csscategories,
48
+ integer?:csscategories,
49
+ number?:csscategories,
50
+ optionfieldset?:csscategories,
51
+ password?:csscategories,
52
+ radiobuttons?:csscategories,
53
+ radio?:csscategories,
54
+ radios?:csscategories,
55
+ "radios-inline"?:csscategories,
56
+ 'range'?:csscategories,
57
+ section?:csscategories,
58
+ selectfieldset?:csscategories,
59
+ select?:csscategories,
60
+ submit?:csscategories,
61
+ text?:csscategories,
62
+ tabs?:csscategories,
63
+ tabarray?:csscategories,
64
+ textarea?:csscategories,
65
+ default:csscategories
66
+ }
67
+ export type frameworkcfg={
68
+ name:string,
69
+ text:string;
70
+ stylesheets:string[],
71
+ scripts?:string[],
72
+ widgetstyles:widgetstyles,
73
+ widgets?:any;
74
+ }
75
+
76
+
77
+
78
+ }
@@ -0,0 +1,29 @@
1
+ import { CommonModule } from '@angular/common';
2
+ import { NgModule } from '@angular/core';
3
+ import { FrameworkLibraryService, JsonSchemaFormModule, JsonSchemaFormService, WidgetLibraryModule, WidgetLibraryService } from '@ng-formworks/core';
4
+ import { CssFrameworkComponent } from './css-framework.component';
5
+ import { CssframeworkService } from './css-framework.service';
6
+
7
+
8
+
9
+ @NgModule({
10
+ declarations: [
11
+ CssFrameworkComponent
12
+ ],
13
+ imports: [
14
+ JsonSchemaFormModule,
15
+ CommonModule,
16
+ WidgetLibraryModule,
17
+ ],
18
+ exports: [
19
+ CssFrameworkComponent
20
+ ],
21
+ providers: [
22
+ JsonSchemaFormService,
23
+ FrameworkLibraryService,
24
+ WidgetLibraryService,
25
+ CssframeworkService
26
+ // { provide: Framework, useClass: CssFramework, multi: true },
27
+ ]
28
+ })
29
+ export class CssFrameworkModule { }
@@ -0,0 +1,16 @@
1
+ import { TestBed } from '@angular/core/testing';
2
+
3
+ import { CssframeworkService } from './css-framework.service';
4
+
5
+ describe('CssframeworkService', () => {
6
+ let service: CssframeworkService;
7
+
8
+ beforeEach(() => {
9
+ TestBed.configureTestingModule({});
10
+ service = TestBed.inject(CssframeworkService);
11
+ });
12
+
13
+ it('should be created', () => {
14
+ expect(service).toBeTruthy();
15
+ });
16
+ });
@@ -0,0 +1,33 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { Observable, Subject } from 'rxjs';
3
+
4
+ @Injectable({
5
+ providedIn: 'root'
6
+ })
7
+ export class CssframeworkService {
8
+
9
+ frameworkTheme$: Observable<string>;
10
+ activeRequestedTheme:string;
11
+ frameworkThemeSubject: Subject<string>;
12
+ constructor() {
13
+ this.frameworkThemeSubject = new Subject<string>();
14
+ this.frameworkTheme$ = this.frameworkThemeSubject.asObservable();
15
+ }
16
+
17
+ //TODO-review: this acts as a public api to change the theme
18
+ //but doesn't do the actual change, instead it relies on
19
+ //the CssFramewkCoromponent having subscribed to listen
20
+ //and perform the actual theme change
21
+ requestThemeChange(themeName:string){
22
+ this.frameworkThemeSubject.next(themeName);
23
+ this.activeRequestedTheme=themeName;
24
+ }
25
+
26
+ //TODO-review:there's no way of knowing what the individual component instance
27
+ //has set its theme to, this is just the theme made through the requestThemeChange
28
+ //calls and not guaranteed to correspond to the actual theme set by the
29
+ //component instance themselves
30
+ getActiveRequestedTheme():string{
31
+ return this.activeRequestedTheme;
32
+ }
33
+ }
@@ -0,0 +1,99 @@
1
+ import { Inject, Injectable } from '@angular/core';
2
+ import { Framework } from '@ng-formworks/core';
3
+ import { CssFrameworkComponent } from './css-framework.component';
4
+ import { CSS_FRAMEWORK_CFG, css_fw } from './css-framework.defs';
5
+ import { CssframeworkService } from './css-framework.service';
6
+
7
+
8
+
9
+ @Injectable()
10
+ export class CssFramework extends Framework {
11
+ name = 'css';
12
+
13
+ framework:any = CssFrameworkComponent;
14
+ config:css_fw.frameworkcfg
15
+ constructor(@Inject(CSS_FRAMEWORK_CFG ) cfg:css_fw.frameworkcfg,public cssFWService:CssframeworkService){
16
+ super();
17
+
18
+ this.name=cfg.name;
19
+ this.text=cfg.text||this.name;
20
+ this.stylesheets=cfg.stylesheets;
21
+ this.scripts=cfg.scripts;
22
+ this.config=cfg;
23
+ this.widgets=cfg.widgets;
24
+ }
25
+ getActiveTheme():css_fw.themeKV{
26
+ let activeRequestedThemeName=this.cssFWService.getActiveRequestedTheme();
27
+ let frameWorkThemes=this.config?.widgetstyles?.__themes__;
28
+
29
+ let theme=frameWorkThemes && frameWorkThemes[0]
30
+ if(activeRequestedThemeName){//if not set return first theme in config;
31
+ theme={name:activeRequestedThemeName,text:activeRequestedThemeName};
32
+ if(frameWorkThemes){
33
+ let filtered=frameWorkThemes.filter(theme=>{return theme.name==activeRequestedThemeName});
34
+ theme=(filtered && filtered[0])||theme;
35
+ }
36
+ }
37
+ return theme;
38
+ }
39
+
40
+ requestThemeChange(name:string){
41
+ this.cssFWService.requestThemeChange(name);
42
+ }
43
+
44
+ registerTheme(newTheme:css_fw.themeKV,overwrite:boolean=true):boolean{
45
+ let themeList=this.config?.widgetstyles?.__themes__||[];
46
+ let matchedThemes=themeList.filter(theme=>{return newTheme.name==theme.name});
47
+ if(matchedThemes && matchedThemes[0]){
48
+ if(overwrite){
49
+ matchedThemes[0].text=newTheme.text;
50
+ return true;
51
+ }
52
+ if(!overwrite){
53
+ return false;
54
+ }
55
+
56
+ }
57
+ if(!matchedThemes || matchedThemes.length==0){
58
+ let cfg:any=this.config
59
+ cfg.widgetstyles= this.config.widgetstyles||{};
60
+ cfg.widgetstyles.__themes__=cfg.widgetstyles.__themes__||[];
61
+ cfg.widgetstyles.__themes__.push(newTheme);
62
+ return true;
63
+ }
64
+ };
65
+
66
+ unregisterTheme(name:string):boolean{
67
+ let themeList=this.config?.widgetstyles?.__themes__;
68
+ let foundInd=-1;
69
+ if(themeList){
70
+ themeList.forEach((theme,ind)=>{
71
+ if(name==theme.name){
72
+ foundInd=ind;
73
+ }
74
+ });
75
+ if(foundInd>=0){
76
+ themeList.splice(foundInd,1);
77
+ return true;
78
+ }
79
+ }
80
+ return false;
81
+ }
82
+
83
+ getConfig():css_fw.frameworkcfg{
84
+ return this.config;
85
+ }
86
+
87
+ /*
88
+ stylesheets = [
89
+ //TODO-enable for dev only
90
+ cdn.tailwindcss.com/3.3.3'
91
+ ];
92
+
93
+
94
+ scripts = [
95
+
96
+ ];
97
+ */
98
+
99
+ }
@@ -0,0 +1,10 @@
1
+ /*
2
+ * Public API Surface of ng-formworks-cssframework
3
+ */
4
+
5
+ export * from './lib/css-framework.component';
6
+ export * from './lib/css-framework.defs';
7
+ export * from './lib/css-framework.module';
8
+ export * from './lib/css-framework.service';
9
+ export * from './lib/css.framework';
10
+
@@ -0,0 +1,14 @@
1
+ /* To learn more about this file see: https://angular.io/config/tsconfig. */
2
+ {
3
+ "extends": "../../tsconfig.json",
4
+ "compilerOptions": {
5
+ "outDir": "../../out-tsc/lib",
6
+ "declaration": true,
7
+ "declarationMap": true,
8
+ "inlineSources": true,
9
+ "types": []
10
+ },
11
+ "exclude": [
12
+ "**/*.spec.ts"
13
+ ]
14
+ }
@@ -0,0 +1,10 @@
1
+ /* To learn more about this file see: https://angular.io/config/tsconfig. */
2
+ {
3
+ "extends": "./tsconfig.lib.json",
4
+ "compilerOptions": {
5
+ "declarationMap": false
6
+ },
7
+ "angularCompilerOptions": {
8
+ "compilationMode": "partial"
9
+ }
10
+ }
@@ -0,0 +1,14 @@
1
+ /* To learn more about this file see: https://angular.io/config/tsconfig. */
2
+ {
3
+ "extends": "../../tsconfig.json",
4
+ "compilerOptions": {
5
+ "outDir": "../../out-tsc/spec",
6
+ "types": [
7
+ "jasmine"
8
+ ]
9
+ },
10
+ "include": [
11
+ "**/*.spec.ts",
12
+ "**/*.d.ts"
13
+ ]
14
+ }