@react-fabric/core 1.0.0-beta.60 → 1.0.0-beta.62

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 (118) hide show
  1. package/css/components/_breadcrumbs.css +2 -0
  2. package/css/components/_button.css +16 -2
  3. package/css/components/_icon.css +1 -1
  4. package/css/components/_modal.css +2 -2
  5. package/css/core/_theme.css +1 -1
  6. package/css/reset/_reset.css +5 -1
  7. package/css/reset/_theme.css +3 -3
  8. package/css/styles.css +2 -0
  9. package/css/theme/_colors.css +2 -2
  10. package/dist/cjs/components/animations/Animations.js +54 -49
  11. package/dist/cjs/components/button/Button.js +2 -2
  12. package/dist/cjs/components/callout/Callout.js +4 -4
  13. package/dist/cjs/components/collapsable/Collapsable.js +4 -5
  14. package/dist/cjs/components/dropdown/Dropdown.js +13 -1
  15. package/dist/cjs/components/dropdown/DropdownTool.js +1 -2
  16. package/dist/cjs/components/icon/Icon.js +24 -24
  17. package/dist/cjs/components/media/Media.js +9 -8
  18. package/dist/cjs/components/menu/Menu.js +5 -5
  19. package/dist/cjs/components/menu/MenuItem.js +1 -2
  20. package/dist/cjs/components/navigator/Navigator.js +4 -5
  21. package/dist/cjs/components/panel/Panel.js +7 -7
  22. package/dist/cjs/components/tabpanel/Tab.js +0 -1
  23. package/dist/cjs/components/tabpanel/TabPanel.js +3 -2
  24. package/dist/cjs/core/aside/Aside.js +3 -4
  25. package/dist/cjs/core/page/Page.js +1 -1
  26. package/dist/cjs/core/theme/ThemeProvider.js +3 -2
  27. package/dist/cjs/hooks/useNavigator.js +9 -8
  28. package/dist/cjs/hooks/useOverlayService.js +34 -13
  29. package/dist/cjs/hooks/useStepper.js +0 -1
  30. package/dist/cjs/i18n/index.js +4 -4
  31. package/dist/cjs/index.js +4 -8
  32. package/dist/cjs/overlays/alert/Alert.js +1 -2
  33. package/dist/cjs/overlays/flyout/Flyout.js +2 -3
  34. package/dist/cjs/overlays/modal/Modal.js +2 -3
  35. package/dist/cjs/overlays/toast/Toast.js +2 -3
  36. package/dist/cjs/overlays/tooltip/Tooltip.js +1 -2
  37. package/dist/cjs/typography/Copy.js +1 -2
  38. package/dist/esm/components/animations/Animations.js +51 -47
  39. package/dist/esm/components/button/Button.js +2 -2
  40. package/dist/esm/components/callout/Callout.js +4 -4
  41. package/dist/esm/components/collapsable/Collapsable.js +4 -5
  42. package/dist/esm/components/dropdown/Dropdown.js +14 -2
  43. package/dist/esm/components/dropdown/DropdownTool.js +1 -2
  44. package/dist/esm/components/icon/Icon.js +24 -24
  45. package/dist/esm/components/media/Media.js +9 -8
  46. package/dist/esm/components/menu/Menu.js +5 -5
  47. package/dist/esm/components/menu/MenuItem.js +1 -2
  48. package/dist/esm/components/navigator/Navigator.js +4 -5
  49. package/dist/esm/components/panel/Panel.js +8 -8
  50. package/dist/esm/components/tabpanel/Tab.js +0 -1
  51. package/dist/esm/components/tabpanel/TabPanel.js +3 -2
  52. package/dist/esm/core/aside/Aside.js +4 -5
  53. package/dist/esm/core/page/Page.js +2 -2
  54. package/dist/esm/core/theme/ThemeProvider.js +3 -2
  55. package/dist/esm/hooks/useNavigator.js +10 -9
  56. package/dist/esm/hooks/useOverlayService.js +35 -14
  57. package/dist/esm/hooks/useStepper.js +0 -1
  58. package/dist/esm/i18n/index.js +2 -2
  59. package/dist/esm/index.js +1 -2
  60. package/dist/esm/overlays/alert/Alert.js +1 -2
  61. package/dist/esm/overlays/flyout/Flyout.js +3 -4
  62. package/dist/esm/overlays/modal/Modal.js +3 -4
  63. package/dist/esm/overlays/toast/Toast.js +2 -3
  64. package/dist/esm/overlays/tooltip/Tooltip.js +1 -2
  65. package/dist/esm/typography/Copy.js +1 -2
  66. package/dist/types/components/animations/Animations.d.ts +28 -9
  67. package/dist/types/components/collapsable/Collapsable.d.ts +2 -2
  68. package/dist/types/components/index.d.ts +2 -2
  69. package/dist/types/components/menu/types.d.ts +6 -1
  70. package/dist/types/components/navigator/Navigator.d.ts +6 -0
  71. package/dist/types/components/panel/Panel.d.ts +1 -1
  72. package/dist/types/core/aside/Aside.d.ts +1 -1
  73. package/dist/types/core/theme/ThemeProvider.d.ts +2 -2
  74. package/dist/types/hooks/useOverlayService.d.ts +3 -5
  75. package/dist/types/index.d.ts +0 -1
  76. package/dist/types/types/index.d.ts +9 -3
  77. package/package.json +6 -3
  78. package/src/components/animations/Animations.tsx +53 -45
  79. package/src/components/button/Button.tsx +4 -2
  80. package/src/components/callout/Callout.tsx +4 -5
  81. package/src/components/collapsable/Collapsable.tsx +4 -5
  82. package/src/components/dropdown/Dropdown.tsx +23 -6
  83. package/src/components/dropdown/DropdownTool.tsx +1 -2
  84. package/src/components/icon/Icon.tsx +22 -22
  85. package/src/components/index.ts +5 -4
  86. package/src/components/media/Media.tsx +7 -8
  87. package/src/components/menu/Menu.tsx +4 -4
  88. package/src/components/menu/MenuItem.tsx +1 -1
  89. package/src/components/menu/types.ts +6 -1
  90. package/src/components/navigator/Navigator.tsx +11 -5
  91. package/src/components/panel/Panel.tsx +14 -8
  92. package/src/components/tabpanel/TabPanel.tsx +2 -1
  93. package/src/core/aside/Aside.tsx +4 -5
  94. package/src/core/page/Page.tsx +2 -2
  95. package/src/core/theme/ThemeProvider.tsx +4 -2
  96. package/src/hooks/useNavigator.tsx +10 -11
  97. package/src/hooks/useOverlayService.tsx +29 -16
  98. package/src/i18n/index.ts +2 -2
  99. package/src/index.ts +0 -1
  100. package/src/overlays/alert/Alert.tsx +1 -2
  101. package/src/overlays/flyout/Flyout.tsx +3 -4
  102. package/src/overlays/modal/Modal.tsx +3 -4
  103. package/src/overlays/toast/Toast.tsx +2 -3
  104. package/src/overlays/tooltip/Tooltip.tsx +1 -2
  105. package/src/types/index.ts +32 -2
  106. package/src/typography/Copy.tsx +1 -2
  107. package/css/flags.rect.css +0 -1607
  108. package/css/flags.wavy.css +0 -1606
  109. package/dist/cjs/types/icons.js +0 -212
  110. package/dist/esm/types/icons.js +0 -214
  111. package/dist/types/types/icons.d.ts +0 -210
  112. package/src/types/icons.ts +0 -451
  113. /package/dist/cjs/i18n/{ar.json.js → ar/core.json.js} +0 -0
  114. /package/dist/cjs/i18n/{en.json.js → en/core.json.js} +0 -0
  115. /package/dist/esm/i18n/{ar.json.js → ar/core.json.js} +0 -0
  116. /package/dist/esm/i18n/{en.json.js → en/core.json.js} +0 -0
  117. /package/src/i18n/{ar.json → ar/core.json} +0 -0
  118. /package/src/i18n/{en.json → en/core.json} +0 -0
