@juspay/blend-design-system 0.0.37-beta.6 → 0.0.37-beta.7

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 (39) hide show
  1. package/dist/components/DataTable/TableBody/types.d.ts +1 -0
  2. package/dist/components/DataTable/TableCell/types.d.ts +1 -0
  3. package/dist/components/DataTable/columnTypes.d.ts +5 -3
  4. package/dist/components/DataTable/dataTable.tokens.d.ts +4 -0
  5. package/dist/components/DataTable/types.d.ts +20 -2
  6. package/dist/components/DataTable/utils.d.ts +4 -3
  7. package/dist/components/Skeleton/hooks/useSkeletonBase.d.ts +7 -11
  8. package/dist/components/StatCardV2/StatCardV2.d.ts +1 -0
  9. package/dist/components/StatCardV2/StatCardV2NoData.d.ts +2 -2
  10. package/dist/components/StatCardV2/statcardV2.types.d.ts +1 -0
  11. package/dist/components/TabsV2/tabsV2.tokens.types.d.ts +3 -0
  12. package/dist/global-utils/GlobalUtils.d.ts +2 -1
  13. package/dist/main.js +24982 -24910
  14. package/dist/{node-CJ_Tft0g.js → node-C_DmV86X.js} +49 -25
  15. package/dist/node.js +1 -1
  16. package/dist/tokens.js +1 -1
  17. package/lib/components/Card/Card.tsx +1 -0
  18. package/lib/components/Charts/ChartHeader.tsx +4 -1
  19. package/lib/components/CodeBlock/CodeBlock.tsx +8 -4
  20. package/lib/components/DataTable/DataTable.tsx +2 -0
  21. package/lib/components/DataTable/TableBody/index.tsx +2 -0
  22. package/lib/components/DataTable/TableBody/types.ts +1 -0
  23. package/lib/components/DataTable/TableCell/index.tsx +45 -20
  24. package/lib/components/DataTable/TableCell/types.ts +1 -0
  25. package/lib/components/DataTable/columnTypes.ts +5 -3
  26. package/lib/components/DataTable/dataTable.tokens.ts +15 -0
  27. package/lib/components/DataTable/types.ts +33 -2
  28. package/lib/components/DataTable/utils.ts +91 -5
  29. package/lib/components/Skeleton/hooks/useSkeletonBase.ts +11 -1
  30. package/lib/components/StatCard/StatCard.tsx +10 -2
  31. package/lib/components/StatCardV2/StatCardV2.tsx +8 -6
  32. package/lib/components/StatCardV2/StatCardV2NoData.tsx +8 -6
  33. package/lib/components/StatCardV2/statcardV2.types.ts +1 -0
  34. package/lib/components/TabsV2/TabsV2List.tsx +5 -1
  35. package/lib/components/TabsV2/tabsV2.dark.tokens.ts +12 -0
  36. package/lib/components/TabsV2/tabsV2.light.tokens.ts +12 -0
  37. package/lib/components/TabsV2/tabsV2.tokens.types.ts +3 -0
  38. package/lib/global-utils/GlobalUtils.ts +10 -1
  39. package/package.json +1 -1
@@ -7,6 +7,7 @@ import {
7
7
  ColumnDefinition,
8
8
  ColumnType,
9
9
  PivotAggregationType,
10
+ DateFormat,
10
11
  } from './types'
11
12
  import {
12
13
  validateColumnData,
@@ -904,6 +905,91 @@ export const formatDate = (dateString: string): string => {
904
905
  }).format(date)
905
906
  }
906
907
 
