@opengovsg/oui 0.0.29 → 0.0.30
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.
- package/dist/cjs/banner/banner.cjs +1 -1
- package/dist/cjs/checkbox/checkbox.cjs +1 -1
- package/dist/cjs/combo-box/combo-box.cjs +1 -1
- package/dist/cjs/date-field/date-field.cjs +1 -1
- package/dist/cjs/date-picker/date-picker.cjs +5 -4
- package/dist/cjs/date-range-picker/date-range-picker.cjs +3 -3
- package/dist/cjs/file-dropzone/file-dropzone.cjs +12 -8
- package/dist/cjs/file-dropzone/file-info.cjs +3 -2
- package/dist/cjs/file-dropzone/utils.cjs +4 -4
- package/dist/cjs/hooks/use-scroll-position.cjs +53 -0
- package/dist/cjs/index.cjs +51 -51
- package/dist/cjs/modal/modal-content.cjs +1 -1
- package/dist/cjs/navbar/navbar-menu/menu.cjs +2 -2
- package/dist/cjs/navbar/navbar-menu/toggle.cjs +3 -2
- package/dist/cjs/navbar/navbar.cjs +25 -1
- package/dist/cjs/navbar/use-navbar.cjs +42 -32
- package/dist/cjs/number-field/number-field.cjs +2 -2
- package/dist/cjs/range-calendar/range-calendar.cjs +1 -1
- package/dist/cjs/select/select.cjs +2 -2
- package/dist/cjs/tag-field/tag-field.cjs +1 -1
- package/dist/cjs/text-area-field/text-area-field.cjs +1 -1
- package/dist/cjs/text-field/text-field.cjs +1 -1
- package/dist/esm/banner/banner.js +1 -1
- package/dist/esm/checkbox/checkbox.js +1 -1
- package/dist/esm/combo-box/combo-box.js +1 -1
- package/dist/esm/date-field/date-field.js +1 -1
- package/dist/esm/date-picker/date-picker.js +5 -4
- package/dist/esm/date-range-picker/date-range-picker.js +3 -3
- package/dist/esm/file-dropzone/file-dropzone.js +12 -8
- package/dist/esm/file-dropzone/file-info.js +3 -2
- package/dist/esm/file-dropzone/utils.js +4 -4
- package/dist/esm/hooks/use-scroll-position.js +51 -0
- package/dist/esm/index.js +17 -17
- package/dist/esm/modal/modal-content.js +1 -1
- package/dist/esm/navbar/navbar-menu/menu.js +2 -2
- package/dist/esm/navbar/navbar-menu/toggle.js +3 -2
- package/dist/esm/navbar/navbar.js +26 -2
- package/dist/esm/navbar/use-navbar.js +43 -33
- package/dist/esm/number-field/number-field.js +2 -2
- package/dist/esm/range-calendar/range-calendar.js +1 -1
- package/dist/esm/select/select.js +2 -2
- package/dist/esm/tag-field/tag-field.js +1 -1
- package/dist/esm/text-area-field/text-area-field.js +1 -1
- package/dist/esm/text-field/text-field.js +1 -1
- package/dist/types/calendar/calendar.d.ts.map +1 -1
- package/dist/types/date-field/date-field.d.ts.map +1 -1
- package/dist/types/file-dropzone/file-dropzone.d.ts +8 -2
- package/dist/types/file-dropzone/file-dropzone.d.ts.map +1 -1
- package/dist/types/file-dropzone/file-info.d.ts.map +1 -1
- package/dist/types/file-dropzone/types.d.ts +1 -0
- package/dist/types/file-dropzone/types.d.ts.map +1 -1
- package/dist/types/file-dropzone/utils.d.ts +2 -1
- package/dist/types/file-dropzone/utils.d.ts.map +1 -1
- package/dist/types/hooks/use-scroll-position.d.ts +29 -0
- package/dist/types/hooks/use-scroll-position.d.ts.map +1 -0
- package/dist/types/menu/menu.d.ts.map +1 -1
- package/dist/types/navbar/navbar-context.d.ts +10 -2
- package/dist/types/navbar/navbar-context.d.ts.map +1 -1
- package/dist/types/navbar/navbar-menu/menu.d.ts.map +1 -1
- package/dist/types/navbar/navbar-menu/toggle.d.ts.map +1 -1
- package/dist/types/navbar/navbar.d.ts.map +1 -1
- package/dist/types/navbar/use-navbar.d.ts +33 -1
- package/dist/types/navbar/use-navbar.d.ts.map +1 -1
- package/dist/types/range-calendar/range-calendar.d.ts.map +1 -1
- package/dist/types/system/utils.d.ts.map +1 -1
- package/dist/types/tabs/tabs.d.ts.map +1 -1
- package/dist/types/tag-field/tag-field-item.d.ts.map +1 -1
- package/dist/types/tag-field/tag-field-list.d.ts.map +1 -1
- package/package.json +3 -3
|
@@ -6,24 +6,30 @@ var $670gB$react = require('react');
|
|
|
6
6
|
var usePreventScroll = require('../node_modules/.pnpm/@react-aria_overlays@3.30.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@react-aria/overlays/dist/usePreventScroll.cjs');
|
|
7
7
|
var utils$2 = require('@react-aria/utils');
|
|
8
8
|
var utils$1 = require('@react-stately/utils');
|
|
9
|
-
var useDeepCompare = require('use-deep-compare');
|
|
10
9
|
var ouiTheme = require('@opengovsg/oui-theme');
|
|
10
|
+
var useScrollPosition = require('../hooks/use-scroll-position.cjs');
|
|
11
11
|
var utils = require('../system/utils.cjs');
|
|
12
12
|
var refs = require('../system/react-utils/refs.cjs');
|
|
13
13
|
|
|
14
|
+
const NAVBAR_PRESENCE_BUFFER = 10;
|
|
14
15
|
function useNavbar(originalProps) {
|
|
15
16
|
const [
|
|
16
17
|
{
|
|
17
18
|
ref,
|
|
18
19
|
as,
|
|
20
|
+
parentRef,
|
|
19
21
|
height = "4rem",
|
|
20
22
|
shouldBlockScroll = true,
|
|
23
|
+
shouldShowOnScrollUp = false,
|
|
24
|
+
disableScrollHandler = false,
|
|
25
|
+
onScrollPositionChange,
|
|
21
26
|
isMenuOpen: isMenuOpenProp,
|
|
22
27
|
isMenuDefaultOpen,
|
|
23
28
|
onMenuOpenChange = () => {
|
|
24
29
|
},
|
|
25
30
|
className,
|
|
26
31
|
classNames,
|
|
32
|
+
motionProps,
|
|
27
33
|
...otherProps
|
|
28
34
|
},
|
|
29
35
|
variantProps
|
|
@@ -31,62 +37,62 @@ function useNavbar(originalProps) {
|
|
|
31
37
|
const Component = as || "nav";
|
|
32
38
|
const domRef = refs.useDomRef(ref);
|
|
33
39
|
const menuRef = $670gB$react.useRef(null);
|
|
34
|
-
const prevWidth = $670gB$react.useRef(0);
|
|
35
|
-
const navHeight = $670gB$react.useRef(0);
|
|
36
40
|
const handleMenuOpenChange = $670gB$react.useCallback(
|
|
37
41
|
(isOpen) => {
|
|
38
42
|
onMenuOpenChange(isOpen || false);
|
|
39
43
|
},
|
|
40
44
|
[onMenuOpenChange]
|
|
41
45
|
);
|
|
46
|
+
const [menuTopOffset, setMenuOffset] = $670gB$react.useState(0);
|
|
47
|
+
const [isNavbarHidden, setIsNavbarHidden] = $670gB$react.useState(false);
|
|
42
48
|
const [isMenuOpen, setIsMenuOpen] = utils$1.useControlledState(
|
|
43
49
|
isMenuOpenProp,
|
|
44
50
|
isMenuDefaultOpen ?? false,
|
|
45
51
|
handleMenuOpenChange
|
|
46
52
|
);
|
|
47
|
-
const updateWidth = $670gB$react.useCallback(() => {
|
|
48
|
-
if (domRef.current) {
|
|
49
|
-
const width = domRef.current.offsetWidth;
|
|
50
|
-
if (width !== prevWidth.current) {
|
|
51
|
-
prevWidth.current = width;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}, [domRef]);
|
|
55
53
|
usePreventScroll.usePreventScroll({
|
|
56
54
|
isDisabled: !(shouldBlockScroll && isMenuOpen)
|
|
57
55
|
});
|
|
58
56
|
utils$2.useResizeObserver({
|
|
59
57
|
ref: domRef,
|
|
60
58
|
onResize: () => {
|
|
61
|
-
|
|
62
|
-
const scrollWidth = window.innerWidth - document.documentElement.clientWidth;
|
|
63
|
-
if (currentWidth && currentWidth + scrollWidth == prevWidth.current) {
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
if (currentWidth !== prevWidth.current) {
|
|
67
|
-
updateWidth();
|
|
68
|
-
setIsMenuOpen(false);
|
|
69
|
-
}
|
|
59
|
+
setMenuOffset(domRef.current?.getBoundingClientRect().top || 0);
|
|
70
60
|
}
|
|
71
61
|
});
|
|
62
|
+
const truePosition = variantProps.position ?? "sticky";
|
|
63
|
+
const positionVariantProp = shouldShowOnScrollUp ? "sticky" : truePosition;
|
|
64
|
+
const slots = ouiTheme.navbarStyles({
|
|
65
|
+
...variantProps,
|
|
66
|
+
position: positionVariantProp
|
|
67
|
+
});
|
|
68
|
+
const baseStyles = ouiTheme.cn(classNames?.base, className);
|
|
69
|
+
const navHeight = $670gB$react.useRef(0);
|
|
72
70
|
$670gB$react.useEffect(() => {
|
|
73
|
-
updateWidth();
|
|
74
71
|
navHeight.current = domRef.current?.offsetHeight || 0;
|
|
75
|
-
}, [domRef
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
72
|
+
}, [domRef]);
|
|
73
|
+
useScrollPosition.useScrollPosition({
|
|
74
|
+
elementRef: parentRef,
|
|
75
|
+
isEnabled: shouldShowOnScrollUp || !disableScrollHandler,
|
|
76
|
+
callback: ({ prevPos, currPos }) => {
|
|
77
|
+
onScrollPositionChange?.(currPos.y);
|
|
78
|
+
if (shouldShowOnScrollUp) {
|
|
79
|
+
setIsNavbarHidden((prev) => {
|
|
80
|
+
const next = currPos.y > prevPos.y + NAVBAR_PRESENCE_BUFFER && currPos.y > navHeight.current;
|
|
81
|
+
return next !== prev ? next : prev;
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
const heightPx = typeof height === "number" ? `${height}px` : height;
|
|
87
|
+
const menuTopOffsetPx = `calc(${heightPx} + ${menuTopOffset}px)`;
|
|
83
88
|
const getBaseProps = (props = {}) => ({
|
|
84
89
|
...utils$2.mergeProps(otherProps, props),
|
|
90
|
+
"data-hidden": ouiTheme.dataAttr(isNavbarHidden),
|
|
85
91
|
"data-menu-open": ouiTheme.dataAttr(isMenuOpen),
|
|
86
92
|
ref: domRef,
|
|
87
93
|
className: slots.base({ class: ouiTheme.cn(baseStyles, props?.className) }),
|
|
88
94
|
style: {
|
|
89
|
-
"--navbar-height":
|
|
95
|
+
"--navbar-height": heightPx,
|
|
90
96
|
...otherProps?.style,
|
|
91
97
|
...props?.style
|
|
92
98
|
}
|
|
@@ -102,14 +108,18 @@ function useNavbar(originalProps) {
|
|
|
102
108
|
Component,
|
|
103
109
|
slots,
|
|
104
110
|
domRef,
|
|
105
|
-
|
|
111
|
+
menuTopOffset,
|
|
112
|
+
menuTopOffsetPx,
|
|
113
|
+
isNavbarHidden,
|
|
114
|
+
shouldShowOnScrollUp: shouldShowOnScrollUp && truePosition === "static",
|
|
106
115
|
isMenuOpen,
|
|
107
116
|
classNames,
|
|
108
117
|
setIsMenuOpen,
|
|
109
118
|
menuRef,
|
|
110
119
|
getBaseProps,
|
|
111
120
|
getWrapperProps,
|
|
112
|
-
position:
|
|
121
|
+
position: positionVariantProp,
|
|
122
|
+
motionProps
|
|
113
123
|
};
|
|
114
124
|
}
|
|
115
125
|
|
|
@@ -5,12 +5,12 @@
|
|
|
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 button = require('../button/button.cjs');
|
|
9
|
+
var field = require('../field/field.cjs');
|
|
8
10
|
var input = require('../input/input.cjs');
|
|
9
11
|
var utils = require('../system/utils.cjs');
|
|
10
12
|
var minus = require('../node_modules/.pnpm/lucide-react@0.475.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/minus.cjs');
|
|
11
13
|
var plus = require('../node_modules/.pnpm/lucide-react@0.475.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/plus.cjs');
|
|
12
|
-
var field = require('../field/field.cjs');
|
|
13
|
-
var button = require('../button/button.cjs');
|
|
14
14
|
|
|
15
15
|
function NumberField(originalProps) {
|
|
16
16
|
const [
|
|
@@ -8,12 +8,12 @@ var date = require('@internationalized/date');
|
|
|
8
8
|
var reactAriaComponents = require('react-aria-components');
|
|
9
9
|
var useDeepCompare = require('use-deep-compare');
|
|
10
10
|
var ouiTheme = require('@opengovsg/oui-theme');
|
|
11
|
+
var calendarStyleContext = require('../calendar/calendar-style-context.cjs');
|
|
11
12
|
var agnosticCalendarStateContext = require('../calendar/agnostic-calendar-state-context.cjs');
|
|
12
13
|
var calendarBottomContent = require('../calendar/calendar-bottom-content.cjs');
|
|
13
14
|
var calendarGridHeader = require('../calendar/calendar-grid-header.cjs');
|
|
14
15
|
var calendarHeader = require('../calendar/calendar-header.cjs');
|
|
15
16
|
var utils = require('../system/utils.cjs');
|
|
16
|
-
var calendarStyleContext = require('../calendar/calendar-style-context.cjs');
|
|
17
17
|
|
|
18
18
|
const RangeCalendar = utils.forwardRefGeneric(function RangeCalendar2(originalProps, ref) {
|
|
19
19
|
const [props, variantProps] = utils.mapPropsVariants(
|
|
@@ -6,12 +6,12 @@ var jsxRuntime = require('react/jsx-runtime');
|
|
|
6
6
|
var $670gB$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');
|
|
9
11
|
var popover = require('../popover/popover.cjs');
|
|
10
12
|
var utils = require('../system/utils.cjs');
|
|
11
13
|
var selectVariantContext = require('./select-variant-context.cjs');
|
|
12
|
-
var field = require('../field/field.cjs');
|
|
13
14
|
var chevronDown = require('../node_modules/.pnpm/lucide-react@0.475.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/chevron-down.cjs');
|
|
14
|
-
var button = require('../button/button.cjs');
|
|
15
15
|
|
|
16
16
|
const calculateEstimatedRowHeight = (size) => {
|
|
17
17
|
switch (size) {
|
|
@@ -6,6 +6,7 @@ var jsxRuntime = require('react/jsx-runtime');
|
|
|
6
6
|
var $670gB$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');
|
|
9
10
|
var input = require('../input/input.cjs');
|
|
10
11
|
var popover = require('../popover/popover.cjs');
|
|
11
12
|
var tagFieldItem = require('./tag-field-item.cjs');
|
|
@@ -14,7 +15,6 @@ var tagFieldRoot = require('./tag-field-root.cjs');
|
|
|
14
15
|
var tagFieldTagList = require('./tag-field-tag-list.cjs');
|
|
15
16
|
var tagFieldTrigger = require('./tag-field-trigger.cjs');
|
|
16
17
|
var chevronDown = require('../node_modules/.pnpm/lucide-react@0.475.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/chevron-down.cjs');
|
|
17
|
-
var field = require('../field/field.cjs');
|
|
18
18
|
|
|
19
19
|
function TagField({
|
|
20
20
|
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 textArea = require('../text-area/text-area.cjs');
|
|
9
8
|
var field = require('../field/field.cjs');
|
|
9
|
+
var textArea = require('../text-area/text-area.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 input = require('../input/input.cjs');
|
|
9
8
|
var field = require('../field/field.cjs');
|
|
9
|
+
var input = require('../input/input.cjs');
|
|
10
10
|
|
|
11
11
|
function TextField({
|
|
12
12
|
label,
|
|
@@ -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';
|
|
8
9
|
import CircleAlert from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/circle-alert.js';
|
|
9
10
|
import Info from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.2.3/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.2.3/node_modules/lucide-react/dist/esm/icons/x.js';
|
|
12
12
|
|
|
13
13
|
const i18nStrings = {
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
4
|
import { Checkbox as Checkbox$1, composeRenderProps, Provider, CheckboxGroup as CheckboxGroup$1 } from 'react-aria-components';
|
|
5
5
|
import { checkboxStyles, checkboxGroupStyles } from '@opengovsg/oui-theme';
|
|
6
|
+
import { Label, Description, FieldError } from '../field/field.js';
|
|
6
7
|
import { mapPropsVariants } from '../system/utils.js';
|
|
7
8
|
import { useCheckboxGroupStyleContext, CheckboxGroupStyleContext } from './checkbox-group-style-context.js';
|
|
8
9
|
import Minus from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/minus.js';
|
|
9
10
|
import Check from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/check.js';
|
|
10
|
-
import { Label, Description, FieldError } from '../field/field.js';
|
|
11
11
|
|
|
12
12
|
const Checkbox = ({
|
|
13
13
|
classNames,
|
|
@@ -5,10 +5,10 @@ import { useMemo, useCallback } from 'react';
|
|
|
5
5
|
import { useMessageFormatter } from 'react-aria';
|
|
6
6
|
import { ListLayout, Provider, ComboBox as ComboBox$1, Input, Button, Virtualizer, ListBox } from 'react-aria-components';
|
|
7
7
|
import { listBoxItemStyles, cn, comboBoxStyles, composeTailwindRenderProps, composeRenderProps, comboBoxClearButtonStyles } from '@opengovsg/oui-theme';
|
|
8
|
+
import { Label, FieldGroup, Description, FieldError } from '../field/field.js';
|
|
8
9
|
import { Popover } from '../popover/popover.js';
|
|
9
10
|
import { mapPropsVariants } from '../system/utils.js';
|
|
10
11
|
import { ComboBoxVariantContext } from './combo-box-variant-context.js';
|
|
11
|
-
import { Label, FieldGroup, Description, FieldError } from '../field/field.js';
|
|
12
12
|
import ChevronUp from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/chevron-up.js';
|
|
13
13
|
import ChevronDown from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/chevron-down.js';
|
|
14
14
|
import X from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/x.js';
|
|
@@ -4,8 +4,8 @@ import { jsxs, jsx } from 'react/jsx-runtime';
|
|
|
4
4
|
import { useMemo } from 'react';
|
|
5
5
|
import { DateField as DateField$1, DateInput as DateInput$1, DateSegment } from 'react-aria-components';
|
|
6
6
|
import { dateFieldStyles, composeTailwindRenderProps, dateInputStyles, composeRenderProps } from '@opengovsg/oui-theme';
|
|
7
|
-
import { mapPropsVariants } from '../system/utils.js';
|
|
8
7
|
import { Label, Description, FieldError } from '../field/field.js';
|
|
8
|
+
import { mapPropsVariants } from '../system/utils.js';
|
|
9
9
|
|
|
10
10
|
function DateField(originalProps) {
|
|
11
11
|
const [
|
|
@@ -4,13 +4,14 @@ import { jsxs, jsx } from 'react/jsx-runtime';
|
|
|
4
4
|
import { useMemo } from 'react';
|
|
5
5
|
import { DatePicker as DatePicker$1, Dialog } from 'react-aria-components';
|
|
6
6
|
import { datePickerStyles, composeTailwindRenderProps } from '@opengovsg/oui-theme';
|
|
7
|
+
import { Button } from '../button/button.js';
|
|
8
|
+
import { Calendar as Calendar$1 } from '../calendar/calendar.js';
|
|
9
|
+
import '@internationalized/date';
|
|
10
|
+
import { DateInput } from '../date-field/date-field.js';
|
|
11
|
+
import { Label, FieldGroup, Description, FieldError } from '../field/field.js';
|
|
7
12
|
import { Popover } from '../popover/popover.js';
|
|
8
13
|
import { mapPropsVariants } from '../system/utils.js';
|
|
9
|
-
import { DateInput } from '../date-field/date-field.js';
|
|
10
14
|
import Calendar from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/calendar.js';
|
|
11
|
-
import { Calendar as Calendar$1 } from '../calendar/calendar.js';
|
|
12
|
-
import { Label, FieldGroup, Description, FieldError } from '../field/field.js';
|
|
13
|
-
import { Button } from '../button/button.js';
|
|
14
15
|
|
|
15
16
|
function DatePicker(originalProps) {
|
|
16
17
|
const [
|
|
@@ -5,13 +5,13 @@ import { useMemo } from 'react';
|
|
|
5
5
|
import { CalendarDate } from '@internationalized/date';
|
|
6
6
|
import { DateRangePicker as DateRangePicker$1, Dialog } from 'react-aria-components';
|
|
7
7
|
import { dateRangePickerStyles, composeTailwindRenderProps } from '@opengovsg/oui-theme';
|
|
8
|
+
import { Button } from '../button/button.js';
|
|
9
|
+
import { DateInput } from '../date-field/date-field.js';
|
|
10
|
+
import { Label, FieldGroup, Description, FieldError } from '../field/field.js';
|
|
8
11
|
import { Popover } from '../popover/popover.js';
|
|
9
12
|
import { RangeCalendar } from '../range-calendar/range-calendar.js';
|
|
10
13
|
import { mapPropsVariants } from '../system/utils.js';
|
|
11
14
|
import Calendar from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/calendar.js';
|
|
12
|
-
import { Label, FieldGroup, Description, FieldError } from '../field/field.js';
|
|
13
|
-
import { DateInput } from '../date-field/date-field.js';
|
|
14
|
-
import { Button } from '../button/button.js';
|
|
15
15
|
|
|
16
16
|
function DateRangePicker(originalProps) {
|
|
17
17
|
const [
|
|
@@ -7,13 +7,13 @@ import { useField, useId } from 'react-aria';
|
|
|
7
7
|
import { Provider, LabelContext, GroupContext, TextContext, FieldErrorContext, Group } from 'react-aria-components';
|
|
8
8
|
import { useDropzone } from 'react-dropzone';
|
|
9
9
|
import { fileDropzoneStyles, dataAttr } from '@opengovsg/oui-theme';
|
|
10
|
+
import { Label, Description, FieldError } from '../field/field.js';
|
|
10
11
|
import { useControllableState } from '../hooks/use-controllable-state.js';
|
|
11
12
|
import { mapPropsVariants } from '../system/utils.js';
|
|
12
13
|
import { FileDropzoneStyleContext, FileDropzoneStateContext, useFileDropzoneStateContext, useFileDropzoneStyleContext } from './contexts.js';
|
|
13
14
|
import { FileInfo } from './file-info.js';
|
|
14
15
|
import { formatErrorMessage, formatBytes } from './utils.js';
|
|
15
16
|
import Upload from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/upload.js';
|
|
16
|
-
import { Label, Description, FieldError } from '../field/field.js';
|
|
17
17
|
|
|
18
18
|
const FileDropzone = (originalProps) => {
|
|
19
19
|
const [props, variantProps] = mapPropsVariants(
|
|
@@ -23,6 +23,7 @@ const FileDropzone = (originalProps) => {
|
|
|
23
23
|
const {
|
|
24
24
|
name,
|
|
25
25
|
allowedMimeTypes = [],
|
|
26
|
+
fileSizeBase = "binary",
|
|
26
27
|
maxFileSize = Number.POSITIVE_INFINITY,
|
|
27
28
|
minFileSize = 0,
|
|
28
29
|
showFileSizeText = true,
|
|
@@ -67,9 +68,10 @@ const FileDropzone = (originalProps) => {
|
|
|
67
68
|
(error) => formatErrorMessage(error, {
|
|
68
69
|
maxFileSize,
|
|
69
70
|
minFileSize,
|
|
70
|
-
maxFiles
|
|
71
|
+
maxFiles,
|
|
72
|
+
fileSizeBase
|
|
71
73
|
}),
|
|
72
|
-
[maxFileSize, maxFiles, minFileSize]
|
|
74
|
+
[fileSizeBase, maxFileSize, maxFiles, minFileSize]
|
|
73
75
|
);
|
|
74
76
|
const onDrop = useCallback(
|
|
75
77
|
(acceptedFiles, fileRejections) => {
|
|
@@ -127,19 +129,20 @@ const FileDropzone = (originalProps) => {
|
|
|
127
129
|
const shouldShow = showFileSizeText && (notDefaultMaxFileSize || notDefaultMinFileSize);
|
|
128
130
|
if (!shouldShow) return null;
|
|
129
131
|
if (notDefaultMaxFileSize && notDefaultMinFileSize) {
|
|
130
|
-
return `File size must be between ${formatBytes(minFileSize, 2)} and ${formatBytes(
|
|
132
|
+
return `File size must be between ${formatBytes(minFileSize, 2, fileSizeBase)} and ${formatBytes(
|
|
131
133
|
maxFileSize,
|
|
132
|
-
2
|
|
134
|
+
2,
|
|
135
|
+
fileSizeBase
|
|
133
136
|
)}`;
|
|
134
137
|
}
|
|
135
138
|
if (notDefaultMaxFileSize) {
|
|
136
|
-
return `Maximum file size: ${formatBytes(maxFileSize, 2)}`;
|
|
139
|
+
return `Maximum file size: ${formatBytes(maxFileSize, 2, fileSizeBase)}`;
|
|
137
140
|
}
|
|
138
141
|
if (notDefaultMinFileSize) {
|
|
139
|
-
return `Minimum file size: ${formatBytes(minFileSize, 2)}`;
|
|
142
|
+
return `Minimum file size: ${formatBytes(minFileSize, 2, fileSizeBase)}`;
|
|
140
143
|
}
|
|
141
144
|
return null;
|
|
142
|
-
}, [maxFileSize, minFileSize, showFileSizeText]);
|
|
145
|
+
}, [maxFileSize, minFileSize, showFileSizeText, fileSizeBase]);
|
|
143
146
|
const triggerFileSelector = useCallback(() => {
|
|
144
147
|
if (isDisabled || isReadOnly) return;
|
|
145
148
|
dropzoneState.inputRef.current?.click();
|
|
@@ -185,6 +188,7 @@ const FileDropzone = (originalProps) => {
|
|
|
185
188
|
{
|
|
186
189
|
isDisabled,
|
|
187
190
|
isReadOnly,
|
|
191
|
+
fileSizeBase,
|
|
188
192
|
maxFiles,
|
|
189
193
|
maxFileSize,
|
|
190
194
|
showDropzone,
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
4
|
import { useState, useEffect } from 'react';
|
|
5
5
|
import { fileInfoDropzoneStyles, cn } from '@opengovsg/oui-theme';
|
|
6
|
+
import { Button } from '../button/button.js';
|
|
6
7
|
import { useFileDropzoneStateContext, useFileDropzoneStyleContext } from './contexts.js';
|
|
7
8
|
import { formatBytes } from './utils.js';
|
|
8
9
|
import Trash2 from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/trash-2.js';
|
|
9
|
-
import { Button } from '../button/button.js';
|
|
10
10
|
|
|
11
11
|
const FileInfo = ({ file, imagePreview, classNames }) => {
|
|
12
12
|
const {
|
|
@@ -17,7 +17,8 @@ const FileInfo = ({ file, imagePreview, classNames }) => {
|
|
|
17
17
|
isReadOnly
|
|
18
18
|
} = useFileDropzoneStateContext();
|
|
19
19
|
const { size, variant, itemClassNames } = useFileDropzoneStyleContext();
|
|
20
|
-
const
|
|
20
|
+
const { fileSizeBase } = useFileDropzoneStateContext();
|
|
21
|
+
const readableFileSize = formatBytes(file.size, 2, fileSizeBase);
|
|
21
22
|
const styles = fileInfoDropzoneStyles({
|
|
22
23
|
size,
|
|
23
24
|
variant,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
import { ErrorCode } from 'react-dropzone';
|
|
3
3
|
|
|
4
|
-
const formatBytes = (bytes, decimals = 2, size) => {
|
|
5
|
-
const k = 1e3;
|
|
4
|
+
const formatBytes = (bytes, decimals = 2, base = "binary", size) => {
|
|
5
|
+
const k = base === "binary" ? 1024 : 1e3;
|
|
6
6
|
const dm = decimals < 0 ? 0 : decimals;
|
|
7
7
|
const sizes = ["bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
|
8
8
|
if (bytes === 0 || bytes === void 0)
|
|
@@ -14,9 +14,9 @@ const formatErrorMessage = (error, config) => {
|
|
|
14
14
|
const { maxFileSize, minFileSize, maxFiles } = config;
|
|
15
15
|
switch (error.code) {
|
|
16
16
|
case ErrorCode.FileTooLarge:
|
|
17
|
-
return `You have exceeded the size limit, please upload a file below ${formatBytes(maxFileSize, 2)}`;
|
|
17
|
+
return `You have exceeded the size limit, please upload a file below ${formatBytes(maxFileSize, 2, config.fileSizeBase)}`;
|
|
18
18
|
case ErrorCode.FileTooSmall:
|
|
19
|
-
return `Please upload a file above ${formatBytes(minFileSize, 2)}`;
|
|
19
|
+
return `Please upload a file above ${formatBytes(minFileSize, 2, config.fileSizeBase)}`;
|
|
20
20
|
case ErrorCode.TooManyFiles:
|
|
21
21
|
return `Maximum number of files allowed is ${maxFiles}.`;
|
|
22
22
|
default: {
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
import { useRef, useCallback, useEffect } from 'react';
|
|
3
|
+
|
|
4
|
+
const isBrowser = typeof window !== "undefined";
|
|
5
|
+
function getScrollPosition(element) {
|
|
6
|
+
if (!isBrowser) return { x: 0, y: 0 };
|
|
7
|
+
if (!element) {
|
|
8
|
+
return { x: window.scrollX, y: window.scrollY };
|
|
9
|
+
}
|
|
10
|
+
return { x: element.scrollLeft, y: element.scrollTop };
|
|
11
|
+
}
|
|
12
|
+
const useScrollPosition = (props) => {
|
|
13
|
+
const { elementRef, delay = 30, callback, isEnabled } = props;
|
|
14
|
+
const position = useRef(
|
|
15
|
+
isEnabled ? getScrollPosition(elementRef?.current) : { x: 0, y: 0 }
|
|
16
|
+
);
|
|
17
|
+
const throttleTimeout = useRef(null);
|
|
18
|
+
const handler = useCallback(() => {
|
|
19
|
+
const currPos = getScrollPosition(elementRef?.current);
|
|
20
|
+
if (typeof callback === "function") {
|
|
21
|
+
callback({ prevPos: position.current, currPos });
|
|
22
|
+
}
|
|
23
|
+
position.current = currPos;
|
|
24
|
+
throttleTimeout.current = null;
|
|
25
|
+
}, [callback, elementRef]);
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
if (!isEnabled) return;
|
|
28
|
+
const handleScroll = () => {
|
|
29
|
+
if (delay) {
|
|
30
|
+
if (throttleTimeout.current) {
|
|
31
|
+
clearTimeout(throttleTimeout.current);
|
|
32
|
+
}
|
|
33
|
+
throttleTimeout.current = setTimeout(handler, delay);
|
|
34
|
+
} else {
|
|
35
|
+
handler();
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
const target = elementRef?.current || window;
|
|
39
|
+
target.addEventListener("scroll", handleScroll);
|
|
40
|
+
return () => {
|
|
41
|
+
target.removeEventListener("scroll", handleScroll);
|
|
42
|
+
if (throttleTimeout.current) {
|
|
43
|
+
clearTimeout(throttleTimeout.current);
|
|
44
|
+
throttleTimeout.current = null;
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}, [elementRef?.current, delay, handler, isEnabled]);
|
|
48
|
+
return position.current;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export { useScrollPosition };
|
package/dist/esm/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
export { useControllableState } from './hooks/use-controllable-state.js';
|
|
3
3
|
export { useDraggable } from './hooks/use-draggable.js';
|
|
4
|
+
export { Button } from './button/button.js';
|
|
4
5
|
export { GovtBanner } from './govt-banner/govt-banner.js';
|
|
5
6
|
export { Ripple } from './ripple/ripple.js';
|
|
6
7
|
export { useRipple } from './ripple/use-ripple.js';
|
|
@@ -10,17 +11,33 @@ export { Toggle } from './toggle/toggle.js';
|
|
|
10
11
|
export { SkipNavLink } from './skip-nav-link/skip-nav-link.js';
|
|
11
12
|
export { Input } from './input/input.js';
|
|
12
13
|
export { TextField } from './text-field/text-field.js';
|
|
14
|
+
export { Description, FieldError, FieldErrorIcon, FieldGroup, Label } from './field/field.js';
|
|
13
15
|
export { TextArea } from './text-area/text-area.js';
|
|
14
16
|
export { TextAreaField } from './text-area-field/text-area-field.js';
|
|
17
|
+
export { ComboBox, ComboBoxEmptyState } from './combo-box/combo-box.js';
|
|
18
|
+
export { ComboBoxFuzzy } from './combo-box/combo-box-fuzzy.js';
|
|
19
|
+
export { ComboBoxItem } from './combo-box/combo-box-item.js';
|
|
20
|
+
export { ComboBoxVariantContext, useComboBoxVariantContext } from './combo-box/combo-box-variant-context.js';
|
|
21
|
+
export { Banner } from './banner/banner.js';
|
|
15
22
|
export { TagField } from './tag-field/tag-field.js';
|
|
16
23
|
export { TagFieldItem } from './tag-field/tag-field-item.js';
|
|
17
24
|
export { Select } from './select/select.js';
|
|
18
25
|
export { SelectItem } from './select/select-item.js';
|
|
19
26
|
export { SelectVariantContext, useSelectVariantContext } from './select/select-variant-context.js';
|
|
27
|
+
export { Badge } from './badge/badge.js';
|
|
28
|
+
export { Calendar, CalendarStateWrapper } from './calendar/calendar.js';
|
|
29
|
+
export { CalendarStyleContext, useCalendarStyleContext } from './calendar/calendar-style-context.js';
|
|
30
|
+
export { getEraFormat, useGenerateLocalizedMonths, useGenerateLocalizedYears, useLocalizedMonthYear } from './calendar/utils.js';
|
|
31
|
+
export { CalendarDate } from '@internationalized/date';
|
|
20
32
|
export { RangeCalendar, RangeCalendarCell, RangeCalendarStateWrapper } from './range-calendar/range-calendar.js';
|
|
21
33
|
export { Menu, MenuItem, MenuSection, MenuSeparator, MenuTrigger, MenuVariantContext, SubmenuTrigger, useMenuVariantContext } from './menu/menu.js';
|
|
22
34
|
export { Popover } from './popover/popover.js';
|
|
23
35
|
export { Tab, TabList, TabPanel, Tabs, TabsVariantContext, useTabsVariantContext } from './tabs/tabs.js';
|
|
36
|
+
export { DateField, DateInput } from './date-field/date-field.js';
|
|
37
|
+
export { DatePicker } from './date-picker/date-picker.js';
|
|
38
|
+
export { DateRangePicker } from './date-range-picker/date-range-picker.js';
|
|
39
|
+
export { Checkbox, CheckboxGroup } from './checkbox/checkbox.js';
|
|
40
|
+
export { CheckboxGroupStyleContext, useCheckboxGroupStyleContext } from './checkbox/checkbox-group-style-context.js';
|
|
24
41
|
export { Pagination } from './pagination/pagination.js';
|
|
25
42
|
export { PaginationCursor } from './pagination/pagination-cursor.js';
|
|
26
43
|
export { PaginationItem } from './pagination/pagination-item.js';
|
|
@@ -46,21 +63,4 @@ export { NavbarMenuToggle } from './navbar/navbar-menu/toggle.js';
|
|
|
46
63
|
export { NavbarItem } from './navbar/navbar-item.js';
|
|
47
64
|
export { useNavbar } from './navbar/use-navbar.js';
|
|
48
65
|
export { NavbarProvider, useNavbarContext } from './navbar/navbar-context.js';
|
|
49
|
-
export { Button } from './button/button.js';
|
|
50
|
-
export { Description, FieldError, FieldErrorIcon, FieldGroup, Label } from './field/field.js';
|
|
51
|
-
export { ComboBox, ComboBoxEmptyState } from './combo-box/combo-box.js';
|
|
52
|
-
export { ComboBoxFuzzy } from './combo-box/combo-box-fuzzy.js';
|
|
53
|
-
export { ComboBoxItem } from './combo-box/combo-box-item.js';
|
|
54
|
-
export { ComboBoxVariantContext, useComboBoxVariantContext } from './combo-box/combo-box-variant-context.js';
|
|
55
|
-
export { Banner } from './banner/banner.js';
|
|
56
|
-
export { Badge } from './badge/badge.js';
|
|
57
|
-
export { CalendarDate } from '@internationalized/date';
|
|
58
|
-
export { Calendar, CalendarStateWrapper } from './calendar/calendar.js';
|
|
59
|
-
export { CalendarStyleContext, useCalendarStyleContext } from './calendar/calendar-style-context.js';
|
|
60
|
-
export { getEraFormat, useGenerateLocalizedMonths, useGenerateLocalizedYears, useLocalizedMonthYear } from './calendar/utils.js';
|
|
61
|
-
export { DateField, DateInput } from './date-field/date-field.js';
|
|
62
|
-
export { DatePicker } from './date-picker/date-picker.js';
|
|
63
|
-
export { DateRangePicker } from './date-range-picker/date-range-picker.js';
|
|
64
|
-
export { Checkbox, CheckboxGroup } from './checkbox/checkbox.js';
|
|
65
|
-
export { CheckboxGroupStyleContext, useCheckboxGroupStyleContext } from './checkbox/checkbox-group-style-context.js';
|
|
66
66
|
export { toast } from 'sonner';
|
|
@@ -5,10 +5,10 @@ import { useContext, isValidElement } from 'react';
|
|
|
5
5
|
import { useMessageFormatter } from 'react-aria';
|
|
6
6
|
import { Dialog } from 'react-aria-components';
|
|
7
7
|
import { cn } from '@opengovsg/oui-theme';
|
|
8
|
+
import { Button } from '../button/button.js';
|
|
8
9
|
import { i18nStrings } from './i18n.js';
|
|
9
10
|
import { ModalVariantContext } from './modal-variant-context.js';
|
|
10
11
|
import X from '../node_modules/.pnpm/lucide-react@0.475.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/x.js';
|
|
11
|
-
import { Button } from '../button/button.js';
|
|
12
12
|
|
|
13
13
|
function ModalContent({
|
|
14
14
|
closeButtonContent: closeButtonContentProp,
|
|
@@ -14,7 +14,7 @@ const NavbarMenu = forwardRef(
|
|
|
14
14
|
const {
|
|
15
15
|
slots,
|
|
16
16
|
isMenuOpen,
|
|
17
|
-
|
|
17
|
+
menuTopOffsetPx,
|
|
18
18
|
classNames,
|
|
19
19
|
setIsMenuOpen,
|
|
20
20
|
domRef: parentRef,
|
|
@@ -44,7 +44,7 @@ const NavbarMenu = forwardRef(
|
|
|
44
44
|
style: {
|
|
45
45
|
...style,
|
|
46
46
|
// @ts-expect-error due to not having any type declaration for CSS variables in React style prop
|
|
47
|
-
"--
|
|
47
|
+
"--menu-offset": menuTopOffsetPx
|
|
48
48
|
},
|
|
49
49
|
onKeyDown: chain(handleKeyDown, onKeyDown),
|
|
50
50
|
...props,
|
|
@@ -24,13 +24,14 @@ const NavbarMenuToggle = ({
|
|
|
24
24
|
isMenuOpen,
|
|
25
25
|
setIsMenuOpen,
|
|
26
26
|
menuRef,
|
|
27
|
-
position
|
|
27
|
+
position,
|
|
28
|
+
menuTopOffset
|
|
28
29
|
} = useNavbarContext();
|
|
29
30
|
const shouldScrollToTop = (isMenuOpen2) => {
|
|
30
31
|
if (!isMenuOpen2 || position === "sticky" || typeof window === "undefined") {
|
|
31
32
|
return;
|
|
32
33
|
}
|
|
33
|
-
window.scrollTo({ top:
|
|
34
|
+
window.scrollTo({ top: menuTopOffset, behavior: "instant" });
|
|
34
35
|
};
|
|
35
36
|
const formatMessage = useMessageFormatter(i18nStrings);
|
|
36
37
|
const toggleStyles = useMemo(() => {
|
|
@@ -1,13 +1,28 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
"use client";
|
|
3
3
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
4
|
-
import {
|
|
4
|
+
import { LazyMotion, domAnimation, m } from 'motion/react';
|
|
5
|
+
import { FocusScope, mergeProps } from 'react-aria';
|
|
5
6
|
import { pickChildren } from '../system/react-utils/children.js';
|
|
6
7
|
import { forwardRef } from '../system/utils.js';
|
|
7
8
|
import { NavbarProvider } from './navbar-context.js';
|
|
8
9
|
import { NavbarMenu } from './navbar-menu/menu.js';
|
|
9
10
|
import { useNavbar } from './use-navbar.js';
|
|
10
11
|
|
|
12
|
+
const showOnScrollUpVariants = {
|
|
13
|
+
visible: {
|
|
14
|
+
y: 0,
|
|
15
|
+
transition: {
|
|
16
|
+
ease: [0, 0, 0.2, 1]
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
hidden: {
|
|
20
|
+
y: "-100%",
|
|
21
|
+
transition: {
|
|
22
|
+
ease: [0, 0, 0.2, 1]
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
};
|
|
11
26
|
const Navbar = forwardRef((props, ref) => {
|
|
12
27
|
const { children, ...otherProps } = props;
|
|
13
28
|
const context = useNavbar({ ...otherProps, ref });
|
|
@@ -17,7 +32,16 @@ const Navbar = forwardRef((props, ref) => {
|
|
|
17
32
|
/* @__PURE__ */ jsx("header", { ...context.getWrapperProps(), children: childrenWithoutMenu }),
|
|
18
33
|
menu
|
|
19
34
|
] });
|
|
20
|
-
return /* @__PURE__ */ jsx(NavbarProvider, { value: context, children: /* @__PURE__ */ jsx(FocusScope, { contain: context.isMenuOpen, children: /* @__PURE__ */ jsx(
|
|
35
|
+
return /* @__PURE__ */ jsx(NavbarProvider, { value: context, children: /* @__PURE__ */ jsx(FocusScope, { contain: context.isMenuOpen, children: context.shouldShowOnScrollUp ? /* @__PURE__ */ jsx(LazyMotion, { features: domAnimation, children: /* @__PURE__ */ jsx(
|
|
36
|
+
m.nav,
|
|
37
|
+
{
|
|
38
|
+
animate: context.isNavbarHidden ? "hidden" : "visible",
|
|
39
|
+
initial: "visible",
|
|
40
|
+
variants: showOnScrollUpVariants,
|
|
41
|
+
...mergeProps(context.getBaseProps(), context.motionProps),
|
|
42
|
+
children: content
|
|
43
|
+
}
|
|
44
|
+
) }) : /* @__PURE__ */ jsx(Component, { ...context.getBaseProps(), children: content }) }) });
|
|
21
45
|
});
|
|
22
46
|
Navbar.displayName = "Navbar";
|
|
23
47
|
|