@opengovsg/oui 0.0.31 → 0.0.33

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.
@@ -0,0 +1,189 @@
1
+ "use strict";
2
+ "use client";
3
+ 'use strict';
4
+
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+ var $670gB$react = require('react');
7
+ var reactAriaComponents = require('react-aria-components');
8
+ var ouiTheme = require('@opengovsg/oui-theme');
9
+ var children = require('../system/react-utils/children.cjs');
10
+ var utils = require('../system/utils.cjs');
11
+ var context = require('../system/react-utils/context.cjs');
12
+ var chevronDown = require('../node_modules/.pnpm/lucide-react@0.475.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/chevron-down.cjs');
13
+
14
+ const [AccordionStyleContext, useAccordionStyleContext] = context.createContext({
15
+ name: "AccordionStyleContext",
16
+ strict: true
17
+ });
18
+ const AccordionItem = utils.forwardRef(
19
+ ({ classNames, className, children, ...props }, ref) => {
20
+ const { slots } = $670gB$react.useContext(AccordionStyleContext);
21
+ return /* @__PURE__ */ jsxRuntime.jsx(
22
+ reactAriaComponents.Disclosure,
23
+ {
24
+ ...props,
25
+ ref,
26
+ className: reactAriaComponents.composeRenderProps(
27
+ className,
28
+ (className2, renderProps) => slots.item({
29
+ ...renderProps,
30
+ className: ouiTheme.cn(classNames?.item, className2)
31
+ })
32
+ ),
33
+ children
34
+ }
35
+ );
36
+ }
37
+ );
38
+ AccordionItem.displayName = "AccordionItem";
39
+ function AccordionHeader({
40
+ children: children$1,
41
+ classNames,
42
+ indicator,
43
+ startContent,
44
+ endContent,
45
+ hideIndicator = false
46
+ }) {
47
+ const { slots, classNames: contextClassNames } = $670gB$react.useContext(
48
+ AccordionStyleContext
49
+ );
50
+ const { isExpanded } = $670gB$react.useContext(reactAriaComponents.DisclosureStateContext);
51
+ return /* @__PURE__ */ jsxRuntime.jsx(
52
+ reactAriaComponents.Heading,
53
+ {
54
+ className: slots.heading({
55
+ className: ouiTheme.cn(contextClassNames?.heading, classNames?.heading)
56
+ }),
57
+ children: /* @__PURE__ */ jsxRuntime.jsx(
58
+ reactAriaComponents.Button,
59
+ {
60
+ slot: "trigger",
61
+ className: slots.trigger({
62
+ className: ouiTheme.cn(contextClassNames?.trigger, classNames?.trigger)
63
+ }),
64
+ children: (buttonRenderProps) => {
65
+ const headerRenderProps = { ...buttonRenderProps, isExpanded };
66
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
67
+ startContent && /* @__PURE__ */ jsxRuntime.jsx(
68
+ "div",
69
+ {
70
+ className: slots.startContentWrapper({
71
+ className: ouiTheme.cn(
72
+ contextClassNames?.startContentWrapper,
73
+ classNames?.startContentWrapper
74
+ )
75
+ }),
76
+ children: children.renderChildren(headerRenderProps, startContent)
77
+ }
78
+ ),
79
+ /* @__PURE__ */ jsxRuntime.jsx(
80
+ "span",
81
+ {
82
+ className: slots.title({
83
+ className: ouiTheme.cn(contextClassNames?.title, classNames?.title)
84
+ }),
85
+ children: children.renderChildren(headerRenderProps, children$1)
86
+ }
87
+ ),
88
+ !hideIndicator && /* @__PURE__ */ jsxRuntime.jsx(
89
+ "span",
90
+ {
91
+ "aria-hidden": true,
92
+ className: slots.indicator({
93
+ className: ouiTheme.cn(
94
+ contextClassNames?.indicator,
95
+ classNames?.indicator
96
+ )
97
+ }),
98
+ children: children.renderChildren(
99
+ headerRenderProps,
100
+ indicator ?? /* @__PURE__ */ jsxRuntime.jsx(chevronDown.default, {})
101
+ )
102
+ }
103
+ ),
104
+ startContent && /* @__PURE__ */ jsxRuntime.jsx(
105
+ "div",
106
+ {
107
+ className: slots.endContentWrapper({
108
+ className: ouiTheme.cn(
109
+ contextClassNames?.endContentWrapper,
110
+ classNames?.endContentWrapper
111
+ )
112
+ }),
113
+ children: children.renderChildren(headerRenderProps, endContent)
114
+ }
115
+ ),
116
+ children.renderChildren(headerRenderProps, endContent)
117
+ ] });
118
+ }
119
+ }
120
+ )
121
+ }
122
+ );
123
+ }
124
+ function AccordionContent({
125
+ children,
126
+ classNames,
127
+ ...props
128
+ }) {
129
+ const { slots, classNames: contextClassNames } = $670gB$react.useContext(
130
+ AccordionStyleContext
131
+ );
132
+ return /* @__PURE__ */ jsxRuntime.jsx(
133
+ reactAriaComponents.DisclosurePanel,
134
+ {
135
+ ...props,
136
+ className: ouiTheme.composeTailwindRenderProps(
137
+ props.className,
138
+ slots.panel({
139
+ className: ouiTheme.cn(contextClassNames?.panel, classNames?.panel)
140
+ })
141
+ ),
142
+ children: /* @__PURE__ */ jsxRuntime.jsx(
143
+ "div",
144
+ {
145
+ className: slots.content({
146
+ className: ouiTheme.cn(contextClassNames?.content, classNames?.content)
147
+ }),
148
+ children
149
+ }
150
+ )
151
+ }
152
+ );
153
+ }
154
+ const Accordion = utils.forwardRef(
155
+ (originalProps, ref) => {
156
+ const [
157
+ { classNames, className, ...props },
158
+ { size = "md", ...variantProps }
159
+ ] = utils.mapPropsVariants(originalProps, ouiTheme.accordionStyles.variantKeys);
160
+ const slots = ouiTheme.accordionStyles({ size, ...variantProps });
161
+ return /* @__PURE__ */ jsxRuntime.jsx(
162
+ AccordionStyleContext.Provider,
163
+ {
164
+ value: {
165
+ slots,
166
+ classNames
167
+ },
168
+ children: /* @__PURE__ */ jsxRuntime.jsx(
169
+ reactAriaComponents.DisclosureGroup,
170
+ {
171
+ className: slots.base({
172
+ className: ouiTheme.cn(classNames?.base, className)
173
+ }),
174
+ ...props,
175
+ ref
176
+ }
177
+ )
178
+ }
179
+ );
180
+ }
181
+ );
182
+ Accordion.displayName = "Accordion";
183
+
184
+ exports.Accordion = Accordion;
185
+ exports.AccordionContent = AccordionContent;
186
+ exports.AccordionHeader = AccordionHeader;
187
+ exports.AccordionItem = AccordionItem;
188
+ exports.AccordionStyleContext = AccordionStyleContext;
189
+ exports.useAccordionStyleContext = useAccordionStyleContext;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ 'use strict';
3
+
4
+ var accordion = require('./accordion.cjs');
5
+
6
+
7
+
8
+ exports.Accordion = accordion.Accordion;
9
+ exports.AccordionContent = accordion.AccordionContent;
10
+ exports.AccordionHeader = accordion.AccordionHeader;
11
+ exports.AccordionItem = accordion.AccordionItem;
12
+ exports.AccordionStyleContext = accordion.AccordionStyleContext;
13
+ exports.useAccordionStyleContext = accordion.useAccordionStyleContext;
@@ -10,6 +10,7 @@ var ouiTheme = require('@opengovsg/oui-theme');
10
10
  var ripple = require('../ripple/ripple.cjs');
