@newlogic-digital/ui 3.0.4 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/README.md +6 -10
  2. package/gulpfile.js +17 -168
  3. package/package.json +13 -8
  4. package/src/emails/email.css +3 -3
  5. package/src/emails/email.twig +1 -1
  6. package/src/icons.svg +32 -0
  7. package/src/main.json +12 -10
  8. package/src/scripts/Components/+.js +2 -2
  9. package/src/scripts/Components/CookieConsent.js +66 -64
  10. package/src/scripts/Components/Form.js +28 -21
  11. package/src/scripts/Layout/+.js +2 -1
  12. package/src/scripts/Layout/Header.js +18 -0
  13. package/src/scripts/Layout/Main.js +49 -45
  14. package/src/scripts/Libraries/+.js +12 -10
  15. package/src/scripts/Libraries/Anchor.js +18 -43
  16. package/src/scripts/Libraries/CookieConsent.js +37 -58
  17. package/src/scripts/Libraries/Dialog.js +56 -55
  18. package/src/scripts/Libraries/Drawer.js +23 -23
  19. package/src/scripts/Libraries/NativeSlider.js +86 -86
  20. package/src/scripts/Libraries/ReCaptcha.js +20 -18
  21. package/src/scripts/Libraries/Ripple.js +16 -32
  22. package/src/scripts/Libraries/Stimulus.js +30 -34
  23. package/src/scripts/Libraries/Swup.js +47 -50
  24. package/src/scripts/Libraries/Tabs.js +12 -18
  25. package/src/scripts/Libraries/Tippy.js +118 -0
  26. package/src/scripts/Ui/+.js +5 -3
  27. package/src/scripts/Ui/Checkbox.js +19 -0
  28. package/src/scripts/Ui/Input.js +188 -161
  29. package/src/scripts/Ui/Radio.js +23 -0
  30. package/src/scripts/Ui/Select.js +64 -37
  31. package/src/scripts/Ui/Text.js +25 -0
  32. package/src/scripts/Utils/Functions/+.js +6 -6
  33. package/src/scripts/Utils/Functions/dataValue.js +28 -25
  34. package/src/scripts/Utils/Functions/importScript.js +9 -11
  35. package/src/scripts/Utils/Functions/importStyle.js +18 -5
  36. package/src/scripts/Utils/Functions/inView.js +19 -21
  37. package/src/scripts/Utils/Functions/loadStimulus.js +22 -20
  38. package/src/scripts/Utils/cdn.js +6 -4
  39. package/src/scripts/Utils/global.js +10 -33
  40. package/src/scripts/main.js +6 -6
  41. package/src/styles/Components/CookieConsent.css +40 -179
  42. package/src/styles/Components/Dialog/Default.css +12 -15
  43. package/src/styles/Components/Form/CookieConsent.css +7 -12
  44. package/src/styles/Layout/+.css +2 -0
  45. package/src/{templates/Sections/.gitkeep → styles/Layout/Header.css} +0 -0
  46. package/src/styles/Layout/Main.css +28 -63
  47. package/src/styles/Layout/Nav.css +43 -0
  48. package/src/styles/Libraries/+.css +1 -1
  49. package/src/styles/Libraries/Datepicker.css +85 -39
  50. package/src/styles/Libraries/Dialog.css +6 -5
  51. package/src/styles/Libraries/Drawer.css +15 -14
  52. package/src/styles/Libraries/Hint.css +29 -23
  53. package/src/styles/Libraries/Lazysizes.css +2 -1
  54. package/src/styles/Libraries/NativeSlider.css +18 -17
  55. package/src/styles/Libraries/Ripple.css +8 -5
  56. package/src/styles/Libraries/Tabs.css +4 -4
  57. package/src/styles/Libraries/Tippy.css +87 -0
  58. package/src/styles/Ui/+.css +5 -1
  59. package/src/styles/Ui/Badge.css +33 -19
  60. package/src/styles/Ui/Btn.css +80 -53
  61. package/src/styles/Ui/Checkbox.css +80 -41
  62. package/src/styles/Ui/Dropdown.css +5 -0
  63. package/src/styles/Ui/Heading.css +12 -12
  64. package/src/styles/Ui/Icon.css +27 -8
  65. package/src/styles/Ui/Image.css +23 -0
  66. package/src/styles/Ui/Input.css +295 -220
  67. package/src/styles/Ui/Label.css +14 -0
  68. package/src/styles/Ui/Link.css +3 -3
  69. package/src/styles/Ui/Notice.css +14 -16
  70. package/src/styles/Ui/Progress.css +10 -21
  71. package/src/styles/Ui/Radio.css +3 -8
  72. package/src/styles/Ui/Select.css +63 -112
  73. package/src/styles/Ui/Switch.css +70 -0
  74. package/src/styles/Ui/{Wsw.css → Text.css} +61 -80
  75. package/src/styles/Ui/Title.css +8 -4
  76. package/src/styles/Utils/default.css +75 -67
  77. package/src/styles/Utils/icons.css +9 -0
  78. package/src/styles/Utils/keyframes.css +182 -0
  79. package/src/styles/Utils/normalize.css +223 -0
  80. package/src/styles/Utils/print.css +1 -1
  81. package/src/styles/Utils/tailwind/base.css +15 -0
  82. package/src/styles/Utils/tailwind/gutters.css +264 -263
  83. package/src/styles/Utils/theme/main.css +24 -21
  84. package/src/styles/Utils/vars.css +58 -35
  85. package/src/styles/Utils/vendor.css +1 -2
  86. package/src/styles/main.css +6 -3
  87. package/src/styles/tailwind.css +1 -4
  88. package/src/templates/Components/CookieConsent.twig +30 -0
  89. package/src/templates/Components/Dialogs/Basic.twig +7 -3
  90. package/src/templates/Layout/Header.twig +42 -0
  91. package/src/templates/Layout/Main.twig +52 -67
  92. package/src/templates/Sections/Gdpr.twig +64 -0
  93. package/src/templates/Sections/Ui.twig +2104 -0
  94. package/src/templates/dialog-basic.twig +2 -2
  95. package/src/templates/gdpr.json +11 -0
  96. package/src/templates/index.json +8 -2
  97. package/src/templates/json-tippy.twig +16 -0
  98. package/src/templates/ui.json +11 -0
  99. package/CHANGELOG +0 -231
  100. package/src/icons/iconfont.css +0 -171
  101. package/src/icons/selection.json +0 -1
  102. package/src/icons/variables.css +0 -31
  103. package/src/scripts/Ui/Wsw.js +0 -25
  104. package/src/scripts/Utils/Functions/bodyLoaded.js +0 -12
  105. package/src/styles/Libraries/Animate.css +0 -184
  106. package/src/styles/Utils/reference.css +0 -2
  107. package/src/styles/Utils/tailwind/content.css +0 -24
  108. package/src/styles/Utils/theme/vars.css +0 -19
  109. package/src/styles/preload.css +0 -29
