@opengovsg/oui 0.0.0-snapshot-20251216073051 → 0.0.0-snapshot-20260126025301

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 (113) hide show
  1. package/dist/cjs/accordion/accordion.cjs +189 -0
  2. package/dist/cjs/accordion/index.cjs +13 -0
  3. package/dist/cjs/avatar/avatar-context.cjs +12 -0
  4. package/dist/cjs/avatar/avatar-group-context.cjs +88 -0
  5. package/dist/cjs/avatar/avatar-group.cjs +60 -0
  6. package/dist/cjs/avatar/avatar.cjs +132 -0
  7. package/dist/cjs/avatar/hooks/use-img-loading-status.cjs +68 -0
  8. package/dist/cjs/avatar/index.cjs +23 -0
  9. package/dist/cjs/avatar/utils.cjs +9 -0
  10. package/dist/cjs/banner/banner.cjs +1 -1
  11. package/dist/cjs/button/button.cjs +13 -10
  12. package/dist/cjs/calendar/calendar-month-day-selector.cjs +2 -2
  13. package/dist/cjs/checkbox/checkbox.cjs +3 -3
  14. package/dist/cjs/combo-box/combo-box.cjs +2 -2
  15. package/dist/cjs/date-field/date-field.cjs +1 -1
  16. package/dist/cjs/date-picker/date-picker.cjs +5 -4
  17. package/dist/cjs/date-range-picker/date-range-picker.cjs +5 -5
  18. package/dist/cjs/file-dropzone/file-dropzone.cjs +13 -9
  19. package/dist/cjs/file-dropzone/file-info.cjs +3 -2
  20. package/dist/cjs/file-dropzone/utils.cjs +4 -4
  21. package/dist/cjs/index.cjs +33 -12
  22. package/dist/cjs/menu/menu.cjs +1 -1
  23. package/dist/cjs/modal/modal-content.cjs +1 -1
  24. package/dist/cjs/node_modules/.pnpm/lucide-react@0.475.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/user.cjs +22 -0
  25. package/dist/cjs/number-field/number-field.cjs +3 -3
  26. package/dist/cjs/range-calendar/range-calendar.cjs +1 -1
  27. package/dist/cjs/select/select.cjs +89 -17
  28. package/dist/cjs/system/react-utils/children.cjs +7 -0
  29. package/dist/cjs/tag-field/tag-field.cjs +3 -3
  30. package/dist/cjs/text-area-field/text-area-field.cjs +1 -1
  31. package/dist/cjs/text-field/text-field.cjs +1 -1
  32. package/dist/cjs/toast/toast.cjs +1 -1
  33. package/dist/esm/accordion/accordion.js +182 -0
  34. package/dist/esm/accordion/index.js +2 -0
  35. package/dist/esm/avatar/avatar-context.js +9 -0
  36. package/dist/esm/avatar/avatar-group-context.js +84 -0
  37. package/dist/esm/avatar/avatar-group.js +58 -0
  38. package/dist/esm/avatar/avatar.js +128 -0
  39. package/dist/esm/avatar/hooks/use-img-loading-status.js +66 -0
  40. package/dist/esm/avatar/index.js +13 -0
  41. package/dist/esm/avatar/utils.js +7 -0
  42. package/dist/esm/banner/banner.js +1 -1
  43. package/dist/esm/button/button.js +13 -10
  44. package/dist/esm/calendar/calendar-month-day-selector.js +2 -2
  45. package/dist/esm/checkbox/checkbox.js +3 -3
  46. package/dist/esm/combo-box/combo-box.js +2 -2
  47. package/dist/esm/date-field/date-field.js +1 -1
  48. package/dist/esm/date-picker/date-picker.js +5 -4
  49. package/dist/esm/date-range-picker/date-range-picker.js +5 -5
  50. package/dist/esm/file-dropzone/file-dropzone.js +13 -9
  51. package/dist/esm/file-dropzone/file-info.js +3 -2
  52. package/dist/esm/file-dropzone/utils.js +4 -4
  53. package/dist/esm/index.js +9 -3
  54. package/dist/esm/menu/menu.js +1 -1
  55. package/dist/esm/modal/modal-content.js +1 -1
  56. package/dist/esm/node_modules/.pnpm/lucide-react@0.475.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/user.js +17 -0
  57. package/dist/esm/number-field/number-field.js +3 -3
  58. package/dist/esm/range-calendar/range-calendar.js +1 -1
  59. package/dist/esm/select/select.js +92 -20
  60. package/dist/esm/system/react-utils/children.js +7 -1
  61. package/dist/esm/tag-field/tag-field.js +3 -3
  62. package/dist/esm/text-area-field/text-area-field.js +1 -1
  63. package/dist/esm/text-field/text-field.js +1 -1
  64. package/dist/esm/toast/toast.js +1 -1
  65. package/dist/types/accordion/accordion.d.ts +50 -0
  66. package/dist/types/accordion/accordion.d.ts.map +1 -0
  67. package/dist/types/accordion/index.d.ts +2 -0
  68. package/dist/types/accordion/index.d.ts.map +1 -0
  69. package/dist/types/avatar/avatar-context.d.ts +12 -0
  70. package/dist/types/avatar/avatar-context.d.ts.map +1 -0
  71. package/dist/types/avatar/avatar-group-context.d.ts +70 -0
  72. package/dist/types/avatar/avatar-group-context.d.ts.map +1 -0
  73. package/dist/types/avatar/avatar-group.d.ts +5 -0
  74. package/dist/types/avatar/avatar-group.d.ts.map +1 -0
  75. package/dist/types/avatar/avatar.d.ts +18 -0
  76. package/dist/types/avatar/avatar.d.ts.map +1 -0
  77. package/dist/types/avatar/hooks/use-img-loading-status.d.ts +4 -0
  78. package/dist/types/avatar/hooks/use-img-loading-status.d.ts.map +1 -0
  79. package/dist/types/avatar/index.d.ts +15 -0
  80. package/dist/types/avatar/index.d.ts.map +1 -0
  81. package/dist/types/avatar/utils.d.ts +2 -0
  82. package/dist/types/avatar/utils.d.ts.map +1 -0
  83. package/dist/types/button/button.d.ts +12 -6
  84. package/dist/types/button/button.d.ts.map +1 -1
  85. package/dist/types/calendar/calendar.d.ts.map +1 -1
  86. package/dist/types/checkbox/checkbox-group-style-context.d.ts +1 -1
  87. package/dist/types/checkbox/checkbox-group-style-context.d.ts.map +1 -1
  88. package/dist/types/date-field/date-field.d.ts.map +1 -1
  89. package/dist/types/file-dropzone/file-dropzone.d.ts +8 -2
  90. package/dist/types/file-dropzone/file-dropzone.d.ts.map +1 -1
  91. package/dist/types/file-dropzone/file-info.d.ts.map +1 -1
  92. package/dist/types/file-dropzone/types.d.ts +1 -0
  93. package/dist/types/file-dropzone/types.d.ts.map +1 -1
  94. package/dist/types/file-dropzone/utils.d.ts +2 -1
  95. package/dist/types/file-dropzone/utils.d.ts.map +1 -1
  96. package/dist/types/index.d.mts +2 -0
  97. package/dist/types/index.d.ts +2 -0
  98. package/dist/types/index.d.ts.map +1 -1
  99. package/dist/types/menu/menu.d.ts.map +1 -1
  100. package/dist/types/range-calendar/range-calendar.d.ts.map +1 -1
  101. package/dist/types/select/select-item.d.ts +1 -2
  102. package/dist/types/select/select-item.d.ts.map +1 -1
  103. package/dist/types/select/select.d.ts +14 -0
  104. package/dist/types/select/select.d.ts.map +1 -1
  105. package/dist/types/system/react-utils/children.d.ts +3 -0
  106. package/dist/types/system/react-utils/children.d.ts.map +1 -1
  107. package/dist/types/system/react-utils/context.d.ts +4 -4
  108. package/dist/types/system/react-utils/context.d.ts.map +1 -1
  109. package/dist/types/system/utils.d.ts.map +1 -1
  110. package/dist/types/tabs/tabs.d.ts.map +1 -1
  111. package/dist/types/tag-field/tag-field-item.d.ts.map +1 -1
  112. package/dist/types/tag-field/tag-field-list.d.ts.map +1 -1
  113. package/package.json +8 -8
