xmlui 0.10.15 → 0.10.18

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 (86) hide show
  1. package/dist/lib/{index-axjeT2uJ.mjs → index-Cy6Emsex.mjs} +3452 -1954
  2. package/dist/lib/index.css +1 -1
  3. package/dist/lib/{initMock-BoTWMs19.mjs → initMock-B-rmnC-t.mjs} +1 -1
  4. package/dist/lib/xmlui-parser.d.ts +1 -1
  5. package/dist/lib/xmlui.d.ts +4 -6
  6. package/dist/lib/xmlui.mjs +1 -1
  7. package/dist/metadata/{collectedComponentMetadata-CQywuPDB.mjs → collectedComponentMetadata-CB63ngkU.mjs} +3845 -2357
  8. package/dist/metadata/{initMock-Bi5kF5Af.mjs → initMock-D0wDKF_I.mjs} +1 -1
  9. package/dist/metadata/style.css +1 -1
  10. package/dist/metadata/xmlui-metadata.mjs +1 -1
  11. package/dist/metadata/xmlui-metadata.umd.js +3 -3
  12. package/dist/scripts/package.json +1 -1
  13. package/dist/scripts/src/components/Accordion/Accordion.spec.js +1 -1
  14. package/dist/scripts/src/components/Accordion/AccordionItemNative.js +1 -1
  15. package/dist/scripts/src/components/Animation/AnimationNative.js +5 -1
  16. package/dist/scripts/src/components/AutoComplete/AutoComplete.js +1 -5
  17. package/dist/scripts/src/components/AutoComplete/AutoComplete.spec.js +29 -0
  18. package/dist/scripts/src/components/AutoComplete/AutoCompleteContext.js +2 -0
  19. package/dist/scripts/src/components/AutoComplete/AutoCompleteNative.js +262 -62
  20. package/dist/scripts/src/components/Checkbox/Checkbox.js +1 -5
  21. package/dist/scripts/src/components/ColorPicker/ColorPicker.js +2 -6
  22. package/dist/scripts/src/components/ColorPicker/ColorPicker.spec.js +29 -0
  23. package/dist/scripts/src/components/ColorPicker/ColorPickerNative.js +12 -9
  24. package/dist/scripts/src/components/ComponentProvider.js +2 -0
  25. package/dist/scripts/src/components/DateInput/DateInput.js +1 -5
  26. package/dist/scripts/src/components/DateInput/DateInput.spec.js +29 -0
  27. package/dist/scripts/src/components/DateInput/DateInputNative.js +12 -16
  28. package/dist/scripts/src/components/DatePicker/DatePicker.js +1 -5
  29. package/dist/scripts/src/components/DatePicker/DatePicker.spec.js +29 -0
  30. package/dist/scripts/src/components/DatePicker/DatePickerNative.js +12 -13
  31. package/dist/scripts/src/components/FileInput/FileInput.js +1 -5
  32. package/dist/scripts/src/components/FileInput/FileInput.spec.js +29 -0
  33. package/dist/scripts/src/components/FileInput/FileInputNative.js +14 -15
  34. package/dist/scripts/src/components/Form/Form.spec.js +11 -9
  35. package/dist/scripts/src/components/Form/FormNative.js +41 -27
  36. package/dist/scripts/src/components/FormItem/FormItem.spec.js +179 -30
  37. package/dist/scripts/src/components/FormItem/FormItemNative.js +20 -22
  38. package/dist/scripts/src/components/FormItem/ItemWithLabel.js +8 -17
  39. package/dist/scripts/src/components/FormItem/Validations.js +25 -6
  40. package/dist/scripts/src/components/Icon/IconNative.js +18 -15
  41. package/dist/scripts/src/components/Input/PartialInput.js +2 -2
  42. package/dist/scripts/src/components/NestedApp/AppWithCodeViewNative.js +1 -1
  43. package/dist/scripts/src/components/NumberBox/NumberBox.js +5 -9
  44. package/dist/scripts/src/components/NumberBox/NumberBox.spec.js +142 -430
  45. package/dist/scripts/src/components/NumberBox/NumberBoxNative.js +33 -21
  46. package/dist/scripts/src/components/Option/Option.js +3 -1
  47. package/dist/scripts/src/components/RadioGroup/RadioGroup.js +1 -5
  48. package/dist/scripts/src/components/RadioGroup/RadioGroupNative.js +4 -5
  49. package/dist/scripts/src/components/RadioGroup/RadioItem.js +28 -0
  50. package/dist/scripts/src/components/Select/HiddenOption.js +1 -1
  51. package/dist/scripts/src/components/Select/Select.js +1 -5
  52. package/dist/scripts/src/components/Select/Select.spec.js +31 -3
  53. package/dist/scripts/src/components/Select/SelectNative.js +26 -32
  54. package/dist/scripts/src/components/Slider/Slider.js +1 -5
  55. package/dist/scripts/src/components/Slider/Slider.spec.js +75 -13
  56. package/dist/scripts/src/components/Slider/SliderNative.js +33 -24
  57. package/dist/scripts/src/components/Switch/Switch.js +1 -5
  58. package/dist/scripts/src/components/TextArea/TextArea.js +1 -5
  59. package/dist/scripts/src/components/TextArea/TextArea.spec.js +29 -0
  60. package/dist/scripts/src/components/TextArea/TextAreaNative.js +8 -29
  61. package/dist/scripts/src/components/TextBox/TextBox.spec.js +38 -7
  62. package/dist/scripts/src/components/TextBox/TextBoxNative.js +2 -2
  63. package/dist/scripts/src/components/TimeInput/TimeInput.spec.js +31 -0
  64. package/dist/scripts/src/components/Timer/Timer.spec.js +66 -96
  65. package/dist/scripts/src/components/Toggle/Toggle.js +28 -25
  66. package/dist/scripts/src/components/Tree/Tree-dynamic.spec.js +2894 -0
  67. package/dist/scripts/src/components/Tree/Tree-icons.spec.js +206 -0
  68. package/dist/scripts/src/components/Tree/Tree.spec.js +2839 -0
  69. package/dist/scripts/src/components/Tree/TreeComponent.js +303 -10
  70. package/dist/scripts/src/components/Tree/TreeNative.js +1090 -23
  71. package/dist/scripts/src/components/Tree/testData.js +296 -0
  72. package/dist/scripts/src/components-core/behaviors/Behavior.js +2 -0
  73. package/dist/scripts/src/components-core/behaviors/CoreBehaviors.js +8 -4
  74. package/dist/scripts/src/components-core/rendering/AppRoot.js +1 -2
  75. package/dist/scripts/src/components-core/rendering/ComponentAdapter.js +13 -15
  76. package/dist/scripts/src/components-core/utils/treeUtils.js +190 -12
  77. package/dist/scripts/src/testing/ComponentDrivers.js +79 -7
  78. package/dist/scripts/src/testing/drivers/NumberBoxDriver.js +2 -2
  79. package/dist/scripts/src/testing/drivers/TreeDriver.js +13 -0
  80. package/dist/scripts/src/testing/fixtures.js +7 -2
  81. package/dist/standalone/xmlui-standalone.es.d.ts +4 -6
  82. package/dist/standalone/xmlui-standalone.umd.js +36 -36
  83. package/package.json +1 -1
  84. package/dist/scripts/src/components/Animation/Animation.js +0 -50
  85. package/dist/scripts/src/components-core/behaviors/BehaviorContext.js +0 -54
  86. package/dist/scripts/src/testing/drivers/SliderDriver.js +0 -20