@@ -0,0 +1,118 @@
1
+ import { loadStimulus, importStyle } from '../Utils/Functions/+.js'
2
+ import cdn from '../Utils/cdn.js'
3
+
4
+ export default class LibTippy {
5
+ async init(element, options, template) {
6
+ const tippy = (await import('tippy.js')).default
7
+ const { roundArrow } = await import('tippy.js')
8
+
9
+ await importStyle(cdn.tippy)
10
+
11
+ if (typeof element._tippy !== 'undefined') {
12
+ return false
13
+ }
14
+
15
+ if (this.type.includes('dropdown')) {
16
+ this.options.placement = 'bottom-end'
17
+ this.options.arrow = false
18
+ this.options.maxWidth = 'none'
19
+ }
20
+
21
+ if (this.type.includes('arrow')) {
22
+ options.arrow = roundArrow
23
+ }
24
+
25
+ if (!template.startsWith('/')) {
26
+ if (template !== '') {
27
+ options.content = document.querySelector('#' + template).innerHTML
28
+ } else {
29
+ options.content = `
30
+ <div class="ui-dropdown">
31
+ <div class="wrp_dropdown_body">
32
+ ${element.getAttribute('aria-label')}
33
+ </div>
34
+ </div>
35
+ `
36
+ }
37
+ }
38
+
39
+ if (typeof element.dataset.libTippySlot !== 'undefined') {
40
+ for (const [key, value] of Object.entries(JSON.parse(element.dataset.libTippySlot))) {
41
+ options.content = options.content.replaceAll(`{${key}}`, value).replaceAll(`%7B${key}%7B`, value)
42
+ }
43
+ }
44
+
45
+ tippy(element, options)
46
+ }
47
+
48
+ constructor(element, attributes = ['tooltip', '']) {
49
+ const self = this
50
+
51
+ this.options = {
52
+ content: '',
53
+ placement: 'bottom',
54
+ trigger: 'mouseenter focus',
55
+ interactive: true,
56
+ appendTo: 'parent',
57
+ arrow: false,
58
+ theme: 'light-border',
59
+ animation: 'scale',
60
+ inertia: true,
61
+ allowHTML: true,
62
+ onShow: (instance) => {
63
+ let name = this.template
64
+
65
+ if (this.type.includes('-full')) {
66
+ instance.popper.classList.add('is-full')
67
+ document.documentElement.classList.add('m:is-body-overlay')
68
+ }
69
+
70
+ if (typeof name === 'undefined') {
71
+ name = this.type
72
+ }
73
+
74
+ instance.popper.querySelector('.tippy-box').setAttribute('data-name', name)
75
+
76
+ loadStimulus(instance.popper.querySelector('.tippy-content'))
77
+ },
78
+ onHide: () => {
79
+ if (this.type.includes('-full')) {
80
+ setTimeout(() => document.documentElement.classList.remove('m:is-body-overlay'), 50)
81
+ }
82
+ }
83
+ }
84
+
85
+ this.type = attributes[0]
86
+ this.template = attributes[1]
87
+
88
+ if (this.type.includes('dropdown')) {
89
+ this.options.trigger = 'click'
90
+ }
91
+
92
+ if (typeof element.dataset.tippyTrigger !== 'undefined') {
93
+ this.options.trigger = element.dataset.tippyTrigger
94
+ }
95
+
96
+ this.options.showOnCreate = true
97
+
98
+ this.options.trigger !== 'manual' && this.options.trigger.split(' ').forEach(event => {
99
+ element.addEventListener(event, async function e() {
100
+ if (self.template.startsWith('/') && self.options.content === '') {
101
+ element.style.cursor = 'wait'
102
+
103
+ fetch(self.template, { headers: { 'X-Requested-With': 'XMLHttpRequest' } }).then(response => {
104
+ return response.json()
105
+ }).then(async(data) => {
106
+ self.options.content = data.content
107
+ element.style.cursor = ''
108
+ await self.init(element, self.options, self.template)
109
+ element.removeEventListener(event, e)
110
+ })
111
+ } else {
112
+ await self.init(element, self.options, self.template)
113
+ element.removeEventListener(event, e)
114
+ }
115
+ })
116
+ })
117
+ }
118
+ }
@@ -1,3 +1,5 @@
1
- import './Input.js';
2
- import './Select.js';
3
- import './Wsw.js';
1
+ import './Checkbox.js'
2
+ import './Input.js'
3
+ import './Radio.js'
4
+ import './Select.js'
5
+ import './Text.js'
@@ -0,0 +1,19 @@
1
+ import { LibStimulus, Controller } from '../Libraries/Stimulus.js'
2
+
3
+ LibStimulus.register('ui-checkbox', class extends Controller {
4
+ validate(element) {
5
+ element.parentNode._removeDataValue('state', 'valid invalid')
6
+
7
+ if (element.checkValidity()) {
8
+ element.parentNode._addDataValue('state', 'valid')
9
+ } else {
10
+ element.parentNode._addDataValue('state', 'invalid')
11
+ }
12
+ }
13
+
14
+ connect() {
15
+ const input = this.element.querySelector('input:not([type="hidden"])')
16
+
17
+ input.addEventListener('change', () => this.validate(input))
18
+ }
19
+ })
@@ -1,228 +1,257 @@
1
- import cdn from "../Utils/cdn.js";
2
- import {LibStimulus, Controller} from "../Libraries/Stimulus.js";
3
- import {importStyle} from "../Utils/Functions/+.js";
1
+ import cdn from '../Utils/cdn.js'
2
+ import { LibStimulus, Controller } from '../Libraries/Stimulus.js'
3
+ import { importStyle } from '../Utils/Functions/+.js'
4
4
 
