@mezzanine-ui/react 1.0.4 → 1.2.0
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/COMPONENTS.md +35 -31
- package/Calendar/CalendarConfigProviderTemporal.d.ts +55 -0
- package/Calendar/CalendarConfigProviderTemporal.js +49 -0
- package/Calendar/index.d.ts +2 -0
- package/Calendar/index.js +1 -0
- package/Dropdown/Dropdown.d.ts +8 -0
- package/Dropdown/Dropdown.js +11 -2
- package/Input/SelectButton/SelectButton.d.ts +5 -0
- package/Input/SelectButton/SelectButton.js +10 -10
- package/Pagination/PaginationPageSize.js +1 -1
- package/Picker/getFocusableElements.d.ts +3 -0
- package/Picker/getFocusableElements.js +70 -0
- package/Picker/usePickerDocumentEventClose.js +130 -16
- package/Table/Table.js +14 -9
- package/Table/TableContext.d.ts +1 -1
- package/Table/components/TableRow.js +1 -1
- package/Table/hooks/useTableVirtualization.js +1 -1
- package/package.json +5 -3
- package/temporal.d.ts +48 -0
- package/temporal.js +2 -0
package/COMPONENTS.md
CHANGED
|
@@ -150,37 +150,41 @@
|
|
|
150
150
|
|
|
151
151
|
## Utility(工具)
|
|
152
152
|
|
|
153
|
-
| 元件
|
|
154
|
-
|
|
|
155
|
-
| Calendar
|
|
156
|
-
| RangeCalendar
|
|
157
|
-
| CalendarCell
|
|
158
|
-
| CalendarConfigProvider
|
|
159
|
-
|
|
|
160
|
-
|
|
|
161
|
-
|
|
|
162
|
-
|
|
|
163
|
-
|
|
|
164
|
-
|
|
|
165
|
-
|
|
|
166
|
-
|
|
|
167
|
-
|
|
|
168
|
-
|
|
|
169
|
-
|
|
|
170
|
-
|
|
|
171
|
-
|
|
|
172
|
-
|
|
|
173
|
-
|
|
|
174
|
-
|
|
|
175
|
-
|
|
|
176
|
-
|
|
|
177
|
-
|
|
|
178
|
-
|
|
|
179
|
-
|
|
|
180
|
-
|
|
|
181
|
-
|
|
|
182
|
-
|
|
|
183
|
-
|
|
|
153
|
+
| 元件 | 匯入名稱 | 說明 |
|
|
154
|
+
| ------------------------------ | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
155
|
+
| Calendar | `Calendar` | 完整日曆元件,支援日/週/月/季/半年/年視圖切換 |
|
|
156
|
+
| RangeCalendar | `RangeCalendar` | 範圍日曆,支援選取起始至結束日期範圍 |
|
|
157
|
+
| CalendarCell | `CalendarCell` | 日曆中的單一日期格子 |
|
|
158
|
+
| CalendarConfigProvider | `CalendarConfigProvider` | 日曆全域設定提供者,設定語系與格式 |
|
|
159
|
+
| CalendarConfigProviderDayjs | `CalendarConfigProviderDayjs` | 預設綁定 dayjs 實作的 CalendarConfigProvider,sub-path entry `@mezzanine-ui/react/dayjs` |
|
|
160
|
+
| CalendarConfigProviderLuxon | `CalendarConfigProviderLuxon` | 預設綁定 luxon 實作的 CalendarConfigProvider,sub-path entry `@mezzanine-ui/react/luxon` |
|
|
161
|
+
| CalendarConfigProviderMoment | `CalendarConfigProviderMoment` | 預設綁定 moment 實作的 CalendarConfigProvider,sub-path entry `@mezzanine-ui/react/moment` |
|
|
162
|
+
| CalendarConfigProviderTemporal | `CalendarConfigProviderTemporal` | 預設綁定 JS-native Temporal 實作的 CalendarConfigProvider,sub-path entry `@mezzanine-ui/react/temporal`;Safari / Node 22 須先安裝 `@js-temporal/polyfill` |
|
|
163
|
+
| CalendarControls | `CalendarControls` | 日曆的月份/年份切換控制列 |
|
|
164
|
+
| CalendarDayOfWeek | `CalendarDayOfWeek` | 日曆的週幾標題列 |
|
|
165
|
+
| CalendarDays | `CalendarDays` | 日曆的日期格子區域 |
|
|
166
|
+
| CalendarHalfYears | `CalendarHalfYears` | 日曆的半年視圖 |
|
|
167
|
+
| CalendarMonths | `CalendarMonths` | 日曆的月份視圖 |
|
|
168
|
+
| CalendarQuarters | `CalendarQuarters` | 日曆的季度視圖 |
|
|
169
|
+
| CalendarWeeks | `CalendarWeeks` | 日曆的週視圖 |
|
|
170
|
+
| CalendarYears | `CalendarYears` | 日曆的年份視圖 |
|
|
171
|
+
| Dropdown | `Dropdown` | 下拉選單面板,由 Select、AutoComplete、Cascader 等元件內部使用 |
|
|
172
|
+
| DropdownAction | `DropdownAction` | Dropdown 中的操作按鈕項目 |
|
|
173
|
+
| DropdownItem | `DropdownItem` | Dropdown 中的標準選項項目 |
|
|
174
|
+
| DropdownItemCard | `DropdownItemCard` | Dropdown 中的卡片式選項項目 |
|
|
175
|
+
| DropdownStatus | `DropdownStatus` | Dropdown 的狀態提示顯示(空狀態、載入中等) |
|
|
176
|
+
| Popper | `Popper` | 定位浮層元件,基於 Floating UI,Tooltip / Dropdown 的定位基底 |
|
|
177
|
+
| Portal | `Portal` | 將子元件渲染到指定 DOM 節點,Modal、Drawer 使用此元件脫離文件流 |
|
|
178
|
+
| TimePanel | `TimePanel` | 時間選取面板,包含時/分/秒的滾輪選取 |
|
|
179
|
+
| TimePanelColumn | `TimePanelColumn` | TimePanel 中的單一時間欄(時、分或秒)的滾輪列 |
|
|
180
|
+
| Transition | `Transition` | 動畫過渡基底元件,提供 Collapse / Fade / Rotate / Scale / Slide / Translate 六種動畫 |
|
|
181
|
+
| Collapse | `Collapse` | 收合展開動畫(高度過渡) |
|
|
182
|
+
| Fade | `Fade` | 淡入淡出動畫 |
|
|
183
|
+
| Rotate | `Rotate` | 旋轉動畫 |
|
|
184
|
+
| Scale | `Scale` | 縮放動畫 |
|
|
185
|
+
| Slide | `Slide` | 滑動動畫,Drawer 使用此元件進行進出場 |
|
|
186
|
+
| Translate | `Translate` | 位移動畫 |
|
|
187
|
+
| createNotifier | `createNotifier` | 工廠函式,建立通知管理器實例,用於指令式顯示 toast / 通知訊息 |
|
|
184
188
|
|
|
185
189
|
---
|
|
186
190
|
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { CalendarLocaleValue } from '@mezzanine-ui/core/calendar';
|
|
3
|
+
export type CalendarConfigProviderTemporalProps = {
|
|
4
|
+
children?: ReactNode;
|
|
5
|
+
defaultDateFormat?: string;
|
|
6
|
+
defaultTimeFormat?: string;
|
|
7
|
+
/**
|
|
8
|
+
* The unified locale for all calendar display and value processing.
|
|
9
|
+
* This determines the first day of week, month names, weekday names, etc.
|
|
10
|
+
* Use CalendarLocale enum for type-safe locale values.
|
|
11
|
+
* @example CalendarLocale.EN_US, CalendarLocale.ZH_TW, CalendarLocale.DE_DE
|
|
12
|
+
* @default CalendarLocale.EN_US
|
|
13
|
+
*/
|
|
14
|
+
locale?: CalendarLocaleValue;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Pre-configured CalendarConfigProvider backed by the JS-native Temporal API.
|
|
18
|
+
*
|
|
19
|
+
* Requires `globalThis.Temporal` to be present **on the client** before any
|
|
20
|
+
* code imports `CalendarMethodsTemporal`. On runtimes that lack native
|
|
21
|
+
* support (Safari, Node 22), install `@js-temporal/polyfill` as a peer
|
|
22
|
+
* dependency.
|
|
23
|
+
*
|
|
24
|
+
* IMPORTANT: in Next.js App Router (and other RSC frameworks), default
|
|
25
|
+
* layouts are Server Components — registering the polyfill at module level
|
|
26
|
+
* in such a layout only runs on the server, leaving the browser without
|
|
27
|
+
* `globalThis.Temporal`. Use a Client Component wrapper instead. See the
|
|
28
|
+
* Calendar story docs for full setup examples (Vite/CRA vs App Router).
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```tsx
|
|
32
|
+
* // app/temporal-polyfill.tsx (Client Component)
|
|
33
|
+
* 'use client';
|
|
34
|
+
* import { Temporal } from '@js-temporal/polyfill';
|
|
35
|
+
* (globalThis as { Temporal?: unknown }).Temporal = Temporal;
|
|
36
|
+
* export function TemporalPolyfill() { return null; }
|
|
37
|
+
*
|
|
38
|
+
* // app/layout.tsx
|
|
39
|
+
* import { TemporalPolyfill } from './temporal-polyfill';
|
|
40
|
+
* import { CalendarConfigProviderTemporal, CalendarLocale } from '@mezzanine-ui/react/temporal';
|
|
41
|
+
*
|
|
42
|
+
* export default function RootLayout({ children }) {
|
|
43
|
+
* return (
|
|
44
|
+
* <html><body>
|
|
45
|
+
* <TemporalPolyfill />
|
|
46
|
+
* <CalendarConfigProviderTemporal locale={CalendarLocale.ZH_TW}>
|
|
47
|
+
* {children}
|
|
48
|
+
* </CalendarConfigProviderTemporal>
|
|
49
|
+
* </body></html>
|
|
50
|
+
* );
|
|
51
|
+
* }
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export declare function CalendarConfigProviderTemporal(props: CalendarConfigProviderTemporalProps): import("react/jsx-runtime").JSX.Element;
|
|
55
|
+
export default CalendarConfigProviderTemporal;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx } from 'react/jsx-runtime';
|
|
3
|
+
import CalendarMethodsTemporal from '@mezzanine-ui/core/calendarMethodsTemporal';
|
|
4
|
+
import CalendarConfigProvider from './CalendarContext.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Pre-configured CalendarConfigProvider backed by the JS-native Temporal API.
|
|
8
|
+
*
|
|
9
|
+
* Requires `globalThis.Temporal` to be present **on the client** before any
|
|
10
|
+
* code imports `CalendarMethodsTemporal`. On runtimes that lack native
|
|
11
|
+
* support (Safari, Node 22), install `@js-temporal/polyfill` as a peer
|
|
12
|
+
* dependency.
|
|
13
|
+
*
|
|
14
|
+
* IMPORTANT: in Next.js App Router (and other RSC frameworks), default
|
|
15
|
+
* layouts are Server Components — registering the polyfill at module level
|
|
16
|
+
* in such a layout only runs on the server, leaving the browser without
|
|
17
|
+
* `globalThis.Temporal`. Use a Client Component wrapper instead. See the
|
|
18
|
+
* Calendar story docs for full setup examples (Vite/CRA vs App Router).
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```tsx
|
|
22
|
+
* // app/temporal-polyfill.tsx (Client Component)
|
|
23
|
+
* 'use client';
|
|
24
|
+
* import { Temporal } from '@js-temporal/polyfill';
|
|
25
|
+
* (globalThis as { Temporal?: unknown }).Temporal = Temporal;
|
|
26
|
+
* export function TemporalPolyfill() { return null; }
|
|
27
|
+
*
|
|
28
|
+
* // app/layout.tsx
|
|
29
|
+
* import { TemporalPolyfill } from './temporal-polyfill';
|
|
30
|
+
* import { CalendarConfigProviderTemporal, CalendarLocale } from '@mezzanine-ui/react/temporal';
|
|
31
|
+
*
|
|
32
|
+
* export default function RootLayout({ children }) {
|
|
33
|
+
* return (
|
|
34
|
+
* <html><body>
|
|
35
|
+
* <TemporalPolyfill />
|
|
36
|
+
* <CalendarConfigProviderTemporal locale={CalendarLocale.ZH_TW}>
|
|
37
|
+
* {children}
|
|
38
|
+
* </CalendarConfigProviderTemporal>
|
|
39
|
+
* </body></html>
|
|
40
|
+
* );
|
|
41
|
+
* }
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
function CalendarConfigProviderTemporal(props) {
|
|
45
|
+
const { children, defaultDateFormat, defaultTimeFormat, locale } = props;
|
|
46
|
+
return (jsx(CalendarConfigProvider, { defaultDateFormat: defaultDateFormat, defaultTimeFormat: defaultTimeFormat, locale: locale, methods: CalendarMethodsTemporal, children: children }));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export { CalendarConfigProviderTemporal, CalendarConfigProviderTemporal as default };
|
package/Calendar/index.d.ts
CHANGED
|
@@ -10,6 +10,8 @@ export { default as CalendarConfigProviderMoment } from './CalendarConfigProvide
|
|
|
10
10
|
export type { CalendarConfigProviderMomentProps } from './CalendarConfigProviderMoment';
|
|
11
11
|
export { default as CalendarConfigProviderLuxon } from './CalendarConfigProviderLuxon';
|
|
12
12
|
export type { CalendarConfigProviderLuxonProps } from './CalendarConfigProviderLuxon';
|
|
13
|
+
export { default as CalendarConfigProviderTemporal } from './CalendarConfigProviderTemporal';
|
|
14
|
+
export type { CalendarConfigProviderTemporalProps } from './CalendarConfigProviderTemporal';
|
|
13
15
|
export type { CalendarYearsProps } from './CalendarYears';
|
|
14
16
|
export { default as CalendarYears } from './CalendarYears';
|
|
15
17
|
export type { CalendarQuartersProps } from './CalendarQuarters';
|
package/Calendar/index.js
CHANGED
|
@@ -5,6 +5,7 @@ export { default as CalendarConfigProvider, CalendarContext, useCalendarContext
|
|
|
5
5
|
export { CalendarConfigProviderDayjs } from './CalendarConfigProviderDayjs.js';
|
|
6
6
|
export { CalendarConfigProviderMoment } from './CalendarConfigProviderMoment.js';
|
|
7
7
|
export { CalendarConfigProviderLuxon } from './CalendarConfigProviderLuxon.js';
|
|
8
|
+
export { CalendarConfigProviderTemporal } from './CalendarConfigProviderTemporal.js';
|
|
8
9
|
export { default as CalendarYears } from './CalendarYears.js';
|
|
9
10
|
export { default as CalendarQuarters } from './CalendarQuarters.js';
|
|
10
11
|
export { default as CalendarHalfYears } from './CalendarHalfYears.js';
|
package/Dropdown/Dropdown.d.ts
CHANGED
|
@@ -144,6 +144,14 @@ export interface DropdownProps extends DropdownItemSharedProps {
|
|
|
144
144
|
* @default false
|
|
145
145
|
*/
|
|
146
146
|
sameWidth?: boolean;
|
|
147
|
+
/**
|
|
148
|
+
* Whether to enable floating-ui `flip` middleware.
|
|
149
|
+
* When `true`, the dropdown automatically flips to the opposite side
|
|
150
|
+
* (e.g. `bottom-start` → `top-start`) if it would overflow the viewport.
|
|
151
|
+
* Off by default to preserve existing placement behavior across consumers.
|
|
152
|
+
* @default false
|
|
153
|
+
*/
|
|
154
|
+
flip?: boolean;
|
|
147
155
|
/**
|
|
148
156
|
* If true, display a bar at the top of the dropdown action area.
|
|
149
157
|
* @default false
|
package/Dropdown/Dropdown.js
CHANGED
|
@@ -3,7 +3,7 @@ import { jsxs, jsx } from 'react/jsx-runtime';
|
|
|
3
3
|
import { useId, useMemo, useState, useRef, useCallback, useEffect, cloneElement, createElement } from 'react';
|
|
4
4
|
import cx from 'clsx';
|
|
5
5
|
import { dropdownClasses } from '@mezzanine-ui/core/dropdown/dropdown';
|
|
6
|
-
import { size, offset } from '@floating-ui/react-dom';
|
|
6
|
+
import { size, offset, flip } from '@floating-ui/react-dom';
|
|
7
7
|
import { MOTION_EASING, MOTION_DURATION } from '@mezzanine-ui/system/motion';
|
|
8
8
|
import { TransitionGroup } from 'react-transition-group';
|
|
9
9
|
import Button from '../Button/Button.js';
|
|
@@ -72,7 +72,7 @@ function getElementRef(element) {
|
|
|
72
72
|
* @see {@link AutoComplete} 具備自動補全功能的輸入元件
|
|
73
73
|
*/
|
|
74
74
|
function Dropdown(props) {
|
|
75
|
-
const { activeIndex: activeIndexProp, keyboardActiveIndex: keyboardActiveIndexProp, id, children, options = [], type = 'default', toggleCheckedOnClick, maxHeight, minWidth, disabled = false, showDropdownActions = false, actionCancelText, actionConfirmText, actionText, actionClearText, actionCustomButtonProps, showActionShowTopBar, isMatchInputValue = false, inputPosition = 'outside', placement = 'bottom-start', customWidth, sameWidth = false, listboxId: listboxIdProp, listboxLabel, onClose, onOpen, open: openProp, onVisibilityChange, onSelect, onActionConfirm, onActionCancel, onActionCustom, onActionClear, onItemHover, zIndex, status, loadingText, emptyText, emptyIcon, loadingPosition = 'full', followText: followTextProp, globalPortal = true, onReachBottom, onLeaveBottom, onScroll, mode, value, scrollbarDefer, scrollbarDisabled, scrollbarMaxWidth, scrollbarOptions, } = props;
|
|
75
|
+
const { activeIndex: activeIndexProp, keyboardActiveIndex: keyboardActiveIndexProp, id, children, options = [], type = 'default', toggleCheckedOnClick, maxHeight, minWidth, disabled = false, showDropdownActions = false, actionCancelText, actionConfirmText, actionText, actionClearText, actionCustomButtonProps, showActionShowTopBar, isMatchInputValue = false, inputPosition = 'outside', placement = 'bottom-start', customWidth, sameWidth = false, flip: flip$1 = false, listboxId: listboxIdProp, listboxLabel, onClose, onOpen, open: openProp, onVisibilityChange, onSelect, onActionConfirm, onActionCancel, onActionCustom, onActionClear, onItemHover, zIndex, status, loadingText, emptyText, emptyIcon, loadingPosition = 'full', followText: followTextProp, globalPortal = true, onReachBottom, onLeaveBottom, onScroll, mode, value, scrollbarDefer, scrollbarDisabled, scrollbarMaxWidth, scrollbarOptions, } = props;
|
|
76
76
|
const isInline = inputPosition === 'inside';
|
|
77
77
|
const inputId = useId();
|
|
78
78
|
const defaultListboxId = `${inputId}-listbox`;
|
|
@@ -221,6 +221,14 @@ function Dropdown(props) {
|
|
|
221
221
|
const offsetMiddleware = useMemo(() => {
|
|
222
222
|
return offset({ mainAxis: 4 });
|
|
223
223
|
}, []);
|
|
224
|
+
const flipMiddleware = useMemo(() => {
|
|
225
|
+
if (!flip$1)
|
|
226
|
+
return null;
|
|
227
|
+
return flip({
|
|
228
|
+
fallbackStrategy: 'bestFit',
|
|
229
|
+
padding: 8,
|
|
230
|
+
});
|
|
231
|
+
}, [flip$1]);
|
|
224
232
|
// Set z-index for popper only when explicitly provided via the `zIndex` prop.
|
|
225
233
|
// When not provided, do NOT apply any inline z-index so that elements inside
|
|
226
234
|
// the portal stack purely by DOM order — this ensures Modals opened from
|
|
@@ -560,6 +568,7 @@ function Dropdown(props) {
|
|
|
560
568
|
placement: popoverPlacement,
|
|
561
569
|
middleware: [
|
|
562
570
|
offsetMiddleware,
|
|
571
|
+
...(flipMiddleware ? [flipMiddleware] : []),
|
|
563
572
|
...(zIndexMiddleware ? [zIndexMiddleware] : []),
|
|
564
573
|
...(customWidthMiddleware ? [customWidthMiddleware] : []),
|
|
565
574
|
...(sameWidthMiddleware ? [sameWidthMiddleware] : []),
|
|
@@ -3,6 +3,11 @@ import { DropdownOption } from '@mezzanine-ui/core/dropdown/dropdown';
|
|
|
3
3
|
import { PopperPlacement } from '../../Popper';
|
|
4
4
|
import { NativeElementPropsWithoutKeyAndRef } from '../../utils/jsx-types';
|
|
5
5
|
export interface SelectButtonProps extends Omit<NativeElementPropsWithoutKeyAndRef<'button'>, 'disabled' | 'onSelect' | 'type' | 'selectedValue'> {
|
|
6
|
+
/**
|
|
7
|
+
* Whether clicking an option should automatically close the dropdown.
|
|
8
|
+
* @default true
|
|
9
|
+
*/
|
|
10
|
+
closeOnSelect?: boolean;
|
|
6
11
|
/**
|
|
7
12
|
* Whether the select button is disabled.
|
|
8
13
|
*/
|
|
@@ -10,24 +10,24 @@ import Icon from '../../Icon/Icon.js';
|
|
|
10
10
|
import cx from 'clsx';
|
|
11
11
|
|
|
12
12
|
const SelectButton = forwardRef(function SelectButton(props, ref) {
|
|
13
|
-
const { className, disabled, dropdownMaxHeight = 114, dropdownPlacement = 'bottom-start', dropdownWidth = 120, onSelect, options = [], size = 'main', value, ...rest } = props;
|
|
13
|
+
const { className, closeOnSelect = true, disabled, dropdownMaxHeight = 114, dropdownPlacement = 'bottom-start', dropdownWidth = 120, onSelect, options = [], size = 'main', value, ...rest } = props;
|
|
14
14
|
const [open, setOpen] = useState(false);
|
|
15
|
-
const
|
|
16
|
-
if (
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
const handleVisibilityChange = useCallback((next) => {
|
|
16
|
+
if (disabled && next)
|
|
17
|
+
return;
|
|
18
|
+
setOpen(next);
|
|
19
19
|
}, [disabled]);
|
|
20
|
-
const handleClose = useCallback(() => {
|
|
21
|
-
setOpen(false);
|
|
22
|
-
}, []);
|
|
23
20
|
const handleSelect = useCallback((option) => {
|
|
24
21
|
onSelect === null || onSelect === void 0 ? void 0 : onSelect(option.id);
|
|
25
|
-
|
|
22
|
+
if (closeOnSelect) {
|
|
23
|
+
setOpen(false);
|
|
24
|
+
}
|
|
25
|
+
}, [closeOnSelect, onSelect]);
|
|
26
26
|
const dropdownOptions = options.map((option) => ({
|
|
27
27
|
...option,
|
|
28
28
|
...(option.id === value ? { checkSite: 'suffix' } : {}),
|
|
29
29
|
}));
|
|
30
|
-
return (jsx(Dropdown, { customWidth: dropdownWidth, disabled: disabled, maxHeight: dropdownMaxHeight,
|
|
30
|
+
return (jsx(Dropdown, { customWidth: dropdownWidth, disabled: disabled, maxHeight: dropdownMaxHeight, onSelect: handleSelect, onVisibilityChange: handleVisibilityChange, open: open, options: dropdownOptions, placement: dropdownPlacement, value: value, children: jsxs("button", { ref: ref, type: "button", disabled: disabled, className: cx(inputSelectButtonClasses.host, disabled && inputSelectButtonClasses.disabled, size === 'main' ? inputSelectButtonClasses.main : inputSelectButtonClasses.sub, className), title: value, ...rest, children: [jsx("span", { className: inputSelectButtonClasses.text, children: value }), jsx(Rotate, { in: open, duration: MOTION_DURATION.fast, easing: MOTION_EASING.standard, children: jsx(Icon, { className: inputSelectButtonClasses.icon, icon: ChevronDownIcon, size: 16 }) })] }) }));
|
|
31
31
|
});
|
|
32
32
|
|
|
33
33
|
export { SelectButton as default };
|
|
@@ -25,7 +25,7 @@ const PaginationPageSize = forwardRef((props, ref) => {
|
|
|
25
25
|
onChange === null || onChange === void 0 ? void 0 : onChange(Number(option.id));
|
|
26
26
|
setOpen(false);
|
|
27
27
|
};
|
|
28
|
-
return (jsxs("div", { ...rest, ref: ref, className: cx(paginationPageSizeClasses.host, className), children: [label ? (jsx(Typography, { component: "div", ellipsis: true, variant: "label-primary", children: label })) : null, jsx(Dropdown, { disabled: disabled, minWidth: 0, onSelect: dropDownOnSelect, onVisibilityChange: setOpen, open: open, options: selectOptions, sameWidth: true, value: currentValue === null || currentValue === void 0 ? void 0 : currentValue.id, children: jsx(SelectTrigger, { className: paginationPageSizeClasses.select, disabled: disabled, size: "sub", value: currentValue }) })] }));
|
|
28
|
+
return (jsxs("div", { ...rest, ref: ref, className: cx(paginationPageSizeClasses.host, className), children: [label ? (jsx(Typography, { component: "div", ellipsis: true, variant: "label-primary", children: label })) : null, jsx(Dropdown, { disabled: disabled, flip: true, minWidth: 0, onSelect: dropDownOnSelect, onVisibilityChange: setOpen, open: open, options: selectOptions, sameWidth: true, value: currentValue === null || currentValue === void 0 ? void 0 : currentValue.id, children: jsx(SelectTrigger, { className: paginationPageSizeClasses.select, disabled: disabled, size: "sub", value: currentValue }) })] }));
|
|
29
29
|
});
|
|
30
30
|
|
|
31
31
|
export { PaginationPageSize as default };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare function getFocusableElements(container: HTMLElement | null): HTMLElement[];
|
|
2
|
+
export declare function getNextTabbableAfter(element: HTMLElement, skipContainer?: HTMLElement | null): HTMLElement | null;
|
|
3
|
+
export declare function getPreviousTabbableBefore(element: HTMLElement): HTMLElement | null;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
const FOCUSABLE_SELECTOR = [
|
|
2
|
+
'a[href]',
|
|
3
|
+
'area[href]',
|
|
4
|
+
'button:not([disabled])',
|
|
5
|
+
'input:not([disabled]):not([type="hidden"])',
|
|
6
|
+
'select:not([disabled])',
|
|
7
|
+
'textarea:not([disabled])',
|
|
8
|
+
'iframe',
|
|
9
|
+
'object',
|
|
10
|
+
'embed',
|
|
11
|
+
'audio[controls]',
|
|
12
|
+
'video[controls]',
|
|
13
|
+
'[contenteditable]:not([contenteditable="false"])',
|
|
14
|
+
'[tabindex]:not([tabindex="-1"])',
|
|
15
|
+
].join(',');
|
|
16
|
+
function isVisible(element) {
|
|
17
|
+
var _a, _b;
|
|
18
|
+
if (element.hidden)
|
|
19
|
+
return false;
|
|
20
|
+
const style = (_b = (_a = element.ownerDocument) === null || _a === void 0 ? void 0 : _a.defaultView) === null || _b === void 0 ? void 0 : _b.getComputedStyle(element);
|
|
21
|
+
if (!style)
|
|
22
|
+
return true;
|
|
23
|
+
return style.visibility !== 'hidden' && style.display !== 'none';
|
|
24
|
+
}
|
|
25
|
+
function getFocusableElements(container) {
|
|
26
|
+
if (!container)
|
|
27
|
+
return [];
|
|
28
|
+
const nodes = container.querySelectorAll(FOCUSABLE_SELECTOR);
|
|
29
|
+
const result = [];
|
|
30
|
+
for (const node of Array.from(nodes)) {
|
|
31
|
+
if (node.getAttribute('aria-hidden') === 'true')
|
|
32
|
+
continue;
|
|
33
|
+
if (!isVisible(node))
|
|
34
|
+
continue;
|
|
35
|
+
result.push(node);
|
|
36
|
+
}
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
39
|
+
function getNextTabbableAfter(element, skipContainer) {
|
|
40
|
+
const doc = element.ownerDocument;
|
|
41
|
+
const all = getFocusableElements(doc.body);
|
|
42
|
+
for (const node of all) {
|
|
43
|
+
if (node === element || element.contains(node))
|
|
44
|
+
continue;
|
|
45
|
+
if (skipContainer &&
|
|
46
|
+
(node === skipContainer || skipContainer.contains(node)))
|
|
47
|
+
continue;
|
|
48
|
+
const position = element.compareDocumentPosition(node);
|
|
49
|
+
if (position & Node.DOCUMENT_POSITION_FOLLOWING) {
|
|
50
|
+
return node;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
function getPreviousTabbableBefore(element) {
|
|
56
|
+
const doc = element.ownerDocument;
|
|
57
|
+
const all = getFocusableElements(doc.body);
|
|
58
|
+
let previous = null;
|
|
59
|
+
for (const node of all) {
|
|
60
|
+
if (node === element || element.contains(node))
|
|
61
|
+
continue;
|
|
62
|
+
const position = element.compareDocumentPosition(node);
|
|
63
|
+
if (position & Node.DOCUMENT_POSITION_PRECEDING) {
|
|
64
|
+
previous = node;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return previous;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export { getFocusableElements, getNextTabbableAfter, getPreviousTabbableBefore };
|
|
@@ -1,27 +1,141 @@
|
|
|
1
|
+
import { useRef } from 'react';
|
|
1
2
|
import { useClickAway } from '../hooks/useClickAway.js';
|
|
2
3
|
import { useDocumentEscapeKeyDown } from '../hooks/useDocumentEscapeKeyDown.js';
|
|
3
|
-
import {
|
|
4
|
+
import { useDocumentTabKeyDown } from '../hooks/useDocumentTabKeyDown.js';
|
|
5
|
+
import { useIsomorphicLayoutEffect } from '../hooks/useIsomorphicLayoutEffect.js';
|
|
6
|
+
import { getFocusableElements, getNextTabbableAfter, getPreviousTabbableBefore } from './getFocusableElements.js';
|
|
4
7
|
|
|
5
8
|
function usePickerDocumentEventClose({ anchorRef, lastElementRefInFlow, onClose, onChangeClose, open, popperRef, }) {
|
|
6
|
-
|
|
7
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Mirror the latest values into refs so the document-level event handlers
|
|
11
|
+
* (which are installed once and only re-installed when deps change) always
|
|
12
|
+
* read the freshest props rather than a closure captured at install time.
|
|
13
|
+
*/
|
|
14
|
+
const openRef = useRef(open);
|
|
15
|
+
const onCloseRef = useRef(onClose);
|
|
16
|
+
const onChangeCloseRef = useRef(onChangeClose);
|
|
17
|
+
useIsomorphicLayoutEffect(() => {
|
|
18
|
+
openRef.current = open;
|
|
19
|
+
onCloseRef.current = onClose;
|
|
20
|
+
onChangeCloseRef.current = onChangeClose;
|
|
21
|
+
});
|
|
22
|
+
useClickAway(() => (event) => {
|
|
23
|
+
var _a;
|
|
24
|
+
if (!openRef.current)
|
|
8
25
|
return;
|
|
26
|
+
if (!((_a = popperRef.current) === null || _a === void 0 ? void 0 : _a.contains(event.target))) {
|
|
27
|
+
onChangeCloseRef.current();
|
|
9
28
|
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
};
|
|
16
|
-
}, anchorRef, [open, onClose]);
|
|
17
|
-
/** Close popper when escape key down */
|
|
29
|
+
}, anchorRef, []);
|
|
30
|
+
/**
|
|
31
|
+
* Close popper on Escape and return focus to the trigger input so the
|
|
32
|
+
* user does not lose their place in the page tab order.
|
|
33
|
+
*/
|
|
18
34
|
useDocumentEscapeKeyDown(() => () => {
|
|
19
|
-
|
|
20
|
-
|
|
35
|
+
var _a;
|
|
36
|
+
if (!openRef.current)
|
|
37
|
+
return;
|
|
38
|
+
onCloseRef.current();
|
|
39
|
+
const popper = popperRef.current;
|
|
40
|
+
const active = document.activeElement;
|
|
41
|
+
if (popper && active && popper.contains(active)) {
|
|
42
|
+
(_a = lastElementRefInFlow.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
21
43
|
}
|
|
22
|
-
}, [
|
|
23
|
-
/**
|
|
24
|
-
|
|
44
|
+
}, [lastElementRefInFlow, popperRef]);
|
|
45
|
+
/**
|
|
46
|
+
* Keyboard navigation across the trigger input and the portalled popper.
|
|
47
|
+
*
|
|
48
|
+
* The popper is rendered into document.body via Portal, so the natural
|
|
49
|
+
* Tab order skips it entirely. We bridge the trigger and the popper as
|
|
50
|
+
* a logical sequence:
|
|
51
|
+
*
|
|
52
|
+
* - Tab from trigger input → first focusable inside popper (handled by
|
|
53
|
+
* the direct trigger listener below, which uses `stopPropagation` so
|
|
54
|
+
* this document-level handler does not run again for that case)
|
|
55
|
+
* - Shift+Tab from trigger → close popper (same)
|
|
56
|
+
* - Tab from last popper → close + focus next tab stop after anchor
|
|
57
|
+
* - Shift+Tab from first → return focus to trigger input
|
|
58
|
+
*
|
|
59
|
+
* Other Tabs inside the popper fall through to the browser's default
|
|
60
|
+
* focus traversal, so users can walk through calendar buttons, footer
|
|
61
|
+
* actions, etc. with the regular keyboard.
|
|
62
|
+
*/
|
|
63
|
+
useDocumentTabKeyDown(() => (event) => {
|
|
64
|
+
var _a;
|
|
65
|
+
if (!openRef.current)
|
|
66
|
+
return;
|
|
67
|
+
const popper = popperRef.current;
|
|
68
|
+
const anchor = anchorRef.current;
|
|
69
|
+
const trigger = lastElementRefInFlow.current;
|
|
70
|
+
if (!popper || !anchor)
|
|
71
|
+
return;
|
|
72
|
+
const active = document.activeElement;
|
|
73
|
+
if (!active || !popper.contains(active))
|
|
74
|
+
return;
|
|
75
|
+
const focusables = getFocusableElements(popper);
|
|
76
|
+
if (focusables.length === 0)
|
|
77
|
+
return;
|
|
78
|
+
const first = focusables[0];
|
|
79
|
+
const last = focusables[focusables.length - 1];
|
|
80
|
+
if (!event.shiftKey && active === last) {
|
|
81
|
+
event.preventDefault();
|
|
82
|
+
onChangeCloseRef.current();
|
|
83
|
+
const next = getNextTabbableAfter(anchor, popper);
|
|
84
|
+
if (next) {
|
|
85
|
+
next.focus();
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
trigger === null || trigger === void 0 ? void 0 : trigger.blur();
|
|
89
|
+
}
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (event.shiftKey && active === first) {
|
|
93
|
+
event.preventDefault();
|
|
94
|
+
if (trigger) {
|
|
95
|
+
trigger.focus();
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
onChangeCloseRef.current();
|
|
99
|
+
(_a = getPreviousTabbableBefore(anchor)) === null || _a === void 0 ? void 0 : _a.focus();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}, [anchorRef, popperRef, lastElementRefInFlow]);
|
|
103
|
+
/**
|
|
104
|
+
* Direct keydown listener on the trigger element for the Tab → popper
|
|
105
|
+
* bridge. Binding directly on the trigger (instead of the document) is
|
|
106
|
+
* more reliable: it still fires when the picker lives inside a Modal or
|
|
107
|
+
* focus trap that stops keydown propagation before it reaches document.
|
|
108
|
+
*/
|
|
109
|
+
useIsomorphicLayoutEffect(() => {
|
|
110
|
+
const trigger = lastElementRefInFlow.current;
|
|
111
|
+
if (!trigger)
|
|
112
|
+
return;
|
|
113
|
+
const handleKeyDown = (event) => {
|
|
114
|
+
if (event.key !== 'Tab')
|
|
115
|
+
return;
|
|
116
|
+
if (!openRef.current)
|
|
117
|
+
return;
|
|
118
|
+
const popper = popperRef.current;
|
|
119
|
+
if (!popper)
|
|
120
|
+
return;
|
|
121
|
+
if (event.shiftKey) {
|
|
122
|
+
onChangeCloseRef.current();
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const focusables = getFocusableElements(popper);
|
|
126
|
+
if (focusables.length === 0) {
|
|
127
|
+
onChangeCloseRef.current();
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
event.preventDefault();
|
|
131
|
+
event.stopPropagation();
|
|
132
|
+
focusables[0].focus();
|
|
133
|
+
};
|
|
134
|
+
trigger.addEventListener('keydown', handleKeyDown);
|
|
135
|
+
return () => {
|
|
136
|
+
trigger.removeEventListener('keydown', handleKeyDown);
|
|
137
|
+
};
|
|
138
|
+
}, [lastElementRefInFlow, popperRef]);
|
|
25
139
|
}
|
|
26
140
|
|
|
27
141
|
export { usePickerDocumentEventClose };
|
package/Table/Table.js
CHANGED
|
@@ -16,6 +16,7 @@ import { useTableScroll } from './hooks/useTableScroll.js';
|
|
|
16
16
|
import { useTableSelection } from './hooks/useTableSelection.js';
|
|
17
17
|
import { useTableSorting } from './hooks/useTableSorting.js';
|
|
18
18
|
import { getNumericCSSVariablePixelValue } from '../utils/get-css-variable-value.js';
|
|
19
|
+
import { useIsomorphicLayoutEffect } from '../hooks/useIsomorphicLayoutEffect.js';
|
|
19
20
|
import { spacingPrefix } from '@mezzanine-ui/system/spacing';
|
|
20
21
|
import TableBulkActions from './components/TableBulkActions.js';
|
|
21
22
|
import { useComposeRefs } from '../hooks/useComposeRefs.js';
|
|
@@ -33,27 +34,31 @@ function TableInner(props, ref) {
|
|
|
33
34
|
}))
|
|
34
35
|
: dataSource;
|
|
35
36
|
/** Feature: Row Height Preset */
|
|
36
|
-
const
|
|
37
|
+
const rowHeightVariableName = useMemo(() => {
|
|
37
38
|
switch (rowHeightPreset) {
|
|
38
39
|
case 'condensed':
|
|
39
40
|
return size === 'main'
|
|
40
|
-
?
|
|
41
|
-
:
|
|
41
|
+
? `--${spacingPrefix}-size-container-condensed`
|
|
42
|
+
: `--${spacingPrefix}-size-container-reduced`;
|
|
42
43
|
case 'detailed':
|
|
43
44
|
return size === 'main'
|
|
44
|
-
?
|
|
45
|
-
:
|
|
45
|
+
? `--${spacingPrefix}-size-container-tiny`
|
|
46
|
+
: `--${spacingPrefix}-size-container-tightened`;
|
|
46
47
|
case 'roomy':
|
|
47
48
|
return size === 'main'
|
|
48
|
-
?
|
|
49
|
-
:
|
|
49
|
+
? `--${spacingPrefix}-size-container-small`
|
|
50
|
+
: `--${spacingPrefix}-size-container-medium`;
|
|
50
51
|
case 'base':
|
|
51
52
|
default:
|
|
52
53
|
return size === 'main'
|
|
53
|
-
?
|
|
54
|
-
:
|
|
54
|
+
? `--${spacingPrefix}-size-container-minimized`
|
|
55
|
+
: `--${spacingPrefix}-size-container-minimal`;
|
|
55
56
|
}
|
|
56
57
|
}, [rowHeightPreset, size]);
|
|
58
|
+
const [rowHeight, setRowHeight] = useState(undefined);
|
|
59
|
+
useIsomorphicLayoutEffect(() => {
|
|
60
|
+
setRowHeight(getNumericCSSVariablePixelValue(rowHeightVariableName));
|
|
61
|
+
}, [rowHeightVariableName]);
|
|
57
62
|
/** Feature: Highlight */
|
|
58
63
|
const [hoveredRowIndex, setHoveredRowIndex] = useState(null);
|
|
59
64
|
const [hoveredColumnIndex, setHoveredColumnIndex] = useState(null);
|
package/Table/TableContext.d.ts
CHANGED
|
@@ -60,7 +60,7 @@ export interface TableContextValue<T extends TableDataSource = TableDataSource>
|
|
|
60
60
|
pinnable?: TablePinnable;
|
|
61
61
|
resizable?: boolean;
|
|
62
62
|
rowState?: TableRowState | ((rowData: TableDataSource) => TableRowState | undefined);
|
|
63
|
-
rowHeight: number;
|
|
63
|
+
rowHeight: number | undefined;
|
|
64
64
|
scroll?: TableScroll;
|
|
65
65
|
scrollContainerRef?: React.RefObject<HTMLDivElement | null>;
|
|
66
66
|
selection?: TableSelectionState<T>;
|
|
@@ -45,7 +45,7 @@ const TableRowInner = forwardRef(function TableRow(props, ref) {
|
|
|
45
45
|
const resolvedStyle = useMemo(() => ({
|
|
46
46
|
...style,
|
|
47
47
|
...draggableProvided === null || draggableProvided === void 0 ? void 0 : draggableProvided.draggableProps.style,
|
|
48
|
-
height: rowHeight,
|
|
48
|
+
...(rowHeight !== undefined && { height: rowHeight }),
|
|
49
49
|
}), [style, rowHeight, draggableProvided === null || draggableProvided === void 0 ? void 0 : draggableProvided.draggableProps.style]);
|
|
50
50
|
const { containerWidth, getResizedColumnWidth, scrollLeft } = useTableSuperContext();
|
|
51
51
|
const rowKey = useMemo(() => getRowKey(record), [record]);
|
|
@@ -16,7 +16,7 @@ function useTableVirtualization({ dataSource, enabled = true, isContainerReady =
|
|
|
16
16
|
if (measuredHeight !== undefined) {
|
|
17
17
|
return measuredHeight;
|
|
18
18
|
}
|
|
19
|
-
return rowHeight;
|
|
19
|
+
return rowHeight !== null && rowHeight !== void 0 ? rowHeight : 0;
|
|
20
20
|
}, [dataSource, rowHeight]);
|
|
21
21
|
const getItemKey = useCallback((index) => {
|
|
22
22
|
const record = dataSource[index];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mezzanine-ui/react",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "React components for mezzanine-ui",
|
|
5
5
|
"author": "Mezzanine",
|
|
6
6
|
"repository": {
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"@floating-ui/dom": "^1.7.4",
|
|
33
33
|
"@floating-ui/react-dom": "^2.1.6",
|
|
34
34
|
"@hello-pangea/dnd": "^18.0.1",
|
|
35
|
-
"@mezzanine-ui/core": "1.0
|
|
35
|
+
"@mezzanine-ui/core": "1.1.0",
|
|
36
36
|
"@mezzanine-ui/icons": "1.0.2",
|
|
37
37
|
"@mezzanine-ui/system": "1.0.2",
|
|
38
38
|
"@tanstack/react-virtual": "^3.13.13",
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"tslib": "^2.8.1"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
+
"@js-temporal/polyfill": "^0.5.1",
|
|
49
50
|
"@types/lodash": "^4.17.20",
|
|
50
51
|
"@types/moment": "^2.13.0",
|
|
51
52
|
"@types/react": "^19.2.2",
|
|
@@ -56,5 +57,6 @@
|
|
|
56
57
|
"moment": "^2.30.1",
|
|
57
58
|
"react": "^19.2.0",
|
|
58
59
|
"react-dom": "^19.2.0"
|
|
59
|
-
}
|
|
60
|
+
},
|
|
61
|
+
"gitHead": "f5fa136dac936a0debafff9ea5a3815ff0b5c040"
|
|
60
62
|
}
|
package/temporal.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Temporal-specific entry point for Mezzanine UI React.
|
|
3
|
+
* Import from this path to use the JS-native Temporal API without loading
|
|
4
|
+
* any other date library (moment / dayjs / luxon).
|
|
5
|
+
*
|
|
6
|
+
* Runtime requirement: `globalThis.Temporal` must be available **on the
|
|
7
|
+
* client** before any import of `CalendarMethodsTemporal`. On runtimes that
|
|
8
|
+
* lack native support (Safari, Node 22), install `@js-temporal/polyfill` as
|
|
9
|
+
* a peer dependency and register it from a Client Component side-effect.
|
|
10
|
+
*
|
|
11
|
+
* @example Vite / CRA — register at the client entry
|
|
12
|
+
* ```tsx
|
|
13
|
+
* // main.tsx
|
|
14
|
+
* import { Temporal } from '@js-temporal/polyfill';
|
|
15
|
+
* (globalThis as { Temporal?: unknown }).Temporal = Temporal;
|
|
16
|
+
*
|
|
17
|
+
* import { CalendarConfigProviderTemporal, CalendarLocale } from '@mezzanine-ui/react/temporal';
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* @example Next.js App Router — Server Component layouts cannot register
|
|
21
|
+
* the polyfill for the browser, so wrap it in a Client Component module:
|
|
22
|
+
* ```tsx
|
|
23
|
+
* // app/temporal-polyfill.tsx
|
|
24
|
+
* 'use client';
|
|
25
|
+
* import { Temporal } from '@js-temporal/polyfill';
|
|
26
|
+
* (globalThis as { Temporal?: unknown }).Temporal = Temporal;
|
|
27
|
+
* export function TemporalPolyfill() { return null; }
|
|
28
|
+
*
|
|
29
|
+
* // app/layout.tsx
|
|
30
|
+
* import { TemporalPolyfill } from './temporal-polyfill';
|
|
31
|
+
* import { CalendarConfigProviderTemporal, CalendarLocale } from '@mezzanine-ui/react/temporal';
|
|
32
|
+
*
|
|
33
|
+
* export default function RootLayout({ children }) {
|
|
34
|
+
* return (
|
|
35
|
+
* <html><body>
|
|
36
|
+
* <TemporalPolyfill />
|
|
37
|
+
* <CalendarConfigProviderTemporal locale={CalendarLocale.ZH_TW}>
|
|
38
|
+
* {children}
|
|
39
|
+
* </CalendarConfigProviderTemporal>
|
|
40
|
+
* </body></html>
|
|
41
|
+
* );
|
|
42
|
+
* }
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export { CalendarLocale } from '@mezzanine-ui/core/calendar';
|
|
46
|
+
export type { CalendarLocaleValue } from '@mezzanine-ui/core/calendar';
|
|
47
|
+
export { default as CalendarConfigProviderTemporal } from './Calendar/CalendarConfigProviderTemporal';
|
|
48
|
+
export type { CalendarConfigProviderTemporalProps } from './Calendar/CalendarConfigProviderTemporal';
|
package/temporal.js
ADDED