@opengovsg/oui 0.0.0-snapshot-20250318052429 → 0.0.0-snapshot-20250318093226

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 (42) hide show
  1. package/dist/cjs/badge/badge.cjs +42 -0
  2. package/dist/cjs/badge/index.cjs +8 -0
  3. package/dist/cjs/badge/use-badge.cjs +111 -0
  4. package/dist/cjs/banner/banner.cjs +1 -1
  5. package/dist/cjs/button/button.cjs +1 -1
  6. package/dist/cjs/combo-box/combo-box.cjs +1 -1
  7. package/dist/cjs/index.cjs +2 -0
  8. package/dist/cjs/select/select.cjs +2 -2
  9. package/dist/cjs/system/react-utils/index.cjs +2 -0
  10. package/dist/cjs/system/react-utils/refs.cjs +12 -0
  11. package/dist/cjs/tag-field/tag-field-list.cjs +2 -2
  12. package/dist/cjs/tag-field/tag-field.cjs +2 -2
  13. package/dist/cjs/text-area-field/text-area-field.cjs +1 -1
  14. package/dist/cjs/text-field/text-field.cjs +1 -1
  15. package/dist/esm/badge/badge.js +40 -0
  16. package/dist/esm/badge/index.js +2 -0
  17. package/dist/esm/badge/use-badge.js +109 -0
  18. package/dist/esm/banner/banner.js +1 -1
  19. package/dist/esm/button/button.js +1 -1
  20. package/dist/esm/combo-box/combo-box.js +1 -1
  21. package/dist/esm/index.js +1 -0
  22. package/dist/esm/select/select.js +2 -2
  23. package/dist/esm/system/react-utils/index.js +1 -0
  24. package/dist/esm/system/react-utils/refs.js +10 -0
  25. package/dist/esm/tag-field/tag-field-list.js +2 -2
  26. package/dist/esm/tag-field/tag-field.js +2 -2
  27. package/dist/esm/text-area-field/text-area-field.js +1 -1
  28. package/dist/esm/text-field/text-field.js +1 -1
  29. package/dist/types/badge/badge.d.ts +3 -0
  30. package/dist/types/badge/badge.d.ts.map +1 -0
  31. package/dist/types/badge/index.d.ts +2 -0
  32. package/dist/types/badge/index.d.ts.map +1 -0
  33. package/dist/types/badge/use-badge.d.ts +166 -0
  34. package/dist/types/badge/use-badge.d.ts.map +1 -0
  35. package/dist/types/index.d.mts +1 -0
  36. package/dist/types/index.d.ts +1 -0
  37. package/dist/types/index.d.ts.map +1 -1
  38. package/dist/types/system/react-utils/index.d.ts +1 -0
  39. package/dist/types/system/react-utils/index.d.ts.map +1 -1
  40. package/dist/types/system/react-utils/refs.d.ts +4 -0
  41. package/dist/types/system/react-utils/refs.d.ts.map +1 -0
  42. package/package.json +5 -4
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ "use client";
3
+ 'use strict';
4
+
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+ var react = require('react');
7
+ var useBadge = require('./use-badge.cjs');
8
+ var x = require('../node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/x.cjs');
9
+
10
+ const Badge = react.forwardRef((props, ref) => {
11
+ const {
12
+ Component,
13
+ children,
14
+ slots,
15
+ classNames,
16
+ getChipProps,
17
+ getCloseButtonProps,
18
+ startContent,
19
+ endContent,
20
+ isCloseable
21
+ } = useBadge.useBadge({ ...props, ref });
22
+ const start = react.useMemo(() => {
23
+ if (props.variant === "dot" && !startContent) {
24
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: slots.dot({ className: classNames?.dot }) });
25
+ }
26
+ return startContent;
27
+ }, [props.variant, startContent, slots, classNames?.dot]);
28
+ const end = react.useMemo(() => {
29
+ if (isCloseable) {
30
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { ...getCloseButtonProps(), children: endContent ?? /* @__PURE__ */ jsxRuntime.jsx(x.default, { className: "size-full" }) });
31
+ }
32
+ return endContent;
33
+ }, [endContent, getCloseButtonProps, isCloseable]);
34
+ return /* @__PURE__ */ jsxRuntime.jsxs(Component, { ...getChipProps(), children: [
35
+ start,
36
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: slots.content({ className: classNames?.content }), children }),
37
+ end
38
+ ] });
39
+ });
40
+ Badge.displayName = "Badge";
41
+
42
+ exports.Badge = Badge;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ 'use strict';
3
+
4
+ var badge = require('./badge.cjs');
5
+
6
+
7
+
8
+ exports.Badge = badge.Badge;
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ 'use strict';
3
+
4
+ var react = require('react');
5
+ var utils$1 = require('@react-aria/utils');
6
+ var reactAria = require('react-aria');
7
+ var useDeepCompare = require('use-deep-compare');
8
+ var ouiTheme = require('@opengovsg/oui-theme');
9
+ var utils = require('../system/utils.cjs');
10
+ var refs = require('../system/react-utils/refs.cjs');
11
+
12
+ const i18nStrings = {
13
+ "en-SG": {
14
+ close: "Close badge"
15
+ },
16
+ "zh-SG": {
17
+ close: "\u5173\u95ED\u5FBD\u7AE0"
18
+ },
19
+ "ms-SG": {
20
+ close: "Tutup lencana"
21
+ },
22
+ "ta-SG": {
23
+ close: "\u0BAA\u0BC7\u0B9F\u0BCD\u0B9C\u0BC8 \u0BAE\u0BC2\u0B9F\u0BC1"
24
+ }
25
+ };
26
+ function useBadge(originalProps) {
27
+ const [_props, variantProps] = utils.mapPropsVariants(
28
+ originalProps,
29
+ ouiTheme.badgeStyles.variantKeys
30
+ );
31
+ const {
32
+ ref,
33
+ as,
34
+ children,
35
+ startContent,
36
+ endContent,
37
+ onClose,
38
+ classNames,
39
+ className,
40
+ ...props
41
+ } = _props;
42
+ const domRef = refs.useDomRef(ref);
43
+ const Component = react.useMemo(() => as || "div", [as]);
44
+ const baseClassName = ouiTheme.cn(classNames?.base, className);
45
+ const formatMessage = reactAria.useMessageFormatter(i18nStrings);
46
+ const isCloseable = variantProps.isCloseable || !!onClose;
47
+ const {
48
+ focusProps: closeFocusProps,
49
+ isFocusVisible: isCloseButtonFocusVisible
50
+ } = reactAria.useFocusRing();
51
+ const slots = useDeepCompare.useDeepCompareMemo(
52
+ () => ({
53
+ ...ouiTheme.badgeStyles({ isCloseable, ...variantProps }),
54
+ closeButton: ouiTheme.badgeCloseButtonStyles
55
+ }),
56
+ [variantProps, isCloseable, ouiTheme.badgeStyles, ouiTheme.badgeCloseButtonStyles]
57
+ );
58
+ const { pressProps: closePressProps } = reactAria.usePress({
59
+ isDisabled: !!variantProps?.isDisabled,
60
+ onPress: onClose
61
+ });
62
+ const getContentClone = react.useCallback(
63
+ (content) => react.isValidElement(content) ? react.cloneElement(content, {
64
+ // @ts-expect-error types are not full
65
+ className: content.props?.className
66
+ }) : null,
67
+ []
68
+ );
69
+ const getChipProps = react.useCallback(() => {
70
+ return {
71
+ ref: domRef,
72
+ className: slots.base({ className: baseClassName }),
73
+ "aria-disabled": variantProps?.isDisabled,
74
+ ...props
75
+ };
76
+ }, [baseClassName, domRef, props, slots, variantProps?.isDisabled]);
77
+ const getCloseButtonProps = react.useCallback(() => {
78
+ return {
79
+ role: "button",
80
+ tabIndex: 0,
81
+ className: slots.closeButton({
82
+ size: variantProps?.size,
83
+ className: classNames?.closeButton,
84
+ isFocusVisible: isCloseButtonFocusVisible
85
+ }),
86
+ "aria-label": formatMessage("close"),
87
+ ...utils$1.mergeProps(closePressProps, closeFocusProps)
88
+ };
89
+ }, [
90
+ classNames?.closeButton,
91
+ closeFocusProps,
92
+ closePressProps,
93
+ formatMessage,
94
+ isCloseButtonFocusVisible,
95
+ slots,
96
+ variantProps?.size
97
+ ]);
98
+ return {
99
+ Component,
100
+ children,
101
+ slots,
102
+ classNames,
103
+ isCloseable,
104
+ startContent: getContentClone(startContent),
105
+ endContent: getContentClone(endContent),
106
+ getCloseButtonProps,
107
+ getChipProps
108
+ };
109
+ }
110
+
111
+ exports.useBadge = useBadge;
@@ -7,9 +7,9 @@ var react = require('react');
7
7
  var reactAria = require('react-aria');
