@opengovsg/oui 0.0.7 → 0.0.9

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 (122) 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/calendar/calendar-base.cjs +347 -0
  5. package/dist/cjs/calendar/calendar-style-context.cjs +38 -0
  6. package/dist/cjs/calendar/calendar.cjs +16 -0
  7. package/dist/cjs/calendar/index.cjs +22 -0
  8. package/dist/cjs/calendar/types.cjs +3 -0
  9. package/dist/cjs/calendar/utils.cjs +62 -0
  10. package/dist/cjs/combo-box/combo-box-fuzzy.cjs +52 -30
  11. package/dist/cjs/combo-box/combo-box-item.cjs +70 -0
  12. package/dist/cjs/combo-box/combo-box-variant-context.cjs +13 -0
  13. package/dist/cjs/combo-box/combo-box.cjs +46 -100
  14. package/dist/cjs/combo-box/index.cjs +5 -1
  15. package/dist/cjs/index.cjs +30 -1
  16. package/dist/cjs/node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/{check.cjs → chevron-left.cjs} +3 -3
  17. package/dist/cjs/node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/{chevrons-up-down.cjs → chevron-right.cjs} +3 -6
  18. package/dist/cjs/select/index.cjs +5 -0
  19. package/dist/cjs/select/select-item.cjs +12 -24
  20. package/dist/cjs/select/select-variant-context.cjs +1 -0
  21. package/dist/cjs/select/select.cjs +14 -6
  22. package/dist/cjs/system/react-utils/index.cjs +2 -0
  23. package/dist/cjs/system/react-utils/refs.cjs +12 -0
  24. package/dist/cjs/system/utils.cjs +9 -6
  25. package/dist/cjs/tag-field/index.cjs +2 -0
  26. package/dist/cjs/tag-field/tag-field-item.cjs +28 -0
  27. package/dist/cjs/tag-field/tag-field-list.cjs +11 -21
  28. package/dist/cjs/tag-field/tag-field-tag-list.cjs +3 -2
  29. package/dist/cjs/tag-field/tag-field-trigger.cjs +1 -0
  30. package/dist/cjs/tag-field/tag-field.cjs +2 -1
  31. package/dist/esm/badge/badge.js +40 -0
  32. package/dist/esm/badge/index.js +2 -0
  33. package/dist/esm/badge/use-badge.js +109 -0
  34. package/dist/esm/calendar/calendar-base.js +343 -0
  35. package/dist/esm/calendar/calendar-style-context.js +34 -0
  36. package/dist/esm/calendar/calendar.js +14 -0
  37. package/dist/esm/calendar/index.js +5 -0
  38. package/dist/esm/calendar/types.js +1 -0
  39. package/dist/esm/calendar/utils.js +57 -0
  40. package/dist/esm/combo-box/combo-box-fuzzy.js +55 -33
  41. package/dist/esm/combo-box/combo-box-item.js +68 -0
  42. package/dist/esm/combo-box/combo-box-variant-context.js +10 -0
  43. package/dist/esm/combo-box/combo-box.js +48 -101
  44. package/dist/esm/combo-box/index.js +3 -1
  45. package/dist/esm/index.js +11 -1
  46. package/dist/esm/node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/{check.js → chevron-left.js} +3 -3
  47. package/dist/esm/node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/chevron-right.js +14 -0
  48. package/dist/esm/select/index.js +2 -0
  49. package/dist/esm/select/select-item.js +13 -25
  50. package/dist/esm/select/select-variant-context.js +1 -0
  51. package/dist/esm/select/select.js +15 -7
  52. package/dist/esm/system/react-utils/index.js +1 -0
  53. package/dist/esm/system/react-utils/refs.js +10 -0
  54. package/dist/esm/system/utils.js +9 -6
  55. package/dist/esm/tag-field/index.js +1 -0
  56. package/dist/esm/tag-field/tag-field-item.js +26 -0
  57. package/dist/esm/tag-field/tag-field-list.js +12 -21
  58. package/dist/esm/tag-field/tag-field-tag-list.js +3 -2
  59. package/dist/esm/tag-field/tag-field-trigger.js +1 -0
  60. package/dist/esm/tag-field/tag-field.js +3 -2
  61. package/dist/types/badge/badge.d.ts +3 -0
  62. package/dist/types/badge/badge.d.ts.map +1 -0
  63. package/dist/types/badge/index.d.ts +2 -0
  64. package/dist/types/badge/index.d.ts.map +1 -0
  65. package/dist/types/badge/use-badge.d.ts +166 -0
  66. package/dist/types/badge/use-badge.d.ts.map +1 -0
  67. package/dist/types/button/button.d.ts +5 -0
  68. package/dist/types/button/button.d.ts.map +1 -1
  69. package/dist/types/calendar/calendar-base.d.ts +14 -0
  70. package/dist/types/calendar/calendar-base.d.ts.map +1 -0
  71. package/dist/types/calendar/calendar-style-context.d.ts +1032 -0
  72. package/dist/types/calendar/calendar-style-context.d.ts.map +1 -0
  73. package/dist/types/calendar/calendar.d.ts +5 -0
  74. package/dist/types/calendar/calendar.d.ts.map +1 -0
  75. package/dist/types/calendar/index.d.ts +6 -0
  76. package/dist/types/calendar/index.d.ts.map +1 -0
  77. package/dist/types/calendar/types.d.ts +58 -0
  78. package/dist/types/calendar/types.d.ts.map +1 -0
  79. package/dist/types/calendar/utils.d.ts +13 -0
  80. package/dist/types/calendar/utils.d.ts.map +1 -0
  81. package/dist/types/combo-box/combo-box-fuzzy.d.ts +12 -4
  82. package/dist/types/combo-box/combo-box-fuzzy.d.ts.map +1 -1
  83. package/dist/types/combo-box/combo-box-item.d.ts +11 -0
  84. package/dist/types/combo-box/combo-box-item.d.ts.map +1 -0
  85. package/dist/types/combo-box/combo-box-variant-context.d.ts +4 -0
  86. package/dist/types/combo-box/combo-box-variant-context.d.ts.map +1 -0
  87. package/dist/types/combo-box/combo-box.d.ts +5 -21
  88. package/dist/types/combo-box/combo-box.d.ts.map +1 -1
  89. package/dist/types/combo-box/index.d.ts +2 -0
  90. package/dist/types/combo-box/index.d.ts.map +1 -1
  91. package/dist/types/index.d.mts +2 -0
  92. package/dist/types/index.d.ts +2 -0
  93. package/dist/types/index.d.ts.map +1 -1
  94. package/dist/types/select/index.d.ts +2 -0
  95. package/dist/types/select/index.d.ts.map +1 -1
  96. package/dist/types/select/select-item.d.ts.map +1 -1
  97. package/dist/types/select/select-variant-context.d.ts.map +1 -1
  98. package/dist/types/select/select.d.ts.map +1 -1
  99. package/dist/types/system/react-utils/index.d.ts +1 -0
  100. package/dist/types/system/react-utils/index.d.ts.map +1 -1
  101. package/dist/types/system/react-utils/refs.d.ts +4 -0
  102. package/dist/types/system/react-utils/refs.d.ts.map +1 -0
  103. package/dist/types/system/utils.d.ts.map +1 -1
  104. package/dist/types/tag-field/index.d.ts +1 -0
  105. package/dist/types/tag-field/index.d.ts.map +1 -1
  106. package/dist/types/tag-field/tag-field-item.d.ts +7 -0
  107. package/dist/types/tag-field/tag-field-item.d.ts.map +1 -0
  108. package/dist/types/tag-field/tag-field-list.d.ts +5 -9
  109. package/dist/types/tag-field/tag-field-list.d.ts.map +1 -1
  110. package/dist/types/tag-field/tag-field-root.d.ts +4 -4
  111. package/dist/types/tag-field/tag-field-root.d.ts.map +1 -1
  112. package/dist/types/tag-field/tag-field-state-context.d.ts +1 -2
  113. package/dist/types/tag-field/tag-field-state-context.d.ts.map +1 -1
  114. package/dist/types/tag-field/tag-field-tag-list.d.ts +2 -3
  115. package/dist/types/tag-field/tag-field-tag-list.d.ts.map +1 -1
  116. package/dist/types/tag-field/tag-field-trigger.d.ts.map +1 -1
  117. package/dist/types/tag-field/tag-field.d.ts +2 -2
  118. package/dist/types/tag-field/tag-field.d.ts.map +1 -1
  119. package/dist/types/tag-field/types.d.ts +6 -9
  120. package/dist/types/tag-field/types.d.ts.map +1 -1
  121. package/package.json +8 -6
  122. package/dist/esm/node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/chevrons-up-down.js +0 -17
