hr-design-system-handlebars 1.102.0 → 1.102.2

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.
Files changed (28) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/assets/index.css +37 -3
  3. package/dist/assets/js/components/forms/inputHandler.alpine.js +13 -8
  4. package/dist/views/components/forms/choice.hbs +97 -0
  5. package/dist/views/components/forms/fields.hbs +10 -11
  6. package/dist/views/components/forms/input.hbs +1 -1
  7. package/dist/views/components/forms/select.hbs +8 -1
  8. package/dist/views_static/components/forms/choice.hbs +97 -0
  9. package/dist/views_static/components/forms/fields.hbs +10 -11
  10. package/dist/views_static/components/forms/input.hbs +1 -1
  11. package/dist/views_static/components/forms/select.hbs +8 -1
  12. package/package.json +1 -1
  13. package/src/assets/css/custom-utilities.css +13 -1
  14. package/src/assets/fixtures/forms/form_checkbox.json +18 -0
  15. package/src/assets/fixtures/forms/form_fields.inc.json +31 -0
  16. package/src/assets/fixtures/forms/form_group.json +46 -0
  17. package/src/stories/views/components/forms/choice.hbs +97 -0
  18. package/src/stories/views/components/forms/fields.hbs +10 -11
  19. package/src/stories/views/components/forms/fixtures/form_checkbox.json +1 -0
  20. package/src/stories/views/components/forms/fixtures/form_group.json +1 -0
  21. package/src/stories/views/components/forms/form.mdx +1 -1
  22. package/src/stories/views/components/forms/form_checkbox.stories.js +34 -0
  23. package/src/stories/views/components/forms/form_group.stories.js +34 -0
  24. package/src/stories/views/components/forms/form_select.stories.js +34 -0
  25. package/src/stories/views/components/forms/{form.stories.js → form_textfields.stories.js} +0 -7
  26. package/src/stories/views/components/forms/input.hbs +1 -1
  27. package/src/stories/views/components/forms/inputHandler.alpine.js +13 -8
  28. package/src/stories/views/components/forms/select.hbs +8 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,28 @@
