@duskmoon-dev/components 0.3.3 → 0.4.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/README.md +61 -2
- package/dist/classes/chat.d.ts +9 -1
- package/dist/classes/console-page.d.ts +16 -0
- package/dist/classes/dropdown.d.ts +5 -5
- package/dist/classes/fab.d.ts +11 -0
- package/dist/classes/index.d.ts +5 -0
- package/dist/classes/index.js +180 -34
- package/dist/classes/megamenu.d.ts +10 -0
- package/dist/classes/otp-input.d.ts +12 -0
- package/dist/classes/popover.d.ts +1 -3
- package/dist/classes/swap.d.ts +12 -0
- package/dist/classes/tree-select.d.ts +6 -6
- package/dist/components/app/index.js +128 -68
- package/dist/components/avatar/Avatar.types.d.ts +1 -1
- package/dist/components/avatar/index.js +2 -1
- package/dist/components/badge/index.js +1 -1
- package/dist/components/button/Button.d.ts +1 -1
- package/dist/components/button/Button.types.d.ts +8 -0
- package/dist/components/button/index.js +253 -24
- package/dist/components/calendar/index.js +44 -19
- package/dist/components/chat/Chat.d.ts +9 -1
- package/dist/components/chat/Chat.types.d.ts +26 -0
- package/dist/components/chat/index.js +92 -3
- package/dist/components/color-picker/ColorPicker.types.d.ts +2 -1
- package/dist/components/color-picker/index.js +206 -9
- package/dist/components/console-page/ConsolePage.d.ts +2 -0
- package/dist/components/console-page/ConsolePage.types.d.ts +29 -0
- package/dist/components/console-page/index.d.ts +2 -0
- package/dist/components/console-page/index.js +205 -0
- package/dist/components/date-picker/DatePicker.types.d.ts +1 -0
- package/dist/components/date-picker/index.js +537 -35
- package/dist/components/date-picker/usePickerDropdown.d.ts +17 -0
- package/dist/components/dm-date-picker/index.js +545 -43
- package/dist/components/dm-drawer/index.js +253 -24
- package/dist/components/dm-layout/index.js +391 -24
- package/dist/components/dm-menu/index.js +380 -13
- package/dist/components/dm-page-header/index.js +404 -114
- package/dist/components/dm-pro-table/index.js +1183 -368
- package/dist/components/dm-query/DmQuery.types.d.ts +1 -1
- package/dist/components/dm-query/index.js +931 -188
- package/dist/components/dm-search/DmSearch.types.d.ts +4 -0
- package/dist/components/dm-search/index.js +917 -163
- package/dist/components/dm-table/index.js +1001 -247
- package/dist/components/dm-toolbar/index.js +400 -110
- package/dist/components/dm-truncate/index.js +115 -35
- package/dist/components/dropdown/Dropdown.types.d.ts +1 -1
- package/dist/components/dropdown/index.js +400 -110
- package/dist/components/fab/Fab.d.ts +4 -0
- package/dist/components/fab/Fab.types.d.ts +25 -0
- package/dist/components/fab/index.d.ts +2 -0
- package/dist/components/fab/index.js +480 -0
- package/dist/components/form/Form.types.d.ts +1 -0
- package/dist/components/form/index.js +14 -3
- package/dist/components/megamenu/Megamenu.d.ts +2 -0
- package/dist/components/megamenu/Megamenu.types.d.ts +32 -0
- package/dist/components/megamenu/index.d.ts +2 -0
- package/dist/components/megamenu/index.js +214 -0
- package/dist/components/modal/index.js +128 -68
- package/dist/components/otp-input/OtpInput.d.ts +2 -0
- package/dist/components/otp-input/OtpInput.types.d.ts +16 -0
- package/dist/components/otp-input/index.d.ts +2 -0
- package/dist/components/otp-input/index.js +112 -0
- package/dist/components/popconfirm/index.js +255 -26
- package/dist/components/popover/index.js +24 -4
- package/dist/components/swap/Swap.d.ts +3 -0
- package/dist/components/swap/Swap.types.d.ts +22 -0
- package/dist/components/swap/index.d.ts +2 -0
- package/dist/components/swap/index.js +109 -0
- package/dist/components/time-picker/TimePicker.types.d.ts +1 -0
- package/dist/components/time-picker/index.js +167 -29
- package/dist/components/tooltip/Tooltip.types.d.ts +4 -0
- package/dist/components/tooltip/index.js +107 -27
- package/dist/components/tour/index.js +253 -24
- package/dist/components/tree-select/index.js +8 -8
- package/dist/components/upload/Upload.types.d.ts +1 -0
- package/dist/components/upload/index.js +2 -0
- package/dist/generated/version.d.ts +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.js +3330 -1632
- package/dist/infrastructure.js +1 -1
- package/dist/styles.css +1190 -906
- package/package.json +23 -3
|
@@ -5,7 +5,9 @@ import {
|
|
|
5
5
|
cloneElement,
|
|
6
6
|
forwardRef,
|
|
7
7
|
isValidElement,
|
|
8
|
+
useEffect,
|
|
8
9
|
useId,
|
|
10
|
+
useRef,
|
|
9
11
|
useState
|
|
10
12
|
} from "react";
|
|
11
13
|
|
|
@@ -35,29 +37,25 @@ function cn(...inputs) {
|
|
|
35
37
|
return clsx(inputs);
|
|
36
38
|
}
|
|
37
39
|
// src/classes/dropdown.ts
|
|
38
|
-
var dropdownWrapperClass = "dropdown
|
|
39
|
-
var dropdownBaseClass = "
|
|
40
|
-
var
|
|
41
|
-
var dropdownArrowClass = "popover-arrow dropdown-arrow";
|
|
40
|
+
var dropdownWrapperClass = "dropdown";
|
|
41
|
+
var dropdownBaseClass = "dropdown-content";
|
|
42
|
+
var dropdownArrowClass = "dropdown-arrow";
|
|
42
43
|
var dropdownMenuClass = "menu dropdown-menu";
|
|
43
44
|
var dropdownButtonClass = "dropdown-button";
|
|
44
45
|
var dropdownPlacementClasses = {
|
|
45
|
-
top: "
|
|
46
|
-
bottom: "
|
|
47
|
-
left: "
|
|
48
|
-
right: "
|
|
49
|
-
topLeft: "
|
|
50
|
-
topRight: "
|
|
51
|
-
bottomLeft: "
|
|
52
|
-
bottomRight: "
|
|
46
|
+
top: "dropdown-block-start",
|
|
47
|
+
bottom: "dropdown-block-end",
|
|
48
|
+
left: "dropdown-inline-start",
|
|
49
|
+
right: "dropdown-inline-end",
|
|
50
|
+
topLeft: "dropdown-block-start",
|
|
51
|
+
topRight: "dropdown-block-start",
|
|
52
|
+
bottomLeft: "dropdown-block-end",
|
|
53
|
+
bottomRight: "dropdown-block-end"
|
|
53
54
|
};
|
|
54
55
|
function getDropdownClasses({
|
|
55
|
-
placement = "bottomLeft",
|
|
56
|
-
open,
|
|
57
|
-
arrow,
|
|
58
56
|
className
|
|
59
57
|
}) {
|
|
60
|
-
return cn(dropdownBaseClass,
|
|
58
|
+
return cn(dropdownBaseClass, className);
|
|
61
59
|
}
|
|
62
60
|
|
|
63
61
|
// src/classes/menu.ts
|
|
@@ -108,6 +106,10 @@ function getMenuItemClasses({
|
|
|
108
106
|
return cn(menuItemClass, active && menuItemActiveClass, disabled && menuItemDisabledClass, danger && "menu-item-danger", submenu && menuItemSubmenuClass, className);
|
|
109
107
|
}
|
|
110
108
|
|
|
109
|
+
// src/components/button/Button.tsx
|
|
110
|
+
import React from "react";
|
|
111
|
+
import { createPortal } from "react-dom";
|
|
112
|
+
|
|
111
113
|
// src/classes/button.ts
|
|
112
114
|
var buttonBaseClass = "btn";
|
|
113
115
|
var buttonColorClasses = {
|
|
@@ -131,7 +133,7 @@ var buttonAppearanceClasses = {
|
|
|
131
133
|
};
|
|
132
134
|
var buttonShapeClasses = {
|
|
133
135
|
rect: "",
|
|
134
|
-
circle: "btn-circle",
|
|
136
|
+
circle: "btn-circle btn-icon",
|
|
135
137
|
square: "btn-square"
|
|
136
138
|
};
|
|
137
139
|
var buttonSizeClasses = {
|
|
@@ -151,11 +153,14 @@ function getButtonClasses({
|
|
|
151
153
|
isLoading,
|
|
152
154
|
className
|
|
153
155
|
}) {
|
|
154
|
-
return cn(buttonBaseClass, buttonColorClasses[color], buttonAppearanceClasses[appearance], buttonShapeClasses[shape], buttonSizeClasses[size], block && buttonBlockClass, isLoading && buttonIsLoadingClass, className);
|
|
156
|
+
return cn(buttonBaseClass, buttonColorClasses[color], buttonAppearanceClasses[appearance], buttonShapeClasses[shape], buttonSizeClasses[size], shape === "circle" && size === "xs" && "btn-icon-sm", shape === "circle" && size === "sm" && "btn-icon-sm", shape === "circle" && size === "lg" && "btn-icon-lg", block && buttonBlockClass, isLoading && buttonIsLoadingClass, className);
|
|
155
157
|
}
|
|
156
158
|
|
|
157
159
|
// src/components/button/Button.tsx
|
|
158
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
160
|
+
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
161
|
+
function isPromiseLike(value) {
|
|
162
|
+
return value !== null && (typeof value === "object" || typeof value === "function") && typeof value.then === "function";
|
|
163
|
+
}
|
|
159
164
|
function Button({
|
|
160
165
|
color = "primary",
|
|
161
166
|
appearance = "filled",
|
|
@@ -169,8 +174,155 @@ function Button({
|
|
|
169
174
|
children,
|
|
170
175
|
disabled,
|
|
171
176
|
ref,
|
|
177
|
+
confirm,
|
|
178
|
+
onClick,
|
|
172
179
|
...props
|
|
173
180
|
}) {
|
|
181
|
+
const buttonRef = React.useRef(null);
|
|
182
|
+
const popoverRef = React.useRef(null);
|
|
183
|
+
const cancelRef = React.useRef(null);
|
|
184
|
+
const approvalRef = React.useRef("idle");
|
|
185
|
+
const pendingRef = React.useRef(false);
|
|
186
|
+
const actionRef = React.useRef(0);
|
|
187
|
+
const operationRef = React.useRef(0);
|
|
188
|
+
const mountedRef = React.useRef(false);
|
|
189
|
+
const [portalTarget, setPortalTarget] = React.useState(null);
|
|
190
|
+
const [confirmLoading, setConfirmLoading] = React.useState(false);
|
|
191
|
+
const [confirmError, setConfirmError] = React.useState(false);
|
|
192
|
+
const generatedId = React.useId().replace(/:/g, "");
|
|
193
|
+
const popoverId = `button-confirm-${generatedId}`;
|
|
194
|
+
const titleId = `${popoverId}-title`;
|
|
195
|
+
const descriptionId = `${popoverId}-description`;
|
|
196
|
+
const anchor = `--${popoverId}-anchor`;
|
|
197
|
+
const hasConfirm = Boolean(confirm);
|
|
198
|
+
const confirmation = confirm && typeof confirm === "object" ? confirm : undefined;
|
|
199
|
+
const title = confirmation ? confirmation.title : "Confirm action";
|
|
200
|
+
const hasTitle = title !== undefined && title !== null && title !== false && title !== "";
|
|
201
|
+
const content = confirmation?.component ?? confirmation?.message ?? confirmation?.description;
|
|
202
|
+
const hasContent = content !== undefined && content !== null && content !== false && content !== "";
|
|
203
|
+
const mergedRef = React.useCallback((node) => {
|
|
204
|
+
buttonRef.current = node;
|
|
205
|
+
if (!node) {
|
|
206
|
+
if (typeof ref === "function")
|
|
207
|
+
ref(null);
|
|
208
|
+
else if (ref)
|
|
209
|
+
ref.current = null;
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
const cleanup = typeof ref === "function" ? ref(node) : undefined;
|
|
213
|
+
if (ref && typeof ref !== "function")
|
|
214
|
+
ref.current = node;
|
|
215
|
+
return () => {
|
|
216
|
+
buttonRef.current = null;
|
|
217
|
+
if (typeof cleanup === "function")
|
|
218
|
+
cleanup();
|
|
219
|
+
else if (typeof ref === "function")
|
|
220
|
+
ref(null);
|
|
221
|
+
else if (ref)
|
|
222
|
+
ref.current = null;
|
|
223
|
+
};
|
|
224
|
+
}, [ref]);
|
|
225
|
+
React.useEffect(() => {
|
|
226
|
+
mountedRef.current = true;
|
|
227
|
+
return () => {
|
|
228
|
+
mountedRef.current = false;
|
|
229
|
+
operationRef.current += 1;
|
|
230
|
+
};
|
|
231
|
+
}, []);
|
|
232
|
+
React.useEffect(() => {
|
|
233
|
+
operationRef.current += 1;
|
|
234
|
+
approvalRef.current = "idle";
|
|
235
|
+
setConfirmError(false);
|
|
236
|
+
setPortalTarget(hasConfirm ? document.body : null);
|
|
237
|
+
}, [hasConfirm]);
|
|
238
|
+
function closePopover() {
|
|
239
|
+
if (popoverRef.current?.matches(":popover-open")) {
|
|
240
|
+
popoverRef.current.hidePopover();
|
|
241
|
+
}
|
|
242
|
+
buttonRef.current?.focus();
|
|
243
|
+
}
|
|
244
|
+
function handleClick(event) {
|
|
245
|
+
if (!confirm) {
|
|
246
|
+
onClick?.(event);
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
if (approvalRef.current === "native") {
|
|
250
|
+
approvalRef.current = "idle";
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
if (approvalRef.current === "action") {
|
|
254
|
+
approvalRef.current = "idle";
|
|
255
|
+
let result;
|
|
256
|
+
try {
|
|
257
|
+
result = onClick?.(event);
|
|
258
|
+
} catch {
|
|
259
|
+
event.preventDefault();
|
|
260
|
+
pendingRef.current = false;
|
|
261
|
+
setConfirmError(true);
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
if (!isPromiseLike(result)) {
|
|
265
|
+
pendingRef.current = false;
|
|
266
|
+
closePopover();
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
const userPreventedDefault = event.defaultPrevented;
|
|
270
|
+
event.preventDefault();
|
|
271
|
+
setConfirmLoading(true);
|
|
272
|
+
const action = actionRef.current;
|
|
273
|
+
const operation = operationRef.current;
|
|
274
|
+
Promise.resolve(result).then(() => {
|
|
275
|
+
if (!mountedRef.current || action !== actionRef.current)
|
|
276
|
+
return;
|
|
277
|
+
pendingRef.current = false;
|
|
278
|
+
setConfirmLoading(false);
|
|
279
|
+
if (operation !== operationRef.current)
|
|
280
|
+
return;
|
|
281
|
+
closePopover();
|
|
282
|
+
if (!userPreventedDefault && !buttonRef.current?.disabled) {
|
|
283
|
+
approvalRef.current = "native";
|
|
284
|
+
buttonRef.current?.click();
|
|
285
|
+
approvalRef.current = "idle";
|
|
286
|
+
}
|
|
287
|
+
}, () => {
|
|
288
|
+
if (!mountedRef.current || action !== actionRef.current)
|
|
289
|
+
return;
|
|
290
|
+
pendingRef.current = false;
|
|
291
|
+
setConfirmLoading(false);
|
|
292
|
+
if (operation !== operationRef.current)
|
|
293
|
+
return;
|
|
294
|
+
setConfirmError(true);
|
|
295
|
+
cancelRef.current?.focus();
|
|
296
|
+
});
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
event.preventDefault();
|
|
300
|
+
if (disabled || isLoading || pendingRef.current)
|
|
301
|
+
return;
|
|
302
|
+
if (popoverRef.current?.matches(":popover-open")) {
|
|
303
|
+
closePopover();
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
setConfirmError(false);
|
|
307
|
+
popoverRef.current?.showPopover();
|
|
308
|
+
cancelRef.current?.focus();
|
|
309
|
+
}
|
|
310
|
+
function handleConfirm(event) {
|
|
311
|
+
event.preventDefault();
|
|
312
|
+
event.stopPropagation();
|
|
313
|
+
const trigger = buttonRef.current;
|
|
314
|
+
if (disabled || isLoading || pendingRef.current || !trigger || trigger.disabled || !event.currentTarget.matches(":popover-open"))
|
|
315
|
+
return;
|
|
316
|
+
setConfirmError(false);
|
|
317
|
+
pendingRef.current = true;
|
|
318
|
+
actionRef.current += 1;
|
|
319
|
+
approvalRef.current = "action";
|
|
320
|
+
trigger.click();
|
|
321
|
+
if (approvalRef.current === "action") {
|
|
322
|
+
approvalRef.current = "idle";
|
|
323
|
+
pendingRef.current = false;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
174
326
|
const classes = getButtonClasses({
|
|
175
327
|
color,
|
|
176
328
|
appearance,
|
|
@@ -180,37 +332,109 @@ function Button({
|
|
|
180
332
|
isLoading,
|
|
181
333
|
className
|
|
182
334
|
});
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
...props,
|
|
335
|
+
const confirmClasses = getButtonClasses({
|
|
336
|
+
color,
|
|
337
|
+
size: "sm",
|
|
338
|
+
isLoading: confirmLoading
|
|
339
|
+
});
|
|
340
|
+
return /* @__PURE__ */ jsxs(Fragment, {
|
|
190
341
|
children: [
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
342
|
+
/* @__PURE__ */ jsxs("button", {
|
|
343
|
+
ref: confirm ? mergedRef : ref,
|
|
344
|
+
className: classes,
|
|
345
|
+
disabled: disabled || isLoading,
|
|
346
|
+
"aria-busy": isLoading,
|
|
347
|
+
"aria-disabled": disabled || isLoading,
|
|
348
|
+
...props,
|
|
349
|
+
style: confirm ? { ...props.style, anchorName: anchor } : props.style,
|
|
350
|
+
"aria-haspopup": confirm ? "dialog" : props["aria-haspopup"],
|
|
351
|
+
"aria-controls": confirm ? popoverId : props["aria-controls"],
|
|
352
|
+
onClick: confirm ? handleClick : onClick,
|
|
353
|
+
children: [
|
|
354
|
+
isLoading && /* @__PURE__ */ jsx("span", {
|
|
355
|
+
className: "btn-spinner"
|
|
356
|
+
}),
|
|
357
|
+
!isLoading && leftIcon && /* @__PURE__ */ jsx("span", {
|
|
358
|
+
className: "btn-icon-left",
|
|
359
|
+
children: leftIcon
|
|
360
|
+
}),
|
|
361
|
+
/* @__PURE__ */ jsx("span", {
|
|
362
|
+
className: "btn-content",
|
|
363
|
+
children
|
|
364
|
+
}),
|
|
365
|
+
!isLoading && rightIcon && /* @__PURE__ */ jsx("span", {
|
|
366
|
+
className: "btn-icon-right",
|
|
367
|
+
children: rightIcon
|
|
368
|
+
})
|
|
369
|
+
]
|
|
201
370
|
}),
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
371
|
+
confirm && portalTarget && createPortal(/* @__PURE__ */ jsxs("form", {
|
|
372
|
+
id: popoverId,
|
|
373
|
+
ref: popoverRef,
|
|
374
|
+
popover: "auto",
|
|
375
|
+
role: "dialog",
|
|
376
|
+
"aria-labelledby": hasTitle ? titleId : undefined,
|
|
377
|
+
"aria-label": hasTitle ? undefined : "Confirm action",
|
|
378
|
+
"aria-describedby": hasContent ? descriptionId : undefined,
|
|
379
|
+
className: "popover popover-confirm popover-bottom",
|
|
380
|
+
style: { positionAnchor: anchor },
|
|
381
|
+
onSubmit: handleConfirm,
|
|
382
|
+
onClick: (event) => event.stopPropagation(),
|
|
383
|
+
onToggle: (event) => {
|
|
384
|
+
if (!event.currentTarget.matches(":popover-open")) {
|
|
385
|
+
operationRef.current += 1;
|
|
386
|
+
if (event.currentTarget.contains(document.activeElement) || document.activeElement === document.body) {
|
|
387
|
+
buttonRef.current?.focus();
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
},
|
|
391
|
+
children: [
|
|
392
|
+
hasTitle && /* @__PURE__ */ jsx("div", {
|
|
393
|
+
className: "popover-header",
|
|
394
|
+
children: /* @__PURE__ */ jsx("h3", {
|
|
395
|
+
id: titleId,
|
|
396
|
+
className: "popover-title",
|
|
397
|
+
children: title
|
|
398
|
+
})
|
|
399
|
+
}),
|
|
400
|
+
hasContent && /* @__PURE__ */ jsx("div", {
|
|
401
|
+
id: descriptionId,
|
|
402
|
+
className: "popover-body",
|
|
403
|
+
children: content
|
|
404
|
+
}),
|
|
405
|
+
confirmError && /* @__PURE__ */ jsx("div", {
|
|
406
|
+
role: "alert",
|
|
407
|
+
className: "popover-body",
|
|
408
|
+
children: "The action failed. Please try again."
|
|
409
|
+
}),
|
|
410
|
+
/* @__PURE__ */ jsxs("div", {
|
|
411
|
+
className: "popover-footer",
|
|
412
|
+
children: [
|
|
413
|
+
/* @__PURE__ */ jsx("button", {
|
|
414
|
+
ref: cancelRef,
|
|
415
|
+
type: "button",
|
|
416
|
+
className: "btn btn-text btn-sm",
|
|
417
|
+
popoverTarget: popoverId,
|
|
418
|
+
popoverTargetAction: "hide",
|
|
419
|
+
disabled: confirmLoading,
|
|
420
|
+
children: confirmation?.cancelText ?? "Cancel"
|
|
421
|
+
}),
|
|
422
|
+
/* @__PURE__ */ jsx("button", {
|
|
423
|
+
type: "submit",
|
|
424
|
+
className: confirmClasses,
|
|
425
|
+
disabled: disabled || isLoading || confirmLoading,
|
|
426
|
+
"aria-busy": confirmLoading,
|
|
427
|
+
children: confirmation?.confirmText ?? "Confirm"
|
|
428
|
+
})
|
|
429
|
+
]
|
|
430
|
+
})
|
|
431
|
+
]
|
|
432
|
+
}), portalTarget)
|
|
206
433
|
]
|
|
207
434
|
});
|
|
208
435
|
}
|
|
209
436
|
// src/components/dropdown/Dropdown.tsx
|
|
210
437
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
211
|
-
function hasTrigger(triggers, trigger) {
|
|
212
|
-
return (triggers ?? ["hover"]).includes(trigger);
|
|
213
|
-
}
|
|
214
438
|
function callHandler(handler, event) {
|
|
215
439
|
handler?.(event);
|
|
216
440
|
}
|
|
@@ -262,85 +486,103 @@ var DropdownRoot = forwardRef(({
|
|
|
262
486
|
...props
|
|
263
487
|
}, ref) => {
|
|
264
488
|
const [internalOpen, setInternalOpen] = useState(Boolean(defaultOpen));
|
|
265
|
-
const
|
|
266
|
-
const visible =
|
|
267
|
-
const
|
|
268
|
-
|
|
269
|
-
|
|
489
|
+
const [nativeOpen, setNativeOpen] = useState(Boolean(open ?? defaultOpen));
|
|
490
|
+
const visible = open ?? internalOpen;
|
|
491
|
+
const popupRef = useRef(null);
|
|
492
|
+
const popupId = useId();
|
|
493
|
+
const anchorName = `--dm-dropdown-${popupId.replace(/[^a-zA-Z0-9_-]/g, "")}`;
|
|
494
|
+
const clickTrigger = trigger.includes("click") || trigger.includes("hover");
|
|
495
|
+
useEffect(() => {
|
|
496
|
+
const popup = popupRef.current;
|
|
497
|
+
if (!popup?.showPopover || !popup?.hidePopover)
|
|
270
498
|
return;
|
|
271
|
-
if (!
|
|
499
|
+
if (visible && !popup.matches(":popover-open"))
|
|
500
|
+
popup.showPopover();
|
|
501
|
+
if (!visible && popup.matches(":popover-open"))
|
|
502
|
+
popup.hidePopover();
|
|
503
|
+
}, [visible]);
|
|
504
|
+
function setVisible(nextOpen) {
|
|
505
|
+
if (open === undefined)
|
|
272
506
|
setInternalOpen(nextOpen);
|
|
273
|
-
}
|
|
274
507
|
onOpenChange?.(nextOpen);
|
|
275
508
|
}
|
|
276
|
-
|
|
277
|
-
|
|
509
|
+
function close() {
|
|
510
|
+
const popup = popupRef.current;
|
|
511
|
+
if (popup?.matches(":popover-open"))
|
|
512
|
+
popup.hidePopover();
|
|
513
|
+
else
|
|
514
|
+
setVisible(false);
|
|
515
|
+
}
|
|
278
516
|
const menuNode = overlay ?? (menu?.items ? /* @__PURE__ */ jsx2("ul", {
|
|
279
517
|
className: dropdownMenuClass,
|
|
280
518
|
children: menu.items.map((item) => renderMenuItem(item, menu.onClick, close))
|
|
281
519
|
}) : null);
|
|
282
520
|
const popup = dropdownRender ? dropdownRender(menuNode) : menuNode;
|
|
283
|
-
const
|
|
284
|
-
const
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
toggleVisible();
|
|
293
|
-
} : undefined
|
|
521
|
+
const show = () => !disabled && popupRef.current?.showPopover?.();
|
|
522
|
+
const hide = () => !disabled && popupRef.current?.hidePopover?.();
|
|
523
|
+
const toggle = () => {
|
|
524
|
+
if (disabled)
|
|
525
|
+
return;
|
|
526
|
+
if (popupRef.current?.matches(":popover-open"))
|
|
527
|
+
hide();
|
|
528
|
+
else
|
|
529
|
+
show();
|
|
294
530
|
};
|
|
531
|
+
const childIsButton = isValidElement(children) && (children.type === "button" || children.type === Button);
|
|
295
532
|
const triggerNode = isValidElement(children) ? cloneElement(children, {
|
|
296
|
-
|
|
297
|
-
|
|
533
|
+
popoverTarget: childIsButton && clickTrigger && !disabled ? popupId : undefined,
|
|
534
|
+
style: {
|
|
535
|
+
...children.props.style,
|
|
536
|
+
anchorName
|
|
537
|
+
},
|
|
538
|
+
"aria-controls": popupId,
|
|
539
|
+
"aria-expanded": nativeOpen,
|
|
540
|
+
disabled: disabled || children.props.disabled,
|
|
298
541
|
onMouseEnter: (event) => {
|
|
299
542
|
callHandler(children.props.onMouseEnter, event);
|
|
300
|
-
|
|
543
|
+
if (trigger.includes("hover"))
|
|
544
|
+
show();
|
|
301
545
|
onMouseEnter?.(event);
|
|
302
546
|
},
|
|
303
547
|
onMouseLeave: (event) => {
|
|
304
548
|
callHandler(children.props.onMouseLeave, event);
|
|
305
|
-
triggerProps.onMouseLeave?.();
|
|
306
549
|
onMouseLeave?.(event);
|
|
307
550
|
},
|
|
308
551
|
onClick: (event) => {
|
|
309
552
|
callHandler(children.props.onClick, event);
|
|
310
|
-
triggerProps.onClick?.();
|
|
311
553
|
onClick?.(event);
|
|
554
|
+
if (!childIsButton && clickTrigger && !event.defaultPrevented)
|
|
555
|
+
toggle();
|
|
312
556
|
},
|
|
313
557
|
onContextMenu: (event) => {
|
|
314
558
|
callHandler(children.props.onContextMenu, event);
|
|
315
|
-
|
|
559
|
+
if (trigger.includes("contextMenu")) {
|
|
560
|
+
event.preventDefault();
|
|
561
|
+
toggle();
|
|
562
|
+
}
|
|
316
563
|
onContextMenu?.(event);
|
|
317
564
|
}
|
|
318
|
-
}) : /* @__PURE__ */ jsx2("
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
"aria-
|
|
565
|
+
}) : /* @__PURE__ */ jsx2("button", {
|
|
566
|
+
type: "button",
|
|
567
|
+
disabled,
|
|
568
|
+
popoverTarget: clickTrigger && !disabled ? popupId : undefined,
|
|
569
|
+
style: { anchorName },
|
|
570
|
+
"aria-controls": popupId,
|
|
571
|
+
"aria-expanded": nativeOpen,
|
|
324
572
|
onMouseEnter: (event) => {
|
|
325
|
-
|
|
573
|
+
if (trigger.includes("hover"))
|
|
574
|
+
show();
|
|
326
575
|
onMouseEnter?.(event);
|
|
327
576
|
},
|
|
328
577
|
onMouseLeave: (event) => {
|
|
329
|
-
triggerProps.onMouseLeave?.();
|
|
330
578
|
onMouseLeave?.(event);
|
|
331
579
|
},
|
|
332
|
-
onClick
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
},
|
|
336
|
-
onKeyDown: (event) => {
|
|
337
|
-
if (event.key === "Enter" || event.key === " ") {
|
|
580
|
+
onClick,
|
|
581
|
+
onContextMenu: (event) => {
|
|
582
|
+
if (trigger.includes("contextMenu")) {
|
|
338
583
|
event.preventDefault();
|
|
339
|
-
|
|
584
|
+
toggle();
|
|
340
585
|
}
|
|
341
|
-
},
|
|
342
|
-
onContextMenu: (event) => {
|
|
343
|
-
triggerProps.onContextMenu?.(event);
|
|
344
586
|
onContextMenu?.(event);
|
|
345
587
|
},
|
|
346
588
|
children
|
|
@@ -348,25 +590,30 @@ var DropdownRoot = forwardRef(({
|
|
|
348
590
|
return /* @__PURE__ */ jsxs2("span", {
|
|
349
591
|
...props,
|
|
350
592
|
ref,
|
|
351
|
-
className: dropdownWrapperClass,
|
|
593
|
+
className: cn(dropdownWrapperClass, dropdownPlacementClasses[placement]),
|
|
594
|
+
onMouseLeave: trigger.includes("hover") ? hide : undefined,
|
|
352
595
|
children: [
|
|
353
596
|
triggerNode,
|
|
354
|
-
|
|
355
|
-
id:
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
597
|
+
/* @__PURE__ */ jsxs2("span", {
|
|
598
|
+
id: popupId,
|
|
599
|
+
ref: popupRef,
|
|
600
|
+
popover: "auto",
|
|
601
|
+
style: { positionAnchor: anchorName },
|
|
602
|
+
className: getDropdownClasses({ className, arrow }),
|
|
603
|
+
onToggle: (event) => {
|
|
604
|
+
if (event.target !== event.currentTarget)
|
|
605
|
+
return;
|
|
606
|
+
const nextOpen = event.nativeEvent.newState === "open";
|
|
607
|
+
setNativeOpen(nextOpen);
|
|
608
|
+
setVisible(nextOpen);
|
|
609
|
+
},
|
|
363
610
|
children: [
|
|
364
|
-
popup,
|
|
611
|
+
!destroyPopupOnHide || visible ? popup : null,
|
|
365
612
|
arrow ? /* @__PURE__ */ jsx2("span", {
|
|
366
613
|
className: dropdownArrowClass
|
|
367
614
|
}) : null
|
|
368
615
|
]
|
|
369
|
-
})
|
|
616
|
+
})
|
|
370
617
|
]
|
|
371
618
|
});
|
|
372
619
|
});
|
|
@@ -378,31 +625,74 @@ var DropdownButton = forwardRef(({
|
|
|
378
625
|
menu,
|
|
379
626
|
onClick,
|
|
380
627
|
trigger = ["click"],
|
|
628
|
+
color = "base",
|
|
629
|
+
appearance = "outline",
|
|
630
|
+
size,
|
|
631
|
+
shape,
|
|
632
|
+
block,
|
|
633
|
+
isLoading,
|
|
634
|
+
leftIcon,
|
|
635
|
+
rightIcon,
|
|
636
|
+
confirm,
|
|
381
637
|
...props
|
|
382
638
|
}, ref) => {
|
|
639
|
+
const buttonStyle = { color, appearance, size, shape };
|
|
383
640
|
const buttons = [
|
|
384
641
|
/* @__PURE__ */ jsx2(Button, {
|
|
642
|
+
...buttonStyle,
|
|
385
643
|
disabled,
|
|
644
|
+
isLoading,
|
|
645
|
+
leftIcon,
|
|
646
|
+
rightIcon,
|
|
647
|
+
confirm,
|
|
386
648
|
onClick,
|
|
387
649
|
children
|
|
388
650
|
}, "primary"),
|
|
389
651
|
/* @__PURE__ */ jsx2(Button, {
|
|
652
|
+
...buttonStyle,
|
|
653
|
+
type: "button",
|
|
390
654
|
"aria-label": "Open dropdown",
|
|
391
|
-
disabled,
|
|
392
|
-
children: "
|
|
655
|
+
disabled: disabled || isLoading,
|
|
656
|
+
children: /* @__PURE__ */ jsxs2("svg", {
|
|
657
|
+
"aria-hidden": "true",
|
|
658
|
+
width: "18",
|
|
659
|
+
height: "18",
|
|
660
|
+
viewBox: "0 0 24 24",
|
|
661
|
+
fill: "currentColor",
|
|
662
|
+
children: [
|
|
663
|
+
/* @__PURE__ */ jsx2("circle", {
|
|
664
|
+
cx: "5",
|
|
665
|
+
cy: "12",
|
|
666
|
+
r: "1.75"
|
|
667
|
+
}),
|
|
668
|
+
/* @__PURE__ */ jsx2("circle", {
|
|
669
|
+
cx: "12",
|
|
670
|
+
cy: "12",
|
|
671
|
+
r: "1.75"
|
|
672
|
+
}),
|
|
673
|
+
/* @__PURE__ */ jsx2("circle", {
|
|
674
|
+
cx: "19",
|
|
675
|
+
cy: "12",
|
|
676
|
+
r: "1.75"
|
|
677
|
+
})
|
|
678
|
+
]
|
|
679
|
+
})
|
|
393
680
|
}, "trigger")
|
|
394
681
|
];
|
|
395
682
|
const renderedButtons = buttonsRender ? buttonsRender(buttons) : buttons;
|
|
396
|
-
return /* @__PURE__ */
|
|
397
|
-
...props,
|
|
683
|
+
return /* @__PURE__ */ jsxs2("span", {
|
|
398
684
|
ref,
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
685
|
+
className: cn(dropdownButtonClass, block && "dropdown-button-block"),
|
|
686
|
+
children: [
|
|
687
|
+
renderedButtons[0],
|
|
688
|
+
/* @__PURE__ */ jsx2(DropdownRoot, {
|
|
689
|
+
...props,
|
|
690
|
+
menu,
|
|
691
|
+
trigger,
|
|
692
|
+
disabled: disabled || isLoading,
|
|
693
|
+
children: renderedButtons[1]
|
|
694
|
+
})
|
|
695
|
+
]
|
|
406
696
|
});
|
|
407
697
|
});
|
|
408
698
|
DropdownButton.displayName = "Dropdown.Button";
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ComponentProps, ForwardRefExoticComponent, ReactNode, RefAttributes } from "react";
|
|
2
|
+
import type { ButtonProps } from "../button";
|
|
3
|
+
export interface FabProps extends Omit<ComponentProps<"div">, "ref"> {
|
|
4
|
+
contained?: boolean;
|
|
5
|
+
start?: boolean;
|
|
6
|
+
speedDial?: boolean;
|
|
7
|
+
label?: string;
|
|
8
|
+
actions?: ReactNode;
|
|
9
|
+
extended?: boolean;
|
|
10
|
+
buttonProps?: Omit<ButtonProps, "children" | "type" | "popoverTarget" | "aria-label">;
|
|
11
|
+
}
|
|
12
|
+
export interface FabActionProps extends FabSectionProps {
|
|
13
|
+
label?: ReactNode;
|
|
14
|
+
}
|
|
15
|
+
export interface FabTriggerProps extends ButtonProps {
|
|
16
|
+
extended?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export type FabSectionProps = Omit<ComponentProps<"div">, "ref">;
|
|
19
|
+
export type FabLabelProps = Omit<ComponentProps<"span">, "ref">;
|
|
20
|
+
export interface FabComponent extends ForwardRefExoticComponent<FabProps & RefAttributes<HTMLDivElement>> {
|
|
21
|
+
Trigger: ForwardRefExoticComponent<FabTriggerProps & RefAttributes<HTMLButtonElement>>;
|
|
22
|
+
Actions: ForwardRefExoticComponent<FabSectionProps & RefAttributes<HTMLDivElement>>;
|
|
23
|
+
Action: ForwardRefExoticComponent<FabSectionProps & RefAttributes<HTMLDivElement>>;
|
|
24
|
+
Label: ForwardRefExoticComponent<FabLabelProps & RefAttributes<HTMLSpanElement>>;
|
|
25
|
+
}
|