@@ -140,62 +140,66 @@ exports.FormItem = (0, react_1.memo)(function FormItem(_a) {
140
140
  };
141
141
  }, [formItemId, dispatch]);
142
142
  const { validationStatus, isHelperTextShown } = (0, Validations_1.useValidationDisplay)(formItemId, value, validationResult, validationMode);
143
+ const onFocus = (0, misc_1.useEvent)(() => {
144
+ dispatch((0, formActions_1.fieldFocused)(formItemId));
145
+ });
146
+ const onBlur = (0, misc_1.useEvent)(() => {
147
+ dispatch((0, formActions_1.fieldLostFocus)(formItemId));
148
+ });
143
149
  let formControl = null;
144
150
  switch (type) {
145
151
  case "select": {
146
- formControl = ((0, jsx_runtime_1.jsx)(SelectNative_1.Select, Object.assign({}, rest, { value: value, updateState: onStateChange, registerComponentApi: registerComponentApi, enabled: isEnabled, validationStatus: validationStatus, children: children })));
152
+ formControl = ((0, jsx_runtime_1.jsx)(SelectNative_1.Select, Object.assign({}, rest, { value: value, updateState: onStateChange, registerComponentApi: registerComponentApi, onFocus: onFocus, onBlur: onBlur, enabled: isEnabled, validationStatus: validationStatus, children: children })));
147
153
  break;
148
154
  }
149
155
  case "autocomplete": {
150
- formControl = ((0, jsx_runtime_1.jsx)(AutoCompleteNative_1.AutoComplete, Object.assign({}, rest, { value: value, updateState: onStateChange, registerComponentApi: registerComponentApi, enabled: isEnabled, validationStatus: validationStatus, children: children })));
156
+ formControl = ((0, jsx_runtime_1.jsx)(AutoCompleteNative_1.AutoComplete, Object.assign({}, rest, { value: value, updateState: onStateChange, registerComponentApi: registerComponentApi, onFocus: onFocus, onBlur: onBlur, enabled: isEnabled, validationStatus: validationStatus, children: children })));
151
157
  break;
152
158
  }
153
159
  case "datePicker": {
154
160
  formControl = ((0, jsx_runtime_1.jsx)(DatePickerNative_1.DatePicker, Object.assign({}, rest, { value: value, updateState: onStateChange,
155
- // registerComponentApi={registerComponentApi}
156
- enabled: isEnabled, validationStatus: validationStatus })));
161
+ //registerComponentApi={registerComponentApi}
162
+ onFocus: onFocus, onBlur: onBlur, enabled: isEnabled, validationStatus: validationStatus })));
157
163
  break;
158
164
  }
159
165
  case "radioGroup": {
160
166
  formControl = ((0, jsx_runtime_1.jsx)(RadioGroupNative_1.RadioGroup, Object.assign({}, rest, { value: value, updateState: onStateChange,
161
- // registerComponentApi={registerComponentApi}
162
- enabled: isEnabled, validationStatus: validationStatus, children: children })));
167
+ //registerComponentApi={registerComponentApi}
168
+ onFocus: onFocus, onBlur: onBlur, enabled: isEnabled, validationStatus: validationStatus, children: children })));
163
169
  break;
164
170
  }
165
171
  case "number":
