@majoo-ui/react 2.1.3 → 2.2.1

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.
@@ -36,6 +36,9 @@ import { ConditionalWrapper } from '../../../../wrapper/ConditionalWrapper.esm.j
36
36
  import OptionGroupItem from './OptionGroupItem.esm.js';
37
37
  import { useMountedLayoutEffect } from 'react-table';
38
38
  import { useVirtual } from 'react-virtual';
39
+ import { useFloating, autoUpdate } from '@floating-ui/react';
40
+ import { Portal } from '@majoo-ui/helpers';
41
+ import { createPopoverMiddleware } from '../../../popover/middleware.esm.js';
39
42
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
40
43
 
41
44
  const startTransition = React__default.startTransition || (callback => {
@@ -223,34 +226,23 @@ const TagWrapper = styled(Box, {
223
226
  margin: '10px 0',
224
227
  gap: '5px'
225
228
  });
229
+
230
+ // Positioned by floating-ui (see `useFloating` below) and portalled, so it is
231
+ // neither clipped by an `overflow: hidden` ancestor nor pushed off the viewport.
232
+ // Its children stay in-flow: floating-ui measures this element to decide flips.
226
233
  const OptionWrapper = styled('div', {
227
234
  display: 'none',
228
235
  overflow: 'hidden',
229
- zIndex: 12,
236
+ zIndex: '$tooltip',
237
+ pointerEvents: 'auto',
230
238
  borderRadius: '$sm',
231
239
  backgroundColor: '$bgWhite',
232
240
  boxShadow: '0px 2px 12px #00000014',
233
- width: '100%',
234
- // height: '160px',
235
- position: 'absolute',
236
- float: 'left',
237
- // top: '40px',
238
- left: '0px',
241
+ width: 'var(--majoo-popover-reference-width, 100%)',
239
242
  color: '$textPrimary',
240
- variants: {
241
- placement: {
242
- bottom: {
243
- top: '100%',
244
- left: '0',
245
- transform: 'none'
246
- },
247
- top: {
248
- top: '0',
249
- left: '0',
250
- transform: 'translate(0, -100%)'
251
- }
252
- }
253
- }
243
+ fontFamily: 'inherit',
244
+ fontSize: '$short-content-regular',
245
+ textAlign: 'left'
254
246
  });
255
247
  const Option = styled('div', {
256
248
  flexDirection: 'column',
@@ -258,7 +250,7 @@ const Option = styled('div', {
258
250
  borderRadius: '$lg',
259
251
  overflowY: 'auto',
260
252
  padding: '8px 16px',
261
- maxHeight: '160px',
253
+ maxHeight: 'min(160px, var(--majoo-popover-available-height, 160px))',
262
254
  height: 'auto',
263
255
  '@sm': {
264
256
  borderRadius: 'unset'
@@ -815,6 +807,20 @@ const InputSelectCheck = /*#__PURE__*/forwardRef(({
815
807
  }
816
808
  }
817
809
  });
810
+
811
+ // downshift owns open/close and outside-click; floating-ui only positions the
812
+ // menu. The floating ref is attached only while the menu is shown, so a closed
813
+ // select does not keep autoUpdate's scroll/resize listeners alive.
814
+ // `placement` is a preference: the menu flips when that side lacks room.
815
+ const isMenuShown = isOpen && disabled === false;
816
+ const floating = useFloating({
817
+ open: isMenuShown,
818
+ placement,
819
+ whileElementsMounted: autoUpdate,
820
+ middleware: createPopoverMiddleware({
821
+ sideOffset: 4
822
+ })
823
+ });
818
824
  const memoOptions = useMemo(() => {
819
825
  // Skip expensive operations for very large datasets
820
826
  const isVeryLarge = option?.length > 10000;
@@ -1019,6 +1025,7 @@ const InputSelectCheck = /*#__PURE__*/forwardRef(({
1019
1025
  mobileOnly: mobileOnly,
1020
1026
  desktopOnly: desktopOnly,
1021
1027
  children: [/*#__PURE__*/jsxs(Select, {
1028
+ ref: floating.refs.setReference,
1022
1029
  size: size,
1023
1030
  disabled: disabled || readOnly,
1024
1031
  isInvalid: isInvalid,
@@ -1162,152 +1169,153 @@ const InputSelectCheck = /*#__PURE__*/forwardRef(({
1162
1169
  },
1163
1170
  color: "brand",
1164
1171
  children: `${totalOptions ? totalOptions : selectedItems?.filter(item => item?.id !== '!all')?.length} ${labelCounter || t('labelCounterText', 'Item terpilih')}`
1165
- }), /*#__PURE__*/jsxs(OptionWrapper, {
1166
- placement: placement,
1167
- css: {
1168
- display: isOpen && disabled === false ? 'block' : 'none',
1169
- top: size === 'lg' ? '45px' : '35px',
1170
- minHeight: isLoading ? 40 : 0
1171
- },
1172
- children: [isLoading && /*#__PURE__*/jsx(Flex, {
1173
- justify: "center",
1174
- align: "center",
1172
+ }), /*#__PURE__*/jsx(Portal, {
1173
+ children: /*#__PURE__*/jsxs(OptionWrapper, {
1174
+ ref: isMenuShown ? floating.refs.setFloating : null,
1175
+ style: {
1176
+ position: floating.strategy,
1177
+ top: floating.y ?? 0,
1178
+ left: floating.x ?? 0
1179
+ },
1175
1180
  css: {
1176
- position: 'absolute',
1177
- inset: 0,
1178
- zIndex: '$tooltip',
1179
- top: items.length > 0 ? '0px' : placement === 'top' ? '-20px' : '0px',
1180
- // bottom: '80px',
1181
- width: '100%',
1182
- minHeight: 40,
1183
- height: scrollerRef.current ? scrollerRef.current.clientHeight : '40px',
1184
- backgroundColor: '$bgWhite',
1185
- opacity: 0.8,
1186
- transform: placement === 'top' ? 'translate(0, -100%)' : 'none'
1181
+ display: isMenuShown ? 'block' : 'none',
1182
+ minHeight: isLoading ? 40 : 0
1187
1183
  },
1188
- children: /*#__PURE__*/jsx(Text, {
1189
- variant: "caption",
1190
- children: "Loading...."
1191
- })
1192
- }), items.length > 0 || isLoading ? /*#__PURE__*/jsx(Option, {
1193
- ...getMenuProps({
1194
- ref: scrollerRef
1195
- }, {
1196
- suppressRefError: true
1197
- }),
1198
- css: optionListCss,
1199
- children: /*#__PURE__*/jsx(ConditionalWrapper, {
1200
- condition: !!fetchData && items.length > 0,
1201
- wrapper: child => /*#__PURE__*/jsx(InfiniteScroll, {
1202
- loadMore: () => {
1203
- if (!isLoading) {
1204
- if (scrollerRef.current) {
1205
- scrollerRef.current.scrollBy(0, -5);
1184
+ children: [isLoading && /*#__PURE__*/jsx(Flex, {
1185
+ justify: "center",
1186
+ align: "center",
1187
+ css: {
1188
+ position: 'absolute',
1189
+ inset: 0,
1190
+ zIndex: '$tooltip',
1191
+ minHeight: 40,
1192
+ backgroundColor: '$bgWhite',
1193
+ opacity: 0.8
1194
+ },
1195
+ children: /*#__PURE__*/jsx(Text, {
1196
+ variant: "caption",
1197
+ children: "Loading...."
1198
+ })
1199
+ }), items.length > 0 || isLoading ? /*#__PURE__*/jsx(Option, {
1200
+ ...getMenuProps({
1201
+ ref: scrollerRef
1202
+ }, {
1203
+ suppressRefError: true
1204
+ }),
1205
+ css: optionListCss,
1206
+ children: /*#__PURE__*/jsx(ConditionalWrapper, {
1207
+ condition: !!fetchData && items.length > 0,
1208
+ wrapper: child => /*#__PURE__*/jsx(InfiniteScroll, {
1209
+ loadMore: () => {
1210
+ if (!isLoading) {
1211
+ if (scrollerRef.current) {
1212
+ scrollerRef.current.scrollBy(0, -5);
1213
+ }
1214
+ fetchData?.({
1215
+ query
1216
+ });
1206
1217
  }
1207
- fetchData?.({
1208
- query
1209
- });
1210
- }
1211
- },
1212
- hasMore: true,
1213
- threshold: 0,
1214
- useWindow: false,
1215
- children: child
1216
- }, isLoading),
1217
- children: isOpen && shouldVirtualize ?
1218
- /*#__PURE__*/
1219
- // Virtualized rendering for large lists
1220
- jsx(Fragment, {
1221
- children: /*#__PURE__*/jsx("div", {
1222
- style: {
1223
- height: `${rowVirtualizer.totalSize}px`,
1224
- position: 'relative',
1225
- width: '100%'
1226
1218
  },
1227
- children: rowVirtualizer.virtualItems.map(virtualRow => {
1228
- const virtualItem = getItemAtIndex(virtualRow.index);
1229
- if (!virtualItem) return null;
1230
- const {
1231
- type,
1232
- item
1233
- } = virtualItem;
1234
- return /*#__PURE__*/jsx("div", {
1235
- style: {
1236
- position: 'absolute',
1237
- top: 0,
1238
- left: 0,
1239
- width: '100%',
1240
- transform: `translateY(${virtualRow.start}px)`
1241
- },
1242
- children: type === 'group' ?
1243
- /*#__PURE__*/
1244
- // Render option group header (without children, as they're rendered separately)
1245
- jsxs(ItemWrapper, {
1246
- ...getItemProps({
1247
- item,
1248
- index: virtualRow.index,
1249
- disabled: item.isDisabled
1250
- }),
1251
- css: {
1252
- backgroundColor: highlightedIndex === virtualRow.index ? '$bgGray' : '$bgWhite',
1253
- cursor: item.isDisabled ? 'not-allowed' : 'pointer',
1254
- color: item.isDisabled ? '$textDisable' : 'textPrimary',
1255
- fontWeight: 600
1219
+ hasMore: true,
1220
+ threshold: 0,
1221
+ useWindow: false,
1222
+ children: child
1223
+ }, isLoading),
1224
+ children: isOpen && shouldVirtualize ?
1225
+ /*#__PURE__*/
1226
+ // Virtualized rendering for large lists
1227
+ jsx(Fragment, {
1228
+ children: /*#__PURE__*/jsx("div", {
1229
+ style: {
1230
+ height: `${rowVirtualizer.totalSize}px`,
1231
+ position: 'relative',
1232
+ width: '100%'
1233
+ },
1234
+ children: rowVirtualizer.virtualItems.map(virtualRow => {
1235
+ const virtualItem = getItemAtIndex(virtualRow.index);
1236
+ if (!virtualItem) return null;
1237
+ const {
1238
+ type,
1239
+ item
1240
+ } = virtualItem;
1241
+ return /*#__PURE__*/jsx("div", {
1242
+ style: {
1243
+ position: 'absolute',
1244
+ top: 0,
1245
+ left: 0,
1246
+ width: '100%',
1247
+ transform: `translateY(${virtualRow.start}px)`
1256
1248
  },
1257
- children: [/*#__PURE__*/jsx(IconWrapper, {
1249
+ children: type === 'group' ?
1250
+ /*#__PURE__*/
1251
+ // Render option group header (without children, as they're rendered separately)
1252
+ jsxs(ItemWrapper, {
1253
+ ...getItemProps({
1254
+ item,
1255
+ index: virtualRow.index,
1256
+ disabled: item.isDisabled
1257
+ }),
1258
1258
  css: {
1259
- width: '16px',
1260
- height: '16px',
1261
- border: '1px solid $bgBorder',
1259
+ backgroundColor: highlightedIndex === virtualRow.index ? '$bgGray' : '$bgWhite',
1262
1260
  cursor: item.isDisabled ? 'not-allowed' : 'pointer',
1263
- ...checkBoxCss
1261
+ color: item.isDisabled ? '$textDisable' : 'textPrimary',
1262
+ fontWeight: 600
1264
1263
  },
1265
- children: !item?.hideCheck && item.isDisabled ? /*#__PURE__*/jsx(CheckOutline, {
1266
- color: colors.iconDisable
1267
- }) : item?.children?.filter(e => selectedValueSet.has(e.id) && !e.isDisabled)?.length === item?.children?.filter(e => !e.isDisabled)?.length ? /*#__PURE__*/jsx(CheckOutline, {
1268
- color: colors.iconBrand
1269
- }) : item?.children?.filter(e => selectedValueSet.has(e.id) && !e.isDisabled)?.length > 0 ? /*#__PURE__*/jsx(IndeterminateFilled, {
1270
- children: "-"
1271
- }) : null
1272
- }), /*#__PURE__*/jsx(Item, {
1273
- css: {
1274
- backgroundColor: 'unset',
1275
- width: '100%'
1276
- },
1277
- children: item.render ? item.render?.(item.name) : item.name
1278
- })]
1279
- }) :
1280
- // Render regular item or child item
1281
- renderOptionItem(item, virtualRow.index, type === 'child')
1282
- }, `${type}-${item.id}-${virtualRow.index}`);
1264
+ children: [/*#__PURE__*/jsx(IconWrapper, {
1265
+ css: {
1266
+ width: '16px',
1267
+ height: '16px',
1268
+ border: '1px solid $bgBorder',
1269
+ cursor: item.isDisabled ? 'not-allowed' : 'pointer',
1270
+ ...checkBoxCss
1271
+ },
1272
+ children: !item?.hideCheck && item.isDisabled ? /*#__PURE__*/jsx(CheckOutline, {
1273
+ color: colors.iconDisable
1274
+ }) : item?.children?.filter(e => selectedValueSet.has(e.id) && !e.isDisabled)?.length === item?.children?.filter(e => !e.isDisabled)?.length ? /*#__PURE__*/jsx(CheckOutline, {
1275
+ color: colors.iconBrand
1276
+ }) : item?.children?.filter(e => selectedValueSet.has(e.id) && !e.isDisabled)?.length > 0 ? /*#__PURE__*/jsx(IndeterminateFilled, {
1277
+ children: "-"
1278
+ }) : null
1279
+ }), /*#__PURE__*/jsx(Item, {
1280
+ css: {
1281
+ backgroundColor: 'unset',
1282
+ width: '100%'
1283
+ },
1284
+ children: item.render ? item.render?.(item.name) : item.name
1285
+ })]
1286
+ }) :
1287
+ // Render regular item or child item
1288
+ renderOptionItem(item, virtualRow.index, type === 'child')
1289
+ }, `${type}-${item.id}-${virtualRow.index}`);
1290
+ })
1283
1291
  })
1284
- })
1285
- }) :
1286
- // Non-virtualized rendering for small lists
1287
- isOpen && items.map((item, index) => item?.children ? renderOptionGroupItem(item) : renderOptionItem(item, index))
1288
- })
1289
- }) : /*#__PURE__*/jsx(Option, {
1290
- css: {
1291
- height: 'auto'
1292
- },
1293
- ...getMenuProps({}, {
1294
- suppressRefError: true
1295
- }),
1296
- children: /*#__PURE__*/jsxs(StyledDiv, {
1297
- children: [/*#__PURE__*/jsx("div", {
1298
- style: {
1299
- marginRight: '6px'
1300
- },
1301
- children: /*#__PURE__*/jsx(CircleInfoOutline, {
1302
- size: "16px",
1303
- color: colors.iconDisable,
1292
+ }) :
1293
+ // Non-virtualized rendering for small lists
1294
+ isOpen && items.map((item, index) => item?.children ? renderOptionGroupItem(item) : renderOptionItem(item, index))
1295
+ })
1296
+ }) : /*#__PURE__*/jsx(Option, {
1297
+ css: {
1298
+ height: 'auto'
1299
+ },
1300
+ ...getMenuProps({}, {
1301
+ suppressRefError: true
1302
+ }),
1303
+ children: /*#__PURE__*/jsxs(StyledDiv, {
1304
+ children: [/*#__PURE__*/jsx("div", {
1304
1305
  style: {
1305
- verticalAlign: 'text-bottom'
1306
- }
1307
- })
1308
- }), textEmptyItem ?? t('emptyItemText', 'Item tidak ditemukan')]
1309
- })
1310
- })]
1306
+ marginRight: '6px'
1307
+ },
1308
+ children: /*#__PURE__*/jsx(CircleInfoOutline, {
1309
+ size: "16px",
1310
+ color: colors.iconDisable,
1311
+ style: {
1312
+ verticalAlign: 'text-bottom'
1313
+ }
1314
+ })
1315
+ }), textEmptyItem ?? t('emptyItemText', 'Item tidak ditemukan')]
1316
+ })
1317
+ })]
1318
+ })
1311
1319
  })]
1312
1320
  });
1313
1321
  });
@@ -34,7 +34,6 @@ function MapPicker(props) {
34
34
  const isDesktop = useMediaQuery('(min-width: 767px)');
35
35
  const {
36
36
  center,
37
- setCenter,
38
37
  places,
39
38
  searchQuery,
40
39
  searchResult,
@@ -49,12 +48,15 @@ function MapPicker(props) {
49
48
  showSelectButton,
50
49
  onChange
51
50
  });
51
+ // Keyed on the coordinates, not the object: a parent re-rendering with a new but equal
52
+ // `value` must not pull the map back from where the user dragged it. handleSearchLatLng is
53
+ // left out because it changes with every new `onChange`, which InputMapPicker passes inline.
52
54
  useEffect(() => {
53
55
  if (value && (value === null || value === void 0 ? void 0 : value.lat) && (value === null || value === void 0 ? void 0 : value.lng)) {
54
- setCenter(value);
55
56
  handleSearchLatLng(value);
56
57
  }
57
- }, [value, setCenter]);
58
+ // eslint-disable-next-line react-hooks/exhaustive-deps
59
+ }, [value === null || value === void 0 ? void 0 : value.lat, value === null || value === void 0 ? void 0 : value.lng]);
58
60
  function handleMarkerClick() {
59
61
  if (places.length > 0) {
60
62
  const mapObject = {
@@ -82,7 +82,19 @@ function useMapSearch({
82
82
  }, abortControllerRef.current.signal);
83
83
  // getFullAddress returns null if aborted
84
84
  if (fullAddress) {
85
- handleSelect(fullAddress);
85
+ // Keep the chosen item's coordinates; the reverse geocode only supplies the address.
86
+ const {
87
+ display_name,
88
+ place_id,
89
+ address
90
+ } = fullAddress;
91
+ handleSelect({
92
+ lat: item.lat,
93
+ lon: item.lon,
94
+ display_name,
95
+ place_id,
96
+ address
97
+ });
86
98
  }
87
99
  }), [getFullAddress, handleSelect]);
88
100
  const handleSearchLatLng = useCallback(latLng => __awaiter(this, void 0, void 0, function* () {
@@ -90,19 +102,26 @@ function useMapSearch({
90
102
  // Cancel any previous pending request
91
103
  (_b = abortControllerRef.current) === null || _b === void 0 ? void 0 : _b.abort();
92
104
  abortControllerRef.current = new AbortController();
105
+ // Move the center now, so a re-render while the address loads (or a failed lookup)
106
+ // does not send the map back to the previous point.
107
+ setCenter({
108
+ lat: Number(latLng.lat),
109
+ lng: Number(latLng.lng)
110
+ });
93
111
  const fullAddress = yield getFullAddress(latLng, abortControllerRef.current.signal);
94
112
  // getFullAddress returns null if aborted
95
113
  if (fullAddress) {
114
+ // Nominatim answers with the coordinates of the OSM object it matched (for a large
115
+ // polygon such as a golf course, its centroid), not the point that was asked about.
116
+ // Keep the requested point; the reverse geocode only supplies the address.
96
117
  const {
97
- lat,
98
- lon,
99
118
  display_name,
100
119
  place_id,
101
120
  address
102
121
  } = fullAddress;
103
122
  handleSelect({
104
- lat,
105
- lon,
123
+ lat: String(latLng.lat),
124
+ lon: String(latLng.lng),
106
125
  display_name,
107
126
  place_id,
108
127
  address
@@ -0,0 +1,212 @@
1
+ import 'core-js/modules/es.iterator.constructor.js';
2
+ import 'core-js/modules/es.iterator.map.js';
3
+ import { jsxs, jsx } from 'react/jsx-runtime';
4
+ import React__default, { useState } from 'react';
5
+ import { useTranslation } from 'react-i18next';
6
+ import { CaretDownOutline, ChevronRightOutline } from '@majoo-ui/icons';
7
+ import { styled, colors } from '../../config/stitches.config.esm.js';
8
+ import { weekdayNamesFullEng, weekdayNamesFullId } from '../../utils/calendar.esm.js';
9
+ import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuSub, DropdownMenuSubTrigger, RightSlot, DropdownMenuSubContent, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem } from '../dropdownMenu/DropdownMenu.esm.js';
10
+
11
+ const Trigger = styled('button', {
12
+ all: 'unset',
13
+ boxSizing: 'border-box',
14
+ display: 'inline-flex',
15
+ alignItems: 'center',
16
+ gap: '$spacing-02',
17
+ padding: '0 $spacing-04',
18
+ border: '1px solid $bgOutline',
19
+ borderRadius: '$lg',
20
+ backgroundColor: '$bgWhite',
21
+ color: '$textPrimary',
22
+ fontFamily: 'inherit',
23
+ fontSize: '$short-content-regular',
24
+ lineHeight: '$short-content-regular',
25
+ letterSpacing: '$short-content-regular',
26
+ cursor: 'pointer',
27
+ '&:hover': {
28
+ borderColor: '$primary600'
29
+ },
30
+ '&[data-state="open"]': {
31
+ borderColor: '$primary400'
32
+ },
33
+ variants: {
34
+ size: {
35
+ sm: {
36
+ height: 32
37
+ },
38
+ lg: {
39
+ height: 40
40
+ }
41
+ },
42
+ // Named apart from the DOM attribute so Stitches does not swallow it as a variant —
43
+ // the button still needs a real `disabled` to block the menu from opening.
44
+ isDisabled: {
45
+ true: {
46
+ backgroundColor: '$formDisable',
47
+ color: '$textDisable',
48
+ cursor: 'not-allowed',
49
+ '&:hover': {
50
+ borderColor: '$bgOutline'
51
+ }
52
+ }
53
+ }
54
+ },
55
+ defaultVariants: {
56
+ size: 'lg'
57
+ }
58
+ });
59
+ const TriggerLabel = styled('span', {
60
+ fontWeight: 600
61
+ });
62
+ const TriggerRange = styled('span', {
63
+ color: '$textDisable'
64
+ });
65
+ const MENU_ITEM_CSS = {
66
+ paddingLeft: '$spacing-04',
67
+ paddingRight: '$spacing-04'
68
+ };
69
+ const DEFAULT_PERIODS = ['day', 'week', 'month'];
70
+ // Listed Monday first, the way the week reads in Indonesian — not in Date#getDay order.
71
+ const START_DAY_ORDER = [1, 2, 3, 4, 5, 6, 0];
72
+ const PeriodSelect = /*#__PURE__*/React__default.forwardRef(({
73
+ value,
74
+ onChange,
75
+ startDay,
76
+ onStartDayChange,
77
+ defaultStartDay = 1,
78
+ resetStartDayOnPeriodChange = true,
79
+ periods = DEFAULT_PERIODS,
80
+ showRange = true,
81
+ disabled = false,
82
+ size = 'lg',
83
+ side = 'bottom',
84
+ align = 'start',
85
+ periodLabels,
86
+ startWeekLabel,
87
+ formatWeekRange,
88
+ css
89
+ }, ref) => {
90
+ const {
91
+ t,
92
+ i18n: {
93
+ language
94
+ }
95
+ } = useTranslation(['MajooUI/periodSelect', 'translation']);
96
+ const [open, setOpen] = useState(false);
97
+ const [internalStartDay, setInternalStartDay] = useState(defaultStartDay);
98
+ const activeStartDay = startDay !== null && startDay !== void 0 ? startDay : internalStartDay;
99
+ const weekdayNames = language === 'en' ? weekdayNamesFullEng : weekdayNamesFullId;
100
+ // A week always spans 7 days, so the last one is always 6 days after the first.
101
+ const rangeLabel = (day, place) => {
102
+ const endDay = (day + 6) % 7;
103
+ const range = {
104
+ startDay: day,
105
+ endDay,
106
+ startName: weekdayNames[day],
107
+ endName: weekdayNames[endDay],
108
+ place
109
+ };
110
+ return formatWeekRange ? formatWeekRange(range) : `${range.startName} - ${range.endName}`;
111
+ };
112
+ const showWeekRange = showRange && value === 'week';
113
+ const defaultPeriodLabels = {
114
+ day: t('day', 'Hari'),
115
+ week: t('week', 'Minggu'),
116
+ month: t('month', 'Bulan')
117
+ };
118
+ const periodLabel = period => {
119
+ var _a;
120
+ return (_a = periodLabels === null || periodLabels === void 0 ? void 0 : periodLabels[period]) !== null && _a !== void 0 ? _a : defaultPeriodLabels[period];
121
+ };
122
+ const applyStartDay = day => {
123
+ setInternalStartDay(day);
124
+ onStartDayChange === null || onStartDayChange === void 0 ? void 0 : onStartDayChange(day);
125
+ };
126
+ const selectPeriod = period => {
127
+ onChange(period);
128
+ if (resetStartDayOnPeriodChange && period !== 'week' && activeStartDay !== defaultStartDay) {
129
+ applyStartDay(defaultStartDay);
130
+ }
131
+ setOpen(false);
132
+ };
133
+ const renderPeriodItem = period => {
134
+ if (period !== 'week') {
135
+ return jsx(DropdownMenuItem, {
136
+ selected: value === period,
137
+ onSelect: () => selectPeriod(period),
138
+ css: MENU_ITEM_CSS,
139
+ children: periodLabel(period)
140
+ }, period);
141
+ }
142
+ return jsxs(DropdownMenuSub, {
143
+ children: [jsxs(DropdownMenuSubTrigger, {
144
+ selected: value === 'week',
145
+ onClick: () => selectPeriod('week'),
146
+ css: MENU_ITEM_CSS,
147
+ children: [periodLabel('week'), jsx(RightSlot, {
148
+ children: jsx(ChevronRightOutline, {
149
+ size: "16",
150
+ color: "currentColor"
151
+ })
152
+ })]
153
+ }), jsxs(DropdownMenuSubContent, {
154
+ sideOffset: 8,
155
+ alignOffset: -8,
156
+ css: {
157
+ padding: '$spacing-04 $spacing-05'
158
+ },
159
+ children: [jsx(DropdownMenuLabel, {
160
+ children: startWeekLabel !== null && startWeekLabel !== void 0 ? startWeekLabel : t('startWeekFrom', 'Mulai minggu dari:')
161
+ }), jsx(DropdownMenuRadioGroup, {
162
+ value: String(activeStartDay),
163
+ onValueChange: day => {
164
+ applyStartDay(Number(day));
165
+ onChange('week');
166
+ },
167
+ children: START_DAY_ORDER.map(day => jsx(DropdownMenuRadioItem, {
168
+ value: String(day),
169
+ children: rangeLabel(day, 'option')
170
+ }, day))
171
+ })]
172
+ })]
173
+ }, period);
174
+ };
175
+ return jsxs(DropdownMenu, {
176
+ open: open,
177
+ onOpenChange: setOpen,
178
+ side: side,
179
+ align: align,
180
+ modal: false,
181
+ children: [jsx(DropdownMenuTrigger, {
182
+ asChild: true,
183
+ children: jsxs(Trigger, {
184
+ ref: ref,
185
+ size: size,
186
+ isDisabled: disabled,
187
+ disabled: disabled,
188
+ css: css,
189
+ type: "button",
190
+ children: [jsxs(TriggerLabel, {
191
+ children: [periodLabel(value), showWeekRange && ',']
192
+ }), showWeekRange && jsx(TriggerRange, {
193
+ children: rangeLabel(activeStartDay, 'trigger')
194
+ }), jsx(CaretDownOutline, {
195
+ size: "16",
196
+ color: disabled ? colors.iconDisable : colors.iconPrimary
197
+ })]
198
+ })
199
+ }), jsx(DropdownMenuContent, {
200
+ sideOffset: 4,
201
+ css: {
202
+ width: 'max-content',
203
+ minWidth: 160,
204
+ maxWidth: 'none'
205
+ },
206
+ children: periods.map(renderPeriodItem)
207
+ })]
208
+ });
209
+ });
210
+ PeriodSelect.displayName = 'PeriodSelect';
211
+
212
+ export { PeriodSelect as default };