@ng-zen/cli 20.0.0 → 20.1.0-next.1

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 CHANGED
@@ -1,3 +1,10 @@
1
+ ## [20.1.0-next.1](https://github.com/kstepien3/ng-zen/compare/v20.0.0...v20.1.0-next.1) (2025-07-30)
2
+
3
+ ### 🚀 New Features
4
+
5
+ * **checkbox:** add indeterminate state if value is null ([#260](https://github.com/kstepien3/ng-zen/issues/260)) ([d13c241](https://github.com/kstepien3/ng-zen/commit/d13c2416984df1de188082760aadfe280c7ed315))
6
+ * **form-control:** add abstract logic for form control components ([#252](https://github.com/kstepien3/ng-zen/issues/252)) ([10e66b4](https://github.com/kstepien3/ng-zen/commit/10e66b4b0606a05d02ba527de42407129e085cbe))
7
+
1
8
  ## [20.0.0](https://github.com/kstepien3/ng-zen/compare/v19.4.0...v20.0.0) (2025-07-22)
2
9
 
3
10
  ### ⚠ BREAKING CHANGES
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ng-zen/cli",
3
- "version": "20.0.0",
3
+ "version": "20.1.0-next.1",
4
4
  "description": "A CLI tool for generating customizable, modern Angular UI components using schematics.",
5
5
  "license": "BSD-2-Clause",
6
6
  "private": false,
@@ -1 +1 @@
1
- {"version":3,"file":"components-generator.js","sourceRoot":"","sources":["../../../../../src/schematics/components/components-generator.ts"],"names":[],"mappings":"","sourcesContent":["import { GeneratorSchemaBase } from '../../types';\n\nexport type ComponentType =\n | 'avatar'\n | 'button'\n | 'checkbox'\n | 'divider'\n | 'icon'\n | 'input'\n | 'skeleton'\n | 'switch'\n | 'textarea';\n\nexport interface ComponentGeneratorSchema extends GeneratorSchemaBase {\n components: ComponentType[];\n}\n"]}
1
+ {"version":3,"file":"components-generator.js","sourceRoot":"","sources":["../../../../../src/schematics/components/components-generator.ts"],"names":[],"mappings":"","sourcesContent":["import { GeneratorSchemaBase } from '../../types';\n\nexport type ComponentType =\n | 'avatar'\n | 'button'\n | 'checkbox'\n | 'divider'\n | 'form-control'\n | 'icon'\n | 'input'\n | 'skeleton'\n | 'switch'\n | 'textarea';\n\nexport interface ComponentGeneratorSchema extends GeneratorSchemaBase {\n components: ComponentType[];\n}\n"]}
@@ -5,6 +5,7 @@ export type ComponentType =
5
5
  | 'button'
6
6
  | 'checkbox'
7
7
  | 'divider'
8
+ | 'form-control'
8
9
  | 'icon'
9
10
  | 'input'
10
11
  | 'skeleton'
@@ -7,16 +7,17 @@ export default {
7
7
  component: ZenCheckbox,
8
8
  tags: ['autodocs'],
9
9
  argTypes: {
10
- value: { control: 'boolean' },
10
+ value: {
11
+ control: 'radio',
12
+ options: [true, false, null],
13
+ },
11
14
  disabled: { control: 'boolean' },
12
15
  required: { control: 'boolean' },
13
- id: { control: 'text' },
14
16
  },
15
17
  args: {
16
18
  value: false,
17
19
  disabled: false,
18
20
  required: false,
19
- id: '',
20
21
  },
21
22
  } satisfies Meta<ZenCheckbox>;
22
23
 
@@ -29,7 +30,6 @@ export const Default: Story = {
29
30
  <zen-checkbox
30
31
  [disabled]="${args.disabled}"
31
32
  [value]="${args.value}"
32
- ${args.id ? 'id="' + args.id + '"' : ''}
33
33
  ${args.required ? 'required' : ''}
34
34
  />`,
35
35
  }),
@@ -1,5 +1,7 @@
1
- import { booleanAttribute, ChangeDetectionStrategy, Component, forwardRef, input, model } from '@angular/core';
2
- import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
1
+ import { ChangeDetectionStrategy, Component, effect, ElementRef, model, viewChild } from '@angular/core';
2
+ import { FormsModule } from '@angular/forms';
3
+
4
+ import { ZenFormControl, ZenFormControlProvider } from '../form-control';
3
5
 
4
6
  /**
5
7
  * ZenCheckbox is a reusable checkbox component designed to provide
@@ -8,7 +10,9 @@ import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/f
8
10
  * for boolean values.
9
11
  *
10
12
  * @example
11
- * <zen-checkbox value="false" />
13
+ * <zen-checkbox [value]="true" /> Checked
14
+ * <zen-checkbox [value]="false" /> Unchecked
15
+ * <zen-checkbox [value]="null" /> Indeterminate
12
16
  *
13
17
  * ### CSS Custom Properties
14
18
  *
@@ -25,7 +29,7 @@ import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/f
25
29
  * }
26
30
  * ```
27
31
  *
28
- * @implements {ControlValueAccessor}
32
+ * @implements {ZenFormControl<boolean>}
29
33
  *
30
34
  * @author Konrad Stępień
31
35
  * @license {@link https://github.com/kstepien3/ng-zen/blob/master/LICENSE|BSD-2-Clause}
@@ -37,10 +41,9 @@ import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/f
37
41
  template: `
38
42
  <input
39
43
  [attr.aria-disabled]="disabled()"
40
- [attr.id]="id()"
41
44
  [disabled]="disabled()"
42
45
  [ngModel]="value()"
43
- (ngModelChange)="onInputChange($event)"
46
+ (ngModelChange)="onInput($event)"
44
47
  #inputElement
45
48
  type="checkbox"
46
49
  />
@@ -54,59 +57,25 @@ import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/f
54
57
  styleUrls: ['./checkbox.scss'],
55
58
  changeDetection: ChangeDetectionStrategy.OnPush,
56
59
  imports: [FormsModule],
57
- providers: [
58
- {
59
- provide: NG_VALUE_ACCESSOR,
60
- useExisting: forwardRef(() => ZenCheckbox),
61
- multi: true,
62
- },
63
- ],
60
+ providers: [ZenFormControlProvider(ZenCheckbox)],
64
61
  host: {
65
62
  '(blur)': 'onTouched()',
66
63
  },
67
64
  })
68
- export class ZenCheckbox implements ControlValueAccessor {
69
- /** Holds the current checkbox value. */
70
- readonly value = model(false);
71
- /** Determines if the checkbox is disabled. */
72
- readonly disabled = model(false);
73
- /** Determines if the input is required.*/
74
- readonly required = input(false, { transform: booleanAttribute });
75
- /** Sets the HTML id attribute for the checkbox element. */
76
- readonly id = input<string>();
77
-
78
- /** @ignore */
79
- // eslint-disable-next-line @typescript-eslint/no-empty-function
80
- onChange: (value: boolean) => void = () => {};
81
- /** @ignore */
82
- // eslint-disable-next-line @typescript-eslint/no-empty-function
83
- onTouched: () => void = () => {};
84
-
85
- /** @ignore */
86
- writeValue(value: boolean): void {
87
- this.value.set(value);
88
- }
89
-
65
+ export class ZenCheckbox extends ZenFormControl<boolean | null> {
66
+ /**
67
+ * Holds the current checkbox value.
68
+ * Set value to `null` to mark the checkbox as indeterminate
69
+ */
70
+ readonly value = model<boolean | null>(false);
90
71
  /** @ignore */
91
- registerOnChange(fn: (value: boolean) => void): void {
92
- this.onChange = fn;
93
- }
94
-
95
- /** @ignore */
96
- registerOnTouched(fn: () => void): void {
97
- this.onTouched = fn;
98
- }
99
-
100
- /** @ignore */
101
- setDisabledState(isDisabled: boolean): void {
102
- this.disabled.set(isDisabled);
103
- }
72
+ private readonly inputElement = viewChild.required<ElementRef<HTMLInputElement>>('inputElement');
104
73
 
105
- /** Handles checkbox change event */
106
- onInputChange(value: boolean): void {
107
- if (this.disabled()) return;
74
+ constructor() {
75
+ super();
108
76
 
109
- this.value.set(value);
110
- this.onChange(value);
77
+ effect(() => {
78
+ if (this.value() === null) this.inputElement().nativeElement.indeterminate = true;
79
+ });
111
80
  }
112
81
  }
@@ -0,0 +1,31 @@
1
+ import { Component, model } from '@angular/core';
2
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
3
+
4
+ import { ZenFormControl, ZenFormControlProvider } from './form-control';
5
+
6
+ @Component({
7
+ template: '...',
8
+ providers: [ZenFormControlProvider(FormControl)],
9
+ })
10
+ class FormControl extends ZenFormControl<string> {
11
+ readonly value = model<string>('');
12
+ }
13
+
14
+ describe('FormControl', () => {
15
+ let component: FormControl;
16
+ let fixture: ComponentFixture<FormControl>;
17
+
18
+ beforeEach(async () => {
19
+ await TestBed.configureTestingModule({
20
+ imports: [FormControl],
21
+ }).compileComponents();
22
+
23
+ fixture = TestBed.createComponent(FormControl);
24
+ component = fixture.componentInstance;
25
+ fixture.detectChanges();
26
+ });
27
+
28
+ it('should create', () => {
29
+ expect(component).toBeTruthy();
30
+ });
31
+ });
@@ -0,0 +1,37 @@
1
+ import { Meta, moduleMetadata } from '@storybook/angular';
2
+
3
+ import { ZenCheckbox } from '../checkbox';
4
+ import { ZenInput } from '../input';
5
+ import { ZenSwitch } from '../switch';
6
+ import { ZenFormControl } from './form-control';
7
+
8
+ export default {
9
+ title: 'Components/FormControl',
10
+ component: ZenFormControl,
11
+ tags: ['autodocs'],
12
+ decorators: [moduleMetadata({ imports: [ZenCheckbox, ZenInput, ZenSwitch] })],
13
+ args: {
14
+ value: '',
15
+ disabled: false,
16
+ required: false,
17
+ },
18
+ argTypes: {
19
+ value: { control: false },
20
+ placeholder: { control: false },
21
+ disabled: { control: 'boolean' },
22
+ required: { control: 'boolean' },
23
+ },
24
+ parameters: {
25
+ docs: {
26
+ canvas: {
27
+ // This will remove the "show code" button
28
+ // https://storybook.js.org/docs/api/doc-blocks/doc-block-canvas#sourcestate
29
+ sourceState: 'none',
30
+ },
31
+ },
32
+ },
33
+ } satisfies Meta<ZenFormControl<unknown>>;
34
+
35
+ export { Default as Checkbox } from '../checkbox/checkbox.stories';
36
+ export { Default as Input } from '../input/input.stories';
37
+ export { Default as Switch } from '../switch/switch.stories';
@@ -0,0 +1,116 @@
1
+ import { booleanAttribute, Directive, forwardRef, input, model, ModelSignal, Type } from '@angular/core';
2
+ import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
3
+
4
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5
+ export const ZenFormControlProvider = <T extends ZenFormControl<any>>(component: Type<T>) => ({
6
+ provide: NG_VALUE_ACCESSOR,
7
+ useExisting: forwardRef(() => component),
8
+ multi: true,
9
+ });
10
+
11
+ /**
12
+ * A base class for creating custom Angular form controls that integrate with both
13
+ * template-driven and reactive forms. It simplifies the implementation of the
14
+ * ControlValueAccessor interface by using signals for the control's value and state.
15
+ *
16
+ * Subclasses must provide an implementation for the abstract `value` property.
17
+ *
18
+ * @example
19
+ *
20
+ * ```ts
21
+ * @Component({
22
+ * template: '...',
23
+ * providers: [ZenFormControlProvider(ZenInput)]
24
+ * })
25
+ * export class Input extends ZenFormControl<string> {
26
+ * readonly value = model<string>('')
27
+ * }
28
+ * ```
29
+ *
30
+ * @implements {ControlValueAccessor}
31
+ *
32
+ * @author Konrad Stępień
33
+ * @license {@link https://github.com/kstepien3/ng-zen/blob/master/LICENSE|BSD-2-Clause}
34
+ * @see [GitHub](https://github.com/kstepien3/ng-zen)
35
+ */
36
+ @Directive({})
37
+ export abstract class ZenFormControl<Value> implements ControlValueAccessor {
38
+ /**
39
+ * The underlying value of the control.
40
+ * Subclasses must provide their own implementation, typically using `model()`.
41
+ */
42
+ abstract readonly value: ModelSignal<Value>;
43
+
44
+ /** The placeholder text for the form control. */
45
+ readonly placeholder = input<string>();
46
+
47
+ /**
48
+ * Whether the form control is disabled.
49
+ */
50
+ readonly disabled = model(false);
51
+
52
+ /** Whether the form control is required. */
53
+ readonly required = input(false, { transform: booleanAttribute });
54
+
55
+ /**
56
+ * @internal For internal use by Angular forms.
57
+ * @ignore
58
+ */
59
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
60
+ onChange: (value: Value) => void = () => {};
61
+
62
+ /**
63
+ * @internal For internal use by Angular forms.
64
+ * @ignore
65
+ */
66
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
67
+ onTouched: () => void = () => {};
68
+
69
+ /**
70
+ * Should be called by the subclass when the control's value changes
71
+ * as a result of user interaction. This method updates the control's value
72
+ * and notifies Angular of the change.
73
+ */
74
+ onInput(value: Value): void {
75
+ if (this.disabled()) return;
76
+
77
+ this.value.set(value);
78
+ this.onChange(this.value());
79
+ }
80
+
81
+ /**
82
+ * Writes a new value to the element.
83
+ * @internal For internal use by Angular forms.
84
+ * @ignore
85
+ */
86
+ writeValue(value: Value): void {
87
+ this.value.set(value);
88
+ }
89
+
90
+ /**
91
+ * Registers a callback function that is called when the control's value changes in the UI.
92
+ * @internal For internal use by Angular forms.
93
+ * @ignore
94
+ */
95
+ registerOnChange(fn: (value: Value) => void): void {
96
+ this.onChange = fn;
97
+ }
98
+
99
+ /**
100
+ * Registers a callback function that is called by the forms API on component touch.
101
+ * @internal For internal use by Angular forms.
102
+ * @ignore
103
+ */
104
+ registerOnTouched(fn: () => void): void {
105
+ this.onTouched = fn;
106
+ }
107
+
108
+ /**
109
+ * This function is called by the forms API when the control status changes to or from "DISABLED".
110
+ * @internal For internal use by Angular forms.
111
+ * @ignore
112
+ */
113
+ setDisabledState(isDisabled: boolean): void {
114
+ this.disabled.set(isDisabled);
115
+ }
116
+ }
@@ -0,0 +1 @@
1
+ export * from './form-control';
@@ -11,14 +11,12 @@ export default {
11
11
  placeholder: { control: 'text' },
12
12
  disabled: { control: 'boolean' },
13
13
  required: { control: 'boolean' },
14
- id: { control: 'text' },
15
14
  },
16
15
  args: {
17
16
  value: '',
18
17
  placeholder: '',
19
18
  disabled: false,
20
19
  required: false,
21
- id: '',
22
20
  },
23
21
  } satisfies Meta<ZenInput>;
24
22
 
@@ -31,7 +29,6 @@ export const Default: Story = {
31
29
  <zen-input
32
30
  [disabled]="${args.disabled}"
33
31
  [value]="'${args.value}'"
34
- ${args.id ? 'id="' + args.id + '"' : ''}
35
32
  ${args.placeholder ? 'placeholder="' + args.placeholder + '"' : ''}
36
33
  ${args.required ? 'required' : ''}
37
34
  />`,
@@ -1,5 +1,7 @@
1
- import { booleanAttribute, ChangeDetectionStrategy, Component, forwardRef, input, model } from '@angular/core';
2
- import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
1
+ import { ChangeDetectionStrategy, Component, model } from '@angular/core';
2
+ import { FormsModule } from '@angular/forms';
3
+
4
+ import { ZenFormControl, ZenFormControlProvider } from '../form-control/form-control';
3
5
 
4
6
  /**
5
7
  * ZenInput is a reusable text input component designed to provide
@@ -22,7 +24,7 @@ import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/f
22
24
  * }
23
25
  * ```
24
26
  *
25
- * @implements {ControlValueAccessor}
27
+ * @implements {ZenFormControl<string>}
26
28
  *
27
29
  * @author Konrad Stępień
28
30
  * @license {@link https://github.com/kstepien3/ng-zen/blob/master/LICENSE|BSD-2-Clause}
@@ -33,69 +35,20 @@ import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/f
33
35
  standalone: true,
34
36
  template: `
35
37
  <input
36
- [attr.id]="id()"
37
38
  [attr.placeholder]="placeholder()"
38
39
  [attr.required]="required()"
39
40
  [disabled]="disabled()"
40
41
  [ngModel]="value()"
41
42
  [value]="value()"
42
43
  (blur)="onTouched()"
43
- (ngModelChange)="onInputChange($event)"
44
+ (ngModelChange)="onInput($event)"
44
45
  />
45
46
  `,
46
47
  styleUrls: ['./input.scss'],
47
48
  changeDetection: ChangeDetectionStrategy.OnPush,
48
- providers: [
49
- {
50
- provide: NG_VALUE_ACCESSOR,
51
- useExisting: forwardRef(() => ZenInput),
52
- multi: true,
53
- },
54
- ],
49
+ providers: [ZenFormControlProvider(ZenInput)],
55
50
  imports: [FormsModule],
56
51
  })
57
- export class ZenInput implements ControlValueAccessor {
58
- /** Holds the current input value. */
52
+ export class ZenInput extends ZenFormControl<string> {
59
53
  readonly value = model('');
60
- /** Determines if the input is disabled. */
61
- readonly disabled = model(false);
62
- /** Determines if the input is required.*/
63
- readonly required = input(false, { transform: booleanAttribute });
64
- /** Sets the HTML id attribute for the input element.*/
65
- readonly id = input<string>();
66
- /** Provides a hint or example text that will be displayed */
67
- readonly placeholder = input<string>();
68
-
69
- /** @ignore */
70
- // eslint-disable-next-line @typescript-eslint/no-empty-function
71
- onChange: (value: string) => void = () => {};
72
- /** @ignore */
73
- // eslint-disable-next-line @typescript-eslint/no-empty-function
74
- onTouched: () => void = () => {};
75
-
76
- /** @ignore */
77
- writeValue(value: string): void {
78
- this.value.set(value);
79
- }
80
- /** @ignore */
81
- registerOnChange(fn: (value: string) => void): void {
82
- this.onChange = fn;
83
- }
84
- /** @ignore */
85
- registerOnTouched(fn: () => void): void {
86
- this.onTouched = fn;
87
- }
88
-
89
- /** @ignore */
90
- setDisabledState(isDisabled: boolean): void {
91
- this.disabled.set(isDisabled);
92
- }
93
-
94
- /** Handles input change event */
95
- onInputChange(value: string): void {
96
- if (this.disabled()) return;
97
-
98
- this.value.set(value);
99
- this.onChange(value);
100
- }
101
54
  }
@@ -1,5 +1,6 @@
1
- import { ChangeDetectionStrategy, Component, forwardRef, model } from '@angular/core';
2
- import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
1
+ import { ChangeDetectionStrategy, Component, model } from '@angular/core';
2
+
3
+ import { ZenFormControl, ZenFormControlProvider } from '../form-control';
3
4
 
4
5
  /**
5
6
  * ZenInput is a reusable text input component designed to provide
@@ -25,7 +26,7 @@ import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
25
26
  * }
26
27
  * ```
27
28
  *
28
- * @implements {ControlValueAccessor}
29
+ * @implements {ZenFormControl<boolean>}
29
30
  *
30
31
  * @author Konrad Stępień
31
32
  * @license {@link https://github.com/kstepien3/ng-zen/blob/master/LICENSE|BSD-2-Clause}
@@ -41,75 +42,19 @@ import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
41
42
  `,
42
43
  styleUrl: './switch.scss',
43
44
  changeDetection: ChangeDetectionStrategy.OnPush,
44
- providers: [
45
- {
46
- provide: NG_VALUE_ACCESSOR,
47
- useExisting: forwardRef(() => ZenSwitch),
48
- multi: true,
49
- },
50
- ],
45
+ providers: [ZenFormControlProvider(ZenSwitch)],
51
46
  host: {
52
47
  tabindex: '0',
53
48
  '[attr.data-disabled]': 'disabled()',
54
49
  '[attr.data-checked]': 'value()',
55
50
  '(blur)': 'onTouched()',
56
- '(click)': 'onInputChange(!this.value())',
51
+ '(click)': 'onInput(!this.value())',
57
52
  '(keydown)': 'onKeyDown($event)',
58
53
  },
59
54
  })
60
- export class ZenSwitch implements ControlValueAccessor {
55
+ export class ZenSwitch extends ZenFormControl<boolean> {
61
56
  /** Holds the current checkbox value. */
62
57
  readonly value = model(false);
63
- /** Determines if the checkbox is disabled. */
64
- readonly disabled = model(false);
65
-
66
- /** @ignore */
67
- // eslint-disable-next-line @typescript-eslint/no-empty-function
68
- onChange: (value: boolean) => void = () => {};
69
- /** @ignore */
70
- // eslint-disable-next-line @typescript-eslint/no-empty-function
71
- onTouched: () => void = () => {};
72
- /**
73
- * Writes a new value to the component.
74
- * @ignore
75
- */
76
- writeValue(value: boolean): void {
77
- this.value.set(value);
78
- }
79
-
80
- /**
81
- * Registers a function to be called when the value changes.
82
- * @ignore
83
- */
84
- registerOnChange(fn: (value: boolean) => void): void {
85
- this.onChange = fn;
86
- }
87
-
88
- /**
89
- * Registers a function to be called when the component is touched.
90
- * @ignore
91
- */
92
- registerOnTouched(fn: () => void): void {
93
- this.onTouched = fn;
94
- }
95
-
96
- /**
97
- * Sets the disabled state of the component.
98
- * @ignore
99
- */
100
- setDisabledState(isDisabled: boolean): void {
101
- this.disabled.set(isDisabled);
102
- }
103
-
104
- /**
105
- * Toggles the switch value and notifies the change.
106
- */
107
- onInputChange(value: boolean): void {
108
- if (this.disabled()) return;
109
-
110
- this.writeValue(value);
111
- this.onChange(value);
112
- }
113
58
 
114
59
  /**
115
60
  * Handles keyboard events for accessibility.
@@ -119,15 +64,15 @@ export class ZenSwitch implements ControlValueAccessor {
119
64
  case 'Enter':
120
65
  case 'Space': {
121
66
  event.preventDefault();
122
- this.onInputChange(!this.value());
67
+ this.onInput(!this.value());
123
68
  break;
124
69
  }
125
70
  case 'ArrowRight': {
126
- this.onInputChange(true);
71
+ this.onInput(true);
127
72
  break;
128
73
  }
129
74
  case 'ArrowLeft': {
130
- this.onInputChange(false);
75
+ this.onInput(false);
131
76
  break;
132
77
  }
133
78
  }
@@ -10,7 +10,18 @@
10
10
  "type": "array",
11
11
  "items": {
12
12
  "type": "string",
13
- "enum": ["avatar", "button", "checkbox", "divider", "icon", "input", "skeleton", "switch", "textarea"]
13
+ "enum": [
14
+ "avatar",
15
+ "button",
16
+ "checkbox",
17
+ "divider",
18
+ "form-control",
19
+ "icon",
20
+ "input",
21
+ "skeleton",
22
+ "switch",
23
+ "textarea"
24
+ ]
14
25
  },
15
26
  "multiselect": true,
16
27
  "x-prompt": "Which component should be generated?"