8
8
  var reactStately = require('react-stately');
9
9
  var ouiTheme = require('@opengovsg/oui-theme');
10
- var button = require('../button/button.cjs');
11
10
  var circleAlert = require('../node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/circle-alert.cjs');
12
11
  var info = require('../node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/info.cjs');
12
+ var button = require('../button/button.cjs');
13
13
  var x = require('../node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/x.cjs');
14
14
 
15
15
  const i18nStrings = {
@@ -7,9 +7,9 @@ var react = require('react');
7
7
  var utils = require('@react-aria/utils');
8
8
  var reactAriaComponents = require('react-aria-components');
9
9
  var ouiTheme = require('@opengovsg/oui-theme');
10
- var ripple = require('../ripple/ripple.cjs');
11
10
  var useRipple = require('../ripple/use-ripple.cjs');
12
11
  var spinner = require('../spinner/spinner.cjs');
12
+ var ripple = require('../ripple/ripple.cjs');
13
13
 
14
14
  const Button = react.forwardRef(
15
15
  ({
@@ -7,9 +7,9 @@ var react = require('react');
7
7
  var reactAria = require('react-aria');
8
8
  var reactAriaComponents = require('react-aria-components');
9
9
  var ouiTheme = require('@opengovsg/oui-theme');
10
- var field = require('../field/field.cjs');
11
10
  var utils = require('../system/utils.cjs');
12
11
  var comboBoxVariantContext = require('./combo-box-variant-context.cjs');
12
+ var field = require('../field/field.cjs');
13
13
  var chevronUp = require('../node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/chevron-up.cjs');
14
14
  var chevronDown = require('../node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/chevron-down.cjs');
15
15
  var x = require('../node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/x.cjs');
@@ -24,6 +24,7 @@ var tagField = require('./tag-field/tag-field.cjs');
24
24
  var select = require('./select/select.cjs');
25
25
  var selectItem = require('./select/select-item.cjs');
26
26
  var selectVariantContext = require('./select/select-variant-context.cjs');
27
+ var badge = require('./badge/badge.cjs');
27
28
 
28
29
 
29
30
 
@@ -56,3 +57,4 @@ exports.Select = select.Select;
56
57
  exports.SelectItem = selectItem.SelectItem;
57
58
  exports.SelectVariantContext = selectVariantContext.SelectVariantContext;
58
59
  exports.useSelectVariantContext = selectVariantContext.useSelectVariantContext;
60
+ exports.Badge = badge.Badge;
@@ -6,11 +6,11 @@ var jsxRuntime = require('react/jsx-runtime');
6
6
  var react = require('react');
7
7
  var reactAriaComponents = require('react-aria-components');
8
8
  var ouiTheme = require('@opengovsg/oui-theme');
9
- var button = require('../button/button.cjs');
10
- var field = require('../field/field.cjs');
11
9
  var utils = require('../system/utils.cjs');
12
10
  var selectVariantContext = require('./select-variant-context.cjs');
13
11
  var chevronsUpDown = require('../node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/chevrons-up-down.cjs');
12
+ var field = require('../field/field.cjs');
13
+ var button = require('../button/button.cjs');
14
14
 
15
15
  const calculateEstimatedRowHeight = (size) => {
16
16
  switch (size) {
@@ -2,7 +2,9 @@
2
2
  'use strict';
3
3
 
4
4
  var context = require('./context.cjs');
5
+ var refs = require('./refs.cjs');
5
6
 
6
7
 
7
8
 
8
9
  exports.createContext = context.createContext;
10
+ exports.useDomRef = refs.useDomRef;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ 'use strict';
3
+
4
+ var react = require('react');
5
+
6
+ function useDomRef(ref) {
7
+ const domRef = react.useRef(null);
8
+ react.useImperativeHandle(ref, () => domRef.current);
9
+ return domRef;
10
+ }
11
+
12
+ exports.useDomRef = useDomRef;
@@ -57,8 +57,8 @@ const TagFieldListInner = (props, ref) => {
57
57
  item,
58
58
  isHighlighted: highlightedIndex === virtualRow.index,
59
59
  key: virtualRow.key,
60
- ...itemProps,
61
- classNames: itemClassNames
60
+ itemClassNames,
61
+ ...itemProps
62
62
  };
63
63
  if (typeof props.children === "function") {
64
64
  return props.children(childProps);
@@ -6,13 +6,13 @@ var jsxRuntime = require('react/jsx-runtime');
6
6
  var react = require('react');
7
7
  var reactAriaComponents = require('react-aria-components');
8
8
  var ouiTheme = require('@opengovsg/oui-theme');
9
- var field = require('../field/field.cjs');
10
- var input = require('../input/input.cjs');
11
9
  var tagFieldList = require('./tag-field-list.cjs');
12
10
  var tagFieldRoot = require('./tag-field-root.cjs');
13
11
  var tagFieldTagList = require('./tag-field-tag-list.cjs');
14
12
  var tagFieldTrigger = require('./tag-field-trigger.cjs');
15
13
  var chevronDown = require('../node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/chevron-down.cjs');
14
+ var field = require('../field/field.cjs');
15
+ var input = require('../input/input.cjs');
16
16
 
17
17
  function TagField({
18
18
  classNames,
@@ -5,8 +5,8 @@
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
  var reactAriaComponents = require('react-aria-components');
7
7
  var ouiTheme = require('@opengovsg/oui-theme');
8
- var field = require('../field/field.cjs');
9
8
  var textArea = require('../text-area/text-area.cjs');
9
+ var field = require('../field/field.cjs');
10
10
 
11
11
  function TextAreaField({
12
12
  label,
@@ -5,8 +5,8 @@
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
  var reactAriaComponents = require('react-aria-components');
7
7
  var ouiTheme = require('@opengovsg/oui-theme');
8
- var field = require('../field/field.cjs');
9
8
  var input = require('../input/input.cjs');
9
+ var field = require('../field/field.cjs');
10
10
 
11
11
  function TextField({
12
12
  label,
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ "use client";
3
+ import { jsx, jsxs } from 'react/jsx-runtime';
4
+ import { forwardRef, useMemo } from 'react';
5
+ import { useBadge } from './use-badge.js';
6
+ import X from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/x.js';
7
+
8
+ const Badge = forwardRef((props, ref) => {
9
+ const {
10
+ Component,
11
+ children,
12
+ slots,
13
+ classNames,
14
+ getChipProps,
15
+ getCloseButtonProps,
16
+ startContent,
17
+ endContent,
18
+ isCloseable
19
+ } = useBadge({ ...props, ref });
20
+ const start = useMemo(() => {
21
+ if (props.variant === "dot" && !startContent) {
22
+ return /* @__PURE__ */ jsx("span", { className: slots.dot({ className: classNames?.dot }) });
23
+ }
24
+ return startContent;
25
+ }, [props.variant, startContent, slots, classNames?.dot]);
26
+ const end = useMemo(() => {
27
+ if (isCloseable) {
28
+ return /* @__PURE__ */ jsx("span", { ...getCloseButtonProps(), children: endContent ?? /* @__PURE__ */ jsx(X, { className: "size-full" }) });
29
+ }
30
+ return endContent;
31
+ }, [endContent, getCloseButtonProps, isCloseable]);
32
+ return /* @__PURE__ */ jsxs(Component, { ...getChipProps(), children: [
33
+ start,
34
+ /* @__PURE__ */ jsx("span", { className: slots.content({ className: classNames?.content }), children }),
35
+ end
36
+ ] });
37
+ });
38
+ Badge.displayName = "Badge";
39
+
40
+ export { Badge };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ export { Badge } from './badge.js';
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ import { useMemo, useCallback, cloneElement, isValidElement } from 'react';
3
+ import { mergeProps } from '@react-aria/utils';
4
+ import { useMessageFormatter, useFocusRing, usePress } from 'react-aria';
5
+ import { useDeepCompareMemo } from 'use-deep-compare';
6
+ import { badgeStyles, cn, badgeCloseButtonStyles } from '@opengovsg/oui-theme';
7
+ import { mapPropsVariants } from '../system/utils.js';
8
+ import { useDomRef } from '../system/react-utils/refs.js';
9
+
10
+ const i18nStrings = {
11
+ "en-SG": {
12
+ close: "Close badge"
13
+ },
14
+ "zh-SG": {
15
+ close: "\u5173\u95ED\u5FBD\u7AE0"
16
+ },
17
+ "ms-SG": {
18
+ close: "Tutup lencana"
19
+ },
20
+ "ta-SG": {
21
+ close: "\u0BAA\u0BC7\u0B9F\u0BCD\u0B9C\u0BC8 \u0BAE\u0BC2\u0B9F\u0BC1"
22
+ }
23
+ };
24
+ function useBadge(originalProps) {
25
+ const [_props, variantProps] = mapPropsVariants(
26
+ originalProps,
27
+ badgeStyles.variantKeys
28
+ );
29
+ const {
30
+ ref,
31
+ as,
32
+ children,
33
+ startContent,
34
+ endContent,
35
+ onClose,
36
+ classNames,
37
+ className,
38
+ ...props
39
+ } = _props;
40
+ const domRef = useDomRef(ref);
41
+ const Component = useMemo(() => as || "div", [as]);
42
+ const baseClassName = cn(classNames?.base, className);
43
+ const formatMessage = useMessageFormatter(i18nStrings);
44
+ const isCloseable = variantProps.isCloseable || !!onClose;
45
+ const {
46
+ focusProps: closeFocusProps,
47
+ isFocusVisible: isCloseButtonFocusVisible
48
+ } = useFocusRing();
49
+ const slots = useDeepCompareMemo(
50
+ () => ({
51
+ ...badgeStyles({ isCloseable, ...variantProps }),
52
+ closeButton: badgeCloseButtonStyles
53
+ }),
54
+ [variantProps, isCloseable, badgeStyles, badgeCloseButtonStyles]
55
+ );
56
+ const { pressProps: closePressProps } = usePress({
57
+ isDisabled: !!variantProps?.isDisabled,
58
+ onPress: onClose
59
+ });
60
+ const getContentClone = useCallback(
61
+ (content) => isValidElement(content) ? cloneElement(content, {
62
+ // @ts-expect-error types are not full
63
+ className: content.props?.className
64
+ }) : null,
65
+ []
66
+ );
67
+ const getChipProps = useCallback(() => {
68
+ return {
69
+ ref: domRef,
70
+ className: slots.base({ className: baseClassName }),
71
+ "aria-disabled": variantProps?.isDisabled,
72
+ ...props
73
+ };
74
+ }, [baseClassName, domRef, props, slots, variantProps?.isDisabled]);
75
+ const getCloseButtonProps = useCallback(() => {
76
+ return {
77
+ role: "button",
78
+ tabIndex: 0,
79
+ className: slots.closeButton({
80
+ size: variantProps?.size,
81
+ className: classNames?.closeButton,
82
+ isFocusVisible: isCloseButtonFocusVisible
83
+ }),
84
+ "aria-label": formatMessage("close"),
85
+ ...mergeProps(closePressProps, closeFocusProps)
86
+ };
87
+ }, [
88
+ classNames?.closeButton,
89
+ closeFocusProps,
90
+ closePressProps,
91
+ formatMessage,
92
+ isCloseButtonFocusVisible,
93
+ slots,
94
+ variantProps?.size
95
+ ]);
96
+ return {
97
+ Component,
98
+ children,
99
+ slots,
100
+ classNames,
101
+ isCloseable,
102
+ startContent: getContentClone(startContent),
103
+ endContent: getContentClone(endContent),
104
+ getCloseButtonProps,
105
+ getChipProps
106
+ };
107
+ }
108
+
109
+ export { useBadge };
@@ -5,9 +5,9 @@ import { useMemo, useRef } from 'react';
5
5
  import { useMessageFormatter, useDisclosure } from 'react-aria';
6
6
  import { useDisclosureState } from 'react-stately';
7
7
  import { bannerStyles } from '@opengovsg/oui-theme';
8
- import { Button } from '../button/button.js';
9
8
  import CircleAlert from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/circle-alert.js';
10
9
  import Info from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/info.js';
10
+ import { Button } from '../button/button.js';
11
11
  import X from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/x.js';
12
12
 
13
13
  const i18nStrings = {
@@ -5,9 +5,9 @@ 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';
7
7
  import { buttonStyles } from '@opengovsg/oui-theme';
8
- import { Ripple } from '../ripple/ripple.js';
9
8
  import { useRipple } from '../ripple/use-ripple.js';
10
9
  import { Spinner } from '../spinner/spinner.js';
10
+ import { Ripple } from '../ripple/ripple.js';
11
11
 
12
12
  const Button = forwardRef(
13
13
  ({
@@ -5,9 +5,9 @@ import { useMemo, useCallback } from 'react';
5
5
  import { useMessageFormatter } from 'react-aria';
6
6
  import { ListLayout, Provider, ComboBox as ComboBox$1, Input, Button, Popover, Virtualizer, ListBox } from 'react-aria-components';
7
7
  import { comboBoxItemStyles, cn, comboBoxStyles, composeTailwindRenderProps, composeRenderProps, comboBoxClearButtonStyles } from '@opengovsg/oui-theme';
8
- import { Label, FieldGroup, Description, FieldError } from '../field/field.js';
9
8
  import { mapPropsVariants } from '../system/utils.js';
10
9
  import { ComboBoxVariantContext } from './combo-box-variant-context.js';
10
+ import { Label, FieldGroup, Description, FieldError } from '../field/field.js';
11
11
  import ChevronUp from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/chevron-up.js';
12
12
  import ChevronDown from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/chevron-down.js';
13
13
  import X from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/x.js';
package/dist/esm/index.js CHANGED
@@ -22,3 +22,4 @@ export { TagField } from './tag-field/tag-field.js';
22
22
  export { Select } from './select/select.js';
23
23
  export { SelectItem } from './select/select-item.js';
24
24
  export { SelectVariantContext, useSelectVariantContext } from './select/select-variant-context.js';
25
+ export { Badge } from './badge/badge.js';
@@ -4,11 +4,11 @@ import { jsx, jsxs } from 'react/jsx-runtime';
4
4
  import { useMemo } from 'react';
5
5
  import { ListLayout, Provider, Select as Select$1, SelectValue, Popover, Virtualizer, ListBox } from 'react-aria-components';
6
6
  import { selectStyles, composeRenderProps } from '@opengovsg/oui-theme';
7
- import { Button } from '../button/button.js';
8
- import { Label, Description } from '../field/field.js';
9
7
  import { mapPropsVariants } from '../system/utils.js';
10
8
  import { SelectVariantContext } from './select-variant-context.js';
11
9
  import ChevronsUpDown from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/chevrons-up-down.js';
10
+ import { Label, Description } from '../field/field.js';
11
+ import { Button } from '../button/button.js';
12
12
 
13
13
  const calculateEstimatedRowHeight = (size) => {
14
14
  switch (size) {
@@ -1,2 +1,3 @@
1
1
  "use strict";
2
2
  export { createContext } from './context.js';
3
+ export { useDomRef } from './refs.js';
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ import { useRef, useImperativeHandle } from 'react';
3
+
4
+ function useDomRef(ref) {
5
+ const domRef = useRef(null);
6
+ useImperativeHandle(ref, () => domRef.current);
7
+ return domRef;
8
+ }
9
+
10
+ export { useDomRef };
@@ -55,8 +55,8 @@ const TagFieldListInner = (props, ref) => {
55
55
  item,
56
56
  isHighlighted: highlightedIndex === virtualRow.index,
57
57
  key: virtualRow.key,
58
- ...itemProps,
59
- classNames: itemClassNames
58
+ itemClassNames,
59
+ ...itemProps
60
60
  };
61
61
  if (typeof props.children === "function") {
62
62
  return props.children(childProps);
@@ -4,13 +4,13 @@ import { jsxs, jsx } from 'react/jsx-runtime';
4
4
  import { createElement } from 'react';
5
5
  import { composeRenderProps, Popover } 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
7
  import { TagFieldList, TagFieldListItem } from './tag-field-list.js';
10
8
  import { TagFieldRoot } from './tag-field-root.js';
11
9
  import { TagFieldTagList } from './tag-field-tag-list.js';
12
10
  import { TagFieldTrigger } from './tag-field-trigger.js';
13
11
  import ChevronDown from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/chevron-down.js';
12
+ import { Label, FieldGroup, Description, FieldError } from '../field/field.js';
13
+ import { Input } from '../input/input.js';
14
14
 
15
15
  function TagField({
16
16
  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 { Label, Description, FieldError } from '../field/field.js';
7
6
  import { TextArea } from '../text-area/text-area.js';
7
+ import { Label, Description, FieldError } from '../field/field.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 { Label, Description, FieldError } from '../field/field.js';
7
6
  import { Input } from '../input/input.js';
7
+ import { Label, Description, FieldError } from '../field/field.js';
8
8
 
9
9
  function TextField({
10
10
  label,
@@ -0,0 +1,3 @@
1
+ import type { UseBadgeProps } from "./use-badge";
2
+ export declare const Badge: import("react").ForwardRefExoticComponent<Omit<UseBadgeProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
3
+ //# sourceMappingURL=badge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"badge.d.ts","sourceRoot":"","sources":["../../../src/badge/badge.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAGhD,eAAO,MAAM,KAAK,uHAwChB,CAAA"}
@@ -0,0 +1,2 @@
1
+ export * from "./badge";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/badge/index.tsx"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA"}
@@ -0,0 +1,166 @@
1
+ import type { PressEvent } from "@react-types/shared";
2
+ import type { ReactNode } from "react";
3
+ import type { BadgeSlots, BadgeVariantProps, SlotsToClasses } from "@opengovsg/oui-theme";
4
+ import type { ReactRef } from "../system/react-utils";
5
+ import type { HtmlUiProps, PropGetter } from "../system/types";
6
+ export interface UseBadgeProps extends HtmlUiProps, BadgeVariantProps {
7
+ ref?: ReactRef<HTMLDivElement | null>;
8
+ /**
9
+ * Element to be rendered in the left side of the badge.
10
+ */
11
+ startContent?: React.ReactNode;
12
+ /**
13
+ * Element to be rendered in the right side of the badge.
14
+ * if you pass this prop and the `onClose` prop, the passed element
15
+ * will have the close button props and it will be rendered instead of the
16
+ * default close button.
17
+ */
18
+ endContent?: React.ReactNode;
19
+ /**
20
+ * Classname or List of classes to change the classNames of the element.
21
+ * if `className` is passed, it will be added to the base slot.
22
+ *
23
+ * @example
24
+ * ```ts
25
+ * <Badge classNames={{
26
+ * base:"base-classes",
27
+ * dot: "dot-classes",
28
+ * content: "content-classes",
29
+ * closeButton: "close-button-classes",
30
+ * }} />
31
+ * ```
32
+ */
33
+ classNames?: SlotsToClasses<BadgeSlots | "closeButton">;
34
+ /**
35
+ * Callback fired when the badge is closed. if you pass this prop,
36
+ * the badge will display a close button in the `endContent` slot.
37
+ * @param e PressEvent
38
+ */
39
+ onClose?: (e: PressEvent) => void;
40
+ }
41
+ export declare function useBadge(originalProps: UseBadgeProps): {
42
+ Component: import("../system/types").As<any>;
43
+ children: ReactNode;
44
+ slots: {
45
+ closeButton: import("tailwind-variants").TVReturnType<{
46
+ size: {
47
+ xs: string;
48
+ sm: string;
49
+ md: string;
50
+ };
51
+ }, undefined, string, {
52
+ responsiveVariants?: boolean | (string | number | symbol)[] | {
53
+ size?: boolean | (string | number | symbol)[] | undefined;
54
+ isFocusVisible?: boolean | (string | number | symbol)[] | undefined;
55
+ } | undefined;
56
+ } & import("tailwind-variants/dist/config.js").TWMConfig & {
57
+ twMergeConfig: {
58
+ extend: {
59
+ theme: {};
60
+ classGroups: {
61
+ prose: {
62
+ prose: (() => boolean)[];
63
+ }[];
64
+ };
65
+ };
66
+ };
67
+ }, {
68
+ isFocusVisible: {
69
+ false: string;
70
+ true: string;
71
+ };
72
+ }, undefined, import("tailwind-variants").TVReturnType<{
73
+ isFocusVisible: {
74
+ false: string;
75
+ true: string;
76
+ };
77
+ }, undefined, "outline-offset-2 outline-none", {
78
+ responsiveVariants?: boolean | (string | number | symbol)[] | {
79
+ isFocusVisible?: boolean | (string | number | symbol)[] | undefined;
80
+ } | undefined;
81
+ } & import("tailwind-variants/dist/config.js").TWMConfig & {
82
+ twMergeConfig: {
83
+ extend: {
84
+ theme: {};
85
+ classGroups: {
86
+ prose: {
87
+ prose: (() => boolean)[];
88
+ }[];
89
+ };
90
+ };
91
+ };
92
+ }, {
93
+ isFocusVisible: {
94
+ false: string;
95
+ true: string;
96
+ };
97
+ }, undefined, import("tailwind-variants").TVReturnType<{
98
+ isFocusVisible: {
99
+ false: string;
100
+ true: string;
101
+ };
102
+ }, undefined, "outline-offset-2 outline-none", import("tailwind-variants/dist/config.js").TVConfig<{
103
+ isFocusVisible: {
104
+ false: string;
105
+ true: string;
106
+ };
107
+ }, {
108
+ isFocusVisible: {
109
+ false: string;
110
+ true: string;
111
+ };
112
+ }>, unknown, unknown, undefined>>>;
113
+ base: ((slotProps?: ({
114
+ size?: "md" | "sm" | "xs" | undefined;
115
+ color?: "sub" | "main" | "neutral" | "critical" | "warning" | "success" | undefined;
116
+ radius?: "lg" | "md" | "sm" | "none" | "full" | undefined;
117
+ variant?: "solid" | "outline" | "dot" | "subtle" | undefined;
118
+ isDisabled?: boolean | undefined;
119
+ isCloseable?: boolean | undefined;
120
+ } & import("tailwind-variants").ClassProp<import("tailwind-variants").ClassValue>) | undefined) => string) & ((slotProps?: ({
121
+ size?: "md" | "sm" | "xs" | undefined;
122
+ color?: "sub" | "main" | "neutral" | "critical" | "warning" | "success" | undefined;
123
+ radius?: "lg" | "md" | "sm" | "none" | "full" | undefined;
124
+ variant?: "solid" | "outline" | "dot" | "subtle" | undefined;
125
+ isDisabled?: boolean | undefined;
126
+ isCloseable?: boolean | undefined;
127
+ } & import("tailwind-variants").ClassProp<import("tailwind-variants").ClassValue>) | undefined) => string);
128
+ dot: ((slotProps?: ({
129
+ size?: "md" | "sm" | "xs" | undefined;
130
+ color?: "sub" | "main" | "neutral" | "critical" | "warning" | "success" | undefined;
131
+ radius?: "lg" | "md" | "sm" | "none" | "full" | undefined;
132
+ variant?: "solid" | "outline" | "dot" | "subtle" | undefined;
133
+ isDisabled?: boolean | undefined;
134
+ isCloseable?: boolean | undefined;
135
+ } & import("tailwind-variants").ClassProp<import("tailwind-variants").ClassValue>) | undefined) => string) & ((slotProps?: ({
136
+ size?: "md" | "sm" | "xs" | undefined;
137
+ color?: "sub" | "main" | "neutral" | "critical" | "warning" | "success" | undefined;
138
+ radius?: "lg" | "md" | "sm" | "none" | "full" | undefined;
139
+ variant?: "solid" | "outline" | "dot" | "subtle" | undefined;
140
+ isDisabled?: boolean | undefined;
141
+ isCloseable?: boolean | undefined;
142
+ } & import("tailwind-variants").ClassProp<import("tailwind-variants").ClassValue>) | undefined) => string);
143
+ content: ((slotProps?: ({
144
+ size?: "md" | "sm" | "xs" | undefined;
145
+ color?: "sub" | "main" | "neutral" | "critical" | "warning" | "success" | undefined;
146
+ radius?: "lg" | "md" | "sm" | "none" | "full" | undefined;
147
+ variant?: "solid" | "outline" | "dot" | "subtle" | undefined;
148
+ isDisabled?: boolean | undefined;
149
+ isCloseable?: boolean | undefined;
150
+ } & import("tailwind-variants").ClassProp<import("tailwind-variants").ClassValue>) | undefined) => string) & ((slotProps?: ({
151
+ size?: "md" | "sm" | "xs" | undefined;
152
+ color?: "sub" | "main" | "neutral" | "critical" | "warning" | "success" | undefined;
153
+ radius?: "lg" | "md" | "sm" | "none" | "full" | undefined;
154
+ variant?: "solid" | "outline" | "dot" | "subtle" | undefined;
155
+ isDisabled?: boolean | undefined;
156
+ isCloseable?: boolean | undefined;
157
+ } & import("tailwind-variants").ClassProp<import("tailwind-variants").ClassValue>) | undefined) => string);
158
+ };
159
+ classNames: SlotsToClasses<"content" | "base" | "dot" | "closeButton"> | undefined;
160
+ isCloseable: boolean;
161
+ startContent: import("react").DetailedReactHTMLElement<import("react").HTMLAttributes<HTMLElement>, HTMLElement> | null;
162
+ endContent: import("react").DetailedReactHTMLElement<import("react").HTMLAttributes<HTMLElement>, HTMLElement> | null;
163
+ getCloseButtonProps: PropGetter;
164
+ getChipProps: PropGetter;
165
+ };
166
+ //# sourceMappingURL=use-badge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-badge.d.ts","sourceRoot":"","sources":["../../../src/badge/use-badge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AACrD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAOtC,OAAO,KAAK,EACV,UAAU,EACV,iBAAiB,EACjB,cAAc,EACf,MAAM,sBAAsB,CAAA;AAG7B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAI9D,MAAM,WAAW,aAAc,SAAQ,WAAW,EAAE,iBAAiB;IACnE,GAAG,CAAC,EAAE,QAAQ,CAAC,cAAc,GAAG,IAAI,CAAC,CAAA;IACrC;;OAEG;IACH,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC9B;;;;;OAKG;IACH,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAE5B;;;;;;;;;;;;;OAaG;IACH,UAAU,CAAC,EAAE,cAAc,CAAC,UAAU,GAAG,aAAa,CAAC,CAAA;IACvD;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAA;CAClC;AAiBD,wBAAgB,QAAQ,CAAC,aAAa,EAAE,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiGpD"}
@@ -14,4 +14,5 @@ export * from "./combo-box";
14
14
  export * from "./banner";
15
15
  export * from "./tag-field";
16
16
  export * from "./select";
17
+ export * from "./badge";
17
18
  //# sourceMappingURL=index.d.ts.map
@@ -14,4 +14,5 @@ export * from "./combo-box";
14
14
  export * from "./banner";
15
15
  export * from "./tag-field";
16
16
  export * from "./select";
17
+ export * from "./badge";
17
18
  //# 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"}
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"}
@@ -1,2 +1,3 @@
1
1
  export * from "./context";
2
+ export * from "./refs";
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/system/react-utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/system/react-utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA;AACzB,cAAc,QAAQ,CAAA"}
@@ -0,0 +1,4 @@
1
+ import type React from "react";
2
+ export type ReactRef<T> = React.RefObject<T> | React.Ref<T>;
3
+ export declare function useDomRef<T extends HTMLElement = HTMLElement>(ref?: ReactRef<T | null>): React.RefObject<T | null>;
4
+ //# sourceMappingURL=refs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refs.d.ts","sourceRoot":"","sources":["../../../../src/system/react-utils/refs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;AAE3D,wBAAgB,SAAS,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,EAC3D,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC,GAAG,IAAI,CAAC,6BAOzB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengovsg/oui",
3
- "version": "0.0.0-snapshot-20250318052429",
3
+ "version": "0.0.0-snapshot-20250318093226",
4
4
  "sideEffects": false,
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "type": "module",
@@ -47,10 +47,10 @@
47
47
  "prettier": "^3.5.0",
48
48
  "tsx": "^4.19.2",
49
49
  "typescript": "5.7.3",
50
- "@opengovsg/oui-theme": "0.0.5",
50
+ "@oui/chromatic": "0.0.0",
51
51
  "@oui/eslint-config": "0.0.0",
52
+ "@opengovsg/oui-theme": "0.0.0-snapshot-20250318093226",
52
53
  "@oui/prettier-config": "0.0.0",
53
- "@oui/chromatic": "0.0.0",
54
54
  "@oui/typescript-config": "0.0.0"
55
55
  },
56
56
  "dependencies": {
@@ -78,11 +78,12 @@
78
78
  "peerDependencies": {
79
79
  "motion": ">=11.12.0 || >=12.0.0-alpha.1",
80
80
  "react-aria-components": "^1.7.1",
81
- "@opengovsg/oui-theme": "0.0.5"
81
+ "@opengovsg/oui-theme": "0.0.0-snapshot-20250318093226"
82
82
  },
83
83
  "prettier": "@oui/prettier-config",
84
84
  "scripts": {
85
85
  "build": "tsx ../../tooling/build-scripts/main.ts --dts --clean",
86
+ "changeset": "cd ../.. && pnpm changeset",
86
87
  "dev": "tsx ../../tooling/build-scripts/main.ts --watch",
87
88
  "lint": "eslint . --max-warnings 0",
88
89
  "lint:fix": "eslint . --fix",