@@ -5,7 +5,7 @@ export type ModalProps<P = unknown> = P & {
5
5
  };
6
6
  export type SizeType = "xs" | "sm" | "md" | "lg" | "xl";
7
7
  export type SizeTypeWithZero = "xs" | "sm" | "md" | "lg" | "xl" | 0;
8
- export type ColorState = "primary" | "accent" | "info" | "danger" | "success" | "warning";
8
+ export type ColorState = "default" | "primary" | "accent" | "muted" | "info" | "danger" | "success" | "warning";
9
9
  export type ColorType = "primary-50" | "primary-100" | "primary-200" | "primary-300" | "primary-400" | "primary-500" | "primary-600" | "primary-700" | "primary-800" | "primary-900" | "primary-950" | "accent-50" | "accent-100" | "accent-200" | "accent-300" | "accent-400" | "accent-500" | "accent-600" | "accent-700" | "accent-800" | "accent-900" | "accent-950" | "info-50" | "info-100" | "info-200" | "info-300" | "info-400" | "info-500" | "info-600" | "info-700" | "info-800" | "info-900" | "info-950" | "danger-50" | "danger-100" | "danger-200" | "danger-300" | "danger-400" | "danger-500" | "danger-600" | "danger-700" | "danger-800" | "danger-900" | "danger-950" | "success-50" | "success-100" | "success-200" | "success-300" | "success-400" | "success-500" | "success-600" | "success-700" | "success-800" | "success-900" | "success-950" | "warning-50" | "warning-100" | "warning-200" | "warning-300" | "warning-400" | "warning-500" | "warning-600" | "warning-700" | "warning-800" | "warning-900" | "warning-950";
