@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.
Files changed (82) hide show
  1. package/README.md +61 -2
  2. package/dist/classes/chat.d.ts +9 -1
  3. package/dist/classes/console-page.d.ts +16 -0
  4. package/dist/classes/dropdown.d.ts +5 -5
  5. package/dist/classes/fab.d.ts +11 -0
  6. package/dist/classes/index.d.ts +5 -0
  7. package/dist/classes/index.js +180 -34
  8. package/dist/classes/megamenu.d.ts +10 -0
  9. package/dist/classes/otp-input.d.ts +12 -0
  10. package/dist/classes/popover.d.ts +1 -3
  11. package/dist/classes/swap.d.ts +12 -0
  12. package/dist/classes/tree-select.d.ts +6 -6
  13. package/dist/components/app/index.js +128 -68
  14. package/dist/components/avatar/Avatar.types.d.ts +1 -1
  15. package/dist/components/avatar/index.js +2 -1
  16. package/dist/components/badge/index.js +1 -1
  17. package/dist/components/button/Button.d.ts +1 -1
  18. package/dist/components/button/Button.types.d.ts +8 -0
  19. package/dist/components/button/index.js +253 -24
  20. package/dist/components/calendar/index.js +44 -19
  21. package/dist/components/chat/Chat.d.ts +9 -1
  22. package/dist/components/chat/Chat.types.d.ts +26 -0
  23. package/dist/components/chat/index.js +92 -3
  24. package/dist/components/color-picker/ColorPicker.types.d.ts +2 -1
  25. package/dist/components/color-picker/index.js +206 -9
  26. package/dist/components/console-page/ConsolePage.d.ts +2 -0
  27. package/dist/components/console-page/ConsolePage.types.d.ts +29 -0
  28. package/dist/components/console-page/index.d.ts +2 -0
  29. package/dist/components/console-page/index.js +205 -0
  30. package/dist/components/date-picker/DatePicker.types.d.ts +1 -0
  31. package/dist/components/date-picker/index.js +537 -35
  32. package/dist/components/date-picker/usePickerDropdown.d.ts +17 -0
  33. package/dist/components/dm-date-picker/index.js +545 -43
  34. package/dist/components/dm-drawer/index.js +253 -24
  35. package/dist/components/dm-layout/index.js +391 -24
  36. package/dist/components/dm-menu/index.js +380 -13
  37. package/dist/components/dm-page-header/index.js +404 -114
  38. package/dist/components/dm-pro-table/index.js +1183 -368
  39. package/dist/components/dm-query/DmQuery.types.d.ts +1 -1
  40. package/dist/components/dm-query/index.js +931 -188
  41. package/dist/components/dm-search/DmSearch.types.d.ts +4 -0
  42. package/dist/components/dm-search/index.js +917 -163
  43. package/dist/components/dm-table/index.js +1001 -247
  44. package/dist/components/dm-toolbar/index.js +400 -110
  45. package/dist/components/dm-truncate/index.js +115 -35
  46. package/dist/components/dropdown/Dropdown.types.d.ts +1 -1
  47. package/dist/components/dropdown/index.js +400 -110
  48. package/dist/components/fab/Fab.d.ts +4 -0
  49. package/dist/components/fab/Fab.types.d.ts +25 -0
  50. package/dist/components/fab/index.d.ts +2 -0
  51. package/dist/components/fab/index.js +480 -0
  52. package/dist/components/form/Form.types.d.ts +1 -0
  53. package/dist/components/form/index.js +14 -3
  54. package/dist/components/megamenu/Megamenu.d.ts +2 -0
  55. package/dist/components/megamenu/Megamenu.types.d.ts +32 -0
  56. package/dist/components/megamenu/index.d.ts +2 -0
  57. package/dist/components/megamenu/index.js +214 -0
  58. package/dist/components/modal/index.js +128 -68
  59. package/dist/components/otp-input/OtpInput.d.ts +2 -0
  60. package/dist/components/otp-input/OtpInput.types.d.ts +16 -0
  61. package/dist/components/otp-input/index.d.ts +2 -0
  62. package/dist/components/otp-input/index.js +112 -0
  63. package/dist/components/popconfirm/index.js +255 -26
  64. package/dist/components/popover/index.js +24 -4
  65. package/dist/components/swap/Swap.d.ts +3 -0
  66. package/dist/components/swap/Swap.types.d.ts +22 -0
  67. package/dist/components/swap/index.d.ts +2 -0
  68. package/dist/components/swap/index.js +109 -0
  69. package/dist/components/time-picker/TimePicker.types.d.ts +1 -0
  70. package/dist/components/time-picker/index.js +167 -29
  71. package/dist/components/tooltip/Tooltip.types.d.ts +4 -0
  72. package/dist/components/tooltip/index.js +107 -27
  73. package/dist/components/tour/index.js +253 -24
  74. package/dist/components/tree-select/index.js +8 -8
  75. package/dist/components/upload/Upload.types.d.ts +1 -0
  76. package/dist/components/upload/index.js +2 -0
  77. package/dist/generated/version.d.ts +1 -1
  78. package/dist/index.d.ts +5 -0
  79. package/dist/index.js +3330 -1632
  80. package/dist/infrastructure.js +1 -1
  81. package/dist/styles.css +1190 -906
  82. 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-wrapper";