@@ -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;
@@ -0,0 +1,347 @@
1
+ "use strict";
2
+ "use client";
3
+ 'use strict';
4
+
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+ var react = require('react');
7
+ var date = require('@internationalized/date');
8
+ var reactAria = require('react-aria');
9
+ var reactAriaComponents = require('react-aria-components');
10
+ var ouiTheme = require('@opengovsg/oui-theme');
11
+ var button = require('../button/button.cjs');
12
+ var calendarStyleContext = require('./calendar-style-context.cjs');
13
+ var utils = require('./utils.cjs');
14
+ var chevronRight = require('../node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/chevron-right.cjs');
15
+ var chevronLeft = require('../node_modules/.pnpm/lucide-react@0.475.0_react@19.0.0/node_modules/lucide-react/dist/esm/icons/chevron-left.cjs');
16
+ var select = require('../select/select.cjs');
17
+ var selectItem = require('../select/select-item.cjs');
18
+
19
+ const useCalendarSelectors = (state) => {
20
+ const yearRange = react.useMemo(() => {
21
+ const start = state.minValue.year ?? 1900;
22
+ const end = state.maxValue.year ?? 2100;
23
+ return { start, end };
24
+ }, [state.maxValue, state.minValue]);
25
+ const dateFormatter = reactAria.useDateFormatter(state);
26
+ const datePartOrder = react.useMemo(() => {
27
+ const parts = dateFormatter.formatToParts(
28
+ state.visibleRange.start.toDate(state.timeZone)
29
+ );
30
+ const filteredParts = parts.filter(
31
+ (part) => ["year", "month"].includes(part.type)
32
+ );
33
+ const filteredPartNames = filteredParts.map((part) => part.type);
34
+ return filteredPartNames;
35
+ }, [dateFormatter, state.timeZone, state.visibleRange.start]);
36
+ const months = utils.useGenerateLocalizedMonths(state.timeZone);
37
+ const years = utils.useGenerateLocalizedYears(
38
+ yearRange.start,
39
+ yearRange.end,
40
+ state.timeZone
41
+ );
42
+ return react.useMemo(() => {
43
+ return {
44
+ months,
45
+ years,
46
+ datePartOrder
47
+ };
48
+ }, [datePartOrder, months, years]);
49
+ };
50
+ const i18nStrings = {
51
+ "en-SG": {
52
+ selectMonth: "Select month",
53
+ selectYear: "Select year",
54
+ today: "Today"
55
+ },
56
+ "zh-SG": {
57
+ selectMonth: "\u9009\u62E9\u6708\u4EFD",
58
+ selectYear: "\u9009\u62E9\u5E74\u4EFD",
59
+ today: "\u4ECA\u5929"
60
+ },
61
+ "ms-SG": {
62
+ selectMonth: "Pilih bulan",
63
+ selectYear: "Pilih tahun",
64
+ today: "Hari ini"
65
+ },
66
+ "ta-SG": {
67
+ selectMonth: "\u0BAE\u0BBE\u0BA4\u0BA4\u0BCD\u0BA4\u0BC8 \u0BA4\u0BC7\u0BB0\u0BCD\u0BA8\u0BCD\u0BA4\u0BC6\u0B9F\u0BC1\u0B95\u0BCD\u0B95\u0BB5\u0BC1\u0BAE\u0BCD",
68
+ selectYear: "\u0B86\u0BA3\u0BCD\u0B9F\u0BC8 \u0BA4\u0BC7\u0BB0\u0BCD\u0BA8\u0BCD\u0BA4\u0BC6\u0B9F\u0BC1\u0B95\u0BCD\u0B95\u0BB5\u0BC1\u0BAE\u0BCD",
69
+ today: "\u0B87\u0BA9\u0BCD\u0BB1\u0BC1"
70
+ }
71
+ };
72
+ const CalendarBottomContent = ({
73
+ bottomContent,
74
+ showTodayButton
75
+ }) => {
76
+ const state = react.useContext(reactAriaComponents.CalendarStateContext);
77
+ const { slots, classNames, size } = calendarStyleContext.useCalendarStyleContext();
78
+ const formatMessage = reactAria.useMessageFormatter(i18nStrings);
79
+ if (bottomContent) {
80
+ return bottomContent;
81
+ }
82
+ if (!showTodayButton) {
83
+ return null;
84
+ }
85
+ return /* @__PURE__ */ jsxRuntime.jsx(
86
+ "div",
87
+ {
88
+ className: slots.bottomContentWrapper({
89
+ className: classNames?.bottomContentWrapper
90
+ }),
91
+ children: /* @__PURE__ */ jsxRuntime.jsx(
92
+ button.Button,
93
+ {
94
+ isDisabled: state.isDisabled,
95
+ variant: "clear",
96
+ color: "sub",
97
+ size,
98
+ slot: null,
99
+ className: slots.todayButton({ className: classNames?.todayButton }),
100
+ onPress: () => {
101
+ state.setFocusedDate(date.today(date.getLocalTimeZone()));
102
+ },
103
+ children: formatMessage("today")
104
+ }
105
+ )
106
+ }
107
+ );
108
+ };
109
+ function CalendarBase({
110
+ weekdayStyle = "narrow",
111
+ calendarRef,
112
+ minValue = new date.CalendarDate(1900, 0, 1),
113
+ maxValue = new date.CalendarDate(2100, 12, 31),
114
+ bottomContent,
115
+ showTodayButton = true,
116
+ ...props
117
+ }) {
118
+ const { slots, className, classNames } = calendarStyleContext.useCalendarStyleContext();
119
+ const numberOfVisibleMonths = props.visibleDuration?.months ?? 1;
120
+ const dateToHighlight = react.useMemo(() => {
121
+ return props.defaultFocusedValue ?? date.today(date.getLocalTimeZone());
122
+ }, [props.defaultFocusedValue]);
123
+ return /* @__PURE__ */ jsxRuntime.jsxs(
124
+ reactAriaComponents.Calendar,
125
+ {
126
+ pageBehavior: "single",
127
+ ...props,
128
+ ref: calendarRef,
129
+ minValue,
130
+ maxValue,
131
+ className: reactAriaComponents.composeRenderProps(
132
+ className,
133
+ (className2, renderProps) => slots.base({
134
+ className: ouiTheme.cn(classNames?.base, className2),
135
+ ...renderProps
136
+ })
137
+ ),
138
+ children: [
139
+ /* @__PURE__ */ jsxRuntime.jsx(
140
+ "div",
141
+ {
142
+ className: slots.gridWrapper({
143
+ className: classNames?.gridWrapper
144
+ }),
145
+ children: Array.from({ length: numberOfVisibleMonths }).map((_, index) => /* @__PURE__ */ jsxRuntime.jsxs(
146
+ "div",
147
+ {
148
+ className: slots.calendar({ className: classNames?.calendar }),
149
+ children: [
150
+ /* @__PURE__ */ jsxRuntime.jsx(CalendarHeader, { offsetMonths: index }),
151
+ /* @__PURE__ */ jsxRuntime.jsxs(
152
+ reactAriaComponents.CalendarGrid,
153
+ {
154
+ className: slots.grid({ className: classNames?.grid }),
155
+ weekdayStyle,
156
+ offset: { months: index },
157
+ children: [
158
+ /* @__PURE__ */ jsxRuntime.jsx(CalendarGridHeader, {}),
159
+ /* @__PURE__ */ jsxRuntime.jsx(
160
+ reactAriaComponents.CalendarGridBody,
161
+ {
162
+ className: slots.gridBody({ className: classNames?.gridBody }),
163
+ children: (date) => /* @__PURE__ */ jsxRuntime.jsx(
164
+ reactAriaComponents.CalendarCell,
165
+ {
166
+ className: reactAriaComponents.composeRenderProps(
167
+ classNames?.cell,
168
+ (className2, renderProps) => slots.cell({
169
+ className: className2,
170
+ isMultipleMonths: numberOfVisibleMonths >= 2,
171
+ isDateHighlighted: date.compare(dateToHighlight) === 0,
172
+ ...renderProps
173
+ })
174
+ ),
175
+ date
176
+ }
177
+ )
178
+ }
179
+ )
180
+ ]
181
+ }
182
+ )
183
+ ]
184
+ },
185
+ index
186
+ ))
187
+ }
188
+ ),
189
+ /* @__PURE__ */ jsxRuntime.jsx(
190
+ CalendarBottomContent,
191
+ {
192
+ bottomContent,
193
+ showTodayButton
194
+ }
195
+ )
196
+ ]
197
+ }
198
+ );
199
+ }
200
+ const CalendarMonthDaySelector = () => {
201
+ const { slots, size, classNames } = calendarStyleContext.useCalendarStyleContext();
202
+ const state = react.useContext(reactAriaComponents.CalendarStateContext);
203
+ const { months, years, datePartOrder } = useCalendarSelectors(state);
204
+ const formatMessage = reactAria.useMessageFormatter(i18nStrings);
205
+ return /* @__PURE__ */ jsxRuntime.jsx(reactAriaComponents.Group, { className: slots.selectors({ className: classNames?.selectors }), children: datePartOrder.map((part) => {
206
+ if (part === "month") {
207
+ return /* @__PURE__ */ jsxRuntime.jsx(
208
+ select.Select,
209
+ {
210
+ isDisabled: state.isDisabled,
211
+ size,
212
+ items: months,
213
+ variant: "clear",
214
+ classNames: {
215
+ trigger: slots.monthSelector({
216
+ className: classNames?.monthSelector
217
+ }),
218
+ list: slots.monthList({ className: classNames?.monthList }),
219
+ selectedText: slots.selectorText({
220
+ className: classNames?.selectorText
221
+ }),
222
+ popover: "min-w-[12ch]"
223
+ },
224
+ selectedKey: state.visibleRange.start.month,
225
+ "aria-label": formatMessage("selectMonth"),
226
+ onSelectionChange: (month) => {
227
+ state.setFocusedDate(
228
+ new date.CalendarDate(state.focusedDate.year, Number(month), 1)
229
+ );
230
+ },
231
+ children: (month) => /* @__PURE__ */ jsxRuntime.jsx(selectItem.SelectItem, { children: month.textValue })
232
+ },
233
+ part
234
+ );
235
+ }
236
+ return /* @__PURE__ */ jsxRuntime.jsx(
237
+ select.Select,
238
+ {
239
+ isDisabled: state.isDisabled,
240
+ size,
241
+ variant: "clear",
242
+ items: years,
243
+ classNames: {
244
+ trigger: slots.yearSelector({
245
+ className: classNames?.yearSelector
246
+ }),
247
+ list: slots.yearList({ className: classNames?.yearList }),
248
+ selectedText: slots.selectorText({
249
+ className: classNames?.selectorText
250
+ })
251
+ },
252
+ selectedKey: state.visibleRange.start.year,
253
+ "aria-label": formatMessage("selectYear"),
254
+ onSelectionChange: (year) => {
255
+ state.setFocusedDate(
256
+ new date.CalendarDate(
257
+ Number(year),
258
+ state.focusedDate.month,
259
+ state.focusedDate.day
260
+ )
261
+ );
262
+ },
263
+ children: (year) => /* @__PURE__ */ jsxRuntime.jsx(selectItem.SelectItem, { children: year.textValue })
264
+ },
265
+ part
266
+ );
267
+ }) });
268
+ };
269
+ function CalendarHeader({ offsetMonths = 0 }) {
270
+ const { direction } = reactAriaComponents.useLocale();
271
+ const { slots, classNames, size } = calendarStyleContext.useCalendarStyleContext();
272
+ const state = react.useContext(reactAriaComponents.CalendarStateContext);
273
+ const monthYearTitle = utils.useLocalizedMonthYear(
274
+ state.visibleRange.start.add({ months: offsetMonths }),
275
+ state.timeZone
276
+ );
277
+ if (offsetMonths === 0) {
278
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: slots.header({ className: classNames?.header }), children: [
279
+ /* @__PURE__ */ jsxRuntime.jsx(CalendarMonthDaySelector, {}),
280
+ /* @__PURE__ */ jsxRuntime.jsxs(
281
+ reactAriaComponents.Group,
282
+ {
283
+ className: slots.buttonGroup({ className: classNames?.buttonGroup }),
284
+ children: [
285
+ /* @__PURE__ */ jsxRuntime.jsx(
286
+ button.Button,
287
+ {
288
+ size,
289
+ isIconOnly: true,
290
+ variant: "clear",
291
+ color: "sub",
292
+ slot: "previous",
293
+ className: slots.prevButton({ className: classNames?.prevButton }),
294
+ children: direction === "rtl" ? /* @__PURE__ */ jsxRuntime.jsx(chevronRight.default, { "aria-hidden": true }) : /* @__PURE__ */ jsxRuntime.jsx(chevronLeft.default, { "aria-hidden": true })
295
+ }
296
+ ),
297
+ /* @__PURE__ */ jsxRuntime.jsx(
298
+ button.Button,
299
+ {
300
+ size,
301
+ variant: "clear",
302
+ color: "sub",
303
+ isIconOnly: true,
304
+ slot: "next",
305
+ className: slots.nextButton({
306
+ className: classNames?.nextButton
307
+ }),
308
+ children: direction === "rtl" ? /* @__PURE__ */ jsxRuntime.jsx(chevronLeft.default, { "aria-hidden": true }) : /* @__PURE__ */ jsxRuntime.jsx(chevronRight.default, { "aria-hidden": true })
309
+ }
310
+ )
311
+ ]
312
+ }
313
+ )
314
+ ] });
315
+ }
316
+ return /* @__PURE__ */ jsxRuntime.jsx(
317
+ reactAriaComponents.Heading,
318
+ {
319
+ className: slots.header({ className: classNames?.header }),
320
+ "aria-hidden": true,
321
+ level: 2,
322
+ children: monthYearTitle
323
+ }
324
+ );
325
+ }
326
+ function CalendarGridHeader() {
327
+ const { slots, classNames } = calendarStyleContext.useCalendarStyleContext();
328
+ return /* @__PURE__ */ jsxRuntime.jsx(
329
+ reactAriaComponents.CalendarGridHeader,
330
+ {
331
+ className: slots.gridHeader({ className: classNames?.gridHeader }),
332
+ children: (day) => /* @__PURE__ */ jsxRuntime.jsx(
333
+ reactAriaComponents.CalendarHeaderCell,
334
+ {
335
+ className: slots.gridHeaderCell({
336
+ className: classNames?.gridHeaderCell
337
+ }),
338
+ children: day
339
+ }
340
+ )
341
+ }
342
+ );
343
+ }
344
+
345
+ exports.CalendarBase = CalendarBase;
346
+ exports.CalendarGridHeader = CalendarGridHeader;
347
+ exports.CalendarHeader = CalendarHeader;
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ "use client";
3
+ 'use strict';
4
+
5
+ var useDeepCompare = require('use-deep-compare');
6
+ var ouiTheme = require('@opengovsg/oui-theme');
7
+ var utils = require('../system/utils.cjs');
8
+ var context = require('../system/react-utils/context.cjs');
9
+
10
+ function useProvideCalendarStyles(originalProps) {
11
+ const [props, variantProps] = utils.mapPropsVariants(
12
+ originalProps,
13
+ ouiTheme.calendarStyles.variantKeys
14
+ );
15
+ const { errorMessage, className, classNames, ...restProps } = props;
16
+ const slots = useDeepCompare.useDeepCompareMemo(
17
+ () => ouiTheme.calendarStyles(variantProps),
18
+ [variantProps]
19
+ );
20
+ return {
21
+ context: {
22
+ slots,
23
+ classNames,
24
+ className,
25
+ size: variantProps.size ?? ouiTheme.calendarStyles.defaultVariants.size,
26
+ errorMessage
27
+ },
28
+ calendarProps: { ...restProps, onChange: restProps.onChange }
29
+ };
30
+ }
31
+ const [CalendarStyleContext, useCalendarStyleContext] = context.createContext({
32
+ name: "CalendarStyleContext",
33
+ strict: true
34
+ });
35
+
36
+ exports.CalendarStyleContext = CalendarStyleContext;
37
+ exports.useCalendarStyleContext = useCalendarStyleContext;
38
+ exports.useProvideCalendarStyles = useProvideCalendarStyles;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ "use client";
3
+ 'use strict';
4
+
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+ var reactAriaComponents = require('react-aria-components');
7
+ var utils = require('../system/utils.cjs');
8
+ var calendarBase = require('./calendar-base.cjs');
9
+ var calendarStyleContext = require('./calendar-style-context.cjs');
10
+
11
+ const Calendar = utils.forwardRef(function Calendar2(props, ref) {
12
+ const { calendarProps, context } = calendarStyleContext.useProvideCalendarStyles(props);
13
+ return /* @__PURE__ */ jsxRuntime.jsx(reactAriaComponents.Provider, { values: [[calendarStyleContext.CalendarStyleContext, context]], children: /* @__PURE__ */ jsxRuntime.jsx(calendarBase.CalendarBase, { calendarRef: ref, ...calendarProps }) });
14
+ });
15
+
16
+ exports.Calendar = Calendar;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ 'use strict';
3
+
4
+ var calendar = require('./calendar.cjs');
5
+ var calendarStyleContext = require('./calendar-style-context.cjs');
6
+ var utils = require('./utils.cjs');
7
+ var date = require('@internationalized/date');
8
+
9
+
10
+
11
+ exports.Calendar = calendar.Calendar;
12
+ exports.CalendarStyleContext = calendarStyleContext.CalendarStyleContext;
13
+ exports.useCalendarStyleContext = calendarStyleContext.useCalendarStyleContext;
14
+ exports.useProvideCalendarStyles = calendarStyleContext.useProvideCalendarStyles;
15
+ exports.getEraFormat = utils.getEraFormat;
16
+ exports.useGenerateLocalizedMonths = utils.useGenerateLocalizedMonths;
17
+ exports.useGenerateLocalizedYears = utils.useGenerateLocalizedYears;
18
+ exports.useLocalizedMonthYear = utils.useLocalizedMonthYear;
19
+ Object.defineProperty(exports, "CalendarDate", {
20
+ enumerable: true,
21
+ get: function () { return date.CalendarDate; }
22
+ });
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ 'use strict';
3
+
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ 'use strict';
3
+
4
+ var react = require('react');
5
+ var date = require('@internationalized/date');
6
+ var i18n = require('@react-aria/i18n');
7
+
8
+ function getEraFormat(date) {
9
+ return date?.calendar.identifier === "gregory" && date.era === "BC" ? "short" : void 0;
10
+ }
11
+ function useLocalizedMonthYear(date, timeZone) {
12
+ const era = getEraFormat(date);
13
+ const monthFormatter = i18n.useDateFormatter({
14
+ month: "long",
15
+ year: "numeric",
16
+ era,
17
+ calendar: date.calendar.identifier,
18
+ timeZone
19
+ });
20
+ return monthFormatter.format(date.toDate(timeZone));
21
+ }
22
+ function useGenerateLocalizedMonths(timeZone, formatterOptions) {
23
+ const formatter = i18n.useDateFormatter({
24
+ month: "long",
25
+ timeZone,
26
+ ...formatterOptions
27
+ });
28
+ return react.useMemo(() => {
29
+ return Array.from({ length: 12 }, (_, i) => {
30
+ const id = i + 1;
31
+ return {
32
+ id,
33
+ textValue: formatter.format(
34
+ new date.CalendarDate(2020, id, 1).toDate(timeZone)
35
+ )
36
+ };
37
+ });
38
+ }, [formatter, timeZone]);
39
+ }
40
+ function useGenerateLocalizedYears(yearStart, yearEnd, timeZone, formatterOptions) {
41
+ const formatter = i18n.useDateFormatter({
42
+ year: "numeric",
43
+ timeZone,
44
+ ...formatterOptions
45
+ });
46
+ return react.useMemo(() => {
47
+ return Array.from({ length: yearEnd - yearStart + 1 }, (_, i) => {
48
+ const year = yearStart + i;
49
+ return {
50
+ id: year,
51
+ textValue: formatter.format(
52
+ new date.CalendarDate(year, 1, 1).toDate(timeZone)
53
+ )
54
+ };
55
+ });
56
+ }, [formatter, yearStart, yearEnd, timeZone]);
57
+ }
58
+
59
+ exports.getEraFormat = getEraFormat;
60
+ exports.useGenerateLocalizedMonths = useGenerateLocalizedMonths;
61
+ exports.useGenerateLocalizedYears = useGenerateLocalizedYears;
62
+ exports.useLocalizedMonthYear = useLocalizedMonthYear;