@rivtn/noseur 1.0.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 (138) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +2 -0
  3. package/dist/esm/Template.d.ts +7 -0
  4. package/dist/esm/Template.js +13 -0
  5. package/dist/esm/compose/Composed.css +437 -0
  6. package/dist/esm/compose/exotic/ColorPicker.d.ts +41 -0
  7. package/dist/esm/compose/exotic/ColorPicker.js +85 -0
  8. package/dist/esm/compose/exotic/ColorSlider.d.ts +30 -0
  9. package/dist/esm/compose/exotic/ColorSlider.js +99 -0
  10. package/dist/esm/compose/form/ComposedPassword.d.ts +25 -0
  11. package/dist/esm/compose/form/ComposedPassword.js +103 -0
  12. package/dist/esm/compose/form/DateTimeInput.d.ts +28 -0
  13. package/dist/esm/compose/form/DateTimeInput.js +154 -0
  14. package/dist/esm/compose/form/DateTimePicker.d.ts +341 -0
  15. package/dist/esm/compose/form/DateTimePicker.js +1265 -0
  16. package/dist/esm/compose/form/FormControl.d.ts +33 -0
  17. package/dist/esm/compose/form/FormControl.js +163 -0
  18. package/dist/esm/compose/form/FormGroup.d.ts +14 -0
  19. package/dist/esm/compose/form/FormGroup.js +58 -0
  20. package/dist/esm/compose/overlay/Alert.d.ts +56 -0
  21. package/dist/esm/compose/overlay/Alert.js +267 -0
  22. package/dist/esm/constants/Alignment.d.ts +17 -0
  23. package/dist/esm/constants/Alignment.js +18 -0
  24. package/dist/esm/constants/Direction.d.ts +26 -0
  25. package/dist/esm/constants/Direction.js +22 -0
  26. package/dist/esm/constants/Orientation.d.ts +8 -0
  27. package/dist/esm/constants/Orientation.js +9 -0
  28. package/dist/esm/constants/Scheme.d.ts +39 -0
  29. package/dist/esm/constants/Scheme.js +43 -0
  30. package/dist/esm/constants/Transition.d.ts +81 -0
  31. package/dist/esm/constants/Transition.js +85 -0
  32. package/dist/esm/constants/Types.d.ts +74 -0
  33. package/dist/esm/constants/Types.js +14 -0
  34. package/dist/esm/core/ComponentBaseProps.d.ts +53 -0
  35. package/dist/esm/core/ComponentBaseProps.js +33 -0
  36. package/dist/esm/core/noseur.css +2390 -0
  37. package/dist/esm/data/Column.d.ts +235 -0
  38. package/dist/esm/data/Column.js +98 -0
  39. package/dist/esm/data/Data.css +213 -0
  40. package/dist/esm/data/Data.d.ts +98 -0
  41. package/dist/esm/data/Data.js +142 -0
  42. package/dist/esm/data/List.d.ts +14 -0
  43. package/dist/esm/data/List.js +117 -0
  44. package/dist/esm/data/Table.d.ts +22 -0
  45. package/dist/esm/data/Table.js +236 -0
  46. package/dist/esm/form/Button.d.ts +35 -0
  47. package/dist/esm/form/Button.js +131 -0
  48. package/dist/esm/form/Calendar.d.ts +20 -0
  49. package/dist/esm/form/Calendar.js +46 -0
  50. package/dist/esm/form/Checkbox.d.ts +20 -0
  51. package/dist/esm/form/Checkbox.js +155 -0
  52. package/dist/esm/form/ColorMap.d.ts +22 -0
  53. package/dist/esm/form/ColorMap.js +43 -0
  54. package/dist/esm/form/ColorPalette.d.ts +28 -0
  55. package/dist/esm/form/ColorPalette.js +87 -0
  56. package/dist/esm/form/Dropdown.d.ts +78 -0
  57. package/dist/esm/form/Dropdown.js +360 -0
  58. package/dist/esm/form/FileInput.d.ts +134 -0
  59. package/dist/esm/form/FileInput.js +523 -0
  60. package/dist/esm/form/Form.css +467 -0
  61. package/dist/esm/form/Input.d.ts +45 -0
  62. package/dist/esm/form/Input.js +186 -0
  63. package/dist/esm/form/RadioButton.d.ts +21 -0
  64. package/dist/esm/form/RadioButton.js +178 -0
  65. package/dist/esm/form/Slider.d.ts +21 -0
  66. package/dist/esm/form/Slider.js +163 -0
  67. package/dist/esm/hooks/useSearchParams.d.ts +15 -0
  68. package/dist/esm/hooks/useSearchParams.js +50 -0
  69. package/dist/esm/hooks/useSubscription.d.ts +9 -0
  70. package/dist/esm/hooks/useSubscription.js +26 -0
  71. package/dist/esm/index.d.ts +60 -0
  72. package/dist/esm/index.js +73 -0
  73. package/dist/esm/layout/GridView.d.ts +23 -0
  74. package/dist/esm/layout/GridView.js +34 -0
  75. package/dist/esm/layout/Layout.css +5 -0
  76. package/dist/esm/misc/Misc.css +164 -0
  77. package/dist/esm/misc/ProgressBar.d.ts +22 -0
  78. package/dist/esm/misc/ProgressBar.js +86 -0
  79. package/dist/esm/overlay/Dialog.d.ts +46 -0
  80. package/dist/esm/overlay/Dialog.js +290 -0
  81. package/dist/esm/overlay/Message.d.ts +35 -0
  82. package/dist/esm/overlay/Message.js +187 -0
  83. package/dist/esm/overlay/Overlay.css +382 -0
  84. package/dist/esm/overlay/Popover.d.ts +30 -0
  85. package/dist/esm/overlay/Popover.js +245 -0
  86. package/dist/esm/overlay/Portal.d.ts +11 -0
  87. package/dist/esm/overlay/Portal.js +29 -0
  88. package/dist/esm/overlay/Toast.d.ts +49 -0
  89. package/dist/esm/overlay/Toast.js +341 -0
  90. package/dist/esm/panel/Accordion.d.ts +26 -0
  91. package/dist/esm/panel/Accordion.js +127 -0
  92. package/dist/esm/panel/Panel.css +317 -0
  93. package/dist/esm/panel/Panel.d.ts +43 -0
  94. package/dist/esm/panel/Panel.js +125 -0
  95. package/dist/esm/panel/ScrollPanel.d.ts +27 -0
  96. package/dist/esm/panel/ScrollPanel.js +43 -0
  97. package/dist/esm/panel/TabPane.d.ts +82 -0
  98. package/dist/esm/panel/TabPane.js +237 -0
  99. package/dist/esm/presentation/Chart.d.ts +49 -0
  100. package/dist/esm/presentation/Chart.js +62 -0
  101. package/dist/esm/presentation/Paginator.d.ts +90 -0
  102. package/dist/esm/presentation/Paginator.js +331 -0
  103. package/dist/esm/presentation/Presentation.css +23 -0
  104. package/dist/esm/sensor/DragSensor.d.ts +50 -0
  105. package/dist/esm/sensor/DragSensor.js +156 -0
  106. package/dist/esm/sensor/ViewportSensor.d.ts +18 -0
  107. package/dist/esm/sensor/ViewportSensor.js +85 -0
  108. package/dist/esm/utils/BoolHelper.d.ts +13 -0
  109. package/dist/esm/utils/BoolHelper.js +105 -0
  110. package/dist/esm/utils/Classname.d.ts +9 -0
  111. package/dist/esm/utils/Classname.js +20 -0
  112. package/dist/esm/utils/ColorHelper.d.ts +127 -0
  113. package/dist/esm/utils/ColorHelper.js +198 -0
  114. package/dist/esm/utils/DOMUtils.d.ts +142 -0
  115. package/dist/esm/utils/DOMUtils.js +759 -0
  116. package/dist/esm/utils/DateHelper.d.ts +115 -0
  117. package/dist/esm/utils/DateHelper.js +338 -0
  118. package/dist/esm/utils/Debugger.d.ts +12 -0
  119. package/dist/esm/utils/Debugger.js +30 -0
  120. package/dist/esm/utils/FileHelper.d.ts +8 -0
  121. package/dist/esm/utils/FileHelper.js +65 -0
  122. package/dist/esm/utils/FunctionStackManager.d.ts +13 -0
  123. package/dist/esm/utils/FunctionStackManager.js +59 -0
  124. package/dist/esm/utils/InputHelper.d.ts +37 -0
  125. package/dist/esm/utils/InputHelper.js +70 -0
  126. package/dist/esm/utils/MicroBuilder.d.ts +24 -0
  127. package/dist/esm/utils/MicroBuilder.js +61 -0
  128. package/dist/esm/utils/ObjectHelper.d.ts +51 -0
  129. package/dist/esm/utils/ObjectHelper.js +334 -0
  130. package/dist/esm/utils/StringHelper.d.ts +10 -0
  131. package/dist/esm/utils/StringHelper.js +54 -0
  132. package/dist/esm/utils/Subscriber.d.ts +14 -0
  133. package/dist/esm/utils/Subscriber.js +27 -0
  134. package/dist/esm/utils/Timer.d.ts +32 -0
  135. package/dist/esm/utils/Timer.js +68 -0
  136. package/dist/esm/utils/TypeChecker.d.ts +12 -0
  137. package/dist/esm/utils/TypeChecker.js +38 -0
  138. package/package.json +63 -0