166
172
  case "integer": {
167
- formControl = ((0, jsx_runtime_1.jsx)(NumberBoxNative_1.NumberBox, Object.assign({}, rest, { initialValue: initialValue, value: value, updateState: onStateChange, registerComponentApi: registerComponentApi, enabled: isEnabled, integersOnly: type === "integer", validationStatus: validationStatus, min: validations.minValue, max: validations.maxValue, maxLength: maxTextLength !== null && maxTextLength !== void 0 ? maxTextLength : validations === null || validations === void 0 ? void 0 : validations.maxLength, gap: gap })));
173
+ formControl = ((0, jsx_runtime_1.jsx)(NumberBoxNative_1.NumberBox, Object.assign({}, rest, { initialValue: initialValue, value: value, updateState: onStateChange, registerComponentApi: registerComponentApi, onFocus: onFocus, onBlur: onBlur, enabled: isEnabled, integersOnly: type === "integer", validationStatus: validationStatus, min: validations.minValue, max: validations.maxValue, maxLength: maxTextLength !== null && maxTextLength !== void 0 ? maxTextLength : validations === null || validations === void 0 ? void 0 : validations.maxLength, gap: gap })));
168
174
  break;
169
175
  }
170
176
  case "switch":
171
177
  case "checkbox": {
172
- formControl = ((0, jsx_runtime_1.jsx)(Toggle_1.Toggle, Object.assign({}, rest, { value: value, updateState: onStateChange,
173
- // registerComponentApi={registerComponentApi}
174
- enabled: isEnabled, validationStatus: validationStatus, variant: type, inputRenderer: inputRenderer })));
178
+ formControl = ((0, jsx_runtime_1.jsx)(Toggle_1.Toggle, Object.assign({}, rest, { value: value, updateState: onStateChange, registerComponentApi: registerComponentApi, onFocus: onFocus, onBlur: onBlur, enabled: isEnabled, validationStatus: validationStatus, variant: type, inputRenderer: inputRenderer })));
175
179
  break;
176
180
  }
177
181
  case "file": {
178
- formControl = ((0, jsx_runtime_1.jsx)(FileInputNative_1.FileInput, Object.assign({}, rest, { value: value, updateState: onStateChange, registerComponentApi: registerComponentApi, enabled: isEnabled, validationStatus: validationStatus, multiple: (0, valueExtractor_1.asOptionalBoolean)(rest.multiple, false) })));
182
+ formControl = ((0, jsx_runtime_1.jsx)(FileInputNative_1.FileInput, Object.assign({}, rest, { value: value, updateState: onStateChange, registerComponentApi: registerComponentApi, onFocus: onFocus, onBlur: onBlur, enabled: isEnabled, validationStatus: validationStatus, multiple: (0, valueExtractor_1.asOptionalBoolean)(rest.multiple, false) })));
179
183
  break;
180
184
  }
181
185
  case "text": {
182
- formControl = ((0, jsx_runtime_1.jsx)(TextBoxNative_1.TextBox, Object.assign({}, rest, { value: value, updateState: onStateChange, registerComponentApi: registerComponentApi, enabled: isEnabled, validationStatus: validationStatus, maxLength: maxTextLength !== null && maxTextLength !== void 0 ? maxTextLength : validations === null || validations === void 0 ? void 0 : validations.maxLength, gap: gap })));
186
+ formControl = ((0, jsx_runtime_1.jsx)(TextBoxNative_1.TextBox, Object.assign({}, rest, { value: value, updateState: onStateChange, registerComponentApi: registerComponentApi, onFocus: onFocus, onBlur: onBlur, enabled: isEnabled, validationStatus: validationStatus, maxLength: maxTextLength !== null && maxTextLength !== void 0 ? maxTextLength : validations === null || validations === void 0 ? void 0 : validations.maxLength, gap: gap })));
183
187
  break;
184
188
  }
185
189
  case "password": {
186
- formControl = ((0, jsx_runtime_1.jsx)(TextBoxNative_1.TextBox, Object.assign({}, rest, { type: "password", value: value, updateState: onStateChange, registerComponentApi: registerComponentApi, enabled: isEnabled, validationStatus: validationStatus, maxLength: maxTextLength !== null && maxTextLength !== void 0 ? maxTextLength : validations === null || validations === void 0 ? void 0 : validations.maxLength })));
190
+ formControl = ((0, jsx_runtime_1.jsx)(TextBoxNative_1.TextBox, Object.assign({}, rest, { type: "password", value: value, updateState: onStateChange, registerComponentApi: registerComponentApi, onFocus: onFocus, onBlur: onBlur, enabled: isEnabled, validationStatus: validationStatus, maxLength: maxTextLength !== null && maxTextLength !== void 0 ? maxTextLength : validations === null || validations === void 0 ? void 0 : validations.maxLength })));
187
191
  break;
188
192
  }
189
193
  case "textarea": {
190
- formControl = ((0, jsx_runtime_1.jsx)(TextAreaNative_1.TextArea, Object.assign({}, rest, { value: value, updateState: onStateChange, registerComponentApi: registerComponentApi, enabled: isEnabled, validationStatus: validationStatus, maxLength: maxTextLength !== null && maxTextLength !== void 0 ? maxTextLength : validations === null || validations === void 0 ? void 0 : validations.maxLength })));
194
+ formControl = ((0, jsx_runtime_1.jsx)(TextAreaNative_1.TextArea, Object.assign({}, rest, { value: value, updateState: onStateChange, registerComponentApi: registerComponentApi, onFocus: onFocus, onBlur: onBlur, enabled: isEnabled, validationStatus: validationStatus, maxLength: maxTextLength !== null && maxTextLength !== void 0 ? maxTextLength : validations === null || validations === void 0 ? void 0 : validations.maxLength })));
191
195
  break;
192
196
  }
