@opengovsg/oui 0.0.44 → 0.0.46

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 (100) hide show
  1. package/dist/cjs/field/field.cjs +15 -12
  2. package/dist/cjs/index.cjs +40 -0
  3. package/dist/cjs/phone-number-field/constants.cjs +500 -0
  4. package/dist/cjs/phone-number-field/context.cjs +11 -0
  5. package/dist/cjs/phone-number-field/i18n.cjs +1043 -0
  6. package/dist/cjs/phone-number-field/index.cjs +32 -0
  7. package/dist/cjs/phone-number-field/phone-number-field.cjs +299 -0
  8. package/dist/cjs/phone-number-field/types.cjs +3 -0
  9. package/dist/cjs/select/i18n.cjs +23 -0
  10. package/dist/cjs/select/select.cjs +45 -45
  11. package/dist/cjs/sidebar/context.cjs +24 -0
  12. package/dist/cjs/sidebar/i18n.cjs +23 -0
  13. package/dist/cjs/sidebar/index.cjs +17 -0
  14. package/dist/cjs/sidebar/sidebar-header.cjs +40 -0
  15. package/dist/cjs/sidebar/sidebar-item.cjs +61 -0
  16. package/dist/cjs/sidebar/sidebar-list.cjs +213 -0
  17. package/dist/cjs/sidebar/sidebar-root.cjs +63 -0
  18. package/dist/cjs/sidebar/sidebar.cjs +31 -0
  19. package/dist/cjs/sidebar/types.cjs +3 -0
  20. package/dist/cjs/sidebar/utils.cjs +12 -0
  21. package/dist/cjs/system/l10n.cjs +18 -0
  22. package/dist/cjs/system/react-utils/sizing.cjs +21 -0
  23. package/dist/cjs/tooltip/index.cjs +9 -0
  24. package/dist/cjs/tooltip/tooltip.cjs +54 -0
  25. package/dist/esm/field/field.js +18 -15
  26. package/dist/esm/index.js +8 -0
  27. package/dist/esm/phone-number-field/constants.js +497 -0
  28. package/dist/esm/phone-number-field/context.js +8 -0
  29. package/dist/esm/phone-number-field/i18n.js +1041 -0
  30. package/dist/esm/phone-number-field/index.js +3 -0
  31. package/dist/esm/phone-number-field/phone-number-field.js +294 -0
  32. package/dist/esm/phone-number-field/types.js +1 -0
  33. package/dist/esm/select/i18n.js +21 -0
  34. package/dist/esm/select/select.js +45 -45
  35. package/dist/esm/sidebar/context.js +17 -0
  36. package/dist/esm/sidebar/i18n.js +21 -0
  37. package/dist/esm/sidebar/index.js +6 -0
  38. package/dist/esm/sidebar/sidebar-header.js +38 -0
  39. package/dist/esm/sidebar/sidebar-item.js +59 -0
  40. package/dist/esm/sidebar/sidebar-list.js +211 -0
  41. package/dist/esm/sidebar/sidebar-root.js +61 -0
  42. package/dist/esm/sidebar/sidebar.js +28 -0
  43. package/dist/esm/sidebar/types.js +1 -0
  44. package/dist/esm/sidebar/utils.js +9 -0
  45. package/dist/esm/system/l10n.js +16 -0
  46. package/dist/esm/system/react-utils/sizing.js +19 -0
  47. package/dist/esm/tooltip/index.js +2 -0
  48. package/dist/esm/tooltip/tooltip.js +51 -0
  49. package/dist/types/field/field.d.ts +1 -1
  50. package/dist/types/field/field.d.ts.map +1 -1
  51. package/dist/types/index.d.mts +3 -0
  52. package/dist/types/index.d.ts +3 -0
  53. package/dist/types/index.d.ts.map +1 -1
  54. package/dist/types/phone-number-field/constants.d.ts +495 -0
  55. package/dist/types/phone-number-field/constants.d.ts.map +1 -0
  56. package/dist/types/phone-number-field/context.d.ts +15 -0
  57. package/dist/types/phone-number-field/context.d.ts.map +1 -0
  58. package/dist/types/phone-number-field/i18n.d.ts +1039 -0
  59. package/dist/types/phone-number-field/i18n.d.ts.map +1 -0
  60. package/dist/types/phone-number-field/index.d.ts +9 -0
  61. package/dist/types/phone-number-field/index.d.ts.map +1 -0
  62. package/dist/types/phone-number-field/phone-number-field.d.ts +42 -0
  63. package/dist/types/phone-number-field/phone-number-field.d.ts.map +1 -0
  64. package/dist/types/phone-number-field/types.d.ts +21 -0
  65. package/dist/types/phone-number-field/types.d.ts.map +1 -0
  66. package/dist/types/select/i18n.d.ts +19 -0
  67. package/dist/types/select/i18n.d.ts.map +1 -0
  68. package/dist/types/select/select.d.ts +11 -1
  69. package/dist/types/select/select.d.ts.map +1 -1
  70. package/dist/types/sidebar/context.d.ts +22 -0
  71. package/dist/types/sidebar/context.d.ts.map +1 -0
  72. package/dist/types/sidebar/i18n.d.ts +19 -0
  73. package/dist/types/sidebar/i18n.d.ts.map +1 -0
  74. package/dist/types/sidebar/index.d.ts +7 -0
  75. package/dist/types/sidebar/index.d.ts.map +1 -0
  76. package/dist/types/sidebar/sidebar-header.d.ts +6 -0
  77. package/dist/types/sidebar/sidebar-header.d.ts.map +1 -0
  78. package/dist/types/sidebar/sidebar-item.d.ts +3 -0
  79. package/dist/types/sidebar/sidebar-item.d.ts.map +1 -0
  80. package/dist/types/sidebar/sidebar-list.d.ts +3 -0
  81. package/dist/types/sidebar/sidebar-list.d.ts.map +1 -0
  82. package/dist/types/sidebar/sidebar-root.d.ts +17 -0
  83. package/dist/types/sidebar/sidebar-root.d.ts.map +1 -0
  84. package/dist/types/sidebar/sidebar.d.ts +8 -0
  85. package/dist/types/sidebar/sidebar.d.ts.map +1 -0
  86. package/dist/types/sidebar/types.d.ts +48 -0
  87. package/dist/types/sidebar/types.d.ts.map +1 -0
  88. package/dist/types/sidebar/utils.d.ts +4 -0
  89. package/dist/types/sidebar/utils.d.ts.map +1 -0
  90. package/dist/types/system/l10n.d.ts +10 -0
  91. package/dist/types/system/l10n.d.ts.map +1 -0
  92. package/dist/types/system/react-utils/children.d.ts +1 -2
  93. package/dist/types/system/react-utils/children.d.ts.map +1 -1
  94. package/dist/types/system/react-utils/sizing.d.ts +8 -0
  95. package/dist/types/system/react-utils/sizing.d.ts.map +1 -0
  96. package/dist/types/tooltip/index.d.ts +2 -0
  97. package/dist/types/tooltip/index.d.ts.map +1 -0
  98. package/dist/types/tooltip/tooltip.d.ts +16 -0
  99. package/dist/types/tooltip/tooltip.d.ts.map +1 -0
  100. package/package.json +7 -5
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ export { CountrySelect, FlagComponent, PhoneInput, PhoneNumberField } from './phone-number-field.js';
3
+ export { formatPhoneNumber, formatPhoneNumberIntl, isPossiblePhoneNumber, isValidPhoneNumber, parsePhoneNumber } from 'react-phone-number-input';
@@ -0,0 +1,294 @@
1
+ "use strict";
2
+ "use client";
3
+ import { jsxs, jsx } from 'react/jsx-runtime';
4
+ import { useMemo, useState, useRef, useCallback } from 'react';
5
+ import { TextField, Provider } from 'react-aria-components';
6
+ import BasePhoneInput, { getCountryCallingCode } from 'react-phone-number-input';
7
+ import flags from 'react-phone-number-input/flags';
8
+ import NonInternationalBasePhoneInput from 'react-phone-number-input/input';
9
+ import { phoneNumberFieldStyles, cn } from '@opengovsg/oui-theme';
10
+ import { Label, FieldGroup, Description, FieldError } from '../field/field.js';
11
+ import { useControllableState } from '../hooks/use-controllable-state.js';
12
+ import { Input } from '../input/input.js';
13
+ import { Select } from '../select/select.js';
14
+ import { SelectItem } from '../select/select-item.js';
15
+ import { useLocalizedStringFormatter } from '../system/l10n.js';
16
+ import { mapPropsVariants } from '../system/utils.js';
17
+ import { MOBILE_EXAMPLES } from './constants.js';
18
+ import { PhoneInputContext, usePhoneInputContext } from './context.js';
19
+ import { i18nStrings } from './i18n.js';
20
+
21
+ const PhoneInput = ({
22
+ onClear,
23
+ onKeyDown,
24
+ ...props
25
+ }) => {
26
+ const {
27
+ placeholderMode,
28
+ examples,
29
+ selectedCountry,
30
+ styles,
31
+ size,
32
+ classNames,
33
+ stringFormatter
34
+ } = usePhoneInputContext();
35
+ const inputPlaceholder = useMemo(() => {
36
+ const defaultPlaceholder = stringFormatter.format("Enter a phone number");
37
+ if (placeholderMode === "off") {
38
+ return props.placeholder ?? defaultPlaceholder;
39
+ }
40
+ const exampleNumber = selectedCountry && examples[selectedCountry];
41
+ if (placeholderMode === "aggressive") {
42
+ return exampleNumber ?? props.placeholder ?? defaultPlaceholder;
43
+ }
44
+ return props.placeholder ?? exampleNumber ?? defaultPlaceholder;
45
+ }, [
46
+ props.placeholder,
47
+ stringFormatter,
48
+ placeholderMode,
49
+ examples,
50
+ selectedCountry
51
+ ]);
52
+ const handleKeyDown = useCallback(
53
+ (event) => {
54
+ if (event.metaKey && event.key === "Backspace") {
55
+ event.preventDefault();
56
+ onClear?.();
57
+ } else {
58
+ onKeyDown?.(event);
59
+ }
60
+ },
61
+ [onClear, onKeyDown]
62
+ );
63
+ return /* @__PURE__ */ jsx(
64
+ Input,
65
+ {
66
+ variant: "unstyled",
67
+ placeholder: inputPlaceholder,
68
+ type: "tel",
69
+ autoComplete: "tel",
70
+ size,
71
+ ...props,
72
+ onKeyDown: handleKeyDown,
73
+ className: styles.input({
74
+ className: cn(classNames?.input, props.className)
75
+ })
76
+ }
77
+ );
78
+ };
79
+ const PhoneNumberField = (originalProps) => {
80
+ const [
81
+ {
82
+ placeholderMode = "polite",
83
+ examples = MOBILE_EXAMPLES,
84
+ label,
85
+ description,
86
+ errorMessage,
87
+ classNames,
88
+ isInvalid,
89
+ ...props
90
+ },
91
+ { variant = "international", ...variantProps }
92
+ ] = mapPropsVariants(originalProps, phoneNumberFieldStyles.variantKeys);
93
+ const stringFormatter = useLocalizedStringFormatter(i18nStrings);
94
+ const defaultCountry = useMemo(
95
+ () => props.defaultCountry ?? "SG",
96
+ [props.defaultCountry]
97
+ );
98
+ const [selectedCountry, setSelectedCountry] = useState(
99
+ defaultCountry
100
+ );
101
+ const [value, setValue] = useControllableState({
102
+ defaultValue: props.defaultValue,
103
+ value: props.value,
104
+ onChange: props.onChange
105
+ });
106
+ const triggerRef = useRef(null);
107
+ const { size = "md", isDisabled } = variantProps;
108
+ const styles = phoneNumberFieldStyles({
109
+ ...variantProps,
110
+ variant,
111
+ isDisabled,
112
+ size
113
+ });
114
+ return /* @__PURE__ */ jsxs(
115
+ TextField,
116
+ {
117
+ isDisabled,
118
+ className: styles.base({
119
+ className: classNames?.base
120
+ }),
121
+ isInvalid,
122
+ children: [
123
+ label && /* @__PURE__ */ jsx(Label, { size, className: classNames?.label, children: label }),
124
+ /* @__PURE__ */ jsx(
125
+ Provider,
126
+ {
127
+ values: [
128
+ [
129
+ PhoneInputContext,
130
+ {
131
+ triggerRef,
132
+ placeholderMode,
133
+ examples,
134
+ selectedCountry,
135
+ classNames,
136
+ styles,
137
+ variant,
138
+ ...variantProps,
139
+ size,
140
+ stringFormatter
141
+ }
142
+ ]
143
+ ],
144
+ children: /* @__PURE__ */ jsx(
145
+ FieldGroup,
146
+ {
147
+ isInvalid,
148
+ isDisabled,
149
+ "data-variant": variant,
150
+ ref: triggerRef,
151
+ className: styles.group({
152
+ className: classNames?.group
153
+ }),
154
+ children: variant === "international" ? /* @__PURE__ */ jsx(
155
+ BasePhoneInput,
156
+ {
157
+ disabled: isDisabled,
158
+ className: styles.wrapper({
159
+ className: classNames?.wrapper
160
+ }),
161
+ international: false,
162
+ addInternationalOption: false,
163
+ defaultCountry: selectedCountry,
164
+ countryOptionsOrder: [defaultCountry],
165
+ onCountryChange: setSelectedCountry,
166
+ countrySelectComponent: CountrySelect,
167
+ inputComponent: PhoneInput,
168
+ onClear: () => setValue(void 0),
169
+ ...props,
170
+ value,
171
+ onChange: (v) => setValue(v)
172
+ }
173
+ ) : /* @__PURE__ */ jsxs("div", { className: styles.wrapper({ className: classNames?.wrapper }), children: [
174
+ /* @__PURE__ */ jsx(
175
+ NonInternationalBasePhoneInput,
176
+ {
177
+ country: defaultCountry,
178
+ onClear: () => setValue(void 0),
179
+ ...props,
180
+ inputComponent: PhoneInput,
181
+ value,
182
+ onChange: setValue
183
+ }
184
+ ),
185
+ /* @__PURE__ */ jsx(
186
+ FlagComponent,
187
+ {
188
+ className: styles.flag({ className: classNames?.flag }),
189
+ country: defaultCountry,
190
+ countryName: stringFormatter.format(defaultCountry)
191
+ }
192
+ )
193
+ ] })
194
+ }
195
+ )
196
+ }
197
+ ),
198
+ description && /* @__PURE__ */ jsx(Description, { size, className: classNames?.description, children: description }),
199
+ /* @__PURE__ */ jsx(FieldError, { size, className: classNames?.error, children: errorMessage })
200
+ ]
201
+ }
202
+ );
203
+ };
204
+ function CountrySelect(props) {
205
+ const { options, value, onChange, onBlur, onFocus } = props;
206
+ const { triggerRef, classNames, styles, size, isDisabled, stringFormatter } = usePhoneInputContext();
207
+ return /* @__PURE__ */ jsx(
208
+ Select,
209
+ {
210
+ size,
211
+ popoverProps: {
212
+ // Position popover relative to the wrapping div instead of the Button
213
+ triggerRef
214
+ },
215
+ classNames: {
216
+ base: styles.select({ className: classNames?.select }),
217
+ trigger: styles.selectTrigger({
218
+ className: classNames?.selectTrigger
219
+ }),
220
+ icon: styles.selectIcon({ className: classNames?.selectIcon }),
221
+ // Apply same styles as trigger for consistent sizing
222
+ list: styles.selectList({ className: classNames?.selectList }),
223
+ popover: styles.selectPopover({ className: classNames?.selectPopover })
224
+ },
225
+ enableSearch: true,
226
+ variant: "unstyled",
227
+ isDisabled,
228
+ value,
229
+ onChange: (v) => onChange(v),
230
+ items: options,
231
+ renderSelectValue: () => /* @__PURE__ */ jsx(
232
+ FlagComponent,
233
+ {
234
+ className: styles.flag({ className: classNames?.flag }),
235
+ country: value,
236
+ countryName: value && stringFormatter.format(value)
237
+ }
238
+ ),
239
+ onBlur,
240
+ onFocus,
241
+ children: (country) => {
242
+ const l10nLabel = country.value ? stringFormatter.format(country.value) : "";
243
+ return /* @__PURE__ */ jsxs(
244
+ SelectItem,
245
+ {
246
+ classNames: {
247
+ text: styles.selectItem({ className: classNames?.selectItem })
248
+ },
249
+ textValue: `${l10nLabel} ${country.label}`,
250
+ id: country.value,
251
+ children: [
252
+ /* @__PURE__ */ jsx(
253
+ FlagComponent,
254
+ {
255
+ className: styles.flag({ className: classNames?.flag }),
256
+ country: country.value,
257
+ countryName: l10nLabel
258
+ }
259
+ ),
260
+ /* @__PURE__ */ jsx(
261
+ "span",
262
+ {
263
+ className: styles.selectItemLabel({
264
+ className: classNames?.selectItemLabel
265
+ }),
266
+ children: l10nLabel
267
+ }
268
+ ),
269
+ country.value && /* @__PURE__ */ jsx(
270
+ "span",
271
+ {
272
+ className: styles.selectItemCountryCode({
273
+ className: classNames?.selectItemCountryCode
274
+ }),
275
+ children: `+${getCountryCallingCode(country.value)}`
276
+ }
277
+ )
278
+ ]
279
+ }
280
+ );
281
+ }
282
+ }
283
+ );
284
+ }
285
+ const FlagComponent = ({
286
+ country,
287
+ countryName,
288
+ className
289
+ }) => {
290
+ const Flag = country && flags[country];
291
+ return /* @__PURE__ */ jsx("span", { className, children: Flag && /* @__PURE__ */ jsx(Flag, { title: countryName }) });
292
+ };
293
+
294
+ export { CountrySelect, FlagComponent, PhoneInput, PhoneNumberField };
@@ -0,0 +1 @@
1
+ "use strict";
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ const i18nStrings = {
3
+ "en-SG": {
4
+ "Search...": "Search...",
5
+ "Search options": "Search options"
6
+ },
7
+ "zh-SG": {
8
+ "Search...": "\u641C\u7D22...",
9
+ "Search options": "\u641C\u7D22\u9009\u9879"
10
+ },
11
+ "ms-SG": {
12
+ "Search...": "Cari...",
13
+ "Search options": "Cari pilihan"
14
+ },
15
+ "ta-SG": {
16
+ "Search...": "\u0BA4\u0BC7\u0B9F\u0BC1...",
17
+ "Search options": "\u0BA4\u0BC7\u0B9F\u0BB2\u0BCD \u0BB5\u0BBF\u0BB0\u0BC1\u0BAA\u0BCD\u0BAA\u0B99\u0BCD\u0B95\u0BB3\u0BCD"
18
+ }
19
+ };
20
+
21
+ export { i18nStrings };
@@ -8,28 +8,12 @@ import { selectStyles, cn, composeRenderProps } from '@opengovsg/oui-theme';
8
8
  import { Button } from '../button/button.js';
