@vellira-ui/react-native 2.55.0 → 2.56.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 (2) hide show
  1. package/dist/index.js +99 -76
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -698,11 +698,7 @@ const createStyles$21 = (theme) => StyleSheet.create({
698
698
  justifyContent: "center",
699
699
  padding: theme.tokens.spacing[4]
700
700
  },
701
- popover: {
702
- alignItems: "center",
703
- justifyContent: "center",
704
- padding: theme.tokens.spacing[4]
705
- },
701
+ popover: { flex: 1 },
706
702
  backdrop: {
707
703
  ...StyleSheet.absoluteFill,
708
704
  backgroundColor: theme.semantic.overlay.backdrop
@@ -777,11 +773,12 @@ const createStyles$21 = (theme) => StyleSheet.create({
777
773
  //#region src/components/Dropdown/Content/DropdownContent.tsx
778
774
  const nativePointerEventsBoxNone$1 = Platform.OS === "web" ? void 0 : { pointerEvents: "box-none" };
779
775
  const webPointerEventsBoxNone$1 = Platform.OS === "web" ? { pointerEvents: "box-none" } : void 0;
780
- function DropdownContent({ isOpen, children, onClose, color = "primary", contentStyle, accessibilityLabel, presentation, searchable = false, searchValue = "", searchPlaceholder = "Search actions...", searchAccessibilityLabel, onSearchChange }) {
776
+ function DropdownContent({ isOpen, children, onClose, color = "primary", contentStyle, accessibilityLabel, presentation, position, onFloatingLayout, searchable = false, searchValue = "", searchPlaceholder = "Search actions...", searchAccessibilityLabel, onSearchChange }) {
781
777
  const { theme } = useTheme();
782
778
  const styles = useThemeStyles(createStyles$21);
783
779
  const colorPalette = theme.components.dropdown[color];
784
780
  const isSheet = presentation === "sheet";
781
+ const isPopover = presentation === "popover";
785
782
  const animation = useRef(new Animated.Value(isOpen ? 1 : 0)).current;
786
783
  const [reduceMotion, setReduceMotion] = useState(false);
787
784
  useEffect(() => {
@@ -857,9 +854,15 @@ function DropdownContent({ isOpen, children, onClose, color = "primary", content
857
854
  styles.menu,
858
855
  styles[`${presentation}Menu`],
859
856
  { borderColor: colorPalette.content.border },
857
+ isPopover && {
858
+ position: "absolute",
859
+ top: position.top,
860
+ left: position.left
861
+ },
860
862
  contentStyle,
861
863
  menuAnimatedStyle
862
864
  ],
865
+ onLayout: isPopover ? onFloatingLayout : void 0,
863
866
  children: [searchable && /* @__PURE__ */ jsxs(View, {
864
867
  style: styles.searchWrap,
865
868
  children: [/* @__PURE__ */ jsx(View, {
@@ -887,27 +890,6 @@ function DropdownContent({ isOpen, children, onClose, color = "primary", content
887
890
  }
888
891
  DropdownContent.displayName = "DropdownContent";
889
892
  //#endregion
890
- //#region src/components/Dropdown/Group/DropdownGroup.styles.ts
891
- const createStyles$20 = (theme) => StyleSheet.create({ groupLabel: {
892
- paddingHorizontal: theme.tokens.spacing[4],
893
- paddingVertical: theme.tokens.spacing[2],
894
- color: theme.components.dropdown.groupLabel.fg,
895
- fontFamily: theme.tokens.typography.family.medium,
896
- fontSize: theme.tokens.typography.size.xs,
897
- lineHeight: theme.tokens.typography.lineHeight.sm,
898
- textTransform: "uppercase"
899
- } });
900
- //#endregion
901
- //#region src/components/Dropdown/Group/DropdownGroup.tsx
902
- function DropdownGroup({ label }) {
903
- return /* @__PURE__ */ jsx(Text, {
904
- accessibilityRole: "header",
905
- style: useThemeStyles(createStyles$20).groupLabel,
906
- children: label
907
- });
908
- }
909
- DropdownGroup.displayName = "DropdownGroup";
910
- //#endregion
911
893
  //#region src/components/Dropdown/internal/DropdownCollection.ts
912
894
  function createDropdownSlot(name, displayName) {
913
895
  const Slot = () => null;
@@ -1011,8 +993,65 @@ function getItemLabel(children) {
1011
993
  return labelParts.join("").trim();
1012
994
  }
1013
995
  //#endregion
996
+ //#region src/components/Dropdown/Dropdown.styles.ts
997
+ const createStyles$20 = (theme) => StyleSheet.create({
998
+ root: { alignSelf: "flex-start" },
999
+ emptyText: {
1000
+ minHeight: 44,
1001
+ paddingHorizontal: theme.tokens.spacing[3],
1002
+ paddingVertical: theme.tokens.spacing[3],
1003
+ color: theme.components.dropdown.item.disabled.fg,
1004
+ fontFamily: theme.tokens.typography.family.regular,
1005
+ fontSize: theme.tokens.typography.size.md,
1006
+ lineHeight: theme.tokens.typography.lineHeight.md
1007
+ }
1008
+ });
1009
+ //#endregion
1010
+ //#region src/components/Dropdown/Group/DropdownGroup.styles.ts
1011
+ const createStyles$19 = (theme) => StyleSheet.create({ groupLabel: {
1012
+ paddingHorizontal: theme.tokens.spacing[4],
1013
+ paddingVertical: theme.tokens.spacing[2],
1014
+ color: theme.components.dropdown.groupLabel.fg,
1015
+ fontFamily: theme.tokens.typography.family.medium,
1016
+ fontSize: theme.tokens.typography.size.xs,
1017
+ lineHeight: theme.tokens.typography.lineHeight.sm,
1018
+ textTransform: "uppercase"
1019
+ } });
1020
+ //#endregion
1021
+ //#region src/components/Dropdown/Group/DropdownGroup.tsx
1022
+ function DropdownGroup({ label }) {
1023
+ return /* @__PURE__ */ jsx(Text, {
1024
+ accessibilityRole: "header",
1025
+ style: useThemeStyles(createStyles$19).groupLabel,
1026
+ children: label
1027
+ });
1028
+ }
1029
+ DropdownGroup.displayName = "DropdownGroup";
1030
+ //#endregion
1031
+ //#region src/components/Dropdown/internal/DropdownUtils.ts
1032
+ function createDropdownSelectEvent() {
1033
+ let defaultPrevented = false;
1034
+ return {
1035
+ preventDefault: () => {
1036
+ defaultPrevented = true;
1037
+ },
1038
+ get defaultPrevented() {
1039
+ return defaultPrevented;
1040
+ }
1041
+ };
1042
+ }
1043
+ function filterDropdownEntries(parsed, searchValue) {
1044
+ const normalizedSearch = searchValue.trim().toLocaleLowerCase();
1045
+ const matchedItems = new Set(parsed.items.filter((item) => item.label.toLocaleLowerCase().includes(normalizedSearch)).map((item) => item.id));
1046
+ return {
1047
+ ...parsed,
1048
+ items: parsed.items.filter((item) => matchedItems.has(item.id)),
1049
+ entries: parsed.entries.filter((entry) => entry.type !== "item" || matchedItems.has(entry.id))
1050
+ };
1051
+ }
1052
+ //#endregion
1014
1053
  //#region src/components/Dropdown/Item/DropdownItem.styles.ts
1015
- const createStyles$19 = (theme) => StyleSheet.create({
1054
+ const createStyles$18 = (theme) => StyleSheet.create({
1016
1055
  item: {
1017
1056
  minWidth: 0,
1018
1057
  minHeight: 44,
@@ -1037,7 +1076,7 @@ const createStyles$19 = (theme) => StyleSheet.create({
1037
1076
  //#region src/components/Dropdown/Item/DropdownItem.tsx
1038
1077
  function DropdownItem({ label, value, rootColor = "primary", color = "default", icon, disabled = false, textWrap = "truncate", itemStyle, textStyle, onSelect }) {
1039
1078
  const { theme } = useTheme();
1040
- const styles = useThemeStyles(createStyles$19);
1079
+ const styles = useThemeStyles(createStyles$18);
1041
1080
  const rootColorPalette = theme.components.dropdown[rootColor];
1042
1081
  const itemColorPalette = color === "default" ? void 0 : theme.components.dropdown[color];
1043
1082
  const renderColoredNode = (node, color) => {
@@ -1091,19 +1130,19 @@ function DropdownItem({ label, value, rootColor = "primary", color = "default",
1091
1130
  DropdownItem.displayName = "DropdownItem";
1092
1131
  //#endregion
1093
1132
  //#region src/components/Dropdown/Separator/DropdownSeparator.styles.ts
1094
- const createStyles$18 = (theme) => StyleSheet.create({ separator: {
1133
+ const createStyles$17 = (theme) => StyleSheet.create({ separator: {
1095
1134
  height: 1,
1096
1135
  backgroundColor: theme.components.dropdown.separator.bg
1097
1136
  } });
1098
1137
  //#endregion
1099
1138
  //#region src/components/Dropdown/Separator/DropdownSeparator.tsx
1100
1139
  function DropdownSeparator() {
1101
- return /* @__PURE__ */ jsx(View, { style: useThemeStyles(createStyles$18).separator });
1140
+ return /* @__PURE__ */ jsx(View, { style: useThemeStyles(createStyles$17).separator });
1102
1141
  }
1103
1142
  DropdownSeparator.displayName = "DropdownSeparator";
1104
1143
  //#endregion
1105
1144
  //#region src/components/Dropdown/Trigger/DropdownTrigger.styles.ts
1106
- const createStyles$17 = (theme) => StyleSheet.create({
1145
+ const createStyles$16 = (theme) => StyleSheet.create({
1107
1146
  trigger: {
1108
1147
  alignItems: "center",
1109
1148
  justifyContent: "center",
@@ -1191,7 +1230,7 @@ const createStyles$17 = (theme) => StyleSheet.create({
1191
1230
  //#region src/components/Dropdown/Trigger/DropdownTrigger.tsx
1192
1231
  function DropdownTrigger({ asChild = false, label, trigger, children, icon, arrowIcon, showArrow = true, color = "primary", size = "md", disabled = false, isOpen, triggerStyle, triggerRef, accessibilityLabel, accessibilityHint, onPress }) {
1193
1232
  const { theme } = useTheme();
1194
- const styles = useThemeStyles(createStyles$17);
1233
+ const styles = useThemeStyles(createStyles$16);
1195
1234
  const colorPalette = theme.components.dropdown[color];
1196
1235
  const textSizeStyle = {
1197
1236
  sm: styles.textSm,
@@ -1311,32 +1350,28 @@ function DropdownTrigger({ asChild = false, label, trigger, children, icon, arro
1311
1350
  }
1312
1351
  DropdownTrigger.displayName = "DropdownTrigger";
1313
1352
  //#endregion
1314
- //#region src/components/Dropdown/Dropdown.styles.ts
1315
- const createStyles$16 = (theme) => StyleSheet.create({
1316
- root: { alignSelf: "flex-start" },
1317
- emptyText: {
1318
- minHeight: 44,
1319
- paddingHorizontal: theme.tokens.spacing[3],
1320
- paddingVertical: theme.tokens.spacing[3],
1321
- color: theme.components.dropdown.item.disabled.fg,
1322
- fontFamily: theme.tokens.typography.family.regular,
1323
- fontSize: theme.tokens.typography.size.md,
1324
- lineHeight: theme.tokens.typography.lineHeight.md
1325
- }
1326
- });
1327
- //#endregion
1328
- //#region src/components/Dropdown/Dropdown.tsx
1329
- function DropdownRoot({ children, label = "Menu", trigger, icon, arrowIcon, showArrow = true, open, defaultOpen = false, onOpenChange, presentation = "auto", closeOnSelect = true, color = "primary", disabled = false, loading = false, loadingText = "Loading actions...", searchable = false, command = false, searchValue, defaultSearchValue = "", searchPlaceholder, onSearch, empty, size = "md", style, triggerStyle, contentStyle, itemStyle, textStyle, accessibilityLabel, accessibilityHint }) {
1330
- const styles = useThemeStyles(createStyles$16);
1353
+ //#region src/components/Dropdown/Root/DropdownRoot.tsx
1354
+ function DropdownRoot({ children, label = "Menu", trigger, icon, arrowIcon, showArrow = true, open, defaultOpen = false, onOpenChange, presentation = "auto", placement = "bottom-start", offset = 8, closeOnSelect = true, color = "primary", disabled = false, loading = false, loadingText = "Loading actions...", searchable = false, command = false, searchValue, defaultSearchValue = "", searchPlaceholder, onSearch, empty, size = "md", style, triggerStyle, contentStyle, itemStyle, textStyle, accessibilityLabel, accessibilityHint }) {
1355
+ const styles = useThemeStyles(createStyles$20);
1331
1356
  const overlayId = useId();
1332
1357
  const [uncontrolledSearchValue, setUncontrolledSearchValue] = useState(defaultSearchValue);
1333
1358
  const resolvedSearchValue = searchValue ?? uncontrolledSearchValue;
1334
1359
  const { width } = useWindowDimensions();
1335
1360
  const triggerRef = useRef(null);
1361
+ const setTriggerRef = useCallback((node) => {
1362
+ if (node && typeof node === "object" && "measureInWindow" in node && typeof node.measureInWindow === "function") {
1363
+ triggerRef.current = node;
1364
+ return;
1365
+ }
1366
+ triggerRef.current = null;
1367
+ }, []);
1336
1368
  const parsed = useMemo(() => parseDropdownChildren(children), [children]);
1337
1369
  const contentCommand = parsed.contentProps?.command ?? false;
1338
1370
  const isSearchable = searchable || command || contentCommand || !!parsed.searchProps;
1339
1371
  const resolvedPresentation = presentation === "auto" ? width < 768 ? "sheet" : "popover" : presentation;
1372
+ const contentStyleFromSlot = parsed.contentProps?.style;
1373
+ const contentPresentation = (parsed.contentProps?.presentation === "auto" ? void 0 : parsed.contentProps?.presentation) ?? resolvedPresentation;
1374
+ const { position, updatePosition, onFloatingLayout } = useNativeFloatingPosition(placement, offset);
1340
1375
  const menuAccessibilityLabel = useMemo(() => {
1341
1376
  if (accessibilityLabel) return accessibilityLabel;
1342
1377
  return typeof label === "string" ? label : "Menu";
@@ -1363,6 +1398,14 @@ function DropdownRoot({ children, label = "Menu", trigger, icon, arrowIcon, show
1363
1398
  getItemValue: (item) => item.value,
1364
1399
  getItemText: (item) => typeof item.label === "string" ? item.label : item.value
1365
1400
  });
1401
+ useEffect(() => {
1402
+ if (!isOpen || contentPresentation !== "popover") return;
1403
+ updatePosition(triggerRef);
1404
+ }, [
1405
+ isOpen,
1406
+ contentPresentation,
1407
+ updatePosition
1408
+ ]);
1366
1409
  useEffect(() => {
1367
1410
  if (!isOpen) return;
1368
1411
  AccessibilityInfo.announceForAccessibility(`${menuAccessibilityLabel} opened`);
@@ -1443,8 +1486,6 @@ function DropdownRoot({ children, label = "Menu", trigger, icon, arrowIcon, show
1443
1486
  id: "empty",
1444
1487
  props: { children: empty ?? "No actions found" }
1445
1488
  }] : filteredParsed.entries;
1446
- const contentStyleFromSlot = parsed.contentProps?.style;
1447
- const presentationFromSlot = parsed.contentProps?.presentation === "auto" ? void 0 : parsed.contentProps?.presentation;
1448
1489
  return /* @__PURE__ */ jsxs(View, {
1449
1490
  style: [styles.root, style],
1450
1491
  children: [/* @__PURE__ */ jsx(DropdownTrigger, {
@@ -1458,9 +1499,7 @@ function DropdownRoot({ children, label = "Menu", trigger, icon, arrowIcon, show
1458
1499
  disabled: disabled || parsed.triggerProps?.disabled,
1459
1500
  isOpen,
1460
1501
  size,
1461
- triggerRef: (node) => {
1462
- triggerRef.current = node;
1463
- },
1502
+ triggerRef: setTriggerRef,
1464
1503
  triggerStyle,
1465
1504
  accessibilityLabel,
1466
1505
  accessibilityHint,
@@ -1471,7 +1510,9 @@ function DropdownRoot({ children, label = "Menu", trigger, icon, arrowIcon, show
1471
1510
  color,
1472
1511
  contentStyle: [contentStyle, contentStyleFromSlot],
1473
1512
  accessibilityLabel: menuAccessibilityLabel,
1474
- presentation: presentationFromSlot ?? resolvedPresentation,
1513
+ presentation: contentPresentation,
1514
+ position,
1515
+ onFloatingLayout,
1475
1516
  searchable: isSearchable,
1476
1517
  searchValue: resolvedSearchValue,
1477
1518
  searchPlaceholder: parsed.searchProps?.placeholder ?? searchPlaceholder ?? (command || contentCommand ? "Type a command..." : "Search actions..."),
@@ -1488,26 +1529,8 @@ function DropdownRoot({ children, label = "Menu", trigger, icon, arrowIcon, show
1488
1529
  });
1489
1530
  }
1490
1531
  DropdownRoot.displayName = "Dropdown";
1491
- function createDropdownSelectEvent() {
1492
- let defaultPrevented = false;
1493
- return {
1494
- preventDefault: () => {
1495
- defaultPrevented = true;
1496
- },
1497
- get defaultPrevented() {
1498
- return defaultPrevented;
1499
- }
1500
- };
1501
- }
1502
- function filterDropdownEntries(parsed, searchValue) {
1503
- const normalizedSearch = searchValue.trim().toLocaleLowerCase();
1504
- const matchedItems = new Set(parsed.items.filter((item) => item.label.toLocaleLowerCase().includes(normalizedSearch)).map((item) => item.id));
1505
- return {
1506
- ...parsed,
1507
- items: parsed.items.filter((item) => matchedItems.has(item.id)),
1508
- entries: parsed.entries.filter((entry) => entry.type !== "item" || matchedItems.has(entry.id))
1509
- };
1510
- }
1532
+ //#endregion
1533
+ //#region src/components/Dropdown/Dropdown.tsx
1511
1534
  const DropdownTriggerSlot = createDropdownSlot("trigger", "Dropdown.Trigger");
1512
1535
  const DropdownContentSlot = createDropdownSlot("content", "Dropdown.Content");
1513
1536
  const DropdownItemSlot = createDropdownSlot("item", "Dropdown.Item");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vellira-ui/react-native",
3
- "version": "2.55.0",
3
+ "version": "2.56.0",
4
4
  "description": "React Native components for Vellira Design System",
5
5
  "keywords": [
6
6
  "vellira",