193
197
  case "slider": {
194
- formControl = ((0, jsx_runtime_1.jsx)(SliderNative_1.Slider, Object.assign({}, rest, { value: value, updateState: onStateChange, registerComponentApi: registerComponentApi, enabled: isEnabled, validationStatus: validationStatus, min: validations.minValue, max: validations.maxValue })));
198
+ formControl = ((0, jsx_runtime_1.jsx)(SliderNative_1.Slider, Object.assign({}, rest, { value: value, updateState: onStateChange, registerComponentApi: registerComponentApi, onFocus: onFocus, onBlur: onBlur, enabled: isEnabled, validationStatus: validationStatus, min: validations.minValue, max: validations.maxValue })));
195
199
  break;
196
200
  }
197
201
  case "colorpicker": {
198
- formControl = ((0, jsx_runtime_1.jsx)(ColorPickerNative_1.ColorPicker, Object.assign({}, rest, { value: value, updateState: onStateChange, registerComponentApi: registerComponentApi, enabled: isEnabled, validationStatus: validationStatus })));
202
+ formControl = ((0, jsx_runtime_1.jsx)(ColorPickerNative_1.ColorPicker, Object.assign({}, rest, { value: value, updateState: onStateChange, registerComponentApi: registerComponentApi, onFocus: onFocus, onBlur: onBlur, enabled: isEnabled, validationStatus: validationStatus })));
199
203
  break;
200
204
  }
201
205
  case "items": {
@@ -212,12 +216,6 @@ exports.FormItem = (0, react_1.memo)(function FormItem(_a) {
212
216
  break;
213
217
  }
214
218
  }
215
- const onFocus = (0, misc_1.useEvent)(() => {
216
- dispatch((0, formActions_1.fieldFocused)(formItemId));
217
- });
218
- const onBlur = (0, misc_1.useEvent)(() => {
219
- dispatch((0, formActions_1.fieldLostFocus)(formItemId));
220
- });
221
219
  const [animateContainerRef] = (0, react_2.useAutoAnimate)({ duration: 100 });
222
220
  return ((0, jsx_runtime_1.jsx)(ItemWithLabel_1.ItemWithLabel, { labelPosition: labelPositionValue, label: label, labelWidth: labelWidthValue, labelBreak: labelBreakValue, enabled: isEnabled, required: validations.required, validationInProgress: validationResult === null || validationResult === void 0 ? void 0 : validationResult.partial, onFocus: onFocus, onBlur: onBlur, style: style, className: className, validationResult: (0, jsx_runtime_1.jsx)("div", { ref: animateContainerRef, children: isHelperTextShown &&
223
221
  (validationResult === null || validationResult === void 0 ? void 0 : validationResult.validations.map((singleValidation, i) => ((0, jsx_runtime_1.jsxs)(react_1.Fragment, { children: [singleValidation.isValid && !!singleValidation.validMessage && ((0, jsx_runtime_1.jsx)(HelperText_1.HelperText, { text: singleValidation.validMessage, status: "valid", style: { opacity: singleValidation.stale ? 0.5 : undefined } })), !singleValidation.isValid && !!singleValidation.invalidMessage && ((0, jsx_runtime_1.jsx)(HelperText_1.HelperText, { text: singleValidation.invalidMessage, status: singleValidation.severity, style: { opacity: singleValidation.stale ? 0.5 : undefined } }))] }, i)))) }), children: formControl }));
@@ -27,27 +27,13 @@ exports.defaultProps = {
27
27
  };
28
28
  const numberRegex = /^[0-9]+$/;
29
29
  exports.ItemWithLabel = (0, react_1.forwardRef)(function ItemWithLabel(_a, ref) {
30
- var { id, testId, labelPosition = "top", style = {}, className, label, labelBreak = exports.defaultProps.labelBreak, labelWidth, enabled = true, required = false, children, validationInProgress = false, shrinkToLabel = false, onFocus, onBlur, labelStyle, validationResult, isInputTemplateUsed = false, onLabelClick } = _a, rest = __rest(_a, ["id", "testId", "labelPosition", "style", "className", "label", "labelBreak", "labelWidth", "enabled", "required", "children", "validationInProgress", "shrinkToLabel", "onFocus", "onBlur", "labelStyle", "validationResult", "isInputTemplateUsed", "onLabelClick"]);
31
- // --- HACK: the "rest" may contain a "layoutContext" property that React doesn't recognize
32
- // --- as a valid DOM attribute, which would issue a warning in React.
33
- if (rest.layoutContext !== undefined) {
34
- delete rest.layoutContext;
35
- }
36
- // --- END HACK
30
+ var { id, labelPosition = "top", style = {}, className, label, labelBreak = exports.defaultProps.labelBreak, labelWidth, enabled = true, required = false, children, validationInProgress = false, shrinkToLabel = false, onFocus, onBlur, labelStyle, validationResult, isInputTemplateUsed = false, onLabelClick, layoutContext } = _a, rest = __rest(_a, ["id", "labelPosition", "style", "className", "label", "labelBreak", "labelWidth", "enabled", "required", "children", "validationInProgress", "shrinkToLabel", "onFocus", "onBlur", "labelStyle", "validationResult", "isInputTemplateUsed", "onLabelClick", "layoutContext"]);
37
31
  const generatedId = (0, react_1.useId)();
38
32
  const inputId = id || generatedId;
39
33
  if (label === undefined && !validationResult) {
40
34
  return ((0, jsx_runtime_1.jsx)(react_slot_1.Slot, Object.assign({}, rest, { "data-part-id": parts_1.PART_LABELED_ITEM, style: style, className: className, id: inputId, ref: ref, children: children })));
41
- // return cloneElement(children as ReactElement, {
42
- // ...mergeProps((children as ReactElement).props, {
43
- // style,
44
- // id: inputId,
45
- // onFocus: onFocus,
46
- // onBlur: onBlur
47
- // }),
48
- // });
49
35
  }
50
- return ((0, jsx_runtime_1.jsxs)("div", Object.assign({}, rest, { "data-testid": testId, ref: ref, style: style, className: (0, classnames_1.default)(className, FormItem_module_scss_1.default.itemWithLabel), children: [(0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(FormItem_module_scss_1.default.container, {
36
+ return ((0, jsx_runtime_1.jsxs)("div", Object.assign({}, rest, { ref: ref, style: style, className: (0, classnames_1.default)(className, FormItem_module_scss_1.default.itemWithLabel), children: [(0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(FormItem_module_scss_1.default.container, {
51
37
  [FormItem_module_scss_1.default.top]: labelPosition === "top",
52
38
  [FormItem_module_scss_1.default.bottom]: labelPosition === "bottom",
53
39
  [FormItem_module_scss_1.default.start]: labelPosition === "start",
@@ -57,5 +43,10 @@ exports.ItemWithLabel = (0, react_1.forwardRef)(function ItemWithLabel(_a, ref)
57
43
  [FormItem_module_scss_1.default.required]: required,
58
44
  [FormItem_module_scss_1.default.disabled]: !enabled,
59
45
  [FormItem_module_scss_1.default.labelBreak]: labelBreak,
60
- }), children: [label, " ", required && (0, jsx_runtime_1.jsx)("span", { className: FormItem_module_scss_1.default.requiredMark, children: "*" }), validationInProgress && ((0, jsx_runtime_1.jsx)(SpinnerNative_1.Spinner, { style: { height: "1em", width: "1em", marginLeft: "1em", alignSelf: "center" } }))] })), (0, jsx_runtime_1.jsx)(react_slot_1.Slot, { "data-part-id": parts_1.PART_LABELED_ITEM, id: !isInputTemplateUsed ? inputId : undefined, "data-testid": undefined, children: children })] }), validationResult] })));
46
+ }), children: [label, " ", required && (0, jsx_runtime_1.jsx)("span", { className: FormItem_module_scss_1.default.requiredMark, children: "*" }), validationInProgress && ((0, jsx_runtime_1.jsx)(SpinnerNative_1.Spinner, { style: { height: "1em", width: "1em", marginLeft: "1em", alignSelf: "center" } }))] })), (0, react_1.cloneElement)(children, {
47
+ id: !isInputTemplateUsed ? inputId : undefined,
48
+ style: undefined,
49
+ className: undefined,
50
+ "data-part-id": parts_1.PART_LABELED_ITEM,
51
+ })] }), validationResult] })));
61
52
  });