@@ -4,8 +4,8 @@ import { jsxs, jsx } from 'react/jsx-runtime';
4
4
  import { useMemo } from 'react';
5
5
  import { DateField as DateField$1, DateInput as DateInput$1, DateSegment } from 'react-aria-components';
6
6
  import { dateFieldStyles, composeTailwindRenderProps, dateInputStyles, composeRenderProps } from '@opengovsg/oui-theme';
7
- import { mapPropsVariants } from '../system/utils.js';
8
7
  import { Label, Description, FieldError } from '../field/field.js';
8
+ import { mapPropsVariants } from '../system/utils.js';
9
9
 
10
10
  function DateField(originalProps) {
11
11
  const [
@@ -4,13 +4,14 @@ import { jsxs, jsx } from 'react/jsx-runtime';
4
4
  import { useMemo } from 'react';
5
5
  import { DatePicker as DatePicker$1, Dialog } from 'react-aria-components';
6
6
  import { datePickerStyles, composeTailwindRenderProps } from '@opengovsg/oui-theme';
7
- import { mapPropsVariants } from '../system/utils.js';
8
- import { DateInput } from '../date-field/date-field.js';
9
- import Calendar from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/calendar.js';
7
+ import { Button } from '../button/button.js';
10
8
  import { Calendar as Calendar$1 } from '../calendar/calendar.js';
9
+ import '@internationalized/date';
10
+ import { DateInput } from '../date-field/date-field.js';
11
11
  import { Label, FieldGroup, Description, FieldError } from '../field/field.js';
12
- import { Button } from '../button/button.js';
13
12
  import { Popover } from '../popover/popover.js';
13
+ import { mapPropsVariants } from '../system/utils.js';
14
+ import Calendar from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/calendar.js';
14
15
 
15
16
  function DatePicker(originalProps) {
16
17
  const [
@@ -5,13 +5,13 @@ import { useMemo } from 'react';
5
5
  import { CalendarDate } from '@internationalized/date';
6
6
  import { DateRangePicker as DateRangePicker$1, Dialog } from 'react-aria-components';
7
7
  import { dateRangePickerStyles, composeTailwindRenderProps } from '@opengovsg/oui-theme';
8
- import { mapPropsVariants } from '../system/utils.js';
9
- import Calendar from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/calendar.js';
10
- import { RangeCalendar } from '../range-calendar/range-calendar.js';
11
- import { Label, FieldGroup, Description, FieldError } from '../field/field.js';
12
- import { DateInput } from '../date-field/date-field.js';
13
8
  import { Button } from '../button/button.js';
9
+ import { DateInput } from '../date-field/date-field.js';
10
+ import { Label, FieldGroup, Description, FieldError } from '../field/field.js';
14
11
  import { Popover } from '../popover/popover.js';
12
+ import { RangeCalendar } from '../range-calendar/range-calendar.js';
13
+ import { mapPropsVariants } from '../system/utils.js';
14
+ import Calendar from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/calendar.js';
15
15
 
16
16
  function DateRangePicker(originalProps) {
17
17
  const [
@@ -7,13 +7,13 @@ import { useField, useId } from 'react-aria';
7
7
  import { Provider, LabelContext, GroupContext, TextContext, FieldErrorContext, Group } from 'react-aria-components';
8
8
  import { useDropzone } from 'react-dropzone';
9
9
  import { fileDropzoneStyles, dataAttr } from '@opengovsg/oui-theme';
10
+ import { Label, Description, FieldError } from '../field/field.js';
11
+ import { useControllableState } from '../hooks/use-controllable-state.js';
10
12
  import { mapPropsVariants } from '../system/utils.js';
11
13
  import { FileDropzoneStyleContext, FileDropzoneStateContext, useFileDropzoneStateContext, useFileDropzoneStyleContext } from './contexts.js';
12
14
  import { FileInfo } from './file-info.js';
13
15
  import { formatErrorMessage, formatBytes } from './utils.js';
14
- import { useControllableState } from '../hooks/use-controllable-state.js';
15
16
  import Upload from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/upload.js';
16
- import { Label, Description, FieldError } from '../field/field.js';
17
17
 
18
18
  const FileDropzone = (originalProps) => {
19
19
  const [props, variantProps] = mapPropsVariants(
@@ -23,6 +23,7 @@ const FileDropzone = (originalProps) => {
23
23
  const {
24
24
  name,
25
25
  allowedMimeTypes = [],
26
+ fileSizeBase = "binary",
26
27
  maxFileSize = Number.POSITIVE_INFINITY,
27
28
  minFileSize = 0,
28
29
  showFileSizeText = true,
@@ -67,9 +68,10 @@ const FileDropzone = (originalProps) => {
67
68
  (error) => formatErrorMessage(error, {
68
69
  maxFileSize,
69
70
  minFileSize,
70
- maxFiles
71
+ maxFiles,
72
+ fileSizeBase
71
73
  }),
72
- [maxFileSize, maxFiles, minFileSize]
74
+ [fileSizeBase, maxFileSize, maxFiles, minFileSize]
73
75
  );
74
76
  const onDrop = useCallback(
75
77
  (acceptedFiles, fileRejections) => {
@@ -127,19 +129,20 @@ const FileDropzone = (originalProps) => {
127
129
  const shouldShow = showFileSizeText && (notDefaultMaxFileSize || notDefaultMinFileSize);
128
130
  if (!shouldShow) return null;
129
131
  if (notDefaultMaxFileSize && notDefaultMinFileSize) {
130
- return `File size must be between ${formatBytes(minFileSize, 2)} and ${formatBytes(
132
+ return `File size must be between ${formatBytes(minFileSize, 2, fileSizeBase)} and ${formatBytes(
131
133
  maxFileSize,
132
- 2
134
+ 2,
135
+ fileSizeBase
133
136
  )}`;
134
137
  }
135
138
  if (notDefaultMaxFileSize) {
136
- return `Maximum file size: ${formatBytes(maxFileSize, 2)}`;
139
+ return `Maximum file size: ${formatBytes(maxFileSize, 2, fileSizeBase)}`;
137
140
  }
138
141
  if (notDefaultMinFileSize) {
139
- return `Minimum file size: ${formatBytes(minFileSize, 2)}`;
142
+ return `Minimum file size: ${formatBytes(minFileSize, 2, fileSizeBase)}`;
140
143
  }
141
144
  return null;
142
- }, [maxFileSize, minFileSize, showFileSizeText]);
145
+ }, [maxFileSize, minFileSize, showFileSizeText, fileSizeBase]);
143
146
  const triggerFileSelector = useCallback(() => {
144
147
  if (isDisabled || isReadOnly) return;
145
148
  dropzoneState.inputRef.current?.click();
@@ -185,6 +188,7 @@ const FileDropzone = (originalProps) => {
185
188
  {
186
189
  isDisabled,
187
190
  isReadOnly,
191
+ fileSizeBase,
188
192
  maxFiles,
189
193
  maxFileSize,
190
194
  showDropzone,
@@ -3,10 +3,10 @@
3
3
  import { jsxs, jsx } from 'react/jsx-runtime';
4
4
  import { useState, useEffect } from 'react';
5
5
  import { fileInfoDropzoneStyles, cn } from '@opengovsg/oui-theme';
6
+ import { Button } from '../button/button.js';
6
7
  import { useFileDropzoneStateContext, useFileDropzoneStyleContext } from './contexts.js';
7
8
  import { formatBytes } from './utils.js';
8
9
  import Trash2 from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/trash-2.js';
9
- import { Button } from '../button/button.js';
10
10
 
11
11
  const FileInfo = ({ file, imagePreview, classNames }) => {
12
12
  const {
@@ -17,7 +17,8 @@ const FileInfo = ({ file, imagePreview, classNames }) => {
17
17
  isReadOnly
18
18
  } = useFileDropzoneStateContext();
19
19
  const { size, variant, itemClassNames } = useFileDropzoneStyleContext();
20
- const readableFileSize = formatBytes(file.size, 2);
20
+ const { fileSizeBase } = useFileDropzoneStateContext();
21
+ const readableFileSize = formatBytes(file.size, 2, fileSizeBase);
21
22
  const styles = fileInfoDropzoneStyles({
22
23
  size,
23
24
  variant,
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  import { ErrorCode } from 'react-dropzone';
3
3
 
4
- const formatBytes = (bytes, decimals = 2, size) => {
5
- const k = 1e3;
4
+ const formatBytes = (bytes, decimals = 2, base = "binary", size) => {
5
+ const k = base === "binary" ? 1024 : 1e3;
6
6
  const dm = decimals < 0 ? 0 : decimals;
7
7
  const sizes = ["bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
8
8
  if (bytes === 0 || bytes === void 0)
@@ -14,9 +14,9 @@ const formatErrorMessage = (error, config) => {
14
14
  const { maxFileSize, minFileSize, maxFiles } = config;
15
15
  switch (error.code) {
16
16
  case ErrorCode.FileTooLarge:
17
- return `You have exceeded the size limit, please upload a file below ${formatBytes(maxFileSize, 2)}`;
17
+ return `You have exceeded the size limit, please upload a file below ${formatBytes(maxFileSize, 2, config.fileSizeBase)}`;
18
18
  case ErrorCode.FileTooSmall:
19
- return `Please upload a file above ${formatBytes(minFileSize, 2)}`;
19
+ return `Please upload a file above ${formatBytes(minFileSize, 2, config.fileSizeBase)}`;
20
20
  case ErrorCode.TooManyFiles:
21
21
  return `Maximum number of files allowed is ${maxFiles}.`;
22
22
  default: {
package/dist/esm/index.js CHANGED
@@ -25,10 +25,10 @@ export { Select } from './select/select.js';
25
25
  export { SelectItem } from './select/select-item.js';
26
26
  export { SelectVariantContext, useSelectVariantContext } from './select/select-variant-context.js';
27
27
  export { Badge } from './badge/badge.js';
28
- export { CalendarDate } from '@internationalized/date';
29
28
  export { Calendar, CalendarStateWrapper } from './calendar/calendar.js';
30
29
  export { CalendarStyleContext, useCalendarStyleContext } from './calendar/calendar-style-context.js';
31
30
  export { getEraFormat, useGenerateLocalizedMonths, useGenerateLocalizedYears, useLocalizedMonthYear } from './calendar/utils.js';
31
+ export { CalendarDate } from '@internationalized/date';
32
32
  export { RangeCalendar, RangeCalendarCell, RangeCalendarStateWrapper } from './range-calendar/range-calendar.js';
33
33
  export { Menu, MenuItem, MenuSection, MenuSeparator, MenuTrigger, MenuVariantContext, SubmenuTrigger, useMenuVariantContext } from './menu/menu.js';
34
34
  export { Popover } from './popover/popover.js';
@@ -38,10 +38,10 @@ export { DatePicker } from './date-picker/date-picker.js';
38
38
  export { DateRangePicker } from './date-range-picker/date-range-picker.js';
39
39
  export { Checkbox, CheckboxGroup } from './checkbox/checkbox.js';
40
40
  export { CheckboxGroupStyleContext, useCheckboxGroupStyleContext } from './checkbox/checkbox-group-style-context.js';
41
- export { PaginationItemType } from './pagination/hooks/use-pagination.js';
42
41
  export { Pagination } from './pagination/pagination.js';
43
42
  export { PaginationCursor } from './pagination/pagination-cursor.js';
44
43
  export { PaginationItem } from './pagination/pagination-item.js';
44
+ export { PaginationItemType } from './pagination/hooks/use-pagination.js';
45
45
  export { CURSOR_TRANSITION_TIMEOUT, usePagination } from './pagination/use-pagination.js';
46
46
  export { FileDropzone } from './file-dropzone/file-dropzone.js';
47
47
  export { FileInfo } from './file-dropzone/file-info.js';
@@ -54,7 +54,6 @@ export { ModalBody } from './modal/modal-body.js';
54
54
  export { ModalHeader } from './modal/modal-header.js';
55
55
  export { ModalVariantContext, useModalVariantContext } from './modal/modal-variant-context.js';
56
56
  export { Toaster } from './toast/toast.js';
57
- export { toast } from 'sonner';
58
57
  export { Navbar } from './navbar/navbar.js';
59
58
  export { NavbarBrand } from './navbar/navbar-brand.js';
60
59
  export { NavbarContent } from './navbar/navbar-content.js';
@@ -64,3 +63,10 @@ export { NavbarMenuToggle } from './navbar/navbar-menu/toggle.js';
64
63
  export { NavbarItem } from './navbar/navbar-item.js';
65
64
  export { useNavbar } from './navbar/use-navbar.js';
66
65
  export { NavbarProvider, useNavbarContext } from './navbar/navbar-context.js';
66
+ export { Avatar } from './avatar/index.js';
67
+ export { Accordion, AccordionContent, AccordionHeader, AccordionItem, AccordionStyleContext, useAccordionStyleContext } from './accordion/accordion.js';
68
+ export { toast } from 'sonner';
69
+ export { AvatarContext, useAvatarContext } from './avatar/avatar-context.js';
70
+ export { AvatarGroup } from './avatar/avatar-group.js';
71
+ export { AvatarGroupProvider, useAvatarGroup } from './avatar/avatar-group-context.js';
72
+ export { AvatarFallback, AvatarImage, AvatarRoot } from './avatar/avatar.js';
@@ -4,11 +4,11 @@ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
4
  import { forwardRef, useMemo, useCallback } from 'react';
5
5
  import { useContextProps, MenuItem as MenuItem$1, composeRenderProps, Provider, Menu as Menu$1, MenuSection as MenuSection$1, Header, Collection, MenuTrigger as MenuTrigger$1, SubmenuTrigger as SubmenuTrigger$1, Separator } from 'react-aria-components';
6
6
  import { listBoxItemStyles, menuItemStyles, menuStyles, menuSectionStyles, menuDividerStyles } from '@opengovsg/oui-theme';
7
+ import { Popover } from '../popover/popover.js';
7
8
  import { forwardRefGeneric, mapPropsVariants } from '../system/utils.js';
8
9
  import { createContext } from '../system/react-utils/context.js';
9
10
  import Check from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/check.js';
10
11
  import ChevronRight from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/chevron-right.js';
11
- import { Popover } from '../popover/popover.js';
12
12
 
13
13
  const [MenuVariantContext, useMenuVariantContext] = createContext({
14
14
  name: "MenuVariantContext",
@@ -5,10 +5,10 @@ import { useContext, isValidElement } from 'react';
5
5
  import { useMessageFormatter } from 'react-aria';
6
6
  import { Dialog } from 'react-aria-components';
7
7
  import { cn } from '@opengovsg/oui-theme';
8
+ import { Button } from '../button/button.js';
8
9
  import { i18nStrings } from './i18n.js';
9
10
  import { ModalVariantContext } from './modal-variant-context.js';
10
11
  import X from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/x.js';
11
- import { Button } from '../button/button.js';
12
12
 
13
13
  function ModalContent({
14
14
  closeButtonContent: closeButtonContentProp,
@@ -0,0 +1,17 @@
1
+ import createLucideIcon from '../createLucideIcon.js';
2
+
3
+ /**
4
+ * @license lucide-react v0.475.0 - ISC
5
+ *
6
+ * This source code is licensed under the ISC license.
7
+ * See the LICENSE file in the root directory of this source tree.
8
+ */
9
+
10
+
11
+ const __iconNode = [
12
+ ["path", { d: "M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2", key: "975kel" }],
13
+ ["circle", { cx: "12", cy: "7", r: "4", key: "17ys0d" }]
14
+ ];
15
+ const User = createLucideIcon("User", __iconNode);
16
+
17
+ export { __iconNode, User as default };
@@ -3,12 +3,12 @@
3
3
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
4
4
  import { NumberField as NumberField$1 } from 'react-aria-components';
5
5
  import { numberFieldStyles, composeTailwindRenderProps, dataAttr, fieldBorderStyles, cn } from '@opengovsg/oui-theme';
6
+ import { Button } from '../button/button.js';
7
+ import { Label, FieldGroup, Description, FieldError } from '../field/field.js';
8
+ import { Input } from '../input/input.js';
6
9
  import { mapPropsVariants } from '../system/utils.js';
7
10
  import Minus from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/minus.js';
8
11
  import Plus from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/plus.js';
9
- import { Label, FieldGroup, Description, FieldError } from '../field/field.js';
10
- import { Input } from '../input/input.js';
11
- import { Button } from '../button/button.js';
12
12
 
13
13
  function NumberField(originalProps) {
14
14
  const [
@@ -6,12 +6,12 @@ import { CalendarDate, today, getLocalTimeZone, getDayOfWeek } from '@internatio
6
6
  import { RangeCalendar as RangeCalendar$1, Provider, CalendarGrid, CalendarGridBody, Text, RangeCalendarStateContext, useLocale, CalendarCell } from 'react-aria-components';
7
7
  import { useDeepCompareMemo } from 'use-deep-compare';
8
8
  import { calendarStyles, composeRenderProps, cn, dataAttr } from '@opengovsg/oui-theme';
9
+ import { CalendarStyleContext, useCalendarStyleContext } from '../calendar/calendar-style-context.js';
9
10
  import { AgnosticCalendarStateContext } from '../calendar/agnostic-calendar-state-context.js';
10
11
  import { CalendarBottomContent } from '../calendar/calendar-bottom-content.js';
11
12
  import { CalendarGridHeader } from '../calendar/calendar-grid-header.js';
12
13
  import { CalendarHeader } from '../calendar/calendar-header.js';
13
14
  import { forwardRefGeneric, mapPropsVariants } from '../system/utils.js';
14
- import { CalendarStyleContext, useCalendarStyleContext } from '../calendar/calendar-style-context.js';
15
15
 
16
16
  const RangeCalendar = forwardRefGeneric(function RangeCalendar2(originalProps, ref) {
17
17
  const [props, variantProps] = mapPropsVariants(
@@ -1,16 +1,35 @@
1
1
  "use strict";
2
2
  "use client";
3
3
  import { jsx, jsxs } from 'react/jsx-runtime';
4
- import { useMemo } from 'react';
5
- import { Provider, Select as Select$1, SelectValue, Virtualizer, ListLayout, ListBox } from 'react-aria-components';
6
- import { selectStyles, composeRenderProps } from '@opengovsg/oui-theme';
4
+ import { useMemo, isValidElement, cloneElement } from 'react';
5
+ import { useLocalizedStringFormatter } from 'react-aria';
6
+ import { useFilter, Virtualizer, ListLayout, ListBox, Provider, Select as Select$1, SelectValue, Autocomplete, SearchField, Input } from 'react-aria-components';
7
+ import { selectStyles, cn, composeRenderProps } from '@opengovsg/oui-theme';
8
+ import { Button } from '../button/button.js';
9
+ import { Label, Description, FieldError } from '../field/field.js';
10
+ import { Popover } from '../popover/popover.js';
7
11
  import { mapPropsVariants } from '../system/utils.js';
8
12
  import { SelectVariantContext } from './select-variant-context.js';
9
- import { Label, Description, FieldError } from '../field/field.js';
10
13
  import ChevronDown from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/chevron-down.js';
11
- import { Popover } from '../popover/popover.js';
12
- import { Button } from '../button/button.js';
13
14
 
15
+ const i18nStrings = {
16
+ "en-SG": {
17
+ searchPlaceholder: "Search...",
18
+ searchAriaLabel: "Search options"
19
+ },
20
+ "zh-SG": {
21
+ searchPlaceholder: "\u641C\u7D22...",
22
+ searchAriaLabel: "\u641C\u7D22\u9009\u9879"
23
+ },
24
+ "ms-SG": {
25
+ searchPlaceholder: "Cari...",
26
+ searchAriaLabel: "Cari pilihan"
27
+ },
28
+ "ta-SG": {
29
+ searchPlaceholder: "\u0BA4\u0BC7\u0B9F\u0BC1...",
30
+ searchAriaLabel: "\u0BA4\u0BC7\u0B9F\u0BB2\u0BCD \u0BB5\u0BBF\u0BB0\u0BC1\u0BAA\u0BCD\u0BAA\u0B99\u0BCD\u0B95\u0BB3\u0BCD"
31
+ }
32
+ };
14
33
  const calculateEstimatedRowHeight = (size) => {
15
34
  switch (size) {
16
35
  case "xs":
@@ -28,12 +47,22 @@ function Select({
28
47
  errorMessage,
29
48
  ...originalProps
30
49
  }) {
50
+ const formatter = useLocalizedStringFormatter(i18nStrings);
31
51
  const [_props, variantProps] = mapPropsVariants(
32
52
  originalProps,
33
53
  selectStyles.variantKeys
34
54
  );
35
- const { items, children, listLayoutOptions, ...props } = _props;
55
+ const {
56
+ items,
57
+ children,
58
+ listLayoutOptions,
59
+ enableSearch = false,
60
+ searchPlaceholder,
61
+ searchIcon,
62
+ ...props
63
+ } = _props;
36
64
  const styles = selectStyles(variantProps);
65
+ const { contains } = useFilter({ sensitivity: "base" });
37
66
  const layoutOptions = useMemo(() => {
38
67
  return {
39
68
  estimatedRowHeight: calculateEstimatedRowHeight(
@@ -42,6 +71,37 @@ function Select({
42
71
  ...listLayoutOptions
43
72
  };
44
73
  }, [listLayoutOptions, variantProps.size]);
74
+ const renderedSearchIcon = useMemo(() => {
75
+ if (!enableSearch || !searchIcon) return null;
76
+ if (isValidElement(searchIcon)) {
77
+ const iconElement = searchIcon;
78
+ return cloneElement(iconElement, {
79
+ className: styles.searchIcon({
80
+ className: cn(classNames?.searchIcon, iconElement.props.className)
81
+ })
82
+ });
83
+ }
84
+ return /* @__PURE__ */ jsx(
85
+ "span",
86
+ {
87
+ className: styles.searchIcon({ className: classNames?.searchIcon }),
88
+ children: searchIcon
89
+ }
90
+ );
91
+ }, [classNames?.searchIcon, enableSearch, searchIcon, styles]);
92
+ const listContent = /* @__PURE__ */ jsx(Virtualizer, { layout: ListLayout, layoutOptions, children: /* @__PURE__ */ jsx(
93
+ ListBox,
94
+ {
95
+ autoFocus: !enableSearch,
96
+ items,
97
+ shouldFocusWrap: true,
98
+ className: composeRenderProps(
99
+ classNames?.list,
100
+ (className, renderProps) => styles.list({ className, ...renderProps })
101
+ ),
102
+ children
103
+ }
104
+ ) });
45
105
  return /* @__PURE__ */ jsx(Provider, { values: [[SelectVariantContext, variantProps]], children: /* @__PURE__ */ jsxs(
46
106
  Select$1,
47
107
  {
@@ -91,19 +151,31 @@ function Select({
91
151
  }
92
152
  ),
93
153
  /* @__PURE__ */ jsx(FieldError, { size: variantProps.size, className: classNames?.error, children: errorMessage }),
94
- /* @__PURE__ */ jsx(Popover, { className: styles.popover({ className: classNames?.popover }), children: /* @__PURE__ */ jsx(Virtualizer, { layout: ListLayout, layoutOptions, children: /* @__PURE__ */ jsx(
95
- ListBox,
96
- {
97
- autoFocus: true,
98
- items,
99
- shouldFocusWrap: true,
100
- className: composeRenderProps(
101
- classNames?.list,
102
- (className, renderProps) => styles.list({ className, ...renderProps })
103
- ),
104
- children
105
- }
106
- ) }) })
154
+ /* @__PURE__ */ jsx(Popover, { className: styles.popover({ className: classNames?.popover }), children: enableSearch ? /* @__PURE__ */ jsxs(Autocomplete, { filter: contains, children: [
155
+ /* @__PURE__ */ jsxs(
156
+ SearchField,
157
+ {
158
+ autoFocus: true,
159
+ "aria-label": formatter.format("searchAriaLabel"),
160
+ className: styles.searchField({
161
+ className: classNames?.searchField
162
+ }),
163
+ children: [
164
+ renderedSearchIcon,
165
+ /* @__PURE__ */ jsx(
166
+ Input,
167
+ {
168
+ placeholder: searchPlaceholder ?? formatter.format("searchPlaceholder"),
169
+ className: styles.searchInput({
170
+ className: classNames?.searchInput
171
+ })
172
+ }
173
+ )
174
+ ]
175
+ }
176
+ ),
177
+ listContent
178
+ ] }) : listContent })
107
179
  ]
108
180
  }
109
181
  ) });
@@ -19,5 +19,11 @@ const pickChildren = (children, targetChild) => {
19
19
  const targetChildren = target.length >= 0 ? target : void 0;
20
20
  return [withoutTargetChildren, targetChildren];
21
21
  };
22
+ const renderChildren = (renderProps, children) => {
23
+ if (typeof children === "function") {
24
+ return children(renderProps);
25
+ }
26
+ return children;
27
+ };
22
28
 
23
- export { getValidChildren, pickChildren };
29
+ export { getValidChildren, pickChildren, renderChildren };
@@ -4,15 +4,15 @@ import { jsxs, jsx } from 'react/jsx-runtime';
4
4
  import { createElement } from 'react';
5
5
  import { composeRenderProps } from 'react-aria-components';
6
6
  import { tagFieldStyles } from '@opengovsg/oui-theme';
7
+ import { Label, FieldGroup, Description, FieldError } from '../field/field.js';
8
+ import { Input } from '../input/input.js';
9
+ import { Popover } from '../popover/popover.js';
7
10
  import { TagFieldItem } from './tag-field-item.js';
8
11
  import { TagFieldList } from './tag-field-list.js';
9
12
  import { TagFieldRoot } from './tag-field-root.js';
10
13
  import { TagFieldTagList } from './tag-field-tag-list.js';
11
14
  import { TagFieldTrigger } from './tag-field-trigger.js';
12
15
  import ChevronDown from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/chevron-down.js';
13
- import { Label, FieldGroup, Description, FieldError } from '../field/field.js';
14
- import { Input } from '../input/input.js';
15
- import { Popover } from '../popover/popover.js';
16
16
 
17
17
  function TagField({
18
18
  classNames,
@@ -3,8 +3,8 @@
3
3
  import { jsxs, jsx } from 'react/jsx-runtime';
4
4
  import { TextField } from 'react-aria-components';
5
5
  import { composeTailwindRenderProps } from '@opengovsg/oui-theme';
6
- import { TextArea } from '../text-area/text-area.js';
7
6
  import { Label, Description, FieldError } from '../field/field.js';
7
+ import { TextArea } from '../text-area/text-area.js';
8
8
 
9
9
  function TextAreaField({
10
10
  label,
@@ -3,8 +3,8 @@
3
3
  import { jsxs, jsx } from 'react/jsx-runtime';
4
4
  import { TextField as TextField$1 } from 'react-aria-components';
5
5
  import { composeTailwindRenderProps } from '@opengovsg/oui-theme';
6
- import { Input } from '../input/input.js';
7
6
  import { Label, Description, FieldError } from '../field/field.js';
7
+ import { Input } from '../input/input.js';
8
8
 
9
9
  function TextField({
10
10
  label,
@@ -4,9 +4,9 @@ import { jsx } from 'react/jsx-runtime';
4
4
  import { Toaster as Toaster$1 } from 'sonner';
5
5
  export { toast } from 'sonner';
6
6
  import { toastStyles } from '@opengovsg/oui-theme';
7
+ import { Spinner } from '../spinner/spinner.js';
7
8
  import { mapPropsVariants } from '../system/utils.js';
8
9
  import X from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/x.js';
9
- import { Spinner } from '../spinner/spinner.js';
10
10
 
11
11
  function Toaster(originalProps) {
12
12
  const [{ toastOptions, closeButton = true, ...props }, variantProps] = mapPropsVariants(originalProps, toastStyles.variantKeys);
@@ -0,0 +1,50 @@
1
+ import type React from "react";
2
+ import type { DisclosurePanelProps as AriaDisclosurePanelProps, DisclosureProps as AriaDisclosureProps, ButtonRenderProps, DisclosureGroupProps, RenderProps } from "react-aria-components";
3
+ import type { AccordionSlots, AccordionVariantProps, SlotsToClasses } from "@opengovsg/oui-theme";
4
+ import { accordionStyles } from "@opengovsg/oui-theme";
5
+ export interface UseProvideAccordionStylesReturn {
6
+ slots: ReturnType<typeof accordionStyles>;
7
+ classNames?: SlotsToClasses<AccordionSlots>;
8
+ }
9
+ export declare const AccordionStyleContext: React.Context<UseProvideAccordionStylesReturn>, useAccordionStyleContext: () => UseProvideAccordionStylesReturn;
10
+ export interface AccordionItemProps extends Omit<AriaDisclosureProps, "isExpanded" | "defaultExpanded" | "onExpandedChange"> {
11
+ children: React.ReactNode;
12
+ classNames?: SlotsToClasses<AccordionSlots>;
13
+ }
14
+ export declare const AccordionItem: import("../system/utils").InternalForwardRefRenderFunction<"div", AccordionItemProps, never>;
15
+ export interface AccordionHeaderRenderProps extends ButtonRenderProps {
16
+ isExpanded: boolean;
17
+ }
18
+ export interface AccordionHeaderProps extends Pick<RenderProps<AccordionHeaderRenderProps>, "children"> {
19
+ classNames?: SlotsToClasses<Extract<AccordionSlots, "heading" | "title" | "trigger" | "indicator" | "startContentWrapper" | "endContentWrapper">>;
20
+ /**
21
+ * The indicator. Defaults to a chevron icon.
22
+ */
23
+ indicator?: RenderProps<AccordionHeaderRenderProps>["children"];
24
+ /**
25
+ * Whether to hide the indicator.
26
+ * @default false
27
+ */
28
+ hideIndicator?: boolean;
29
+ /**
30
+ * The header start content.
31
+ */
32
+ startContent?: RenderProps<AccordionHeaderRenderProps>["children"];
33
+ /**
34
+ * The header end content.
35
+ */
36
+ endContent?: RenderProps<AccordionHeaderRenderProps>["children"];
37
+ }
38
+ export declare function AccordionHeader({ children, classNames, indicator, startContent, endContent, hideIndicator, }: AccordionHeaderProps): import("react/jsx-runtime").JSX.Element;
39
+ export interface AccordionContentProps extends AriaDisclosurePanelProps {
40
+ children: React.ReactNode;
41
+ classNames?: SlotsToClasses<"panel" | "content">;
42
+ }
43
+ export declare function AccordionContent({ children, classNames, ...props }: AccordionContentProps): import("react/jsx-runtime").JSX.Element;
44
+ interface AccordionProps extends DisclosureGroupProps, AccordionVariantProps {
45
+ children: React.ReactNode;
46
+ classNames?: SlotsToClasses<AccordionSlots>;
47
+ }
48
+ export declare const Accordion: import("../system/utils").InternalForwardRefRenderFunction<"div", AccordionProps, never>;
49
+ export {};
50
+ //# sourceMappingURL=accordion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accordion.d.ts","sourceRoot":"","sources":["../../../src/accordion/accordion.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,EACV,oBAAoB,IAAI,wBAAwB,EAChD,eAAe,IAAI,mBAAmB,EACtC,iBAAiB,EACjB,oBAAoB,EACpB,WAAW,EACZ,MAAM,uBAAuB,CAAA;AAa9B,OAAO,KAAK,EACV,cAAc,EACd,qBAAqB,EACrB,cAAc,EACf,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EACL,eAAe,EAGhB,MAAM,sBAAsB,CAAA;AAM7B,MAAM,WAAW,+BAA+B;IAC9C,KAAK,EAAE,UAAU,CAAC,OAAO,eAAe,CAAC,CAAA;IACzC,UAAU,CAAC,EAAE,cAAc,CAAC,cAAc,CAAC,CAAA;CAC5C;AAED,eAAO,MAAO,qBAAqB,kDAAE,wBAAwB,uCAIzD,CAAA;AAEJ,MAAM,WAAW,kBACf,SAAQ,IAAI,CACV,mBAAmB,EACnB,YAAY,GAAG,iBAAiB,GAAG,kBAAkB,CACtD;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,UAAU,CAAC,EAAE,cAAc,CAAC,cAAc,CAAC,CAAA;CAC5C;AAED,eAAO,MAAM,aAAa,8FAkBzB,CAAA;AAGD,MAAM,WAAW,0BAA2B,SAAQ,iBAAiB;IACnE,UAAU,EAAE,OAAO,CAAA;CACpB;AAED,MAAM,WAAW,oBACf,SAAQ,IAAI,CAAC,WAAW,CAAC,0BAA0B,CAAC,EAAE,UAAU,CAAC;IACjE,UAAU,CAAC,EAAE,cAAc,CACzB,OAAO,CACL,cAAc,EACZ,SAAS,GACT,OAAO,GACP,SAAS,GACT,WAAW,GACX,qBAAqB,GACrB,mBAAmB,CACtB,CACF,CAAA;IAED;;OAEG;IACH,SAAS,CAAC,EAAE,WAAW,CAAC,0BAA0B,CAAC,CAAC,UAAU,CAAC,CAAA;IAE/D;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IAEvB;;OAEG;IACH,YAAY,CAAC,EAAE,WAAW,CAAC,0BAA0B,CAAC,CAAC,UAAU,CAAC,CAAA;IAClE;;OAEG;IACH,UAAU,CAAC,EAAE,WAAW,CAAC,0BAA0B,CAAC,CAAC,UAAU,CAAC,CAAA;CACjE;AAED,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,UAAU,EACV,SAAS,EACT,YAAY,EACZ,UAAU,EACV,aAAqB,GACtB,EAAE,oBAAoB,2CA6EtB;AAED,MAAM,WAAW,qBAAsB,SAAQ,wBAAwB;IACrE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,UAAU,CAAC,EAAE,cAAc,CAAC,OAAO,GAAG,SAAS,CAAC,CAAA;CACjD;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,QAAQ,EACR,UAAU,EACV,GAAG,KAAK,EACT,EAAE,qBAAqB,2CAuBvB;AAED,UAAU,cAAe,SAAQ,oBAAoB,EAAE,qBAAqB;IAC1E,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,UAAU,CAAC,EAAE,cAAc,CAAC,cAAc,CAAC,CAAA;CAC5C;AAED,eAAO,MAAM,SAAS,0FA0BrB,CAAA"}
@@ -0,0 +1,2 @@
1
+ export * from "./accordion";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/accordion/index.tsx"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA"}
@@ -0,0 +1,12 @@
1
+ import type { AvatarSlots, avatarStyles, SlotsToClasses } from "@opengovsg/oui-theme";
2
+ import type { ImageLoadingStatus } from "./hooks/use-img-loading-status";
3
+ export interface UseAvatarContextReturn {
4
+ imageLoadingStatus: ImageLoadingStatus;
5
+ setImageLoadingStatus: React.Dispatch<React.SetStateAction<ImageLoadingStatus>>;
6
+ slots: ReturnType<typeof avatarStyles>;
7
+ classNames?: SlotsToClasses<AvatarSlots>;
8
+ name?: string;
9
+ getInitials: (name: string) => string;
10
+ }
11
+ export declare const AvatarContext: import("react").Context<UseAvatarContextReturn>, useAvatarContext: () => UseAvatarContextReturn;
12
+ //# sourceMappingURL=avatar-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"avatar-context.d.ts","sourceRoot":"","sources":["../../../src/avatar/avatar-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,YAAY,EACZ,cAAc,EACf,MAAM,sBAAsB,CAAA;AAE7B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA;AAGxE,MAAM,WAAW,sBAAsB;IACrC,kBAAkB,EAAE,kBAAkB,CAAA;IACtC,qBAAqB,EAAE,KAAK,CAAC,QAAQ,CACnC,KAAK,CAAC,cAAc,CAAC,kBAAkB,CAAC,CACzC,CAAA;IACD,KAAK,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAA;IACtC,UAAU,CAAC,EAAE,cAAc,CAAC,WAAW,CAAC,CAAA;IACxC,IAAI,CAAC,EAAE,MAAM,CAAA;IAEb,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;CACtC;AACD,eAAO,MAAO,aAAa,mDAAE,gBAAgB,8BAIzC,CAAA"}