5
- LibStimulus.register("ui-input", class extends Controller {
6
- connect() {
7
- let element = this.element;
5
+ LibStimulus.register('ui-input', class extends Controller {
6
+ async connect() {
7
+ const element = this.element
8
8
 
9
- this.validateInput(element, false);
9
+ this.validate(element, false)
10
10
 
11
- element.addEventListener("change", () => {
12
- this.validateInput(element, true);
13
- });
14
-
15
- this.typeNumber(element);
11
+ element.addEventListener('change', () => {
12
+ this.validate(element, true)
13
+ })
16
14
 
17
- this.typeTime(element);
15
+ this.typeNumber(element)
18
16
 
19
- this.typeDatetime(element);
17
+ this.typeFile(element)
20
18
 
21
- this.typeColor(element);
19
+ await this.typeDatetime(element)
22
20
 
23
- this.typeFile(element);
21
+ await this.typeColor(element)
24
22
  }
25
23
 
26
- validateInput(element, validate) {
27
- let input = element.querySelectorAll("input, textarea");
24
+ validate(element, validate) {
25
+ const input = element.querySelectorAll('input, textarea')
26
+
27
+ input.forEach(input => {
28
+ let validationMessage = input.validationMessage
29
+
30
+ if (typeof input.dataset.validationMessage !== 'undefined') {
31
+ validationMessage = input.dataset.validationMessage
32
+ }
28
33
 
29
- [...input].map((input) => {
30
34
  if (input.outerHTML.match(/(data-novalidate|readonly|hidden|data-state="invalid")/) === null && validate) {
31
- element.removeAttribute("data-state");
35
+ element._removeDataValue('state', 'valid invalid active')
36
+
37
+ if (element.querySelector('[class^="icon"][class*="valid"]') !== null) {
38
+ element.querySelector('[class^="icon"][class*="valid"]').remove()
39
+ }
32
40
 
33
41
  if (input.checkValidity()) {
34
- element._addDataValue("state", "valid");
42
+ element._addDataValue('state', 'valid')
35
43
  } else {
36
- element._addDataValue("state", "invalid");
44
+ element._addDataValue('state', 'invalid')
45
+
46
+ if (element.querySelector('[class^="icon"][class*="valid"]') === null) {
47
+ const icon = element.querySelector('.icon-r')
48
+ const elm = icon || element
49
+ const where = icon ? 'afterend' : 'beforeend'
50
+
51
+ elm.insertAdjacentHTML(where, `<div class="icon-r icon-invalid text-error lib-hint-top lib-hint-error" tabindex="0" aria-label="${validationMessage}"><svg><use href="#icon-exclamation-circle"></use></svg></div>`)
52
+ }
37
53
  }
38
54
  }
39
55
 
40
- if (input.value !== "") {
41
- element._addDataValue("state", "active");
56
+ if (input.value !== '') {
57
+ element._addDataValue('state', 'active')
42
58
  }
43
59
  })
44
60
  }
45
61
 
46
62
  typeNumber(element) {
47
- if (element.querySelector(`[type="number"]`) !== null) {
48
- if (element.querySelector(".icon") === null) {
49
- element.insertAdjacentHTML("beforeend", `<span class="icon icon-angle-down" data-action="minus"></span><span class="icon icon-angle-up" data-action="plus"></span>`);
63
+ if (element.querySelector('[type="number"]') !== null) {
64
+ if (element.querySelector('.icon') === null) {
65
+ element.insertAdjacentHTML('beforeend', '<span class="icon icon-angle-down" data-action="minus"></span><span class="icon icon-angle-up" data-action="plus"></span>')
50
66
  }
51
67
 
52
- element.querySelector(`[type="number"]`).addEventListener("keydown", (e) => {
68
+ element.querySelector('[type="number"]').addEventListener('keydown', e => {
53
69
  if ([46, 8, 9, 27, 13, 190].indexOf(e.keyCode) !== -1 || e.keyCode === 16 || (e.keyCode === 65 && e.ctrlKey === true) || (e.keyCode >= 35 && e.keyCode <= 39)) {
54
- return;
70
+ return
55
71
  }
56
72
 
57
73
  if (((e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) {
58
- e.preventDefault();
74
+ e.preventDefault()
59
75
  }
60
- });
76
+ })
61
77
 
62
- element.querySelector(`[data-action="plus"]`).addEventListener("click", () => {
63
- let input = this.element.querySelector("input"),
64
- num = parseInt(input.value) + parseInt(input.getAttribute('data-step'));
78
+ element.querySelector('[data-action="plus"]').addEventListener('click', () => {
79
+ const input = this.element.querySelector('input')
80
+ const num = parseInt(input.value === '' ? 0 : input.value) + parseInt(input.step)
65
81
 
66
- if (num <= input.getAttribute('max')) {
67
- input.value = num;
68
- input.dispatchEvent(new Event('change', { 'bubbles': true }));
82
+ if (num <= input.max) {
83
+ input.value = num
84
+ input.dispatchEvent(new Event('change', { bubbles: true }))
69
85
  }
70
- });
86
+ })
71
87
 
72
- element.querySelector(`[data-action="minus"]`).addEventListener("click", () => {
73
- let input = this.element.querySelector("input"),
74
- num = parseInt(input.value) - parseInt(input.getAttribute('data-step'));
88
+ element.querySelector('[data-action="minus"]').addEventListener('click', () => {
89
+ const input = this.element.querySelector('input')
90
+ const num = parseInt(input.value) - parseInt(input.step)
75
91
 
76
- if (num >= input.getAttribute('min')) {
77
- input.value = num;
78
- input.dispatchEvent(new Event('change', { 'bubbles': true }));
92
+ if (num >= input.min) {
93
+ input.value = num
94
+ input.dispatchEvent(new Event('change', { bubbles: true }))
79
95
  }
80
- });
96
+ })
81
97
  }
82
98
  }
83
99
 
84
100
  async typeDatetime(element) {
85
- let date = element.querySelector(`[type^="date"]`);
101
+ const date = element.querySelector('[type^="date"]')
86
102
 
87
- if (date !== null && !document.documentElement.classList.contains("mobile")) {
88
- const lang = await import(`/* @vite-ignore */https://cdn.esm.sh/v41/vanillajs-datepicker/locales/${document.documentElement.lang === "en" ? "cs" : document.documentElement.lang}.js`);
89
- const { Datepicker } = await import("vanillajs-datepicker");
103
+ if (date !== null && !document.documentElement.classList.contains('mobile')) {
104
+ const lang = await import(`/* @vite-ignore */https://cdn.jsdelivr.net/npm/vanillajs-datepicker@1.2.0/js/i18n/locales/${document.documentElement.lang === 'en' ? 'cs' : document.documentElement.lang}.min.js`)
105
+ const { Datepicker } = await import('vanillajs-datepicker')
106
+
107
+ await importStyle(cdn.datepicker)
90
108
 
91
109
  Object.assign(Datepicker.locales, lang.default)
92
110
 
93
- let datetime = date.getAttribute("type") === "datetime-local";
94
- let required = date.getAttribute("required") !== null;
95
- let placeholder = date.getAttribute("placeholder") !== null;
96
- let currentDate, currentTime = null;
111
+ const datetime = date.getAttribute('type') === 'datetime-local'
112
+ const required = date.getAttribute('required') !== null
113
+ const placeholder = date.getAttribute('placeholder') !== null
114
+ let currentDate; let currentTime = null
97
115
 
98
- date.setAttribute("type", "hidden");
99
- element.insertAdjacentHTML("beforeend", `<input type="text" inputmode="none" ${required ? 'required': ''} ${placeholder ? 'placeholder': ''}>`);
100
- element.querySelector(`[type="text"]`).addEventListener("keydown", (e) => e.preventDefault());
116
+ date.setAttribute('type', 'hidden')
117
+ element.insertAdjacentHTML('beforeend', `<input type="text" inputmode="none" ${required ? 'required' : ''} ${placeholder ? `placeholder="${date.getAttribute('placeholder')}"` : ''}>`)
101
118
 
102
- let hidden = element.querySelector(`[type="hidden"]`);
119
+ const hidden = element.querySelector('[type="hidden"]')
103
120
 
104
- if (datetime && hidden.value.indexOf(":") !== -1) {
105
- hidden.setAttribute("data-time", hidden.value.substr(hidden.value.indexOf(":") - 2, hidden.value.length))
121
+ if (datetime && hidden.value.indexOf(':') !== -1) {
122
+ hidden.setAttribute('data-time', hidden.value.substr(hidden.value.indexOf(':') - 2, hidden.value.length))
106
123
  }
107
124
 
108
- let datepicker = new Datepicker(element.querySelector(`[type="text"]`), Object.assign({
109
- autohide: true,
125
+ const datepicker = new Datepicker(element.querySelector('[type="text"]'), Object.assign({
126
+ autohide: !datetime,
110
127
  language: document.documentElement.lang,
111
- minDate: Datepicker.parseDate(hidden.getAttribute("min"),"yyyy-mm-dd"),
112
- maxDate: Datepicker.parseDate(hidden.getAttribute("max"),"yyyy-mm-dd")
113
- }, JSON.parse(element.getAttribute("data-lib-datepicker"))));
114
-
115
- datepicker.setDate(Datepicker.parseDate(hidden.value,"yyyy-mm-dd"));
128
+ format: 'dd.mm.yyyy',
129
+ clearBtn: true,
130
+ todayBtn: true,
131
+ todayBtnMode: 1,
132
+ minDate: Datepicker.parseDate(hidden.getAttribute('min'), 'yyyy-mm-dd'),
133
+ maxDate: Datepicker.parseDate(hidden.getAttribute('max'), 'yyyy-mm-dd')
134
+ }, JSON.parse(element.getAttribute('data-lib-datepicker'))))
135
+ datepicker.setDate(Datepicker.parseDate(hidden.value, 'yyyy-mm-dd'))
116
136
 
117
137
  if (datetime && hidden.value) {
118
- element.insertAdjacentHTML("afterbegin", `<span class="input" ${placeholder ? 'placeholder': ''}>${datepicker.getDate("dd.mm.yyyy") + " " + hidden.dataset.time}</span>`);
138
+ element.insertAdjacentHTML('afterbegin', `<span class="input" ${placeholder ? 'placeholder' : ''}><span>${datepicker.getDate('dd.mm.yyyy') + '</span>&nbsp;' + hidden.dataset.time}</span>`)
139
+ }
140
+
141
+ if (datetime) {
142
+ datepicker.element.addEventListener('keydown', e => {
143
+ if (e.key === 'Backspace' || e.key === 'Delete') {
144
+ datepicker.setDate({ clear: true })
145
+ } else {
146
+ e.preventDefault()
147
+ }
148
+ })
119
149
  }
120
150
 
121
- datepicker.element.addEventListener("changeDate", () => {
122
- if (typeof hidden.dataset.time !== "undefined") {
123
- hidden.value = datepicker.getDate("yyyy-mm-dd") + "T" + hidden.dataset.time;
151
+ datepicker.element.addEventListener('changeDate', () => {
152
+ if (typeof hidden.dataset.time !== 'undefined') {
153
+ if (typeof datepicker.getDate('yyyy-mm-dd') !== 'undefined') {
154
+ hidden.value = datepicker.getDate('yyyy-mm-dd') + 'T' + hidden.dataset.time
124
155
 
125
- let value = datepicker.getDate("dd.mm.yyyy") + " " + hidden.dataset.time;
156
+ const value = '<span>' + datepicker.getDate('dd.mm.yyyy') + '</span>&nbsp;' + hidden.dataset.time
126
157
 
127
- if (element.querySelector('.input') === null) {
128
- element.insertAdjacentHTML("afterbegin", `<span class="input" ${placeholder ? 'placeholder': ''}>${value}</span>`);
158
+ if (element.querySelector('.input') === null) {
159
+ element.insertAdjacentHTML('afterbegin', `<span class="input" ${placeholder ? 'placeholder' : ''}>${value}</span>`)
160
+ } else {
161
+ element.querySelector('.input').innerHTML = value
162
+ }
129
163
  } else {
130
- element.querySelector('.input').textContent = value;
164
+ hidden.value = ''
165
+ element.querySelector('.input').textContent = ''
131
166
  }
167
+ } else if (datepicker.getDate()) {
168
+ hidden.value = datepicker.getDate('yyyy-mm-dd')
132
169
  } else {
133
- hidden.value = datepicker.getDate("yyyy-mm-dd");
170
+ hidden.value = ''
134
171
  }
135
172
 
136
- hidden.dispatchEvent(new Event('change', { 'bubbles': true }));
137
- });
173
+ hidden.dispatchEvent(new Event('change', { bubbles: true }))
174
+ })
138
175
 
139
- datepicker.element.addEventListener("show", (element) => {
140
- let footer = element.detail.datepicker.picker.element.querySelector(".datepicker-footer");
141
- currentDate = datepicker.getDate("yyyy-mm-dd");
176
+ datepicker.element.addEventListener('show', element => {
177
+ const footer = element.detail.datepicker.picker.element.querySelector('.datepicker-footer')
178
+ currentDate = datepicker.getDate('yyyy-mm-dd')
142
179
 
143
- this.element._addDataValue("state", "active");
180
+ this.element._addDataValue('state', 'active')
144
181
 
145
182
  if (footer.querySelector('[type="time"]') === null && datetime) {
146
- let time = hidden.dataset.time;
183
+ let time = hidden.dataset.time
147
184
 
148
- if (typeof time === "undefined") {
149
- time = new Date().toLocaleTimeString("de", {hour: "2-digit", minute: "2-digit"});
150
- hidden.setAttribute("data-time", time);
185
+ if (typeof time === 'undefined') {
186
+ time = new Date().toLocaleTimeString('de', { hour: '2-digit', minute: '2-digit' })
187
+ hidden.setAttribute('data-time', time)
151
188
  }
152
189
 
153
- currentTime = time;
190
+ currentTime = time
154
191
 
155
- footer.insertAdjacentHTML("beforeend", `<div class="datepicker-time"><input type="time" value="${time}" aria-label="Text"></div>`);
192
+ footer.querySelector('.datepicker-controls').insertAdjacentHTML('beforeend', `<input type="time" value="${time}" aria-label="Text"><button type="button" data-ok class="button ok-btn" style="width: auto;">Ok</button>`)
156
193
 
157
- this.typeTime(footer);
194
+ footer.querySelector('[type="time"]').addEventListener('change', e => {
195
+ hidden.setAttribute('data-time', e.target.value)
196
+ })
158
197
 
159
- footer.querySelector(`[type="time"]`).addEventListener("change", (e) => {
160
- hidden.setAttribute("data-time", e.target.value);
161
- });
198
+ footer.querySelector('[type="time"]').addEventListener('mousedown', e =>
199
+ e.stopPropagation()
200
+ )
162
201
 
163
- footer.querySelector(`[type="time"]`).addEventListener("click", (e) => {
164
- e.stopPropagation();
165
- e.preventDefault();
166
- e.target.focus();
167
- });
168
- } else if (datetime) {
169
- currentTime = hidden.dataset.time;
170
- }
171
- });
202
+ footer.querySelector('[type="time"]').addEventListener('blur', e => {
203
+ e.stopPropagation()
204
+ e.preventDefault()
205
+ datepicker.element.focus()
206
+ })
172
207
 
173
- datepicker.element.addEventListener("hide", (element) => {
208
+ footer.querySelector('[data-ok]').addEventListener('click', e => {
209
+ if (hidden.value === '') {
210
+ footer.querySelector('.today-btn').click()
211
+ }
174
212
 
175
- if (hidden.value === "") {
176
- this.element._removeDataValue("state", "active");
177
- }
213
+ datepicker.element.focus()
214
+ datepicker.hide()
215
+ })
216
+ } else if (datetime) {
217
+ currentTime = hidden.dataset.time
218
+ }
219
+ })
178
220
 
179
- if (datetime) {
180
- element.detail.datepicker.picker.element.querySelector(`[type="time"]`).dispatchEvent(new Event('change', { 'bubbles': true }));
221
+ datepicker.element.addEventListener('hide', element => {
222
+ if (hidden.value === '') {
223
+ this.element._removeDataValue('state', 'active')
224
+ } else {
225
+ if (datetime) {
226
+ element.detail.datepicker.picker.element.querySelector('[type="time"]').dispatchEvent(new Event('change', { bubbles: true }))
181
227
 
182
- if (currentDate === datepicker.getDate("yyyy-mm-dd") && currentTime.toString() !== hidden.dataset.time.toString()) {
183
- datepicker.element.dispatchEvent(new Event('changeDate', { 'bubbles': true }));
228
+ if (currentDate !== datepicker.getDate('yyyy-mm-dd') || currentTime.toString() !== hidden.dataset.time.toString()) {
229
+ datepicker.element.dispatchEvent(new Event('changeDate', { bubbles: true }))
230
+ }
184
231
  }
185
232
  }
186
- });
187
- }
188
- }
189
-
190
- async typeTime(element) {
191
- if (element.querySelector(`[type="time"]`) !== null && element.querySelector(`[type="time"]`).type !== "time") {
192
- const Cleave = (await import("cleave.js")).default;
193
-
194
- element.querySelector('[type="time"]').setAttribute("placeholder", "--:--");
195
- element.querySelector('[type="time"]').classList.add("polyfill");
196
-
197
- if (element.querySelector("label") !== null) {
198
- element.querySelector('[type="time"]').classList.add("is-label");
199
- }
200
-
201
- new Cleave(element.querySelector('[type="time"]'), {
202
- time: true,
203
- timePattern: ['h', 'm']
204
- });
233
+ })
205
234
  }
206
235
  }
207
236
 
208
237
  async typeColor(element) {
209
- if (element.querySelector(`[type="color"]`) !== null) {
210
- element.setAttribute("data-type", "color");
211
- element.querySelector(`[type="color"]`).setAttribute("inputmode", "none");
212
- element.querySelector(`[type="color"]`).setAttribute("type", "text");
213
- element.insertAdjacentHTML("afterbegin", `<span class="color"></span>`);
238
+ if (element.querySelector('[type="color"]') !== null) {
239
+ element.setAttribute('data-type', 'color')
240
+ element.querySelector('[type="color"]').setAttribute('inputmode', 'none')
241
+ element.querySelector('[type="color"]').setAttribute('type', 'text')
242
+ element.insertAdjacentHTML('afterbegin', '<span class="color"></span>')
214
243
 
215
- importStyle(cdn.pickr_css);
244
+ await importStyle(cdn.pickr_css)
216
245
 
217
- let Pickr = (await import("@simonwep/pickr")).default;
246
+ let Pickr = (await import('@simonwep/pickr')).default
218
247
 
219
- if (typeof Pickr.default !== "undefined") {
248
+ if (typeof Pickr.default !== 'undefined') {
220
249
  Pickr = Pickr.default
221
250
  }
222
251
 
223
- let input = element.querySelector("input");
224
- input.setAttribute("maxlength", "9");
225
- input.setAttribute("pattern", "^#?([a-fA-F0-9]{8}|[a-fA-F0-9]{6}|[a-fA-F0-9]{3})$");
252
+ const input = element.querySelector('input')
253
+ input.setAttribute('maxlength', '9')
254
+ input.setAttribute('pattern', '^#?([a-fA-F0-9]{8}|[a-fA-F0-9]{6}|[a-fA-F0-9]{3})$')
226
255
 
227
256
  const pickr = new Pickr({
228
257
  el: input,
@@ -240,39 +269,37 @@ LibStimulus.register("ui-input", class extends Controller {
240
269
  }
241
270
  }
242
271
  }).on('init', pickr => {
243
- pickr.setColor(input.value);
272
+ pickr.setColor(input.value)
244
273
  }).on('change', color => {
245
- input.value = color.toHEXA().toString();
246
- element.querySelector(".color").style["background-color"] = color.toHEXA().toString();
274
+ input.value = color.toHEXA().toString()
275
+ element.querySelector('.color').style['background-color'] = color.toHEXA().toString()
247
276
  }).on('hide', pickr => {
248
- pickr.applyColor();
249
- input.dispatchEvent(new Event('change', { 'bubbles': true }));
277
+ pickr.applyColor()
278
+ input.dispatchEvent(new Event('change', { bubbles: true }))
250
279
  })
251
280
 
252
- input.addEventListener("change", (e) => {
253
- pickr.setColor(e.target.value);
281
+ input.addEventListener('change', e => {
282
+ pickr.setColor(e.target.value)
254
283
  })
255
-
256
284
  }
257
285
  }
258
286
 
259
287
  typeFile(element) {
260
- if (element.querySelector(`[type="file"]`) !== null) {
261
- element.setAttribute("data-type", "file");
262
- element.insertAdjacentHTML("beforeend", `<span class="icon icon-paper-clip">${element.querySelector("input").title}</span><span data-placeholder="${element.querySelector("input").placeholder}"></span>`);
263
- element.querySelector("input").addEventListener("change", (e) => {
264
- let placeholder = element.querySelector("span:not(.icon)");
265
-
266
- if (e.target.getAttribute("multiple") === null) {
267
- placeholder.removeAttribute("data-placeholder");
268
- placeholder.textContent = e.target.value.replace(/.*(\/|\\)/, '');
288
+ if (element.querySelector('[type="file"]') !== null) {
289
+ element.setAttribute('data-type', 'file')
290
+ element.insertAdjacentHTML('beforeend', `<span class="icon icon-paper-clip">${element.querySelector('input').title}</span><span data-placeholder="${element.querySelector('input').placeholder}"></span>`)
291
+ element.querySelector('input').addEventListener('change', e => {
292
+ const placeholder = element.querySelector('span:not(.icon)')
293
+
294
+ if (e.target.getAttribute('multiple') === null) {
295
+ placeholder.removeAttribute('data-placeholder')
296
+ placeholder.textContent = e.target.value.replace(/.*(\/|\\)/, '')
269
297
  } else {
270
- let files = e.target.files;
271
- placeholder.removeAttribute("data-placeholder");
272
- placeholder.textContent = `${Object.keys(files).length} soubory`;
273
-
298
+ const files = e.target.files
299
+ placeholder.removeAttribute('data-placeholder')
300
+ placeholder.textContent = Object.keys(files).length === 1 ? e.target.value.replace(/.*(\/|\\)/, '') : `${Object.keys(files).length} soubory`
274
301
  }
275
- });
302
+ })
276
303
  }
277
304
  }
278
- });
305
+ })
@@ -0,0 +1,23 @@
1
+ import { LibStimulus, Controller } from '../Libraries/Stimulus.js'
2
+
3
+ LibStimulus.register('ui-radio', class extends Controller {
4
+ validate(element) {
5
+ element.parentNode._removeDataValue('state', 'valid invalid')
6
+
7
+ if (element.checkValidity()) {
8
+ element.parentNode._addDataValue('state', 'valid')
9
+
10
+ document.querySelectorAll(`input[name="${element.name}"]`).forEach(element => {
11
+ element.parentNode._addDataValue('state', 'valid')
12
+ })
13
+ } else {
14
+ element.parentNode._addDataValue('state', 'invalid')
15
+ }
16
+ }
17
+
18
+ connect() {
19
+ const input = this.element.querySelector('input:not([type="hidden"])')
20
+
21
+ input.addEventListener('change', () => this.validate(input))
22
+ }
23
+ })