@mezzanine-ui/react 1.0.0-beta.6 → 1.0.0-beta.7
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/Accordion/Accordion.d.ts +23 -1
- package/Accordion/Accordion.js +59 -11
- package/Accordion/AccordionActions.d.ts +13 -0
- package/Accordion/AccordionActions.js +24 -0
- package/Accordion/AccordionContent.d.ts +9 -0
- package/Accordion/{AccordionDetails.js → AccordionContent.js} +4 -6
- package/Accordion/AccordionControlContext.d.ts +2 -2
- package/Accordion/AccordionGroup.d.ts +10 -0
- package/Accordion/AccordionGroup.js +26 -0
- package/Accordion/AccordionTitle.d.ts +14 -0
- package/Accordion/AccordionTitle.js +56 -0
- package/Accordion/index.d.ts +8 -4
- package/Accordion/index.js +4 -2
- package/AutoComplete/AutoComplete.d.ts +20 -6
- package/AutoComplete/AutoComplete.js +118 -30
- package/Backdrop/Backdrop.js +15 -19
- package/Calendar/CalendarDays.js +1 -1
- package/Card/BaseCard.d.ts +11 -0
- package/Card/BaseCard.js +48 -0
- package/Card/BaseCardSkeleton.d.ts +14 -0
- package/Card/BaseCardSkeleton.js +18 -0
- package/Card/CardGroup.d.ts +47 -0
- package/Card/CardGroup.js +147 -0
- package/Card/FourThumbnailCard.d.ts +14 -0
- package/Card/FourThumbnailCard.js +73 -0
- package/Card/FourThumbnailCardSkeleton.d.ts +14 -0
- package/Card/FourThumbnailCardSkeleton.js +20 -0
- package/Card/QuickActionCard.d.ts +12 -0
- package/Card/QuickActionCard.js +23 -0
- package/Card/QuickActionCardSkeleton.d.ts +14 -0
- package/Card/QuickActionCardSkeleton.js +18 -0
- package/Card/SingleThumbnailCard.d.ts +13 -0
- package/Card/SingleThumbnailCard.js +44 -0
- package/Card/SingleThumbnailCardSkeleton.d.ts +19 -0
- package/Card/SingleThumbnailCardSkeleton.js +18 -0
- package/Card/Thumbnail.d.ts +12 -0
- package/Card/Thumbnail.js +18 -0
- package/Card/ThumbnailCardInfo.d.ts +34 -0
- package/Card/ThumbnailCardInfo.js +43 -0
- package/Card/index.d.ts +43 -4
- package/Card/index.js +19 -2
- package/Card/typings.d.ts +442 -0
- package/Checkbox/Checkbox.d.ts +8 -0
- package/Checkbox/Checkbox.js +3 -2
- package/Checkbox/CheckboxGroup.js +1 -1
- package/ContentHeader/ContentHeader.d.ts +22 -70
- package/ContentHeader/ContentHeader.js +1 -1
- package/ContentHeader/ContentHeaderResponsive.d.ts +9 -0
- package/ContentHeader/ContentHeaderResponsive.js +7 -0
- package/ContentHeader/utils.d.ts +3 -3
- package/ContentHeader/utils.js +66 -20
- package/Cropper/Cropper.d.ts +66 -0
- package/Cropper/Cropper.js +115 -0
- package/Cropper/CropperElement.d.ts +10 -0
- package/Cropper/CropperElement.js +892 -0
- package/Cropper/index.d.ts +18 -0
- package/Cropper/index.js +8 -0
- package/Cropper/tools.d.ts +90 -0
- package/Cropper/tools.js +143 -0
- package/Cropper/typings.d.ts +69 -0
- package/Cropper/utils/cropper-calculations.d.ts +39 -0
- package/Cropper/utils/cropper-calculations.js +95 -0
- package/DateTimePicker/DateTimePicker.d.ts +1 -1
- package/DateTimePicker/DateTimePicker.js +14 -1
- package/Dropdown/Dropdown.d.ts +7 -1
- package/Dropdown/Dropdown.js +31 -14
- package/Dropdown/DropdownItem.d.ts +7 -1
- package/Dropdown/DropdownItem.js +36 -6
- package/Dropdown/DropdownItemCard.js +2 -1
- package/FloatingButton/FloatingButton.d.ts +21 -0
- package/FloatingButton/FloatingButton.js +18 -0
- package/FloatingButton/index.d.ts +2 -0
- package/FloatingButton/index.js +1 -0
- package/Form/FormField.d.ts +21 -10
- package/Form/FormField.js +12 -4
- package/Input/Input.js +9 -2
- package/Message/Message.js +1 -1
- package/MultipleDatePicker/MultipleDatePicker.js +2 -2
- package/Navigation/NavigationHeader.js +1 -1
- package/Picker/FormattedInput.d.ts +1 -1
- package/Picker/FormattedInput.js +2 -1
- package/Picker/PickerTriggerWithSeparator.d.ts +10 -0
- package/Picker/PickerTriggerWithSeparator.js +2 -2
- package/Picker/useDateInputFormatter.d.ts +6 -0
- package/Picker/useDateInputFormatter.js +4 -1
- package/Select/Select.d.ts +2 -8
- package/Select/Select.js +12 -33
- package/Select/SelectTrigger.js +21 -7
- package/Select/index.d.ts +0 -4
- package/Select/index.js +0 -2
- package/Select/typings.d.ts +0 -4
- package/Select/useSelectTriggerTags.d.ts +1 -1
- package/Select/useSelectTriggerTags.js +9 -6
- package/Separator/Separator.d.ts +14 -0
- package/Separator/Separator.js +17 -0
- package/Separator/index.d.ts +2 -0
- package/Separator/index.js +1 -0
- package/Table/utils/useTableRowSelection.js +6 -0
- package/Tag/TagGroup.d.ts +4 -2
- package/Tag/TagGroup.js +7 -4
- package/TextField/TextField.d.ts +1 -1
- package/TextField/TextField.js +63 -9
- package/TimePanel/TimePanelColumn.js +19 -12
- package/index.d.ts +27 -28
- package/index.js +23 -25
- package/package.json +4 -4
- package/Accordion/AccordionDetails.d.ts +0 -9
- package/Accordion/AccordionSummary.d.ts +0 -18
- package/Accordion/AccordionSummary.js +0 -51
- package/Alert/Alert.d.ts +0 -20
- package/Alert/Alert.js +0 -18
- package/Alert/index.d.ts +0 -3
- package/Alert/index.js +0 -1
- package/Card/Card.d.ts +0 -51
- package/Card/Card.js +0 -20
- package/Card/CardActions.d.ts +0 -34
- package/Card/CardActions.js +0 -15
- package/ConfirmActions/ConfirmActions.d.ts +0 -46
- package/ConfirmActions/ConfirmActions.js +0 -15
- package/ConfirmActions/index.d.ts +0 -2
- package/ConfirmActions/index.js +0 -1
- package/Select/Option.d.ts +0 -18
- package/Select/Option.js +0 -45
- package/Select/TreeSelect.d.ts +0 -72
- package/Select/TreeSelect.js +0 -205
- package/Tree/Tree.d.ts +0 -70
- package/Tree/Tree.js +0 -139
- package/Tree/TreeNode.d.ts +0 -40
- package/Tree/TreeNode.js +0 -50
- package/Tree/TreeNodeList.d.ts +0 -24
- package/Tree/TreeNodeList.js +0 -28
- package/Tree/getTreeNodeEntities.d.ts +0 -11
- package/Tree/getTreeNodeEntities.js +0 -92
- package/Tree/index.d.ts +0 -13
- package/Tree/index.js +0 -7
- package/Tree/toggleValue.d.ts +0 -4
- package/Tree/toggleValue.js +0 -19
- package/Tree/traverseTree.d.ts +0 -2
- package/Tree/traverseTree.js +0 -11
- package/Tree/typings.d.ts +0 -16
- package/Tree/useTreeExpandedValue.d.ts +0 -14
- package/Tree/useTreeExpandedValue.js +0 -33
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { PropsWithoutRef, ReactElement, RefAttributes } from 'react';
|
|
2
|
+
import { CropperModal, CropperProps } from './Cropper';
|
|
3
|
+
import { CropArea, CropperComponent, CropperElementComponent, CropperPropsBase } from './typings';
|
|
4
|
+
export type { CropperSize } from '@mezzanine-ui/core/cropper';
|
|
5
|
+
export type { CropperModalConfirmContext, CropperModalOpenOptions, CropperModalProps, CropperModalResult, CropperModalType } from './Cropper';
|
|
6
|
+
export { default as CropperElement } from './CropperElement';
|
|
7
|
+
export type { CropperElementProps } from './CropperElement';
|
|
8
|
+
export { cropToBlob, cropToDataURL, cropToFile } from './tools';
|
|
9
|
+
export type { CropToBlobOptions } from './tools';
|
|
10
|
+
export { CropperModal };
|
|
11
|
+
export type { CropArea, CropperComponent, CropperElementComponent, CropperProps, CropperPropsBase };
|
|
12
|
+
/**
|
|
13
|
+
* @remark
|
|
14
|
+
* Add type alias here for parsable to react docgen typescript.
|
|
15
|
+
*/
|
|
16
|
+
type GenericCropper = <C extends CropperComponent = 'div'>(props: PropsWithoutRef<CropperProps<C>> & RefAttributes<HTMLDivElement>) => ReactElement<any>;
|
|
17
|
+
declare const _default: GenericCropper;
|
|
18
|
+
export default _default;
|
package/Cropper/index.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { CropArea } from './typings';
|
|
2
|
+
export interface CropToBlobOptions {
|
|
3
|
+
/**
|
|
4
|
+
* The image source (URL, File, or Blob).
|
|
5
|
+
*/
|
|
6
|
+
imageSrc: string | File | Blob;
|
|
7
|
+
/**
|
|
8
|
+
* The crop area coordinates and dimensions in image pixel space.
|
|
9
|
+
*/
|
|
10
|
+
cropArea: CropArea;
|
|
11
|
+
/**
|
|
12
|
+
* The canvas element used for cropping.
|
|
13
|
+
* If not provided, a temporary canvas will be created.
|
|
14
|
+
*/
|
|
15
|
+
canvas?: HTMLCanvasElement;
|
|
16
|
+
/**
|
|
17
|
+
* The output image format.
|
|
18
|
+
* @default 'image/png'
|
|
19
|
+
*/
|
|
20
|
+
format?: string;
|
|
21
|
+
/**
|
|
22
|
+
* The output image quality (0-1).
|
|
23
|
+
* Only applies to 'image/jpeg' and 'image/webp' formats.
|
|
24
|
+
* @default 0.92
|
|
25
|
+
*/
|
|
26
|
+
quality?: number;
|
|
27
|
+
/**
|
|
28
|
+
* The output image width in pixels.
|
|
29
|
+
* If not provided, uses the crop area width.
|
|
30
|
+
*/
|
|
31
|
+
outputWidth?: number;
|
|
32
|
+
/**
|
|
33
|
+
* The output image height in pixels.
|
|
34
|
+
* If not provided, uses the crop area height.
|
|
35
|
+
*/
|
|
36
|
+
outputHeight?: number;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Converts a cropped image area to a Blob.
|
|
40
|
+
*
|
|
41
|
+
* @param options - The cropping options
|
|
42
|
+
* @returns A Promise that resolves to a Blob of the cropped image
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```tsx
|
|
46
|
+
* const blob = await cropToBlob({
|
|
47
|
+
* imageSrc: 'https://example.com/image.jpg',
|
|
48
|
+
* cropArea: { x: 100, y: 100, width: 200, height: 200 },
|
|
49
|
+
* format: 'image/jpeg',
|
|
50
|
+
* quality: 0.9,
|
|
51
|
+
* });
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export declare function cropToBlob(options: CropToBlobOptions): Promise<Blob>;
|
|
55
|
+
/**
|
|
56
|
+
* Converts a cropped image area to a File.
|
|
57
|
+
*
|
|
58
|
+
* @param options - The cropping options
|
|
59
|
+
* @param filename - The filename for the output file
|
|
60
|
+
* @returns A Promise that resolves to a File of the cropped image
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```tsx
|
|
64
|
+
* const file = await cropToFile(
|
|
65
|
+
* {
|
|
66
|
+
* imageSrc: fileInput.files[0],
|
|
67
|
+
* cropArea: { x: 100, y: 100, width: 200, height: 200 },
|
|
68
|
+
* },
|
|
69
|
+
* 'cropped-image.jpg',
|
|
70
|
+
* );
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export declare function cropToFile(options: CropToBlobOptions, filename: string): Promise<File>;
|
|
74
|
+
/**
|
|
75
|
+
* Converts a cropped image area to a data URL.
|
|
76
|
+
*
|
|
77
|
+
* @param options - The cropping options
|
|
78
|
+
* @returns A Promise that resolves to a data URL string of the cropped image
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```tsx
|
|
82
|
+
* const dataUrl = await cropToDataURL({
|
|
83
|
+
* imageSrc: 'https://example.com/image.jpg',
|
|
84
|
+
* cropArea: { x: 100, y: 100, width: 200, height: 200 },
|
|
85
|
+
* format: 'image/jpeg',
|
|
86
|
+
* quality: 0.9,
|
|
87
|
+
* });
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
export declare function cropToDataURL(options: CropToBlobOptions): Promise<string>;
|
package/Cropper/tools.js
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts a cropped image area to a Blob.
|
|
3
|
+
*
|
|
4
|
+
* @param options - The cropping options
|
|
5
|
+
* @returns A Promise that resolves to a Blob of the cropped image
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```tsx
|
|
9
|
+
* const blob = await cropToBlob({
|
|
10
|
+
* imageSrc: 'https://example.com/image.jpg',
|
|
11
|
+
* cropArea: { x: 100, y: 100, width: 200, height: 200 },
|
|
12
|
+
* format: 'image/jpeg',
|
|
13
|
+
* quality: 0.9,
|
|
14
|
+
* });
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
async function cropToBlob(options) {
|
|
18
|
+
const { imageSrc, cropArea, canvas: providedCanvas, format = 'image/png', quality = 0.92, outputWidth, outputHeight, } = options;
|
|
19
|
+
// Load image
|
|
20
|
+
const img = await loadImage(imageSrc);
|
|
21
|
+
// Create or use provided canvas
|
|
22
|
+
const canvas = providedCanvas || document.createElement('canvas');
|
|
23
|
+
const ctx = canvas.getContext('2d');
|
|
24
|
+
if (!ctx) {
|
|
25
|
+
throw new Error('Failed to get canvas context');
|
|
26
|
+
}
|
|
27
|
+
// Crop area is already in image pixel space
|
|
28
|
+
const actualCropX = cropArea.x;
|
|
29
|
+
const actualCropY = cropArea.y;
|
|
30
|
+
const actualCropWidth = cropArea.width;
|
|
31
|
+
const actualCropHeight = cropArea.height;
|
|
32
|
+
// Set canvas size to output dimensions or crop area dimensions
|
|
33
|
+
const finalWidth = outputWidth || cropArea.width;
|
|
34
|
+
const finalHeight = outputHeight || cropArea.height;
|
|
35
|
+
canvas.width = finalWidth;
|
|
36
|
+
canvas.height = finalHeight;
|
|
37
|
+
// Draw the cropped portion of the image
|
|
38
|
+
ctx.drawImage(img, actualCropX, actualCropY, actualCropWidth, actualCropHeight, 0, 0, finalWidth, finalHeight);
|
|
39
|
+
// Convert to blob
|
|
40
|
+
return new Promise((resolve, reject) => {
|
|
41
|
+
canvas.toBlob((blob) => {
|
|
42
|
+
if (blob) {
|
|
43
|
+
resolve(blob);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
reject(new Error('Failed to convert canvas to blob'));
|
|
47
|
+
}
|
|
48
|
+
}, format, quality);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Converts a cropped image area to a File.
|
|
53
|
+
*
|
|
54
|
+
* @param options - The cropping options
|
|
55
|
+
* @param filename - The filename for the output file
|
|
56
|
+
* @returns A Promise that resolves to a File of the cropped image
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```tsx
|
|
60
|
+
* const file = await cropToFile(
|
|
61
|
+
* {
|
|
62
|
+
* imageSrc: fileInput.files[0],
|
|
63
|
+
* cropArea: { x: 100, y: 100, width: 200, height: 200 },
|
|
64
|
+
* },
|
|
65
|
+
* 'cropped-image.jpg',
|
|
66
|
+
* );
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
async function cropToFile(options, filename) {
|
|
70
|
+
const blob = await cropToBlob(options);
|
|
71
|
+
return new File([blob], filename, { type: blob.type });
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Converts a cropped image area to a data URL.
|
|
75
|
+
*
|
|
76
|
+
* @param options - The cropping options
|
|
77
|
+
* @returns A Promise that resolves to a data URL string of the cropped image
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```tsx
|
|
81
|
+
* const dataUrl = await cropToDataURL({
|
|
82
|
+
* imageSrc: 'https://example.com/image.jpg',
|
|
83
|
+
* cropArea: { x: 100, y: 100, width: 200, height: 200 },
|
|
84
|
+
* format: 'image/jpeg',
|
|
85
|
+
* quality: 0.9,
|
|
86
|
+
* });
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
async function cropToDataURL(options) {
|
|
90
|
+
const { imageSrc, cropArea, canvas: providedCanvas, format = 'image/png', quality = 0.92, outputWidth, outputHeight, } = options;
|
|
91
|
+
// Load image
|
|
92
|
+
const img = await loadImage(imageSrc);
|
|
93
|
+
// Create or use provided canvas
|
|
94
|
+
const canvas = providedCanvas || document.createElement('canvas');
|
|
95
|
+
const ctx = canvas.getContext('2d');
|
|
96
|
+
if (!ctx) {
|
|
97
|
+
throw new Error('Failed to get canvas context');
|
|
98
|
+
}
|
|
99
|
+
// Crop area is already in image pixel space
|
|
100
|
+
const actualCropX = cropArea.x;
|
|
101
|
+
const actualCropY = cropArea.y;
|
|
102
|
+
const actualCropWidth = cropArea.width;
|
|
103
|
+
const actualCropHeight = cropArea.height;
|
|
104
|
+
// Set canvas size to output dimensions or crop area dimensions
|
|
105
|
+
const finalWidth = outputWidth || cropArea.width;
|
|
106
|
+
const finalHeight = outputHeight || cropArea.height;
|
|
107
|
+
canvas.width = finalWidth;
|
|
108
|
+
canvas.height = finalHeight;
|
|
109
|
+
// Draw the cropped portion of the image
|
|
110
|
+
ctx.drawImage(img, actualCropX, actualCropY, actualCropWidth, actualCropHeight, 0, 0, finalWidth, finalHeight);
|
|
111
|
+
return canvas.toDataURL(format, quality);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Helper function to load an image from various sources.
|
|
115
|
+
*/
|
|
116
|
+
async function loadImage(src) {
|
|
117
|
+
return new Promise((resolve, reject) => {
|
|
118
|
+
const img = new Image();
|
|
119
|
+
let objectUrl = null;
|
|
120
|
+
img.crossOrigin = 'anonymous';
|
|
121
|
+
img.onload = () => {
|
|
122
|
+
if (objectUrl) {
|
|
123
|
+
URL.revokeObjectURL(objectUrl);
|
|
124
|
+
}
|
|
125
|
+
resolve(img);
|
|
126
|
+
};
|
|
127
|
+
img.onerror = (error) => {
|
|
128
|
+
if (objectUrl) {
|
|
129
|
+
URL.revokeObjectURL(objectUrl);
|
|
130
|
+
}
|
|
131
|
+
reject(error);
|
|
132
|
+
};
|
|
133
|
+
if (typeof src === 'string') {
|
|
134
|
+
img.src = src;
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
objectUrl = URL.createObjectURL(src);
|
|
138
|
+
img.src = objectUrl;
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export { cropToBlob, cropToDataURL, cropToFile };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { CropperSize } from '@mezzanine-ui/core/cropper';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
export type CropperComponent = 'div' | 'span';
|
|
4
|
+
export type CropperElementComponent = 'canvas';
|
|
5
|
+
export interface CropperPropsBase {
|
|
6
|
+
/**
|
|
7
|
+
* The size of cropper.
|
|
8
|
+
* @default 'main'
|
|
9
|
+
*/
|
|
10
|
+
size?: CropperSize;
|
|
11
|
+
/**
|
|
12
|
+
* The cropper content.
|
|
13
|
+
*/
|
|
14
|
+
children?: ReactNode;
|
|
15
|
+
/**
|
|
16
|
+
* The image source to crop.
|
|
17
|
+
* Can be a URL string, File, or Blob.
|
|
18
|
+
*/
|
|
19
|
+
imageSrc?: string | File | Blob;
|
|
20
|
+
/**
|
|
21
|
+
* Callback fired when the crop area changes.
|
|
22
|
+
*/
|
|
23
|
+
onCropChange?: (cropArea: CropArea) => void;
|
|
24
|
+
/**
|
|
25
|
+
* Callback fired when crop area drag ends.
|
|
26
|
+
*/
|
|
27
|
+
onCropDragEnd?: (cropArea: CropArea) => void;
|
|
28
|
+
/**
|
|
29
|
+
* Callback fired when image drag ends.
|
|
30
|
+
*/
|
|
31
|
+
onImageDragEnd?: () => void;
|
|
32
|
+
/**
|
|
33
|
+
* Callback fired when scale (zoom) changes.
|
|
34
|
+
*/
|
|
35
|
+
onScaleChange?: (scale: number) => void;
|
|
36
|
+
/**
|
|
37
|
+
* Callback fired when image loads successfully.
|
|
38
|
+
*/
|
|
39
|
+
onImageLoad?: () => void;
|
|
40
|
+
/**
|
|
41
|
+
* Callback fired when image fails to load.
|
|
42
|
+
*/
|
|
43
|
+
onImageError?: (error: Error) => void;
|
|
44
|
+
/**
|
|
45
|
+
* Initial crop area.
|
|
46
|
+
*/
|
|
47
|
+
initialCropArea?: CropArea;
|
|
48
|
+
/**
|
|
49
|
+
* Aspect ratio for the crop area (width / height).
|
|
50
|
+
* If not provided, free aspect ratio is allowed.
|
|
51
|
+
*/
|
|
52
|
+
aspectRatio?: number;
|
|
53
|
+
/**
|
|
54
|
+
* Minimum crop area width in pixels.
|
|
55
|
+
* @default 50
|
|
56
|
+
*/
|
|
57
|
+
minWidth?: number;
|
|
58
|
+
/**
|
|
59
|
+
* Minimum crop area height in pixels.
|
|
60
|
+
* @default 50
|
|
61
|
+
*/
|
|
62
|
+
minHeight?: number;
|
|
63
|
+
}
|
|
64
|
+
export interface CropArea {
|
|
65
|
+
x: number;
|
|
66
|
+
y: number;
|
|
67
|
+
width: number;
|
|
68
|
+
height: number;
|
|
69
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { CropArea } from '../typings';
|
|
2
|
+
export interface ImagePosition {
|
|
3
|
+
offsetX: number;
|
|
4
|
+
offsetY: number;
|
|
5
|
+
}
|
|
6
|
+
export interface BaseDisplaySize {
|
|
7
|
+
width: number;
|
|
8
|
+
height: number;
|
|
9
|
+
}
|
|
10
|
+
export interface InitialCropAreaResult {
|
|
11
|
+
baseDisplayHeight: number;
|
|
12
|
+
baseDisplayWidth: number;
|
|
13
|
+
cropArea: CropArea;
|
|
14
|
+
imagePosition: ImagePosition;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Calculate base scale for image to fit canvas height.
|
|
18
|
+
*/
|
|
19
|
+
export declare function getBaseScale(rect: DOMRect, img: HTMLImageElement): number;
|
|
20
|
+
/**
|
|
21
|
+
* Calculate base display size of image.
|
|
22
|
+
*/
|
|
23
|
+
export declare function getBaseDisplaySize(rect: DOMRect, img: HTMLImageElement): BaseDisplaySize;
|
|
24
|
+
/**
|
|
25
|
+
* Calculate initial crop area and image position.
|
|
26
|
+
*/
|
|
27
|
+
export declare function calculateInitialCropArea(img: HTMLImageElement, rect: DOMRect, aspectRatio?: number): InitialCropAreaResult;
|
|
28
|
+
/**
|
|
29
|
+
* Constrain image position to ensure it covers crop area.
|
|
30
|
+
*/
|
|
31
|
+
export declare function constrainImagePosition(newOffsetX: number, newOffsetY: number, displayWidth: number, displayHeight: number, cropArea: CropArea): ImagePosition;
|
|
32
|
+
/**
|
|
33
|
+
* Check if two crop areas are similar (within threshold).
|
|
34
|
+
*/
|
|
35
|
+
export declare function isCropAreaSimilar(a: CropArea | null, b: CropArea | null, threshold?: number): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Check if two image positions are similar (within threshold).
|
|
38
|
+
*/
|
|
39
|
+
export declare function isImagePositionSimilar(a: ImagePosition | null, b: ImagePosition | null, threshold?: number): boolean;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calculate base scale for image to fit canvas height.
|
|
3
|
+
*/
|
|
4
|
+
function getBaseScale(rect, img) {
|
|
5
|
+
if (!rect.height)
|
|
6
|
+
return 1;
|
|
7
|
+
return img.height / rect.height;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Calculate base display size of image.
|
|
11
|
+
*/
|
|
12
|
+
function getBaseDisplaySize(rect, img) {
|
|
13
|
+
const baseScale = getBaseScale(rect, img);
|
|
14
|
+
return {
|
|
15
|
+
width: img.width / baseScale,
|
|
16
|
+
height: img.height / baseScale,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Calculate initial crop area and image position.
|
|
21
|
+
*/
|
|
22
|
+
function calculateInitialCropArea(img, rect, aspectRatio) {
|
|
23
|
+
const baseScale = getBaseScale(rect, img);
|
|
24
|
+
const baseDisplayWidth = img.width / baseScale;
|
|
25
|
+
const baseDisplayHeight = img.height / baseScale;
|
|
26
|
+
const initialOffsetX = (rect.width - baseDisplayWidth) / 2;
|
|
27
|
+
const initialOffsetY = (rect.height - baseDisplayHeight) / 2;
|
|
28
|
+
let initialWidth = baseDisplayWidth;
|
|
29
|
+
let initialHeight = baseDisplayHeight;
|
|
30
|
+
if (aspectRatio) {
|
|
31
|
+
const maxWidthByHeight = baseDisplayHeight * aspectRatio;
|
|
32
|
+
const maxHeightByWidth = baseDisplayWidth / aspectRatio;
|
|
33
|
+
if (maxWidthByHeight <= baseDisplayWidth) {
|
|
34
|
+
initialWidth = maxWidthByHeight;
|
|
35
|
+
initialHeight = baseDisplayHeight;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
initialWidth = baseDisplayWidth;
|
|
39
|
+
initialHeight = maxHeightByWidth;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const initialX = initialOffsetX + (baseDisplayWidth - initialWidth) / 2;
|
|
43
|
+
const initialY = initialOffsetY + (baseDisplayHeight - initialHeight) / 2;
|
|
44
|
+
return {
|
|
45
|
+
baseDisplayHeight,
|
|
46
|
+
baseDisplayWidth,
|
|
47
|
+
cropArea: {
|
|
48
|
+
height: initialHeight,
|
|
49
|
+
width: initialWidth,
|
|
50
|
+
x: initialX,
|
|
51
|
+
y: initialY,
|
|
52
|
+
},
|
|
53
|
+
imagePosition: {
|
|
54
|
+
offsetX: initialOffsetX,
|
|
55
|
+
offsetY: initialOffsetY,
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Constrain image position to ensure it covers crop area.
|
|
61
|
+
*/
|
|
62
|
+
function constrainImagePosition(newOffsetX, newOffsetY, displayWidth, displayHeight, cropArea) {
|
|
63
|
+
const { x: cx, y: cy, width: cw, height: ch } = cropArea;
|
|
64
|
+
// Ensure image always covers crop area (no white space in crop area)
|
|
65
|
+
const minOffsetX = cx + cw - displayWidth;
|
|
66
|
+
const maxOffsetX = cx;
|
|
67
|
+
const minOffsetY = cy + ch - displayHeight;
|
|
68
|
+
const maxOffsetY = cy;
|
|
69
|
+
return {
|
|
70
|
+
offsetX: Math.max(minOffsetX, Math.min(newOffsetX, maxOffsetX)),
|
|
71
|
+
offsetY: Math.max(minOffsetY, Math.min(newOffsetY, maxOffsetY)),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Check if two crop areas are similar (within threshold).
|
|
76
|
+
*/
|
|
77
|
+
function isCropAreaSimilar(a, b, threshold = 0.5) {
|
|
78
|
+
if (!a || !b)
|
|
79
|
+
return a === b;
|
|
80
|
+
return (Math.abs(a.x - b.x) < threshold &&
|
|
81
|
+
Math.abs(a.y - b.y) < threshold &&
|
|
82
|
+
Math.abs(a.width - b.width) < threshold &&
|
|
83
|
+
Math.abs(a.height - b.height) < threshold);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Check if two image positions are similar (within threshold).
|
|
87
|
+
*/
|
|
88
|
+
function isImagePositionSimilar(a, b, threshold = 0.1) {
|
|
89
|
+
if (!a || !b)
|
|
90
|
+
return a === b;
|
|
91
|
+
return (Math.abs(a.offsetX - b.offsetX) < threshold &&
|
|
92
|
+
Math.abs(a.offsetY - b.offsetY) < threshold);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export { calculateInitialCropArea, constrainImagePosition, getBaseDisplaySize, getBaseScale, isCropAreaSimilar, isImagePositionSimilar };
|
|
@@ -3,7 +3,7 @@ import { DatePickerCalendarProps } from '../DatePicker';
|
|
|
3
3
|
import { PickerTriggerWithSeparatorProps } from '../Picker';
|
|
4
4
|
import { TimePickerPanelProps } from '../TimePicker';
|
|
5
5
|
type FocusedInput = 'left' | 'right' | null;
|
|
6
|
-
export interface DateTimePickerProps extends Omit<DatePickerCalendarProps, 'anchor' | 'onChange' | 'open' | 'referenceDate' | 'value'>, Omit<TimePickerPanelProps, 'anchor' | 'onChange' | 'open' | 'popperProps' | 'value'>, Omit<PickerTriggerWithSeparatorProps, 'formatLeft' | 'formatRight' | 'inputLeftRef' | 'inputRightRef' | 'onBlurLeft' | 'onBlurRight' | 'onChangeLeft' | 'onChangeRight' | 'onFocusLeft' | 'onFocusRight' | 'onLeftComplete' | 'onRightComplete' | 'suffix' | 'valueLeft' | 'valueRight'> {
|
|
6
|
+
export interface DateTimePickerProps extends Omit<DatePickerCalendarProps, 'anchor' | 'onChange' | 'open' | 'referenceDate' | 'value'>, Omit<TimePickerPanelProps, 'anchor' | 'onChange' | 'open' | 'popperProps' | 'value'>, Omit<PickerTriggerWithSeparatorProps, 'formatLeft' | 'formatRight' | 'inputLeftRef' | 'inputRightRef' | 'onBlurLeft' | 'onBlurRight' | 'onChangeLeft' | 'onChangeRight' | 'onFocusLeft' | 'onFocusRight' | 'onLeftComplete' | 'onPasteIsoValueLeft' | 'onPasteIsoValueRight' | 'onRightComplete' | 'suffix' | 'valueLeft' | 'valueRight'> {
|
|
7
7
|
/**
|
|
8
8
|
* Default value for date-time picker.
|
|
9
9
|
*/
|
|
@@ -153,6 +153,19 @@ const DateTimePicker = forwardRef(function DateTimePicker(props, ref) {
|
|
|
153
153
|
notifyChange(dateValue, isoValue);
|
|
154
154
|
}
|
|
155
155
|
}, [dateValue, isValid, notifyChange]);
|
|
156
|
+
const onPasteIsoValueLeft = useCallback((isoValue) => {
|
|
157
|
+
if (!timeValue && isValid(isoValue)) {
|
|
158
|
+
// Time is empty, update it from pasted value
|
|
159
|
+
setTimeValue(isoValue);
|
|
160
|
+
}
|
|
161
|
+
}, [isValid, timeValue]);
|
|
162
|
+
const onPasteIsoValueRight = useCallback((isoValue) => {
|
|
163
|
+
if (!dateValue && isValid(isoValue)) {
|
|
164
|
+
// Date is empty, update it from pasted value
|
|
165
|
+
setDateValue(isoValue);
|
|
166
|
+
setReferenceDate(startOf(isoValue, 'day'));
|
|
167
|
+
}
|
|
168
|
+
}, [dateValue, isValid, startOf]);
|
|
156
169
|
const onCalendarChange = useCallback((target) => {
|
|
157
170
|
setDateValue(target);
|
|
158
171
|
setReferenceDate(startOf(target, 'day'));
|
|
@@ -204,7 +217,7 @@ const DateTimePicker = forwardRef(function DateTimePicker(props, ref) {
|
|
|
204
217
|
}
|
|
205
218
|
}, [disabled, focusedInput, onPanelToggle, readOnly]);
|
|
206
219
|
const suffix = (jsx(Icon, { "aria-label": "Open calendar", icon: CalendarTimeIcon, onClick: onCalendarIconClick }));
|
|
207
|
-
return (jsxs(Fragment, { children: [jsx(PickerTriggerWithSeparator, { ...restTriggerProps, ref: triggerComposedRef, className: className, clearable: clearable, disabled: disabled, error: error, formatLeft: formatDate, formatRight: formatTime, fullWidth: fullWidth, inputLeftRef: inputLeftRef, inputRightRef: inputRightRef, onBlurLeft: () => { }, onBlurRight: () => { }, onChangeLeft: onChangeLeft, onChangeRight: onChangeRight, onClear: onClear, onFocusLeft: onFocusLeft, onFocusRight: onFocusRight, onLeftComplete: onLeftComplete, onRightComplete: onRightComplete, placeholderLeft: placeholderLeft, placeholderRight: placeholderRight, prefix: prefix, readOnly: readOnly, required: required, size: size, suffix: suffix, valueLeft: displayDateValue, valueRight: displayTimeValue }), jsx(DatePickerCalendar, { ref: calendarPanelRef, anchor: anchorRef, calendarProps: calendarProps, calendarRef: calendarRef, disabledMonthSwitch: disabledMonthSwitch, disableOnDoubleNext: disableOnDoubleNext, disableOnDoublePrev: disableOnDoublePrev, disableOnNext: disableOnNext, disableOnPrev: disableOnPrev, disabledYearSwitch: disabledYearSwitch, displayMonthLocale: displayMonthLocale, fadeProps: fadeProps, isDateDisabled: isDateDisabled, isHalfYearDisabled: isHalfYearDisabled, isMonthDisabled: isMonthDisabled, isQuarterDisabled: isQuarterDisabled, isWeekDisabled: isWeekDisabled, isYearDisabled: isYearDisabled, mode: mode, onChange: onCalendarChange, open: openCalendar, popperProps: popperProps, referenceDate: referenceDate, value: dateValue }), jsx(TimePickerPanel, { ref: timePanelRef, anchor: anchorRef, fadeProps: fadeProps, hideHour: hideHour, hideMinute: hideMinute, hideSecond: hideSecond, hourStep: hourStep, minuteStep: minuteStep, onChange: onTimePanelChange, open: openTimePanel, popperProps: popperPropsTime, secondStep: secondStep, value: timeValue })] }));
|
|
220
|
+
return (jsxs(Fragment, { children: [jsx(PickerTriggerWithSeparator, { ...restTriggerProps, ref: triggerComposedRef, className: className, clearable: clearable, disabled: disabled, error: error, formatLeft: formatDate, formatRight: formatTime, fullWidth: fullWidth, inputLeftRef: inputLeftRef, inputRightRef: inputRightRef, onBlurLeft: () => { }, onBlurRight: () => { }, onChangeLeft: onChangeLeft, onChangeRight: onChangeRight, onClear: onClear, onFocusLeft: onFocusLeft, onFocusRight: onFocusRight, onLeftComplete: onLeftComplete, onPasteIsoValueLeft: onPasteIsoValueLeft, onPasteIsoValueRight: onPasteIsoValueRight, onRightComplete: onRightComplete, placeholderLeft: placeholderLeft, placeholderRight: placeholderRight, prefix: prefix, readOnly: readOnly, required: required, size: size, suffix: suffix, valueLeft: displayDateValue, valueRight: displayTimeValue }), jsx(DatePickerCalendar, { ref: calendarPanelRef, anchor: anchorRef, calendarProps: calendarProps, calendarRef: calendarRef, disabledMonthSwitch: disabledMonthSwitch, disableOnDoubleNext: disableOnDoubleNext, disableOnDoublePrev: disableOnDoublePrev, disableOnNext: disableOnNext, disableOnPrev: disableOnPrev, disabledYearSwitch: disabledYearSwitch, displayMonthLocale: displayMonthLocale, fadeProps: fadeProps, isDateDisabled: isDateDisabled, isHalfYearDisabled: isHalfYearDisabled, isMonthDisabled: isMonthDisabled, isQuarterDisabled: isQuarterDisabled, isWeekDisabled: isWeekDisabled, isYearDisabled: isYearDisabled, mode: mode, onChange: onCalendarChange, open: openCalendar, popperProps: popperProps, referenceDate: referenceDate, value: dateValue }), jsx(TimePickerPanel, { ref: timePanelRef, anchor: anchorRef, fadeProps: fadeProps, hideHour: hideHour, hideMinute: hideMinute, hideSecond: hideSecond, hourStep: hourStep, minuteStep: minuteStep, onChange: onTimePanelChange, open: openTimePanel, popperProps: popperPropsTime, secondStep: secondStep, value: timeValue })] }));
|
|
208
221
|
});
|
|
209
222
|
|
|
210
223
|
export { DateTimePicker as default };
|
package/Dropdown/Dropdown.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ReactElement } from 'react';
|
|
2
|
-
import { DropdownInputPosition, DropdownItemSharedProps, DropdownOption, DropdownStatus as DropdownStatusType, DropdownType } from '@mezzanine-ui/core/dropdown/dropdown';
|
|
2
|
+
import { DropdownInputPosition, DropdownItemSharedProps, DropdownLoadingPosition, DropdownOption, DropdownStatus as DropdownStatusType, DropdownType } from '@mezzanine-ui/core/dropdown/dropdown';
|
|
3
3
|
import { ButtonProps } from '../Button';
|
|
4
4
|
import { InputProps } from '../Input';
|
|
5
5
|
import { PopperPlacement } from '../Popper';
|
|
@@ -162,6 +162,12 @@ export interface DropdownProps extends DropdownItemSharedProps {
|
|
|
162
162
|
* The icon of the dropdown empty status.
|
|
163
163
|
*/
|
|
164
164
|
emptyIcon?: IconDefinition;
|
|
165
|
+
/**
|
|
166
|
+
* The position to display the loading status.
|
|
167
|
+
* Only takes effect when `status === 'loading'`.
|
|
168
|
+
* @default 'full'
|
|
169
|
+
*/
|
|
170
|
+
loadingPosition?: DropdownLoadingPosition;
|
|
165
171
|
/**
|
|
166
172
|
* Whether to enable portal.
|
|
167
173
|
* This prop is only relevant when `inputPosition` is set to 'outside'.
|
package/Dropdown/Dropdown.js
CHANGED
|
@@ -13,8 +13,19 @@ import { composeRefs } from '../utils/composeRefs.js';
|
|
|
13
13
|
import DropdownItem from './DropdownItem.js';
|
|
14
14
|
import Popper from '../Popper/Popper.js';
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Extracts ref from a ReactElement, supporting both React 18 and 19.
|
|
18
|
+
* In React 18, ref is on the element itself; in React 19, ref is in props.
|
|
19
|
+
*/
|
|
20
|
+
function getElementRef(element) {
|
|
21
|
+
var _a;
|
|
22
|
+
// React 19: ref is in props
|
|
23
|
+
const propsRef = (_a = element.props) === null || _a === void 0 ? void 0 : _a.ref;
|
|
24
|
+
// React 18: ref is on the element itself
|
|
25
|
+
return propsRef !== null && propsRef !== void 0 ? propsRef : element.ref;
|
|
26
|
+
}
|
|
16
27
|
function Dropdown(props) {
|
|
17
|
-
const { activeIndex: activeIndexProp, id, children, options = [], type = 'default', maxHeight, disabled = false, showDropdownActions = false, actionCancelText, actionConfirmText, actionText, actionClearText, actionCustomButtonProps, showActionShowTopBar, isMatchInputValue = false, inputPosition = 'outside', placement = 'bottom', customWidth, sameWidth = false, listboxId: listboxIdProp, listboxLabel, onClose, onOpen, open: openProp, onVisibilityChange, onSelect, onActionConfirm, onActionCancel, onActionCustom, onActionClear, onItemHover, zIndex, status, loadingText, emptyText, emptyIcon, followText: followTextProp, globalPortal = true, onReachBottom, onLeaveBottom, onScroll, mode, value, scrollbarDefer, scrollbarDisabled, scrollbarMaxWidth, scrollbarOptions, } = props;
|
|
28
|
+
const { activeIndex: activeIndexProp, id, children, options = [], type = 'default', maxHeight, disabled = false, showDropdownActions = false, actionCancelText, actionConfirmText, actionText, actionClearText, actionCustomButtonProps, showActionShowTopBar, isMatchInputValue = false, inputPosition = 'outside', placement = 'bottom', 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;
|
|
18
29
|
const isInline = inputPosition === 'inside';
|
|
19
30
|
const inputId = useId();
|
|
20
31
|
const defaultListboxId = `${inputId}-listbox`;
|
|
@@ -179,8 +190,8 @@ function Dropdown(props) {
|
|
|
179
190
|
const popperControllerRef = useRef(null);
|
|
180
191
|
// Extract combobox props logic to avoid duplication
|
|
181
192
|
const getComboboxProps = useMemo(() => {
|
|
182
|
-
|
|
183
|
-
const isInput =
|
|
193
|
+
// Only access the type property to check if it's a Button component
|
|
194
|
+
const isInput = children.type !== Button;
|
|
184
195
|
if (!isInput)
|
|
185
196
|
return {};
|
|
186
197
|
return {
|
|
@@ -216,6 +227,7 @@ function Dropdown(props) {
|
|
|
216
227
|
loadingText,
|
|
217
228
|
emptyText,
|
|
218
229
|
emptyIcon,
|
|
230
|
+
loadingPosition,
|
|
219
231
|
mode,
|
|
220
232
|
value,
|
|
221
233
|
scrollbarDefer,
|
|
@@ -242,6 +254,7 @@ function Dropdown(props) {
|
|
|
242
254
|
loadingText,
|
|
243
255
|
emptyText,
|
|
244
256
|
emptyIcon,
|
|
257
|
+
loadingPosition,
|
|
245
258
|
mode,
|
|
246
259
|
value,
|
|
247
260
|
scrollbarDefer,
|
|
@@ -251,13 +264,15 @@ function Dropdown(props) {
|
|
|
251
264
|
]);
|
|
252
265
|
const triggerElement = useMemo(() => {
|
|
253
266
|
const childWithRef = children;
|
|
254
|
-
const
|
|
267
|
+
const childProps = childWithRef.props;
|
|
268
|
+
const childRef = getElementRef(childWithRef);
|
|
269
|
+
const composedRef = composeRefs([anchorRef, childRef]);
|
|
270
|
+
const originalOnClick = childProps.onClick;
|
|
255
271
|
return cloneElement(childWithRef, {
|
|
256
272
|
ref: composedRef,
|
|
257
273
|
...getComboboxProps,
|
|
258
274
|
onClick: (event) => {
|
|
259
|
-
|
|
260
|
-
(_b = (_a = childWithRef.props) === null || _a === void 0 ? void 0 : _a.onClick) === null || _b === void 0 ? void 0 : _b.call(_a, event);
|
|
275
|
+
originalOnClick === null || originalOnClick === void 0 ? void 0 : originalOnClick(event);
|
|
261
276
|
if (event === null || event === void 0 ? void 0 : event.defaultPrevented)
|
|
262
277
|
return;
|
|
263
278
|
if (!isInline) {
|
|
@@ -271,13 +286,17 @@ function Dropdown(props) {
|
|
|
271
286
|
return null;
|
|
272
287
|
}
|
|
273
288
|
const childWithRef = children;
|
|
274
|
-
const
|
|
289
|
+
const childProps = childWithRef.props;
|
|
290
|
+
const childRef = getElementRef(childWithRef);
|
|
291
|
+
const composedRef = composeRefs([childRef]);
|
|
292
|
+
const originalOnBlur = childProps.onBlur;
|
|
293
|
+
const originalOnClick = childProps.onClick;
|
|
294
|
+
const originalOnFocus = childProps.onFocus;
|
|
275
295
|
return cloneElement(childWithRef, {
|
|
276
296
|
ref: composedRef,
|
|
277
297
|
...getComboboxProps,
|
|
278
298
|
onBlur: (event) => {
|
|
279
|
-
|
|
280
|
-
(_b = (_a = childWithRef.props) === null || _a === void 0 ? void 0 : _a.onBlur) === null || _b === void 0 ? void 0 : _b.call(_a, event);
|
|
299
|
+
originalOnBlur === null || originalOnBlur === void 0 ? void 0 : originalOnBlur(event);
|
|
281
300
|
if (event === null || event === void 0 ? void 0 : event.defaultPrevented)
|
|
282
301
|
return;
|
|
283
302
|
// When open is controlled, don't automatically close on blur
|
|
@@ -295,21 +314,19 @@ function Dropdown(props) {
|
|
|
295
314
|
setOpen(false);
|
|
296
315
|
},
|
|
297
316
|
onClick: (event) => {
|
|
298
|
-
|
|
299
|
-
(_b = (_a = childWithRef.props) === null || _a === void 0 ? void 0 : _a.onClick) === null || _b === void 0 ? void 0 : _b.call(_a, event);
|
|
317
|
+
originalOnClick === null || originalOnClick === void 0 ? void 0 : originalOnClick(event);
|
|
300
318
|
if (event === null || event === void 0 ? void 0 : event.defaultPrevented)
|
|
301
319
|
return;
|
|
302
320
|
setOpen(true);
|
|
303
321
|
},
|
|
304
322
|
onFocus: (event) => {
|
|
305
|
-
|
|
306
|
-
(_b = (_a = childWithRef.props) === null || _a === void 0 ? void 0 : _a.onFocus) === null || _b === void 0 ? void 0 : _b.call(_a, event);
|
|
323
|
+
originalOnFocus === null || originalOnFocus === void 0 ? void 0 : originalOnFocus(event);
|
|
307
324
|
if (event === null || event === void 0 ? void 0 : event.defaultPrevented)
|
|
308
325
|
return;
|
|
309
326
|
setOpen(true);
|
|
310
327
|
},
|
|
311
328
|
});
|
|
312
|
-
}, [children, getComboboxProps, isInline,
|
|
329
|
+
}, [children, getComboboxProps, isInline, isOpenControlled, setOpen]);
|
|
313
330
|
useDocumentEvents(() => {
|
|
314
331
|
if (!isOpen) {
|
|
315
332
|
return;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
-
import { DropdownItemSharedProps, DropdownOptionsByType, DropdownStatus as DropdownStatusType, DropdownType } from '@mezzanine-ui/core/dropdown/dropdown';
|
|
2
|
+
import { DropdownItemSharedProps, DropdownLoadingPosition, DropdownOptionsByType, DropdownStatus as DropdownStatusType, DropdownType } from '@mezzanine-ui/core/dropdown/dropdown';
|
|
3
3
|
import { type IconDefinition } from '@mezzanine-ui/icons';
|
|
4
4
|
import type { PartialOptions } from 'overlayscrollbars';
|
|
5
5
|
import { type DropdownActionProps } from './DropdownAction';
|
|
@@ -74,6 +74,12 @@ export interface DropdownItemProps<T extends DropdownType | undefined = Dropdown
|
|
|
74
74
|
* The icon of the dropdown empty status.
|
|
75
75
|
*/
|
|
76
76
|
emptyIcon?: IconDefinition;
|
|
77
|
+
/**
|
|
78
|
+
* The position to display the loading status.
|
|
79
|
+
* Only takes effect when `status === 'loading'`.
|
|
80
|
+
* @default 'full'
|
|
81
|
+
*/
|
|
82
|
+
loadingPosition?: DropdownLoadingPosition;
|
|
77
83
|
/**
|
|
78
84
|
* Callback fired when the dropdown list reaches the bottom.
|
|
79
85
|
* Only fires when `maxHeight` is set and the list is scrollable.
|