39
- var dropdownBaseClass = "popover dropdown";
40
- var dropdownOpenClass = "popover-show dropdown-open";
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: "popover-top dropdown-top",
46
- bottom: "popover-bottom dropdown-bottom",
47
- left: "popover-left dropdown-left",
48
- right: "popover-right dropdown-right",
49
- topLeft: "popover-top dropdown-top-left",
50
- topRight: "popover-top dropdown-top-right",
51
- bottomLeft: "popover-bottom dropdown-bottom-left",
52
- bottomRight: "popover-bottom dropdown-bottom-right"
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, dropdownPlacementClasses[placement], open && dropdownOpenClass, !arrow && "popover-no-arrow dropdown-no-arrow", className);
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
- return /* @__PURE__ */ jsxs("button", {
184
- ref,
185
- className: classes,
186
- disabled: disabled || isLoading,
187
- "aria-busy": isLoading,
188
- "aria-disabled": disabled || isLoading,
189
- ...props,
335
+ const confirmClasses = getButtonClasses({
336
+ color,
337
+ size: "sm",
338
+ isLoading: confirmLoading
339
+ });
340
+ return /* @__PURE__ */ jsxs(Fragment, {
190
341
  children: [
191
- isLoading && /* @__PURE__ */ jsx("span", {
192
- className: "btn-spinner"
193
- }),
194
- !isLoading && leftIcon && /* @__PURE__ */ jsx("span", {
195
- className: "btn-icon-left",
196
- children: leftIcon
197
- }),
198
- /* @__PURE__ */ jsx("span", {
199
- className: "btn-content",
200
- children
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
- !isLoading && rightIcon && /* @__PURE__ */ jsx("span", {
203
- className: "btn-icon-right",
204
- children: rightIcon
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 isControlled = open !== undefined;
266
- const visible = isControlled ? open : internalOpen;
267
- const overlayId = useId();
268
- function setVisible(nextOpen) {
269
- if (disabled)
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 (!isControlled) {
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
- const close = () => setVisible(false);
277
- const toggleVisible = () => setVisible(!visible);
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 shouldRenderPopup = !destroyPopupOnHide || visible;
284
- const triggerProps = {
285
- "aria-controls": visible ? overlayId : undefined,
286
- "aria-expanded": visible || undefined,
287
- onMouseEnter: hasTrigger(trigger, "hover") ? () => setVisible(true) : undefined,
288
- onMouseLeave: hasTrigger(trigger, "hover") ? () => setVisible(false) : undefined,
289
- onClick: hasTrigger(trigger, "click") ? toggleVisible : undefined,
290
- onContextMenu: hasTrigger(trigger, "contextMenu") ? (event) => {
291
- event.preventDefault();
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
- "aria-controls": triggerProps["aria-controls"] ?? children.props["aria-controls"],
297
- "aria-expanded": triggerProps["aria-expanded"] ?? children.props["aria-expanded"],
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
- triggerProps.onMouseEnter?.();
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
- triggerProps.onContextMenu?.(event);
559
+ if (trigger.includes("contextMenu")) {
560
+ event.preventDefault();
561
+ toggle();
562
+ }
316
563
  onContextMenu?.(event);
317
564
  }
318
- }) : /* @__PURE__ */ jsx2("span", {
319
- role: "button",
320
- tabIndex: disabled ? -1 : 0,
321
- "aria-disabled": disabled || undefined,
322
- "aria-controls": triggerProps["aria-controls"],
323
- "aria-expanded": triggerProps["aria-expanded"],
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
- triggerProps.onMouseEnter?.();
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: (event) => {
333
- triggerProps.onClick?.();
334
- onClick?.(event);
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
- triggerProps.onClick?.();
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
- shouldRenderPopup ? /* @__PURE__ */ jsxs2("span", {
355
- id: overlayId,
356
- role: "menu",
357
- className: getDropdownClasses({
358
- placement,
359
- open: visible,
360
- arrow,
361
- className
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
- }) : null
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: "v"
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__ */ jsx2(DropdownRoot, {
397
- ...props,
683
+ return /* @__PURE__ */ jsxs2("span", {
398
684
  ref,
399
- menu,
400
- trigger,
401
- disabled,
402
- children: /* @__PURE__ */ jsx2("span", {
403
- className: dropdownButtonClass,
404
- children: renderedButtons
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,4 @@
1
+ import React from "react";
2
+ import type { FabComponent, FabActionProps } from "./Fab.types";
3
+ export declare const Fab: FabComponent;
4
+ export declare const FabAction: React.ForwardRefExoticComponent<FabActionProps & React.RefAttributes<HTMLDivElement>>;
@@ -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
+ }