@@ -0,0 +1,360 @@
1
+ import "./Form.css";
2
+ import React from 'react';
3
+ import { Scheme } from "../constants/Scheme";
4
+ import { DOMHelper } from "../utils/DOMUtils";
5
+ import { Classname } from "../utils/Classname";
6
+ import { BoolHelper } from "../utils/BoolHelper";
7
+ import { TypeChecker } from "../utils/TypeChecker";
8
+ import { ObjectHelper } from "../utils/ObjectHelper";
9
+ import { Popover } from "../overlay/Popover";
10
+ import { Position } from "../constants/Alignment";
11
+ import { FunctionStackManager } from "../utils/FunctionStackManager";
12
+ import { FormControl } from "../compose/form/FormControl";
13
+ import { TextInput } from "./Input";
14
+ // TODO implements keyboard and mouse shortcuts
15
+ class DropdownComponent extends React.Component {
16
+ static defaultProps = {
17
+ disabled: false,
18
+ highlight: false,
19
+ popoverProps: {},
20
+ borderless: false,
21
+ textInputProps: {},
22
+ formControlProps: {},
23
+ responsiveWidth: true,
24
+ selectedOptionIndex: -1,
25
+ scheme: Scheme.SECONDARY,
26
+ iconPosition: Position.LEFT,
27
+ togglePosition: Position.RIGHT,
28
+ optionGroupChildrenKey: "items",
29
+ toggleIcons: {
30
+ hide: 'fa fa-angle-up',
31
+ show: 'fa fa-angle-down',
32
+ },
33
+ };
34
+ state = {
35
+ popoverVisible: false,
36
+ options: this.props.options,
37
+ selectedOptionIndex: this.props.selectedOptionIndexes || { primaryIndex: this.props.selectedOptionIndex, secondaryIndex: this.props.selectedOptionIndex },
38
+ };
39
+ optionTemplate;
40
+ compoundElement;
41
+ optionGroupTemplate;
42
+ internalPopoverElement;
43
+ internalTextInputElement;
44
+ internalManageRefCache;
45
+ functionStackManager = new FunctionStackManager();
46
+ constructor(props) {
47
+ super(props);
48
+ this.optionTemplate = this.props.optionTemplate ?? this.buildSingleOption;
49
+ this.optionGroupTemplate = this.props.optionGroupTemplate ?? this.buildSingleOption;
50
+ this.togglePopover = this.togglePopover.bind(this);
51
+ this.onDropdownShow = this.onDropdownShow.bind(this);
52
+ this.onDropdownHide = this.onDropdownHide.bind(this);
53
+ }
54
+ componentDidMount() {
55
+ this.internalManageRefCache = {
56
+ toggle: this.togglePopover,
57
+ changeOptions: (options) => {
58
+ this.setState({ options });
59
+ },
60
+ hideDropDown: (e) => { if (this.state.popoverVisible) {
61
+ this.togglePopover(e, true);
62
+ } },
63
+ showDropDown: (e) => { if (!this.state.popoverVisible) {
64
+ this.togglePopover(e, true);
65
+ } },
66
+ };
67
+ ObjectHelper.resolveManageRef(this, this.internalManageRefCache);
68
+ }
69
+ componentDidUpdate(prevProps, _) {
70
+ const optionsChanged = !BoolHelper.deepEqual(this.props, prevProps, ["options"]);
71
+ const selectedOptionIndexChanged = !BoolHelper.deepEqual(this.props, prevProps, ["selectedOptionIndex"]);
72
+ if (optionsChanged || selectedOptionIndexChanged) {
73
+ let options = this.state.options;
74
+ if (optionsChanged)
75
+ options = this.props.options;
76
+ const newState = { options };
77
+ if (selectedOptionIndexChanged) {
78
+ const selectedOptionIndex = this.props.selectedOptionIndexes
79
+ ?? { primaryIndex: this.props.selectedOptionIndex, secondaryIndex: this.props.selectedOptionIndex };
80
+ if (selectedOptionIndex.primaryIndex === -1) {
81
+ if (this.props.renderOptionAsPlaceholder)
82
+ this.internalTextInputElement.placeholder = this.props.placeholder;
83
+ else
84
+ this.internalTextInputElement.value = "";
85
+ }
86
+ else {
87
+ newState.selectedOptionIndex = selectedOptionIndex;
88
+ if (optionsChanged || this.props.forceUpdateIfSelectedIndexChanges) {
89
+ this.selectOption(null, newState.selectedOptionIndex, newState.options.find((_, i) => i === selectedOptionIndex.primaryIndex), true);
90
+ }
91
+ }
92
+ }
93
+ this.setState(newState);
94
+ }
95
+ }
96
+ componentWillUnmount() {
97
+ ObjectHelper.resolveManageRef(this, null);
98
+ }
99
+ togglePopover(e, ignoreEditable = true) {
100
+ e.stopPropagation();
101
+ if (!this.internalPopoverElement || (!ignoreEditable && this.props.editable && e.target === this.internalTextInputElement))
102
+ return;
103
+ this.internalPopoverElement.toggle(e, this.compoundElement);
104
+ }
105
+ onDropdownHide() {
106
+ this.setState({ popoverVisible: false });
107
+ if (this.props.onDropdownHide)
108
+ this.props.onDropdownHide();
109
+ }
110
+ onDropdownShow() {
111
+ this.setState({ popoverVisible: true });
112
+ if (this.props.onDropdownShow)
113
+ this.props.onDropdownShow();
114
+ }
115
+ selectOption(e, selectedOptionIndex, option, skipReport) {
116
+ if (!skipReport && selectedOptionIndex.primaryIndex === -1) {
117
+ if (this.props.onDeSelectOption)
118
+ this.props.onDeSelectOption(e);
119
+ }
120
+ ;
121
+ if (selectedOptionIndex.primaryIndex === -1 || (skipReport || !this.props.onSelectOption || this.props.onSelectOption(option, e) !== true)) {
122
+ if (!skipReport)
123
+ this.setState({ selectedOptionIndex: selectedOptionIndex });
124
+ const optionLabel = option ? this.resolveOptionLabel(option) : (this.props.renderOptionAsPlaceholder ? this.props.placeholder : "");
125
+ if (this.props.renderOptionAsPlaceholder) {
126
+ this.internalTextInputElement.placeholder = optionLabel;
127
+ }
128
+ else {
129
+ this.internalTextInputElement.value = optionLabel;
130
+ }
131
+ if (!this.props.fill && this.props.responsiveWidth) {
132
+ const sidePaddings = parseInt(DOMHelper.getElementStyle(this.internalTextInputElement).paddingLeft) + parseInt(DOMHelper.getElementStyle(this.internalTextInputElement).paddingRight);
133
+ this.internalTextInputElement.style.width = `${DOMHelper.getTextWidth(optionLabel, this.internalTextInputElement) + sidePaddings}px`;
134
+ }
135
+ }
136
+ if (skipReport)
137
+ return;
138
+ return this.togglePopover(e, false);
139
+ }
140
+ resolveOptionLabel(option) {
141
+ if (!option)
142
+ return;
143
+ const optionMap = this.props.optionMap;
144
+ if (!optionMap || !optionMap.label)
145
+ return option.label ? option.label : "";
146
+ if (optionMap.label.indexOf('{') < 0) {
147
+ return option[optionMap.label] || optionMap.label;
148
+ }
149
+ return ObjectHelper.expandStringTemplate(optionMap.label, option);
150
+ }
151
+ resolveOptionIcon(option) {
152
+ if (!option || this.props.noIcon)
153
+ return null;
154
+ const optionMap = this.props.optionMap;
155
+ let icon = option.icon;
156
+ if (optionMap && optionMap.icon) {
157
+ if (optionMap.icon.indexOf && optionMap.icon.indexOf('{') >= 0) {
158
+ icon = ObjectHelper.expandStringTemplate(optionMap.icon, option);
159
+ }
160
+ else {
161
+ icon = option[optionMap.icon];
162
+ }
163
+ }
164
+ return option ? (TypeChecker.isString(icon) ? React.createElement("img", { src: icon }) : icon) : null;
165
+ }
166
+ buildSingleOption(option) {
167
+ const icon = this.resolveOptionIcon(option);
168
+ const label = this.resolveOptionLabel(option);
169
+ return (React.createElement("span", { className: "noseur-dropdown-popover-li-item" },
170
+ icon,
171
+ label));
172
+ }
173
+ getSelectedOption() {
174
+ if (!this.state.options || this.state.selectedOptionIndex == null || this.state.selectedOptionIndex.primaryIndex == null ||
175
+ this.state.selectedOptionIndex.primaryIndex < 0 || this.state.selectedOptionIndex.primaryIndex >= Object.keys(this.state.options).length) {
176
+ return null;
177
+ }
178
+ const childrenKey = this.props.optionGroupChildrenKey;
179
+ const selectedOption = this.state.options[this.state.selectedOptionIndex.primaryIndex];
180
+ return (TypeChecker.isArray(selectedOption) && childrenKey in selectedOption)
181
+ ? selectedOption[childrenKey][this.state.selectedOptionIndex.secondaryIndex || 0]
182
+ : selectedOption;
183
+ }
184
+ buildListItem(option, isGroupTitle = false, groupIndex = null, index = -1, isSelected = false, className = "noseur-dropdown-popover-li-grp") {
185
+ if (isGroupTitle) {
186
+ return (React.createElement("li", { key: `${groupIndex || -2}-${index}`, "aria-label": option.label, role: "group", className: className, onClick: (_) => { } }, this.optionGroupTemplate(option)));
187
+ }
188
+ const optionElement = this.optionTemplate(option);
189
+ const refProps = {};
190
+ if (isSelected)
191
+ refProps.ref = (r) => r && this.functionStackManager.register("POPOVER_REFED", (popOverElement) => {
192
+ popOverElement.scrollTop = r.offsetTop - popOverElement.offsetTop;
193
+ });
194
+ return (React.createElement("li", { key: `${groupIndex || -1}-${index}`, "aria-label": option.label, role: "option", "aria-selected": isSelected, className: className, ref: (r) => r && isSelected && r.scrollIntoView(), ...refProps, onClick: (e) => {
195
+ if (this.props.disabled)
196
+ return;
197
+ this.selectOption(e, {
198
+ secondaryIndex: (groupIndex == null ? -1 : index),
199
+ primaryIndex: (groupIndex == null ? index : groupIndex),
200
+ }, option);
201
+ } }, optionElement));
202
+ }
203
+ renderOption(options, groupIndex = null, isSelectedGroup = false) {
204
+ const listItems = [];
205
+ const isGroupOptions = !!groupIndex;
206
+ const selectedOptionIndex = this.state.selectedOptionIndex;
207
+ options.forEach((option, index) => {
208
+ const trueSelectedIndex = isGroupOptions ? (isSelectedGroup ? selectedOptionIndex.secondaryIndex : -1) : selectedOptionIndex.primaryIndex;
209
+ const isSelected = index === trueSelectedIndex;
210
+ const isGroup = (this.props.optionGroupChildrenKey in option);
211
+ if (isGroup) {
212
+ listItems.push(this.buildListItem(option, true, index));
213
+ listItems.push(...this.renderOption(option[this.props.optionGroupChildrenKey], index, isSelected));
214
+ return;
215
+ }
216
+ const className = Classname.build((this.props.scheme && isSelected ? this.props.scheme : null), (this.props.scheme && !this.props.disabled ? `${this.props.scheme}-bg-hv` : null), {
217
+ 'default-style': !this.props.scheme,
218
+ 'noseur-disabled': option.not_selectable,
219
+ }, "noseur-dropdown-popover-li-item", this.props.optionsClassName, option.className);
220
+ listItems.push(this.buildListItem(option, false, groupIndex, index, isSelected, className));
221
+ });
222
+ return listItems;
223
+ }
224
+ buildSelectedOption(selectedOption) {
225
+ if (selectedOption && this.props.selectedOptionTemplate)
226
+ return this.props.selectedOptionTemplate(selectedOption);
227
+ let selectedOptionLabel = this.resolveOptionLabel(selectedOption);
228
+ if (this.props.translateSelectionLabel)
229
+ selectedOptionLabel = this.props.translateSelectionLabel(selectedOptionLabel, selectedOption);
230
+ let defaultValue = selectedOptionLabel;
231
+ const placeholder = (this.props.renderOptionAsPlaceholder && selectedOptionLabel ? selectedOptionLabel : this.props.placeholder);
232
+ if (defaultValue && this.props.renderOptionAsPlaceholder)
233
+ defaultValue = null;
234
+ if (!defaultValue)
235
+ defaultValue = this.props.textInputProps.defaultValue;
236
+ if (!defaultValue)
237
+ defaultValue = this.props.defaultInputValue;
238
+ const inputProps = {
239
+ placeholder,
240
+ defaultValue,
241
+ noStyle: true,
242
+ borderless: true,
243
+ id: this.props.id,
244
+ fill: this.props.fill,
245
+ scheme: this.props.scheme,
246
+ ...this.props.textInputProps,
247
+ disabled: this.props.disabled,
248
+ readOnly: !this.props.editable,
249
+ highlight: this.props.highlight,
250
+ onInputComplete: this.props.onInputComplete,
251
+ style: { ...(this.props.style ?? {}), ...(this.props.textInputProps?.style ?? {}) },
252
+ ref: (el) => {
253
+ if (!el)
254
+ return;
255
+ this.internalTextInputElement = el;
256
+ if (!this.props.fill && this.props.responsiveWidth) {
257
+ const sidePaddings = parseInt(DOMHelper.getElementStyle(el).paddingLeft) + parseInt(DOMHelper.getElementStyle(el).paddingRight);
258
+ el.style.width = `${DOMHelper.getTextWidth((defaultValue ? defaultValue : placeholder), el) + sidePaddings}px`;
259
+ }
260
+ if (!this.props.textInputRef)
261
+ return;
262
+ if (this.props.textInputRef instanceof Function)
263
+ this.props.textInputRef(el);
264
+ else
265
+ this.props.textInputRef.current = el;
266
+ },
267
+ className: Classname.build('noseur-dropdown-inputtext', {
268
+ 'noseur-cursor-pointer': !this.props.editable,
269
+ }, (this.props.textInputProps ?? {}).className, this.props.className),
270
+ };
271
+ if (!this.props.editable) {
272
+ inputProps.style.cursor = "pointer";
273
+ }
274
+ else if (this.props.onSearch) {
275
+ inputProps.onInput = (e) => {
276
+ if (this.props.onSearch) {
277
+ const options = this.props.onSearch(e, this.internalManageRefCache);
278
+ if (options === null)
279
+ return;
280
+ this.setState({ options });
281
+ }
282
+ };
283
+ }
284
+ return (React.createElement(TextInput, { ...inputProps, onClick: (e) => this.togglePopover(e, false) }));
285
+ }
286
+ renderPopover() {
287
+ let listItems;
288
+ const popoverProps = this.props.popoverProps ?? {};
289
+ popoverProps.matchTargetSize = !this.props.dontMatchTargetSize;
290
+ popoverProps.className = Classname.build("noseur-dropdown-popover", popoverProps.className);
291
+ if (this.state.options) {
292
+ if (!this.state.options.length && this.props.emptyTemplate)
293
+ listItems = this.props.emptyTemplate();
294
+ else
295
+ listItems = this.renderOption(this.state.options);
296
+ }
297
+ else {
298
+ listItems = this.props.loadingTemplate ? this.props.loadingTemplate() : (React.createElement("div", { className: "noseur-dropdown-popover-empty" },
299
+ React.createElement("i", { style: { fontSize: 30 }, className: "fa fa-spinner fa-spin" })));
300
+ }
301
+ const popoverHeader = (this.props.popoverHeaderTemplate) ? this.props.popoverHeaderTemplate() : null;
302
+ const popoverFooter = (this.props.popoverFooterTemplate) ? this.props.popoverFooterTemplate() : null;
303
+ const popoverItemsRef = (r) => {
304
+ r && this.functionStackManager.popSmoke("POPOVER_REFED", r);
305
+ };
306
+ return (React.createElement(Popover, { pointingArrowClassName: null, ...popoverProps, manageRef: (r) => this.internalPopoverElement = r, ref: this.props.popoverRef, onCloseFocusRef: this.props.textInputRef, onShow: this.onDropdownShow, onHide: this.onDropdownHide },
307
+ popoverHeader,
308
+ React.createElement("ul", { ref: popoverItemsRef, role: "listbox", className: "noseur-dropdown-popover-list" }, listItems),
309
+ popoverFooter));
310
+ }
311
+ renderToggleIcon() {
312
+ if (this.props.noToggleIcons)
313
+ return null;
314
+ const toggleIcon = this.props.toggleIcons[this.state.popoverVisible ? "hide" : "show"];
315
+ return TypeChecker.isString(toggleIcon)
316
+ ? React.createElement("i", { className: Classname.build(toggleIcon, (this.props.scheme ? `${this.props.scheme}-tx` : null)) })
317
+ : toggleIcon;
318
+ }
319
+ renderLeftContent(selectedOption, formControlProps) {
320
+ const icon = this.props.iconPosition === Position.LEFT && !this.props.noSelectionIcon ? this.resolveOptionIcon(selectedOption) : null;
321
+ const leftContent = this.props.selectedOptionTemplate ? null : icon ?? formControlProps.leftContent;
322
+ const toggleIcon = this.props.togglePosition === Position.LEFT ? this.renderToggleIcon() : null;
323
+ if (!toggleIcon && !leftContent)
324
+ return null;
325
+ return (React.createElement("div", { className: "noseur-dropdown-left-content" },
326
+ toggleIcon,
327
+ leftContent));
328
+ }
329
+ renderRightContent(selectedOption, optionIsSelected) {
330
+ let closeIconClassname;
331
+ if (this.props.clearable && optionIsSelected) {
332
+ closeIconClassname = (React.createElement("i", { className: Classname.build("fa fa-close", `${Scheme.DANGER}-tx-hv`), onClick: (e) => {
333
+ e.stopPropagation();
334
+ this.selectOption(e, { primaryIndex: -1, secondaryIndex: -1 });
335
+ if (this.internalTextInputElement && this.props.renderOptionAsPlaceholder)
336
+ this.internalTextInputElement.placeholder = this.props.placeholder;
337
+ } }));
338
+ }
339
+ const icon = this.props.iconPosition === Position.RIGHT && !this.props.noSelectionIcon ? this.resolveOptionIcon(selectedOption) : null;
340
+ const toggleIcon = this.props.togglePosition === Position.RIGHT ? this.renderToggleIcon() : null;
341
+ if (!closeIconClassname && !toggleIcon && !icon)
342
+ return null;
343
+ return (React.createElement("div", { className: "noseur-dropdown-right-content" },
344
+ closeIconClassname,
345
+ icon,
346
+ toggleIcon));
347
+ }
348
+ render() {
349
+ const popover = this.renderPopover();
350
+ const selectedOption = this.getSelectedOption();
351
+ const formControlProps = (this.props.formControlProps || {});
352
+ const selectedOptionElement = this.buildSelectedOption(selectedOption);
353
+ const className = Classname.build('noseur-dropdown', this.props.formControlProps?.className, { "noseur-disabled": this.props.disabled });
354
+ return (React.createElement(React.Fragment, null,
355
+ React.createElement(FormControl, { ...formControlProps, className: className, borderless: this.props.borderless, leftContent: this.renderLeftContent(selectedOption, formControlProps), rightContent: this.renderRightContent(selectedOption, !!selectedOption), contentStyle: { width: "initial", ...(formControlProps.style || {}) }, fill: this.props.fill, scheme: this.props.scheme || formControlProps.scheme, ref: (r) => this.compoundElement = r, onClick: this.togglePopover }, selectedOptionElement),
356
+ popover));
357
+ }
358
+ }
359
+ export const Dropdown = ({ ref, ...props }) => (React.createElement(DropdownComponent, { ...props, forwardRef: ref }));
360
+ // TODO adapt size of selected label to input width
@@ -0,0 +1,134 @@
1
+ import "./Form.css";
2
+ import React from 'react';
3
+ import { BareInputManageRef } from "./Input";
4
+ import { Alignment } from "../constants/Alignment";
5
+ import { Orientation } from "../constants/Orientation";
6
+ import { NoseurElement, NoseurObject } from "../constants/Types";
7
+ import { ButtonProps } from "./Button";
8
+ import { ComponentBaseProps, ComponentElementBasicAttributes } from "../core/ComponentBaseProps";
9
+ export declare enum FileInputMode {
10
+ BUTTON = 0,
11
+ PREVIEW = 1,
12
+ ELEMENT = 2,
13
+ CONTROLLED = 3
14
+ }
15
+ export declare enum FileInputPreviewType {
16
+ PDF = "PDF",
17
+ AUTO = "AUTO",
18
+ NONE = "NONE",
19
+ HTML = "HTML",
20
+ TEXT = "TEXT",
21
+ IMAGE = "IMAGE",
22
+ VIDEO = "VIDEO",
23
+ AUDIO = "AUDIO",
24
+ BINARY = "BINARY",
25
+ CUSTOM = "CUSTOM"
26
+ }
27
+ export interface FileInputFixtureOptions {
28
+ className: string;
29
+ props: FileInputProps;
30
+ clearControl: NoseurElement;
31
+ selectControl: NoseurElement;
32
+ actionControl: NoseurElement;
33
+ }
34
+ export interface FileInputItemOptions {
35
+ file: File;
36
+ url: string;
37
+ index: number;
38
+ className: string;
39
+ props: FileInputProps;
40
+ formattedSize: string;
41
+ previewElement: NoseurElement;
42
+ onRemove: FileInputFileEventHandler;
43
+ }
44
+ export interface DragAndDropRefOptions {
45
+ count: number;
46
+ interval: number;
47
+ }
48
+ export type FileInputDialogEventHandler = (event: any) => void;
49
+ export type FileInputValidationHandler = (file: File) => string;
50
+ export type FileInputSelectFileHandler = (files: File[]) => void;
51
+ export type FileInputDragEventHandler = (event: DragEvent) => boolean;
52
+ export type FileInputFileEventHandler = (file: File, event?: Event) => void;
53
+ export type FileInputValidationEventHandler = (file: File, error: string) => boolean;
54
+ export type FileInputItemTemplateHandler = (options: FileInputItemOptions) => NoseurElement;
55
+ export type FileInputFixtureTemplateHandler = (options: FileInputFixtureOptions) => NoseurElement;
56
+ export type FileInputMountHandler = (onSelect?: (e?: any) => void, onDrop?: React.DragEventHandler<any>, onDragOver?: React.DragEventHandler<any>) => void;
57
+ export type FileInputEmptyTemplateHandler = (onSelect?: (e?: any) => void, onDrop?: React.DragEventHandler<any>, onDragOver?: React.DragEventHandler<any>) => NoseurElement;
58
+ export type FileInputAttributesRelays = {
59
+ control?: {
60
+ alignment?: Alignment;
61
+ } & ComponentElementBasicAttributes;
62
+ previews?: {
63
+ className?: string;
64
+ style?: React.CSSProperties;
65
+ };
66
+ preview?: {
67
+ className?: string;
68
+ style?: React.CSSProperties;
69
+ };
70
+ };
71
+ export interface FileInputManageRef extends BareInputManageRef<File> {
72
+ files: () => File[];
73
+ resolve: () => void;
74
+ select: (e?: Event) => void;
75
+ changeFiles: (files: File[]) => void;
76
+ }
77
+ export interface FileInputProps extends ComponentBaseProps<HTMLInputElement, FileInputManageRef, FileInputAttributesRelays> {
78
+ accepts: string;
79
+ rounded: boolean;
80
+ multiple: boolean;
81
+ selectOnly: boolean;
82
+ maxFileSize: number;
83
+ mode: FileInputMode;
84
+ defaultFiles: File[];
85
+ control: NoseurElement;
86
+ noDragAndDrop: boolean;
87
+ clickToChange: boolean;
88
+ stickyPreview: boolean;
89
+ concatNewFile: boolean;
90
+ orientation: Orientation;
91
+ controlIsManaged: boolean;
92
+ previewType: FileInputPreviewType;
93
+ buttonProps: Partial<ButtonProps>;
94
+ relayToAttachFileInputOnly: boolean;
95
+ elementProps: Partial<NoseurObject<any>>;
96
+ clearControl: Partial<ButtonProps> | NoseurElement;
97
+ selectControl: Partial<ButtonProps> | NoseurElement;
98
+ actionControl: Partial<ButtonProps> | NoseurElement;
99
+ dragAndDropRefOptions: Partial<DragAndDropRefOptions>;
100
+ dragAndDropRefs: React.MutableRefObject<HTMLElement>[];
101
+ attachFileInputManageRef: React.RefObject<FileInputManageRef | null>;
102
+ onMount: FileInputMountHandler;
103
+ onUnMount: FileInputMountHandler;
104
+ onDrop: React.DragEventHandler<any>;
105
+ onAction: FileInputSelectFileHandler;
106
+ onDragOver: React.DragEventHandler<any>;
107
+ onRemoveFile: FileInputFileEventHandler;
108
+ onBeforeDrop: FileInputDragEventHandler;
109
+ onDragBegin: React.DragEventHandler<any>;
110
+ validateFile: FileInputValidationHandler;
111
+ onSelectFiles: FileInputSelectFileHandler;
112
+ itemTemplate: FileInputItemTemplateHandler;
113
+ onDragComplete: React.DragEventHandler<any>;
114
+ onCancelDialog: FileInputDialogEventHandler;
115
+ emptyTemplate: FileInputEmptyTemplateHandler;
116
+ onConfirmDialog: FileInputDialogEventHandler;
117
+ headerTemplate: FileInputFixtureTemplateHandler;
118
+ footerTemplate: FileInputFixtureTemplateHandler;
119
+ onValidationFail: FileInputValidationEventHandler;
120
+ }
121
+ export declare const FileInput: ({ ref, ...props }: Partial<FileInputProps>) => React.JSX.Element;
122
+ export interface FileInputPreviewOption {
123
+ file?: File;
124
+ alt?: string;
125
+ url?: string;
126
+ formattedSize?: string;
127
+ style?: React.CSSProperties;
128
+ ref?: React.ForwardedRef<any>;
129
+ previewType?: FileInputPreviewType;
130
+ onRemove?: FileInputFileEventHandler;
131
+ removeButton?: React.ReactElement<ButtonProps, string | React.JSXElementConstructor<ButtonProps>>;
132
+ }
133
+ export declare function fileInputBuildFileInputPreview(options: FileInputPreviewOption): React.JSX.Element;
134
+ export declare function fileInputFileFromUrl(url: string, name?: string, type?: string): File;