@stellar-expert/ui-framework 1.16.8 → 1.17.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/CLAUDE.md +35 -0
- package/README.md +1125 -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/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 +1241 -0
- 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 +41 -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/info-tooltip.js
CHANGED
|
@@ -1,17 +1,24 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import PropTypes from 'prop-types'
|
|
3
|
-
import cn from 'classnames'
|
|
4
|
-
import {Tooltip} from './tooltip'
|
|
5
|
-
import './info-tooltip.scss'
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
InfoTooltip.
|
|
15
|
-
|
|
16
|
-
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import PropTypes from 'prop-types'
|
|
3
|
+
import cn from 'classnames'
|
|
4
|
+
import {Tooltip} from './tooltip'
|
|
5
|
+
import './info-tooltip.scss'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Help icon that shows a tooltip with explanatory text on hover
|
|
9
|
+
* @param {Object} props
|
|
10
|
+
* @param {*} props.children - Tooltip content
|
|
11
|
+
* @param {string} [props.link] - Optional "Read more" URL
|
|
12
|
+
* @param {string} [props.icon='icon-help'] - Icon CSS class
|
|
13
|
+
*/
|
|
14
|
+
export const InfoTooltip = React.memo(function InfoTooltip({children, link, icon = 'icon-help', ...otherProps}) {
|
|
15
|
+
return <Tooltip trigger={<i className={cn('trigger icon info-tooltip text-small text-justify', icon)} {...otherProps}/>} maxWidth="30em">
|
|
16
|
+
{children}
|
|
17
|
+
{!!link && <a href={link} className="info-tooltip-link" target="_blank">Read more…</a>}
|
|
18
|
+
</Tooltip>
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
InfoTooltip.propTypes = {
|
|
22
|
+
children: PropTypes.any.isRequired,
|
|
23
|
+
link: PropTypes.string
|
|
17
24
|
}
|
package/controls/slider.js
CHANGED
|
@@ -1,20 +1,30 @@
|
|
|
1
|
-
import React, {useCallback, useMemo, useState} from 'react'
|
|
2
|
-
import {throttle} from 'throttle-debounce'
|
|
3
|
-
import './slider.scss'
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
1
|
+
import React, {useCallback, useMemo, useState} from 'react'
|
|
2
|
+
import {throttle} from 'throttle-debounce'
|
|
3
|
+
import './slider.scss'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Range input slider with optional labeled categories
|
|
7
|
+
* @param {Object} props
|
|
8
|
+
* @param {number} [props.value] - Current slider value
|
|
9
|
+
* @param {string[]} [props.categories] - Category labels displayed as a datalist
|
|
10
|
+
* @param {function(number): void} [props.onChange] - Callback invoked with the new value (throttled)
|
|
11
|
+
* @param {number} [props.min=0] - Minimum value
|
|
12
|
+
* @param {number} [props.max=100] - Maximum value
|
|
13
|
+
* @param {number} [props.step=1] - Step increment
|
|
14
|
+
*/
|
|
15
|
+
export function Slider({value, categories, onChange, min = 0, max = 100, step = 1, ...otherProps}) {
|
|
16
|
+
const [inputValue, setInputValue] = useState(value || min)
|
|
17
|
+
const change = useMemo(() => throttle(300, onChange), [onChange])
|
|
18
|
+
const onSlide = useCallback(function (e) {
|
|
19
|
+
const value = parseFloat(e.target.value)
|
|
20
|
+
setInputValue(value)
|
|
21
|
+
change(value)
|
|
22
|
+
}, [change])
|
|
23
|
+
|
|
24
|
+
return <div className="slider dimmed text-small" {...otherProps}>
|
|
25
|
+
{categories && <datalist className="categories dimmed condensed">
|
|
26
|
+
{categories.map((category, index) => <option key={index + category} value={category} label={category}/>)}
|
|
27
|
+
</datalist>}
|
|
28
|
+
<input type="range" min={min} max={max} step={step} value={inputValue} onChange={onSlide}/>
|
|
29
|
+
</div>
|
|
20
30
|
}
|
package/controls/tabs.js
CHANGED
|
@@ -1,94 +1,94 @@
|
|
|
1
|
-
import React, {useEffect} from 'react'
|
|
2
|
-
import cn from 'classnames'
|
|
3
|
-
import {navigation} from '@stellar-expert/navigation'
|
|
4
|
-
import {useDependantState} from '../state/state-hooks'
|
|
5
|
-
import './tabs.scss'
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Tabs control
|
|
9
|
-
* @param {TabDescriptor[]} tabs - Tabs list
|
|
10
|
-
* @param {
|
|
11
|
-
* @param {
|
|
12
|
-
* @param {
|
|
13
|
-
* @param {
|
|
14
|
-
* @param {
|
|
15
|
-
* @param {*} [children] - Additional content to render in the tabs header
|
|
16
|
-
* @constructor
|
|
17
|
-
*/
|
|
18
|
-
export function Tabs({tabs, selectedTab, queryParam, className, onChange, right, children}) {
|
|
19
|
-
const [internallySelectedTab, setSelectedTab] = useDependantState(() => {
|
|
20
|
-
//return the props-derived tab name if available
|
|
21
|
-
if (selectedTab) return selectedTab
|
|
22
|
-
//try to get from query string
|
|
23
|
-
if (queryParam) {
|
|
24
|
-
const tab = navigation.query[queryParam]
|
|
25
|
-
if (findTabByName(tab)) return tab
|
|
26
|
-
}
|
|
27
|
-
//return first tab
|
|
28
|
-
const firstTab = tabs[0]
|
|
29
|
-
return firstTab ? firstTab.name : null
|
|
30
|
-
}, [selectedTab])
|
|
31
|
-
|
|
32
|
-
useEffect(() => {
|
|
33
|
-
if (!queryParam) return
|
|
34
|
-
const stopListeningQueryChanges = navigation.listen(({query}) => {
|
|
35
|
-
const tab = query[queryParam] || (tabs.find(t => t.isDefault) || tabs[0])?.name
|
|
36
|
-
selectTab(tab)
|
|
37
|
-
})
|
|
38
|
-
return () => {
|
|
39
|
-
stopListeningQueryChanges && stopListeningQueryChanges()
|
|
40
|
-
}
|
|
41
|
-
}, [tabs, queryParam])
|
|
42
|
-
|
|
43
|
-
function findTabByName(tabName) {
|
|
44
|
-
return tabs.find(t => t.name === tabName)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function selectTab(tabName) {
|
|
48
|
-
const tab = findTabByName(tabName)
|
|
49
|
-
if (!tab) {
|
|
50
|
-
if (selectedTab === undefined) {
|
|
51
|
-
setSelectedTab(null)
|
|
52
|
-
}
|
|
53
|
-
return
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (internallySelectedTab === tabName || selectedTab === tabName) return
|
|
57
|
-
|
|
58
|
-
if (onChange) {
|
|
59
|
-
onChange(tabName, this)
|
|
60
|
-
}
|
|
61
|
-
if (selectedTab === undefined) {
|
|
62
|
-
setSelectedTab(tabName)
|
|
63
|
-
}
|
|
64
|
-
if (queryParam) {
|
|
65
|
-
navigation.updateQuery({[queryParam]: tab.isDefault ? undefined : tabName})
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const s = selectedTab || internallySelectedTab
|
|
70
|
-
const tabToRender = tabs.find(({name}) => name === s) || tabs[0]
|
|
71
|
-
|
|
72
|
-
return <div className={cn('tabs', className, {'inline-right': right})}>
|
|
73
|
-
<div className="tabs-header">
|
|
74
|
-
<div>
|
|
75
|
-
{tabs.map(({name, title}) => <a href="#" key={name} onClick={() => selectTab(name)}
|
|
76
|
-
className={cn('tabs-item', 'condensed', {selected: s === name})}>
|
|
77
|
-
<span className="tabs-item-text">{title || name}</span></a>)}
|
|
78
|
-
</div>
|
|
79
|
-
{children}
|
|
80
|
-
</div>
|
|
81
|
-
<hr className="flare"/>
|
|
82
|
-
{!!tabToRender.render && <div className="tabs-body">
|
|
83
|
-
{tabToRender.render()}
|
|
84
|
-
</div>}
|
|
85
|
-
</div>
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* @typedef {{}} TabDescriptor
|
|
90
|
-
* @property {
|
|
91
|
-
* @property {
|
|
92
|
-
* @property {
|
|
93
|
-
* @property {
|
|
94
|
-
*/
|
|
1
|
+
import React, {useEffect} from 'react'
|
|
2
|
+
import cn from 'classnames'
|
|
3
|
+
import {navigation} from '@stellar-expert/navigation'
|
|
4
|
+
import {useDependantState} from '../state/state-hooks'
|
|
5
|
+
import './tabs.scss'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Tabs control
|
|
9
|
+
* @param {TabDescriptor[]} tabs - Tabs list
|
|
10
|
+
* @param {string} [selectedTab] - Currently selected tab
|
|
11
|
+
* @param {function} [onChange] - Handler for tabChanged event
|
|
12
|
+
* @param {string} [queryParam] - Associated query param name (control will auto-update query string)
|
|
13
|
+
* @param {string} [className] - Optional CSS class name
|
|
14
|
+
* @param {boolean} [right] - Position tabs to the right within the header
|
|
15
|
+
* @param {*} [children] - Additional content to render in the tabs header
|
|
16
|
+
* @constructor
|
|
17
|
+
*/
|
|
18
|
+
export function Tabs({tabs, selectedTab, queryParam, className, onChange, right, children}) {
|
|
19
|
+
const [internallySelectedTab, setSelectedTab] = useDependantState(() => {
|
|
20
|
+
//return the props-derived tab name if available
|
|
21
|
+
if (selectedTab) return selectedTab
|
|
22
|
+
//try to get from query string
|
|
23
|
+
if (queryParam) {
|
|
24
|
+
const tab = navigation.query[queryParam]
|
|
25
|
+
if (findTabByName(tab)) return tab
|
|
26
|
+
}
|
|
27
|
+
//return first tab
|
|
28
|
+
const firstTab = tabs[0]
|
|
29
|
+
return firstTab ? firstTab.name : null
|
|
30
|
+
}, [selectedTab])
|
|
31
|
+
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
if (!queryParam) return
|
|
34
|
+
const stopListeningQueryChanges = navigation.listen(({query}) => {
|
|
35
|
+
const tab = query[queryParam] || (tabs.find(t => t.isDefault) || tabs[0])?.name
|
|
36
|
+
selectTab(tab)
|
|
37
|
+
})
|
|
38
|
+
return () => {
|
|
39
|
+
stopListeningQueryChanges && stopListeningQueryChanges()
|
|
40
|
+
}
|
|
41
|
+
}, [tabs, queryParam])
|
|
42
|
+
|
|
43
|
+
function findTabByName(tabName) {
|
|
44
|
+
return tabs.find(t => t.name === tabName)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function selectTab(tabName) {
|
|
48
|
+
const tab = findTabByName(tabName)
|
|
49
|
+
if (!tab) {
|
|
50
|
+
if (selectedTab === undefined) {
|
|
51
|
+
setSelectedTab(null)
|
|
52
|
+
}
|
|
53
|
+
return
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (internallySelectedTab === tabName || selectedTab === tabName) return
|
|
57
|
+
|
|
58
|
+
if (onChange) {
|
|
59
|
+
onChange(tabName, this)
|
|
60
|
+
}
|
|
61
|
+
if (selectedTab === undefined) {
|
|
62
|
+
setSelectedTab(tabName)
|
|
63
|
+
}
|
|
64
|
+
if (queryParam) {
|
|
65
|
+
navigation.updateQuery({[queryParam]: tab.isDefault ? undefined : tabName})
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const s = selectedTab || internallySelectedTab
|
|
70
|
+
const tabToRender = tabs.find(({name}) => name === s) || tabs[0]
|
|
71
|
+
|
|
72
|
+
return <div className={cn('tabs', className, {'inline-right': right})}>
|
|
73
|
+
<div className="tabs-header">
|
|
74
|
+
<div>
|
|
75
|
+
{tabs.map(({name, title}) => <a href="#" key={name} onClick={() => selectTab(name)}
|
|
76
|
+
className={cn('tabs-item', 'condensed', {selected: s === name})}>
|
|
77
|
+
<span className="tabs-item-text">{title || name}</span></a>)}
|
|
78
|
+
</div>
|
|
79
|
+
{children}
|
|
80
|
+
</div>
|
|
81
|
+
<hr className="flare"/>
|
|
82
|
+
{!!tabToRender.render && <div className="tabs-body">
|
|
83
|
+
{tabToRender.render()}
|
|
84
|
+
</div>}
|
|
85
|
+
</div>
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* @typedef {{}} TabDescriptor
|
|
90
|
+
* @property {string} name - Unique table name
|
|
91
|
+
* @property {string} [title] - Display name (if differs from tab name)
|
|
92
|
+
* @property {function} [render] - Render callback
|
|
93
|
+
* @property {boolean} [isDefault] - Whether this tab should be displayed by default
|
|
94
|
+
*/
|