908
+ /**
909
+ * Token map for the lightweight format-string parser. Supports the common
910
+ * dashboard tokens; anything else is passed through literally.
911
+ *
912
+ * YYYY -> 4-digit year YY -> 2-digit year
913
+ * MM -> 2-digit month MMM -> short month name (Jan)
914
+ * DD -> 2-digit day dd -> 2-digit day (alias)
915
+ * HH -> 24h hour (2-digit) hh -> 12h hour (2-digit)
916
+ * mm -> minutes (2-digit) ss -> seconds (2-digit)
917
+ * A -> AM/PM a -> am/pm
918
+ */
919
+ const FORMAT_TOKEN_PATTERN = /YYYY|YY|MMM|MM|dd|DD|HH|hh|mm|ss|A|a/g
920
+
921
+ const pad2 = (n: number): string => String(n).padStart(2, '0')
922
+
923
+ // Format a Date using a format string like "DD MMM YYYY, hh:mm A"
924
+ export const formatDateString = (date: Date, format: string): string => {
925
+ if (isNaN(date.getTime())) return '-'
926
+
927
+ const parts = new Intl.DateTimeFormat('en-US', {
928
+ year: 'numeric',
929
+ month: '2-digit',
930
+ day: '2-digit',
931
+ hour: '2-digit',
932
+ minute: '2-digit',
933
+ second: '2-digit',
934
+ hour12: false,
935
+ }).formatToParts(date)
936
+
937
+ const lookup: Record<string, string> = {}
938
+ for (const p of parts) {
939
+ if (p.type !== 'literal') lookup[p.type] = p.value
940
+ }
941
+
942
+ const year = lookup.year ?? ''
943
+ const monthNum = lookup.month ?? ''
944
+ const day = lookup.day ?? ''
945
+ const hour24 = lookup.hour ?? ''
946
+ const minute = lookup.minute ?? ''
947
+ const second = lookup.second ?? ''
948
+
949
+ // Short month name via a separate formatter (month: 'short' gives 'Jan' etc.)
950
+ const shortMonth = new Intl.DateTimeFormat('en-US', {
951
+ month: 'short',
952
+ }).format(date)
953
+
954
+ // Normalize the 24-hour value: some browsers/locales return "24" for
955
+ // midnight instead of "00". Convert 24 -> 0 so HH always prints 00.
956
+ const hourNumRaw = parseInt(hour24, 10)
957
+ const hourNum = hourNumRaw === 24 ? 0 : hourNumRaw
958
+ const hour12 = (hourNum % 12 || 12).toString()
959
+ const ampm = hourNum < 12 ? 'AM' : 'PM'
960
+
961
+ FORMAT_TOKEN_PATTERN.lastIndex = 0
962
+ return format.replace(FORMAT_TOKEN_PATTERN, (token) => {
963
+ switch (token) {
964
+ case 'YYYY':
965
+ return year
966
+ case 'YY':
967
+ return year.slice(-2)
968
+ case 'MMM':
969
+ return shortMonth
970
+ case 'MM':
971
+ return monthNum
972
+ case 'DD':
973
+ case 'dd':
974
+ return day
975
+ case 'HH':
976
+ return pad2(hourNum)
977
+ case 'hh':
978
+ return pad2(parseInt(hour12, 10))
979
+ case 'mm':
980
+ return minute
981
+ case 'ss':
982
+ return second
983
+ case 'A':
984
+ return ampm
985
+ case 'a':
986
+ return ampm.toLowerCase()
987
+ default:
988
+ return token
989
+ }
990
+ })
991
+ }
992
+
907
993
  export const updateColumnFilter = (
908
994
  currentFilters: ColumnFilter[],
909
995
  field: keyof Record<string, unknown>,
@@ -994,7 +1080,7 @@ const getExportValue = <T extends Record<string, unknown>>(
994
1080
  ) {
995
1081
  const dateData = value as {
996
1082
  date: Date | string
997
- format?: string
1083
+ format?: DateFormat
998
1084
  showTime?: boolean
999
1085
  }
1000
1086
  const date = new Date(dateData.date)
@@ -1267,7 +1353,7 @@ export const createMultiSelectData = (
1267
1353
 
1268
1354
  export const createDateData = (
1269
1355
  date: Date | string,
1270
- format?: string
1356
+ format?: DateFormat
1271
1357
  ): DateData => ({
1272
1358
  date,
1273
1359
  format,
@@ -1276,7 +1362,7 @@ export const createDateData = (
1276
1362
  export const createDateRangeData = (
1277
1363
  startDate: Date | string,
1278
1364
  endDate: Date | string,
1279
- format?: string
1365
+ format?: DateFormat
1280
1366
  ): DateRangeData => ({
1281
1367
  startDate,
1282
1368
  endDate,
@@ -1317,9 +1403,9 @@ const getExpectedTypeDescription = (columnType: ColumnType): string => {
1317
1403
  case ColumnType.MULTISELECT:
1318
1404
  return 'MultiSelectData { values: string[], labels?: string[] } or string[]'
1319
1405
  case ColumnType.DATE:
1320
- return 'DateData { date: Date | string, format?: string } or Date or string'
1406
+ return 'DateData { date: Date | string, format?: DateFormat } or Date or string'
1321
1407
  case ColumnType.DATE_RANGE:
1322
- return 'DateRangeData { startDate: Date | string, endDate: Date | string, format?: string }'
1408
+ return 'DateRangeData { startDate: Date | string, endDate: Date | string, format?: DateFormat }'
1323
1409
  case ColumnType.TEXT:
1324
1410
  return 'string or number'
1325
1411
  case ColumnType.NUMBER:
@@ -2,11 +2,21 @@ import { type ReactNode } from 'react'
2
2
  import { useResponsiveTokens } from '../../../hooks/useResponsiveTokens'
3
3
  import type { SkeletonTokensType } from '../skeleton.tokens'
4
4
 
5
+ export type UseSkeletonBaseResult = {
6
+ shouldRender: boolean
7
+ fallback: ReactNode | null
8
+ tokens: SkeletonTokensType | null
9
+ prefersReducedMotion: boolean
10
+ }
11
+
5
12
  /**
6
13
  * Shared hook for all skeleton components to eliminate code duplication
7
14
  * Handles token fetching, loading state, and motion preferences
8
15
  */
9
- export const useSkeletonBase = (loading: boolean, children?: ReactNode) => {
16
+ export const useSkeletonBase = (
17
+ loading: boolean,
18
+ children?: ReactNode
19
+ ): UseSkeletonBaseResult => {
10
20
  const tokens = useResponsiveTokens<SkeletonTokensType>('SKELETON')
11
21
 
12
22
  // Check for motion preferences (accessibility)
@@ -588,7 +588,11 @@ const StatCard = ({
588
588
  overflow="hidden"
589
589
  backgroundColor={statCardToken.backgroundColor}
590
590
  boxShadow={showBorder ? statCardToken.boxShadow : undefined}
591
- padding={`${statCardToken.padding.y} ${statCardToken.padding.x}`}
591
+ padding={
592
+ showBorder
593
+ ? `${statCardToken.padding.y} ${statCardToken.padding.x}`
594
+ : undefined
595
+ }
592
596
  display="flex"
593
597
  flexDirection="column"
594
598
  // gap={statCardToken.gap}
@@ -737,7 +741,11 @@ const StatCard = ({
737
741
  overflow="hidden"
738
742
  backgroundColor={statCardToken.backgroundColor}
739
743
  boxShadow={showBorder ? statCardToken.boxShadow : undefined}
740
- padding={`${statCardToken.padding.y} ${statCardToken.padding.x}`}
744
+ padding={
745
+ showBorder
746
+ ? `${statCardToken.padding.y} ${statCardToken.padding.x}`
747
+ : undefined
748
+ }
741
749
  display="flex"
742
750
  flexDirection="column"
743
751
  // gap={statCardToken.gap}
@@ -48,6 +48,7 @@ const StatCardV2 = forwardRef<HTMLDivElement, StatCardV2Props>(
48
48
  height,
49
49
  options,
50
50
  skeleton,
51
+ showBorder = true,
51
52
  ...props
52
53
  },
53
54
  ref
@@ -131,6 +132,7 @@ const StatCardV2 = forwardRef<HTMLDivElement, StatCardV2Props>(
131
132
  tokens={tokens}
132
133
  isSmallScreen={isSmallScreen}
133
134
  filteredProps={filteredProps}
135
+ showBorder={showBorder}
134
136
  />
135
137
  )
136
138
  }
@@ -141,14 +143,14 @@ const StatCardV2 = forwardRef<HTMLDivElement, StatCardV2Props>(
141
143
  display="flex"
142
144
  flexDirection="column"
143
145
  justifyContent="space-between"
144
- paddingTop={tokens.paddingTop}
145
- paddingBottom={tokens.paddingBottom}
146
- paddingLeft={tokens.paddingLeft}
147
- paddingRight={tokens.paddingRight}
148
- border={tokens.border}
146
+ paddingTop={showBorder ? tokens.paddingTop : undefined}
147
+ paddingBottom={showBorder ? tokens.paddingBottom : undefined}
148
+ paddingLeft={showBorder ? tokens.paddingLeft : undefined}
149
+ paddingRight={showBorder ? tokens.paddingRight : undefined}
150
+ border={showBorder ? tokens.border : undefined}
149
151
  borderRadius={tokens.borderRadius}
150
152
  backgroundColor={tokens.backgroundColor}
151
- boxShadow={tokens.boxShadow}
153
+ boxShadow={showBorder ? tokens.boxShadow : undefined}
152
154
  maxWidth={maxWidth ?? tokens.maxWidth}
153
155
  minWidth={minWidth ?? tokens.minWidth}
154
156
  width={width ?? tokens.width}
@@ -19,6 +19,7 @@ type StatCardV2NoDataProps = Pick<
19
19
  | 'minWidth'
20
20
  | 'width'
21
21
  | 'height'
22
+ | 'showBorder'
22
23
  > & {
23
24
  tokens: StatCardV2TokensType
24
25
  isSmallScreen: boolean
@@ -35,6 +36,7 @@ const StatCardV2NoData = ({
35
36
  minWidth,
36
37
  width,
37
38
  height,
39
+ showBorder = true,
38
40
  tokens,
39
41
  isSmallScreen,
40
42
  filteredProps,
@@ -47,14 +49,14 @@ const StatCardV2NoData = ({
47
49
  display="flex"
48
50
  flexDirection="column"
49
51
  justifyContent="space-between"
50
- paddingTop={tokens.paddingTop}
51
- paddingBottom={tokens.paddingBottom}
52
- paddingLeft={tokens.paddingLeft}
53
- paddingRight={tokens.paddingRight}
54
- border={tokens.border}
52
+ paddingTop={showBorder ? tokens.paddingTop : undefined}
53
+ paddingBottom={showBorder ? tokens.paddingBottom : undefined}
54
+ paddingLeft={showBorder ? tokens.paddingLeft : undefined}
55
+ paddingRight={showBorder ? tokens.paddingRight : undefined}
56
+ border={showBorder ? tokens.border : undefined}
55
57
  borderRadius={tokens.borderRadius}
56
58
  backgroundColor={tokens.backgroundColor}
57
- boxShadow={tokens.boxShadow}
59
+ boxShadow={showBorder ? tokens.boxShadow : undefined}
58
60
  maxWidth={maxWidth ?? tokens.maxWidth}
59
61
  minWidth={minWidth ?? tokens.minWidth}
60
62
  width={width ?? tokens.width}
@@ -84,5 +84,6 @@ export type StatCardV2Props = {
84
84
  options?: ChartV2Options
85
85
  skeleton?: StatCardV2SkeletonProps
86
86
  dropdownProps?: SingleSelectProps
87
+ showBorder?: boolean
87
88
  } & HTMLAttributes<HTMLDivElement> &
88
89
  StatCardV2Dimensions
@@ -343,6 +343,7 @@ const TabsV2List = forwardRef<HTMLDivElement, TabsV2ListProps>(
343
343
  data-element="tabs-list"
344
344
  data-status={expanded ? 'expanded' : 'collapsed'}
345
345
  style={{
346
+ width: '100%',
346
347
  position: stickyHeader ? 'sticky' : 'relative',
347
348
  top: stickyHeader ? offsetTop : 'auto',
348
349
  zIndex: stickyHeader
@@ -351,7 +352,10 @@ const TabsV2List = forwardRef<HTMLDivElement, TabsV2ListProps>(
351
352
  backgroundColor: stickyHeader
352
353
  ? stickyHeaderBackground
353
354
  : 'transparent',
354
- borderBottom: 'none',
355
+ borderBottom:
356
+ variant === TabsV2Variant.UNDERLINE && !hasAnySkeleton
357
+ ? tabsToken.tabList.borderBottom[variant]
358
+ : 'none',
355
359
  boxShadow: stickyHeader
356
360
  ? tabsToken.tabList.stickyHeader.boxShadow
357
361
  : 'none',
@@ -123,6 +123,12 @@ export const getTabsV2DarkTokens = (
123
123
  },
124
124
  },
125
125
  },
126
+ borderBottom: {
127
+ [TabsV2Variant.UNDERLINE]: `${foundationToken.border.width[1]} solid ${foundationToken.colors.gray[700]}`,
128
+ [TabsV2Variant.BOXED]: 'none',
129
+ [TabsV2Variant.FLOATING]: 'none',
130
+ [TabsV2Variant.PILLS]: 'none',
131
+ },
126
132
  activeIndicator: {
127
133
  height: foundationToken.border.width[2],
128
134
  color: foundationToken.colors.gray[200],
@@ -458,6 +464,12 @@ export const getTabsV2DarkTokens = (
458
464
  },
459
465
  },
460
466
  },
467
+ borderBottom: {
468
+ [TabsV2Variant.UNDERLINE]: `${foundationToken.border.width[1]} solid ${foundationToken.colors.gray[700]}`,
469
+ [TabsV2Variant.BOXED]: 'none',
470
+ [TabsV2Variant.FLOATING]: 'none',
471
+ [TabsV2Variant.PILLS]: 'none',
472
+ },
461
473
  activeIndicator: {
462
474
  height: foundationToken.border.width[2],
463
475
  color: foundationToken.colors.gray[200],
@@ -123,6 +123,12 @@ export const getTabsV2LightTokens = (
123
123
  },
124
124
  },
125
125
  },
126
+ borderBottom: {
127
+ [TabsV2Variant.UNDERLINE]: `${foundationToken.border.width[1]} solid ${foundationToken.colors.gray[200]}`,
128
+ [TabsV2Variant.BOXED]: 'none',
129
+ [TabsV2Variant.FLOATING]: 'none',
130
+ [TabsV2Variant.PILLS]: 'none',
131
+ },
126
132
  activeIndicator: {
127
133
  height: foundationToken.border.width[2],
128
134
  color: foundationToken.colors.gray[700],
@@ -458,6 +464,12 @@ export const getTabsV2LightTokens = (
458
464
  },
459
465
  },
460
466
  },
467
+ borderBottom: {
468
+ [TabsV2Variant.UNDERLINE]: `${foundationToken.border.width[1]} solid ${foundationToken.colors.gray[200]}`,
469
+ [TabsV2Variant.BOXED]: 'none',
470
+ [TabsV2Variant.FLOATING]: 'none',
471
+ [TabsV2Variant.PILLS]: 'none',
472
+ },
461
473
  activeIndicator: {
462
474
  height: foundationToken.border.width[2],
463
475
  color: foundationToken.colors.gray[700],
@@ -25,6 +25,9 @@ export type TabsV2TokensType = {
25
25
  }
26
26
  }
27
27
  }
28
+ borderBottom: {
29
+ [key in TabsV2Variant]: CSSObject['borderBottom']
30
+ }
28
31
  activeIndicator: {
29
32
  height: CSSObject['height']
30
33
  color: CSSObject['color']
@@ -18,7 +18,16 @@ export const capitalizeFirstLetter = (string: string): string => {
18
18
  return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase()
19
19
  }
20
20
 
21
- export const getTruncatedText = (text: string, limit?: number) => {
21
+ export type TruncatedTextResult = {
22
+ truncatedValue: string
23
+ fullValue: string
24
+ isTruncated: boolean
25
+ }
26
+
27
+ export const getTruncatedText = (
28
+ text: string,
29
+ limit?: number
30
+ ): TruncatedTextResult => {
22
31
  const shouldTruncate =
23
32
  typeof limit === 'number' && limit > 0 && text.length > limit
24
33
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@juspay/blend-design-system",
3
3
  "private": false,
4
- "version": "0.0.37-beta.6",
4
+ "version": "0.0.37-beta.7",
5
5
  "description": "A comprehensive React component library and design system by Juspay",
6
6
  "type": "module",
7
7
  "main": "./dist/main.js",