@componyx/ui 0.0.0-stage → 1.0.3

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 (169) hide show
  1. package/AppSkin/AppSkin.css +1268 -0
  2. package/AppSkin/AppSkin.js +2748 -0
  3. package/AppSkin/Themes/Default.css +241 -0
  4. package/Base/Base.js +3407 -0
  5. package/Base/ComponentIcons.css +66 -0
  6. package/Base/Font/ComponentIcons.woff +0 -0
  7. package/Base/Font/UI.woff +0 -0
  8. package/Base/Library.js +8432 -0
  9. package/Base/NavigationManager.js +462 -0
  10. package/Base/ResponsiveTemplates.js +371 -0
  11. package/Base/Sanitizer.js +288 -0
  12. package/Base/Themes/Default.css +255 -0
  13. package/Base/UI.css +618 -0
  14. package/Base/UIResourcePath.js +6 -0
  15. package/Bindary/Bindary.js +2011 -0
  16. package/Bindary/Modules/Connection.js +216 -0
  17. package/Bindary/Modules/Core.js +854 -0
  18. package/Bindary/Modules/DataUpdater.js +351 -0
  19. package/Bindary/Modules/ExpressionEngine.js +347 -0
  20. package/Bindary/Modules/ProxyManager.js +482 -0
  21. package/Bindary/Modules/Renderer.js +605 -0
  22. package/Bindary/Modules/Router.js +291 -0
  23. package/Bindary/Modules/Scroller.js +89 -0
  24. package/Bindary/Modules/Template.js +1273 -0
  25. package/BookmarkSpy/BookmarkSpy.js +430 -0
  26. package/Box/Box.css +36 -0
  27. package/Box/Box.js +1685 -0
  28. package/Button/Button.css +470 -0
  29. package/Button/Button.js +1398 -0
  30. package/Button/Themes/Default.css +200 -0
  31. package/Carousel/Carousel.css +273 -0
  32. package/Carousel/Carousel.js +607 -0
  33. package/ColorButton/ColorButton.css +39 -0
  34. package/ColorButton/ColorButton.js +336 -0
  35. package/ColorPicker/ColorPicker.css +359 -0
  36. package/ColorPicker/ColorPicker.js +972 -0
  37. package/ComboBox/ComboBox.css +357 -0
  38. package/ComboBox/ComboBox.js +2342 -0
  39. package/ComboBox/Themes/Default.css +23 -0
  40. package/DataPager/DataPager.css +72 -0
  41. package/DataPager/DataPager.js +674 -0
  42. package/DatePicker/DatePicker.css +227 -0
  43. package/DatePicker/DatePicker.js +1531 -0
  44. package/DatePicker/Themes/Default.css +26 -0
  45. package/Dialog/Dialog.css +106 -0
  46. package/Dialog/Dialog.js +572 -0
  47. package/Dialog/Themes/Default.css +10 -0
  48. package/Editor/Data/Emoji.json +8285 -0
  49. package/Editor/Data/Special.json +1042 -0
  50. package/Editor/Editor.css +1562 -0
  51. package/Editor/Editor.js +4058 -0
  52. package/Editor/Font/Editor.woff +0 -0
  53. package/Editor/Modules/ComponentFactory.js +565 -0
  54. package/Editor/Modules/ContentManager.js +748 -0
  55. package/Editor/Modules/DialogManager.js +1234 -0
  56. package/Editor/Modules/EventManager.js +458 -0
  57. package/Editor/Modules/Format.js +950 -0
  58. package/Editor/Modules/History.js +191 -0
  59. package/Editor/Modules/LayoutState.js +379 -0
  60. package/Editor/Modules/ListManager.js +296 -0
  61. package/Editor/Modules/MenuManager.js +388 -0
  62. package/Editor/Modules/NodeManager.js +681 -0
  63. package/Editor/Modules/ParagraphButtons.js +122 -0
  64. package/Editor/Modules/Resizer.js +176 -0
  65. package/Editor/Modules/SelectionRange.js +564 -0
  66. package/Editor/Modules/SourceViewBuilder.js +212 -0
  67. package/Editor/Modules/SymbolPicker.js +208 -0
  68. package/Editor/Modules/Table.js +2327 -0
  69. package/Editor/Modules/TableDialog.js +757 -0
  70. package/Editor/Modules/Toolbar.js +375 -0
  71. package/Editor/Modules/TooltipMenu.js +125 -0
  72. package/Editor/Modules/Utility.js +131 -0
  73. package/Editor/Themes/Default.css +204 -0
  74. package/FileUpload/FileUpload.css +156 -0
  75. package/FileUpload/FileUpload.js +898 -0
  76. package/FileUpload/Themes/Default.css +17 -0
  77. package/Form/Form.css +1934 -0
  78. package/Form/Form.js +4943 -0
  79. package/Form/Modules/ActionManager.js +368 -0
  80. package/Form/Modules/BuildPanelManager.js +319 -0
  81. package/Form/Modules/ComponentFactory.js +468 -0
  82. package/Form/Modules/ComponentPanel.js +265 -0
  83. package/Form/Modules/ConfigPanelManager.js +685 -0
  84. package/Form/Modules/DataObserver.js +717 -0
  85. package/Form/Modules/Databinder.js +602 -0
  86. package/Form/Modules/Draggable.js +756 -0
  87. package/Form/Modules/OptionsPanel.js +342 -0
  88. package/Form/Modules/Renderer.js +1889 -0
  89. package/Form/Modules/RuleEngine.js +585 -0
  90. package/Form/Modules/RulesPanel.js +1158 -0
  91. package/Form/Modules/Types.js +1709 -0
  92. package/Form/Modules/ValidationManager.js +194 -0
  93. package/Form/Themes/Default.css +216 -0
  94. package/FormField/FormField.css +468 -0
  95. package/FormField/FormField.js +576 -0
  96. package/FormField/Themes/Default.css +99 -0
  97. package/Grid/Grid.css +544 -0
  98. package/Grid/Grid.js +3761 -0
  99. package/Grid/Themes/Default.css +43 -0
  100. package/LICENSE +126 -0
  101. package/MaskedTextBox/MaskedTextBox.css +28 -0
  102. package/MaskedTextBox/MaskedTextBox.js +642 -0
  103. package/MaskedTextBox/Themes/Default.css +6 -0
  104. package/Menu/Menu.css +328 -0
  105. package/Menu/Menu.js +2386 -0
  106. package/Menu/Themes/Default.css +24 -0
  107. package/NumericBox/NumericBox.css +120 -0
  108. package/NumericBox/NumericBox.js +984 -0
  109. package/PanelBar/PanelBar.css +123 -0
  110. package/PanelBar/PanelBar.js +505 -0
  111. package/PanelBar/Themes/Default.css +51 -0
  112. package/PieChart/PieChart.css +95 -0
  113. package/PieChart/PieChart.js +820 -0
  114. package/PieChart/Themes/Default.css +9 -0
  115. package/README.md +178 -3
  116. package/Slider/Slider.css +348 -0
  117. package/Slider/Slider.js +1306 -0
  118. package/Slider/Themes/Default.css +44 -0
  119. package/TabStrip/TabStrip.css +52 -0
  120. package/TabStrip/TabStrip.js +362 -0
  121. package/TabStrip/Themes/Default.css +35 -0
  122. package/TimePicker/Themes/Default.css +30 -0
  123. package/TimePicker/TimePicker.css +253 -0
  124. package/TimePicker/TimePicker.js +1485 -0
  125. package/TooltipManager/Themes/Default.css +21 -0
  126. package/TooltipManager/TooltipManager.css +227 -0
  127. package/TooltipManager/TooltipManager.js +791 -0
  128. package/Validator/Validator.css +54 -0
  129. package/Validator/Validator.js +2508 -0
  130. package/componyx.html-data.json +619 -0
  131. package/index.js +27 -0
  132. package/package.json +43 -4
  133. package/types/AppSkin.d.ts +842 -0
  134. package/types/Base.d.ts +1034 -0
  135. package/types/Bindary.d.ts +1196 -0
  136. package/types/BookmarkSpy.d.ts +112 -0
  137. package/types/Box.d.ts +374 -0
  138. package/types/Button.d.ts +455 -0
  139. package/types/Carousel.d.ts +136 -0
  140. package/types/ColorButton.d.ts +120 -0
  141. package/types/ColorPicker.d.ts +225 -0
  142. package/types/ComboBox.d.ts +507 -0
  143. package/types/DataPager.d.ts +152 -0
  144. package/types/DatePicker.d.ts +354 -0
  145. package/types/Dialog.d.ts +160 -0
  146. package/types/Editor.d.ts +1289 -0
  147. package/types/FileUpload.d.ts +206 -0
  148. package/types/Form.d.ts +3078 -0
  149. package/types/FormField.d.ts +204 -0
  150. package/types/Grid.d.ts +911 -0
  151. package/types/Library.d.ts +1899 -0
  152. package/types/MaskedTextBox.d.ts +91 -0
  153. package/types/Menu.d.ts +577 -0
  154. package/types/NumericBox.d.ts +310 -0
  155. package/types/PanelBar.d.ts +223 -0
  156. package/types/PieChart.d.ts +224 -0
  157. package/types/ResponsiveTemplates.d.ts +108 -0
  158. package/types/Slider.d.ts +227 -0
  159. package/types/TabStrip.d.ts +185 -0
  160. package/types/TimePicker.d.ts +265 -0
  161. package/types/TooltipManager.d.ts +178 -0
  162. package/types/UI.d.ts +29 -0
  163. package/types/Validator.d.ts +653 -0
  164. package/types/index.d.ts +59 -0
  165. package/ui.css +11783 -0
  166. package/ui.js +79477 -0
  167. package/ui.min.css +138 -0
  168. package/ui.min.js +264 -0
  169. package/ui.min.js.map +1 -0
