ywana-core8 0.1.80 → 0.1.81
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/dist/index.cjs +164 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +1 -0
- package/dist/index.css.map +1 -1
- package/dist/index.modern.js +164 -20
- package/dist/index.modern.js.map +1 -1
- package/dist/index.umd.js +164 -20
- package/dist/index.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/html/button.js +22 -4
- package/src/html/header.js +20 -3
- package/src/html/textfield.js +73 -7
- package/src/html/textfield2.js +19 -4
- package/src/html/tooltip.js +21 -3
- package/src/widgets/login/LoginBox.css +1 -0
- package/src/widgets/login/LoginBox.js +29 -6
package/package.json
CHANGED
package/src/html/button.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import React, { useEffect, useState, useCallback } from 'react'
|
1
|
+
import React, { useEffect, useState, useCallback, useMemo } from 'react'
|
2
2
|
import PropTypes from 'prop-types'
|
3
3
|
import { Icon } from './icon'
|
4
4
|
import { Text } from './text'
|
@@ -88,6 +88,24 @@ export const Button = (props) => {
|
|
88
88
|
'aria-describedby': tooltip ? `${id}-tooltip` : undefined
|
89
89
|
}
|
90
90
|
|
91
|
+
// Label text - support both string and React components
|
92
|
+
const labelElement = useMemo(() => {
|
93
|
+
if (!label) return null
|
94
|
+
|
95
|
+
// If label is already a React element, use it directly
|
96
|
+
if (React.isValidElement(label)) {
|
97
|
+
return label
|
98
|
+
}
|
99
|
+
|
100
|
+
// If label is a string, wrap it in Text component
|
101
|
+
if (typeof label === 'string') {
|
102
|
+
return <Text>{label}</Text>
|
103
|
+
}
|
104
|
+
|
105
|
+
// Fallback for other types (convert to string)
|
106
|
+
return <Text>{String(label)}</Text>
|
107
|
+
}, [label])
|
108
|
+
|
91
109
|
// Icon configuration
|
92
110
|
const iconProps = {
|
93
111
|
icon: loading ? 'hourglass_empty' : icon,
|
@@ -111,7 +129,7 @@ export const Button = (props) => {
|
|
111
129
|
{...restProps}
|
112
130
|
>
|
113
131
|
{(icon || loading) && <Icon {...iconProps} />}
|
114
|
-
{
|
132
|
+
{labelElement}
|
115
133
|
{loading && !icon && <span className="loading-text">Loading...</span>}
|
116
134
|
</button>
|
117
135
|
)
|
@@ -207,8 +225,8 @@ export const ActionButton = (props) => {
|
|
207
225
|
Button.propTypes = {
|
208
226
|
/** Unique identifier for the button */
|
209
227
|
id: PropTypes.string,
|
210
|
-
/** Button text label */
|
211
|
-
label: PropTypes.string,
|
228
|
+
/** Button text label - can be string or React element */
|
229
|
+
label: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
|
212
230
|
/** Icon name for Material Icons */
|
213
231
|
icon: PropTypes.string,
|
214
232
|
/** Click handler function */
|
package/src/html/header.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import React from 'react';
|
1
|
+
import React, { useMemo } from 'react';
|
2
2
|
import { Icon } from './icon';
|
3
3
|
import { Text } from './text';
|
4
4
|
import './header.css';
|
@@ -18,11 +18,28 @@ export const Header = (props) => {
|
|
18
18
|
|
19
19
|
const style = props.img ? { backgroundImage: `url(${props.img })` } : {}
|
20
20
|
|
21
|
-
|
21
|
+
// Title element - support both string and React components
|
22
|
+
const titleElement = useMemo(() => {
|
23
|
+
if (!props.title) return null
|
24
|
+
|
25
|
+
// If title is already a React element, use it directly
|
26
|
+
if (React.isValidElement(props.title)) {
|
27
|
+
return props.title
|
28
|
+
}
|
29
|
+
|
30
|
+
// If title is a string, wrap it in Text component
|
31
|
+
if (typeof props.title === 'string') {
|
32
|
+
return <Text>{props.title}</Text>
|
33
|
+
}
|
34
|
+
|
35
|
+
// Fallback for other types (convert to string)
|
36
|
+
return <Text>{String(props.title)}</Text>
|
37
|
+
}, [props.title])
|
38
|
+
|
22
39
|
return (
|
23
40
|
<header className={`header ${caption} ${prominent} ${dense} ${theme} ${props.className}`} style={style}>
|
24
41
|
{icon}
|
25
|
-
{props.title ? <label>{
|
42
|
+
{props.title ? <label>{titleElement}</label> : null }
|
26
43
|
<span className="actions">{props.children}</span>
|
27
44
|
</header>
|
28
45
|
)
|
package/src/html/textfield.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import React, { useContext, useEffect, useState } from 'react'
|
1
|
+
import React, { useContext, useEffect, useState, useMemo } from 'react'
|
2
2
|
import { SiteContext } from '../site/siteContext'
|
3
3
|
import { Icon } from './icon'
|
4
4
|
import { TEXTFORMATS, Text } from './text'
|
@@ -59,7 +59,25 @@ export const TextField = (props) => {
|
|
59
59
|
const labelStyle = label ? "" : "no-label"
|
60
60
|
const labelPositionStyle = labelPosition == 'left' ? "label-left" : "label-top"
|
61
61
|
const style = `${labelStyle} ${labelPositionStyle} ${borderStyle} textfield-${type}`
|
62
|
-
|
62
|
+
|
63
|
+
// Label text - support both string and React components
|
64
|
+
const labelTxt = useMemo(() => {
|
65
|
+
if (!label) return null
|
66
|
+
|
67
|
+
// If label is already a React element, use it directly
|
68
|
+
if (React.isValidElement(label)) {
|
69
|
+
return label
|
70
|
+
}
|
71
|
+
|
72
|
+
// If label is a string, wrap it in Text component
|
73
|
+
if (typeof label === 'string') {
|
74
|
+
return <Text>{label}</Text>
|
75
|
+
}
|
76
|
+
|
77
|
+
// Fallback for other types (convert to string)
|
78
|
+
return <Text>{String(label)}</Text>
|
79
|
+
}, [label])
|
80
|
+
|
63
81
|
const placeholderTxt = site.translate ? site.translate(placeholder) : placeholder
|
64
82
|
|
65
83
|
return (
|
@@ -110,10 +128,26 @@ export const TextArea = (props) => {
|
|
110
128
|
if (onChange) onChange(id, "")
|
111
129
|
}
|
112
130
|
|
113
|
-
const borderStyle = outlined ? "textarea-outlined" : "textarea"
|
114
131
|
const labelStyle = label ? "" : "no-label"
|
115
132
|
const style = `textarea ${labelStyle} textarea-${type}`
|
116
|
-
|
133
|
+
|
134
|
+
// Label text - support both string and React components
|
135
|
+
const labelTxt = useMemo(() => {
|
136
|
+
if (!label) return null
|
137
|
+
|
138
|
+
// If label is already a React element, use it directly
|
139
|
+
if (React.isValidElement(label)) {
|
140
|
+
return label
|
141
|
+
}
|
142
|
+
|
143
|
+
// If label is a string, wrap it in Text component
|
144
|
+
if (typeof label === 'string') {
|
145
|
+
return <Text>{label}</Text>
|
146
|
+
}
|
147
|
+
|
148
|
+
// Fallback for other types (convert to string)
|
149
|
+
return <Text>{String(label)}</Text>
|
150
|
+
}, [label])
|
117
151
|
|
118
152
|
const placeholderTxt = site.translate ? site.translate(placeholder) : placeholder
|
119
153
|
|
@@ -222,7 +256,7 @@ export const DropDown = (props) => {
|
|
222
256
|
*/
|
223
257
|
export const DateRange = (props) => {
|
224
258
|
|
225
|
-
const { id, label,
|
259
|
+
const { id, label, onChange } = props
|
226
260
|
const [form, setForm] = useState({})
|
227
261
|
|
228
262
|
useEffect(() => {
|
@@ -237,7 +271,23 @@ export const DateRange = (props) => {
|
|
237
271
|
setForm(next)
|
238
272
|
}
|
239
273
|
|
240
|
-
|
274
|
+
// Label text - support both string and React components
|
275
|
+
const labelTxt = useMemo(() => {
|
276
|
+
if (!label) return null
|
277
|
+
|
278
|
+
// If label is already a React element, use it directly
|
279
|
+
if (React.isValidElement(label)) {
|
280
|
+
return label
|
281
|
+
}
|
282
|
+
|
283
|
+
// If label is a string, wrap it in Text component
|
284
|
+
if (typeof label === 'string') {
|
285
|
+
return <Text>{label}</Text>
|
286
|
+
}
|
287
|
+
|
288
|
+
// Fallback for other types (convert to string)
|
289
|
+
return <Text>{String(label)}</Text>
|
290
|
+
}, [label])
|
241
291
|
|
242
292
|
return (
|
243
293
|
<div className="date-range">
|
@@ -257,7 +307,23 @@ export const PasswordField = (props) => {
|
|
257
307
|
setShow(!show)
|
258
308
|
}
|
259
309
|
|
260
|
-
|
310
|
+
// Label text - support both string and React components
|
311
|
+
const labelTxt = useMemo(() => {
|
312
|
+
if (!label) return null
|
313
|
+
|
314
|
+
// If label is already a React element, use it directly
|
315
|
+
if (React.isValidElement(label)) {
|
316
|
+
return label
|
317
|
+
}
|
318
|
+
|
319
|
+
// If label is a string, wrap it in Text component
|
320
|
+
if (typeof label === 'string') {
|
321
|
+
return <Text>{label}</Text>
|
322
|
+
}
|
323
|
+
|
324
|
+
// Fallback for other types (convert to string)
|
325
|
+
return <Text>{String(label)}</Text>
|
326
|
+
}, [label])
|
261
327
|
|
262
328
|
return (
|
263
329
|
<div className="password-field">
|
package/src/html/textfield2.js
CHANGED
@@ -204,8 +204,23 @@ export const TextField2 = (props) => {
|
|
204
204
|
...restProps
|
205
205
|
}
|
206
206
|
|
207
|
-
// Label text
|
208
|
-
const labelTxt =
|
207
|
+
// Label text - support both string and React components
|
208
|
+
const labelTxt = useMemo(() => {
|
209
|
+
if (!label) return null
|
210
|
+
|
211
|
+
// If label is already a React element, use it directly
|
212
|
+
if (React.isValidElement(label)) {
|
213
|
+
return label
|
214
|
+
}
|
215
|
+
|
216
|
+
// If label is a string, wrap it in Text component
|
217
|
+
if (typeof label === 'string') {
|
218
|
+
return <Text>{label}</Text>
|
219
|
+
}
|
220
|
+
|
221
|
+
// Fallback for other types (convert to string)
|
222
|
+
return <Text>{String(label)}</Text>
|
223
|
+
}, [label])
|
209
224
|
const placeholderTxt = site?.translate ? site.translate(placeholder) : placeholder
|
210
225
|
|
211
226
|
// Error/helper text
|
@@ -304,8 +319,8 @@ TextField2.propTypes = {
|
|
304
319
|
type: PropTypes.oneOf(['text', 'email', 'password', 'number', 'tel', 'url', 'search', 'date', 'time', 'datetime-local', 'month', 'week', 'textarea']),
|
305
320
|
/** Additional CSS classes */
|
306
321
|
className: PropTypes.string,
|
307
|
-
/** Field label */
|
308
|
-
label: PropTypes.string,
|
322
|
+
/** Field label - can be string or React element */
|
323
|
+
label: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
|
309
324
|
/** Label position */
|
310
325
|
labelPosition: PropTypes.oneOf(['top', 'left']),
|
311
326
|
/** Placeholder text */
|
package/src/html/tooltip.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import React from 'react'
|
1
|
+
import React, { useMemo } from 'react'
|
2
2
|
import { Text } from './text'
|
3
3
|
import './tooltip.css'
|
4
4
|
|
@@ -11,11 +11,29 @@ export const Tooltip = (props) => {
|
|
11
11
|
|
12
12
|
const style = { top, left }
|
13
13
|
|
14
|
+
// Text element - support both string and React components
|
15
|
+
const textElement = useMemo(() => {
|
16
|
+
if (!text) return null
|
17
|
+
|
18
|
+
// If text is already a React element, use it directly
|
19
|
+
if (React.isValidElement(text)) {
|
20
|
+
return text
|
21
|
+
}
|
22
|
+
|
23
|
+
// If text is a string, wrap it in Text component
|
24
|
+
if (typeof text === 'string') {
|
25
|
+
return <Text>{text}</Text>
|
26
|
+
}
|
27
|
+
|
28
|
+
// Fallback for other types (convert to string)
|
29
|
+
return <Text>{String(text)}</Text>
|
30
|
+
}, [text])
|
31
|
+
|
14
32
|
return (
|
15
33
|
<div className="tooltip" >
|
16
|
-
<span className="tooltip-text" style={style}
|
34
|
+
<span className="tooltip-text" style={style}>{textElement}</span>
|
17
35
|
{props.children}
|
18
36
|
</div>
|
19
37
|
)
|
20
38
|
|
21
|
-
}
|
39
|
+
}
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import React, { useState } from 'react'
|
2
|
-
import { Icon , Button, Text, TextField } from '../../html'
|
2
|
+
import { Icon , Button, Text, TextField2 as TextField } from '../../html'
|
3
3
|
import './LoginBox.css'
|
4
4
|
|
5
5
|
/**
|
@@ -24,23 +24,46 @@ export const LoginBox = ({
|
|
24
24
|
if (onOK && canOK()) onOK(user, forcedPwd || password)
|
25
25
|
}
|
26
26
|
|
27
|
+
// Helper function for backward compatibility
|
28
|
+
// TextField2 now supports both strings and React elements
|
27
29
|
function tx(txt) {
|
30
|
+
// For TextField2, we can pass strings directly for better performance
|
31
|
+
// But keep this function for backward compatibility with other components
|
28
32
|
return <Text>{txt}</Text>
|
29
33
|
}
|
30
34
|
|
31
|
-
function changeUser(
|
35
|
+
function changeUser(_, value) {
|
32
36
|
setUser(value)
|
33
37
|
}
|
34
|
-
|
35
|
-
function changePassword(
|
38
|
+
|
39
|
+
function changePassword(_, value) {
|
36
40
|
setPassword(value)
|
37
41
|
}
|
38
42
|
|
39
43
|
return (
|
40
44
|
<div className="login-box">
|
41
45
|
<main>
|
42
|
-
<TextField
|
43
|
-
|
46
|
+
<TextField
|
47
|
+
id="loginbox-user"
|
48
|
+
label={tx(userLabel)}
|
49
|
+
value={user}
|
50
|
+
onChange={changeUser}
|
51
|
+
onEnter={ok}
|
52
|
+
outlined
|
53
|
+
autoComplete="username"
|
54
|
+
required
|
55
|
+
/>
|
56
|
+
<TextField
|
57
|
+
id="loginbox-password"
|
58
|
+
label={tx(passwordLabel)}
|
59
|
+
value={password}
|
60
|
+
onChange={changePassword}
|
61
|
+
onEnter={ok}
|
62
|
+
type="password"
|
63
|
+
outlined
|
64
|
+
autoComplete="current-password"
|
65
|
+
required
|
66
|
+
/>
|
44
67
|
</main>
|
45
68
|
<footer>
|
46
69
|
{ loading ? <div className="load-box"><Icon icon="refresh" /></div> : null }
|