@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.
Files changed (78) hide show
  1. package/CLAUDE.md +35 -0
  2. package/README.md +1125 -3
  3. package/account/account-address.js +127 -127
  4. package/account/available-balance.js +22 -22
  5. package/account/identicon.js +90 -90
  6. package/account/signer-key.js +65 -64
  7. package/api/explorer-api-hooks.js +209 -202
  8. package/api/explorer-api-paginated-list-hooks.js +441 -440
  9. package/api/explorer-batch-info-loader.js +111 -85
  10. package/api/explorer-tx-api.js +28 -28
  11. package/api/ledger-stream.js +15 -0
  12. package/asset/amount.js +56 -56
  13. package/asset/asset-icon.js +41 -41
  14. package/asset/asset-issuer.js +21 -21
  15. package/asset/asset-link.js +107 -107
  16. package/asset/asset-list-hooks.js +59 -59
  17. package/asset/asset-meta-hooks.js +88 -88
  18. package/asset/asset-selector.js +72 -71
  19. package/claimable-balance/claimable-balance-claimants.js +23 -18
  20. package/contract/contract-api.js +15 -0
  21. package/contract/invocation-info-view.js +10 -2
  22. package/contract/sc-val.js +131 -107
  23. package/controls/button-group.js +25 -19
  24. package/controls/button.js +93 -78
  25. package/controls/code-block.js +42 -34
  26. package/controls/dropdown.js +318 -287
  27. package/controls/external-link.js +10 -4
  28. package/controls/info-tooltip.js +23 -16
  29. package/controls/slider.js +29 -19
  30. package/controls/tabs.js +94 -94
  31. package/controls/tooltip.js +244 -240
  32. package/controls/update-highlighter.js +32 -27
  33. package/date/date-selector.js +56 -54
  34. package/date/elapsed-time.js +28 -21
  35. package/dex/price-dynamic.js +53 -44
  36. package/directory/directory-hooks.js +109 -97
  37. package/effect/effect-description.js +346 -344
  38. package/errors/error-boundary.js +110 -97
  39. package/horizon/horizon-account-helpers.js +104 -104
  40. package/horizon/horizon-ledger-helpers.js +35 -35
  41. package/horizon/horizon-trades-helper.js +88 -88
  42. package/horizon/horizon-transaction-helpers.js +36 -36
  43. package/index.d.ts +1241 -0
  44. package/interaction/accordion.js +43 -35
  45. package/interaction/autofocus.js +13 -9
  46. package/interaction/block-select.js +64 -53
  47. package/interaction/copy-to-clipboard.js +25 -18
  48. package/interaction/inline-progress.js +20 -15
  49. package/interaction/qr-code.js +34 -34
  50. package/interaction/responsive.js +20 -20
  51. package/interaction/spoiler.js +52 -39
  52. package/interaction/theme-selector.js +13 -10
  53. package/ledger/ledger-entry-href-formatter.js +27 -26
  54. package/ledger/ledger-entry-link.js +93 -58
  55. package/ledger/ledger-info-parser.js +46 -18
  56. package/meta/page-meta-tags.js +243 -238
  57. package/module/dynamic-module.js +47 -47
  58. package/package.json +41 -40
  59. package/state/on-screen-hooks.js +22 -22
  60. package/state/page-visibility-helpers.js +29 -16
  61. package/state/page-visibility-hooks.js +13 -11
  62. package/state/screen-orientation-hooks.js +19 -15
  63. package/state/state-hooks.js +76 -76
  64. package/state/stellar-network-hooks.js +56 -44
  65. package/state/theme.js +29 -28
  66. package/stellar/key-type.js +92 -91
  67. package/stellar/ledger-generic-id.js +39 -39
  68. package/stellar/signature-hint-utils.js +65 -65
  69. package/toast/toast-notifications-block.js +59 -59
  70. package/tx/op-description-view.js +945 -942
  71. package/tx/op-icon.js +98 -98
  72. package/tx/parser/op-balance-changes.js +66 -66
  73. package/tx/parser/op-descriptor.js +51 -48
  74. package/tx/parser/tx-details-parser.js +81 -81
  75. package/tx/parser/tx-matcher.js +371 -371
  76. package/tx/parser/type-filter-matcher.js +126 -126
  77. package/tx/tx-list-hooks.js +32 -18
  78. package/tx/tx-operations-list.js +117 -116
@@ -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
- export const InfoTooltip = React.memo(function InfoTooltip({children, link, icon = 'icon-help', ...otherProps}) {
8
- return <Tooltip trigger={<i className={cn('trigger icon info-tooltip text-small text-justify', icon)} {...otherProps}/>} maxWidth="30em">
9
- {children}
10
- {!!link && <a href={link} className="info-tooltip-link" target="_blank">Read more&hellip;</a>}
11
- </Tooltip>
12
- })
13
-
14
- InfoTooltip.propTypes = {
15
- children: PropTypes.any.isRequired,
16
- link: PropTypes.string
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&hellip;</a>}
18
+ </Tooltip>
19
+ })
20
+
21
+ InfoTooltip.propTypes = {
22
+ children: PropTypes.any.isRequired,
23
+ link: PropTypes.string
17
24
  }
@@ -1,20 +1,30 @@
1
- import React, {useCallback, useMemo, useState} from 'react'
2
- import {throttle} from 'throttle-debounce'
3
- import './slider.scss'
4
-
5
- export function Slider({value, categories, onChange, min = 0, max = 100, step = 1, ...otherProps}) {
6
- const [inputValue, setInputValue] = useState(value || min)
7
- const change = useMemo(() => throttle(300, onChange), [onChange])
8
- const onSlide = useCallback(function (e) {
9
- const value = parseFloat(e.target.value)
10
- setInputValue(value)
11
- change(value)
12
- }, [change])
13
-
14
- return <div className="slider dimmed text-small" {...otherProps}>
15
- {categories && <datalist className="categories dimmed condensed">
16
- {categories.map((category, index) => <option key={index + category} value={category} label={category}/>)}
17
- </datalist>}
18
- <input type="range" min={min} max={max} step={step} value={inputValue} onChange={onSlide}/>
19
- </div>
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 {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
- */
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
+ */