@streamplace/components 0.8.6 → 0.8.9
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/components/content-metadata/content-metadata-form.js +6 -22
- package/dist/components/content-metadata/content-rights.js +18 -47
- package/dist/components/content-metadata/content-warning-badge.js +42 -0
- package/dist/components/content-metadata/content-warnings.js +15 -48
- package/dist/components/content-metadata/index.js +3 -1
- package/dist/components/mobile-player/ui/viewer-context-menu.js +20 -13
- package/dist/components/ui/checkbox.js +6 -18
- package/dist/components/ui/dropdown.js +238 -26
- package/dist/components/ui/primitives/text.js +19 -4
- package/dist/components/ui/select.js +44 -75
- package/node-compile-cache/v22.15.0-x64-efe9a9df-0/37be0eec +0 -0
- package/package.json +2 -2
- package/src/components/content-metadata/content-metadata-form.tsx +9 -49
- package/src/components/content-metadata/content-rights.tsx +31 -56
- package/src/components/content-metadata/content-warning-badge.tsx +94 -0
- package/src/components/content-metadata/content-warnings.tsx +46 -58
- package/src/components/content-metadata/index.tsx +2 -0
- package/src/components/mobile-player/ui/viewer-context-menu.tsx +81 -26
- package/src/components/ui/checkbox.tsx +23 -21
- package/src/components/ui/dropdown.tsx +445 -75
- package/src/components/ui/primitives/text.tsx +24 -4
- package/src/components/ui/select.tsx +97 -125
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,42 +1,218 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DropdownMenuInfo = exports.DropdownMenuGroup = exports.DropdownMenuSeparator = exports.DropdownMenuLabel = exports.DropdownMenuRadioItem = exports.DropdownMenuCheckboxItem = exports.DropdownMenuItem = exports.ResponsiveDropdownMenuContent = exports.DropdownMenuContentWithoutPortal = exports.DropdownMenuContent = exports.DropdownMenuSubContent = exports.DropdownMenuSubTrigger = exports.DropdownMenuBottomSheet = exports.
|
|
3
|
+
exports.DropdownMenuInfo = exports.DropdownMenuGroup = exports.DropdownMenuSeparator = exports.DropdownMenuLabel = exports.DropdownMenuRadioItem = exports.DropdownMenuCheckboxItem = exports.DropdownMenuItem = exports.ResponsiveDropdownMenuContent = exports.DropdownMenuContentWithoutPortal = exports.DropdownMenuContent = exports.DropdownMenuSubContent = exports.DropdownMenuSubTrigger = exports.DropdownMenuBottomSheet = exports.DropdownMenuSub = exports.DropdownMenuRadioGroup = exports.DropdownMenuPortal = exports.DropdownMenuTrigger = exports.DropdownMenu = void 0;
|
|
4
4
|
exports.DropdownMenuShortcut = DropdownMenuShortcut;
|
|
5
5
|
const tslib_1 = require("tslib");
|
|
6
6
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
7
7
|
const bottom_sheet_1 = tslib_1.__importStar(require("@gorhom/bottom-sheet"));
|
|
8
8
|
const DropdownMenuPrimitive = tslib_1.__importStar(require("@rn-primitives/dropdown-menu"));
|
|
9
9
|
const lucide_react_native_1 = require("lucide-react-native");
|
|
10
|
-
const react_1 = require("react");
|
|
10
|
+
const react_1 = tslib_1.__importStar(require("react"));
|
|
11
11
|
const react_native_1 = require("react-native");
|
|
12
|
+
const react_native_reanimated_1 = tslib_1.__importStar(require("react-native-reanimated"));
|
|
13
|
+
const react_native_safe_area_context_1 = require("react-native-safe-area-context");
|
|
12
14
|
const atoms_1 = require("../../lib/theme/atoms");
|
|
13
15
|
const ui_1 = require("../../ui");
|
|
14
16
|
const text_1 = require("./primitives/text");
|
|
15
17
|
const text_2 = require("./text");
|
|
18
|
+
const NavigationStackContext = (0, react_1.createContext)(null);
|
|
19
|
+
const useNavigationStack = () => {
|
|
20
|
+
const context = (0, react_1.useContext)(NavigationStackContext);
|
|
21
|
+
return context;
|
|
22
|
+
};
|
|
23
|
+
const SubMenuContext = (0, react_1.createContext)(null);
|
|
16
24
|
exports.DropdownMenu = DropdownMenuPrimitive.Root;
|
|
17
25
|
exports.DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
|
|
18
26
|
exports.DropdownMenuPortal = DropdownMenuPrimitive.Portal;
|
|
19
|
-
exports.DropdownMenuSub = DropdownMenuPrimitive.Sub;
|
|
20
27
|
exports.DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
|
|
21
|
-
|
|
28
|
+
// Custom DropdownMenuSub that works with mobile navigation
|
|
29
|
+
exports.DropdownMenuSub = (0, react_1.forwardRef)(({ children, ...props }, ref) => {
|
|
30
|
+
const navStack = useNavigationStack();
|
|
31
|
+
const [subMenuTitle, setSubMenuTitle] = (0, react_1.useState)();
|
|
32
|
+
const renderContentRef = (0, react_1.useRef)(null);
|
|
33
|
+
const [subMenuKey, setSubMenuKey] = (0, react_1.useState)(null);
|
|
34
|
+
// If we're in a mobile navigation stack, use custom context
|
|
35
|
+
if (navStack) {
|
|
36
|
+
const trigger = () => {
|
|
37
|
+
if (renderContentRef.current) {
|
|
38
|
+
const key = `submenu-${Date.now()}`;
|
|
39
|
+
setSubMenuKey(key);
|
|
40
|
+
navStack.push({
|
|
41
|
+
key,
|
|
42
|
+
title: subMenuTitle,
|
|
43
|
+
// Store a function that always reads the latest content from the ref
|
|
44
|
+
content: (props) => {
|
|
45
|
+
const renderFn = renderContentRef.current;
|
|
46
|
+
return renderFn ? renderFn() : null;
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
const setRenderContent = (renderer) => {
|
|
52
|
+
renderContentRef.current = renderer;
|
|
53
|
+
};
|
|
54
|
+
const contextValue = react_1.default.useMemo(() => ({
|
|
55
|
+
renderContent: () => renderContentRef.current?.(),
|
|
56
|
+
setRenderContent,
|
|
57
|
+
title: subMenuTitle,
|
|
58
|
+
setTitle: setSubMenuTitle,
|
|
59
|
+
trigger,
|
|
60
|
+
key: subMenuKey,
|
|
61
|
+
}), [subMenuTitle, subMenuKey]);
|
|
62
|
+
return ((0, jsx_runtime_1.jsx)(SubMenuContext.Provider, { value: contextValue, children: children }));
|
|
63
|
+
}
|
|
64
|
+
// Web - use primitive
|
|
65
|
+
return ((0, jsx_runtime_1.jsx)(DropdownMenuPrimitive.Sub, { ref: ref, ...props, children: children }));
|
|
66
|
+
});
|
|
67
|
+
exports.DropdownMenuBottomSheet = (0, react_1.forwardRef)(function DropdownMenuBottomSheet({ overlayStyle, portalHost, children, ...rest }, _ref) {
|
|
22
68
|
// Use the primitives' context to know if open
|
|
23
|
-
const {
|
|
24
|
-
const { zero: zt } = (0, ui_1.useTheme)();
|
|
25
|
-
const snapPoints = (0, react_1.useMemo)(() => ["25%", "50%", "80%"], []);
|
|
69
|
+
const { onOpenChange } = DropdownMenuPrimitive.useRootContext();
|
|
70
|
+
const { zero: zt, theme } = (0, ui_1.useTheme)();
|
|
26
71
|
const sheetRef = (0, react_1.useRef)(null);
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
72
|
+
const { width } = (0, react_native_1.useWindowDimensions)();
|
|
73
|
+
const isWide = react_native_1.Platform.OS !== "web" && width >= 800;
|
|
74
|
+
const sheetWidth = isWide ? 450 : width;
|
|
75
|
+
const horizontalMargin = isWide ? (width - sheetWidth) / 2 : 0;
|
|
76
|
+
const insets = (0, react_native_safe_area_context_1.useSafeAreaInsets)();
|
|
77
|
+
// Navigation stack state
|
|
78
|
+
const [stack, setStack] = (0, react_1.useState)([
|
|
79
|
+
{ key: "root", content: children },
|
|
80
|
+
]);
|
|
81
|
+
// Update root content when children changes
|
|
82
|
+
react_1.default.useEffect(() => {
|
|
83
|
+
setStack((prev) => {
|
|
84
|
+
if (!Array.isArray(prev) || prev.length === 0) {
|
|
85
|
+
return [{ key: "root", content: children }];
|
|
86
|
+
}
|
|
87
|
+
// Update the root item content
|
|
88
|
+
const newStack = [...prev];
|
|
89
|
+
newStack[0] = { ...newStack[0], content: children };
|
|
90
|
+
return newStack;
|
|
91
|
+
});
|
|
92
|
+
}, [children]);
|
|
93
|
+
const slideAnim = (0, react_native_reanimated_1.useSharedValue)(0);
|
|
94
|
+
const fadeAnim = (0, react_native_reanimated_1.useSharedValue)(1);
|
|
95
|
+
const push = (item) => {
|
|
96
|
+
// First, update the stack
|
|
97
|
+
setStack((prev) => {
|
|
98
|
+
if (!Array.isArray(prev))
|
|
99
|
+
return [{ key: "root", content: children }, item];
|
|
100
|
+
return [...prev, item];
|
|
101
|
+
});
|
|
102
|
+
// Then animate from right to center with fade
|
|
103
|
+
slideAnim.value = 40;
|
|
104
|
+
fadeAnim.value = 0;
|
|
105
|
+
slideAnim.value = (0, react_native_reanimated_1.withTiming)(0, { duration: 350 });
|
|
106
|
+
fadeAnim.value = (0, react_native_reanimated_1.withTiming)(1, { duration: 350 });
|
|
107
|
+
};
|
|
108
|
+
const popStack = () => {
|
|
109
|
+
(0, react_1.startTransition)(() => {
|
|
110
|
+
setStack((prev) => {
|
|
111
|
+
if (!Array.isArray(prev) || prev.length <= 1) {
|
|
112
|
+
return [{ key: "root", content: children }];
|
|
113
|
+
}
|
|
114
|
+
return prev.slice(0, -1);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
};
|
|
118
|
+
const resetAnimationValues = () => {
|
|
119
|
+
setTimeout(() => {
|
|
120
|
+
slideAnim.value = 0;
|
|
121
|
+
fadeAnim.value = 1;
|
|
122
|
+
}, 5);
|
|
123
|
+
};
|
|
124
|
+
const pop = () => {
|
|
125
|
+
if (stack.length <= 1)
|
|
126
|
+
return;
|
|
127
|
+
// Animate out to the right with fade
|
|
128
|
+
slideAnim.value = (0, react_native_reanimated_1.withTiming)(40, { duration: 150 });
|
|
129
|
+
fadeAnim.value = (0, react_native_reanimated_1.withTiming)(0, { duration: 150 }, (finished) => {
|
|
130
|
+
if (finished) {
|
|
131
|
+
// Update stack first with startTransition for smoother render
|
|
132
|
+
(0, react_native_reanimated_1.runOnJS)(popStack)();
|
|
133
|
+
// Then reset animation position after a brief delay to ensure component has unmounted
|
|
134
|
+
(0, react_native_reanimated_1.runOnJS)(resetAnimationValues)();
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
};
|
|
138
|
+
const animatedStyle = (0, react_native_reanimated_1.useAnimatedStyle)(() => ({
|
|
139
|
+
transform: [{ translateX: slideAnim.value }],
|
|
140
|
+
opacity: fadeAnim.value,
|
|
141
|
+
}));
|
|
142
|
+
const headerAnimatedStyle = (0, react_native_reanimated_1.useAnimatedStyle)(() => ({
|
|
143
|
+
opacity: fadeAnim.value,
|
|
144
|
+
}));
|
|
145
|
+
const currentLevel = stack[stack.length - 1];
|
|
146
|
+
const isNested = stack.length > 1;
|
|
147
|
+
const onBackgroundTap = () => {
|
|
148
|
+
if (sheetRef.current)
|
|
149
|
+
sheetRef.current?.close();
|
|
150
|
+
setTimeout(() => {
|
|
151
|
+
onOpenChange?.(false);
|
|
152
|
+
}, 300);
|
|
153
|
+
};
|
|
154
|
+
// Safety check - if no current level, don't render
|
|
155
|
+
if (!currentLevel) {
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
return ((0, jsx_runtime_1.jsx)(DropdownMenuPrimitive.Portal, { hostName: portalHost, children: (0, jsx_runtime_1.jsx)(NavigationStackContext.Provider, { value: { stack, push, pop, isNested }, children: (0, jsx_runtime_1.jsxs)(bottom_sheet_1.default, { ref: sheetRef, enablePanDownToClose: true, enableDynamicSizing: true, detached: isWide, bottomInset: isWide ? 0 : 0, backdropComponent: ({ style }) => ((0, jsx_runtime_1.jsx)(react_native_1.Pressable, { style: [style, react_native_1.StyleSheet.absoluteFill], onPress: () => onBackgroundTap() })), onClose: () => onOpenChange?.(false), style: [
|
|
159
|
+
overlayStyle,
|
|
160
|
+
react_native_1.StyleSheet.flatten(rest.style),
|
|
161
|
+
isWide && { marginHorizontal: horizontalMargin },
|
|
162
|
+
], backgroundStyle: [zt.bg.popover, atoms_1.a.radius.all.md, atoms_1.a.shadows.md, atoms_1.p[1]], handleIndicatorStyle: [
|
|
163
|
+
atoms_1.a.sizes.width[12],
|
|
164
|
+
atoms_1.a.sizes.height[1],
|
|
165
|
+
zt.bg.mutedForeground,
|
|
166
|
+
], children: [isNested && ((0, jsx_runtime_1.jsx)(react_native_reanimated_1.default.View, { style: [
|
|
167
|
+
headerAnimatedStyle,
|
|
168
|
+
atoms_1.a.layout.flex.row,
|
|
169
|
+
atoms_1.a.layout.flex.alignCenter,
|
|
170
|
+
atoms_1.px[4],
|
|
171
|
+
atoms_1.pb[2],
|
|
172
|
+
{
|
|
173
|
+
borderBottomWidth: 1,
|
|
174
|
+
borderBottomColor: theme.colors.border,
|
|
175
|
+
},
|
|
176
|
+
], children: (0, jsx_runtime_1.jsxs)(react_native_1.Pressable, { onPress: pop, style: [
|
|
177
|
+
atoms_1.a.layout.flex.row,
|
|
178
|
+
atoms_1.a.layout.flex.alignCenter,
|
|
179
|
+
atoms_1.gap.all[2],
|
|
180
|
+
], hitSlop: 80, children: [(0, jsx_runtime_1.jsx)(lucide_react_native_1.ChevronLeft, { size: 20, color: theme.colors.foreground }), currentLevel?.title ? ((0, jsx_runtime_1.jsx)(text_2.Text, { size: "lg", children: currentLevel.title })) : null] }) })), (0, jsx_runtime_1.jsx)(react_native_reanimated_1.default.View, { style: animatedStyle, children: (0, jsx_runtime_1.jsx)(bottom_sheet_1.BottomSheetScrollView, { style: [atoms_1.px[4]], contentContainerStyle: {
|
|
181
|
+
paddingBottom: insets.bottom + 50,
|
|
182
|
+
overflow: "hidden",
|
|
183
|
+
}, children: stack.map((level, index) => {
|
|
184
|
+
const isCurrent = index === stack.length - 1;
|
|
185
|
+
return ((0, jsx_runtime_1.jsx)(react_native_1.View, { style: [{ display: isCurrent ? "flex" : "none" }], children: typeof level.content === "function"
|
|
186
|
+
? level.content({ pressed: true })
|
|
187
|
+
: level.content }, level.key));
|
|
188
|
+
}) }) })] }) }) }));
|
|
36
189
|
});
|
|
37
|
-
exports.DropdownMenuSubTrigger = (0, react_1.forwardRef)(({ inset, children, ...props }, ref) => {
|
|
190
|
+
exports.DropdownMenuSubTrigger = (0, react_1.forwardRef)(({ inset, children, subMenuTitle, ...props }, ref) => {
|
|
191
|
+
const navStack = useNavigationStack();
|
|
192
|
+
const subMenuContext = (0, react_1.useContext)(SubMenuContext);
|
|
193
|
+
const { icons, theme } = (0, ui_1.useTheme)();
|
|
194
|
+
// Set the title in the submenu context if provided
|
|
195
|
+
react_1.default.useEffect(() => {
|
|
196
|
+
if (subMenuContext && subMenuTitle) {
|
|
197
|
+
subMenuContext.setTitle(subMenuTitle);
|
|
198
|
+
}
|
|
199
|
+
}, [subMenuContext, subMenuTitle]);
|
|
200
|
+
// If we're in a navigation stack (mobile bottom sheet), handle differently
|
|
201
|
+
if (navStack && subMenuContext) {
|
|
202
|
+
return ((0, jsx_runtime_1.jsx)(react_native_1.Pressable, { onPress: () => {
|
|
203
|
+
subMenuContext.trigger();
|
|
204
|
+
}, ...props, children: (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [
|
|
205
|
+
inset && atoms_1.gap[2],
|
|
206
|
+
atoms_1.layout.flex.row,
|
|
207
|
+
atoms_1.layout.flex.alignCenter,
|
|
208
|
+
atoms_1.a.radius.all.sm,
|
|
209
|
+
atoms_1.py[1],
|
|
210
|
+
atoms_1.pl[2],
|
|
211
|
+
atoms_1.pr[2],
|
|
212
|
+
], children: [typeof children === "function" ? (children({ pressed: true })) : typeof children === "string" ? ((0, jsx_runtime_1.jsx)(text_2.Text, { children: children })) : (children), (0, jsx_runtime_1.jsx)(react_native_1.View, { style: [atoms_1.a.layout.position.absolute, atoms_1.a.position.right[1]], children: (0, jsx_runtime_1.jsx)(lucide_react_native_1.ChevronRight, { size: 18, color: icons.color.muted }) })] }) }));
|
|
213
|
+
}
|
|
214
|
+
// Web behavior - use primitive
|
|
38
215
|
const { open } = DropdownMenuPrimitive.useSubContext();
|
|
39
|
-
const { icons } = (0, ui_1.useTheme)();
|
|
40
216
|
const Icon = react_native_1.Platform.OS === "web" ? lucide_react_native_1.ChevronRight : open ? lucide_react_native_1.ChevronUp : lucide_react_native_1.ChevronDown;
|
|
41
217
|
return ((0, jsx_runtime_1.jsx)(text_1.TextContext.Provider, { value: (0, text_1.objectFromObjects)([
|
|
42
218
|
atoms_1.a.textColors.primary[500],
|
|
@@ -50,8 +226,35 @@ exports.DropdownMenuSubTrigger = (0, react_1.forwardRef)(({ inset, children, ...
|
|
|
50
226
|
atoms_1.pr[8],
|
|
51
227
|
], children: [children, (0, jsx_runtime_1.jsx)(react_native_1.View, { style: [atoms_1.a.layout.position.absolute, atoms_1.a.position.right[1]], children: (0, jsx_runtime_1.jsx)(Icon, { size: 18, color: icons.color.muted }) })] }) }) }));
|
|
52
228
|
});
|
|
53
|
-
exports.DropdownMenuSubContent = (0, react_1.forwardRef)((props, ref) => {
|
|
229
|
+
exports.DropdownMenuSubContent = (0, react_1.forwardRef)(({ children, ...props }, ref) => {
|
|
54
230
|
const { zero: zt } = (0, ui_1.useTheme)();
|
|
231
|
+
const subMenuContext = (0, react_1.useContext)(SubMenuContext);
|
|
232
|
+
const navStack = useNavigationStack();
|
|
233
|
+
const prevChildrenRef = (0, react_1.useRef)(null);
|
|
234
|
+
// Register a render function that will be called fresh each time
|
|
235
|
+
react_1.default.useEffect(() => {
|
|
236
|
+
if (subMenuContext && navStack) {
|
|
237
|
+
// Only update if children reference actually changed
|
|
238
|
+
if (prevChildrenRef.current === children) {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
prevChildrenRef.current = children;
|
|
242
|
+
// Pass a function that returns the current children
|
|
243
|
+
subMenuContext.setRenderContent(() => children);
|
|
244
|
+
// Force a stack update to trigger rerender with the actual children
|
|
245
|
+
if (subMenuContext.key) {
|
|
246
|
+
// Store the children directly so React can handle updates
|
|
247
|
+
//navStack.updateContent(subMenuContext.key, children);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}, [children, subMenuContext, navStack]);
|
|
251
|
+
// On mobile, don't render the subcontent here - it'll be rendered in the nav stack
|
|
252
|
+
// But keep the component mounted so effects run when children change
|
|
253
|
+
if (navStack && subMenuContext) {
|
|
254
|
+
// Component stays mounted to track prop changes, but renders nothing
|
|
255
|
+
return null;
|
|
256
|
+
}
|
|
257
|
+
// Web - use primitive
|
|
55
258
|
return ((0, jsx_runtime_1.jsx)(DropdownMenuPrimitive.SubContent, { ref: ref, style: [
|
|
56
259
|
atoms_1.a.zIndex[50],
|
|
57
260
|
atoms_1.a.sizes.minWidth[32],
|
|
@@ -63,10 +266,12 @@ exports.DropdownMenuSubContent = (0, react_1.forwardRef)((props, ref) => {
|
|
|
63
266
|
zt.bg.popover,
|
|
64
267
|
atoms_1.p[1],
|
|
65
268
|
atoms_1.a.shadows.md,
|
|
66
|
-
], ...props }));
|
|
269
|
+
], ...props, children: children }));
|
|
67
270
|
});
|
|
68
|
-
exports.DropdownMenuContent = (0, react_1.forwardRef)(({ overlayStyle, portalHost, ...props }, ref) => {
|
|
271
|
+
exports.DropdownMenuContent = (0, react_1.forwardRef)(({ overlayStyle, portalHost, style, children, ...props }, ref) => {
|
|
69
272
|
const { zero: zt } = (0, ui_1.useTheme)();
|
|
273
|
+
const { height } = (0, react_native_1.useWindowDimensions)();
|
|
274
|
+
const maxHeight = height * 0.8;
|
|
70
275
|
return ((0, jsx_runtime_1.jsx)(DropdownMenuPrimitive.Portal, { hostName: portalHost, children: (0, jsx_runtime_1.jsx)(DropdownMenuPrimitive.Overlay, { style: [
|
|
71
276
|
react_native_1.Platform.OS !== "web" ? react_native_1.StyleSheet.absoluteFill : undefined,
|
|
72
277
|
overlayStyle,
|
|
@@ -81,10 +286,15 @@ exports.DropdownMenuContent = (0, react_1.forwardRef)(({ overlayStyle, portalHos
|
|
|
81
286
|
zt.bg.popover,
|
|
82
287
|
atoms_1.p[2],
|
|
83
288
|
atoms_1.a.shadows.md,
|
|
84
|
-
|
|
289
|
+
style,
|
|
290
|
+
], ...props, children: (0, jsx_runtime_1.jsx)(react_native_1.ScrollView, { style: { maxHeight }, showsVerticalScrollIndicator: true, children: typeof children === "function"
|
|
291
|
+
? children({ pressed: false })
|
|
292
|
+
: children }) }) }) }));
|
|
85
293
|
});
|
|
86
|
-
exports.DropdownMenuContentWithoutPortal = (0, react_1.forwardRef)(({ overlayStyle, ...props }, ref) => {
|
|
294
|
+
exports.DropdownMenuContentWithoutPortal = (0, react_1.forwardRef)(({ overlayStyle, maxHeightPercentage = 0.8, children, style, ...props }, ref) => {
|
|
87
295
|
const { theme } = (0, ui_1.useTheme)();
|
|
296
|
+
const { height } = (0, react_native_1.useWindowDimensions)();
|
|
297
|
+
const maxHeight = height * maxHeightPercentage;
|
|
88
298
|
return ((0, jsx_runtime_1.jsx)(DropdownMenuPrimitive.Overlay, { style: [
|
|
89
299
|
react_native_1.Platform.OS !== "web" ? react_native_1.StyleSheet.absoluteFill : undefined,
|
|
90
300
|
overlayStyle,
|
|
@@ -92,21 +302,23 @@ exports.DropdownMenuContentWithoutPortal = (0, react_1.forwardRef)(({ overlaySty
|
|
|
92
302
|
{ zIndex: 999999 },
|
|
93
303
|
atoms_1.a.sizes.minWidth[32],
|
|
94
304
|
atoms_1.a.sizes.maxWidth[64],
|
|
95
|
-
atoms_1.a.overflow.hidden,
|
|
96
305
|
atoms_1.a.radius.all.md,
|
|
97
306
|
atoms_1.a.borders.width.thin,
|
|
98
307
|
{ borderColor: theme.colors.border },
|
|
99
308
|
{ backgroundColor: theme.colors.popover },
|
|
100
309
|
atoms_1.p[2],
|
|
101
310
|
atoms_1.a.shadows.md,
|
|
102
|
-
|
|
311
|
+
style,
|
|
312
|
+
], ...props, children: (0, jsx_runtime_1.jsx)(react_native_1.ScrollView, { style: { maxHeight }, showsVerticalScrollIndicator: true, children: typeof children === "function"
|
|
313
|
+
? children({ pressed: false })
|
|
314
|
+
: children }) }) }));
|
|
103
315
|
});
|
|
104
316
|
/// Responsive Dropdown Menu Content. On mobile this will render a *bottom sheet* that is **portaled to the root of the app**.
|
|
105
317
|
/// Prefer passing scoped content in as **otherwise it may crash the app**.
|
|
106
318
|
exports.ResponsiveDropdownMenuContent = (0, react_1.forwardRef)(({ children, ...props }, ref) => {
|
|
107
319
|
const { width } = (0, react_native_1.useWindowDimensions)();
|
|
108
320
|
// On web, you might want to always use the normal dropdown
|
|
109
|
-
const isBottomSheet = react_native_1.Platform.OS !== "web"
|
|
321
|
+
const isBottomSheet = react_native_1.Platform.OS !== "web";
|
|
110
322
|
if (isBottomSheet) {
|
|
111
323
|
return ((0, jsx_runtime_1.jsx)(exports.DropdownMenuBottomSheet, { ref: ref, ...props, children: children }));
|
|
112
324
|
}
|
|
@@ -137,6 +137,18 @@ exports.TextRoot = (0, react_1.forwardRef)(({ variant, size, weight, color, alig
|
|
|
137
137
|
const variantStyles = getVariantStyles();
|
|
138
138
|
// Calculate inherited values
|
|
139
139
|
const inheritedContext = inherit && !reset && parentContext ? parentContext : {};
|
|
140
|
+
// Calculate fontSize first for line height calculation
|
|
141
|
+
let calculatedFontSize = inheritedContext.fontSize;
|
|
142
|
+
// Apply variant font size
|
|
143
|
+
if (variant && variantStyles[variant]?.fontSize) {
|
|
144
|
+
calculatedFontSize = variantStyles[variant].fontSize;
|
|
145
|
+
}
|
|
146
|
+
// Apply size-based font size
|
|
147
|
+
if (size) {
|
|
148
|
+
calculatedFontSize = typeof size === "number" ? size : sizeMap[size];
|
|
149
|
+
}
|
|
150
|
+
// Use default if still undefined
|
|
151
|
+
calculatedFontSize = calculatedFontSize || 16;
|
|
140
152
|
// Calculate final styles
|
|
141
153
|
const finalStyles = {
|
|
142
154
|
// Start with inherited values
|
|
@@ -194,7 +206,9 @@ exports.TextRoot = (0, react_1.forwardRef)(({ variant, size, weight, color, alig
|
|
|
194
206
|
}),
|
|
195
207
|
// Apply line height
|
|
196
208
|
...(leading && {
|
|
197
|
-
lineHeight: typeof leading === "number"
|
|
209
|
+
lineHeight: typeof leading === "number"
|
|
210
|
+
? leading
|
|
211
|
+
: leadingMap[leading] * calculatedFontSize,
|
|
198
212
|
}),
|
|
199
213
|
// Apply letter spacing
|
|
200
214
|
...(tracking && {
|
|
@@ -231,7 +245,7 @@ exports.TextRoot = (0, react_1.forwardRef)(({ variant, size, weight, color, alig
|
|
|
231
245
|
if (typeof fontSize === "number" && !styleObj.lineHeight && !leading) {
|
|
232
246
|
return {
|
|
233
247
|
...styleObj,
|
|
234
|
-
lineHeight: fontSize
|
|
248
|
+
lineHeight: fontSize,
|
|
235
249
|
};
|
|
236
250
|
}
|
|
237
251
|
}
|
|
@@ -285,7 +299,7 @@ function createTextStyle(props) {
|
|
|
285
299
|
if (props.leading === undefined) {
|
|
286
300
|
style.lineHeight =
|
|
287
301
|
typeof props.size === "number"
|
|
288
|
-
? props.size
|
|
302
|
+
? props.size
|
|
289
303
|
: sizeLineHeightMap[props.size];
|
|
290
304
|
}
|
|
291
305
|
}
|
|
@@ -296,10 +310,11 @@ function createTextStyle(props) {
|
|
|
296
310
|
style.textAlign = props.align;
|
|
297
311
|
}
|
|
298
312
|
if (props.leading) {
|
|
313
|
+
const fontSize = style.fontSize || 16; // default font size
|
|
299
314
|
style.lineHeight =
|
|
300
315
|
typeof props.leading === "number"
|
|
301
316
|
? props.leading
|
|
302
|
-
: leadingMap[props.leading];
|
|
317
|
+
: leadingMap[props.leading] * fontSize;
|
|
303
318
|
}
|
|
304
319
|
if (props.tracking) {
|
|
305
320
|
style.letterSpacing =
|
|
@@ -5,85 +5,54 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
5
5
|
const lucide_react_native_1 = require("lucide-react-native");
|
|
6
6
|
const react_1 = require("react");
|
|
7
7
|
const react_native_1 = require("react-native");
|
|
8
|
+
const __1 = require("../..");
|
|
8
9
|
const theme_1 = require("../../lib/theme/theme");
|
|
10
|
+
const ui_1 = require("../../ui");
|
|
11
|
+
const dropdown_1 = require("./dropdown");
|
|
9
12
|
const text_1 = require("./text");
|
|
13
|
+
const { layout, px, py, borders, r, gap } = __1.zero;
|
|
10
14
|
exports.Select = (0, react_1.forwardRef)(({ value, onValueChange, placeholder = "Select...", items, disabled = false, style, }, ref) => {
|
|
11
15
|
const { theme } = (0, theme_1.useTheme)();
|
|
12
|
-
const [isOpen, setIsOpen] = (0, react_1.useState)(false);
|
|
13
16
|
const selectedItem = items.find((item) => item.value === value);
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
17
|
+
return ((0, jsx_runtime_1.jsxs)(dropdown_1.DropdownMenu, { children: [(0, jsx_runtime_1.jsx)(dropdown_1.DropdownMenuTrigger, { disabled: disabled, children: (0, jsx_runtime_1.jsx)(react_native_1.View, { ref: ref, style: [
|
|
18
|
+
{
|
|
19
|
+
width: "100%",
|
|
20
|
+
paddingHorizontal: theme.spacing[3],
|
|
21
|
+
paddingVertical: theme.spacing[3],
|
|
22
|
+
borderWidth: 1,
|
|
23
|
+
borderColor: theme.colors.border,
|
|
24
|
+
borderRadius: theme.borderRadius.md,
|
|
25
|
+
backgroundColor: disabled
|
|
26
|
+
? theme.colors.muted
|
|
27
|
+
: theme.colors.card,
|
|
28
|
+
minHeight: theme.touchTargets.minimum,
|
|
29
|
+
opacity: disabled ? 0.5 : 1,
|
|
30
|
+
},
|
|
31
|
+
style,
|
|
32
|
+
], children: (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: {
|
|
33
|
+
flexDirection: "row",
|
|
34
|
+
alignItems: "center",
|
|
35
|
+
justifyContent: "space-between",
|
|
36
|
+
width: "100%",
|
|
37
|
+
gap: 8,
|
|
38
|
+
}, children: [(0, jsx_runtime_1.jsx)(text_1.Text, { style: {
|
|
39
|
+
fontSize: 16,
|
|
40
|
+
color: disabled
|
|
41
|
+
? theme.colors.textDisabled
|
|
42
|
+
: theme.colors.text,
|
|
43
|
+
flex: 1,
|
|
44
|
+
}, children: selectedItem?.label || placeholder }), (0, jsx_runtime_1.jsx)(lucide_react_native_1.ChevronDown, { size: 16, color: theme.colors.textMuted })] }) }) }), (0, jsx_runtime_1.jsx)(dropdown_1.ResponsiveDropdownMenuContent, { align: "start", style: [
|
|
45
|
+
{
|
|
46
|
+
maxHeight: 400,
|
|
47
|
+
},
|
|
48
|
+
], children: items.map((item, index) => ((0, jsx_runtime_1.jsxs)(react_native_1.View, { children: [(0, jsx_runtime_1.jsx)(dropdown_1.DropdownMenuItem, { onPress: () => onValueChange(item.value), children: (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: {
|
|
49
|
+
flexDirection: "row",
|
|
50
|
+
alignItems: "center",
|
|
51
|
+
justifyContent: "space-between",
|
|
52
|
+
width: "100%",
|
|
53
|
+
gap: 8,
|
|
54
|
+
}, children: [(0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [gap.all[1], py[1], ui_1.flex.values[1]], children: [(0, jsx_runtime_1.jsx)(text_1.Text, { style: {
|
|
55
|
+
fontWeight: item.value === value ? "500" : "400",
|
|
56
|
+
}, color: item.value === value ? "primary" : "default", children: item.label }), item.description && ((0, jsx_runtime_1.jsx)(text_1.Text, { size: "sm", color: "muted", children: item.description }))] }), item.value === value ? ((0, jsx_runtime_1.jsx)(lucide_react_native_1.Check, { size: 16, color: theme.colors.primary })) : ((0, jsx_runtime_1.jsx)(react_native_1.View, { style: { width: 16 } }))] }) }), index < items.length - 1 && (0, jsx_runtime_1.jsx)(dropdown_1.DropdownMenuSeparator, {})] }, item.value))) })] }));
|
|
26
57
|
});
|
|
27
58
|
exports.Select.displayName = "Select";
|
|
28
|
-
function createStyles(theme, disabled) {
|
|
29
|
-
return react_native_1.StyleSheet.create({
|
|
30
|
-
container: {
|
|
31
|
-
flexDirection: "row",
|
|
32
|
-
alignItems: "center",
|
|
33
|
-
justifyContent: "space-between",
|
|
34
|
-
paddingHorizontal: theme.spacing[3],
|
|
35
|
-
paddingVertical: theme.spacing[3],
|
|
36
|
-
borderWidth: 1,
|
|
37
|
-
borderColor: theme.colors.border,
|
|
38
|
-
borderRadius: theme.borderRadius.md,
|
|
39
|
-
backgroundColor: disabled ? theme.colors.muted : theme.colors.card,
|
|
40
|
-
minHeight: theme.touchTargets.minimum,
|
|
41
|
-
},
|
|
42
|
-
value: {
|
|
43
|
-
fontSize: 16,
|
|
44
|
-
color: disabled ? theme.colors.textDisabled : theme.colors.text,
|
|
45
|
-
flex: 1,
|
|
46
|
-
},
|
|
47
|
-
overlay: {
|
|
48
|
-
flex: 1,
|
|
49
|
-
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
|
50
|
-
justifyContent: "center",
|
|
51
|
-
alignItems: "center",
|
|
52
|
-
},
|
|
53
|
-
dropdown: {
|
|
54
|
-
backgroundColor: theme.colors.background,
|
|
55
|
-
borderRadius: theme.borderRadius.md,
|
|
56
|
-
borderWidth: 1,
|
|
57
|
-
borderColor: theme.colors.border,
|
|
58
|
-
maxHeight: 300,
|
|
59
|
-
width: "90%",
|
|
60
|
-
maxWidth: 400,
|
|
61
|
-
...theme.shadows.lg,
|
|
62
|
-
},
|
|
63
|
-
list: {
|
|
64
|
-
maxHeight: 300,
|
|
65
|
-
},
|
|
66
|
-
item: {
|
|
67
|
-
paddingHorizontal: theme.spacing[4],
|
|
68
|
-
paddingVertical: theme.spacing[3],
|
|
69
|
-
borderBottomWidth: 1,
|
|
70
|
-
borderBottomColor: theme.colors.border,
|
|
71
|
-
},
|
|
72
|
-
selectedItem: {
|
|
73
|
-
backgroundColor: theme.colors.primary,
|
|
74
|
-
},
|
|
75
|
-
itemText: {
|
|
76
|
-
fontSize: 16,
|
|
77
|
-
color: theme.colors.text,
|
|
78
|
-
},
|
|
79
|
-
selectedItemText: {
|
|
80
|
-
color: theme.colors.primaryForeground,
|
|
81
|
-
fontWeight: "500",
|
|
82
|
-
},
|
|
83
|
-
itemDescription: {
|
|
84
|
-
fontSize: 14,
|
|
85
|
-
color: theme.colors.textMuted,
|
|
86
|
-
marginTop: theme.spacing[1],
|
|
87
|
-
},
|
|
88
|
-
});
|
|
89
|
-
}
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@streamplace/components",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.9",
|
|
4
4
|
"description": "Streamplace React (Native) Components",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "src/index.tsx",
|
|
@@ -56,5 +56,5 @@
|
|
|
56
56
|
"start": "tsc --watch --preserveWatchOutput",
|
|
57
57
|
"prepare": "tsc"
|
|
58
58
|
},
|
|
59
|
-
"gitHead": "
|
|
59
|
+
"gitHead": "2ac59bf91315b2b1f848842c1048a23bd74658b7"
|
|
60
60
|
}
|
|
@@ -376,26 +376,11 @@ export const ContentMetadataForm = forwardRef<any, ContentMetadataFormProps>(
|
|
|
376
376
|
layout.flex.row,
|
|
377
377
|
layout.flex.alignCenter,
|
|
378
378
|
w.percent[100],
|
|
379
|
+
gap.all[2],
|
|
379
380
|
]}
|
|
380
381
|
>
|
|
381
|
-
<Text
|
|
382
|
-
|
|
383
|
-
text.neutral[300],
|
|
384
|
-
{
|
|
385
|
-
minWidth: 100,
|
|
386
|
-
textAlign: "left",
|
|
387
|
-
paddingBottom: 8,
|
|
388
|
-
fontSize: 14,
|
|
389
|
-
},
|
|
390
|
-
]}
|
|
391
|
-
>
|
|
392
|
-
Content Warnings
|
|
393
|
-
</Text>
|
|
394
|
-
<Text
|
|
395
|
-
style={[text.gray[500], { fontSize: 12, paddingBottom: 8 }]}
|
|
396
|
-
>
|
|
397
|
-
optional
|
|
398
|
-
</Text>
|
|
382
|
+
<Text>Content Warnings</Text>
|
|
383
|
+
<Text muted>(optional)</Text>
|
|
399
384
|
</View>
|
|
400
385
|
<View style={[gap.all[2], w.percent[100]]}>
|
|
401
386
|
{CONTENT_WARNINGS.map((warning) => (
|
|
@@ -424,26 +409,11 @@ export const ContentMetadataForm = forwardRef<any, ContentMetadataFormProps>(
|
|
|
424
409
|
layout.flex.row,
|
|
425
410
|
layout.flex.alignCenter,
|
|
426
411
|
w.percent[100],
|
|
412
|
+
gap.all[2],
|
|
427
413
|
]}
|
|
428
414
|
>
|
|
429
|
-
<Text
|
|
430
|
-
|
|
431
|
-
text.neutral[300],
|
|
432
|
-
{
|
|
433
|
-
minWidth: 100,
|
|
434
|
-
textAlign: "left",
|
|
435
|
-
paddingBottom: 8,
|
|
436
|
-
fontSize: 14,
|
|
437
|
-
},
|
|
438
|
-
]}
|
|
439
|
-
>
|
|
440
|
-
Content Rights
|
|
441
|
-
</Text>
|
|
442
|
-
<Text
|
|
443
|
-
style={[text.gray[500], { fontSize: 12, paddingBottom: 8 }]}
|
|
444
|
-
>
|
|
445
|
-
optional
|
|
446
|
-
</Text>
|
|
415
|
+
<Text>Content Rights</Text>
|
|
416
|
+
<Text muted>(optional)</Text>
|
|
447
417
|
</View>
|
|
448
418
|
|
|
449
419
|
<View style={[gap.all[3], w.percent[100]]}>
|
|
@@ -674,21 +644,11 @@ export const ContentMetadataForm = forwardRef<any, ContentMetadataFormProps>(
|
|
|
674
644
|
layout.flex.row,
|
|
675
645
|
layout.flex.alignCenter,
|
|
676
646
|
w.percent[100],
|
|
647
|
+
gap.all[2],
|
|
677
648
|
]}
|
|
678
649
|
>
|
|
679
|
-
<Text
|
|
680
|
-
|
|
681
|
-
text.neutral[300],
|
|
682
|
-
{ minWidth: 100, textAlign: "left", paddingBottom: 8 },
|
|
683
|
-
]}
|
|
684
|
-
>
|
|
685
|
-
Distribution
|
|
686
|
-
</Text>
|
|
687
|
-
<Text
|
|
688
|
-
style={[text.gray[500], { fontSize: 12, paddingBottom: 8 }]}
|
|
689
|
-
>
|
|
690
|
-
optional
|
|
691
|
-
</Text>
|
|
650
|
+
<Text>Distribution</Text>
|
|
651
|
+
<Text muted>(optional)</Text>
|
|
692
652
|
</View>
|
|
693
653
|
|
|
694
654
|
{/* allow everyone to distribute your content */}
|