10
10
  export type PaletteType = "scarlet-50" | "scarlet-100" | "scarlet-200" | "scarlet-300" | "scarlet-400" | "scarlet-500" | "scarlet-600" | "scarlet-700" | "scarlet-800" | "scarlet-900" | "scarlet-950" | "pumpkin-50" | "pumpkin-100" | "pumpkin-200" | "pumpkin-300" | "pumpkin-400" | "pumpkin-500" | "pumpkin-600" | "pumpkin-700" | "pumpkin-800" | "pumpkin-900" | "pumpkin-950" | "marigold-50" | "marigold-100" | "marigold-200" | "marigold-300" | "marigold-400" | "marigold-500" | "marigold-600" | "marigold-700" | "marigold-800" | "marigold-900" | "marigold-950" | "avacado-50" | "avacado-100" | "avacado-200" | "avacado-300" | "avacado-400" | "avacado-500" | "avacado-600" | "avacado-700" | "avacado-800" | "avacado-900" | "avacado-950" | "jade-50" | "jade-100" | "jade-200" | "jade-300" | "jade-400" | "jade-500" | "jade-600" | "jade-700" | "jade-800" | "jade-900" | "jade-950" | "denim-50" | "denim-100" | "denim-200" | "denim-300" | "denim-400" | "denim-500" | "denim-600" | "denim-700" | "denim-800" | "denim-900" | "denim-950" | "iris-50" | "iris-100" | "iris-200" | "iris-300" | "iris-400" | "iris-500" | "iris-600" | "iris-700" | "iris-800" | "iris-900" | "iris-950" | "lilac-50" | "lilac-100" | "lilac-200" | "lilac-300" | "lilac-400" | "lilac-500" | "lilac-600" | "lilac-700" | "lilac-800" | "lilac-900" | "lilac-950" | "coral-50" | "coral-100" | "coral-200" | "coral-300" | "coral-400" | "coral-500" | "coral-600" | "coral-700" | "coral-800" | "coral-900" | "coral-950" | "wood-50" | "wood-100" | "wood-200" | "wood-300" | "wood-400" | "wood-500" | "wood-600" | "wood-700" | "wood-800" | "wood-900" | "wood-950" | "silver-50" | "silver-100" | "silver-200" | "silver-300" | "silver-400" | "silver-500" | "silver-600" | "silver-700" | "silver-800" | "silver-900" | "silver-950" | "steel-50" | "steel-100" | "steel-200" | "steel-300" | "steel-400" | "steel-500" | "steel-600" | "steel-700" | "steel-800" | "steel-900" | "steel-950" | "olive-50" | "olive-100" | "olive-200" | "olive-300" | "olive-400" | "olive-500" | "olive-600" | "olive-700" | "olive-800" | "olive-900" | "olive-950" | "sand-50" | "sand-100" | "sand-200" | "sand-300" | "sand-400" | "sand-500" | "sand-600" | "sand-700" | "sand-800" | "sand-900" | "sand-950" | "tint-50" | "tint-100" | "tint-200" | "tint-300" | "tint-400" | "tint-500" | "tint-600" | "tint-700" | "tint-800" | "tint-900" | "tint-950";
11
11
  export type ColorWithGrays = ColorType | "invert" | "dimmed" | "muted";
@@ -118,10 +118,11 @@ export interface TooltipProp {
118
118
  */
119
119
  tooltip?: string | TooltipType;
120
120
  }