9
9
  import { Label, Description, FieldError } from '../field/field.js';
10
10
  import { Popover } from '../popover/popover.js';
11
+ import { useElementWidth } from '../system/react-utils/sizing.js';
11
12
  import { mapPropsVariants } from '../system/utils.js';
13
+ import { i18nStrings } from './i18n.js';
12
14
  import { SelectVariantContext } from './select-variant-context.js';
13
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';
14
16
 
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
- };
33
17
  const calculateEstimatedRowHeight = (size) => {
34
18
  switch (size) {
35
19
  case "xs":
@@ -47,7 +31,7 @@ function Select({
47
31
  errorMessage,
48
32
  ...originalProps
49
33
  }) {
50
- const formatter = useLocalizedStringFormatter(i18nStrings);
34
+ const stringFormatter = useLocalizedStringFormatter(i18nStrings);
51
35
  const [_props, variantProps] = mapPropsVariants(
52
36
  originalProps,
53
37
  selectStyles.variantKeys
@@ -59,9 +43,12 @@ function Select({
59
43
  enableSearch = false,
60
44
  searchPlaceholder,
61
45
  searchIcon,
46
+ renderSelectValue,
47
+ popoverProps,
62
48
  ...props
63
49
  } = _props;
64
50
  const styles = selectStyles(variantProps);
51
+ const triggerWidth = useElementWidth(popoverProps?.triggerRef);
65
52
  const { contains } = useFilter({ sensitivity: "base" });
66
53
  const layoutOptions = useMemo(() => {
67
54
  return {
@@ -128,7 +115,8 @@ function Select({
128
115
  {
129
116
  className: styles.selectedText({
130
117
  className: classNames?.selectedText
131
- })
118
+ }),
119
+ children: renderSelectValue
132
120
  }
133
121
  ),
134
122
  /* @__PURE__ */ jsx(
@@ -151,31 +139,43 @@ function Select({
151
139
  }
152
140
  ),
153
141
  /* @__PURE__ */ jsx(FieldError, { size: variantProps.size, className: classNames?.error, children: errorMessage }),
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 })
142
+ /* @__PURE__ */ jsx(
143
+ Popover,
144
+ {
145
+ className: styles.popover({ className: classNames?.popover }),
146
+ ...triggerWidth !== null ? {
147
+ style: {
148
+ "--trigger-width": triggerWidth
149
+ }
150
+ } : {},
151
+ ...popoverProps,
152
+ children: enableSearch ? /* @__PURE__ */ jsxs(Autocomplete, { filter: contains, children: [
153
+ /* @__PURE__ */ jsxs(
154
+ SearchField,
155
+ {
156
+ autoFocus: true,
157
+ "aria-label": stringFormatter.format("Search options"),
158
+ className: styles.searchField({
159
+ className: classNames?.searchField
160
+ }),
161
+ children: [
162
+ renderedSearchIcon,
163
+ /* @__PURE__ */ jsx(
164
+ Input,
165
+ {
166
+ placeholder: searchPlaceholder ?? stringFormatter.format("Search..."),
167
+ className: styles.searchInput({
168
+ className: classNames?.searchInput
169
+ })
170
+ }
171
+ )
172
+ ]
173
+ }
174
+ ),
175
+ listContent
176
+ ] }) : listContent
177
+ }
178
+ )
179
179
  ]
180
180
  }
181
181
  ) });
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ "use client";
3
+ import { createContext } from '../system/react-utils/context.js';
4
+
5
+ const [SidebarStyleContext, useSidebarStyleContext] = createContext({
6
+ name: "SidebarStyleContext"
7
+ });
8
+ const [SidebarCollapseContext, useSidebarCollapseContext] = createContext({
9
+ name: "SidebarCollapseContext"
10
+ });
11
+ const [SidebarNestContext, useSidebarNestContext] = createContext({
12
+ name: "SidebarNestContext",
13
+ strict: false,
14
+ defaultValue: { isNested: false, isExpanded: false }
15
+ });
16
+
17
+ export { SidebarCollapseContext, SidebarNestContext, SidebarStyleContext, useSidebarCollapseContext, useSidebarNestContext, useSidebarStyleContext };
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ const i18nStrings = {
3
+ "en-SG": {
4
+ "Expand sidebar section": "Expand sidebar section",
5
+ "Collapse sidebar section": "Collapse sidebar section"
6
+ },
7
+ "zh-SG": {
8
+ "Expand sidebar section": "\u5C55\u5F00\u4FA7\u8FB9\u680F\u90E8\u5206",
9
+ "Collapse sidebar section": "\u6298\u53E0\u4FA7\u8FB9\u680F\u90E8\u5206"
10
+ },
11
+ "ms-SG": {
12
+ "Expand sidebar section": "Perluas bahagian bar sisi",
13
+ "Collapse sidebar section": "Kuncupkan bahagian bar sisi"
14
+ },
15
+ "ta-SG": {
16
+ "Expand sidebar section": "\u0BAA\u0B95\u0BCD\u0B95\u0BB5\u0BBE\u0B9F\u0BCD\u0B9F\u0BC1\u0BAA\u0BCD \u0BAA\u0B95\u0BC1\u0BA4\u0BBF\u0BAF\u0BC8 \u0BB5\u0BBF\u0BB0\u0BBF\u0BB5\u0BBE\u0B95\u0BCD\u0B95\u0BC1",
17
+ "Collapse sidebar section": "\u0BAA\u0B95\u0BCD\u0B95\u0BB5\u0BBE\u0B9F\u0BCD\u0B9F\u0BC1\u0BAA\u0BCD \u0BAA\u0B95\u0BC1\u0BA4\u0BBF\u0BAF\u0BC8 \u0B9A\u0BC1\u0BB0\u0BC1\u0B95\u0BCD\u0B95\u0BC1"
18
+ }
19
+ };
20
+
21
+ export { i18nStrings };
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ export { Sidebar, generateSidebarItems } from './sidebar.js';
3
+ export { SidebarRoot } from './sidebar-root.js';
4
+ export { SidebarItem } from './sidebar-item.js';
5
+ export { SidebarList } from './sidebar-list.js';
6
+ export { SidebarHeader } from './sidebar-header.js';
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ "use client";
3
+ import { jsx, jsxs } from 'react/jsx-runtime';
4
+ import { renderChildren } from '../system/react-utils/children.js';
5
+ import { forwardRef } from '../system/utils.js';
6
+ import { useSidebarStyleContext } from './context.js';
7
+
8
+ const SidebarHeader = forwardRef(
9
+ ({ children, startContent, endContent, ...props }, ref) => {
10
+ const { slots, classNames } = useSidebarStyleContext();
11
+ return /* @__PURE__ */ jsx(
12
+ "li",
13
+ {
14
+ className: slots.headerLi({
15
+ className: classNames?.headerLi
16
+ }),
17
+ children: /* @__PURE__ */ jsxs(
18
+ "h2",
19
+ {
20
+ className: slots.header({
21
+ className: classNames?.header
22
+ }),
23
+ ref,
24
+ ...props,
25
+ children: [
26
+ startContent,
27
+ renderChildren({}, children),
28
+ endContent
29
+ ]
30
+ }
31
+ )
32
+ }
33
+ );
34
+ }
35
+ );
36
+ SidebarHeader.displayName = "SidebarHeader";
37
+
38
+ export { SidebarHeader };
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ "use client";
3
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
+ import { useMemo } from 'react';
5
+ import { Link } from 'react-aria-components';
6
+ import { dataAttr } from '@opengovsg/oui-theme';
7
+ import { renderChildren } from '../system/react-utils/children.js';
8
+ import { forwardRef } from '../system/utils.js';
9
+ import { TooltipTrigger, Tooltip } from '../tooltip/tooltip.js';
10
+ import { useSidebarStyleContext, useSidebarNestContext, useSidebarCollapseContext } from './context.js';
11
+
12
+ const SidebarItem = forwardRef(
13
+ ({ children, startContent, endContent, tooltip, isSelected, ...props }, ref) => {
14
+ const { slots, classNames } = useSidebarStyleContext();
15
+ const { isNested, isExpanded } = useSidebarNestContext() ?? {};
16
+ const { isCollapsed, tooltipProps, tooltipTriggerProps } = useSidebarCollapseContext() ?? {};
17
+ const dataSelected = useMemo(() => {
18
+ if (typeof isSelected === "function") {
19
+ return isSelected();
20
+ }
21
+ return isSelected;
22
+ }, [isSelected]);
23
+ return /* @__PURE__ */ jsx(
24
+ "li",
25
+ {
26
+ "data-selected": dataAttr(dataSelected),
27
+ "data-nested": dataAttr(isNested),
28
+ className: slots.item({
29
+ isNested,
30
+ className: classNames?.item
31
+ }),
32
+ ref,
33
+ children: /* @__PURE__ */ jsxs(TooltipTrigger, { delay: 0, ...tooltipTriggerProps, children: [
34
+ /* @__PURE__ */ jsx(
35
+ Link,
36
+ {
37
+ "aria-label": isCollapsed ? tooltip : void 0,
38
+ ...props,
39
+ className: slots.label({
40
+ isNested,
41
+ isExpanded,
42
+ className: classNames?.label
43
+ }),
44
+ children: (renderProps) => /* @__PURE__ */ jsxs(Fragment, { children: [
45
+ startContent,
46
+ !isCollapsed && renderChildren(renderProps, children),
47
+ !isCollapsed && endContent
48
+ ] })
49
+ }
50
+ ),
51
+ isCollapsed && /* @__PURE__ */ jsx(Tooltip, { placement: "end", ...tooltipProps, children: tooltip })
52
+ ] })
53
+ }
54
+ );
55
+ }
56
+ );
57
+ SidebarItem.displayName = "SidebarItem";
58
+
59
+ export { SidebarItem };