@@ -291,6 +291,7 @@ function useValidationDisplay(bindTo, value, validationResult, validationMode =
291
291
  const interactionFlags = (0, FormContext_1.useFormContextPart)((value) => value.interactionFlags[bindTo]) || constants_1.EMPTY_OBJECT;
292
292
  const forceShowValidationResult = interactionFlags.forceShowValidationResult;
293
293
  const focused = interactionFlags.focused;
294
+ const afterFirstDirtyBlur = interactionFlags.afterFirstDirtyBlur;
294
295
  const isValidLostFocus = interactionFlags.isValidLostFocus;
295
296
  const isValidOnFocus = interactionFlags.isValidOnFocus;
296
297
  const invalidToValid = interactionFlags.invalidToValid;
@@ -313,15 +314,33 @@ function useValidationDisplay(bindTo, value, validationResult, validationMode =
313
314
  }
314
315
  let isHelperTextShown = false;
315
316
  switch (validationMode) {
316
- case "errorLate":
317
- isHelperTextShown =
318
- isDirty && (focused ? !invalidToValid && !isValidOnFocus : !isValidLostFocus);
317
+ // This validation model was inspired by https://medium.com/wdstack/inline-validation-in-forms-designing-the-experience-123fb34088ce
318
+ // The idea is to show validation errors as late as possible (on blur)
319
+ case "errorLate": {
320
+ // --- Don't fire if not dirty
321
+ if (!isDirty) {
322
+ isHelperTextShown = false;
323
+ break;
324
+ }
325
+ // --- Show if losing focus and invalid
326
+ if (!focused && !isValidLostFocus) {
327
+ isHelperTextShown = true;
328
+ break;
329
+ }
330
+ // --- Show if focused, after first meaningful blur, was not valid on last focus and not changed to valid while typing
331
+ if (focused && afterFirstDirtyBlur && !isValidOnFocus && !invalidToValid) {
332
+ isHelperTextShown = true;
333
+ break;
334
+ }
319
335
  break;
320
- case "onChanged":
336
+ }
337
+ case "onChanged": {
321
338
  isHelperTextShown = isDirty;
322
339
  break;
323
- case "onLostFocus":
324
- isHelperTextShown = isDirty && ((!focused && !isValid) || (!isValidLostFocus && !isValid));
340
+ }
341
+ case "onLostFocus": {
342
+ isHelperTextShown = isDirty && !focused && !isValidLostFocus;
343
+ }
325
344
  }
326
345
  isHelperTextShown = isHelperTextShown || forceShowValidationResult;
327
346
  const [prevStableShown, setPrevStableShown] = (0, react_1.useState)(isHelperTextShown);
@@ -26,10 +26,10 @@ const StyleParser_1 = require("../../parsers/style-parser/StyleParser");
26
26
  exports.Icon = (0, react_1.forwardRef)(function Icon(_a, ref) {
27
27
  var _b;
28
28
  var { name, fallback, style, className, size, onClick, tabIndex, onKeyDown } = _a, restProps = __rest(_a, ["name", "fallback", "style", "className", "size", "onClick", "tabIndex", "onKeyDown"]);
29
- const iconRenderer = useFindIconRenderer(name, fallback);
29
+ const { iconRenderer, iconName } = useFindIconRenderer(name, fallback);
30
30
  // Handle keyboard events for clickable icons
31
31
  const handleKeyDown = (event) => {
32
- if (onClick && (event.key === 'Enter' || event.key === ' ')) {
32
+ if (onClick && (event.key === "Enter" || event.key === " ")) {
33
33
  event.preventDefault();
34
34
  onClick(event);
35
35
  }
@@ -40,7 +40,7 @@ exports.Icon = (0, react_1.forwardRef)(function Icon(_a, ref) {
40
40
  const height = computedSize || restProps.height;
41
41
  const computedProps = Object.assign(Object.assign({
42
42
  // className is needed to apply a default color to the icon, thus other component classes can override this one
43
- className: (0, classnames_1.default)(Icon_module_scss_1.default.base, className, { [Icon_module_scss_1.default.clickable]: !!onClick }) }, restProps), { size: computedSize, width: width, height: height, style: Object.assign(Object.assign({}, style), { "--icon-width": width, "--icon-height": height }), onClick, onKeyDown: handleKeyDown, tabIndex: onClick ? (tabIndex !== null && tabIndex !== void 0 ? tabIndex : 0) : tabIndex });
43
+ className: (0, classnames_1.default)(Icon_module_scss_1.default.base, className, { [Icon_module_scss_1.default.clickable]: !!onClick }) }, restProps), { size: computedSize, width: width, height: height, style: Object.assign(Object.assign({}, style), { "--icon-width": width, "--icon-height": height }), "data-icon-name": iconName, onClick, onKeyDown: handleKeyDown, tabIndex: onClick ? (tabIndex !== null && tabIndex !== void 0 ? tabIndex : 0) : tabIndex });
44
44
  // ---
45
45
  const customIconUrl = useCustomIconUrl(name);
46
46
  if (customIconUrl) {
@@ -50,14 +50,14 @@ exports.Icon = (0, react_1.forwardRef)(function Icon(_a, ref) {
50
50
  if (!renderedIcon) {
51
51
  return null;
52
52
  }
53
- return (0, jsx_runtime_1.jsx)("span", { ref: ref, style: { display: "inline-block" }, children: renderedIcon });
53
+ return ((0, jsx_runtime_1.jsx)("span", { ref: ref, style: { display: "inline-block" }, children: renderedIcon }));
54
54
  });
55
55
  const CustomIcon = (0, react_1.forwardRef)(function CustomIcon(props, ref) {
56
56
  var _a;
57
57
  const { url, width, height, name, style, className, onClick, onKeyDown, tabIndex } = props, rest = __rest(props, ["url", "width", "height", "name", "style", "className", "onClick", "onKeyDown", "tabIndex"]);
58
58
  // Handle keyboard events for clickable icons
59
59
  const handleKeyDown = (event) => {
60
- if (onClick && (event.key === 'Enter' || event.key === ' ')) {
60
+ if (onClick && (event.key === "Enter" || event.key === " ")) {
61
61
  event.preventDefault();
62
62
  onClick(event);
63
63
  }
@@ -69,14 +69,14 @@ const CustomIcon = (0, react_1.forwardRef)(function CustomIcon(props, ref) {
69
69
  if (resourceUrl && isSvgIcon) {
70
70
  const renderedIcon = customSvgIconRenderer === null || customSvgIconRenderer === void 0 ? void 0 : customSvgIconRenderer(Object.assign({ style,
71
71
  className,
72
- onClick, onKeyDown: handleKeyDown, tabIndex: onClick ? (tabIndex !== null && tabIndex !== void 0 ? tabIndex : 0) : tabIndex }, rest));
72
+ onClick, onKeyDown: handleKeyDown, tabIndex: onClick ? (tabIndex !== null && tabIndex !== void 0 ? tabIndex : 0) : tabIndex, "data-icon-name": name }, rest));
73
73
  if (!renderedIcon) {
74
74
  //to prevent layout shift
75
- return ((0, jsx_runtime_1.jsx)("span", Object.assign({}, rest, { ref: ref, style: style, className: className, onClick: onClick, onKeyDown: handleKeyDown, tabIndex: onClick ? (tabIndex !== null && tabIndex !== void 0 ? tabIndex : 0) : tabIndex })));
75
+ return ((0, jsx_runtime_1.jsx)("span", Object.assign({}, rest, { "data-icon-name": name, ref: ref, style: style, className: className, onClick: onClick, onKeyDown: handleKeyDown, tabIndex: onClick ? (tabIndex !== null && tabIndex !== void 0 ? tabIndex : 0) : tabIndex })));
76
76
  }
77
77
  return renderedIcon;
78
78
  }
79
- return ((0, jsx_runtime_1.jsx)("img", Object.assign({ ref: ref, src: resourceUrl, style: Object.assign({ width, height }, style), alt: name, onClick: onClick, onKeyDown: handleKeyDown, tabIndex: onClick ? (tabIndex !== null && tabIndex !== void 0 ? tabIndex : 0) : tabIndex }, rest)));
79
+ return ((0, jsx_runtime_1.jsx)("img", Object.assign({ ref: ref, src: resourceUrl, "data-icon-name": name, style: Object.assign({ width, height }, style), alt: name, onClick: onClick, onKeyDown: handleKeyDown, tabIndex: onClick ? (tabIndex !== null && tabIndex !== void 0 ? tabIndex : 0) : tabIndex }, rest)));
80
80
  });
81
81
  function useCustomIconUrl(iconName) {
82
82
  const { getResourceUrl } = (0, ThemeContext_1.useTheme)();
@@ -104,21 +104,24 @@ function useFindIconRenderer(name, fallback) {
104
104
  // Component specific icon
105
105
  if (parts.length > 1) {
106
106
  const iconRenderer = iconRegistry.lookupIconRenderer(`${parts[0].toLowerCase()}${separator}${parts[1]}`);
107
- if (iconRenderer)
108
- return iconRenderer;
107
+ if (iconRenderer) {
108
+ return { iconRenderer, iconName: name };
109
+ }
109
110
  }
110
111
  // General icon
111
112
  if (parts.length === 1) {
112
113
  const iconRenderer = iconRegistry.lookupIconRenderer(parts[0]);
113
- if (iconRenderer)
114
- return iconRenderer;
114
+ if (iconRenderer) {
115
+ return { iconRenderer, iconName: name };
116
+ }
115
117
  }
116
118
  }
117
119
  if (fallback && typeof fallback === "string") {
118
120
  const iconRenderer = iconRegistry.lookupIconRenderer(fallback.toLowerCase());
119
- if (iconRenderer)
120
- return iconRenderer;
121
+ if (iconRenderer) {
122
+ return { iconRenderer, iconName: fallback };
123
+ }
121
124
  }
122
- return null;
125
+ return { iconRenderer: null, iconName: null };
123
126
  }
124
127
  exports.default = exports.Icon;
@@ -36,7 +36,7 @@ const PartialInput_module_scss_1 = __importDefault(require("./PartialInput.modul
36
36
  * @returns A configured input element with enhanced multi-field input behavior
37
37
  */
38
38
  function PartialInput(_a) {
39
- var { value, placeholder, onChange, onBlur, onKeyDown, emptyCharacter, placeholderLength = 2, max, min, maxLength = 2, validateFn, onBeep, nextInputRef, nextButtonRef, name, ariaLabel, className, invalidClassName, disabled, readOnly, required, autoFocus, inputRef, step = 1, isInvalid = false } = _a, restProps = __rest(_a, ["value", "placeholder", "onChange", "onBlur", "onKeyDown", "emptyCharacter", "placeholderLength", "max", "min", "maxLength", "validateFn", "onBeep", "nextInputRef", "nextButtonRef", "name", "ariaLabel", "className", "invalidClassName", "disabled", "readOnly", "required", "autoFocus", "inputRef", "step", "isInvalid"]);
39
+ var { value, placeholder, onChange, onBlur, onKeyDown, emptyCharacter, placeholderLength = 2, max, min, maxLength = 2, validateFn, onBeep, nextInputRef, nextButtonRef, id, name, ariaLabel, className, invalidClassName, disabled, readOnly, required, autoFocus, inputRef, step = 1, isInvalid = false } = _a, restProps = __rest(_a, ["value", "placeholder", "onChange", "onBlur", "onKeyDown", "emptyCharacter", "placeholderLength", "max", "min", "maxLength", "validateFn", "onBeep", "nextInputRef", "nextButtonRef", "id", "name", "ariaLabel", "className", "invalidClassName", "disabled", "readOnly", "required", "autoFocus", "inputRef", "step", "isInvalid"]);
40
40
  /**
41
41
  * Process emptyCharacter according to requirements.
42
42
  * Handles null/empty values, multi-character strings, and unicode characters.
@@ -147,7 +147,7 @@ function PartialInput(_a) {
147
147
  // Call the original onKeyDown handler for other keys
148
148
  onKeyDown === null || onKeyDown === void 0 ? void 0 : onKeyDown(event);
149
149
  }, [onKeyDown]);
150
- return ((0, jsx_runtime_1.jsx)("input", Object.assign({}, restProps, { "aria-label": ariaLabel, autoComplete: "off",
150
+ return ((0, jsx_runtime_1.jsx)("input", Object.assign({}, restProps, { id: id, "aria-label": ariaLabel, autoComplete: "off",
151
151
  // biome-ignore lint/a11y/noAutofocus: This is up to developers' decision
152
152
  autoFocus: autoFocus, className: (0, classnames_1.default)(PartialInput_module_scss_1.default.partialInput, className, {
153
153
  [invalidClassName]: isInvalid,
@@ -36,7 +36,7 @@ function AppWithCodeViewNative({ markdown, splitView, withFrame = true, noHeader
36
36
  const appContext = (0, AppContext_1.useAppContext)();
37
37
  const [refreshVersion, setRefreshVersion] = (0, react_1.useState)(0);
38
38
  const { activeTheme: currentTheme, activeThemeTone, activeThemeId } = (0, ThemeContext_1.useTheme)();
39
- const safePopOutUrl = (0, utils_1.withoutTrailingSlash)(popOutUrl || ((_a = appContext === null || appContext === void 0 ? void 0 : appContext.appGlobals) === null || _a === void 0 ? void 0 : _a.popOutUrl) || "https://docs.xmlui.org/#/playground");
39
+ const safePopOutUrl = (0, utils_1.withoutTrailingSlash)(popOutUrl || ((_a = appContext === null || appContext === void 0 ? void 0 : appContext.appGlobals) === null || _a === void 0 ? void 0 : _a.popOutUrl) || "https://playground.xmlui.org/#/playground");
40
40
  const openPlayground = (0, react_1.useCallback)(() => __awaiter(this, void 0, void 0, function* () {
41
41
  const data = {
42
42
  standalone: {
@@ -34,10 +34,6 @@ exports.NumberBoxMd = (0, metadata_helpers_1.createMetadata)({
34
34
  props: {
35
35
  placeholder: (0, metadata_helpers_1.dPlaceholder)(),
36
36
  initialValue: (0, metadata_helpers_1.dInitialValue)(),
37
- label: (0, metadata_helpers_1.dLabel)(),
38
- labelPosition: (0, metadata_helpers_1.dLabelPosition)("top"),
39
- labelWidth: (0, metadata_helpers_1.dLabelWidth)(COMP),
40
- labelBreak: (0, metadata_helpers_1.dLabelBreak)(COMP),
41
37
  maxLength: (0, metadata_helpers_1.dMaxLength)(),
42
38
  autoFocus: (0, metadata_helpers_1.dAutoFocus)(),
43
39
  required: (0, metadata_helpers_1.dRequired)(),
@@ -118,10 +114,10 @@ exports.NumberBoxMd = (0, metadata_helpers_1.createMetadata)({
118
114
  },
119
115
  });
120
116
  exports.numberBoxComponentRenderer = (0, renderers_1.createComponentRenderer)(COMP, exports.NumberBoxMd, ({ node, state, updateState, lookupEventHandler, extractValue, className, registerComponentApi, }) => {
121
- // --- Handle initial value as a number
122
- let extractedInitialValue = extractValue(node.props.initialValue);
123
- if (typeof extractedInitialValue === "string" && !isNaN(parseFloat(extractedInitialValue))) {
124
- extractedInitialValue = Number(extractedInitialValue);
117
+ let extractedInitialValue;
118
+ try {
119
+ extractedInitialValue = extractValue.asOptionalNumber(node.props.initialValue);
125
120
  }
126
- return ((0, jsx_runtime_1.jsx)(NumberBoxNative_1.NumberBox, { className: className, value: state === null || state === void 0 ? void 0 : state.value, initialValue: extractedInitialValue, step: extractValue(node.props.step), enabled: extractValue.asOptionalBoolean(node.props.enabled), placeholder: extractValue.asOptionalString(node.props.placeholder), validationStatus: extractValue(node.props.validationStatus), updateState: updateState, onDidChange: lookupEventHandler("didChange"), onFocus: lookupEventHandler("gotFocus"), onBlur: lookupEventHandler("lostFocus"), registerComponentApi: registerComponentApi, hasSpinBox: extractValue.asOptionalBoolean(node.props.hasSpinBox), integersOnly: extractValue.asOptionalBoolean(node.props.integersOnly), zeroOrPositive: extractValue.asOptionalBoolean(node.props.zeroOrPositive), min: extractValue.asOptionalNumber(node.props.minValue), max: extractValue.asOptionalNumber(node.props.maxValue), startText: extractValue.asOptionalString(node.props.startText), startIcon: extractValue.asOptionalString(node.props.startIcon), endText: extractValue.asOptionalString(node.props.endText), gap: extractValue.asOptionalString(node.props.gap), endIcon: extractValue.asOptionalString(node.props.endIcon), spinnerUpIcon: extractValue.asOptionalString(node.props.spinnerUpIcon), spinnerDownIcon: extractValue.asOptionalString(node.props.spinnerDownIcon), autoFocus: extractValue.asOptionalBoolean(node.props.autoFocus), readOnly: extractValue.asOptionalBoolean(node.props.readOnly), maxLength: extractValue(node.props.maxLength), label: extractValue(node.props.label), labelPosition: extractValue(node.props.labelPosition), labelWidth: extractValue(node.props.labelWidth), labelBreak: extractValue.asOptionalBoolean(node.props.labelBreak), required: extractValue.asOptionalBoolean(node.props.required) }));
121
+ catch (_a) { }
122
+ return ((0, jsx_runtime_1.jsx)(NumberBoxNative_1.NumberBox, { className: className, value: state === null || state === void 0 ? void 0 : state.value, initialValue: extractedInitialValue, step: extractValue(node.props.step), enabled: extractValue.asOptionalBoolean(node.props.enabled), placeholder: extractValue.asOptionalString(node.props.placeholder), validationStatus: extractValue(node.props.validationStatus), updateState: updateState, onDidChange: lookupEventHandler("didChange"), onFocus: lookupEventHandler("gotFocus"), onBlur: lookupEventHandler("lostFocus"), registerComponentApi: registerComponentApi, hasSpinBox: extractValue.asOptionalBoolean(node.props.hasSpinBox), integersOnly: extractValue.asOptionalBoolean(node.props.integersOnly), zeroOrPositive: extractValue.asOptionalBoolean(node.props.zeroOrPositive), min: extractValue.asOptionalNumber(node.props.minValue), max: extractValue.asOptionalNumber(node.props.maxValue), startText: extractValue.asOptionalString(node.props.startText), startIcon: extractValue.asOptionalString(node.props.startIcon), endText: extractValue.asOptionalString(node.props.endText), gap: extractValue.asOptionalString(node.props.gap), endIcon: extractValue.asOptionalString(node.props.endIcon), spinnerUpIcon: extractValue.asOptionalString(node.props.spinnerUpIcon), spinnerDownIcon: extractValue.asOptionalString(node.props.spinnerDownIcon), autoFocus: extractValue.asOptionalBoolean(node.props.autoFocus), readOnly: extractValue.asOptionalBoolean(node.props.readOnly), maxLength: extractValue(node.props.maxLength), required: extractValue.asOptionalBoolean(node.props.required), direction: extractValue(node.props.direction) }));
127
123
  });