@stellar-expert/ui-framework 1.16.8 → 1.19.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.
- package/README.md +1168 -3
- package/account/account-address.js +127 -127
- package/account/available-balance.js +22 -22
- package/account/identicon.js +90 -90
- package/account/signer-key.js +65 -64
- package/api/explorer-api-hooks.js +209 -202
- package/api/explorer-api-paginated-list-hooks.js +441 -440
- package/api/explorer-batch-info-loader.js +111 -85
- package/api/explorer-tx-api.js +28 -28
- package/api/ledger-stream.js +15 -0
- package/asset/amount.js +56 -56
- package/asset/asset-icon.js +41 -41
- package/asset/asset-issuer.js +21 -21
- package/asset/asset-link.js +107 -107
- package/asset/asset-list-hooks.js +59 -59
- package/asset/asset-meta-hooks.js +88 -88
- package/asset/asset-selector.js +72 -71
- package/claimable-balance/claimable-balance-claimants.js +23 -18
- package/contract/contract-api.js +15 -0
- package/contract/invocation-info-view.js +10 -2
- package/contract/sc-val.js +131 -107
- package/controls/button-group.js +25 -19
- package/controls/button.js +93 -78
- package/controls/code-block.js +42 -34
- package/controls/dropdown.js +318 -287
- package/controls/external-link.js +10 -4
- package/controls/info-tooltip.js +23 -16
- package/controls/slider.js +29 -19
- package/controls/tabs.js +94 -94
- package/controls/tooltip.js +244 -240
- package/controls/update-highlighter.js +32 -27
- package/date/date-selector.js +56 -54
- package/date/elapsed-time.js +28 -21
- package/dex/price-dynamic.js +53 -44
- package/directory/directory-hooks.js +109 -97
- package/effect/effect-description.js +346 -344
- package/errors/error-boundary.js +110 -97
- package/filter/editors/account-filter-view.js +20 -0
- package/filter/editors/asset-filter-view.js +9 -0
- package/filter/editors/timestamp-filter-view.js +34 -0
- package/filter/editors/type-filter-view.js +148 -0
- package/filter/filter-editors.js +102 -0
- package/filter/filter-view.js +218 -0
- package/filter/filter.scss +57 -0
- package/horizon/horizon-account-helpers.js +104 -104
- package/horizon/horizon-ledger-helpers.js +35 -35
- package/horizon/horizon-trades-helper.js +88 -88
- package/horizon/horizon-transaction-helpers.js +36 -36
- package/index.d.ts +1271 -0
- package/index.js +95 -93
- package/interaction/accordion.js +43 -35
- package/interaction/autofocus.js +13 -9
- package/interaction/block-select.js +64 -53
- package/interaction/copy-to-clipboard.js +25 -18
- package/interaction/inline-progress.js +20 -15
- package/interaction/qr-code.js +34 -34
- package/interaction/responsive.js +20 -20
- package/interaction/spoiler.js +52 -39
- package/interaction/theme-selector.js +13 -10
- package/ledger/ledger-entry-href-formatter.js +27 -26
- package/ledger/ledger-entry-link.js +93 -58
- package/ledger/ledger-info-parser.js +46 -18
- package/meta/page-meta-tags.js +243 -238
- package/module/dynamic-module.js +47 -47
- package/package.json +71 -40
- package/state/on-screen-hooks.js +22 -22
- package/state/page-visibility-helpers.js +29 -16
- package/state/page-visibility-hooks.js +13 -11
- package/state/screen-orientation-hooks.js +19 -15
- package/state/state-hooks.js +76 -76
- package/state/stellar-network-hooks.js +56 -44
- package/state/theme.js +29 -28
- package/stellar/key-type.js +92 -91
- package/stellar/ledger-generic-id.js +39 -39
- package/stellar/signature-hint-utils.js +65 -65
- package/toast/toast-notifications-block.js +59 -59
- package/tx/op-description-view.js +945 -942
- package/tx/op-icon.js +98 -98
- package/tx/parser/op-balance-changes.js +66 -66
- package/tx/parser/op-descriptor.js +51 -48
- package/tx/parser/tx-details-parser.js +81 -81
- package/tx/parser/tx-matcher.js +371 -371
- package/tx/parser/type-filter-matcher.js +126 -126
- package/tx/tx-list-hooks.js +32 -18
- package/tx/tx-operations-list.js +117 -116
package/controls/dropdown.js
CHANGED
|
@@ -1,288 +1,319 @@
|
|
|
1
|
-
import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'
|
|
2
|
-
import {createPortal} from 'react-dom'
|
|
3
|
-
import PropTypes from 'prop-types'
|
|
4
|
-
import cn from 'classnames'
|
|
5
|
-
import {throttle} from 'throttle-debounce'
|
|
6
|
-
import {useDependantState} from '../state/state-hooks'
|
|
7
|
-
import './dropdown.scss'
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
return
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
if (
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
1
|
+
import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'
|
|
2
|
+
import {createPortal} from 'react-dom'
|
|
3
|
+
import PropTypes from 'prop-types'
|
|
4
|
+
import cn from 'classnames'
|
|
5
|
+
import {throttle} from 'throttle-debounce'
|
|
6
|
+
import {useDependantState} from '../state/state-hooks'
|
|
7
|
+
import './dropdown.scss'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @typedef {Object} DropdownOption
|
|
11
|
+
* @property {string|number} [value] - Internal value used for identification
|
|
12
|
+
* @property {string} [href] - Link URL for menu-style dropdown items
|
|
13
|
+
* @property {*} [title] - Display title (defaults to value)
|
|
14
|
+
* @property {string} [className] - Additional CSS class
|
|
15
|
+
* @property {boolean} [disabled] - Whether the option is disabled
|
|
16
|
+
* @property {boolean} [hidden] - Whether to hide the option
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Customizable dropdown select component
|
|
21
|
+
* @param {Object} props
|
|
22
|
+
* @param {Array<DropdownOption|string>} props.options - Available options
|
|
23
|
+
* @param {string|number} [props.value] - Currently selected value
|
|
24
|
+
* @param {*} [props.title] - Title to display instead of the selected value
|
|
25
|
+
* @param {boolean} [props.disabled=false] - Disable the dropdown
|
|
26
|
+
* @param {string} [props.className] - Additional CSS classes
|
|
27
|
+
* @param {function(string|number): void} [props.onChange] - Callback invoked with the selected value
|
|
28
|
+
* @param {string} [props.hint] - HTML title attribute for the control
|
|
29
|
+
* @param {boolean} [props.showToggle=true] - Show toggle arrow icon
|
|
30
|
+
* @param {boolean} [props.solo=false] - Show dropdown list in a centered dialog overlay
|
|
31
|
+
* @param {boolean} [props.hideSelected=false] - Hide currently selected item from the list
|
|
32
|
+
* @param {*} [props.header] - Optional list header content
|
|
33
|
+
* @param {*} [props.footer] - Optional list footer content
|
|
34
|
+
* @param {boolean} [props.expanded] - Initially open the dropdown
|
|
35
|
+
* @param {function({position: number, rel: 'top'|'middle'|'bottom'}): void} [props.onScroll] - Scroll handler for infinite scroll support
|
|
36
|
+
* @param {function} [props.onOpen] - Handler called when the dropdown opens
|
|
37
|
+
* @param {function} [props.onClose] - Handler called when the dropdown closes
|
|
38
|
+
* @param {string} [props.maxHeight='35em'] - Maximum dropdown list height
|
|
39
|
+
*/
|
|
40
|
+
export const Dropdown = React.memo(function Dropdown({
|
|
41
|
+
options,
|
|
42
|
+
title,
|
|
43
|
+
value,
|
|
44
|
+
disabled,
|
|
45
|
+
className,
|
|
46
|
+
onChange,
|
|
47
|
+
hint,
|
|
48
|
+
showToggle,
|
|
49
|
+
solo,
|
|
50
|
+
hideSelected,
|
|
51
|
+
header,
|
|
52
|
+
footer,
|
|
53
|
+
expanded,
|
|
54
|
+
onScroll,
|
|
55
|
+
onOpen,
|
|
56
|
+
onClose,
|
|
57
|
+
maxHeight
|
|
58
|
+
}) {
|
|
59
|
+
const headerRef = useRef()
|
|
60
|
+
const listRef = useRef()
|
|
61
|
+
const [listOpen, updateListOpen] = useState(false)
|
|
62
|
+
const [alignRight, setAlignRight] = useState(false)
|
|
63
|
+
//collapse dropdown handler
|
|
64
|
+
const collapseDropdown = useCallback(function () {
|
|
65
|
+
updateListOpen(open => {
|
|
66
|
+
if (!open)
|
|
67
|
+
return false
|
|
68
|
+
onClose?.call(this, this)
|
|
69
|
+
return false
|
|
70
|
+
})
|
|
71
|
+
}, [onClose])
|
|
72
|
+
|
|
73
|
+
//collapse dropdown list on click
|
|
74
|
+
const [selectedValue, updateSelectedValue] = useDependantState(() => {
|
|
75
|
+
if (listOpen) {
|
|
76
|
+
setTimeout(() => {
|
|
77
|
+
document.addEventListener('click', collapseDropdown)
|
|
78
|
+
}, 200)
|
|
79
|
+
}
|
|
80
|
+
return value
|
|
81
|
+
}, [value, listOpen], () => {
|
|
82
|
+
document.removeEventListener('click', collapseDropdown)
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
//close/open dropdown on header click
|
|
86
|
+
const toggleList = useCallback(function toggleList(e) {
|
|
87
|
+
e && e.nativeEvent.stopImmediatePropagation()
|
|
88
|
+
updateListOpen(prevState => {
|
|
89
|
+
if (disabled)
|
|
90
|
+
return false;
|
|
91
|
+
(prevState ? onClose : onOpen)?.call(this, this)
|
|
92
|
+
return !prevState
|
|
93
|
+
})
|
|
94
|
+
}, [disabled, onClose, onOpen])
|
|
95
|
+
|
|
96
|
+
//handle item select action
|
|
97
|
+
const select = useCallback(function (option) {
|
|
98
|
+
collapseDropdown()
|
|
99
|
+
if (disabled)
|
|
100
|
+
return
|
|
101
|
+
onChange && onChange(option.value || option)
|
|
102
|
+
updateSelectedValue(option)
|
|
103
|
+
}, [collapseDropdown, onChange])
|
|
104
|
+
|
|
105
|
+
//handle user scroll action for infinity scroll support
|
|
106
|
+
const scrollList = useMemo(() => throttle(200, e => {
|
|
107
|
+
if (!onScroll)
|
|
108
|
+
return
|
|
109
|
+
const {target} = e
|
|
110
|
+
const pos = {position: target.scrollTop, rel: 'middle'}
|
|
111
|
+
if (target.scrollTop === 0)
|
|
112
|
+
return onScroll({...pos, rel: 'top'})
|
|
113
|
+
if (Math.ceil(target.scrollHeight - target.scrollTop - 8) < target.clientHeight)
|
|
114
|
+
return onScroll({...pos, rel: 'bottom'})
|
|
115
|
+
onScroll(pos)
|
|
116
|
+
}), [onScroll])
|
|
117
|
+
|
|
118
|
+
//locate currently selected option
|
|
119
|
+
const {option: selectedItem, isDefault} = getSelectedOption([value, selectedValue], options)
|
|
120
|
+
|
|
121
|
+
//check dropdown container alignment
|
|
122
|
+
if (listOpen) {
|
|
123
|
+
setTimeout(() => {
|
|
124
|
+
if (!alignRight) {
|
|
125
|
+
const shouldAlignRight = isAlignedRight(listRef.current)
|
|
126
|
+
if (alignRight !== shouldAlignRight) {
|
|
127
|
+
setAlignRight(shouldAlignRight)
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}, 100)
|
|
131
|
+
}
|
|
132
|
+
//show a dropdown after the initial render
|
|
133
|
+
useEffect(() => {
|
|
134
|
+
if (expanded === true) {
|
|
135
|
+
setTimeout(() => updateListOpen(true), 200)
|
|
136
|
+
}
|
|
137
|
+
}, [])
|
|
138
|
+
|
|
139
|
+
const ddTitle = title || selectedItem?.title || selectedItem?.value || selectedItem
|
|
140
|
+
|
|
141
|
+
return <div className={cn('dd-wrapper', {disabled}, className)} title={hint}>
|
|
142
|
+
<a href="#" className="dd-header" onClick={toggleList} ref={headerRef}>
|
|
143
|
+
{ddTitle}{!!showToggle && <span className={cn('dd-toggle', {visible: listOpen})}/>}
|
|
144
|
+
</a>
|
|
145
|
+
{!!listOpen && createPortal(<div className={className}>
|
|
146
|
+
<div className={cn('dd-backdrop', {solo})}/>
|
|
147
|
+
<div className={cn('dd-list', {solo, visible: listOpen && !disabled, 'align-right': alignRight})}
|
|
148
|
+
style={getListPosition(headerRef.current, solo)} ref={listRef}>
|
|
149
|
+
{!!header && <>
|
|
150
|
+
<div className="dd-list-header" onClick={preventClosing}>{header}</div>
|
|
151
|
+
<hr/>
|
|
152
|
+
</>}
|
|
153
|
+
<ul onScroll={scrollList} style={{maxHeight: `min(70vh, ${maxHeight})`}}>
|
|
154
|
+
{options.filter(opt => !opt.hidden).map((option, i) => {
|
|
155
|
+
if (option === '-') return <li className="dd-list-item" key={i + '-'}>
|
|
156
|
+
<hr className="flare"/>
|
|
157
|
+
</li>
|
|
158
|
+
const key = option.value || option.href || option
|
|
159
|
+
const isSelected = !isDefault && option === selectedItem
|
|
160
|
+
const style = isSelected && hideSelected ? {display: 'none'} : {}
|
|
161
|
+
return <DropdownOption {...{key, option, select, isSelected, style}} />
|
|
162
|
+
})}
|
|
163
|
+
</ul>
|
|
164
|
+
{!!footer && <>
|
|
165
|
+
<hr/>
|
|
166
|
+
<div className="dd-list-footer" onClick={preventClosing}>{footer}</div>
|
|
167
|
+
</>}
|
|
168
|
+
</div>
|
|
169
|
+
</div>, document.body)}
|
|
170
|
+
</div>
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
const DropdownOption = React.memo(function DropdownOption({option, isSelected, select, style}) {
|
|
174
|
+
let {value, title, href, className} = option
|
|
175
|
+
if (typeof option === 'string') {
|
|
176
|
+
value = title = option
|
|
177
|
+
}
|
|
178
|
+
if (!title) {
|
|
179
|
+
title = value
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const selectOption = useCallback(function (e) {
|
|
183
|
+
if (option.disabled) {
|
|
184
|
+
e.stopPropagation()
|
|
185
|
+
return
|
|
186
|
+
}
|
|
187
|
+
if (!option.href) {
|
|
188
|
+
e.preventDefault()
|
|
189
|
+
}
|
|
190
|
+
select(option)
|
|
191
|
+
}, [select, option])
|
|
192
|
+
|
|
193
|
+
return <li className="dd-list-item" key={value || href} onClick={selectOption} style={style}>
|
|
194
|
+
<a href={href || '#'} className={cn({className, selected: isSelected})}>{title}</a>
|
|
195
|
+
</li>
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
function getSelectedOption(values, options) {
|
|
199
|
+
for (let v of values) {
|
|
200
|
+
if (v !== null && v !== undefined) {
|
|
201
|
+
const option = options.find(item => item === v || item.value === v)
|
|
202
|
+
if (option) return {option, isDefault: false}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return {option: options.find(opt => typeof opt === 'string' || !opt.disabled), isDefault: true}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function getListPosition(header, solo) {
|
|
209
|
+
if (solo || !header)
|
|
210
|
+
return undefined
|
|
211
|
+
const rect = header.getBoundingClientRect()
|
|
212
|
+
return {
|
|
213
|
+
top: rect.bottom + window.scrollY,
|
|
214
|
+
left: rect.left + window.scrollX
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function isAlignedRight(list) {
|
|
219
|
+
if (!list)
|
|
220
|
+
return
|
|
221
|
+
const rect = list.getBoundingClientRect()
|
|
222
|
+
return window.innerWidth - rect.right < 0 && rect.left - rect.width >= 0
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function preventClosing(e) {
|
|
226
|
+
e.stopPropagation()
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
Dropdown.defaultProps = {
|
|
230
|
+
showToggle: true,
|
|
231
|
+
disabled: false,
|
|
232
|
+
hideSelected: false,
|
|
233
|
+
solo: false,
|
|
234
|
+
maxHeight: '35em'
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
Dropdown.propTypes = {
|
|
238
|
+
/**
|
|
239
|
+
* Available options
|
|
240
|
+
*/
|
|
241
|
+
options: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.shape({
|
|
242
|
+
/**
|
|
243
|
+
* Internal value used for the item identification
|
|
244
|
+
*/
|
|
245
|
+
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
246
|
+
/**
|
|
247
|
+
* Link href - for dropdown menus
|
|
248
|
+
*/
|
|
249
|
+
href: PropTypes.string,
|
|
250
|
+
/**
|
|
251
|
+
* Optional friendly item title
|
|
252
|
+
*/
|
|
253
|
+
title: PropTypes.any
|
|
254
|
+
}), PropTypes.string])).isRequired,
|
|
255
|
+
/**
|
|
256
|
+
* Selected value
|
|
257
|
+
*/
|
|
258
|
+
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
259
|
+
/**
|
|
260
|
+
* Title to display instead of the selected value if needed
|
|
261
|
+
*/
|
|
262
|
+
title: PropTypes.any,
|
|
263
|
+
/**
|
|
264
|
+
* OnChange handler
|
|
265
|
+
*/
|
|
266
|
+
onChange: PropTypes.func,
|
|
267
|
+
/**
|
|
268
|
+
* Whether the dropdown interaction is disabled or not
|
|
269
|
+
*/
|
|
270
|
+
disabled: PropTypes.bool,
|
|
271
|
+
/**
|
|
272
|
+
* HTML hover title attribute for the control
|
|
273
|
+
*/
|
|
274
|
+
hint: PropTypes.string,
|
|
275
|
+
/**
|
|
276
|
+
* Additional HTML classes
|
|
277
|
+
*/
|
|
278
|
+
className: PropTypes.string,
|
|
279
|
+
/**
|
|
280
|
+
* Whether to show toggle icon
|
|
281
|
+
*/
|
|
282
|
+
showToggle: PropTypes.bool,
|
|
283
|
+
/**
|
|
284
|
+
* Show a dropdown list in centered dialog
|
|
285
|
+
*/
|
|
286
|
+
solo: PropTypes.bool,
|
|
287
|
+
/**
|
|
288
|
+
* Do not show selected item in the dropdown list
|
|
289
|
+
*/
|
|
290
|
+
hideSelected: PropTypes.bool,
|
|
291
|
+
/**
|
|
292
|
+
* Optional dropdown list header
|
|
293
|
+
*/
|
|
294
|
+
header: PropTypes.any,
|
|
295
|
+
/**
|
|
296
|
+
* Optional dropdown list footer
|
|
297
|
+
*/
|
|
298
|
+
footer: PropTypes.any,
|
|
299
|
+
/**
|
|
300
|
+
* Initially collapsed or open
|
|
301
|
+
*/
|
|
302
|
+
expanded: PropTypes.bool,
|
|
303
|
+
/**
|
|
304
|
+
* List scroll handler - fires only if the options list has overflow
|
|
305
|
+
*/
|
|
306
|
+
onScroll: PropTypes.func,
|
|
307
|
+
/**
|
|
308
|
+
* List open handler
|
|
309
|
+
*/
|
|
310
|
+
onOpen: PropTypes.func,
|
|
311
|
+
/**
|
|
312
|
+
* Lsi close handler
|
|
313
|
+
*/
|
|
314
|
+
onClose: PropTypes.func,
|
|
315
|
+
/**
|
|
316
|
+
* Maximum dropdown list height
|
|
317
|
+
*/
|
|
318
|
+
maxHeight: PropTypes.string
|
|
288
319
|
}
|
|
@@ -1,5 +1,11 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import React from 'react'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Link that opens in a new tab with `rel="noreferrer noopener"` for security
|
|
5
|
+
* @param {Object} props
|
|
6
|
+
* @param {string} props.href - Link URL
|
|
7
|
+
* @param {*} [props.children] - Link content
|
|
8
|
+
*/
|
|
9
|
+
export const ExternalLink = React.memo(function ExternalLink({href, children, ...otherProps}) {
|
|
10
|
+
return <a href={href} target="_blank" rel="noreferrer noopener" {...otherProps}>{children}</a>
|
|
5
11
|
})
|