1
+ # v1.102.2 (Tue Sep 24 2024)
2
+
3
+ #### 🐛 Bug Fix
4
+
5
+ - ✨ Formulargruppen mit und ohne Überschriften [#1076](https://github.com/mumprod/hr-design-system-handlebars/pull/1076) ([@vascoeduardo](https://github.com/vascoeduardo))
6
+
7
+ #### Authors: 1
8
+
9
+ - Vasco ([@vascoeduardo](https://github.com/vascoeduardo))
10
+
11
+ ---
12
+
13
+ # v1.102.1 (Tue Sep 24 2024)
14
+
15
+ #### 🐛 Bug Fix
16
+
17
+ - DPE-3306: add checkbox field [#1075](https://github.com/mumprod/hr-design-system-handlebars/pull/1075) (saad.elbaciri@hr.de [@selbaciri](https://github.com/selbaciri))
18
+
19
+ #### Authors: 2
20
+
21
+ - Saad El Baciri ([@selbaciri](https://github.com/selbaciri))
22
+ - selbaciri (saad.elbaciri@hr.de)
23
+
24
+ ---
25
+
1
26
  # v1.102.0 (Tue Sep 24 2024)
2
27
 
3
28
  #### 🚀 Enhancement
@@ -1136,6 +1136,9 @@ article.indexTextDS .indexTextHighlighted .link {
1136
1136
  .right-0 {
1137
1137
  right: 0px;
1138
1138
  }
1139
+ .right-14 {
1140
+ right: 3.5rem;
1141
+ }
1139
1142
  .right-4 {
1140
1143
  right: 1rem;
1141
1144
  }
@@ -1862,6 +1865,9 @@ article.indexTextDS .indexTextHighlighted .link {
1862
1865
  .flex-none {
1863
1866
  flex: none;
1864
1867
  }
1868
+ .flex-shrink-0 {
1869
+ flex-shrink: 0;
1870
+ }
1865
1871
  .shrink {
1866
1872
  flex-shrink: 1;
1867
1873
  }
@@ -2308,6 +2314,10 @@ article.indexTextDS .indexTextHighlighted .link {
2308
2314
  --tw-border-opacity: 1;
2309
2315
  border-color: rgba(59, 130, 246, var(--tw-border-opacity));
2310
2316
  }
2317
+ .border-blue-science-hex {
2318
+ --tw-border-opacity: 1;
2319
+ border-color: rgba(0, 109, 193, var(--tw-border-opacity));
2320
+ }
2311
2321
  .border-brandnavigation-border-color {
2312
2322
  border-color: #005293;
2313
2323
  border-color: var(--color-brandnavigation-border-color);
@@ -3476,7 +3486,7 @@ article.indexTextDS .indexTextHighlighted .link {
3476
3486
  border-bottom-color: var(--color-secondary-ds);
3477
3487
  }
3478
3488
  .counter-reset {
3479
- counter-reset: cnt1727170647026;
3489
+ counter-reset: cnt1727186810627;
3480
3490
  }
3481
3491
  .hyphens-auto {
3482
3492
  -webkit-hyphens: auto;
@@ -3884,7 +3894,7 @@ article.indexTextDS .indexTextHighlighted .link {
3884
3894
  --tw-ring-color: rgba(255, 255, 255, 0.5);
3885
3895
  }
3886
3896
  .-ordered {
3887
- counter-increment: cnt1727170647026 1;
3897
+ counter-increment: cnt1727186810627 1;
3888
3898
  }
3889
3899
  .-ordered::before {
3890
3900
  position: absolute;
@@ -3900,7 +3910,7 @@ article.indexTextDS .indexTextHighlighted .link {
3900
3910
  letter-spacing: .0125em;
3901
3911
  --tw-text-opacity: 1;
3902
3912
  color: rgba(0, 0, 0, var(--tw-text-opacity));
3903
- content: counter(cnt1727170647026);
3913
+ content: counter(cnt1727186810627);
3904
3914
  }
3905
3915
  /*! ****************************/
3906
3916
  /*! DataPolicy stuff */
@@ -4023,6 +4033,19 @@ select[\:has\(option\:checked\[value\%3D\%22\%22\]\)] {
4023
4033
  select:has(option:checked[value=""]) {
4024
4034
  color: transparent;
4025
4035
  }
4036
+ input[type="checkbox"]:checked::after {
4037
+ position: absolute;
4038
+ content: '';
4039
+ width: 15px;
4040
+ height: 6px;
4041
+ background: transparent;
4042
+ top: 7px;
4043
+ left: 3px;
4044
+ border: 3px solid white;
4045
+ border-top: none;
4046
+ border-right: none;
4047
+ transform: rotate(-45deg);
4048
+ }
4026
4049
  .\[-T\:\+Z\] {
4027
4050
  --t: +Z;
4028
4051
  }
@@ -5790,6 +5813,13 @@ select:has(option:checked[value=""]) {
5790
5813
  .last-of-type\:pb-3:last-of-type {
5791
5814
  padding-bottom: 0.75rem;
5792
5815
  }
5816
+ .checked\:border-transparent:checked {
5817
+ border-color: transparent;
5818
+ }
5819
+ .checked\:bg-blue-congress-hex:checked {
5820
+ --tw-bg-opacity: 1;
5821
+ background-color: rgba(0, 82, 147, var(--tw-bg-opacity));
5822
+ }
5793
5823
  .empty\:hidden:empty {
5794
5824
  display: none;
5795
5825
  }
@@ -7122,6 +7152,10 @@ select:has(option:checked[value=""]) {
7122
7152
  row-gap: 3.5rem;
7123
7153
  }
7124
7154
 
7155
+ .md\:gap-y-4 {
7156
+ row-gap: 1rem;
7157
+ }
7158
+
7125
7159
  .md\:space-x-3 > :not([hidden]) ~ :not([hidden]) {
7126
7160
  --tw-space-x-reverse: 0;
7127
7161
  margin-right: calc(0.75rem * var(--tw-space-x-reverse));
@@ -1,22 +1,27 @@
1
- export default function inputHandler(element, errorMandatory, errorEmail, isEmail = false, prefilledText = '') {
1
+ export default function inputHandler(element, errorMandatory, type, errorEmail, prefilledText = '') {
2
2
  return {
3
3
  [element]: prefilledText,
4
4
  valid: false,
5
5
  wasFocused: false,
6
6
  isFocused: false,
7
7
  validEmail: false,
8
+ isChecked: false,
8
9
  errorMessage() {
9
- if( Boolean(isEmail)){
10
+ if( type == "email"){
10
11
  return !this.valid ? errorMandatory : errorEmail
11
- } else {
12
+ }
13
+ else {
12
14
  return errorMandatory
13
15
  }
14
16
  },
15
- hideDescription() {
16
- if( Boolean(isEmail)){
17
- return Boolean((!this.valid && this.wasFocused && !this.isFocused) || (!this.validEmail && this.wasFocused && !this.isFocused))
18
- } else {
19
- return Boolean(!this.valid && this.wasFocused && !this.isFocused)
17
+ hideDescription() {
18
+ switch (type) {
19
+ case "email":
20
+ return Boolean((!this.valid && this.wasFocused && !this.isFocused) || (!this.validEmail && this.wasFocused && !this.isFocused));
21
+ case "checkbox":
22
+ return Boolean(!this.valid && this.wasFocused && !this.isFocused && !this.isChecked);
23
+ default:
24
+ return Boolean(!this.valid && this.wasFocused && !this.isFocused);
20
25
  }
21
26
  },
22
27
  hideError() {
@@ -0,0 +1,97 @@
1
+ <div class="relative flex flex-col w-full mb-6 gap-y-3 md:gap-y-4"
2
+ ax-load
3
+ x-data="inputHandler('input{{nextRandom}}','{{_errorMandatory}}','{{_type}}')"
4
+ x-ignore
5
+ >
6
+
7
+ <div class="flex flex-row items-center w-full gap-x-4">
8
+
9
+ <input class="relative self-start flex-shrink-0 w-6 h-6 bg-white border appearance-none cursor-pointer border-blue-science-hex checked:bg-blue-congress-hex checked:border-transparent"
10
+ :class="{' border-blue-science-hex': hideError(),'border-red-700': hideDescription() }"
11
+ @change="validateInput"
12
+ x-model="isChecked"
13
+ id="input{{getRandom}}"
14
+ {{#if _required}}
15
+ @focus="isFocused = true"
16
+ @blur="wasFocused = true; isFocused=false"
17
+ {{/if}}
18
+ type="{{#if _type}}{{_type}}{{/if}}"
19
+ name="{{#if _name}}{{_name}}{{/if}}"
20
+ {{#if _locaKey}}
21
+ title="{{loca _locaKey}}{{#if _required}}*{{/if}}"
22
+ {{else}}
23
+ {{#if _label}}
24
+ title="{{_label}}{{#if _required}}*{{/if}}"
25
+ {{/if}}
26
+ {{/if}}
27
+ {{#if _formField.forHtmlAttribute}}
28
+ value="{{_formField.forHtmlAttribute}}"
29
+ {{else}}
30
+ {{#if _value}}
31
+ value="{{_value}}"
32
+ {{else}}
33
+ value="{{_defaultValue}}"
34
+ {{/if}}
35
+ {{/if}}
36
+ {{#if _required}} required{{/if}}
37
+ {{#unless _multipleChoice}}
38
+ {{#if _required}}
39
+ required
40
+ {{/if}}
41
+ {{/unless}}
42
+ {{#if _formField.rawAsBoolean}}
43
+ checked
44
+ {{else}}
45
+ {{#if _selected}}
46
+ checked
47
+ {{/if}}
48
+ {{/if~}}
49
+ >
50
+
51
+ <label for="input{{getRandom}}" class="items-center justify-center text-xs text-black md:text-sm font-headingSerif ">
52
+ {{#if _hasBody}}
53
+ {{decorator_body}}{{#if _required}}*{{/if}}
54
+ {{else}}
55
+ {{#if _locaKey}}
56
+ {{loca _locaKey}}{{#if _required}}*{{/if}}
57
+ {{else}}
58
+ {{#if _label}}
59
+ {{{_label}}}{{#if _required}}*{{/if}}
60
+ {{/if}}
61
+ {{/if}}
62
+ {{/if}}
63
+ </label>
64
+
65
+ {{#if _required}}
66
+ <div class="flex items-center self-start justify-center">
67
+ <div class="hidden w-5 h-5 font-bold" :class="{'hidden': hideError() }">
68
+ {{> components/base/image/icon _icon="info2" _addClass="w-5 h-5 fill-red-700"}}
69
+ </div>
70
+ </div>
71
+ {{/if}}
72
+
73
+ </div>
74
+
75
+ <div class="flex items-end justify-between h-5 font-heading">
76
+ {{#if _description}}
77
+ <div class="text-xs text-gray-500" {{#if _required}}:class="{'hidden': hideDescription() }"{{/if}}>{{_description}}</div>
78
+ {{/if}}
79
+ {{#if _required}}
80
+ <div class="hidden text-xs text-red-700" :class="{'hidden': hideError()}" x-text="errorMessage"></div>
81
+ {{/if}}
82
+ </div>
83
+
84
+ <div class="hidden" >
85
+ <b>DEBUGG</b>
86
+ <div>isChecked:<span x-text="isChecked" class="font-bold" :class="isChecked ? 'text-green-800' : 'text-red-700'"></span></div>
87
+ <div>isFocused:<span x-text="isFocused" class="font-bold" :class="isFocused ? 'text-green-800' : 'text-red-700'"></span></div>
88
+ <div>wasFocused:<span x-text="wasFocused" class="font-bold" :class="wasFocused ? 'text-green-800' : 'text-red-700'"></span></div>
89
+ <div>valid:<span x-text="valid" class="font-bold" :class="valid ? 'text-green-800' : 'text-red-700'"></span></div>
90
+ <div>hideDescription:<span x-text="hideDescription()" class="font-bold" :class="hideDescription() ? 'text-green-800' : 'text-red-700'"></span></div>
91
+ <div>hideError:<span x-text="hideError()" class="font-bold" :class="hideError() ? 'text-green-800' : 'text-red-700'"></span></div>
92
+ <div>errorMessage:<span x-text="errorMessage" class="font-bold" ></span></div>
93
+ </div>
94
+
95
+
96
+
97
+ </div>
@@ -1,17 +1,15 @@
1
1
  {{#each this.fields}}
2
2
  {{#if this.type.isGroup}}
3
3
 
4
- {{#if this.caption}}
5
- <div class="c-form__row -hasLegend">
6
- <fieldset class="c-form__field-set">
7
- <legend class="c-form__legend">{{this.caption}}</legend>
8
- </fieldset>
9
- {{~> modules/forms/fields}}
10
- </div>
4
+ {{#if this.caption}}
5
+ <fieldset>
6
+ <legend class="mb-5 font-headingSerif">{{this.caption}}</legend>
7
+ {{~> components/forms/fields}}
8
+ </fieldset>
11
9
  {{else}}
12
- <div class="c-form__row -expanded">
13
- {{~> modules/forms/fields}}
14
- </div>
10
+ <fieldset>
11
+ {{~> components/forms/fields}}
12
+ </fieldset>
15
13
  {{/if}}
16
14
 
17
15
  {{else}}
@@ -70,7 +68,7 @@
70
68
 
71
69
  }}
72
70
  {{else}}
73
- {{~> modules/forms/choice
71
+ {{~> components/forms/choice
74
72
  _type=this.type.asString
75
73
  _name=this.name
76
74
  _label=this.label
@@ -79,6 +77,7 @@
79
77
  _value=this.options.[0].value
80
78
  _required=this.isRequired
81
79
  _selected= this.options.[0].isSelected
80
+ _errorMandatory="Bitte füllen Sie dieses Pflichtfeld aus"
82
81
  }}
83
82
  {{/if}}
84
83
  {{else if this.type.isUpload}}
@@ -1,6 +1,6 @@
1
1
  <div class="relative flex flex-col w-full mb-5 {{_wrapperClass}}"
2
2
  ax-load
3
- x-data="inputHandler('input{{nextRandom}}','{{_errorMandatory}}','{{_errorEmail}}',{{#if _isEmail}}true{{else}}false{{/if}},'{{#if _formField.forHtmlAttribute}}{{_formField.forHtmlAttribute}}{{else}}{{#if _value}}{{_value}}{{else}}{{_defaultValue}}{{/if}}{{/if}}')"
3
+ x-data="inputHandler('input{{nextRandom}}','{{_errorMandatory}}',{{#if _isEmail}}'email'{{else}}'{{_type}}'{{/if}},'{{_errorEmail}}','{{#if _formField.forHtmlAttribute}}{{_formField.forHtmlAttribute}}{{else}}{{#if _value}}{{_value}}{{else}}{{_defaultValue}}{{/if}}{{/if}}')"
4
4
  x-ignore
5
5
  >
6
6
  <input class="relative w-full h-12 pt-4 pl-4 text-gray-800 placeholder-transparent bg-white border-blue-500 pr-9 peer border-y focus:border-y-2 border-t-transparent focus:outline-none"
@@ -43,9 +43,16 @@
43
43
  ">
44
44
  {{_label}}{{#if _required}}*{{/if}}
45
45
  </label>
46
+ {{#if _required}}
47
+ <div class="absolute top-0 z-10 flex items-center justify-center h-12 right-14">
48
+ <div class="hidden w-5 h-5 font-bold" :class="{'hidden': hideError() }">
49
+ {{> components/base/image/icon _icon="info2" _addClass="w-5 h-5 fill-red-700"}}
50
+ </div>
51
+ </div>
52
+ {{/if}}
46
53
  <div class="flex items-end justify-between h-5 font-heading">
47
54
  {{#if _description}}
48
- <div class="pl-4 text-xs text-gray-500 min-h- " {{#if _required}}:class="{'hidden': !valid && wasFocused && !isFocused}"{{/if}}>{{_description}}</div>
55
+ <div class="pl-4 text-xs text-gray-500 " {{#if _required}}:class="{'hidden': !valid && wasFocused && !isFocused}"{{/if}}>{{_description}}</div>
49
56
  {{/if}}
50
57
  {{#if _required}}
51
58
  <div class="hidden pl-4 text-xs text-red-700" :class="{'hidden': valid || !wasFocused || isFocused}" >{{_errorMessage}}</div>
@@ -0,0 +1,97 @@
1
+ <div class="relative flex flex-col w-full mb-6 gap-y-3 md:gap-y-4"
2
+ ax-load
3
+ x-data="inputHandler('input{{nextRandom}}','{{_errorMandatory}}','{{_type}}')"
4
+ x-ignore
5
+ >
6
+
7
+ <div class="flex flex-row items-center w-full gap-x-4">
8
+
9
+ <input class="relative self-start flex-shrink-0 w-6 h-6 bg-white border appearance-none cursor-pointer border-blue-science-hex checked:bg-blue-congress-hex checked:border-transparent"
10
+ :class="{' border-blue-science-hex': hideError(),'border-red-700': hideDescription() }"
11
+ @change="validateInput"
12
+ x-model="isChecked"
13
+ id="input{{getRandom}}"
14
+ {{#if _required}}
15
+ @focus="isFocused = true"
16
+ @blur="wasFocused = true; isFocused=false"
17
+ {{/if}}
18
+ type="{{#if _type}}{{_type}}{{/if}}"
19
+ name="{{#if _name}}{{_name}}{{/if}}"
20
+ {{#if _locaKey}}
21
+ title="{{loca _locaKey}}{{#if _required}}*{{/if}}"
22
+ {{else}}
23
+ {{#if _label}}
24
+ title="{{_label}}{{#if _required}}*{{/if}}"
25
+ {{/if}}
26
+ {{/if}}
27
+ {{#if _formField.forHtmlAttribute}}
28
+ value="{{_formField.forHtmlAttribute}}"
29
+ {{else}}
30
+ {{#if _value}}
31
+ value="{{_value}}"
32
+ {{else}}
33
+ value="{{_defaultValue}}"
34
+ {{/if}}
35
+ {{/if}}
36
+ {{#if _required}} required{{/if}}
37
+ {{#unless _multipleChoice}}
38
+ {{#if _required}}
39
+ required
40
+ {{/if}}
41
+ {{/unless}}
42
+ {{#if _formField.rawAsBoolean}}
43
+ checked
44
+ {{else}}
45
+ {{#if _selected}}
46
+ checked
47
+ {{/if}}
48
+ {{/if~}}
49
+ >
50
+
51
+ <label for="input{{getRandom}}" class="items-center justify-center text-xs text-black md:text-sm font-headingSerif ">
52
+ {{#if _hasBody}}
53
+ {{decorator_body}}{{#if _required}}*{{/if}}
54
+ {{else}}
55
+ {{#if _locaKey}}
56
+ {{loca _locaKey}}{{#if _required}}*{{/if}}
57
+ {{else}}
58
+ {{#if _label}}
59
+ {{{_label}}}{{#if _required}}*{{/if}}
60
+ {{/if}}
61
+ {{/if}}
62
+ {{/if}}
63
+ </label>
64
+
65
+ {{#if _required}}
66
+ <div class="flex items-center self-start justify-center">
67
+ <div class="hidden w-5 h-5 font-bold" :class="{'hidden': hideError() }">
68
+ {{> components/base/image/icon _icon="info2" _addClass="w-5 h-5 fill-red-700"}}
69
+ </div>
70
+ </div>
71
+ {{/if}}
72
+
73
+ </div>
74
+
75
+ <div class="flex items-end justify-between h-5 font-heading">
76
+ {{#if _description}}
77
+ <div class="text-xs text-gray-500" {{#if _required}}:class="{'hidden': hideDescription() }"{{/if}}>{{_description}}</div>
78
+ {{/if}}
79
+ {{#if _required}}
80
+ <div class="hidden text-xs text-red-700" :class="{'hidden': hideError()}" x-text="errorMessage"></div>
81
+ {{/if}}
82
+ </div>
83
+
84
+ <div class="hidden" >
85
+ <b>DEBUGG</b>
86
+ <div>isChecked:<span x-text="isChecked" class="font-bold" :class="isChecked ? 'text-green-800' : 'text-red-700'"></span></div>
87
+ <div>isFocused:<span x-text="isFocused" class="font-bold" :class="isFocused ? 'text-green-800' : 'text-red-700'"></span></div>
88
+ <div>wasFocused:<span x-text="wasFocused" class="font-bold" :class="wasFocused ? 'text-green-800' : 'text-red-700'"></span></div>
89
+ <div>valid:<span x-text="valid" class="font-bold" :class="valid ? 'text-green-800' : 'text-red-700'"></span></div>
90
+ <div>hideDescription:<span x-text="hideDescription()" class="font-bold" :class="hideDescription() ? 'text-green-800' : 'text-red-700'"></span></div>
91
+ <div>hideError:<span x-text="hideError()" class="font-bold" :class="hideError() ? 'text-green-800' : 'text-red-700'"></span></div>
92
+ <div>errorMessage:<span x-text="errorMessage" class="font-bold" ></span></div>
93
+ </div>
94
+
95
+
96
+
97
+ </div>
@@ -1,17 +1,15 @@
1
1
  {{#each this.fields}}
2
2
  {{#if this.type.isGroup}}
3
3
 
4
- {{#if this.caption}}
5
- <div class="c-form__row -hasLegend">
6
- <fieldset class="c-form__field-set">
7
- <legend class="c-form__legend">{{this.caption}}</legend>
8
- </fieldset>
9
- {{~> modules/forms/fields}}
10
- </div>
4
+ {{#if this.caption}}
5
+ <fieldset>
6
+ <legend class="mb-5 font-headingSerif">{{this.caption}}</legend>
7
+ {{~> components/forms/fields}}
8
+ </fieldset>
11
9
  {{else}}
12
- <div class="c-form__row -expanded">
13
- {{~> modules/forms/fields}}
14
- </div>
10
+ <fieldset>
11
+ {{~> components/forms/fields}}
12
+ </fieldset>
15
13
  {{/if}}
16
14
 
17
15
  {{else}}
@@ -70,7 +68,7 @@
70
68
 
71
69
  }}
72
70
  {{else}}
73
- {{~> modules/forms/choice
71
+ {{~> components/forms/choice
74
72
  _type=this.type.asString
75
73
  _name=this.name
76
74
  _label=this.label
@@ -79,6 +77,7 @@
79
77
  _value=this.options.[0].value
80
78
  _required=this.isRequired
81
79
  _selected= this.options.[0].isSelected
80
+ _errorMandatory="Bitte füllen Sie dieses Pflichtfeld aus"
82
81
  }}
83
82
  {{/if}}
84
83
  {{else if this.type.isUpload}}
@@ -1,6 +1,6 @@
1
1
  <div class="relative flex flex-col w-full mb-5 {{_wrapperClass}}"
2
2
  ax-load
3
- x-data="inputHandler('input{{nextRandom}}','{{_errorMandatory}}','{{_errorEmail}}',{{#if _isEmail}}true{{else}}false{{/if}},'{{#if _formField.forHtmlAttribute}}{{_formField.forHtmlAttribute}}{{else}}{{#if _value}}{{_value}}{{else}}{{_defaultValue}}{{/if}}{{/if}}')"
3
+ x-data="inputHandler('input{{nextRandom}}','{{_errorMandatory}}',{{#if _isEmail}}'email'{{else}}'{{_type}}'{{/if}},'{{_errorEmail}}','{{#if _formField.forHtmlAttribute}}{{_formField.forHtmlAttribute}}{{else}}{{#if _value}}{{_value}}{{else}}{{_defaultValue}}{{/if}}{{/if}}')"
4
4
  x-ignore
5
5
  >
6
6
  <input class="relative w-full h-12 pt-4 pl-4 text-gray-800 placeholder-transparent bg-white border-blue-500 pr-9 peer border-y focus:border-y-2 border-t-transparent focus:outline-none"
@@ -43,9 +43,16 @@
43
43
  ">
44
44
  {{_label}}{{#if _required}}*{{/if}}
45
45
  </label>
46
+ {{#if _required}}
47
+ <div class="absolute top-0 z-10 flex items-center justify-center h-12 right-14">
48
+ <div class="hidden w-5 h-5 font-bold" :class="{'hidden': hideError() }">
49
+ {{> components/base/image/icon _icon="info2" _addClass="w-5 h-5 fill-red-700"}}
50
+ </div>
51
+ </div>
52
+ {{/if}}
46
53
  <div class="flex items-end justify-between h-5 font-heading">
47
54
  {{#if _description}}
48
- <div class="pl-4 text-xs text-gray-500 min-h- " {{#if _required}}:class="{'hidden': !valid && wasFocused && !isFocused}"{{/if}}>{{_description}}</div>
55
+ <div class="pl-4 text-xs text-gray-500 " {{#if _required}}:class="{'hidden': !valid && wasFocused && !isFocused}"{{/if}}>{{_description}}</div>
49
56
  {{/if}}
50
57
  {{#if _required}}
51
58
  <div class="hidden pl-4 text-xs text-red-700" :class="{'hidden': valid || !wasFocused || isFocused}" >{{_errorMessage}}</div>
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "license": "MIT",
7
7
  "main": "dist/index.js",
8
8
  "repository": "https://github.com/szuelch/hr-design-system-handlebars",
9
- "version": "1.102.0",
9
+ "version": "1.102.2",
10
10
  "scripts": {
11
11
  "test": "echo \"Error: no test specified\" && exit 1",
12
12
  "storybook": "storybook dev -p 6006 public",
@@ -457,6 +457,18 @@
457
457
  select:has(option:checked[value=""]) {
458
458
  @apply text-transparent
459
459
  }
460
-
461
460
 
461
+ input[type="checkbox"]:checked::after {
462
+ position: absolute;
463
+ content: '';
464
+ width: 15px;
465
+ height: 6px;
466
+ background: transparent;
467
+ top: 7px;
468
+ left: 3px;
469
+ border: 3px solid white;
470
+ border-top: none;
471
+ border-right: none;
472
+ transform: rotate(-45deg);
473
+ }
462
474
  }
@@ -0,0 +1,18 @@
1
+ {
2
+ "fields":[
3
+ {
4
+ "@->jsoninclude": "forms/form_fields.inc.json",
5
+ "@->contentpath": "checkbox"
6
+ },
7
+ {
8
+ "@->jsoninclude": "forms/form_fields.inc.json",
9
+ "@->contentpath": "checkbox",
10
+ "@->overrides": [
11
+ {
12
+ "@->contentpath": "label",
13
+ "@->value": "Ich bin damit einverstanden, dass der hr die von mir im vorstehenden Formular angegebenen personenbezogenen Daten für den Zweck der Kontaktaufnahme mit Upload verarbeitet. Eine Weitergabe an Dritte findet nicht statt, es sei denn, es wird ausdrücklich darauf hingewiesen. Unsere Datenschutzerklärung mit sämtlichen Informationen gemäß Art 13 DSGVO zur Datenverarbeitung durch den hr und zu Ihren Rechten können Sie unter Datenschutzerklärung einsehen. Den Datenschutzbeauftragten des hr erreichen Sie unter datenschutz@hr.de."
14
+ }
15
+ ]
16
+ }
17
+ ]
18
+ }
@@ -80,6 +80,29 @@
80
80
  "rows": "10",
81
81
  "counter": true
82
82
  },
83
+ "checkbox":
84
+ {
85
+ "isGrouped":false,
86
+ "type":{
87
+ "isChoice":true,
88
+ "asString":"checkbox"
89
+ },
90
+ "name":"checkbox",
91
+ "label":"Ich bin damit einverstanden.",
92
+ "isMeta":false,
93
+ "description":"Das ist der Beschreibungstext von Checkbox",
94
+ "isRequired":true,
95
+ "options":[
96
+ {
97
+ "value":"value0",
98
+ "isSelected":false
99
+ },
100
+ {
101
+ "value":"value1",
102
+ "isSelected":false
103
+ }
104
+ ]
105
+ },
83
106
  "select": {
84
107
  "type": {
85
108
  "isSelect": true,
@@ -117,5 +140,13 @@
117
140
  "label": "Option 4"
118
141
  }
119
142
  ]
143
+ },
144
+ "group": {
145
+ "type": {
146
+ "isGroup": true,
147
+ "asString": "group"
148
+ },
149
+ "caption": "Eine Gruppe mit Überschrift",
150
+ "fields": []
120
151
  }
121
152
  }
@@ -0,0 +1,46 @@
1
+ {
2
+ "fields":[
3
+ {
4
+ "@->jsoninclude": "forms/form_fields.inc.json",
5
+ "@->contentpath": "group",
6
+ "@->overrides": [
7
+ {
8
+ "@->contentpath": "fields",
9
+ "@->value": [
10
+ {
11
+ "@->jsoninclude": "forms/form_fields.inc.json",
12
+ "@->contentpath": "input-text-vorname-required"
13
+ },
14
+ {
15
+ "@->jsoninclude": "forms/form_fields.inc.json",
16
+ "@->contentpath": "input-text-nachname-required"
17
+ }
18
+ ]
19
+ }
20
+ ]
21
+ },
22
+ {
23
+ "@->jsoninclude": "forms/form_fields.inc.json",
24
+ "@->contentpath": "group",
25
+ "@->overrides": [
26
+ {
27
+ "@->contentpath": "fields",
28
+ "@->value": [
29
+ {
30
+ "@->jsoninclude": "forms/form_fields.inc.json",
31
+ "@->contentpath": "input-text-vorname-required"
32
+ },
33
+ {
34
+ "@->jsoninclude": "forms/form_fields.inc.json",
35
+ "@->contentpath": "input-text-nachname-required"
36
+ }
37
+ ]
38
+ },
39
+ {
40
+ "@->contentpath": "caption",
41
+ "@->value": "Noch eine Gruppe mit einer anderen Überschrift"
42
+ }
43
+ ]
44
+ }
45
+ ]
46
+ }
@@ -0,0 +1,97 @@
1
+ <div class="relative flex flex-col w-full mb-6 gap-y-3 md:gap-y-4"
2
+ ax-load
3
+ x-data="inputHandler('input{{nextRandom}}','{{_errorMandatory}}','{{_type}}')"
4
+ x-ignore
5
+ >
6
+
7
+ <div class="flex flex-row items-center w-full gap-x-4">
8
+
9
+ <input class="relative self-start flex-shrink-0 w-6 h-6 bg-white border appearance-none cursor-pointer border-blue-science-hex checked:bg-blue-congress-hex checked:border-transparent"
10
+ :class="{' border-blue-science-hex': hideError(),'border-red-700': hideDescription() }"
11
+ @change="validateInput"
12
+ x-model="isChecked"
13
+ id="input{{getRandom}}"
14
+ {{#if _required}}
15
+ @focus="isFocused = true"
16
+ @blur="wasFocused = true; isFocused=false"
17
+ {{/if}}
18
+ type="{{#if _type}}{{_type}}{{/if}}"
19
+ name="{{#if _name}}{{_name}}{{/if}}"
20
+ {{#if _locaKey}}
21
+ title="{{loca _locaKey}}{{#if _required}}*{{/if}}"
22
+ {{else}}
23
+ {{#if _label}}
24
+ title="{{_label}}{{#if _required}}*{{/if}}"
25
+ {{/if}}
26
+ {{/if}}
27
+ {{#if _formField.forHtmlAttribute}}
28
+ value="{{_formField.forHtmlAttribute}}"
29
+ {{else}}
30
+ {{#if _value}}
31
+ value="{{_value}}"
32
+ {{else}}
33
+ value="{{_defaultValue}}"
34
+ {{/if}}
35
+ {{/if}}
36
+ {{#if _required}} required{{/if}}
37
+ {{#unless _multipleChoice}}
38
+ {{#if _required}}
39
+ required
40
+ {{/if}}
41
+ {{/unless}}
42
+ {{#if _formField.rawAsBoolean}}
43
+ checked
44
+ {{else}}
45
+ {{#if _selected}}
46
+ checked
47
+ {{/if}}
48
+ {{/if~}}
49
+ >
50
+
51
+ <label for="input{{getRandom}}" class="items-center justify-center text-xs text-black md:text-sm font-headingSerif ">
52
+ {{#if _hasBody}}
53
+ {{decorator_body}}{{#if _required}}*{{/if}}
54
+ {{else}}
55
+ {{#if _locaKey}}
56
+ {{loca _locaKey}}{{#if _required}}*{{/if}}
57
+ {{else}}
58
+ {{#if _label}}
59
+ {{{_label}}}{{#if _required}}*{{/if}}
60
+ {{/if}}
61
+ {{/if}}
62
+ {{/if}}
63
+ </label>
64
+
65
+ {{#if _required}}
66
+ <div class="flex items-center self-start justify-center">
67
+ <div class="hidden w-5 h-5 font-bold" :class="{'hidden': hideError() }">
68
+ {{> components/base/image/icon _icon="info2" _addClass="w-5 h-5 fill-red-700"}}
69
+ </div>
70
+ </div>
71
+ {{/if}}
72
+
73
+ </div>
74
+
75
+ <div class="flex items-end justify-between h-5 font-heading">
76
+ {{#if _description}}
77
+ <div class="text-xs text-gray-500" {{#if _required}}:class="{'hidden': hideDescription() }"{{/if}}>{{_description}}</div>
78
+ {{/if}}
79
+ {{#if _required}}
80
+ <div class="hidden text-xs text-red-700" :class="{'hidden': hideError()}" x-text="errorMessage"></div>
81
+ {{/if}}
82
+ </div>
83
+
84
+ <div class="hidden" >
85
+ <b>DEBUGG</b>
86
+ <div>isChecked:<span x-text="isChecked" class="font-bold" :class="isChecked ? 'text-green-800' : 'text-red-700'"></span></div>
87
+ <div>isFocused:<span x-text="isFocused" class="font-bold" :class="isFocused ? 'text-green-800' : 'text-red-700'"></span></div>
88
+ <div>wasFocused:<span x-text="wasFocused" class="font-bold" :class="wasFocused ? 'text-green-800' : 'text-red-700'"></span></div>
89
+ <div>valid:<span x-text="valid" class="font-bold" :class="valid ? 'text-green-800' : 'text-red-700'"></span></div>
90
+ <div>hideDescription:<span x-text="hideDescription()" class="font-bold" :class="hideDescription() ? 'text-green-800' : 'text-red-700'"></span></div>
91
+ <div>hideError:<span x-text="hideError()" class="font-bold" :class="hideError() ? 'text-green-800' : 'text-red-700'"></span></div>
92
+ <div>errorMessage:<span x-text="errorMessage" class="font-bold" ></span></div>
93
+ </div>
94
+
95
+
96
+
97
+ </div>
@@ -1,17 +1,15 @@
1
1
  {{#each this.fields}}
2
2
  {{#if this.type.isGroup}}
3
3
 
4
- {{#if this.caption}}
5
- <div class="c-form__row -hasLegend">
6
- <fieldset class="c-form__field-set">
7
- <legend class="c-form__legend">{{this.caption}}</legend>
8
- </fieldset>
9
- {{~> modules/forms/fields}}
10
- </div>
4
+ {{#if this.caption}}
5
+ <fieldset>
6
+ <legend class="mb-5 font-headingSerif">{{this.caption}}</legend>
7
+ {{~> components/forms/fields}}
8
+ </fieldset>
11
9
  {{else}}
12
- <div class="c-form__row -expanded">
13
- {{~> modules/forms/fields}}
14
- </div>
10
+ <fieldset>
11
+ {{~> components/forms/fields}}
12
+ </fieldset>
15
13
  {{/if}}
16
14
 
17
15
  {{else}}
@@ -70,7 +68,7 @@
70
68
 
71
69
  }}
72
70
  {{else}}
73
- {{~> modules/forms/choice
71
+ {{~> components/forms/choice
74
72
  _type=this.type.asString
75
73
  _name=this.name
76
74
  _label=this.label
@@ -79,6 +77,7 @@
79
77
  _value=this.options.[0].value
80
78
  _required=this.isRequired
81
79
  _selected= this.options.[0].isSelected
80
+ _errorMandatory="Bitte füllen Sie dieses Pflichtfeld aus"
82
81
  }}
83
82
  {{/if}}
84
83
  {{else if this.type.isUpload}}
@@ -0,0 +1 @@
1
+ {"fields":[{"isGrouped":false,"type":{"isChoice":true,"asString":"checkbox"},"name":"checkbox","label":"Ich bin damit einverstanden.","isMeta":false,"description":"Das ist der Beschreibungstext von Checkbox","isRequired":true,"options":[{"value":"value0","isSelected":false},{"value":"value1","isSelected":false}]},{"isGrouped":false,"type":{"isChoice":true,"asString":"checkbox"},"name":"checkbox","label":"Ich bin damit einverstanden, dass der hr die von mir im vorstehenden Formular angegebenen personenbezogenen Daten für den Zweck der Kontaktaufnahme mit Upload verarbeitet. Eine Weitergabe an Dritte findet nicht statt, es sei denn, es wird ausdrücklich darauf hingewiesen. Unsere Datenschutzerklärung mit sämtlichen Informationen gemäß Art 13 DSGVO zur Datenverarbeitung durch den hr und zu Ihren Rechten können Sie unter Datenschutzerklärung einsehen. Den Datenschutzbeauftragten des hr erreichen Sie unter datenschutz@hr.de.","isMeta":false,"description":"Das ist der Beschreibungstext von Checkbox","isRequired":true,"options":[{"value":"value0","isSelected":false},{"value":"value1","isSelected":false}]}]}
@@ -0,0 +1 @@
1
+ {"fields":[{"type":{"isGroup":true,"asString":"group"},"caption":"Eine Gruppe mit Überschrift","fields":[{"type":{"isText":true,"asString":"text"},"name":"vorname","label":"Vorname","description":"Das ist der Beschreibungstext (*Pflichtfeld)","defaultValue":"","isHidden":false,"isRequired":true,"maxLength":"140"},{"type":{"isText":true,"asString":"text"},"name":"nachname","label":"Nachname","description":"","defaultValue":"","isHidden":false,"isRequired":true,"maxLength":"140"}]},{"type":{"isGroup":true,"asString":"group"},"caption":"Noch eine Gruppe mit einer anderen Überschrift","fields":[{"type":{"isText":true,"asString":"text"},"name":"vorname","label":"Vorname","description":"Das ist der Beschreibungstext (*Pflichtfeld)","defaultValue":"","isHidden":false,"isRequired":true,"maxLength":"140"},{"type":{"isText":true,"asString":"text"},"name":"nachname","label":"Nachname","description":"","defaultValue":"","isHidden":false,"isRequired":true,"maxLength":"140"}]}]}
@@ -1,5 +1,5 @@
1
1
  import { ArgTypes, Meta, Story, Canvas } from '@storybook/blocks'
2
- import * as formStories from './form.stories'
2
+ import * as formStories from './form_textfields.stories'
3
3
 
4
4
  <Meta of={formStories} />
5
5
 
@@ -0,0 +1,34 @@
1
+
2
+ import checkboxJson from './fixtures/form_checkbox.json'
3
+
4
+ const handlebars = require('hrHandlebars')
5
+
6
+
7
+ export default {
8
+ title: 'Komponenten/Formulare',
9
+ decorators: [
10
+ (Story) => {
11
+ return `<div class="grid grid-page">
12
+ <div class="grid bg-white grid-article">
13
+ ${Story()}
14
+ </div>
15
+ </div>`
16
+ },
17
+ ],
18
+ }
19
+ const Template = (args) => {
20
+ let hbsTemplate = handlebars.compile(`
21
+ {{#>components/forms/backgroundBox }}
22
+ <form class="relative flex flex-col justify-center overflow-hidden group" id="form--{{nextRandom}}" action="{{this.url}}" method="post" enctype="{{if this.isMultipart 'multipart/form-data' 'application/x-www-form-urlencoded'}}" accept-charset="utf-8" >
23
+ {{> components/forms/fields }}
24
+ </form>
25
+ {{/components/forms/backgroundBox }}
26
+ `)
27
+ return hbsTemplate({ ...args })
28
+ }
29
+
30
+ export const Checkbox = {
31
+ render: Template.bind({}),
32
+ name: 'Checkbox',
33
+ args: checkboxJson,
34
+ }
@@ -0,0 +1,34 @@
1
+
2
+ import groupJson from './fixtures/form_group.json'
3
+
4
+ const handlebars = require('hrHandlebars')
5
+
6
+
7
+ export default {
8
+ title: 'Komponenten/Formulare',
9
+ decorators: [
10
+ (Story) => {
11
+ return `<div class="grid grid-page">
12
+ <div class="grid bg-white grid-article">
13
+ ${Story()}
14
+ </div>
15
+ </div>`
16
+ },
17
+ ],
18
+ }
19
+ const Template = (args) => {
20
+ let hbsTemplate = handlebars.compile(`
21
+ {{#>components/forms/backgroundBox }}
22
+ <form class="relative flex flex-col justify-center overflow-hidden group" id="form--{{nextRandom}}" action="{{this.url}}" method="post" enctype="{{if this.isMultipart 'multipart/form-data' 'application/x-www-form-urlencoded'}}" accept-charset="utf-8" >
23
+ {{> components/forms/fields }}
24
+ </form>
25
+ {{/components/forms/backgroundBox }}
26
+ `)
27
+ return hbsTemplate({ ...args })
28
+ }
29
+
30
+ export const Gruppe = {
31
+ render: Template.bind({}),
32
+ name: 'Gruppe',
33
+ args: groupJson,
34
+ }
@@ -0,0 +1,34 @@
1
+
2
+ import selectJson from './fixtures/form_select.json'
3
+
4
+ const handlebars = require('hrHandlebars')
5
+
6
+
7
+ export default {
8
+ title: 'Komponenten/Formulare',
9
+ decorators: [
10
+ (Story) => {
11
+ return `<div class="grid grid-page">
12
+ <div class="grid bg-white grid-article">
13
+ ${Story()}
14
+ </div>
15
+ </div>`
16
+ },
17
+ ],
18
+ }
19
+ const Template = (args) => {
20
+ let hbsTemplate = handlebars.compile(`
21
+ {{#>components/forms/backgroundBox }}
22
+ <form class="relative flex flex-col justify-center overflow-hidden group" id="form--{{nextRandom}}" action="{{this.url}}" method="post" enctype="{{if this.isMultipart 'multipart/form-data' 'application/x-www-form-urlencoded'}}" accept-charset="utf-8" >
23
+ {{> components/forms/fields }}
24
+ </form>
25
+ {{/components/forms/backgroundBox }}
26
+ `)
27
+ return hbsTemplate({ ...args })
28
+ }
29
+
30
+ export const Select = {
31
+ render: Template.bind({}),
32
+ name: 'Select',
33
+ args: selectJson,
34
+ }
@@ -4,8 +4,6 @@ import inputMandatoryJson from './fixtures/form_input_mandatory.json'
4
4
  import inputPrefilledJson from './fixtures/form_input_prefilled.json'
5
5
  import textareaJson from './fixtures/form_textarea.json'
6
6
  import emailJson from './fixtures/form_email.json'
7
- import selectJson from './fixtures/form_select.json'
8
-
9
7
 
10
8
  const handlebars = require('hrHandlebars')
11
9
 
@@ -69,8 +67,3 @@ export const Textarea = {
69
67
  name: 'Textarea',
70
68
  args: textareaJson,
71
69
  }
72
- export const Select = {
73
- render: Template.bind({}),
74
- name: 'Select',
75
- args: selectJson,
76
- }
@@ -1,6 +1,6 @@
1
1
  <div class="relative flex flex-col w-full mb-5 {{_wrapperClass}}"
2
2
  ax-load
3
- x-data="inputHandler('input{{nextRandom}}','{{_errorMandatory}}','{{_errorEmail}}',{{#if _isEmail}}true{{else}}false{{/if}},'{{#if _formField.forHtmlAttribute}}{{_formField.forHtmlAttribute}}{{else}}{{#if _value}}{{_value}}{{else}}{{_defaultValue}}{{/if}}{{/if}}')"
3
+ x-data="inputHandler('input{{nextRandom}}','{{_errorMandatory}}',{{#if _isEmail}}'email'{{else}}'{{_type}}'{{/if}},'{{_errorEmail}}','{{#if _formField.forHtmlAttribute}}{{_formField.forHtmlAttribute}}{{else}}{{#if _value}}{{_value}}{{else}}{{_defaultValue}}{{/if}}{{/if}}')"
4
4
  x-ignore
5
5
  >
6
6
  <input class="relative w-full h-12 pt-4 pl-4 text-gray-800 placeholder-transparent bg-white border-blue-500 pr-9 peer border-y focus:border-y-2 border-t-transparent focus:outline-none"
@@ -1,22 +1,27 @@
1
- export default function inputHandler(element, errorMandatory, errorEmail, isEmail = false, prefilledText = '') {
1
+ export default function inputHandler(element, errorMandatory, type, errorEmail, prefilledText = '') {
2
2
  return {
3
3
  [element]: prefilledText,
4
4
  valid: false,
5
5
  wasFocused: false,
6
6
  isFocused: false,
7
7
  validEmail: false,
8
+ isChecked: false,
8
9
  errorMessage() {
9
- if( Boolean(isEmail)){
10
+ if( type == "email"){
10
11
  return !this.valid ? errorMandatory : errorEmail
11
- } else {
12
+ }
13
+ else {
12
14
  return errorMandatory
13
15
  }
14
16
  },
15
- hideDescription() {
16
- if( Boolean(isEmail)){
17
- return Boolean((!this.valid && this.wasFocused && !this.isFocused) || (!this.validEmail && this.wasFocused && !this.isFocused))
18
- } else {
19
- return Boolean(!this.valid && this.wasFocused && !this.isFocused)
17
+ hideDescription() {
18
+ switch (type) {
19
+ case "email":
20
+ return Boolean((!this.valid && this.wasFocused && !this.isFocused) || (!this.validEmail && this.wasFocused && !this.isFocused));
21
+ case "checkbox":
22
+ return Boolean(!this.valid && this.wasFocused && !this.isFocused && !this.isChecked);
23
+ default:
24
+ return Boolean(!this.valid && this.wasFocused && !this.isFocused);
20
25
  }
21
26
  },
22
27
  hideError() {
@@ -43,9 +43,16 @@
43
43
  ">
44
44
  {{_label}}{{#if _required}}*{{/if}}
45
45
  </label>
46
+ {{#if _required}}
47
+ <div class="absolute top-0 z-10 flex items-center justify-center h-12 right-14">
48
+ <div class="hidden w-5 h-5 font-bold" :class="{'hidden': hideError() }">
49
+ {{> components/base/image/icon _icon="info2" _addClass="w-5 h-5 fill-red-700"}}
50
+ </div>
51
+ </div>
52
+ {{/if}}
46
53
  <div class="flex items-end justify-between h-5 font-heading">
47
54
  {{#if _description}}
48
- <div class="pl-4 text-xs text-gray-500 min-h- " {{#if _required}}:class="{'hidden': !valid && wasFocused && !isFocused}"{{/if}}>{{_description}}</div>
55
+ <div class="pl-4 text-xs text-gray-500 " {{#if _required}}:class="{'hidden': !valid && wasFocused && !isFocused}"{{/if}}>{{_description}}</div>
49
56
  {{/if}}
50
57
  {{#if _required}}
51
58
  <div class="hidden pl-4 text-xs text-red-700" :class="{'hidden': valid || !wasFocused || isFocused}" >{{_errorMessage}}</div>