@ecohouse/ui 0.1.6 → 0.1.8
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 +13 -12
- package/dist/index.cjs +699 -102
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +137 -3
- package/dist/index.d.ts +137 -3
- package/dist/index.js +690 -103
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/CommentCard/CommentCard.stories.tsx +31 -0
- package/src/components/CommentCard/CommentCard.tsx +209 -0
- package/src/components/CommentCard/index.ts +2 -0
- package/src/components/LanguageSwitcher/LanguageSwitcher.stories.tsx +52 -0
- package/src/components/LanguageSwitcher/LanguageSwitcher.tsx +287 -0
- package/src/components/LanguageSwitcher/index.ts +2 -0
- package/src/components/RatingInput/RatingInput.stories.tsx +41 -0
- package/src/components/RatingInput/RatingInput.tsx +168 -0
- package/src/components/RatingInput/index.ts +2 -0
- package/src/components/index.ts +9 -0
- package/src/icons/Globe/GlobeIcon.tsx +20 -0
- package/src/icons/Globe/GlobeIcon.web.tsx +26 -0
- package/src/icons/Globe/globePath.ts +3 -0
- package/src/icons/Globe/index.ts +2 -0
- package/src/icons/Star/StarIcon.tsx +35 -0
- package/src/icons/Star/StarIcon.web.tsx +41 -0
- package/src/icons/Star/index.ts +2 -0
- package/src/icons/Star/starPath.ts +3 -0
- package/src/icons/StarFilled/StarFilledIcon.tsx +28 -0
- package/src/icons/StarFilled/StarFilledIcon.web.tsx +34 -0
- package/src/icons/StarFilled/index.ts +1 -0
- package/src/icons/index.ts +4 -0
- package/src/icons/registry.ts +9 -1
- package/src/index.ts +22 -1
- package/src/theme/index.ts +3 -0
- package/src/theme/typography.ts +50 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { forwardRef, useMemo, useRef, useState, type ComponentRef } from "react";
|
|
2
|
+
import {
|
|
3
|
+
Pressable,
|
|
4
|
+
StyleSheet,
|
|
5
|
+
Text,
|
|
6
|
+
View,
|
|
7
|
+
type PressableProps,
|
|
8
|
+
type StyleProp,
|
|
9
|
+
type TextStyle,
|
|
10
|
+
type ViewProps,
|
|
11
|
+
type ViewStyle,
|
|
12
|
+
} from "react-native";
|
|
13
|
+
import { StarFilledIcon, StarIcon } from "../../icons";
|
|
14
|
+
import { colors, ratingTypography } from "../../theme";
|
|
15
|
+
import { mergeRefs } from "../../utils/mergeRefs";
|
|
16
|
+
import { useApplyWebClassName } from "../../utils/useApplyWebClassName";
|
|
17
|
+
|
|
18
|
+
const STAR_COUNT = 5;
|
|
19
|
+
const BASE_ITEM_SIZE = 16;
|
|
20
|
+
const ICON_WIDTH_RATIO = 12.57 / BASE_ITEM_SIZE;
|
|
21
|
+
const ICON_HEIGHT_RATIO = 11.98 / BASE_ITEM_SIZE;
|
|
22
|
+
const STAR_GAP_RATIO = 2 / BASE_ITEM_SIZE;
|
|
23
|
+
|
|
24
|
+
export interface RatingInputProps extends Omit<ViewProps, "style" | "children"> {
|
|
25
|
+
value?: number;
|
|
26
|
+
defaultValue?: number;
|
|
27
|
+
onValueChange?: (value: number) => void;
|
|
28
|
+
showValue?: boolean;
|
|
29
|
+
precision?: number;
|
|
30
|
+
/** Star item size. Glyph dimensions and default spacing scale with it. */
|
|
31
|
+
size?: number;
|
|
32
|
+
/** Overrides the proportional spacing between star items. */
|
|
33
|
+
starGap?: number;
|
|
34
|
+
readOnly?: boolean;
|
|
35
|
+
disabled?: boolean;
|
|
36
|
+
style?: StyleProp<ViewStyle>;
|
|
37
|
+
valueStyle?: StyleProp<TextStyle>;
|
|
38
|
+
className?: string;
|
|
39
|
+
hitSlop?: PressableProps["hitSlop"];
|
|
40
|
+
accessibilityLabel?: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function clamp(value: number) {
|
|
44
|
+
return Math.max(0, Math.min(value, STAR_COUNT));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export const RatingInput = forwardRef<ComponentRef<typeof View>, RatingInputProps>(
|
|
48
|
+
function RatingInput(
|
|
49
|
+
{
|
|
50
|
+
value,
|
|
51
|
+
defaultValue = 0,
|
|
52
|
+
onValueChange,
|
|
53
|
+
showValue = true,
|
|
54
|
+
precision = 1,
|
|
55
|
+
size = 20,
|
|
56
|
+
starGap,
|
|
57
|
+
readOnly = false,
|
|
58
|
+
disabled = false,
|
|
59
|
+
style,
|
|
60
|
+
valueStyle,
|
|
61
|
+
className,
|
|
62
|
+
hitSlop = 6,
|
|
63
|
+
accessibilityLabel,
|
|
64
|
+
...rest
|
|
65
|
+
},
|
|
66
|
+
forwardedRef,
|
|
67
|
+
) {
|
|
68
|
+
const containerRef = useRef<ComponentRef<typeof View>>(null);
|
|
69
|
+
const setContainerRef = useMemo(() => mergeRefs(containerRef, forwardedRef), [forwardedRef]);
|
|
70
|
+
const isControlled = value !== undefined;
|
|
71
|
+
const [uncontrolledValue, setUncontrolledValue] = useState(() => clamp(defaultValue));
|
|
72
|
+
const selectedValue = clamp(isControlled ? value : uncontrolledValue);
|
|
73
|
+
const selectedStarCount = Math.round(selectedValue);
|
|
74
|
+
const iconWidth = size * ICON_WIDTH_RATIO;
|
|
75
|
+
const iconHeight = size * ICON_HEIGHT_RATIO;
|
|
76
|
+
const resolvedStarGap = starGap ?? size * STAR_GAP_RATIO;
|
|
77
|
+
const resolvedAccessibilityLabel =
|
|
78
|
+
accessibilityLabel ?? (readOnly ? `${selectedValue} out of ${STAR_COUNT} stars` : "Rating");
|
|
79
|
+
|
|
80
|
+
useApplyWebClassName(containerRef, className);
|
|
81
|
+
|
|
82
|
+
const selectValue = (nextValue: number) => {
|
|
83
|
+
if (disabled || nextValue === selectedValue) return;
|
|
84
|
+
if (!isControlled) setUncontrolledValue(nextValue);
|
|
85
|
+
onValueChange?.(nextValue);
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
<View
|
|
90
|
+
{...rest}
|
|
91
|
+
ref={setContainerRef}
|
|
92
|
+
style={[styles.root, disabled && styles.disabled, style]}
|
|
93
|
+
>
|
|
94
|
+
{showValue ? (
|
|
95
|
+
<Text numberOfLines={1} style={[styles.value, valueStyle]}>
|
|
96
|
+
{selectedValue.toFixed(precision)}
|
|
97
|
+
</Text>
|
|
98
|
+
) : null}
|
|
99
|
+
|
|
100
|
+
<View
|
|
101
|
+
accessibilityRole={readOnly ? "image" : "radiogroup"}
|
|
102
|
+
accessibilityLabel={resolvedAccessibilityLabel}
|
|
103
|
+
accessibilityState={{ disabled }}
|
|
104
|
+
style={[styles.stars, { gap: resolvedStarGap }]}
|
|
105
|
+
>
|
|
106
|
+
{Array.from({ length: STAR_COUNT }, (_, index) => {
|
|
107
|
+
const starValue = index + 1;
|
|
108
|
+
const isSelected = starValue <= selectedStarCount;
|
|
109
|
+
const icon = isSelected ? (
|
|
110
|
+
<StarFilledIcon size={iconWidth} height={iconHeight} />
|
|
111
|
+
) : (
|
|
112
|
+
<StarIcon size={iconWidth} height={iconHeight} />
|
|
113
|
+
);
|
|
114
|
+
const itemStyle = [styles.starItem, { width: size, height: size }];
|
|
115
|
+
|
|
116
|
+
if (readOnly) {
|
|
117
|
+
return (
|
|
118
|
+
<View key={starValue} style={itemStyle}>
|
|
119
|
+
{icon}
|
|
120
|
+
</View>
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return (
|
|
125
|
+
<Pressable
|
|
126
|
+
key={starValue}
|
|
127
|
+
disabled={disabled}
|
|
128
|
+
hitSlop={hitSlop}
|
|
129
|
+
onPress={() => selectValue(starValue)}
|
|
130
|
+
accessibilityRole="radio"
|
|
131
|
+
accessibilityLabel={`${starValue} star${starValue === 1 ? "" : "s"}`}
|
|
132
|
+
accessibilityState={{ checked: isSelected, disabled }}
|
|
133
|
+
style={itemStyle}
|
|
134
|
+
>
|
|
135
|
+
{icon}
|
|
136
|
+
</Pressable>
|
|
137
|
+
);
|
|
138
|
+
})}
|
|
139
|
+
</View>
|
|
140
|
+
</View>
|
|
141
|
+
);
|
|
142
|
+
},
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
const styles = StyleSheet.create({
|
|
146
|
+
root: {
|
|
147
|
+
flexDirection: "row",
|
|
148
|
+
alignItems: "center",
|
|
149
|
+
flexWrap: "nowrap",
|
|
150
|
+
alignSelf: "flex-start",
|
|
151
|
+
gap: 16,
|
|
152
|
+
},
|
|
153
|
+
stars: {
|
|
154
|
+
flexDirection: "row",
|
|
155
|
+
alignItems: "center",
|
|
156
|
+
},
|
|
157
|
+
starItem: {
|
|
158
|
+
alignItems: "center",
|
|
159
|
+
justifyContent: "center",
|
|
160
|
+
},
|
|
161
|
+
value: {
|
|
162
|
+
...ratingTypography,
|
|
163
|
+
color: colors.white,
|
|
164
|
+
},
|
|
165
|
+
disabled: {
|
|
166
|
+
opacity: 0.5,
|
|
167
|
+
},
|
|
168
|
+
});
|
package/src/components/index.ts
CHANGED
|
@@ -10,6 +10,9 @@ export type { CounterProps } from "./Counter";
|
|
|
10
10
|
export { SegmentedToggle } from "./SegmentedToggle";
|
|
11
11
|
export type { SegmentedToggleOption, SegmentedToggleProps } from "./SegmentedToggle";
|
|
12
12
|
|
|
13
|
+
export { LanguageSwitcher, defaultLanguageOptions } from "./LanguageSwitcher";
|
|
14
|
+
export type { LanguageOption, LanguageSwitcherProps } from "./LanguageSwitcher";
|
|
15
|
+
|
|
13
16
|
export { StatCard } from "./StatCard";
|
|
14
17
|
export type { StatCardProps } from "./StatCard";
|
|
15
18
|
|
|
@@ -38,3 +41,9 @@ export type { TextareaProps } from "./Textarea";
|
|
|
38
41
|
|
|
39
42
|
export { Toggle } from "./Toggle";
|
|
40
43
|
export type { ToggleProps } from "./Toggle";
|
|
44
|
+
|
|
45
|
+
export { RatingInput } from "./RatingInput";
|
|
46
|
+
export type { RatingInputProps } from "./RatingInput";
|
|
47
|
+
|
|
48
|
+
export { CommentCard } from "./CommentCard";
|
|
49
|
+
export type { CommentCardProps } from "./CommentCard";
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import Svg, { Path } from "react-native-svg";
|
|
2
|
+
import { colors } from "../../theme";
|
|
3
|
+
import type { IconProps } from "../types";
|
|
4
|
+
import { GLOBE_PATH } from "./globePath";
|
|
5
|
+
|
|
6
|
+
export function GlobeIcon({ size = 20, color = colors.primary, strokeWidth = 2 }: IconProps) {
|
|
7
|
+
return (
|
|
8
|
+
<Svg width={size} height={size} viewBox="0 0 20 20" fill="none">
|
|
9
|
+
<Path
|
|
10
|
+
d={GLOBE_PATH}
|
|
11
|
+
stroke={color}
|
|
12
|
+
strokeWidth={strokeWidth}
|
|
13
|
+
strokeLinecap="round"
|
|
14
|
+
strokeLinejoin="round"
|
|
15
|
+
/>
|
|
16
|
+
</Svg>
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { GLOBE_PATH } from "./globePath";
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { colors } from "../../theme";
|
|
2
|
+
import type { IconProps } from "../types";
|
|
3
|
+
import { GLOBE_PATH } from "./globePath";
|
|
4
|
+
|
|
5
|
+
export function GlobeIcon({ size = 20, color = colors.primary, strokeWidth = 2 }: IconProps) {
|
|
6
|
+
return (
|
|
7
|
+
<svg
|
|
8
|
+
width={size}
|
|
9
|
+
height={size}
|
|
10
|
+
viewBox="0 0 20 20"
|
|
11
|
+
fill="none"
|
|
12
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
13
|
+
aria-hidden
|
|
14
|
+
>
|
|
15
|
+
<path
|
|
16
|
+
d={GLOBE_PATH}
|
|
17
|
+
stroke={color}
|
|
18
|
+
strokeWidth={strokeWidth}
|
|
19
|
+
strokeLinecap="round"
|
|
20
|
+
strokeLinejoin="round"
|
|
21
|
+
/>
|
|
22
|
+
</svg>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export { GLOBE_PATH } from "./globePath";
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
/** Globe paths — 20×20 viewBox. */
|
|
2
|
+
export const GLOBE_PATH =
|
|
3
|
+
"M18.3333 10C18.3333 14.6024 14.6024 18.3333 10 18.3333M18.3333 10C18.3333 5.39763 14.6024 1.66667 10 1.66667M18.3333 10H1.66667M10 18.3333C5.39763 18.3333 1.66667 14.6024 1.66667 10M10 18.3333C12.0833 16.0511 13.2675 13.0836 13.3333 10C13.2675 6.91643 12.0833 3.94892 10 1.66667M10 18.3333C7.91667 16.0511 6.73248 13.0836 6.66667 10C6.73248 6.91643 7.91667 3.94892 10 1.66667M1.66667 10C1.66667 5.39763 5.39763 1.66667 10 1.66667";
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import Svg, { Path } from "react-native-svg";
|
|
2
|
+
import { colors } from "../../theme";
|
|
3
|
+
import { STAR_PATH } from "./starPath";
|
|
4
|
+
import type { IconProps } from "../types";
|
|
5
|
+
|
|
6
|
+
export interface StarIconProps extends IconProps {
|
|
7
|
+
active?: boolean;
|
|
8
|
+
height?: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** Native — active is solid orange; inactive is a grey outline. */
|
|
12
|
+
export function StarIcon({
|
|
13
|
+
active = false,
|
|
14
|
+
size = 28,
|
|
15
|
+
height,
|
|
16
|
+
color,
|
|
17
|
+
strokeWidth = 2,
|
|
18
|
+
}: StarIconProps) {
|
|
19
|
+
const resolvedColor = color ?? (active ? "#E38E5E" : colors.grey150);
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<Svg width={size} height={height ?? (size * 26) / 28} viewBox="0 0 28 26" fill="none">
|
|
23
|
+
<Path
|
|
24
|
+
d={STAR_PATH}
|
|
25
|
+
fill={active ? resolvedColor : "none"}
|
|
26
|
+
stroke={resolvedColor}
|
|
27
|
+
strokeWidth={strokeWidth}
|
|
28
|
+
strokeLinecap="round"
|
|
29
|
+
strokeLinejoin="round"
|
|
30
|
+
/>
|
|
31
|
+
</Svg>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export { STAR_PATH } from "./starPath";
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { colors } from "../../theme";
|
|
2
|
+
import { STAR_PATH } from "./starPath";
|
|
3
|
+
import type { IconProps } from "../types";
|
|
4
|
+
|
|
5
|
+
export interface StarIconProps extends IconProps {
|
|
6
|
+
active?: boolean;
|
|
7
|
+
height?: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/** Web / Storybook — active is solid orange; inactive is a grey outline. */
|
|
11
|
+
export function StarIcon({
|
|
12
|
+
active = false,
|
|
13
|
+
size = 28,
|
|
14
|
+
height,
|
|
15
|
+
color,
|
|
16
|
+
strokeWidth = 2,
|
|
17
|
+
}: StarIconProps) {
|
|
18
|
+
const resolvedColor = color ?? (active ? "#E38E5E" : colors.grey150);
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<svg
|
|
22
|
+
width={size}
|
|
23
|
+
height={height ?? (size * 26) / 28}
|
|
24
|
+
viewBox="0 0 28 26"
|
|
25
|
+
fill="none"
|
|
26
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
27
|
+
aria-hidden
|
|
28
|
+
>
|
|
29
|
+
<path
|
|
30
|
+
d={STAR_PATH}
|
|
31
|
+
fill={active ? resolvedColor : "none"}
|
|
32
|
+
stroke={resolvedColor}
|
|
33
|
+
strokeWidth={strokeWidth}
|
|
34
|
+
strokeLinecap="round"
|
|
35
|
+
strokeLinejoin="round"
|
|
36
|
+
/>
|
|
37
|
+
</svg>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export { STAR_PATH } from "./starPath";
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
/** Star icon path — 28×26 viewBox. */
|
|
2
|
+
export const STAR_PATH =
|
|
3
|
+
"M12.6112 2.09824C12.9186 1.47565 13.0722 1.16436 13.2808 1.0649C13.4623 0.978367 13.6732 0.978367 13.8546 1.0649C14.0632 1.16436 14.2169 1.47565 14.5242 2.09824L17.4398 8.00486C17.5305 8.18866 17.5759 8.28056 17.6422 8.35192C17.7009 8.41509 17.7713 8.46628 17.8495 8.50264C17.9378 8.54371 18.0392 8.55854 18.242 8.58818L24.7637 9.54142C25.4505 9.6418 25.7938 9.69199 25.9528 9.85973C26.091 10.0057 26.156 10.2062 26.1297 10.4055C26.0995 10.6346 25.8509 10.8767 25.3537 11.361L20.6363 15.9557C20.4893 16.0989 20.4157 16.1706 20.3683 16.2558C20.3263 16.3312 20.2993 16.4141 20.2889 16.4998C20.2772 16.5966 20.2945 16.6978 20.3292 16.9001L21.4423 23.39C21.5597 24.0745 21.6184 24.4167 21.5081 24.6198C21.4121 24.7965 21.2415 24.9205 21.0438 24.9571C20.8165 24.9992 20.5092 24.8376 19.8945 24.5144L14.0642 21.4483C13.8826 21.3527 13.7917 21.305 13.696 21.2862C13.6113 21.2696 13.5242 21.2696 13.4394 21.2862C13.3437 21.305 13.2529 21.3527 13.0713 21.4483L7.24094 24.5144C6.62626 24.8376 6.31892 24.9992 6.09167 24.9571C5.89395 24.9205 5.72334 24.7965 5.62736 24.6198C5.51704 24.4167 5.57574 24.0745 5.69314 23.39L6.80622 16.9001C6.84092 16.6978 6.85828 16.5966 6.84653 16.4998C6.83614 16.4141 6.80919 16.3312 6.76718 16.2558C6.71974 16.1706 6.64621 16.0989 6.49916 15.9557L1.78179 11.361C1.28459 10.8767 1.03599 10.6346 1.00574 10.4055C0.979423 10.2062 1.04445 10.0057 1.18271 9.85973C1.34162 9.69199 1.685 9.6418 2.37177 9.54142L8.89346 8.58818C9.09627 8.55854 9.19768 8.54371 9.286 8.50264C9.36419 8.46628 9.43459 8.41509 9.49329 8.35192C9.55958 8.28056 9.60495 8.18866 9.69567 8.00486L12.6112 2.09824Z";
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import Svg, { Path } from "react-native-svg";
|
|
2
|
+
import { STAR_PATH } from "../Star/starPath";
|
|
3
|
+
import type { IconProps } from "../types";
|
|
4
|
+
|
|
5
|
+
interface StarFilledIconProps extends IconProps {
|
|
6
|
+
height?: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** Native — supplied solid orange 28×26 star icon. */
|
|
10
|
+
export function StarFilledIcon({
|
|
11
|
+
size = 28,
|
|
12
|
+
height,
|
|
13
|
+
color = "#E38E5E",
|
|
14
|
+
strokeWidth = 2,
|
|
15
|
+
}: StarFilledIconProps) {
|
|
16
|
+
return (
|
|
17
|
+
<Svg width={size} height={height ?? (size * 26) / 28} viewBox="0 0 28 26" fill={color}>
|
|
18
|
+
<Path
|
|
19
|
+
d={STAR_PATH}
|
|
20
|
+
fill={color}
|
|
21
|
+
stroke={color}
|
|
22
|
+
strokeWidth={strokeWidth}
|
|
23
|
+
strokeLinecap="round"
|
|
24
|
+
strokeLinejoin="round"
|
|
25
|
+
/>
|
|
26
|
+
</Svg>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { STAR_PATH } from "../Star/starPath";
|
|
2
|
+
import type { IconProps } from "../types";
|
|
3
|
+
|
|
4
|
+
interface StarFilledIconProps extends IconProps {
|
|
5
|
+
height?: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/** Web / Storybook — supplied solid orange 28×26 star icon. */
|
|
9
|
+
export function StarFilledIcon({
|
|
10
|
+
size = 28,
|
|
11
|
+
height,
|
|
12
|
+
color = "#E38E5E",
|
|
13
|
+
strokeWidth = 2,
|
|
14
|
+
}: StarFilledIconProps) {
|
|
15
|
+
return (
|
|
16
|
+
<svg
|
|
17
|
+
width={size}
|
|
18
|
+
height={height ?? (size * 26) / 28}
|
|
19
|
+
viewBox="0 0 28 26"
|
|
20
|
+
fill={color}
|
|
21
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
22
|
+
aria-hidden
|
|
23
|
+
>
|
|
24
|
+
<path
|
|
25
|
+
d={STAR_PATH}
|
|
26
|
+
fill={color}
|
|
27
|
+
stroke={color}
|
|
28
|
+
strokeWidth={strokeWidth}
|
|
29
|
+
strokeLinecap="round"
|
|
30
|
+
strokeLinejoin="round"
|
|
31
|
+
/>
|
|
32
|
+
</svg>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { StarFilledIcon } from "./StarFilledIcon";
|
package/src/icons/index.ts
CHANGED
|
@@ -19,6 +19,7 @@ export { ChevronLeftIcon } from "./ChevronLeft";
|
|
|
19
19
|
export { ClockIcon } from "./Clock";
|
|
20
20
|
export { FacebookIcon } from "./Facebook";
|
|
21
21
|
export { HeartIcon } from "./Heart";
|
|
22
|
+
export { GlobeIcon } from "./Globe";
|
|
22
23
|
export { HelpCircleIcon } from "./HelpCircle";
|
|
23
24
|
export { HomeIcon } from "./Home";
|
|
24
25
|
export { InstagramIcon } from "./Instagram";
|
|
@@ -35,6 +36,9 @@ export { SearchIcon } from "./Search";
|
|
|
35
36
|
export { SettingsIcon } from "./Settings";
|
|
36
37
|
export { ShowIcon } from "./Show";
|
|
37
38
|
export { SidebarIcon } from "./Sidebar";
|
|
39
|
+
export { StarIcon } from "./Star";
|
|
40
|
+
export { StarFilledIcon } from "./StarFilled";
|
|
38
41
|
export { UserIcon } from "./User";
|
|
39
42
|
export { UsersAltIcon } from "./UsersAlt";
|
|
40
43
|
export { VideoIcon } from "./Video";
|
|
44
|
+
export type { StarIconProps } from "./Star";
|
package/src/icons/registry.ts
CHANGED
|
@@ -12,6 +12,7 @@ import { ChevronLeftIcon } from "./ChevronLeft";
|
|
|
12
12
|
import { ClockIcon } from "./Clock";
|
|
13
13
|
import { FacebookIcon } from "./Facebook";
|
|
14
14
|
import { HeartIcon } from "./Heart";
|
|
15
|
+
import { GlobeIcon } from "./Globe";
|
|
15
16
|
import { HelpCircleIcon } from "./HelpCircle";
|
|
16
17
|
import { HomeIcon } from "./Home";
|
|
17
18
|
import { InstagramIcon } from "./Instagram";
|
|
@@ -28,6 +29,8 @@ import { SearchIcon } from "./Search";
|
|
|
28
29
|
import { SettingsIcon } from "./Settings";
|
|
29
30
|
import { ShowIcon } from "./Show";
|
|
30
31
|
import { SidebarIcon } from "./Sidebar";
|
|
32
|
+
import { StarIcon } from "./Star";
|
|
33
|
+
import { StarFilledIcon } from "./StarFilled";
|
|
31
34
|
import { UserIcon } from "./User";
|
|
32
35
|
import { UsersAltIcon } from "./UsersAlt";
|
|
33
36
|
import { VideoIcon } from "./Video";
|
|
@@ -48,6 +51,7 @@ export const icons = {
|
|
|
48
51
|
clock: ClockIcon,
|
|
49
52
|
facebook: FacebookIcon,
|
|
50
53
|
heart: HeartIcon,
|
|
54
|
+
globe: GlobeIcon,
|
|
51
55
|
helpCircle: HelpCircleIcon,
|
|
52
56
|
home: HomeIcon,
|
|
53
57
|
instagram: InstagramIcon,
|
|
@@ -64,6 +68,8 @@ export const icons = {
|
|
|
64
68
|
settings: SettingsIcon,
|
|
65
69
|
show: ShowIcon,
|
|
66
70
|
sidebar: SidebarIcon,
|
|
71
|
+
star: StarIcon,
|
|
72
|
+
starFilled: StarFilledIcon,
|
|
67
73
|
user: UserIcon,
|
|
68
74
|
usersAlt: UsersAltIcon,
|
|
69
75
|
video: VideoIcon,
|
|
@@ -86,13 +92,15 @@ export const iconGroups = {
|
|
|
86
92
|
"calendar",
|
|
87
93
|
"calendarOutline",
|
|
88
94
|
"heart",
|
|
95
|
+
"star",
|
|
96
|
+
"starFilled",
|
|
89
97
|
"minus",
|
|
90
98
|
"plus",
|
|
91
99
|
],
|
|
92
100
|
objects: ["bag", "building", "clock", "user", "usersAlt", "video"],
|
|
93
101
|
communication: ["mail", "phone"],
|
|
94
102
|
social: ["facebook", "instagram", "linkedin"],
|
|
95
|
-
interface: ["layoutGrid", "sidebar", "settings", "helpCircle", "logOut"],
|
|
103
|
+
interface: ["globe", "layoutGrid", "sidebar", "settings", "helpCircle", "logOut"],
|
|
96
104
|
} as const satisfies Record<string, readonly IconName[]>;
|
|
97
105
|
|
|
98
106
|
export type IconGroup = keyof typeof iconGroups;
|
package/src/index.ts
CHANGED
|
@@ -3,6 +3,8 @@ export {
|
|
|
3
3
|
Badge,
|
|
4
4
|
Counter,
|
|
5
5
|
SegmentedToggle,
|
|
6
|
+
LanguageSwitcher,
|
|
7
|
+
defaultLanguageOptions,
|
|
6
8
|
StatCard,
|
|
7
9
|
Button,
|
|
8
10
|
Checkbox,
|
|
@@ -11,6 +13,8 @@ export {
|
|
|
11
13
|
Select,
|
|
12
14
|
Textarea,
|
|
13
15
|
Toggle,
|
|
16
|
+
RatingInput,
|
|
17
|
+
CommentCard,
|
|
14
18
|
} from "./components";
|
|
15
19
|
export type {
|
|
16
20
|
AvatarProps,
|
|
@@ -20,6 +24,8 @@ export type {
|
|
|
20
24
|
CounterProps,
|
|
21
25
|
SegmentedToggleOption,
|
|
22
26
|
SegmentedToggleProps,
|
|
27
|
+
LanguageOption,
|
|
28
|
+
LanguageSwitcherProps,
|
|
23
29
|
StatCardProps,
|
|
24
30
|
ButtonProps,
|
|
25
31
|
ButtonSize,
|
|
@@ -38,6 +44,8 @@ export type {
|
|
|
38
44
|
SelectMultipleProps,
|
|
39
45
|
TextareaProps,
|
|
40
46
|
ToggleProps,
|
|
47
|
+
RatingInputProps,
|
|
48
|
+
CommentCardProps,
|
|
41
49
|
} from "./components";
|
|
42
50
|
|
|
43
51
|
export { MenuItem } from "./primitives";
|
|
@@ -64,6 +72,7 @@ export {
|
|
|
64
72
|
ClockIcon,
|
|
65
73
|
FacebookIcon,
|
|
66
74
|
HeartIcon,
|
|
75
|
+
GlobeIcon,
|
|
67
76
|
HelpCircleIcon,
|
|
68
77
|
HomeIcon,
|
|
69
78
|
InstagramIcon,
|
|
@@ -80,11 +89,20 @@ export {
|
|
|
80
89
|
SettingsIcon,
|
|
81
90
|
ShowIcon,
|
|
82
91
|
SidebarIcon,
|
|
92
|
+
StarIcon,
|
|
93
|
+
StarFilledIcon,
|
|
83
94
|
UserIcon,
|
|
84
95
|
UsersAltIcon,
|
|
85
96
|
VideoIcon,
|
|
86
97
|
} from "./icons";
|
|
87
|
-
export type {
|
|
98
|
+
export type {
|
|
99
|
+
IconProps,
|
|
100
|
+
IconName,
|
|
101
|
+
IconGroup,
|
|
102
|
+
IconComponent,
|
|
103
|
+
IconByNameProps,
|
|
104
|
+
StarIconProps,
|
|
105
|
+
} from "./icons";
|
|
88
106
|
|
|
89
107
|
export {
|
|
90
108
|
colors,
|
|
@@ -93,7 +111,10 @@ export {
|
|
|
93
111
|
badgeTypography,
|
|
94
112
|
statCardTypography,
|
|
95
113
|
segmentedToggleTypography,
|
|
114
|
+
languageSwitcherTypography,
|
|
96
115
|
counterTypography,
|
|
116
|
+
ratingTypography,
|
|
117
|
+
commentCardTypography,
|
|
97
118
|
buttonTypography,
|
|
98
119
|
datePickerTypography,
|
|
99
120
|
inputTypography,
|
package/src/theme/index.ts
CHANGED
package/src/theme/typography.ts
CHANGED
|
@@ -47,6 +47,15 @@ export const segmentedToggleTypography = {
|
|
|
47
47
|
letterSpacing: 0,
|
|
48
48
|
} as const;
|
|
49
49
|
|
|
50
|
+
/** Language switcher trigger and option labels — SemiBold 14. */
|
|
51
|
+
export const languageSwitcherTypography = {
|
|
52
|
+
fontFamily: fonts.sans,
|
|
53
|
+
fontSize: 14,
|
|
54
|
+
fontWeight: "600" as const,
|
|
55
|
+
lineHeight: 19,
|
|
56
|
+
letterSpacing: 0,
|
|
57
|
+
} as const;
|
|
58
|
+
|
|
50
59
|
/** Counter value — Bold 14, line-height 100%, letter-spacing 0. */
|
|
51
60
|
export const counterTypography = {
|
|
52
61
|
fontFamily: fonts.sans,
|
|
@@ -56,6 +65,47 @@ export const counterTypography = {
|
|
|
56
65
|
letterSpacing: 0,
|
|
57
66
|
} as const;
|
|
58
67
|
|
|
68
|
+
/** Rating score — Bold 32, line-height 112%, letter-spacing 0. */
|
|
69
|
+
export const ratingTypography = {
|
|
70
|
+
fontFamily: fonts.sans,
|
|
71
|
+
fontSize: 32,
|
|
72
|
+
fontWeight: "700" as const,
|
|
73
|
+
lineHeight: 35.84,
|
|
74
|
+
letterSpacing: 0,
|
|
75
|
+
} as const;
|
|
76
|
+
|
|
77
|
+
/** Comment card identity, body, and action typography. */
|
|
78
|
+
export const commentCardTypography = {
|
|
79
|
+
name: {
|
|
80
|
+
fontFamily: fonts.sans,
|
|
81
|
+
fontSize: 16,
|
|
82
|
+
fontWeight: "600" as const,
|
|
83
|
+
lineHeight: 18,
|
|
84
|
+
letterSpacing: 0,
|
|
85
|
+
},
|
|
86
|
+
date: {
|
|
87
|
+
fontFamily: fonts.sans,
|
|
88
|
+
fontSize: 14,
|
|
89
|
+
fontWeight: "400" as const,
|
|
90
|
+
lineHeight: 16,
|
|
91
|
+
letterSpacing: 0,
|
|
92
|
+
},
|
|
93
|
+
comment: {
|
|
94
|
+
fontFamily: fonts.sans,
|
|
95
|
+
fontSize: 14,
|
|
96
|
+
fontWeight: "400" as const,
|
|
97
|
+
lineHeight: 19,
|
|
98
|
+
letterSpacing: 0,
|
|
99
|
+
},
|
|
100
|
+
action: {
|
|
101
|
+
fontFamily: fonts.sans,
|
|
102
|
+
fontSize: 12,
|
|
103
|
+
fontWeight: "700" as const,
|
|
104
|
+
lineHeight: 12,
|
|
105
|
+
letterSpacing: 0,
|
|
106
|
+
},
|
|
107
|
+
} as const;
|
|
108
|
+
|
|
59
109
|
/** Input label / field / hint typography. */
|
|
60
110
|
export const inputTypography = {
|
|
61
111
|
label: {
|