@@ -0,0 +1,576 @@
1
+ /*! Componyx.UI | (c) E.H. Daanen / Componyx | BUSL-1.1 | componyx.com/license */
2
+ import '../Base/Base.js';
3
+ import '../Base/Library.js';
4
+
5
+ (function (window)
6
+ {
7
+ /**
8
+ * FormField class.
9
+ * @class
10
+ * @memberof componyx.UI
11
+ * @augments componyx.UI.base.Component
12
+ * @param {String} id The id of the component.
13
+ * @param {Object|HTMLElement} properties The properties used to initialize the component or the container element.
14
+ * @returns {Object} An instance of the component.
15
+ */
16
+ componyx.UI.FormField = function (id, properties)
17
+ {
18
+ // define private properties
19
+ let _instance = this,
20
+ _formElements = 'input:not([type="hidden"]):not([type="file"]), textarea, select',
21
+ _labelDisplayOption = componyx.UI.FormField.LabelDisplayOption,
22
+ _tooltipIcon,
23
+ _classOption =
24
+ {
25
+ INLINE: 'inline',
26
+ REQUIRED: 'required',
27
+ BORDERLESS: 'borderless',
28
+ TRANSPARENT: 'lucent',
29
+ SWITCH: 'switch',
30
+ TOOLTIP_ICON: 'icon ico-question-mark',
31
+ CONTENT_WRAPPER: 'field-content-wrapper',
32
+ DISABLED: 'disabled'
33
+ };
34
+
35
+ // define public properties
36
+ /**
37
+ * Gets or sets the css class which is appended to the formfield class when inline is enabled.
38
+ * @type {String}
39
+ */
40
+ this.cssClassInline = '';
41
+
42
+ /**
43
+ * Gets or sets the css class which is appended to the formfield class when required is enabled.
44
+ * @type {String}
45
+ */
46
+ this.cssClassRequired = '';
47
+
48
+ /**
49
+ * Gets or sets the css class which is appended to the formfield class when borderless is enabled.
50
+ * @type {String}
51
+ */
52
+ this.cssClassBorderless = '';
53
+
54
+ /**
55
+ * Gets or sets the css class which is appended to the formfield class when transparent is enabled.
56
+ * @type {String}
57
+ */
58
+ this.cssClassTransparent = '';
59
+
60
+ /**
61
+ * Gets or sets the css class which is appended to the formfield class when switch is enabled.
62
+ * @type {String}
63
+ */
64
+ this.cssClassSwitch = '';
65
+
66
+ /**
67
+ * Gets or sets the css class of the form field label element.
68
+ * @type {String}
69
+ */
70
+ this.cssClassLabel = '';
71
+
72
+ /**
73
+ * Gets or sets the css class of the form field tooltip icon element.
74
+ * @type {String}
75
+ */
76
+ this.cssClassTooltipIcon = '';
77
+
78
+ /**
79
+ * Gets or sets the css class of the form field content wrapper element when wrapFieldContent is set to true or the field root element is not an input field and the label display is set to above/floating/inside.
80
+ * @type {String}
81
+ */
82
+ this.cssClassContentWrapper = '';
83
+
84
+ /**
85
+ * Gets or sets the text label.
86
+ * @type {String}
87
+ */
88
+ this.label = '';
89
+
90
+ /**
91
+ * Gets or sets a value indicating whether the formfield is displayed as inline or block element.
92
+ * @type {Boolean}
93
+ */
94
+ this.inline = false;
95
+
96
+ /**
97
+ * Gets or sets a value indicating if the form field is required.
98
+ * @type {Boolean}
99
+ */
100
+ this.required = false;
101
+
102
+ /**
103
+ * Gets or sets a value indicating if the form field is rendered without the top, left and right borders.
104
+ * @type {Boolean}
105
+ */
106
+ this.borderless = true;
107
+
108
+ /**
109
+ * Gets or sets a value indicating if the checkbox or radio field must be rendered transparent.
110
+ * @type {Boolean}
111
+ */
112
+ this.transparent = false;
113
+
114
+ /**
115
+ * Gets or sets a value indicating if the form field must be rendered as switch control. This option has effect only when the field is an input of type checkbox.
116
+ * @type {Boolean}
117
+ */
118
+ this.switch = false;
119
+
120
+ /**
121
+ * Gets or sets a value indicating if the form field content is placed inside a wrapper element.
122
+ * @type {Boolean}
123
+ */
124
+ this.wrapFieldContent = false;
125
+
126
+ /**
127
+ * Gets or sets a value indicating if the form field is disabled.
128
+ * @type {Boolean}
129
+ */
130
+ this.disabled = false;
131
+
132
+ /**
133
+ * Gets or sets a value indicating whether the label is displayed automatically, inside, above, before or after the form input field.
134
+ * @type {componyx.UI.FormField.LabelDisplayOption}
135
+ */
136
+ this.labelDisplay = _labelDisplayOption.AUTO;
137
+
138
+ /**
139
+ * Gets or sets the tooltip manager used to display tooltips.
140
+ * @type {String|null}
141
+ */
142
+ this.tooltipManagerId = null;
143
+
144
+ /**
145
+ * Gets or sets the id of the tooltip to show.
146
+ * @type {String|null}
147
+ */
148
+ this.tooltipId = null;
149
+
150
+
151
+ // inherit base instance members
152
+ $base.Component.apply(this, [id, properties]);
153
+
154
+ /**
155
+ * Enables or disables the inline state of the form field.
156
+ * @param {Boolean} enable A value indicating if the option should be enabled or disabled.
157
+ */
158
+ this.setInline = function (enable)
159
+ {
160
+ setCss(enable, _instance.cssClassInline || _classOption.INLINE);
161
+ _instance.inline = enable || false;
162
+ };
163
+
164
+ /**
165
+ * Enables or disables the required state of the form field.
166
+ * @param {Boolean} enable A value indicating if the option should be enabled or disabled.
167
+ */
168
+ this.setRequired = function (enable)
169
+ {
170
+ setCss(enable, _instance.cssClassRequired || _classOption.REQUIRED);
171
+ _instance.required = enable || false;
172
+ };
173
+
174
+ /**
175
+ * Enables or disables the borderless field style.
176
+ * @param {Boolean} enable A value indicating if the option should be enabled or disabled.
177
+ */
178
+ this.setBorderless = function (enable)
179
+ {
180
+ setCss(enable, _instance.cssClassBorderless || _classOption.BORDERLESS);
181
+ _instance.borderless = enable || false;
182
+ };
183
+
184
+ /**
185
+ * Enables or disables the transparent field style.
186
+ * @param {Boolean} enable A value indicating if the option should be enabled or disabled.
187
+ */
188
+ this.setTransparent = function (enable)
189
+ {
190
+ setCss(enable, _instance.cssClassTransparent || _classOption.TRANSPARENT);
191
+ _instance.transparent = enable || false;
192
+ };
193
+
194
+ /**
195
+ * Enables or disables the switch field style.
196
+ * @param {Boolean} enable A value indicating if the option should be enabled or disabled.
197
+ */
198
+ this.setSwitch = function (enable)
199
+ {
200
+ setCss(enable, _instance.cssClassSwitch || _classOption.SWITCH);
201
+ _instance.switch = enable || false;
202
+ };
203
+
204
+ /**
205
+ * Sets the label display type (inside above before after).
206
+ * @param {componyx.UI.FormField.LabelDisplayOption} display The label display option.
207
+ */
208
+ this.setLabelDisplay = function (display)
209
+ {
210
+ var field = _instance.element.firstElementChild;
211
+ $lib.removeClass(_instance.element, 'inside above before after');
212
+
213
+ if (display == _labelDisplayOption.AUTO)
214
+ {
215
+ var name = (field) ? field.nodeName.toLowerCase() : '';
216
+
217
+ if (!isFormElement(field) || (name == 'input' && ' checkbox radio text password email search url tel '.indexOf(' ' + field.type + ' ') == -1))
218
+ {
219
+ $lib.addClass(_instance.element, _labelDisplayOption.getName(_labelDisplayOption.ABOVE));
220
+ return;
221
+ }
222
+
223
+ if (name == 'input' && (field.type == 'checkbox' || field.type == 'radio'))
224
+ $lib.addClass(_instance.element, _labelDisplayOption.getName(_labelDisplayOption.AFTER));
225
+ else
226
+ setInsideDisplay(_labelDisplayOption.FLOATING);
227
+ }
228
+ else if (display <= _labelDisplayOption.INSIDE)
229
+ {
230
+ setInsideDisplay(display);
231
+ }
232
+ else
233
+ $lib.addClass(_instance.element, _labelDisplayOption.getName(display));
234
+ };
235
+
236
+
237
+ /**
238
+ * Adds the content template for the label.
239
+ * @param {HTMLElement|HTMLElement[]|DocumentFragment|String} content The label template content.
240
+ */
241
+ this.setLabelTemplate = function (content)
242
+ {
243
+ _instance.addTemplate('Label', content, false);
244
+ };
245
+
246
+ /**
247
+ * Adds the content template for the field.
248
+ * @param {HTMLElement|HTMLElement[]|DocumentFragment|String} content The field template content.
249
+ */
250
+ this.setFieldTemplate = function (content)
251
+ {
252
+ _instance.addTemplate('Field', content, false);
253
+ };
254
+
255
+ /**
256
+ * Updates the label.
257
+ * @param {HTMLElement|HTMLElement[]|DocumentFragment|String} content The label template content.
258
+ */
259
+ this.updateLabel = function (content)
260
+ {
261
+ let label = _instance.element.querySelector(':scope > label'),
262
+ b = _instance.element.querySelector(':scope > b');
263
+
264
+ if (!label)
265
+ return;
266
+
267
+ label.innerHTML = '';
268
+ _instance.addTemplate('Label', content, false);
269
+ _instance.applyTemplate(label, 'Label');
270
+
271
+ if (b)
272
+ {
273
+ b.setAttribute('title', label.textContent);
274
+ bindLabelEvent(b);
275
+ }
276
+
277
+ _instance.updateTooltip();
278
+ };
279
+
280
+ /**
281
+ * Links the label to the nested input by setting htmlFor and, if necessary, assigning an ID to the input.
282
+ * Adds a placeholder attribute if missing to support CSS styling.
283
+ */
284
+ this.linkLabelToInput = function ()
285
+ {
286
+ const guid = `${_instance.id}_${$lib.guid()}`,
287
+ label = _instance.element.querySelector(':scope > label'),
288
+ formEl = getFormElement();
289
+
290
+ if (label && formEl)
291
+ {
292
+ if (!formEl.id)
293
+ formEl.id = guid;
294
+
295
+ label.htmlFor = formEl.id;
296
+
297
+ if (!formEl.hasAttribute('placeholder'))
298
+ formEl.setAttribute('placeholder', ''); // placeholder is required for css :placeholder-shown to work
299
+
300
+ const observer = new MutationObserver(() =>
301
+ {
302
+ if (formEl.id)
303
+ {
304
+ label.htmlFor = formEl.id;
305
+ observer.disconnect(); // fire once, then done
306
+ }
307
+ });
308
+
309
+ observer.observe(formEl, { attributes: true, attributeFilter: ['id'] });
310
+ }
311
+ };
312
+
313
+ /**
314
+ * Recreates the tooltip icon for the element and updates its trigger in the tooltip manager.
315
+ */
316
+ this.updateTooltip = function ()
317
+ {
318
+ if (_instance.tooltipManagerId)
319
+ {
320
+ const tooltipManager = $UI.store[_instance.tooltipManagerId];
321
+
322
+ if (_tooltipIcon)
323
+ {
324
+ tooltipManager.removeTrigger(_tooltipIcon);
325
+ _tooltipIcon.remove();
326
+ }
327
+
328
+ if (_instance.tooltipId)
329
+ {
330
+ _tooltipIcon = $lib.element({ container: _instance.element.querySelector(':scope > label'), tag: 'i', attrs: { class: _instance.cssClassTooltipIcon || _classOption.TOOLTIP_ICON } });
331
+ tooltipManager.addTrigger(_tooltipIcon, _instance.tooltipId);
332
+ }
333
+ }
334
+ };
335
+
336
+ /**
337
+ * Disables the form field.
338
+ */
339
+ this.disable = function ()
340
+ {
341
+ _instance.element.inert = true;
342
+ _instance.disabled = true;
343
+ setCss(true, _classOption.DISABLED);
344
+ };
345
+
346
+ /**
347
+ * Enables the form field.
348
+ */
349
+ this.enable = function ()
350
+ {
351
+ _instance.element.inert = false;
352
+ _instance.disabled = false;
353
+ setCss(false, _classOption.DISABLED);
354
+ };
355
+
356
+ /**
357
+ * Renders the component
358
+ */
359
+ this.render = function ()
360
+ {
361
+ if (_instance.renderState != $base.static.RenderState.RENDERING)
362
+ {
363
+ // call base render and return
364
+ $base.methods.render.call(_instance, preRender, 'form-field');
365
+ return;
366
+ }
367
+
368
+ // render logic after loading resources
369
+ draw();
370
+ };
371
+
372
+ /**
373
+ * Handles the post render procedure.
374
+ */
375
+ this.postRender = function ()
376
+ {
377
+ if (_instance.renderState != $base.static.RenderState.RENDERING) // extra safety to never execute a postRender when the component state is incorrect
378
+ return;
379
+
380
+ _instance.updateTooltip();
381
+ $base.methods.postRender.call(_instance);
382
+ };
383
+
384
+ function preRender()
385
+ {
386
+ // initialize script and css
387
+ return ['FormField'];
388
+ }
389
+
390
+ function draw()
391
+ {
392
+ let label = document.createElement('label'),
393
+ element = _instance.element;
394
+
395
+ if (_instance.cssClassLabel)
396
+ $lib.addClass(label, _instance.cssClassLabel);
397
+
398
+ _instance.applyTemplate(element, 'Field');
399
+
400
+ if (_instance.hasTemplate('Label'))
401
+ _instance.applyTemplate(label, 'Label');
402
+ else if (_instance.label)
403
+ label.textContent = _instance.label;
404
+
405
+ let firstChild = element.firstElementChild,
406
+ isFormEl = isFormElement(firstChild);
407
+
408
+ if (isFormEl && isCheckOrRadio(firstChild))
409
+ {
410
+ let b = element.appendChild(document.createElement('b'));
411
+ b.setAttribute('title', label.textContent);
412
+ bindLabelEvent(b);
413
+ }
414
+
415
+ _instance.setInline(_instance.inline);
416
+ _instance.setRequired(_instance.required);
417
+ _instance.setBorderless(_instance.borderless);
418
+ _instance.setTransparent(_instance.transparent);
419
+ _instance.setSwitch(_instance.switch);
420
+ _instance.setLabelDisplay(_instance.labelDisplay);
421
+ _instance.element.inert = false; // make sure we remove a possible inert attribute from previous render
422
+
423
+ if (_instance.disabled)
424
+ _instance.disable();
425
+
426
+ if (_instance.wrapFieldContent || (!isFormEl && ($lib.hasClass(_instance.element, 'above') || $lib.hasClass(_instance.element, 'floating') || $lib.hasClass(_instance.element, 'inside')))) // put content inside flex column
427
+ {
428
+ let content = getFieldContent(),
429
+ wrapper = $lib.element({ container: _instance.element, attrs: { class: _instance.cssClassContentWrapper || _classOption.CONTENT_WRAPPER } } );
430
+
431
+ $lib.surround(wrapper, content);
432
+ }
433
+
434
+ element.appendChild(label);
435
+ _instance.linkLabelToInput();
436
+ _instance.postRender();
437
+ }
438
+
439
+ function getFieldContent()
440
+ {
441
+ var content = document.createDocumentFragment(),
442
+ element = _instance.element.firstChild, next;
443
+
444
+ while (element)
445
+ {
446
+ next = element.nextSibling;
447
+ content.appendChild(element);
448
+
449
+ element = next;
450
+ }
451
+
452
+ return content;
453
+ }
454
+
455
+ function bindLabelEvent(el)
456
+ {
457
+ if (!$lib.has(el, 'click', pretendLabelClick))
458
+ $lib.on(el, 'click', pretendLabelClick);
459
+ }
460
+
461
+ function pretendLabelClick(e)
462
+ {
463
+ var el = getFormElement();
464
+
465
+ if (!el)
466
+ return;
467
+
468
+ e.stopPropagation(); // input will bubble click event
469
+ el.focus();
470
+ (el.click) ? el.click() : $lib.fireEvent(el, 'click', true, true);
471
+ }
472
+
473
+ function isFormElement(el)
474
+ {
475
+ if (!el || !el.nodeName) return false;
476
+
477
+ const tag = el.nodeName.toLowerCase();
478
+
479
+ if (tag === 'input')
480
+ {
481
+ const type = (el.getAttribute('type') || '').toLowerCase();
482
+ return type !== 'hidden';
483
+ }
484
+
485
+ return tag === 'textarea' || tag === 'select';
486
+ }
487
+
488
+ function getFormElement()
489
+ {
490
+ const elements = Array.from(_instance.element.querySelectorAll(_formElements)),
491
+ cssClass = '.form-field';
492
+
493
+ return elements.find(el =>
494
+ {
495
+ let nearestFormField = el.closest(cssClass);
496
+
497
+ if (!nearestFormField) return false;
498
+
499
+ while (nearestFormField)
500
+ {
501
+ if (nearestFormField === _instance.element)
502
+ return true; // Input belongs to this component
503
+
504
+ if ($UI.elementStore.has(nearestFormField))
505
+ return false; // Input is inside a child form-field component, skip
506
+
507
+ nearestFormField = nearestFormField.parentElement?.closest(cssClass); // Not registered, move up to the next form-field ancestor
508
+ }
509
+ return false;
510
+ }) || null;
511
+ }
512
+
513
+ function isCheckOrRadio(el)
514
+ {
515
+ return (el.nodeName.toLowerCase() === 'input' && (el.type == 'checkbox' || el.type == 'radio'));
516
+ }
517
+ function setInsideDisplay(display)
518
+ {
519
+ let formEl = getFormElement(),
520
+ ph = 'placeholder';
521
+
522
+ if (!formEl)
523
+ return;
524
+
525
+ if (!formEl.hasAttribute(ph))
526
+ formEl.setAttribute(ph, ''); // placeholder is required for css :placeholder-shown to work
527
+
528
+ if (formEl.getAttribute(ph) === '' && (formEl.nodeName === 'TEXTAREA' || formEl.nodeName === 'INPUT'))
529
+ $lib.addClass(_instance.element, _labelDisplayOption.getName(display).replace('_', ' '));
530
+ else
531
+ $lib.addClass(_instance.element, _labelDisplayOption.getName(_labelDisplayOption.ABOVE));
532
+ }
533
+
534
+ function setCss(enable, css)
535
+ {
536
+ if (enable)
537
+ $lib.addClass(_instance.element, css);
538
+ else
539
+ $lib.removeClass(_instance.element, css);
540
+ }
541
+ };
542
+
543
+ /**
544
+ * @see {@link componyx.UI.base.methods}
545
+ */
546
+ componyx.UI.FormField.prototype = Object.create($base.methods);
547
+ componyx.UI.FormField.prototype.constructor = componyx.UI.FormField;
548
+
549
+ /**
550
+ * LabelDisplayOption
551
+ * @readonly
552
+ * @enum {number}
553
+ */
554
+ componyx.UI.FormField.LabelDisplayOption =
555
+ {
556
+ /** The label display depends on the field type: displayed after when the field is a checkbox or radiobutton,
557
+ displayed floating when the field is a basic textual input and displayed above for all other field types. */
558
+ AUTO: 0,
559
+ /** the label is displayed inside the field when empty and not focused otherwise it will be displayed above the field. */
560
+ FLOATING: 1,
561
+ /** the label is displayed inside the field and will be cleared when the input field gets focus, allowing placeholder to become visible. */
562
+ INSIDE: 2,
563
+ /** the label is displayed above the field. */
564
+ ABOVE: 3,
565
+ /** the label is displayed before the field. */
566
+ BEFORE: 4,
567
+ /** the label is displayed after the field. */
568
+ AFTER: 5,
569
+
570
+ getName: function (value) { return $base.static.getKeyByValue(this, value).toLowerCase(); }
571
+ };
572
+ })();
573
+
574
+ const FormField = componyx.UI.FormField;
575
+
576
+ export { FormField };
@@ -0,0 +1,99 @@
1
+ /*! Componyx.UI | (c) E.H. Daanen / Componyx | BUSL-1.1 | componyx.com/license */
2
+ .form-field.theme.theme-default input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not(:disabled):focus,
3
+ .form-field.theme.theme-default textarea:not(:disabled):focus,
4
+ .form-field.theme.theme-default select:not(:disabled):focus
5
+ {
6
+ box-shadow: inset 0px -2px 0px 0px var(--cui-button-selected-bg-color);
7
+ }
8
+
9
+ /* checkbox and radiobutton */
10
+ .form-field.theme.theme-default > input + b
11
+ {
12
+ background-color: var(--cui-button-bg-color);
13
+ }
14
+
15
+ .form-field.theme.theme-default > input[type="checkbox"]:disabled ~ b::before,
16
+ .form-field.theme.theme-default > input[type="radio"]:disabled ~ b::before,
17
+ .form-field.theme.theme-default.lucent > input[type="radio"] ~ b::before,
18
+ .form-field.theme.theme-default.lucent > input[type="checkbox"] ~ b::before
19
+ {
20
+ border-color: var(--cui-button-basic-text-color);
21
+ }
22
+
23
+ .form-field.theme.theme-default > input[type="radio"]:checked ~ b::before
24
+ {
25
+ background-color: var(--cui-button-text-color);
26
+ }
27
+
28
+ .form-field.theme.theme-default.lucent > input ~ b
29
+ {
30
+ background-color: var(--cui-color-surface);
31
+ }
32
+
33
+ .form-field.theme.theme-default:not(.lucent):hover:not(.switch) > input:not(:disabled) ~ b
34
+ {
35
+ background-color: var(--cui-button-hover-bg-color);
36
+ }
37
+
38
+ .form-field.theme.theme-default:not(.lucent):hover:not(.switch) > input:not(:disabled) ~ b::before
39
+ {
40
+ border-color: var(--cui-button-hover-text-color);
41
+ }
42
+
43
+ .form-field.theme.theme-default > input:focus:not(:disabled) ~ b
44
+ {
45
+ box-shadow: inset 0 -12px 0px -8px var(--cui-focus-box-shadow-color);
46
+ }
47
+
48
+ .form-field.theme.theme-default:not(.lucent) > input[type="checkbox"]:checked:not(:disabled) ~ b::before,
49
+ .form-field.theme.theme-default:not(.lucent) > input[type="radio"]:checked:not(:disabled) ~ b::before
50
+ {
51
+ border-color: var(--cui-button-text-color);
52
+ }
53
+
54
+ /* switch */
55
+ .form-field.theme.switch > input ~ b
56
+ {
57
+ background-color: var(--cui-button-basic-hover-bg-color);
58
+ }
59
+
60
+ .form-field.theme.theme-default.switch > input:checked ~ b
61
+ {
62
+ background-color: var(--cui-button-bg-color);
63
+ }
64
+
65
+ .form-field.theme.theme-default.switch > input:checked ~ b::before
66
+ {
67
+ color: var(--cui-button-bg-color);
68
+ }
69
+
70
+ .form-field.theme.theme-default.switch > input ~ b::before
71
+ {
72
+ background-color: var(--cui-knob-color);
73
+ }
74
+
75
+ /* readonly */
76
+ .form-field.theme.theme-default input[readonly],
77
+ .form-field.theme.theme-default textarea[readonly],
78
+ .form-field.theme.theme-default select[readonly],
79
+ .form-field.theme.theme-default .readonly
80
+ {
81
+ background-color: var(--cui-readonly-bg-color);
82
+ cursor: default;
83
+ }
84
+
85
+ /* disabled */
86
+ .form-field.theme.theme-default input:disabled,
87
+ .form-field.theme.theme-default textarea:disabled,
88
+ .form-field.theme.theme-default select:disabled,
89
+ .form-field.theme.theme-default > input:disabled ~ b,
90
+ .form-field.theme.theme-default.switch > input:disabled ~ b::before
91
+ {
92
+ background-color: var(--cui-disabled-bg-color);
93
+ color: var(--cui-disabled-text-color);
94
+ }
95
+
96
+ .form-field.theme.theme-default.required label::before
97
+ {
98
+ color: var(--cui-negative-text-color);
99
+ }