11
11
  var useRipple = require('../ripple/use-ripple.cjs');
12
12
  var spinner = require('../spinner/spinner.cjs');
13
+ var children = require('../system/react-utils/children.cjs');
13
14
 
14
15
  const Button = $670gB$react.forwardRef(
15
16
  ({
@@ -23,8 +24,9 @@ const Button = $670gB$react.forwardRef(
23
24
  size = "md",
24
25
  spinnerPlacement = "start",
25
26
  loadingText,
27
+ pendingElement,
26
28
  onPress,
27
- children,
29
+ children: children$1,
28
30
  disableRipple,
29
31
  isPending,
30
32
  spinner: spinnerProp,
@@ -49,7 +51,7 @@ const Button = $670gB$react.forwardRef(
49
51
  const spinnerSize = buttonSpinnerSizeMap[size];
50
52
  return /* @__PURE__ */ jsxRuntime.jsx(spinner.Spinner, { size: spinnerSize });
51
53
  }, [size, spinnerProp]);
52
- return /* @__PURE__ */ jsxRuntime.jsxs(
54
+ return /* @__PURE__ */ jsxRuntime.jsx(
53
55
  reactAriaComponents.Button,
54
56
  {
55
57
  ...props,
@@ -70,15 +72,16 @@ const Button = $670gB$react.forwardRef(
70
72
  isPending,
71
73
  onPress: utils.chain(onPress, onPressRipple),
72
74
  ref,
73
- children: [
74
- startContent,
75
- isPending && spinnerPlacement === "start" ? spinner$1 : null,
76
- isPending ? null : children,
75
+ children: (renderProps) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
76
+ children.renderChildren(renderProps, startContent),
77
+ isPending && spinnerPlacement === "start" ? children.renderChildren(renderProps, spinner$1) : null,
78
+ isPending ? null : children.renderChildren(renderProps, children$1),
77
79
  isPending && loadingText ? loadingText : null,
78
- isPending && spinnerPlacement === "end" ? spinner$1 : null,
79
- endContent,
80
+ isPending && pendingElement ? children.renderChildren(renderProps, pendingElement) : null,
81
+ isPending && spinnerPlacement === "end" ? children.renderChildren(renderProps, spinner$1) : null,
82
+ children.renderChildren(renderProps, endContent),
80
83
  !disableRipple && /* @__PURE__ */ jsxRuntime.jsx(ripple.Ripple, { onClear: onClearRipple, ripples })
81
- ]
84
+ ] })
82
85
  }
83
86
  );
84
87
  }
@@ -20,11 +20,13 @@ var comboBox = require('./combo-box/combo-box.cjs');
20
20
  var comboBoxFuzzy = require('./combo-box/combo-box-fuzzy.cjs');
21
21
  var comboBoxItem = require('./combo-box/combo-box-item.cjs');
22
22
  var comboBoxVariantContext = require('./combo-box/combo-box-variant-context.cjs');
23
+ var banner = require('./banner/banner.cjs');
23
24
  var tagField = require('./tag-field/tag-field.cjs');
24
25
  var tagFieldItem = require('./tag-field/tag-field-item.cjs');
25
26
  var select = require('./select/select.cjs');
26
27
  var selectItem = require('./select/select-item.cjs');
27
28
  var selectVariantContext = require('./select/select-variant-context.cjs');
29
+ var badge = require('./badge/badge.cjs');
28
30
  var calendar = require('./calendar/calendar.cjs');
29
31
  var calendarStyleContext = require('./calendar/calendar-style-context.cjs');
30
32
  var utils = require('./calendar/utils.cjs');
@@ -64,8 +66,7 @@ var navbarItem = require('./navbar/navbar-item.cjs');
64
66
  var useNavbar = require('./navbar/use-navbar.cjs');
65
67
  var navbarContext = require('./navbar/navbar-context.cjs');
66
68
  var index = require('./avatar/index.cjs');
67
- var banner = require('./banner/banner.cjs');
68
- var badge = require('./badge/badge.cjs');
69
+ var accordion = require('./accordion/accordion.cjs');
69
70
  var sonner = require('sonner');
70
71
  var avatarContext = require('./avatar/avatar-context.cjs');
71
72
  var avatarGroup = require('./avatar/avatar-group.cjs');
@@ -99,12 +100,14 @@ exports.ComboBoxFuzzy = comboBoxFuzzy.ComboBoxFuzzy;
99
100
  exports.ComboBoxItem = comboBoxItem.ComboBoxItem;
100
101
  exports.ComboBoxVariantContext = comboBoxVariantContext.ComboBoxVariantContext;
101
102
  exports.useComboBoxVariantContext = comboBoxVariantContext.useComboBoxVariantContext;
103
+ exports.Banner = banner.Banner;
102
104
  exports.TagField = tagField.TagField;
103
105
  exports.TagFieldItem = tagFieldItem.TagFieldItem;
104
106
  exports.Select = select.Select;
105
107
  exports.SelectItem = selectItem.SelectItem;
106
108
  exports.SelectVariantContext = selectVariantContext.SelectVariantContext;
107
109
  exports.useSelectVariantContext = selectVariantContext.useSelectVariantContext;
110
+ exports.Badge = badge.Badge;
108
111
  exports.Calendar = calendar.Calendar;
109
112
  exports.CalendarStateWrapper = calendar.CalendarStateWrapper;
110
113
  exports.CalendarStyleContext = calendarStyleContext.CalendarStyleContext;
@@ -173,8 +176,12 @@ exports.useNavbar = useNavbar.useNavbar;
173
176
  exports.NavbarProvider = navbarContext.NavbarProvider;
174
177
  exports.useNavbarContext = navbarContext.useNavbarContext;
175
178
  exports.Avatar = index.Avatar;
176
- exports.Banner = banner.Banner;
177
- exports.Badge = badge.Badge;
179
+ exports.Accordion = accordion.Accordion;
180
+ exports.AccordionContent = accordion.AccordionContent;
181
+ exports.AccordionHeader = accordion.AccordionHeader;
182
+ exports.AccordionItem = accordion.AccordionItem;
183
+ exports.AccordionStyleContext = accordion.AccordionStyleContext;
184
+ exports.useAccordionStyleContext = accordion.useAccordionStyleContext;
178
185
  Object.defineProperty(exports, "toast", {
179
186
  enumerable: true,
180
187
  get: function () { return sonner.toast; }
@@ -4,6 +4,7 @@
4
4
 
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
  var $670gB$react = require('react');
7
+ var reactAria = require('react-aria');
7
8
  var reactAriaComponents = require('react-aria-components');
8
9
  var ouiTheme = require('@opengovsg/oui-theme');
9
10
  var button = require('../button/button.cjs');
@@ -13,6 +14,24 @@ var utils = require('../system/utils.cjs');
13
14
  var selectVariantContext = require('./select-variant-context.cjs');
14
15
  var chevronDown = require('../node_modules/.pnpm/lucide-react@0.475.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/chevron-down.cjs');
15
16
 
17
+ const i18nStrings = {
18
+ "en-SG": {
19
+ searchPlaceholder: "Search...",
20
+ searchAriaLabel: "Search options"
21
+ },
22
+ "zh-SG": {
23
+ searchPlaceholder: "\u641C\u7D22...",
24
+ searchAriaLabel: "\u641C\u7D22\u9009\u9879"
25
+ },
26
+ "ms-SG": {
27
+ searchPlaceholder: "Cari...",
28
+ searchAriaLabel: "Cari pilihan"
29
+ },
30
+ "ta-SG": {
31
+ searchPlaceholder: "\u0BA4\u0BC7\u0B9F\u0BC1...",
32
+ searchAriaLabel: "\u0BA4\u0BC7\u0B9F\u0BB2\u0BCD \u0BB5\u0BBF\u0BB0\u0BC1\u0BAA\u0BCD\u0BAA\u0B99\u0BCD\u0B95\u0BB3\u0BCD"
33
+ }
34
+ };
16
35
  const calculateEstimatedRowHeight = (size) => {
17
36
  switch (size) {
18
37
  case "xs":
@@ -30,12 +49,22 @@ function Select({
30
49
  errorMessage,
31
50
  ...originalProps
32
51
  }) {
52
+ const formatter = reactAria.useLocalizedStringFormatter(i18nStrings);
33
53
  const [_props, variantProps] = utils.mapPropsVariants(
34
54
  originalProps,
35
55
  ouiTheme.selectStyles.variantKeys
36
56
  );
37
- const { items, children, listLayoutOptions, ...props } = _props;
57
+ const {
58
+ items,
59
+ children,
60
+ listLayoutOptions,
61
+ enableSearch = false,
62
+ searchPlaceholder,
63
+ searchIcon,
64
+ ...props
65
+ } = _props;
38
66
  const styles = ouiTheme.selectStyles(variantProps);
67
+ const { contains } = reactAriaComponents.useFilter({ sensitivity: "base" });
39
68
  const layoutOptions = $670gB$react.useMemo(() => {
40
69
  return {
41
70
  estimatedRowHeight: calculateEstimatedRowHeight(
@@ -44,6 +73,37 @@ function Select({
44
73
  ...listLayoutOptions
45
74
  };
46
75
  }, [listLayoutOptions, variantProps.size]);
76
+ const renderedSearchIcon = $670gB$react.useMemo(() => {
77
+ if (!enableSearch || !searchIcon) return null;
78
+ if ($670gB$react.isValidElement(searchIcon)) {
79
+ const iconElement = searchIcon;
80
+ return $670gB$react.cloneElement(iconElement, {
81
+ className: styles.searchIcon({
82
+ className: ouiTheme.cn(classNames?.searchIcon, iconElement.props.className)
83
+ })
84
+ });
85
+ }
86
+ return /* @__PURE__ */ jsxRuntime.jsx(
87
+ "span",
88
+ {
89
+ className: styles.searchIcon({ className: classNames?.searchIcon }),
90
+ children: searchIcon
91
+ }
92
+ );
93
+ }, [classNames?.searchIcon, enableSearch, searchIcon, styles]);
94
+ const listContent = /* @__PURE__ */ jsxRuntime.jsx(reactAriaComponents.Virtualizer, { layout: reactAriaComponents.ListLayout, layoutOptions, children: /* @__PURE__ */ jsxRuntime.jsx(
95
+ reactAriaComponents.ListBox,
96
+ {
97
+ autoFocus: !enableSearch,
98
+ items,
99
+ shouldFocusWrap: true,
100
+ className: ouiTheme.composeRenderProps(
101
+ classNames?.list,
102
+ (className, renderProps) => styles.list({ className, ...renderProps })
103
+ ),
104
+ children
105
+ }
106
+ ) });
47
107
  return /* @__PURE__ */ jsxRuntime.jsx(reactAriaComponents.Provider, { values: [[selectVariantContext.SelectVariantContext, variantProps]], children: /* @__PURE__ */ jsxRuntime.jsxs(
48
108
  reactAriaComponents.Select,
49
109
  {
@@ -93,19 +153,31 @@ function Select({
93
153
  }
94
154
  ),
95
155
  /* @__PURE__ */ jsxRuntime.jsx(field.FieldError, { size: variantProps.size, className: classNames?.error, children: errorMessage }),
96
- /* @__PURE__ */ jsxRuntime.jsx(popover.Popover, { className: styles.popover({ className: classNames?.popover }), children: /* @__PURE__ */ jsxRuntime.jsx(reactAriaComponents.Virtualizer, { layout: reactAriaComponents.ListLayout, layoutOptions, children: /* @__PURE__ */ jsxRuntime.jsx(
97
- reactAriaComponents.ListBox,
98
- {
99
- autoFocus: true,
100
- items,
101
- shouldFocusWrap: true,
102
- className: ouiTheme.composeRenderProps(
103
- classNames?.list,
104
- (className, renderProps) => styles.list({ className, ...renderProps })
105
- ),
106
- children
107
- }
108
- ) }) })
156
+ /* @__PURE__ */ jsxRuntime.jsx(popover.Popover, { className: styles.popover({ className: classNames?.popover }), children: enableSearch ? /* @__PURE__ */ jsxRuntime.jsxs(reactAriaComponents.Autocomplete, { filter: contains, children: [
157
+ /* @__PURE__ */ jsxRuntime.jsxs(
158
+ reactAriaComponents.SearchField,
159
+ {
160
+ autoFocus: true,
161
+ "aria-label": formatter.format("searchAriaLabel"),
162
+ className: styles.searchField({
163
+ className: classNames?.searchField
164
+ }),
165
+ children: [
166
+ renderedSearchIcon,
167
+ /* @__PURE__ */ jsxRuntime.jsx(
168
+ reactAriaComponents.Input,
169
+ {
170
+ placeholder: searchPlaceholder ?? formatter.format("searchPlaceholder"),
171
+ className: styles.searchInput({
172
+ className: classNames?.searchInput
173
+ })
174
+ }
175
+ )
176
+ ]
177
+ }
178
+ ),
179
+ listContent
180
+ ] }) : listContent })
109
181
  ]
110
182
  }
111
183
  ) });
@@ -21,6 +21,13 @@ const pickChildren = (children, targetChild) => {
21
21
  const targetChildren = target.length >= 0 ? target : void 0;
22
22
  return [withoutTargetChildren, targetChildren];
23
23
  };
24
+ const renderChildren = (renderProps, children) => {
25
+ if (typeof children === "function") {
26
+ return children(renderProps);
27
+ }
28
+ return children;
29
+ };
24
30
 
25
31
  exports.getValidChildren = getValidChildren;
26
32
  exports.pickChildren = pickChildren;
33
+ exports.renderChildren = renderChildren;
@@ -0,0 +1,182 @@
1
+ "use strict";
2
+ "use client";
3
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
+ import { useContext } from 'react';
5
+ import { Disclosure, composeRenderProps, DisclosureGroup, DisclosureStateContext, Heading, Button, DisclosurePanel } from 'react-aria-components';
6
+ import { cn, accordionStyles, composeTailwindRenderProps } from '@opengovsg/oui-theme';
7
+ import { renderChildren } from '../system/react-utils/children.js';
8
+ import { forwardRef, mapPropsVariants } from '../system/utils.js';
9
+ import { createContext } from '../system/react-utils/context.js';
10
+ 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
+
12
+ const [AccordionStyleContext, useAccordionStyleContext] = createContext({
13
+ name: "AccordionStyleContext",
14
+ strict: true
15
+ });
16
+ const AccordionItem = forwardRef(
17
+ ({ classNames, className, children, ...props }, ref) => {
18
+ const { slots } = useContext(AccordionStyleContext);
19
+ return /* @__PURE__ */ jsx(
20
+ Disclosure,
21
+ {
22
+ ...props,
23
+ ref,
24
+ className: composeRenderProps(
25
+ className,
26
+ (className2, renderProps) => slots.item({
27
+ ...renderProps,
28
+ className: cn(classNames?.item, className2)
29
+ })
30
+ ),
31
+ children
32
+ }
33
+ );
34
+ }
35
+ );
36
+ AccordionItem.displayName = "AccordionItem";
37
+ function AccordionHeader({
38
+ children,
39
+ classNames,
40
+ indicator,
41
+ startContent,
42
+ endContent,
43
+ hideIndicator = false
44
+ }) {
45
+ const { slots, classNames: contextClassNames } = useContext(
46
+ AccordionStyleContext
47
+ );
48
+ const { isExpanded } = useContext(DisclosureStateContext);
49
+ return /* @__PURE__ */ jsx(
50
+ Heading,
51
+ {
52
+ className: slots.heading({
53
+ className: cn(contextClassNames?.heading, classNames?.heading)
54
+ }),
55
+ children: /* @__PURE__ */ jsx(
56
+ Button,
57
+ {
58
+ slot: "trigger",
59
+ className: slots.trigger({
60
+ className: cn(contextClassNames?.trigger, classNames?.trigger)
61
+ }),
62
+ children: (buttonRenderProps) => {
63
+ const headerRenderProps = { ...buttonRenderProps, isExpanded };
64
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
65
+ startContent && /* @__PURE__ */ jsx(
66
+ "div",
67
+ {
68
+ className: slots.startContentWrapper({
69
+ className: cn(
70
+ contextClassNames?.startContentWrapper,
71
+ classNames?.startContentWrapper
72
+ )
73
+ }),
74
+ children: renderChildren(headerRenderProps, startContent)
75
+ }
76
+ ),
77
+ /* @__PURE__ */ jsx(
78
+ "span",
79
+ {
80
+ className: slots.title({
81
+ className: cn(contextClassNames?.title, classNames?.title)
82
+ }),
83
+ children: renderChildren(headerRenderProps, children)
84
+ }
85
+ ),
86
+ !hideIndicator && /* @__PURE__ */ jsx(
87
+ "span",
88
+ {
89
+ "aria-hidden": true,
90
+ className: slots.indicator({
91
+ className: cn(
92
+ contextClassNames?.indicator,
93
+ classNames?.indicator
94
+ )
95
+ }),
96
+ children: renderChildren(
97
+ headerRenderProps,
98
+ indicator ?? /* @__PURE__ */ jsx(ChevronDown, {})
99
+ )
100
+ }
101
+ ),
102
+ startContent && /* @__PURE__ */ jsx(
103
+ "div",
104
+ {
105
+ className: slots.endContentWrapper({
106
+ className: cn(
107
+ contextClassNames?.endContentWrapper,
108
+ classNames?.endContentWrapper
109
+ )
110
+ }),
111
+ children: renderChildren(headerRenderProps, endContent)
112
+ }
113
+ ),
114
+ renderChildren(headerRenderProps, endContent)
115
+ ] });
116
+ }
117
+ }
118
+ )
119
+ }
120
+ );
121
+ }
122
+ function AccordionContent({
123
+ children,
124
+ classNames,
125
+ ...props
126
+ }) {
127
+ const { slots, classNames: contextClassNames } = useContext(
128
+ AccordionStyleContext
129
+ );
130
+ return /* @__PURE__ */ jsx(
131
+ DisclosurePanel,
132
+ {
133
+ ...props,
134
+ className: composeTailwindRenderProps(
135
+ props.className,
136
+ slots.panel({
137
+ className: cn(contextClassNames?.panel, classNames?.panel)
138
+ })
139
+ ),
140
+ children: /* @__PURE__ */ jsx(
141
+ "div",
142
+ {
143
+ className: slots.content({
144
+ className: cn(contextClassNames?.content, classNames?.content)
145
+ }),
146
+ children
147
+ }
148
+ )
149
+ }
150
+ );
151
+ }
152
+ const Accordion = forwardRef(
153
+ (originalProps, ref) => {
154
+ const [
155
+ { classNames, className, ...props },
156
+ { size = "md", ...variantProps }
157
+ ] = mapPropsVariants(originalProps, accordionStyles.variantKeys);
158
+ const slots = accordionStyles({ size, ...variantProps });
159
+ return /* @__PURE__ */ jsx(
160
+ AccordionStyleContext.Provider,
161
+ {
162
+ value: {
163
+ slots,
164
+ classNames
165
+ },
166
+ children: /* @__PURE__ */ jsx(
167
+ DisclosureGroup,
168
+ {
169
+ className: slots.base({
170
+ className: cn(classNames?.base, className)
171
+ }),
172
+ ...props,
173
+ ref
174
+ }
175
+ )
176
+ }
177
+ );
178
+ }
179
+ );
180
+ Accordion.displayName = "Accordion";
181
+
182
+ export { Accordion, AccordionContent, AccordionHeader, AccordionItem, AccordionStyleContext, useAccordionStyleContext };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ export { Accordion, AccordionContent, AccordionHeader, AccordionItem, AccordionStyleContext, useAccordionStyleContext } from './accordion.js';
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  "use client";
3
- import { jsx, jsxs } from 'react/jsx-runtime';
3
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
4
  import { forwardRef, useMemo } from 'react';
5
5
  import { chain } from '@react-aria/utils';
6
6
  import { Button as Button$1, composeRenderProps } from 'react-aria-components';
@@ -8,6 +8,7 @@ import { buttonStyles } from '@opengovsg/oui-theme';
8
8
  import { Ripple } from '../ripple/ripple.js';
9
9
  import { useRipple } from '../ripple/use-ripple.js';
10
10
  import { Spinner } from '../spinner/spinner.js';
11
+ import { renderChildren } from '../system/react-utils/children.js';
11
12
 
12
13
  const Button = forwardRef(
13
14
  ({
@@ -21,6 +22,7 @@ const Button = forwardRef(
21
22
  size = "md",
22
23
  spinnerPlacement = "start",
23
24
  loadingText,
25
+ pendingElement,
24
26
  onPress,
25
27
  children,
26
28
  disableRipple,
@@ -47,7 +49,7 @@ const Button = forwardRef(
47
49
  const spinnerSize = buttonSpinnerSizeMap[size];
48
50
  return /* @__PURE__ */ jsx(Spinner, { size: spinnerSize });
49
51
  }, [size, spinnerProp]);
50
- return /* @__PURE__ */ jsxs(
52
+ return /* @__PURE__ */ jsx(
51
53
  Button$1,
52
54
  {
53
55
  ...props,
@@ -68,15 +70,16 @@ const Button = forwardRef(
68
70
  isPending,
69
71
  onPress: chain(onPress, onPressRipple),
70
72
  ref,
71
- children: [
72
- startContent,
73
- isPending && spinnerPlacement === "start" ? spinner : null,
74
- isPending ? null : children,
73
+ children: (renderProps) => /* @__PURE__ */ jsxs(Fragment, { children: [
74
+ renderChildren(renderProps, startContent),
75
+ isPending && spinnerPlacement === "start" ? renderChildren(renderProps, spinner) : null,
76
+ isPending ? null : renderChildren(renderProps, children),
75
77
  isPending && loadingText ? loadingText : null,
76
- isPending && spinnerPlacement === "end" ? spinner : null,
77
- endContent,
78
+ isPending && pendingElement ? renderChildren(renderProps, pendingElement) : null,
79
+ isPending && spinnerPlacement === "end" ? renderChildren(renderProps, spinner) : null,
80
+ renderChildren(renderProps, endContent),
78
81
  !disableRipple && /* @__PURE__ */ jsx(Ripple, { onClear: onClearRipple, ripples })
79
- ]
82
+ ] })
80
83
  }
81
84
  );
82
85
  }
package/dist/esm/index.js CHANGED
@@ -18,11 +18,13 @@ export { ComboBox, ComboBoxEmptyState } from './combo-box/combo-box.js';
18
18
  export { ComboBoxFuzzy } from './combo-box/combo-box-fuzzy.js';
19
19
  export { ComboBoxItem } from './combo-box/combo-box-item.js';
20
20
  export { ComboBoxVariantContext, useComboBoxVariantContext } from './combo-box/combo-box-variant-context.js';
21
+ export { Banner } from './banner/banner.js';
21
22
  export { TagField } from './tag-field/tag-field.js';
22
23
  export { TagFieldItem } from './tag-field/tag-field-item.js';
23
24
  export { Select } from './select/select.js';
24
25
  export { SelectItem } from './select/select-item.js';
25
26
  export { SelectVariantContext, useSelectVariantContext } from './select/select-variant-context.js';
27
+ export { Badge } from './badge/badge.js';
26
28
  export { Calendar, CalendarStateWrapper } from './calendar/calendar.js';
27
29
  export { CalendarStyleContext, useCalendarStyleContext } from './calendar/calendar-style-context.js';
28
30
  export { getEraFormat, useGenerateLocalizedMonths, useGenerateLocalizedYears, useLocalizedMonthYear } from './calendar/utils.js';
@@ -62,8 +64,7 @@ export { NavbarItem } from './navbar/navbar-item.js';
62
64
  export { useNavbar } from './navbar/use-navbar.js';
63
65
  export { NavbarProvider, useNavbarContext } from './navbar/navbar-context.js';
64
66
  export { Avatar } from './avatar/index.js';
65
- export { Banner } from './banner/banner.js';
66
- export { Badge } from './badge/badge.js';
67
+ export { Accordion, AccordionContent, AccordionHeader, AccordionItem, AccordionStyleContext, useAccordionStyleContext } from './accordion/accordion.js';
67
68
  export { toast } from 'sonner';
68
69
  export { AvatarContext, useAvatarContext } from './avatar/avatar-context.js';
69
70
  export { AvatarGroup } from './avatar/avatar-group.js';
@@ -1,9 +1,10 @@
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';
7
8
  import { Button } from '../button/button.js';
8
9
  import { Label, Description, FieldError } from '../field/field.js';
9
10
  import { Popover } from '../popover/popover.js';
@@ -11,6 +12,24 @@ import { mapPropsVariants } from '../system/utils.js';
11
12
  import { SelectVariantContext } from './select-variant-context.js';
12
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';
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 };
@@ -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"}
@@ -1,30 +1,36 @@
1
- import type { ButtonProps as AriaButtonProps } from "react-aria-components";
1
+ import type { ButtonProps as AriaButtonProps, RenderProps } from "react-aria-components";
2
2
  import type { ButtonVariantProps } from "@opengovsg/oui-theme";
3
- export interface ButtonProps extends Omit<AriaButtonProps, "children">, ButtonVariantProps {
3
+ export interface ButtonProps extends AriaButtonProps, ButtonVariantProps {
4
4
  /**
5
5
  * Whether the button should display a ripple effect on press.
6
6
  * @defaultValue false
7
7
  */
8
8
  disableRipple?: boolean;
9
- children: React.ReactNode;
10
9
  /**
11
10
  * The button start content.
12
11
  */
13
- startContent?: React.ReactNode;
12
+ startContent?: RenderProps<ButtonProps>["children"];
14
13
  /**
15
14
  * The button end content.
16
15
  */
17
- endContent?: React.ReactNode;
16
+ endContent?: RenderProps<ButtonProps>["children"];
18
17
  /**
19
18
  * Spinner to display when loading.
20
19
  * @defaultValue \@opengovsg/oui/components/spinner
21
20
  */
22
- spinner?: React.ReactNode;
21
+ spinner?: RenderProps<ButtonProps>["children"];
23
22
  /**
24
23
  * Text to show when the button is loading.
25
24
  * If not provided, the button will only show the loading spinner.
25
+ *
26
+ * @deprecated Use `pendingElement` instead.
26
27
  */
27
28
  loadingText?: string;
29
+ /**
30
+ * Text to show when the button is loading.
31
+ * If not provided, the button will only show the loading spinner.
32
+ */
33
+ pendingElement?: RenderProps<ButtonProps>["children"];
28
34
  /**
29
35
  * The spinner placement.
30
36
  * @defaultValue "start"
@@ -1 +1 @@
1
- {"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../src/button/button.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,IAAI,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAK3E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAO9D,MAAM,WAAW,WACf,SAAQ,IAAI,CAAC,eAAe,EAAE,UAAU,CAAC,EACvC,kBAAkB;IACpB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB;;OAEG;IACH,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC9B;;OAEG;IACH,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC5B;;;OAGG;IACH,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAEzB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IAEpB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,GAAG,KAAK,CAAA;IAElC;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED;;;GAGG;AACH,eAAO,MAAM,MAAM,2GA0ElB,CAAA"}
1
+ {"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../src/button/button.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,WAAW,IAAI,eAAe,EAC9B,WAAW,EACZ,MAAM,uBAAuB,CAAA;AAK9B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAQ9D,MAAM,WAAW,WAAY,SAAQ,eAAe,EAAE,kBAAkB;IACtE;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB;;OAEG;IACH,YAAY,CAAC,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC,UAAU,CAAC,CAAA;IACnD;;OAEG;IACH,UAAU,CAAC,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC,UAAU,CAAC,CAAA;IACjD;;;OAGG;IACH,OAAO,CAAC,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC,UAAU,CAAC,CAAA;IAE9C;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IAEpB;;;OAGG;IACH,cAAc,CAAC,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC,UAAU,CAAC,CAAA;IAErD;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,GAAG,KAAK,CAAA;IAElC;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED;;;GAGG;AACH,eAAO,MAAM,MAAM,2GAwFlB,CAAA"}
@@ -31,4 +31,5 @@ export * from "./modal";
31
31
  export * from "./toast";
32
32
  export * from "./navbar";
33
33
  export * from "./avatar";
34
+ export * from "./accordion";
34
35
  //# sourceMappingURL=index.d.ts.map
@@ -31,4 +31,5 @@ export * from "./modal";
31
31
  export * from "./toast";
32
32
  export * from "./navbar";
33
33
  export * from "./avatar";
34
+ export * from "./accordion";
34
35
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA;AACxB,cAAc,eAAe,CAAA;AAC7B,cAAc,UAAU,CAAA;AACxB,cAAc,WAAW,CAAA;AACzB,cAAc,UAAU,CAAA;AACxB,cAAc,iBAAiB,CAAA;AAC/B,cAAc,SAAS,CAAA;AACvB,cAAc,cAAc,CAAA;AAC5B,cAAc,SAAS,CAAA;AACvB,cAAc,aAAa,CAAA;AAC3B,cAAc,mBAAmB,CAAA;AACjC,cAAc,aAAa,CAAA;AAC3B,cAAc,UAAU,CAAA;AACxB,cAAc,aAAa,CAAA;AAC3B,cAAc,UAAU,CAAA;AACxB,cAAc,SAAS,CAAA;AACvB,cAAc,YAAY,CAAA;AAC1B,cAAc,kBAAkB,CAAA;AAChC,cAAc,QAAQ,CAAA;AACtB,cAAc,WAAW,CAAA;AACzB,cAAc,QAAQ,CAAA;AACtB,cAAc,cAAc,CAAA;AAC5B,cAAc,eAAe,CAAA;AAC7B,cAAc,qBAAqB,CAAA;AACnC,cAAc,YAAY,CAAA;AAC1B,cAAc,cAAc,CAAA;AAC5B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,SAAS,CAAA;AACvB,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA;AACxB,cAAc,UAAU,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA;AACxB,cAAc,eAAe,CAAA;AAC7B,cAAc,UAAU,CAAA;AACxB,cAAc,WAAW,CAAA;AACzB,cAAc,UAAU,CAAA;AACxB,cAAc,iBAAiB,CAAA;AAC/B,cAAc,SAAS,CAAA;AACvB,cAAc,cAAc,CAAA;AAC5B,cAAc,SAAS,CAAA;AACvB,cAAc,aAAa,CAAA;AAC3B,cAAc,mBAAmB,CAAA;AACjC,cAAc,aAAa,CAAA;AAC3B,cAAc,UAAU,CAAA;AACxB,cAAc,aAAa,CAAA;AAC3B,cAAc,UAAU,CAAA;AACxB,cAAc,SAAS,CAAA;AACvB,cAAc,YAAY,CAAA;AAC1B,cAAc,kBAAkB,CAAA;AAChC,cAAc,QAAQ,CAAA;AACtB,cAAc,WAAW,CAAA;AACzB,cAAc,QAAQ,CAAA;AACtB,cAAc,cAAc,CAAA;AAC5B,cAAc,eAAe,CAAA;AAC7B,cAAc,qBAAqB,CAAA;AACnC,cAAc,YAAY,CAAA;AAC1B,cAAc,cAAc,CAAA;AAC5B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,SAAS,CAAA;AACvB,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA;AACxB,cAAc,UAAU,CAAA;AACxB,cAAc,aAAa,CAAA"}
@@ -13,6 +13,20 @@ export interface SelectProps<T> extends Omit<AriaSelectProps, "children">, Varia
13
13
  /** The list of Select options to render */
14
14
  items?: NonNullable<ListBoxProps<T>["items"]>;
15
15
  children?: ListBoxProps<T>["children"];
16
+ /**
17
+ * Enable search/autocomplete functionality with a search field
18
+ * @default false
19
+ */
20
+ enableSearch?: boolean;
21
+ /**
22
+ * Placeholder text for the search field.
23
+ * If not provided, a localized default will be used.
24
+ */
25
+ searchPlaceholder?: string;
26
+ /**
27
+ * Icon to display in the search field. If not provided, no icon will be displayed.
28
+ */
29
+ searchIcon?: React.ReactNode;
16
30
  }
17
31
  export declare function Select<T extends object>({ label, description, classNames, errorMessage, ...originalProps }: SelectProps<T>): import("react/jsx-runtime").JSX.Element;
18
32
  //# sourceMappingURL=select.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../../src/select/select.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,WAAW,IAAI,eAAe,EAC9B,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,uBAAuB,CAAA;AAY9B,OAAO,KAAK,EAEV,kBAAkB,EAClB,cAAc,EACd,YAAY,EACb,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAsB,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAQvE,MAAM,WAAW,WAAW,CAAC,CAAC,CAC5B,SAAQ,IAAI,CAAC,eAAe,EAAE,UAAU,CAAC,EACvC,YAAY,CAAC,OAAO,YAAY,CAAC;IACnC,UAAU,CAAC,EAAE,cAAc,CAAC,kBAAkB,GAAG,OAAO,CAAC,CAAA;IAEzD;;OAEG;IACH,iBAAiB,CAAC,EAAE,iBAAiB,CAAA;IAErC,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACvB,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,IAAI,CAAA;IAEpC,YAAY,CAAC,EACT,KAAK,CAAC,SAAS,GACf,CAAC,CAAC,UAAU,EAAE,gBAAgB,KAAK,KAAK,CAAC,SAAS,CAAC,CAAA;IAEvD,2CAA2C;IAC3C,KAAK,CAAC,EAAE,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAA;IAE7C,QAAQ,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAA;CACvC;AAeD,wBAAgB,MAAM,CAAC,CAAC,SAAS,MAAM,EAAE,EACvC,KAAK,EACL,WAAW,EACX,UAAU,EACV,YAAY,EACZ,GAAG,aAAa,EACjB,EAAE,WAAW,CAAC,CAAC,CAAC,2CAqFhB"}
1
+ {"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../../src/select/select.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,WAAW,IAAI,eAAe,EAC9B,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,uBAAuB,CAAA;AAiB9B,OAAO,KAAK,EAEV,kBAAkB,EAClB,cAAc,EACd,YAAY,EACb,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAA0B,YAAY,EAAE,MAAM,sBAAsB,CAAA;AA2B3E,MAAM,WAAW,WAAW,CAAC,CAAC,CAC5B,SAAQ,IAAI,CAAC,eAAe,EAAE,UAAU,CAAC,EACvC,YAAY,CAAC,OAAO,YAAY,CAAC;IACnC,UAAU,CAAC,EAAE,cAAc,CAAC,kBAAkB,GAAG,OAAO,CAAC,CAAA;IAEzD;;OAEG;IACH,iBAAiB,CAAC,EAAE,iBAAiB,CAAA;IAErC,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACvB,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,IAAI,CAAA;IAEpC,YAAY,CAAC,EACT,KAAK,CAAC,SAAS,GACf,CAAC,CAAC,UAAU,EAAE,gBAAgB,KAAK,KAAK,CAAC,SAAS,CAAC,CAAA;IAEvD,2CAA2C;IAC3C,KAAK,CAAC,EAAE,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAA;IAE7C,QAAQ,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAA;IAEtC;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;IAEtB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAE1B;;OAEG;IACH,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAC7B;AAeD,wBAAgB,MAAM,CAAC,CAAC,SAAS,MAAM,EAAE,EACvC,KAAK,EACL,WAAW,EACX,UAAU,EACV,YAAY,EACZ,GAAG,aAAa,EACjB,EAAE,WAAW,CAAC,CAAC,CAAC,2CA+IhB"}
@@ -1,4 +1,5 @@
1
1
  import type { ReactNode } from "react";
2
+ type ChildrenOrFunction<T> = ReactNode | ((values: T) => ReactNode);
2
3
  /**
3
4
  * Gets only the valid children of a component,
4
5
  * and ignores any nullish or falsy child.
@@ -7,4 +8,6 @@ import type { ReactNode } from "react";
7
8
  */
8
9
  export declare function getValidChildren(children: React.ReactNode): React.ReactElement[];
9
10
  export declare const pickChildren: <T = ReactNode>(children: T | undefined, targetChild: React.ElementType) => [T | undefined, T[] | undefined];
11
+ export declare const renderChildren: <T>(renderProps: T, children: ChildrenOrFunction<T>) => ReactNode;
12
+ export {};
10
13
  //# sourceMappingURL=children.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"children.d.ts","sourceRoot":"","sources":["../../../../src/system/react-utils/children.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGtC;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,GAGnD,KAAK,CAAC,YAAY,EAAE,CAC1B;AAED,eAAO,MAAM,YAAY,GAAI,CAAC,wBAClB,CAAC,GAAG,SAAS,eACV,KAAK,CAAC,WAAW,KAC7B,CAAC,CAAC,GAAG,SAAS,EAAE,CAAC,EAAE,GAAG,SAAS,CAiBjC,CAAA"}
1
+ {"version":3,"file":"children.d.ts","sourceRoot":"","sources":["../../../../src/system/react-utils/children.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGtC,KAAK,kBAAkB,CAAC,CAAC,IAAI,SAAS,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,SAAS,CAAC,CAAA;AAEnE;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,GAGnD,KAAK,CAAC,YAAY,EAAE,CAC1B;AAED,eAAO,MAAM,YAAY,GAAI,CAAC,wBAClB,CAAC,GAAG,SAAS,eACV,KAAK,CAAC,WAAW,KAC7B,CAAC,CAAC,GAAG,SAAS,EAAE,CAAC,EAAE,GAAG,SAAS,CAiBjC,CAAA;AAED,eAAO,MAAM,cAAc,GAAI,CAAC,eACjB,CAAC,YACJ,kBAAkB,CAAC,CAAC,CAAC,cAOhC,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengovsg/oui",
3
- "version": "0.0.31",
3
+ "version": "0.0.33",
4
4
  "sideEffects": false,
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "type": "module",
@@ -35,7 +35,7 @@
35
35
  "./package.json": "./package.json"
36
36
  },
37
37
  "devDependencies": {
38
- "@storybook/react-vite": "10.1.2",
38
+ "@storybook/react-vite": "10.1.10",
39
39
  "@types/lodash-es": "^4.17.12",
40
40
  "@types/prop-types": "^15.7.15",
41
41
  "@types/react": "^19.2.7",
@@ -47,10 +47,10 @@
47
47
  "prettier": "^3.5.3",
48
48
  "react": "^19.2.3",
49
49
  "react-aria-components": "^1.13.0",
50
- "storybook": "10.1.2",
50
+ "storybook": "10.1.10",
51
51
  "tsx": "^4.21.0",
52
52
  "typescript": "5.7.3",
53
- "@opengovsg/oui-theme": "0.0.31",
53
+ "@opengovsg/oui-theme": "0.0.33",
54
54
  "@oui/chromatic": "0.0.0",
55
55
  "@oui/eslint-config": "0.0.0",
56
56
  "@oui/prettier-config": "0.0.0",
@@ -88,7 +88,7 @@
88
88
  "motion": ">=11.12.0 || >=12.0.0-alpha.1",
89
89
  "react": ">= 18",
90
90
  "react-aria-components": "^1.13.0",
91
- "@opengovsg/oui-theme": "0.0.31"
91
+ "@opengovsg/oui-theme": "0.0.33"
92
92
  },
93
93
  "scripts": {
94
94
  "build": "tsx ../../tooling/build-scripts/main.ts --dts --clean",