121
- export interface ChildProp<T = JSX.Element> {
121
+ export type ReactElement = React.ReactElement | string | number | bigint | Iterable<React.ReactNode> | React.ReactPortal | boolean | null | undefined;
122
+ export interface ChildProp<T = ReactElement> {
122
123
  children: Elements<T>;
123
124
  }
124
- export interface ChildrenProp<T = JSX.Element> {
125
+ export interface ChildrenProp<T = ReactElement> {
125
126
  children: Elements<T> | Array<Elements<T>>;
126
127
  }
127
128
  export interface PositionObject {
@@ -140,3 +141,8 @@ export type ArrayType<T extends readonly any[] | ArrayLike<any> | undefined> = T
140
141
  export type Complete<T> = {
141
142
  [P in keyof Required<T>]: Pick<T, P> extends Required<Pick<T, P>> ? T[P] : T[P] | undefined;
142
143
  };
144
+ export type NestedKeys<T> = T extends object ? {
145
+ [K in keyof T]: K extends string | number ? T[K] extends object ? T[K] extends readonly any[] ? T[K][number] extends object ? // Array of objects/items: return key with array index notation and recurse
146
+ `${K}.${NestedKeys<T[K][number]>}` | `${K}` : `${K}` : // Standard object: return key with dot notation and recurse
147
+ `${K}.${NestedKeys<T[K]>}` | `${K}` : `${K}` : never;
148
+ }[keyof T] : "";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-fabric/core",
3
- "version": "1.0.0-beta.60",
3
+ "version": "1.0.0-beta.62",
4
4
  "description": "RUF: Core package",
5
5
  "author": "Adarsh Pastakia <adarshpastakia@outlook.com>",
6
6
  "license": "MIT",
@@ -36,7 +36,10 @@
36
36
  },
37
37
  "dependencies": {
38
38
  "@floating-ui/react": "~0.27.16",
39
- "@react-fabric/utilities": "^1.0.0-beta.60",
39
+ "@iconify-json/mdi": "~1.2.3",
40
+ "@iconify-json/svg-spinners": "~1.2.4",
41
+ "@iconify/tailwind4": "~1.2.1",
42
+ "@react-fabric/utilities": "^1.0.0-beta.62",
40
43
  "@tailwindcss/postcss": "~4.1.16",
41
44
  "boring-avatars": "~1.11.2",
42
45
  "classnames": "~2.5.1",
@@ -54,5 +57,5 @@
54
57
  "node": ">=18.12.0",
55
58
  "npm": ">=8.19.0"
56
59
  },
57
- "gitHead": "a79f053ee7e13422c06d7d9c35d4f0c2610cdf5d"
60
+ "gitHead": "9dce2fd9bb753d67e3f8adbf50be257b4bc64242"
58
61
  }
@@ -126,26 +126,24 @@ export const AnimationIndicator = ({
126
126
  };
127
127
 
128
128
  /**
129
- * A component that displays an animated bars loader.
130
- * It can be customized with color and size properties.
131
- * This component is typically used to indicate loading states in the UI.
129
+ * A component that displays a loading animation with a customizable icon, color, size, and mask blur.
130
+ * It is typically used to indicate loading states in the UI.
132
131
  *
133
- * @param {Object} props - The properties for the AnimationBars component.
134
- * @param {ColorType | PaletteType | string} [props.color="tint-500"] - The color of the bars.
135
- * @param {number | string} [props.size="2rem"] - The size of the bars.
136
- * @returns {JSX.Element} The rendered AnimationBars component.
137
- *
138
- * @example
139
- * ```jsx
140
- * <AnimationBars color="primary-500" size="3rem" />
141
- * ```
142
- *
143
- * @see {@link https://adarshpastakia.github.io/react-fabric/?path=/story/core-components-animations--docs} for more details.
132
+ * @param {Object} props - The properties for the AnimationLoader component.
133
+ * @param {ColorType | PaletteType | string} [props.color="tint-500"] - The color of the loader icon.
134
+ * @param {number | string} [props.size="2rem"] - The size of the loader icon.
135
+ * @param {string} props.icon - The icon to be displayed as the loader.
136
+ * @param {"sm" | "md" | "lg"} [props.maskBlur] - The blur effect for the background mask.
137
+ * @returns {JSX.Element} The rendered AnimationLoader component.
144
138
  */
145
- export const AnimationBars = ({
139
+ export const AnimationLoader = ({
146
140
  color = "tint-500",
147
141
  size = "2rem",
142
+ icon,
143
+ maskBlur,
148
144
  }: {
145
+ icon: string;
146
+ maskBlur?: "sm" | "md" | "lg";
149
147
  color?: ColorType | PaletteType | string;
150
148
  size?: number | string;
151
149
  }) => {
@@ -153,65 +151,75 @@ export const AnimationBars = ({
153
151
  <div
154
152
  className={classNames(
155
153
  "absolute inset-0 z-10 flex justify-center items-center cursor-wait",
154
+ maskBlur === "sm" && "backdrop-blur-sm",
155
+ maskBlur === "md" && "backdrop-blur-md",
156
+ maskBlur === "lg" && "backdrop-blur-lg",
156
157
  )}
157
158
  >
158
159
  <div
159
160
  className={classNames(
160
- "outline outline-tint-500/20 p-4 bg-tint-50/50 backdrop-blur-sm rounded",
161
+ "outline outline-tint-500/20 p-4 bg-tint-50/50 backdrop-blur-sm leading-0 rounded",
161
162
  )}
162
163
  >
163
164
  <div
164
- className={classNames("fabric-bars")}
165
- style={{ width: size, color: getColor(color) }}
165
+ className={classNames("aspect-square", icon)}
166
+ style={{ fontSize: size, color: getColor(color) }}
166
167
  />
167
168
  </div>
168
169
  </div>
169
170
  );
170
171
  };
171
172
 
173
+ /**
174
+ * A component that displays an animated bars loader.
175
+ * It can be customized with color and size properties.
176
+ * This component is typically used to indicate loading states in the UI.
177
+ *
178
+ * @param {Object} props - The properties for the LoadingBars component.
179
+ * @param {ColorType | PaletteType | string} [props.color="tint-500"] - The color of the bars.
180
+ * @param {number | string} [props.size="2rem"] - The size of the bars.
181
+ * @returns {JSX.Element} The rendered LoadingBars component.
182
+ *
183
+ * @example
184
+ * ```jsx
185
+ * <LoadingBars color="primary-500" size="3rem" />
186
+ * ```
187
+ *
188
+ * @see {@link https://adarshpastakia.github.io/react-fabric/?path=/story/core-components-animations--docs} for more details.
189
+ */
190
+ export const LoadingBars = (props: {
191
+ color?: ColorType | PaletteType | string;
192
+ size?: number | string;
193
+ maskBlur?: "sm" | "md" | "lg";
194
+ }) => {
195
+ return (
196
+ <AnimationLoader icon="icon-[svg-spinners--bars-scale-fade]" {...props} />
197
+ );
198
+ };
199
+
172
200
  /**
173
201
  * A component that displays a spinner animation.
174
202
  * It can be customized with color and size properties.
175
203
  * This component is typically used to indicate loading states in the UI.
176
204
  *
177
- * @param {Object} props - The properties for the AnimationSpinner component.
205
+ * @param {Object} props - The properties for the LoadingSpinner component.
178
206
  * @param {ColorType | PaletteType | string} [props.color="tint-700"] - The color of the spinner.
179
207
  * @param {number | string} [props.size="2rem"] - The size of the spinner.
180
- * @returns {JSX.Element} The rendered AnimationSpinner component.
208
+ * @returns {JSX.Element} The rendered LoadingSpinner component.
181
209
  *
182
210
  * @example
183
211
  * ```jsx
184
- * <AnimationSpinner color="primary-500" size="3rem" />
212
+ * <LoadingSpinner color="primary-500" size="3rem" />
185
213
  * ```
186
214
  *
187
215
  * @see {@link https://adarshpastakia.github.io/react-fabric/?path=/story/core-components-animations--docs} for more details.
188
216
  */
189
- export const AnimationSpinner = ({
190
- color = "tint-700",
191
- size = "2rem",
192
- }: {
217
+ export const LoadingSpinner = (props: {
193
218
  color?: ColorType | PaletteType | string;
194
219
  size?: number | string;
220
+ maskBlur?: "sm" | "md" | "lg";
195
221
  }) => {
196
- return (
197
- <div
198
- className={classNames(
199
- "absolute inset-0 z-10 flex justify-center items-center cursor-wait",
200
- )}
201
- data-ref="spinner"
202
- >
203
- <div
204
- className={classNames(
205
- "outline outline-tint-500/20 p-4 bg-tint-50/50 backdrop-blur-sm rounded",
206
- )}
207
- >
208
- <div
209
- className={classNames("fabric-spinner")}
210
- style={{ width: size, color: getColor(color) }}
211
- />
212
- </div>
213
- </div>
214
- );
222
+ return <AnimationLoader icon="icon-[svg-spinners--eclipse]" {...props} />;
215
223
  };
216
224
 
217
225
  /**
@@ -260,7 +268,7 @@ export const Skeleton = ({ className, ...rest }: CssProp) => {
260
268
  *
261
269
  * @returns {JSX.Element} The rendered Loading component.
262
270
  */
263
- export const Loading = () => {
271
+ export const LoadingLine = () => {
264
272
  return (
265
273
  <div
266
274
  className={classNames(
@@ -187,7 +187,7 @@ export const Button = <Tag extends React.ElementType = "button">({
187
187
  children,
188
188
  className,
189
189
  active,
190
- color = "primary",
190
+ color = "default",
191
191
  icon,
192
192
  iconAlign = "start",
193
193
  altIcon,
@@ -292,7 +292,9 @@ export const Button = <Tag extends React.ElementType = "button">({
292
292
  data-loading={busy || loading}
293
293
  data-disabled={disabled}
294
294
  >
295
- {hotKey && <HotKey keyCombo={hotKey} handler={hotKeyHandler.current} />}
295
+ {!disabled && hotKey && (
296
+ <HotKey keyCombo={hotKey} handler={hotKeyHandler.current} />
297
+ )}
296
298
  <TooltipWrapper {...tooltipProps}>
297
299
  <E
298
300
  ref={mergeRefs(ref, refEl)}
@@ -29,7 +29,6 @@ import {
29
29
  type CssProp,
30
30
  type TestProps,
31
31
  } from "../../types";
32
- import { CoreIcons } from "../../types/icons";
33
32
  import { Icon } from "../icon/Icon";
34
33
 
35
34
  export interface CalloutProps
@@ -66,7 +65,8 @@ export interface CalloutProps
66
65
  // colors for different callout types
67
66
  const colors = {
68
67
  none: "bg-base text-tint-900 border-tint-100",
69
- tint: "bg-tint-50/50 text-tint-800 border-tint-300",
68
+ default: "bg-tint-50/50 text-tint-800 border-tint-300",
69
+ muted: "bg-tint-50/50 text-muted border-muted",
70
70
  primary: "bg-primary-50/50 text-primary-800 border-primary-300",
71
71
  accent: "bg-accent-50/50 text-accent-800 border-accent-300",
72
72
  info: "bg-info-50/50 text-info-800 border-info-300",
@@ -103,8 +103,7 @@ const colors = {
103
103
  */
104
104
  export const Callout = ({
105
105
  children,
106
- // @ts-expect-error ignore
107
- color = "tint",
106
+ color = "default",
108
107
  legend,
109
108
  title,
110
109
  icon,
@@ -145,7 +144,7 @@ export const Callout = ({
145
144
  size="md"
146
145
  data-ref="calloutClose"
147
146
  className={classNames("absolute end-2", legend ? "top-0" : "top-2")}
148
- icon={CoreIcons.close}
147
+ icon="icon-[mdi--close]"
149
148
  onClick={onClose}
150
149
  />
151
150
  )}
@@ -38,7 +38,6 @@ import {
38
38
  type RefProp,
39
39
  type TestProps,
40
40
  } from "../../types";
41
- import { CoreIcons } from "../../types/icons";
42
41
  import { Icon } from "../icon/Icon";
43
42
 
44
43
  interface CollapsableRef {
@@ -108,8 +107,8 @@ export interface CollapsableProps
108
107
  * ```jsx
109
108
  * <Collapsable
110
109
  * iconAlign="start"
111
- * iconOpen={CoreIcons.chevronDown}
112
- * iconClosed={CoreIcons.chevronRight}
110
+ * iconOpen="icon-[mdi--chevron-down]"
111
+ * iconClosed="icon-[mdi--chevron-right]"
113
112
  * open={true}
114
113
  * onOpen={() => console.log("Opened")}
115
114
  * onClose={() => console.log("Closed")}
@@ -130,8 +129,8 @@ export const Collapsable = ({
130
129
  children,
131
130
  iconAlign,
132
131
  stickyHeader,
133
- iconClosed = CoreIcons.chevronRight,
134
- iconOpen = CoreIcons.chevronDown,
132
+ iconClosed = "icon-[mdi--chevron-right]",
133
+ iconOpen = "icon-[mdi--chevron-down]",
135
134
  open,
136
135
  onClose,
137
136
  onOpen,
@@ -36,6 +36,7 @@ import {
36
36
  useClick,
37
37
  useDismiss,
38
38
  useFloating,
39
+ useFloatingNodeId,
39
40
  useFloatingTree,
40
41
  useHover,
41
42
  useInteractions,
@@ -116,6 +117,7 @@ const DropdownElement = ({
116
117
  const arrowRef = useRef(null);
117
118
  const [isOpen, setIsOpen] = useState(false);
118
119
  const tree = useFloatingTree();
120
+ const nodeId = useFloatingNodeId();
119
121
 
120
122
  const [anchor, panel] = useMemo<AnyObject[]>(
121
123
  () => Children.toArray(children as AnyObject),
@@ -123,6 +125,7 @@ const DropdownElement = ({
123
125
  );
124
126
 
125
127
  const { refs, floatingStyles, context } = useFloating({
128
+ nodeId: `dropdown-${nodeId}`,
126
129
  open: isOpen,
127
130
  onOpenChange: (open, _, reason) => {
128
131
  if (reason === "reference-press") return;
@@ -148,6 +151,7 @@ const DropdownElement = ({
148
151
  enabled: !disabled,
149
152
  handleClose: safePolygon({ blockPointerEvents: true }),
150
153
  });
154
+
151
155
  const dismiss = useDismiss(context, {
152
156
  referencePress: true,
153
157
  });
@@ -168,6 +172,11 @@ const DropdownElement = ({
168
172
  return undefined;
169
173
  }, [refs, isOpen, fitToParent]);
170
174
 
175
+ const dismissDropdown = useCallback(() => {
176
+ setIsOpen(false);
177
+ onClose?.();
178
+ }, []);
179
+
171
180
  const tryClosing = useCallback(
172
181
  (e: React.MouseEvent) => {
173
182
  if (
@@ -259,7 +268,9 @@ const DropdownElement = ({
259
268
  )}
260
269
  onMouseUpCapture={tryClosing}
261
270
  >
262
- {panel}
271
+ {cloneElement(panel, {
272
+ dismiss: dismissDropdown,
273
+ })}
263
274
  </div>
264
275
  {showArrow && (
265
276
  <FloatingArrow
@@ -308,11 +319,17 @@ const DropdownElement = ({
308
319
  * @see {@link https://adarshpastakia.github.io/react-fabric/?path=/docs/core-components-dropdown--docs} for more details.
309
320
  * @see {@link https://floating-ui.com/docs/react} for more details on Floating UI.
310
321
  */
311
- export const Dropdown = (props: DropdownProps) => (
312
- <FloatingTree>
313
- <DropdownElement {...props} />
314
- </FloatingTree>
315
- );
322
+ export const Dropdown = (props: DropdownProps) => {
323
+ const tree = useFloatingTree();
324
+ if (tree) {
325
+ return <DropdownElement {...props} />;
326
+ }
327
+ return (
328
+ <FloatingTree>
329
+ <DropdownElement {...props} />
330
+ </FloatingTree>
331
+ );
332
+ };
316
333
 
317
334
  /**
318
335
  * A component that allows dismissing the dropdown when clicked.
@@ -23,7 +23,6 @@
23
23
 
24
24
  import classNames from "classnames";
25
25
  import { type ChildProp, type CssProp } from "../../types";
26
- import { CoreIcons } from "../../types/icons";
27
26
  import { Icon } from "../icon/Icon";
28
27
  import { Dropdown, type DropdownProps } from "./Dropdown";
29
28
 
@@ -70,7 +69,7 @@ export const DropdownTool = ({
70
69
  return (
71
70
  <Dropdown {...props}>
72
71
  <Icon
73
- icon={icon ?? CoreIcons.caretDown}
72
+ icon={icon ?? "icon-[mdi--menu-down]"}
74
73
  className={classNames(
75
74
  "outline bg-tint-50/50 flex-content pointer-events-auto cursor-pointer",
76
75
  className,
@@ -191,29 +191,29 @@ export const Icon = ({
191
191
  /** ***************** render icon *******************/
192
192
  const iconEl = useMemo(() => {
193
193
  if (isValidElement(icon)) return icon;
194
- if (!isString(icon)) {
195
- throw Error("Invalid icon expected string");
194
+ if (isString(icon)) {
195
+ return isSvg ? (
196
+ <svg viewBox={viewBox}>
197
+ <path fill="currentColor" d={icon.toString()} />
198
+ </svg>
199
+ ) : icon?.toString().length <= 4 ? (
200
+ <svg role="img">
201
+ <text
202
+ x="50%"
203
+ y="50%"
204
+ dy=".1em"
205
+ dominantBaseline="middle"
206
+ textAnchor="middle"
207
+ style={{ fontSize: SvgTextSize[icon.length] }}
208
+ >
209
+ {icon}
210
+ </text>
211
+ </svg>
212
+ ) : (
213
+ <i className={`${icon}`} />
214
+ );
196
215
  }
197
- return isSvg ? (
198
- <svg viewBox={viewBox}>
199
- <path fill="currentColor" d={icon.toString()} />
200
- </svg>
201
- ) : icon?.toString().length <= 4 ? (
202
- <svg role="img">
203
- <text
204
- x="50%"
205
- y="50%"
206
- dy=".1em"
207
- dominantBaseline="middle"
208
- textAnchor="middle"
209
- style={{ fontSize: SvgTextSize[icon.length] }}
210
- >
211
- {icon}
212
- </text>
213
- </svg>
214
- ) : (
215
- <i className={`${icon}`} />
216
- );
216
+ throw Error("Invalid icon expected string");
217
217
  }, [icon, isSvg, viewBox]);
218
218
 
219
219
  return (
@@ -23,10 +23,11 @@
23
23
 
24
24
  export { ActionLabel } from "./actionLabel/ActionLabel";
25
25
  export {
26
- AnimationBars,
27
26
  AnimationIndicator,
28
- AnimationSpinner,
29
- Loading,
27
+ AnimationLoader,
28
+ LoadingBars,
29
+ LoadingLine,
30
+ LoadingSpinner,
30
31
  Skeleton,
31
32
  } from "./animations/Animations";
32
33
  export { Avatar } from "./avatar/Avatar";
@@ -47,7 +48,7 @@ export { Divider } from "./divider/Divider";
47
48
  export { Dropdown, DropdownDismiss } from "./dropdown/Dropdown";
48
49
  export { DropdownTool } from "./dropdown/DropdownTool";
49
50
  export { EmptyContent } from "./empty/EmptyContent";
50
- export { Icon, getIconProps } from "./icon/Icon";
51
+ export { getIconProps, Icon } from "./icon/Icon";
51
52
  export { Image, Video } from "./media/Media";
52
53
  export { ContextMenu } from "./menu/ContextMenu";
53
54
  export { Menu } from "./menu/Menu";
@@ -25,7 +25,6 @@ import { getImageColorset } from "@react-fabric/utilities";
25
25
  import classNames from "classnames";
26
26
  import { Fragment, useEffect, useRef, useState } from "react";
27
27
  import { type AriaProps, type CssProp, type TestProps } from "../../types";
28
- import { CoreIcons } from "../../types/icons";
29
28
  import { Button } from "../button/Button";
30
29
  import { Icon } from "../icon/Icon";
31
30
 
@@ -75,10 +74,10 @@ const loadIndicator = (
75
74
  <div
76
75
  className={classNames(
77
76
  "fabric-mediaPlaceholder",
78
- "absolute z-1 top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 text-4xl text-gray animate-pulse",
77
+ "absolute z-1 top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 text-sm text-gray",
79
78
  )}
80
79
  >
81
- ●●●
80
+ <i className="icon-[svg-spinners--pulse-rings-2]" />
82
81
  </div>
83
82
  );
84
83
 
@@ -156,7 +155,7 @@ export const Image = ({
156
155
  <Icon
157
156
  size="2rem"
158
157
  className="absolute text-tint-300 top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2"
159
- icon={CoreIcons.mediaImageBroken}
158
+ icon="icon-[mdi--image-off-outline]"
160
159
  />
161
160
  )}
162
161
  </div>
@@ -272,7 +271,7 @@ export const Video = ({
272
271
  rounded
273
272
  variant="link"
274
273
  className={"fabric-mediaControlPlaceholder"}
275
- icon={CoreIcons.ellipsis}
274
+ icon="icon-[mdi--dots-vertical]"
276
275
  aria-label="controls"
277
276
  />
278
277
  <Button
@@ -284,7 +283,7 @@ export const Video = ({
284
283
  videoRef.current &&
285
284
  (videoRef.current.volume = videoRef.current.volume ? 0 : 1);
286
285
  }}
287
- icon={volume ? CoreIcons.volumeOn : CoreIcons.volumeOff}
286
+ icon={volume ? "icon-[mdi--volume]" : "icon-[mdi--volume-mute]"}
288
287
  />
289
288
  <Button
290
289
  rounded
@@ -296,7 +295,7 @@ export const Video = ({
296
295
  ? videoRef.current?.play()
297
296
  : videoRef.current?.pause();
298
297
  }}
299
- icon={state ? CoreIcons.pause : CoreIcons.play}
298
+ icon={state ? "icon-[mdi--pause]" : "icon-[mdi--play]"}
300
299
  />
301
300
  </div>
302
301
  </Fragment>
@@ -305,7 +304,7 @@ export const Video = ({
305
304
  <Icon
306
305
  size="2rem"
307
306
  className="absolute text-tint-300 top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2"
308
- icon={CoreIcons.mediaVideoBroken}
307
+ icon="icon-[mdi--video-off-outline]"
309
308
  />
310
309
  )}
311
310
  </div>
@@ -56,7 +56,6 @@ import {
56
56
  useState,
57
57
  } from "react";
58
58
  import { HotKeyWrapper } from "../../hotkeys/HotKeyWrapper";
59
- import { CoreIcons } from "../../types/icons";
60
59
  import { cloneChildren, nodeCheck } from "../../utils";
61
60
  import { MenuItem } from "./MenuItem";
62
61
  import { type MenuProps } from "./types";
@@ -72,6 +71,7 @@ const MenuComponent = ({
72
71
  trigger = "hover",
73
72
  // @ts-expect-error ignore
74
73
  ref,
74
+ forDropdown,
75
75
  ...rest
76
76
  }: Partial<MenuProps>) => {
77
77
  const [isOpen, setIsOpen] = useState(false);
@@ -84,10 +84,10 @@ const MenuComponent = ({
84
84
  const nodeId = useFloatingNodeId();
85
85
  const parentId = useFloatingParentNodeId();
86
86
 
87
- const isNested = parentId !== null;
87
+ const isNested = parentId !== null && !forDropdown;
88
88
 
89
89
  const { floatingStyles, refs, context } = useFloating<HTMLButtonElement>({
90
- nodeId,
90
+ nodeId: `menu-${nodeId}`,
91
91
  open: !isNested || isOpen,
92
92
  onOpenChange(open, event, reason) {
93
93
  isNested && setIsOpen(open);
@@ -218,7 +218,7 @@ const MenuComponent = ({
218
218
  } as AnyObject) as AnyObject)}
219
219
  data-open={isOpen}
220
220
  minimal={minimal}
221
- altIcon={CoreIcons.chevronRight}
221
+ altIcon="icon-[mdi--menu-right]"
222
222
  ref={mergeRefs(refs.setReference, ref)}
223
223
  />
224
224
  )}
@@ -177,7 +177,7 @@ export const MenuItem = <Tag extends React.ElementType = "button">({
177
177
  }}
178
178
  {...(minimal ? {} : aria)}
179
179
  >
180
- {hotKey && (
180
+ {!disabled && hotKey && (
181
181
  <HotKey keyCombo={hotKey} handler={() => elRef.current?.click?.()} />
182
182
  )}
183
183
  {menuLabel}
@@ -45,7 +45,7 @@ export interface MenuItemProps extends CssProp, AriaProps, TestProps {
45
45
  /**
46
46
  * append label badge text
47
47
  */
48
- appendLabel?: string | false;
48
+ appendLabel?: JSX.Element | string | number | false;
49
49
  /**
50
50
  * menu color
51
51
  */
@@ -83,6 +83,10 @@ export interface MenuItemProps extends CssProp, AriaProps, TestProps {
83
83
  export interface MenuRootProps extends CssProp {
84
84
  label?: never;
85
85
  minimal?: boolean;
86
+ /**
87
+ * use this create a dropdown button within menu-item
88
+ */
89
+ forDropdown?: boolean;
86
90
  menuClassName?: never;
87
91
  onClick?: (id: string) => CallbackReturn;
88
92
  }
@@ -91,6 +95,7 @@ export interface MenuInnerProps extends MenuItemProps {
91
95
  label: string;
92
96
  minimal?: never;
93
97
  trigger?: "hover" | "click";
98
+ forDropdown?: boolean;
94
99
  /**
95
100
  * floating menu className
96
101
  */