@impulse-ui-native/datetime 3.0.0 → 5.0.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.
@@ -2,7 +2,10 @@ import { jsx } from "react/jsx-runtime";
2
2
  import { memo, useCallback } from "react";
3
3
  import { StyleSheet } from "react-native";
4
4
  import { Pressable, Typography, View } from "@impulse-ui-native/primitives";
5
- import { useThemedStyles } from "@impulse-ui-native/theme";
5
+ import {
6
+ getDatetimePickerDayStateTokens,
7
+ useThemedStyles
8
+ } from "@impulse-ui-native/theme";
6
9
  const CalendarDay = memo(function CalendarDay2(props) {
7
10
  const styles = useThemedStyles(themedStyles, props, [
8
11
  props.isSelected,
@@ -19,19 +22,11 @@ const CalendarDay = memo(function CalendarDay2(props) {
19
22
  });
20
23
  function themedStyles(theme, props) {
21
24
  const dayTokens = theme.components.datetimePicker.day;
22
- let color = dayTokens.color;
23
- let backgroundColor = "transparent";
24
- if (!props.isCurrentMonth) {
25
- color = dayTokens.outsideMonthColor;
26
- }
27
- if (props.isInRange) {
28
- backgroundColor = dayTokens.rangeBackgroundColor;
29
- color = dayTokens.rangeColor;
30
- }
31
- if (props.isSelected || props.isRangeStart || props.isRangeEnd) {
32
- backgroundColor = dayTokens.selectedBackgroundColor;
33
- color = dayTokens.selectedColor;
34
- }
25
+ const appearanceTokens = getDatetimePickerDayStateTokens(dayTokens.states, {
26
+ currentMonth: props.isCurrentMonth,
27
+ inRange: props.isInRange,
28
+ selected: props.isSelected || props.isRangeStart || props.isRangeEnd
29
+ });
35
30
  return StyleSheet.create({
36
31
  pressableStyles: {
37
32
  justifyContent: "center",
@@ -43,10 +38,10 @@ function themedStyles(theme, props) {
43
38
  height: dayTokens.size,
44
39
  justifyContent: "center",
45
40
  alignItems: "center",
46
- backgroundColor
41
+ backgroundColor: appearanceTokens.backgroundColor
47
42
  },
48
43
  text: {
49
- color
44
+ color: appearanceTokens.color
50
45
  }
51
46
  });
52
47
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/common/calendar-day.tsx"],"sourcesContent":["import { memo, useCallback } from \"react\";\nimport { StyleSheet, TextStyle, ViewStyle } from \"react-native\";\n\nimport { Pressable, Typography, View } from \"@impulse-ui-native/primitives\";\nimport { AppTheme, useThemedStyles } from \"@impulse-ui-native/theme\";\n\ninterface CalendarDayProps {\n date: Date;\n selected?: boolean;\n isSelected?: boolean;\n isRangeStart?: boolean;\n isInRange?: boolean;\n isRangeEnd?: boolean;\n isCurrentMonth?: boolean;\n onPress?: (date: Date) => void;\n}\n\nexport const CalendarDay = memo(function CalendarDay(props: CalendarDayProps) {\n const styles = useThemedStyles(themedStyles, props, [\n props.isSelected,\n props.isRangeStart,\n props.isInRange,\n props.isRangeEnd,\n props.isCurrentMonth,\n ]);\n\n const handleOnPress = useCallback(\n () => props.onPress?.(props.date),\n [props.date, props.onPress],\n );\n\n return (\n <Pressable style={styles.pressableStyles} onPress={handleOnPress}>\n <View style={styles.container}>\n <Typography.Body style={styles.text} numeric>\n {props.date.getDate()}\n </Typography.Body>\n </View>\n </Pressable>\n );\n});\n\nfunction themedStyles(\n theme: AppTheme,\n props: {\n isSelected?: boolean;\n isRangeStart?: boolean;\n isInRange?: boolean;\n isRangeEnd?: boolean;\n isCurrentMonth?: boolean;\n },\n) {\n const dayTokens = theme.components.datetimePicker.day;\n\n let color: TextStyle[\"color\"] = dayTokens.color;\n let backgroundColor: ViewStyle[\"backgroundColor\"] = \"transparent\";\n\n if (!props.isCurrentMonth) {\n color = dayTokens.outsideMonthColor;\n }\n\n if (props.isInRange) {\n backgroundColor = dayTokens.rangeBackgroundColor;\n color = dayTokens.rangeColor;\n }\n\n if (props.isSelected || props.isRangeStart || props.isRangeEnd) {\n backgroundColor = dayTokens.selectedBackgroundColor;\n color = dayTokens.selectedColor;\n }\n\n return StyleSheet.create({\n pressableStyles: {\n justifyContent: \"center\",\n alignItems: \"center\",\n },\n\n container: {\n borderRadius: dayTokens.borderRadius,\n width: dayTokens.size,\n height: dayTokens.size,\n justifyContent: \"center\",\n alignItems: \"center\",\n backgroundColor,\n },\n\n text: {\n color,\n },\n });\n}\n"],"mappings":"AAkCQ;AAlCR,SAAS,MAAM,mBAAmB;AAClC,SAAS,kBAAwC;AAEjD,SAAS,WAAW,YAAY,YAAY;AAC5C,SAAmB,uBAAuB;AAanC,MAAM,cAAc,KAAK,SAASA,aAAY,OAAyB;AAC5E,QAAM,SAAS,gBAAgB,cAAc,OAAO;AAAA,IAClD,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,EACR,CAAC;AAED,QAAM,gBAAgB;AAAA,IACpB,MAAM,MAAM,UAAU,MAAM,IAAI;AAAA,IAChC,CAAC,MAAM,MAAM,MAAM,OAAO;AAAA,EAC5B;AAEA,SACE,oBAAC,aAAU,OAAO,OAAO,iBAAiB,SAAS,eACjD,8BAAC,QAAK,OAAO,OAAO,WAClB,8BAAC,WAAW,MAAX,EAAgB,OAAO,OAAO,MAAM,SAAO,MACzC,gBAAM,KAAK,QAAQ,GACtB,GACF,GACF;AAEJ,CAAC;AAED,SAAS,aACP,OACA,OAOA;AACA,QAAM,YAAY,MAAM,WAAW,eAAe;AAElD,MAAI,QAA4B,UAAU;AAC1C,MAAI,kBAAgD;AAEpD,MAAI,CAAC,MAAM,gBAAgB;AACzB,YAAQ,UAAU;AAAA,EACpB;AAEA,MAAI,MAAM,WAAW;AACnB,sBAAkB,UAAU;AAC5B,YAAQ,UAAU;AAAA,EACpB;AAEA,MAAI,MAAM,cAAc,MAAM,gBAAgB,MAAM,YAAY;AAC9D,sBAAkB,UAAU;AAC5B,YAAQ,UAAU;AAAA,EACpB;AAEA,SAAO,WAAW,OAAO;AAAA,IACvB,iBAAiB;AAAA,MACf,gBAAgB;AAAA,MAChB,YAAY;AAAA,IACd;AAAA,IAEA,WAAW;AAAA,MACT,cAAc,UAAU;AAAA,MACxB,OAAO,UAAU;AAAA,MACjB,QAAQ,UAAU;AAAA,MAClB,gBAAgB;AAAA,MAChB,YAAY;AAAA,MACZ;AAAA,IACF;AAAA,IAEA,MAAM;AAAA,MACJ;AAAA,IACF;AAAA,EACF,CAAC;AACH;","names":["CalendarDay"]}
1
+ {"version":3,"sources":["../../../src/components/common/calendar-day.tsx"],"sourcesContent":["import { memo, useCallback } from \"react\";\nimport { StyleSheet } from \"react-native\";\n\nimport { Pressable, Typography, View } from \"@impulse-ui-native/primitives\";\nimport {\n AppTheme,\n getDatetimePickerDayStateTokens,\n useThemedStyles,\n} from \"@impulse-ui-native/theme\";\n\ninterface CalendarDayProps {\n date: Date;\n selected?: boolean;\n isSelected?: boolean;\n isRangeStart?: boolean;\n isInRange?: boolean;\n isRangeEnd?: boolean;\n isCurrentMonth?: boolean;\n onPress?: (date: Date) => void;\n}\n\nexport const CalendarDay = memo(function CalendarDay(props: CalendarDayProps) {\n const styles = useThemedStyles(themedStyles, props, [\n props.isSelected,\n props.isRangeStart,\n props.isInRange,\n props.isRangeEnd,\n props.isCurrentMonth,\n ]);\n\n const handleOnPress = useCallback(\n () => props.onPress?.(props.date),\n [props.date, props.onPress],\n );\n\n return (\n <Pressable style={styles.pressableStyles} onPress={handleOnPress}>\n <View style={styles.container}>\n <Typography.Body style={styles.text} numeric>\n {props.date.getDate()}\n </Typography.Body>\n </View>\n </Pressable>\n );\n});\n\nfunction themedStyles(\n theme: AppTheme,\n props: {\n isSelected?: boolean;\n isRangeStart?: boolean;\n isInRange?: boolean;\n isRangeEnd?: boolean;\n isCurrentMonth?: boolean;\n },\n) {\n const dayTokens = theme.components.datetimePicker.day;\n const appearanceTokens = getDatetimePickerDayStateTokens(dayTokens.states, {\n currentMonth: props.isCurrentMonth,\n inRange: props.isInRange,\n selected: props.isSelected || props.isRangeStart || props.isRangeEnd,\n });\n\n return StyleSheet.create({\n pressableStyles: {\n justifyContent: \"center\",\n alignItems: \"center\",\n },\n\n container: {\n borderRadius: dayTokens.borderRadius,\n width: dayTokens.size,\n height: dayTokens.size,\n justifyContent: \"center\",\n alignItems: \"center\",\n backgroundColor: appearanceTokens.backgroundColor,\n },\n\n text: {\n color: appearanceTokens.color,\n },\n });\n}\n"],"mappings":"AAsCQ;AAtCR,SAAS,MAAM,mBAAmB;AAClC,SAAS,kBAAkB;AAE3B,SAAS,WAAW,YAAY,YAAY;AAC5C;AAAA,EAEE;AAAA,EACA;AAAA,OACK;AAaA,MAAM,cAAc,KAAK,SAASA,aAAY,OAAyB;AAC5E,QAAM,SAAS,gBAAgB,cAAc,OAAO;AAAA,IAClD,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,EACR,CAAC;AAED,QAAM,gBAAgB;AAAA,IACpB,MAAM,MAAM,UAAU,MAAM,IAAI;AAAA,IAChC,CAAC,MAAM,MAAM,MAAM,OAAO;AAAA,EAC5B;AAEA,SACE,oBAAC,aAAU,OAAO,OAAO,iBAAiB,SAAS,eACjD,8BAAC,QAAK,OAAO,OAAO,WAClB,8BAAC,WAAW,MAAX,EAAgB,OAAO,OAAO,MAAM,SAAO,MACzC,gBAAM,KAAK,QAAQ,GACtB,GACF,GACF;AAEJ,CAAC;AAED,SAAS,aACP,OACA,OAOA;AACA,QAAM,YAAY,MAAM,WAAW,eAAe;AAClD,QAAM,mBAAmB,gCAAgC,UAAU,QAAQ;AAAA,IACzE,cAAc,MAAM;AAAA,IACpB,SAAS,MAAM;AAAA,IACf,UAAU,MAAM,cAAc,MAAM,gBAAgB,MAAM;AAAA,EAC5D,CAAC;AAED,SAAO,WAAW,OAAO;AAAA,IACvB,iBAAiB;AAAA,MACf,gBAAgB;AAAA,MAChB,YAAY;AAAA,IACd;AAAA,IAEA,WAAW;AAAA,MACT,cAAc,UAAU;AAAA,MACxB,OAAO,UAAU;AAAA,MACjB,QAAQ,UAAU;AAAA,MAClB,gBAAgB;AAAA,MAChB,YAAY;AAAA,MACZ,iBAAiB,iBAAiB;AAAA,IACpC;AAAA,IAEA,MAAM;AAAA,MACJ,OAAO,iBAAiB;AAAA,IAC1B;AAAA,EACF,CAAC;AACH;","names":["CalendarDay"]}
@@ -2,7 +2,11 @@ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { memo, useCallback, useEffect, useRef } from "react";
3
3
  import { FlatList, StyleSheet } from "react-native";
4
4
  import { Pressable, Typography, View } from "@impulse-ui-native/primitives";
5
- import { useComponentsTokens, useThemedStyles } from "@impulse-ui-native/theme";
5
+ import {
6
+ getSelectionItemStateTokens,
7
+ useComponentsTokens,
8
+ useThemedStyles
9
+ } from "@impulse-ui-native/theme";
6
10
  import { getClosestIndexByValue } from "../../utils";
7
11
  const PickerColumn = memo(function PickerColumn2(props) {
8
12
  const { data, label, value, initialScrollIndex = 0, onChange } = props;
@@ -34,12 +38,16 @@ const PickerColumn = memo(function PickerColumn2(props) {
34
38
  const renderItem = useCallback(
35
39
  ({ item }) => {
36
40
  const selected = item === value;
37
- const fontWeight = selected ? columnTokens.selectedFontWeight : columnTokens.fontWeight;
41
+ const appearanceTokens = getSelectionItemStateTokens(
42
+ columnTokens.states,
43
+ { selected }
44
+ );
45
+ const fontWeight = appearanceTokens.fontWeight;
38
46
  return /* @__PURE__ */ jsx(Pressable, { style: styles.pressable, children: /* @__PURE__ */ jsx(
39
47
  Typography.Master,
40
48
  {
41
49
  fontSize: columnTokens.fontSize,
42
- color: selected ? columnTokens.selectedColor : columnTokens.color,
50
+ color: appearanceTokens.color,
43
51
  textAlign: "center",
44
52
  numberOfLines: 1,
45
53
  fontWeight,
@@ -48,15 +56,7 @@ const PickerColumn = memo(function PickerColumn2(props) {
48
56
  }
49
57
  ) });
50
58
  },
51
- [
52
- columnTokens.color,
53
- columnTokens.fontSize,
54
- columnTokens.fontWeight,
55
- columnTokens.selectedColor,
56
- columnTokens.selectedFontWeight,
57
- styles.pressable,
58
- value
59
- ]
59
+ [columnTokens.fontSize, columnTokens.states, styles.pressable, value]
60
60
  );
61
61
  const onMomentumScrollEnd = useCallback(
62
62
  (event) => {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/time/picker-column.tsx"],"sourcesContent":["import type {\n ListRenderItemInfo,\n NativeScrollEvent,\n NativeSyntheticEvent,\n} from \"react-native\";\nimport { memo, useCallback, useEffect, useRef } from \"react\";\nimport { FlatList, StyleSheet } from \"react-native\";\n\nimport type { AppTheme, FontWeightValue } from \"@impulse-ui-native/theme\";\nimport { Pressable, Typography, View } from \"@impulse-ui-native/primitives\";\nimport { useComponentsTokens, useThemedStyles } from \"@impulse-ui-native/theme\";\n\nimport { getClosestIndexByValue } from \"../../utils\";\n\ninterface PickerColumnProps {\n data: number[];\n label: string;\n type: \"hour\" | \"minute\" | \"second\";\n format: \"12h\" | \"24h\";\n value?: number;\n initialScrollIndex?: number;\n onChange?: (value: number) => void;\n}\n\nexport const PickerColumn = memo(function PickerColumn(\n props: PickerColumnProps,\n) {\n const { data, label, value, initialScrollIndex = 0, onChange } = props;\n\n const listRef = useRef<FlatList<number>>(null);\n const currentIndexRef = useRef(initialScrollIndex);\n const tokens = useComponentsTokens();\n const columnTokens = tokens.timePicker.column;\n const styles = useThemedStyles(themedStyles);\n\n const keyExtractor = useCallback((item: number, index: number) => {\n return `${item}-${index}`;\n }, []);\n\n const getItemLayout = useCallback(\n (_: ArrayLike<number> | null | undefined, index: number) => {\n return {\n length: columnTokens.itemHeight,\n offset: columnTokens.itemHeight * index,\n index,\n };\n },\n [columnTokens.itemHeight],\n );\n\n const scrollToIndex = useCallback((index: number, animated: boolean) => {\n currentIndexRef.current = index;\n\n listRef.current?.scrollToIndex({\n index,\n animated,\n });\n }, []);\n\n const renderItem = useCallback(\n ({ item }: ListRenderItemInfo<number>) => {\n const selected = item === value;\n const fontWeight: FontWeightValue = (\n selected ? columnTokens.selectedFontWeight : columnTokens.fontWeight\n ) as FontWeightValue;\n\n return (\n <Pressable style={styles.pressable}>\n <Typography.Master\n fontSize={columnTokens.fontSize}\n color={selected ? columnTokens.selectedColor : columnTokens.color}\n textAlign=\"center\"\n numberOfLines={1}\n fontWeight={fontWeight}\n numeric\n >\n {String(item).padStart(2, \"0\")}\n </Typography.Master>\n </Pressable>\n );\n },\n [\n columnTokens.color,\n columnTokens.fontSize,\n columnTokens.fontWeight,\n columnTokens.selectedColor,\n columnTokens.selectedFontWeight,\n styles.pressable,\n value,\n ],\n );\n\n const onMomentumScrollEnd = useCallback(\n (event: NativeSyntheticEvent<NativeScrollEvent>) => {\n const offset = event.nativeEvent.contentOffset.y;\n const index = Math.round(offset / columnTokens.itemHeight);\n const newValue = data[index];\n\n if (newValue === value) {\n return;\n }\n\n currentIndexRef.current = index;\n\n if (newValue !== undefined) {\n onChange?.(newValue);\n }\n },\n [columnTokens.itemHeight, data, onChange, value],\n );\n\n const onScrollToIndexFailed = useCallback(() => {\n requestAnimationFrame(() => {\n listRef.current?.scrollToOffset({\n offset: initialScrollIndex * columnTokens.itemHeight,\n animated: false,\n });\n });\n }, [columnTokens.itemHeight, initialScrollIndex]);\n\n useEffect(() => {\n if (value === undefined) {\n return;\n }\n\n const closestIndex = getClosestIndexByValue(\n data,\n value,\n currentIndexRef.current,\n );\n\n if (closestIndex === -1 || closestIndex === currentIndexRef.current) {\n return;\n }\n\n scrollToIndex(closestIndex, true);\n }, [data, scrollToIndex, value]);\n\n return (\n <View\n width={columnTokens.width}\n height={columnTokens.height}\n flexDirection=\"row\"\n justifyContent=\"center\"\n gap={columnTokens.gap}\n >\n <View\n width={columnTokens.listWidth}\n height={columnTokens.height}\n overflow=\"hidden\"\n >\n <FlatList\n ref={listRef}\n data={data}\n renderItem={renderItem}\n keyExtractor={keyExtractor}\n getItemLayout={getItemLayout}\n snapToInterval={columnTokens.itemHeight}\n snapToAlignment=\"start\"\n decelerationRate=\"fast\"\n initialScrollIndex={initialScrollIndex}\n showsVerticalScrollIndicator={false}\n contentContainerStyle={styles.contentContainer}\n onMomentumScrollEnd={onMomentumScrollEnd}\n onScrollToIndexFailed={onScrollToIndexFailed}\n removeClippedSubviews\n windowSize={3}\n initialNumToRender={7}\n maxToRenderPerBatch={7}\n updateCellsBatchingPeriod={50}\n scrollEventThrottle={16}\n />\n </View>\n\n <Typography.Body alignSelf=\"center\">{label}</Typography.Body>\n </View>\n );\n});\n\nfunction themedStyles(theme: AppTheme) {\n const columnTokens = theme.components.timePicker.column;\n\n return StyleSheet.create({\n contentContainer: {\n paddingVertical: columnTokens.verticalPadding,\n },\n pressable: {\n alignItems: \"center\",\n height: columnTokens.itemHeight,\n justifyContent: \"center\",\n width: columnTokens.listWidth,\n },\n });\n}\n"],"mappings":"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","names":["PickerColumn"]}
1
+ {"version":3,"sources":["../../../src/components/time/picker-column.tsx"],"sourcesContent":["import type {\n ListRenderItemInfo,\n NativeScrollEvent,\n NativeSyntheticEvent,\n} from \"react-native\";\nimport { memo, useCallback, useEffect, useRef } from \"react\";\nimport { FlatList, StyleSheet } from \"react-native\";\n\nimport type { AppTheme, FontWeightValue } from \"@impulse-ui-native/theme\";\nimport { Pressable, Typography, View } from \"@impulse-ui-native/primitives\";\nimport {\n getSelectionItemStateTokens,\n useComponentsTokens,\n useThemedStyles,\n} from \"@impulse-ui-native/theme\";\n\nimport { getClosestIndexByValue } from \"../../utils\";\n\ninterface PickerColumnProps {\n data: number[];\n label: string;\n type: \"hour\" | \"minute\" | \"second\";\n format: \"12h\" | \"24h\";\n value?: number;\n initialScrollIndex?: number;\n onChange?: (value: number) => void;\n}\n\nexport const PickerColumn = memo(function PickerColumn(\n props: PickerColumnProps,\n) {\n const { data, label, value, initialScrollIndex = 0, onChange } = props;\n\n const listRef = useRef<FlatList<number>>(null);\n const currentIndexRef = useRef(initialScrollIndex);\n const tokens = useComponentsTokens();\n const columnTokens = tokens.timePicker.column;\n const styles = useThemedStyles(themedStyles);\n\n const keyExtractor = useCallback((item: number, index: number) => {\n return `${item}-${index}`;\n }, []);\n\n const getItemLayout = useCallback(\n (_: ArrayLike<number> | null | undefined, index: number) => {\n return {\n length: columnTokens.itemHeight,\n offset: columnTokens.itemHeight * index,\n index,\n };\n },\n [columnTokens.itemHeight],\n );\n\n const scrollToIndex = useCallback((index: number, animated: boolean) => {\n currentIndexRef.current = index;\n\n listRef.current?.scrollToIndex({\n index,\n animated,\n });\n }, []);\n\n const renderItem = useCallback(\n ({ item }: ListRenderItemInfo<number>) => {\n const selected = item === value;\n const appearanceTokens = getSelectionItemStateTokens(\n columnTokens.states,\n { selected },\n );\n const fontWeight = appearanceTokens.fontWeight as FontWeightValue;\n\n return (\n <Pressable style={styles.pressable}>\n <Typography.Master\n fontSize={columnTokens.fontSize}\n color={appearanceTokens.color}\n textAlign=\"center\"\n numberOfLines={1}\n fontWeight={fontWeight}\n numeric\n >\n {String(item).padStart(2, \"0\")}\n </Typography.Master>\n </Pressable>\n );\n },\n [columnTokens.fontSize, columnTokens.states, styles.pressable, value],\n );\n\n const onMomentumScrollEnd = useCallback(\n (event: NativeSyntheticEvent<NativeScrollEvent>) => {\n const offset = event.nativeEvent.contentOffset.y;\n const index = Math.round(offset / columnTokens.itemHeight);\n const newValue = data[index];\n\n if (newValue === value) {\n return;\n }\n\n currentIndexRef.current = index;\n\n if (newValue !== undefined) {\n onChange?.(newValue);\n }\n },\n [columnTokens.itemHeight, data, onChange, value],\n );\n\n const onScrollToIndexFailed = useCallback(() => {\n requestAnimationFrame(() => {\n listRef.current?.scrollToOffset({\n offset: initialScrollIndex * columnTokens.itemHeight,\n animated: false,\n });\n });\n }, [columnTokens.itemHeight, initialScrollIndex]);\n\n useEffect(() => {\n if (value === undefined) {\n return;\n }\n\n const closestIndex = getClosestIndexByValue(\n data,\n value,\n currentIndexRef.current,\n );\n\n if (closestIndex === -1 || closestIndex === currentIndexRef.current) {\n return;\n }\n\n scrollToIndex(closestIndex, true);\n }, [data, scrollToIndex, value]);\n\n return (\n <View\n width={columnTokens.width}\n height={columnTokens.height}\n flexDirection=\"row\"\n justifyContent=\"center\"\n gap={columnTokens.gap}\n >\n <View\n width={columnTokens.listWidth}\n height={columnTokens.height}\n overflow=\"hidden\"\n >\n <FlatList\n ref={listRef}\n data={data}\n renderItem={renderItem}\n keyExtractor={keyExtractor}\n getItemLayout={getItemLayout}\n snapToInterval={columnTokens.itemHeight}\n snapToAlignment=\"start\"\n decelerationRate=\"fast\"\n initialScrollIndex={initialScrollIndex}\n showsVerticalScrollIndicator={false}\n contentContainerStyle={styles.contentContainer}\n onMomentumScrollEnd={onMomentumScrollEnd}\n onScrollToIndexFailed={onScrollToIndexFailed}\n removeClippedSubviews\n windowSize={3}\n initialNumToRender={7}\n maxToRenderPerBatch={7}\n updateCellsBatchingPeriod={50}\n scrollEventThrottle={16}\n />\n </View>\n\n <Typography.Body alignSelf=\"center\">{label}</Typography.Body>\n </View>\n );\n});\n\nfunction themedStyles(theme: AppTheme) {\n const columnTokens = theme.components.timePicker.column;\n\n return StyleSheet.create({\n contentContainer: {\n paddingVertical: columnTokens.verticalPadding,\n },\n pressable: {\n alignItems: \"center\",\n height: columnTokens.itemHeight,\n justifyContent: \"center\",\n width: columnTokens.listWidth,\n },\n });\n}\n"],"mappings":"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","names":["PickerColumn"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@impulse-ui-native/datetime",
3
- "version": "3.0.0",
3
+ "version": "5.0.0",
4
4
  "description": "Date and time selection components for ImpulseUI Native applications.",
5
5
  "keywords": [
6
6
  "react-native",
@@ -28,13 +28,13 @@
28
28
  ],
29
29
  "sideEffects": false,
30
30
  "dependencies": {
31
- "@impulse-ui-native/core": "3.0.0",
32
- "@impulse-ui-native/flyout": "3.0.0",
33
- "@impulse-ui-native/theme": "3.0.0",
34
- "@impulse-ui-native/primitives": "3.0.0",
35
- "@impulse-ui-native/select": "3.0.0",
36
- "@impulse-ui-native/icon": "3.0.0",
37
- "@impulse-ui-native/portal": "3.0.0"
31
+ "@impulse-ui-native/primitives": "5.0.0",
32
+ "@impulse-ui-native/flyout": "5.0.0",
33
+ "@impulse-ui-native/select": "5.0.0",
34
+ "@impulse-ui-native/theme": "5.0.0",
35
+ "@impulse-ui-native/core": "5.0.0",
36
+ "@impulse-ui-native/icon": "5.0.0",
37
+ "@impulse-ui-native/portal": "5.0.0"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@types/react": "~19.2.14",