tinywidgets 1.2.4 → 1.3.1
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/package.json +1 -1
- package/src/components/Button/index.tsx +1 -1
- package/src/components/Select/index.css.ts +14 -0
- package/src/components/Select/index.tsx +77 -0
- package/src/components/TextInput/index.css.ts +36 -0
- package/src/components/TextInput/index.tsx +91 -0
- package/src/css/colors.css.ts +8 -0
- package/src/index.ts +2 -0
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
} from './index.css.ts';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
* The `Button` component displays
|
|
14
|
+
* The `Button` component displays a button, with a number of common variants.
|
|
15
15
|
*
|
|
16
16
|
* @param props The props for the component.
|
|
17
17
|
* @returns The Button component.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import {style} from '@vanilla-extract/css';
|
|
2
|
+
import {colors} from '../../css/colors.css';
|
|
3
|
+
import {dimensions} from '../../css/dimensions.css';
|
|
4
|
+
|
|
5
|
+
export const select = style({
|
|
6
|
+
borderRadius: dimensions.radius,
|
|
7
|
+
padding: '0.5rem',
|
|
8
|
+
outlineOffset: '2px',
|
|
9
|
+
color: 'inherit',
|
|
10
|
+
transition: 'background-color 0.1s,border-color 0.1s',
|
|
11
|
+
boxShadow: colors.shadow,
|
|
12
|
+
border: colors.border,
|
|
13
|
+
backgroundColor: colors.background,
|
|
14
|
+
});
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import {useCallback, useState} from 'react';
|
|
2
|
+
import {classNames} from '../../common/functions.tsx';
|
|
3
|
+
import {select} from './index.css.ts';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The `Select` component displays a managed select input with an existing
|
|
7
|
+
* value.
|
|
8
|
+
*
|
|
9
|
+
* @param props The props for the component.
|
|
10
|
+
* @returns The Select component.
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* <Select
|
|
14
|
+
* initialOption="CA"
|
|
15
|
+
* options={{ AL: 'Albania', BE: 'Belgium', CA: 'Canada' }}
|
|
16
|
+
* onChange={(option) => console.log(option)}
|
|
17
|
+
* />
|
|
18
|
+
* ```
|
|
19
|
+
* @icon Lucide.Combine
|
|
20
|
+
*/
|
|
21
|
+
export const Select = ({
|
|
22
|
+
options,
|
|
23
|
+
initialOption,
|
|
24
|
+
onChange,
|
|
25
|
+
alt,
|
|
26
|
+
className,
|
|
27
|
+
ref,
|
|
28
|
+
}: {
|
|
29
|
+
/**
|
|
30
|
+
* The options and labels to show in the select widget.
|
|
31
|
+
*/
|
|
32
|
+
readonly options: {[option: string]: string};
|
|
33
|
+
/**
|
|
34
|
+
* An optional initial option.
|
|
35
|
+
*/
|
|
36
|
+
readonly initialOption?: string;
|
|
37
|
+
/**
|
|
38
|
+
* A handler called when the option is changed.
|
|
39
|
+
*/
|
|
40
|
+
readonly onChange?: (option: string) => void;
|
|
41
|
+
/**
|
|
42
|
+
* Alternative text shown when the user hovers over the input.
|
|
43
|
+
*/
|
|
44
|
+
readonly alt?: string;
|
|
45
|
+
/**
|
|
46
|
+
* An extra CSS class name for the component.
|
|
47
|
+
*/
|
|
48
|
+
readonly className?: string;
|
|
49
|
+
ref?: React.RefObject<HTMLSelectElement | null>;
|
|
50
|
+
}) => {
|
|
51
|
+
const [option, setOption] = useState(initialOption ?? '');
|
|
52
|
+
const handleChange = useCallback(
|
|
53
|
+
({target: {value}}: React.ChangeEvent<HTMLSelectElement>) => {
|
|
54
|
+
setOption(value);
|
|
55
|
+
onChange?.(value);
|
|
56
|
+
},
|
|
57
|
+
[onChange],
|
|
58
|
+
);
|
|
59
|
+
return (
|
|
60
|
+
<select
|
|
61
|
+
className={classNames(select, className)}
|
|
62
|
+
onChange={handleChange}
|
|
63
|
+
title={alt}
|
|
64
|
+
ref={ref}
|
|
65
|
+
>
|
|
66
|
+
{Object.entries(options).map(([eachOption, label]) => (
|
|
67
|
+
<option
|
|
68
|
+
key={eachOption}
|
|
69
|
+
value={eachOption}
|
|
70
|
+
{...(eachOption === option ? {selected: true} : {})}
|
|
71
|
+
>
|
|
72
|
+
{label}
|
|
73
|
+
</option>
|
|
74
|
+
))}
|
|
75
|
+
</select>
|
|
76
|
+
);
|
|
77
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import {style} from '@vanilla-extract/css';
|
|
2
|
+
import {colors} from '../../css/colors.css';
|
|
3
|
+
import {dimensions} from '../../css/dimensions.css';
|
|
4
|
+
|
|
5
|
+
export const wrapper = style({
|
|
6
|
+
flexShrink: 0,
|
|
7
|
+
alignSelf: 'center',
|
|
8
|
+
position: 'relative',
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
export const wrapperWithIcon = style({});
|
|
12
|
+
|
|
13
|
+
export const input = style({
|
|
14
|
+
borderRadius: dimensions.radius,
|
|
15
|
+
padding: '0.5rem',
|
|
16
|
+
outlineOffset: '2px',
|
|
17
|
+
color: 'inherit',
|
|
18
|
+
transition: 'background-color 0.1s,border-color 0.1s',
|
|
19
|
+
boxShadow: colors.shadow + ' inset',
|
|
20
|
+
border: colors.border,
|
|
21
|
+
backgroundColor: colors.background,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
export const inputWithIcon = style({
|
|
25
|
+
textIndent: `calc(${dimensions.icon} * 1.3)`,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
export const icon = style({
|
|
29
|
+
position: 'absolute',
|
|
30
|
+
left: `calc(${dimensions.icon} * .5)`,
|
|
31
|
+
top: `calc(${dimensions.icon} * .65)`,
|
|
32
|
+
color: colors.foregroundDim,
|
|
33
|
+
backgroundColor: colors.background,
|
|
34
|
+
borderRight: `calc(${dimensions.icon} * .25) solid ${colors.background}`,
|
|
35
|
+
boxSizing: 'content-box',
|
|
36
|
+
});
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import {useCallback, useState, type ComponentType} from 'react';
|
|
2
|
+
import {classNames} from '../../common/functions.tsx';
|
|
3
|
+
import {iconSize} from '../../css/dimensions.css.ts';
|
|
4
|
+
import {
|
|
5
|
+
icon,
|
|
6
|
+
input,
|
|
7
|
+
inputWithIcon,
|
|
8
|
+
wrapper,
|
|
9
|
+
wrapperWithIcon,
|
|
10
|
+
} from './index.css.ts';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The `TextInput` component displays a managed text input with an existing
|
|
14
|
+
* value.
|
|
15
|
+
*
|
|
16
|
+
* @param props The props for the component.
|
|
17
|
+
* @returns The TextInput component.
|
|
18
|
+
* @example
|
|
19
|
+
* ```tsx
|
|
20
|
+
* <TextInput
|
|
21
|
+
* initialText="42"
|
|
22
|
+
* onChange={(value) => console.log(value)}
|
|
23
|
+
* />
|
|
24
|
+
* ```
|
|
25
|
+
* This example shows the TextInput component.
|
|
26
|
+
* @example
|
|
27
|
+
* ```tsx
|
|
28
|
+
* <TextInput icon={Lucide.Search} placeholder="Search..." />
|
|
29
|
+
* ```
|
|
30
|
+
* This example shows the TextInput component with an inset icon and
|
|
31
|
+
* placeholder.
|
|
32
|
+
* @icon Lucide.TextCursorInput
|
|
33
|
+
*/
|
|
34
|
+
export const TextInput = ({
|
|
35
|
+
initialText,
|
|
36
|
+
placeholder,
|
|
37
|
+
onChange,
|
|
38
|
+
icon: Icon,
|
|
39
|
+
alt,
|
|
40
|
+
className,
|
|
41
|
+
ref,
|
|
42
|
+
}: {
|
|
43
|
+
/**
|
|
44
|
+
* An optional initial text value.
|
|
45
|
+
*/
|
|
46
|
+
readonly initialText?: string;
|
|
47
|
+
/**
|
|
48
|
+
* An optional placeholder string.
|
|
49
|
+
*/
|
|
50
|
+
readonly placeholder?: string;
|
|
51
|
+
/**
|
|
52
|
+
* A handler called when the text is changed.
|
|
53
|
+
*/
|
|
54
|
+
readonly onChange?: (text: string) => void;
|
|
55
|
+
/**
|
|
56
|
+
* An optional component which renders an icon on the left of the input, and
|
|
57
|
+
* which must accept a className prop.
|
|
58
|
+
*/
|
|
59
|
+
readonly icon?: ComponentType<{className?: string}>;
|
|
60
|
+
/**
|
|
61
|
+
* Alternative text shown when the user hovers over the input.
|
|
62
|
+
*/
|
|
63
|
+
readonly alt?: string;
|
|
64
|
+
/**
|
|
65
|
+
* An extra CSS class name for the component.
|
|
66
|
+
*/
|
|
67
|
+
readonly className?: string;
|
|
68
|
+
ref?: React.RefObject<HTMLInputElement | null>;
|
|
69
|
+
}) => {
|
|
70
|
+
const [text, setText] = useState(initialText ?? '');
|
|
71
|
+
const handleChange = useCallback(
|
|
72
|
+
({target: {value}}: React.ChangeEvent<HTMLInputElement>) => {
|
|
73
|
+
setText(value);
|
|
74
|
+
onChange?.(value);
|
|
75
|
+
},
|
|
76
|
+
[onChange],
|
|
77
|
+
);
|
|
78
|
+
return (
|
|
79
|
+
<div className={classNames(wrapper, Icon && wrapperWithIcon)}>
|
|
80
|
+
{Icon ? <Icon className={classNames(iconSize, icon)} /> : null}
|
|
81
|
+
<input
|
|
82
|
+
value={text}
|
|
83
|
+
placeholder={placeholder}
|
|
84
|
+
className={classNames(input, Icon && inputWithIcon, className)}
|
|
85
|
+
onChange={handleChange}
|
|
86
|
+
title={alt}
|
|
87
|
+
ref={ref}
|
|
88
|
+
/>
|
|
89
|
+
</div>
|
|
90
|
+
);
|
|
91
|
+
};
|
package/src/css/colors.css.ts
CHANGED
|
@@ -20,9 +20,11 @@ import {
|
|
|
20
20
|
* - `background2`
|
|
21
21
|
* - `backgroundHaze`
|
|
22
22
|
* - `backgroundHover`
|
|
23
|
+
* - `backgroundExtreme`
|
|
23
24
|
* - `foreground`
|
|
24
25
|
* - `foregroundBright`
|
|
25
26
|
* - `foregroundDim`
|
|
27
|
+
* - `foregroundExtreme`
|
|
26
28
|
* - `border`
|
|
27
29
|
* - `shadow`
|
|
28
30
|
*
|
|
@@ -72,9 +74,11 @@ export const colors = createThemeContract({
|
|
|
72
74
|
background2: null,
|
|
73
75
|
backgroundHaze: null,
|
|
74
76
|
backgroundHover: null,
|
|
77
|
+
backgroundExtreme: null,
|
|
75
78
|
foreground: null,
|
|
76
79
|
foregroundBright: null,
|
|
77
80
|
foregroundDim: null,
|
|
81
|
+
foregroundExtreme: null,
|
|
78
82
|
border: null,
|
|
79
83
|
shadow: null,
|
|
80
84
|
});
|
|
@@ -97,9 +101,11 @@ export const colorsLight = createTheme(colors, {
|
|
|
97
101
|
background2: `oklch(95% .01 ${colors.backgroundHue})`,
|
|
98
102
|
backgroundHaze: `oklch(99% .01 ${colors.backgroundHue} / .5)`,
|
|
99
103
|
backgroundHover: `oklch(90% .01 ${colors.backgroundHue})`,
|
|
104
|
+
backgroundExtreme: '#fff',
|
|
100
105
|
foreground: `oklch(50% .01 ${colors.accentHue})`,
|
|
101
106
|
foregroundBright: `oklch(10% .01 ${colors.accentHue})`,
|
|
102
107
|
foregroundDim: `oklch(60% .01 ${colors.accentHue})`,
|
|
108
|
+
foregroundExtreme: '#000',
|
|
103
109
|
border: `1px solid oklch(90% .01 ${colors.backgroundHue})`,
|
|
104
110
|
shadow: '0 1px 4px 0 hsl(0 0 20 / .1)',
|
|
105
111
|
});
|
|
@@ -113,9 +119,11 @@ export const colorsDark = createTheme(colors, {
|
|
|
113
119
|
background2: `oklch(15% .01 ${colors.backgroundHue})`,
|
|
114
120
|
backgroundHaze: `oklch(21% 0% ${colors.backgroundHue} / .5)`,
|
|
115
121
|
backgroundHover: `oklch(25% .01 ${colors.backgroundHue})`,
|
|
122
|
+
backgroundExtreme: '#000',
|
|
116
123
|
foreground: `oklch(85% .01 ${colors.accentHue})`,
|
|
117
124
|
foregroundBright: `oklch(95% .01 ${colors.accentHue})`,
|
|
118
125
|
foregroundDim: `oklch(60% .01 ${colors.accentHue})`,
|
|
126
|
+
foregroundExtreme: '#fff',
|
|
119
127
|
border: `1px solid oklch(30% .01 ${colors.backgroundHue})`,
|
|
120
128
|
shadow: '0 1px 4px 0 #000',
|
|
121
129
|
});
|
package/src/index.ts
CHANGED
|
@@ -8,8 +8,10 @@ export {Hr} from './components/Hr/index.tsx';
|
|
|
8
8
|
export {Image} from './components/Image/index.tsx';
|
|
9
9
|
export {Metric} from './components/Metric/index.tsx';
|
|
10
10
|
export {Row} from './components/Row/index.tsx';
|
|
11
|
+
export {Select} from './components/Select/index.tsx';
|
|
11
12
|
export {Summary} from './components/Summary/index.tsx';
|
|
12
13
|
export {Tag} from './components/Tag/index.tsx';
|
|
14
|
+
export {TextInput} from './components/TextInput/index.tsx';
|
|
13
15
|
|
|
14
16
|
export {classNames} from './common/functions.tsx';
|
|
15
17
|
export {useDark} from './stores/LocalStore.tsx';
|