@availity/mui-favorites 0.2.3 → 0.2.5
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/CHANGELOG.md +4 -0
- package/README.md +1 -1
- package/dist/index.d.mts +7 -2
- package/dist/index.d.ts +7 -2
- package/dist/index.js +55 -10
- package/dist/index.mjs +55 -10
- package/package.json +1 -1
- package/src/lib/FavoriteHeart.tsx +69 -7
- package/src/lib/Favorites.tsx +9 -2
- package/src/lib/utils.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
|
|
4
4
|
|
|
5
|
+
## [0.2.5](https://github.com/Availity/element/compare/@availity/mui-favorites@0.2.4...@availity/mui-favorites@0.2.5) (2025-01-13)
|
|
6
|
+
|
|
7
|
+
## [0.2.4](https://github.com/Availity/element/compare/@availity/mui-favorites@0.2.3...@availity/mui-favorites@0.2.4) (2025-01-10)
|
|
8
|
+
|
|
5
9
|
## [0.2.3](https://github.com/Availity/element/compare/@availity/mui-favorites@0.2.2...@availity/mui-favorites@0.2.3) (2025-01-06)
|
|
6
10
|
|
|
7
11
|
### Dependency Updates
|
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
Live demo and documentation in our [Storybook](https://availity.github.io/element/?path=/docs/components-favorites-introduction--docs)
|
|
12
12
|
|
|
13
|
-
Availity standards for design and usage can be found in the [Availity Design Guide](https://
|
|
13
|
+
Availity standards for design and usage can be found in the [Availity Design Guide](https://design.availity.com/2e36e50c7)
|
|
14
14
|
|
|
15
15
|
## Installation
|
|
16
16
|
|
package/dist/index.d.mts
CHANGED
|
@@ -5,9 +5,12 @@ type Favorite = {
|
|
|
5
5
|
pos: number;
|
|
6
6
|
};
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
type StatusUnion = 'idle' | 'error' | 'loading' | 'reloading' | 'success';
|
|
9
|
+
declare const FavoritesProvider: ({ children, onFavoritesChange, settingsFavorites, settingsStatus, }: {
|
|
9
10
|
children: React.ReactNode;
|
|
10
11
|
onFavoritesChange?: (favorites: Favorite[]) => void;
|
|
12
|
+
settingsFavorites?: Favorite[];
|
|
13
|
+
settingsStatus?: StatusUnion;
|
|
11
14
|
}) => JSX.Element;
|
|
12
15
|
type MergedStatusUnion = 'initLoading' | 'reloading' | 'error' | 'success';
|
|
13
16
|
declare const useFavorites: (id: string) => {
|
|
@@ -30,7 +33,9 @@ type FavoriteHeartProps = {
|
|
|
30
33
|
* @default false
|
|
31
34
|
*/
|
|
32
35
|
disabled?: boolean;
|
|
36
|
+
/** The size of the icon in rem or px, minimum size is 1.5rem / 24px */
|
|
37
|
+
customSize?: string;
|
|
33
38
|
};
|
|
34
|
-
declare const FavoriteHeart: ({ id, name, onChange, onMouseDown, disabled, }: FavoriteHeartProps) => JSX.Element;
|
|
39
|
+
declare const FavoriteHeart: ({ id, name, onChange, onMouseDown, disabled, customSize, }: FavoriteHeartProps) => JSX.Element;
|
|
35
40
|
|
|
36
41
|
export { FavoriteHeart, FavoritesProvider, useFavorites };
|
package/dist/index.d.ts
CHANGED
|
@@ -5,9 +5,12 @@ type Favorite = {
|
|
|
5
5
|
pos: number;
|
|
6
6
|
};
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
type StatusUnion = 'idle' | 'error' | 'loading' | 'reloading' | 'success';
|
|
9
|
+
declare const FavoritesProvider: ({ children, onFavoritesChange, settingsFavorites, settingsStatus, }: {
|
|
9
10
|
children: React.ReactNode;
|
|
10
11
|
onFavoritesChange?: (favorites: Favorite[]) => void;
|
|
12
|
+
settingsFavorites?: Favorite[];
|
|
13
|
+
settingsStatus?: StatusUnion;
|
|
11
14
|
}) => JSX.Element;
|
|
12
15
|
type MergedStatusUnion = 'initLoading' | 'reloading' | 'error' | 'success';
|
|
13
16
|
declare const useFavorites: (id: string) => {
|
|
@@ -30,7 +33,9 @@ type FavoriteHeartProps = {
|
|
|
30
33
|
* @default false
|
|
31
34
|
*/
|
|
32
35
|
disabled?: boolean;
|
|
36
|
+
/** The size of the icon in rem or px, minimum size is 1.5rem / 24px */
|
|
37
|
+
customSize?: string;
|
|
33
38
|
};
|
|
34
|
-
declare const FavoriteHeart: ({ id, name, onChange, onMouseDown, disabled, }: FavoriteHeartProps) => JSX.Element;
|
|
39
|
+
declare const FavoriteHeart: ({ id, name, onChange, onMouseDown, disabled, customSize, }: FavoriteHeartProps) => JSX.Element;
|
|
35
40
|
|
|
36
41
|
export { FavoriteHeart, FavoritesProvider, useFavorites };
|
package/dist/index.js
CHANGED
|
@@ -119,7 +119,7 @@ var getFavorites = () => __async(void 0, null, function* () {
|
|
|
119
119
|
const validatedFavorites = validateFavorites(unvalidatedFavorites);
|
|
120
120
|
return validatedFavorites;
|
|
121
121
|
});
|
|
122
|
-
var useFavoritesQuery = () => (0, import_react_query.useQuery)(["favorites"], getFavorites);
|
|
122
|
+
var useFavoritesQuery = (enabled) => (0, import_react_query.useQuery)(["favorites"], getFavorites, { enabled });
|
|
123
123
|
var useSubmitFavorites = ({ onMutationStart }) => {
|
|
124
124
|
const queryClient = (0, import_react_query.useQueryClient)();
|
|
125
125
|
const _a = (0, import_react_query.useMutation)(submit, {
|
|
@@ -142,11 +142,15 @@ var import_jsx_runtime = require("react/jsx-runtime");
|
|
|
142
142
|
var FavoritesContext = (0, import_react.createContext)(null);
|
|
143
143
|
var FavoritesProvider = ({
|
|
144
144
|
children,
|
|
145
|
-
onFavoritesChange
|
|
145
|
+
onFavoritesChange,
|
|
146
|
+
settingsFavorites,
|
|
147
|
+
settingsStatus
|
|
146
148
|
}) => {
|
|
147
149
|
const [lastClickedFavoriteId, setLastClickedFavoriteId] = (0, import_react.useState)("");
|
|
148
150
|
const queryClient = (0, import_react_query2.useQueryClient)();
|
|
149
|
-
const { data:
|
|
151
|
+
const { data: favoritesData, status: favoritesDataStatus } = useFavoritesQuery(!settingsStatus);
|
|
152
|
+
const favorites = settingsStatus ? settingsFavorites : favoritesData;
|
|
153
|
+
const queryStatus = settingsStatus ? settingsStatus : favoritesDataStatus;
|
|
150
154
|
const { submitFavorites, status: mutationStatus } = useSubmitFavorites({
|
|
151
155
|
onMutationStart(targetFavoriteId) {
|
|
152
156
|
setLastClickedFavoriteId(targetFavoriteId);
|
|
@@ -242,6 +246,8 @@ var useFavorites = (id) => {
|
|
|
242
246
|
let status = "initLoading";
|
|
243
247
|
if (queryStatus === "loading")
|
|
244
248
|
status = "initLoading";
|
|
249
|
+
if (queryStatus === "reloading")
|
|
250
|
+
status = "reloading";
|
|
245
251
|
if (mutationStatus === "loading")
|
|
246
252
|
status = "reloading";
|
|
247
253
|
if (queryStatus === "error" || mutationStatus === "error")
|
|
@@ -270,21 +276,59 @@ var icons = {
|
|
|
270
276
|
favoritedHeart: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_mui_icon.HeartIcon, { "aria-hidden": true, color: "error" }),
|
|
271
277
|
unfavoritedHeart: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_mui_icon.HeartEmptyIcon, { "aria-hidden": true, color: "secondary" })
|
|
272
278
|
};
|
|
273
|
-
var
|
|
279
|
+
var DEFAULT_SIZE = "2.5rem";
|
|
280
|
+
var FavoriteHeartContainer = (0, import_styles.styled)("div", {
|
|
281
|
+
name: "AvFavoriteHeart",
|
|
282
|
+
slot: "Root"
|
|
283
|
+
})(({ customSize }) => ({
|
|
284
|
+
height: customSize,
|
|
285
|
+
width: customSize
|
|
286
|
+
}));
|
|
274
287
|
var FavoriteInput = (0, import_styles.styled)("input", {
|
|
275
288
|
name: "AvFavoriteHeart",
|
|
276
289
|
slot: "input"
|
|
277
|
-
})({})
|
|
290
|
+
})(({ customSize }) => ({
|
|
291
|
+
height: customSize,
|
|
292
|
+
width: customSize,
|
|
293
|
+
minHeight: customSize,
|
|
294
|
+
minWidth: customSize
|
|
295
|
+
}));
|
|
296
|
+
var fontSize = (size = DEFAULT_SIZE) => {
|
|
297
|
+
const match = size.match(/^(\d*\.?\d+)(px|rem)$/);
|
|
298
|
+
if (!match) {
|
|
299
|
+
throw new Error("Invalid size format. Must be in 'px' or 'rem'.");
|
|
300
|
+
}
|
|
301
|
+
const [, number, unit] = match;
|
|
302
|
+
const halvedNumber = parseFloat(number) / 2;
|
|
303
|
+
return `${halvedNumber}${unit}`;
|
|
304
|
+
};
|
|
278
305
|
var FavoriteIcon = (0, import_styles.styled)("div", {
|
|
279
306
|
name: "AvFavoriteHeart",
|
|
280
307
|
slot: "icon"
|
|
281
|
-
})({})
|
|
308
|
+
})(({ customSize }) => ({
|
|
309
|
+
fontSize: fontSize(customSize)
|
|
310
|
+
}));
|
|
311
|
+
var validateSize = (size) => {
|
|
312
|
+
const match = size.match(/^(\d*\.?\d+)(px|rem)$/);
|
|
313
|
+
if (!match) {
|
|
314
|
+
return false;
|
|
315
|
+
}
|
|
316
|
+
const [, number, unit] = match;
|
|
317
|
+
const value = parseFloat(number);
|
|
318
|
+
if (unit === "rem" && value >= 1.5) {
|
|
319
|
+
return true;
|
|
320
|
+
} else if (unit === "px" && value >= 24) {
|
|
321
|
+
return true;
|
|
322
|
+
}
|
|
323
|
+
return false;
|
|
324
|
+
};
|
|
282
325
|
var FavoriteHeart = ({
|
|
283
326
|
id,
|
|
284
327
|
name,
|
|
285
328
|
onChange,
|
|
286
329
|
onMouseDown,
|
|
287
|
-
disabled = false
|
|
330
|
+
disabled = false,
|
|
331
|
+
customSize = DEFAULT_SIZE
|
|
288
332
|
}) => {
|
|
289
333
|
const { isFavorited, isLastClickedFavorite, status, toggleFavorite } = useFavorites(id);
|
|
290
334
|
const handleChange = (event) => {
|
|
@@ -325,8 +369,9 @@ var FavoriteHeart = ({
|
|
|
325
369
|
onMouseDown,
|
|
326
370
|
style: { cursor }
|
|
327
371
|
};
|
|
328
|
-
|
|
329
|
-
|
|
372
|
+
const validSize = validateSize(customSize) ? customSize : DEFAULT_SIZE;
|
|
373
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(FavoriteHeartContainer, { customSize: validSize, children: [
|
|
374
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(FavoriteIcon, { customSize: validSize, children: icons[iconKey] }),
|
|
330
375
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
331
376
|
"span",
|
|
332
377
|
{
|
|
@@ -345,7 +390,7 @@ var FavoriteHeart = ({
|
|
|
345
390
|
children: isLastClickedFavorite && status === "reloading" ? "Loading..." : isLastClickedFavorite && status === "error" ? "An error has occurred. Please try again." : ""
|
|
346
391
|
}
|
|
347
392
|
),
|
|
348
|
-
disabled ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(FavoriteInput, __spreadValues({}, favoriteInputProps)) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_mui_tooltip.Tooltip, { title: tooltipContent, placement: "top", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(FavoriteInput, __spreadValues({}, favoriteInputProps)) })
|
|
393
|
+
disabled ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(FavoriteInput, __spreadValues({ customSize: validSize }, favoriteInputProps)) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_mui_tooltip.Tooltip, { title: tooltipContent, placement: "top", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(FavoriteInput, __spreadValues({ customSize: validSize }, favoriteInputProps)) })
|
|
349
394
|
] });
|
|
350
395
|
};
|
|
351
396
|
// Annotate the CommonJS export names for ESM import in node:
|
package/dist/index.mjs
CHANGED
|
@@ -84,7 +84,7 @@ var getFavorites = () => __async(void 0, null, function* () {
|
|
|
84
84
|
const validatedFavorites = validateFavorites(unvalidatedFavorites);
|
|
85
85
|
return validatedFavorites;
|
|
86
86
|
});
|
|
87
|
-
var useFavoritesQuery = () => useQuery(["favorites"], getFavorites);
|
|
87
|
+
var useFavoritesQuery = (enabled) => useQuery(["favorites"], getFavorites, { enabled });
|
|
88
88
|
var useSubmitFavorites = ({ onMutationStart }) => {
|
|
89
89
|
const queryClient = useQueryClient();
|
|
90
90
|
const _a = useMutation(submit, {
|
|
@@ -107,11 +107,15 @@ import { jsx } from "react/jsx-runtime";
|
|
|
107
107
|
var FavoritesContext = createContext(null);
|
|
108
108
|
var FavoritesProvider = ({
|
|
109
109
|
children,
|
|
110
|
-
onFavoritesChange
|
|
110
|
+
onFavoritesChange,
|
|
111
|
+
settingsFavorites,
|
|
112
|
+
settingsStatus
|
|
111
113
|
}) => {
|
|
112
114
|
const [lastClickedFavoriteId, setLastClickedFavoriteId] = useState("");
|
|
113
115
|
const queryClient = useQueryClient2();
|
|
114
|
-
const { data:
|
|
116
|
+
const { data: favoritesData, status: favoritesDataStatus } = useFavoritesQuery(!settingsStatus);
|
|
117
|
+
const favorites = settingsStatus ? settingsFavorites : favoritesData;
|
|
118
|
+
const queryStatus = settingsStatus ? settingsStatus : favoritesDataStatus;
|
|
115
119
|
const { submitFavorites, status: mutationStatus } = useSubmitFavorites({
|
|
116
120
|
onMutationStart(targetFavoriteId) {
|
|
117
121
|
setLastClickedFavoriteId(targetFavoriteId);
|
|
@@ -207,6 +211,8 @@ var useFavorites = (id) => {
|
|
|
207
211
|
let status = "initLoading";
|
|
208
212
|
if (queryStatus === "loading")
|
|
209
213
|
status = "initLoading";
|
|
214
|
+
if (queryStatus === "reloading")
|
|
215
|
+
status = "reloading";
|
|
210
216
|
if (mutationStatus === "loading")
|
|
211
217
|
status = "reloading";
|
|
212
218
|
if (queryStatus === "error" || mutationStatus === "error")
|
|
@@ -235,21 +241,59 @@ var icons = {
|
|
|
235
241
|
favoritedHeart: /* @__PURE__ */ jsx2(HeartIcon, { "aria-hidden": true, color: "error" }),
|
|
236
242
|
unfavoritedHeart: /* @__PURE__ */ jsx2(HeartEmptyIcon, { "aria-hidden": true, color: "secondary" })
|
|
237
243
|
};
|
|
238
|
-
var
|
|
244
|
+
var DEFAULT_SIZE = "2.5rem";
|
|
245
|
+
var FavoriteHeartContainer = styled("div", {
|
|
246
|
+
name: "AvFavoriteHeart",
|
|
247
|
+
slot: "Root"
|
|
248
|
+
})(({ customSize }) => ({
|
|
249
|
+
height: customSize,
|
|
250
|
+
width: customSize
|
|
251
|
+
}));
|
|
239
252
|
var FavoriteInput = styled("input", {
|
|
240
253
|
name: "AvFavoriteHeart",
|
|
241
254
|
slot: "input"
|
|
242
|
-
})({})
|
|
255
|
+
})(({ customSize }) => ({
|
|
256
|
+
height: customSize,
|
|
257
|
+
width: customSize,
|
|
258
|
+
minHeight: customSize,
|
|
259
|
+
minWidth: customSize
|
|
260
|
+
}));
|
|
261
|
+
var fontSize = (size = DEFAULT_SIZE) => {
|
|
262
|
+
const match = size.match(/^(\d*\.?\d+)(px|rem)$/);
|
|
263
|
+
if (!match) {
|
|
264
|
+
throw new Error("Invalid size format. Must be in 'px' or 'rem'.");
|
|
265
|
+
}
|
|
266
|
+
const [, number, unit] = match;
|
|
267
|
+
const halvedNumber = parseFloat(number) / 2;
|
|
268
|
+
return `${halvedNumber}${unit}`;
|
|
269
|
+
};
|
|
243
270
|
var FavoriteIcon = styled("div", {
|
|
244
271
|
name: "AvFavoriteHeart",
|
|
245
272
|
slot: "icon"
|
|
246
|
-
})({})
|
|
273
|
+
})(({ customSize }) => ({
|
|
274
|
+
fontSize: fontSize(customSize)
|
|
275
|
+
}));
|
|
276
|
+
var validateSize = (size) => {
|
|
277
|
+
const match = size.match(/^(\d*\.?\d+)(px|rem)$/);
|
|
278
|
+
if (!match) {
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
const [, number, unit] = match;
|
|
282
|
+
const value = parseFloat(number);
|
|
283
|
+
if (unit === "rem" && value >= 1.5) {
|
|
284
|
+
return true;
|
|
285
|
+
} else if (unit === "px" && value >= 24) {
|
|
286
|
+
return true;
|
|
287
|
+
}
|
|
288
|
+
return false;
|
|
289
|
+
};
|
|
247
290
|
var FavoriteHeart = ({
|
|
248
291
|
id,
|
|
249
292
|
name,
|
|
250
293
|
onChange,
|
|
251
294
|
onMouseDown,
|
|
252
|
-
disabled = false
|
|
295
|
+
disabled = false,
|
|
296
|
+
customSize = DEFAULT_SIZE
|
|
253
297
|
}) => {
|
|
254
298
|
const { isFavorited, isLastClickedFavorite, status, toggleFavorite } = useFavorites(id);
|
|
255
299
|
const handleChange = (event) => {
|
|
@@ -290,8 +334,9 @@ var FavoriteHeart = ({
|
|
|
290
334
|
onMouseDown,
|
|
291
335
|
style: { cursor }
|
|
292
336
|
};
|
|
293
|
-
|
|
294
|
-
|
|
337
|
+
const validSize = validateSize(customSize) ? customSize : DEFAULT_SIZE;
|
|
338
|
+
return /* @__PURE__ */ jsxs(FavoriteHeartContainer, { customSize: validSize, children: [
|
|
339
|
+
/* @__PURE__ */ jsx2(FavoriteIcon, { customSize: validSize, children: icons[iconKey] }),
|
|
295
340
|
/* @__PURE__ */ jsx2(
|
|
296
341
|
"span",
|
|
297
342
|
{
|
|
@@ -310,7 +355,7 @@ var FavoriteHeart = ({
|
|
|
310
355
|
children: isLastClickedFavorite && status === "reloading" ? "Loading..." : isLastClickedFavorite && status === "error" ? "An error has occurred. Please try again." : ""
|
|
311
356
|
}
|
|
312
357
|
),
|
|
313
|
-
disabled ? /* @__PURE__ */ jsx2(FavoriteInput, __spreadValues({}, favoriteInputProps)) : /* @__PURE__ */ jsx2(Tooltip, { title: tooltipContent, placement: "top", children: /* @__PURE__ */ jsx2(FavoriteInput, __spreadValues({}, favoriteInputProps)) })
|
|
358
|
+
disabled ? /* @__PURE__ */ jsx2(FavoriteInput, __spreadValues({ customSize: validSize }, favoriteInputProps)) : /* @__PURE__ */ jsx2(Tooltip, { title: tooltipContent, placement: "top", children: /* @__PURE__ */ jsx2(FavoriteInput, __spreadValues({ customSize: validSize }, favoriteInputProps)) })
|
|
314
359
|
] });
|
|
315
360
|
};
|
|
316
361
|
export {
|
package/package.json
CHANGED
|
@@ -14,16 +14,73 @@ const icons = {
|
|
|
14
14
|
unfavoritedHeart: <HeartEmptyIcon aria-hidden color="secondary" />,
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
-
const
|
|
17
|
+
const DEFAULT_SIZE = '2.5rem';
|
|
18
|
+
|
|
19
|
+
interface SizableHeartProps {
|
|
20
|
+
customSize?: string
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const FavoriteHeartContainer = styled('div', {
|
|
24
|
+
name: 'AvFavoriteHeart',
|
|
25
|
+
slot: 'Root',
|
|
26
|
+
})<SizableHeartProps>(({ customSize }) => ({
|
|
27
|
+
height: customSize,
|
|
28
|
+
width: customSize,
|
|
29
|
+
}));
|
|
30
|
+
|
|
18
31
|
const FavoriteInput = styled('input', {
|
|
19
32
|
name: 'AvFavoriteHeart',
|
|
20
33
|
slot: 'input',
|
|
21
|
-
})({})
|
|
34
|
+
})<SizableHeartProps>(({ customSize }) => ({
|
|
35
|
+
height: customSize,
|
|
36
|
+
width: customSize,
|
|
37
|
+
minHeight: customSize,
|
|
38
|
+
minWidth: customSize,
|
|
39
|
+
}));
|
|
40
|
+
|
|
41
|
+
const fontSize = (size = DEFAULT_SIZE) => {
|
|
42
|
+
// Match the number and unit in the size string
|
|
43
|
+
const match = size.match(/^(\d*\.?\d+)(px|rem)$/);
|
|
44
|
+
|
|
45
|
+
if (!match) {
|
|
46
|
+
throw new Error("Invalid size format. Must be in 'px' or 'rem'.");
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const [, number, unit] = match;
|
|
50
|
+
|
|
51
|
+
// Parse the number, halve it, and return the new size string
|
|
52
|
+
const halvedNumber = parseFloat(number) / 2;
|
|
53
|
+
return `${halvedNumber}${unit}`;
|
|
54
|
+
}
|
|
22
55
|
|
|
23
56
|
const FavoriteIcon = styled('div', {
|
|
24
57
|
name: 'AvFavoriteHeart',
|
|
25
58
|
slot: 'icon',
|
|
26
|
-
})({})
|
|
59
|
+
})<SizableHeartProps>(({ customSize }) => ({
|
|
60
|
+
fontSize: fontSize(customSize),
|
|
61
|
+
}));
|
|
62
|
+
|
|
63
|
+
// validates the size input is the correct format and at least 24px or 1.5rem
|
|
64
|
+
const validateSize = (size: string) => {
|
|
65
|
+
// Match the number and unit in the size string
|
|
66
|
+
const match = size.match(/^(\d*\.?\d+)(px|rem)$/);
|
|
67
|
+
|
|
68
|
+
if (!match) {
|
|
69
|
+
return false; // Invalid format
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const [, number, unit] = match;
|
|
73
|
+
const value = parseFloat(number);
|
|
74
|
+
|
|
75
|
+
// Validate the size based on the unit
|
|
76
|
+
if (unit === 'rem' && value >= 1.5) {
|
|
77
|
+
return true;
|
|
78
|
+
} else if (unit === 'px' && value >= 24) {
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
27
84
|
|
|
28
85
|
type FavoriteHeartProps = {
|
|
29
86
|
/** The configuration's id */
|
|
@@ -41,6 +98,8 @@ type FavoriteHeartProps = {
|
|
|
41
98
|
* @default false
|
|
42
99
|
*/
|
|
43
100
|
disabled?: boolean;
|
|
101
|
+
/** The size of the icon in rem or px, minimum size is 1.5rem / 24px */
|
|
102
|
+
customSize?: string;
|
|
44
103
|
};
|
|
45
104
|
|
|
46
105
|
export const FavoriteHeart = ({
|
|
@@ -49,6 +108,7 @@ export const FavoriteHeart = ({
|
|
|
49
108
|
onChange,
|
|
50
109
|
onMouseDown,
|
|
51
110
|
disabled = false,
|
|
111
|
+
customSize = DEFAULT_SIZE,
|
|
52
112
|
}: FavoriteHeartProps): JSX.Element => {
|
|
53
113
|
const { isFavorited, isLastClickedFavorite, status, toggleFavorite } = useFavorites(id);
|
|
54
114
|
|
|
@@ -97,9 +157,11 @@ export const FavoriteHeart = ({
|
|
|
97
157
|
style: { cursor },
|
|
98
158
|
};
|
|
99
159
|
|
|
160
|
+
const validSize = validateSize(customSize) ? customSize : DEFAULT_SIZE;
|
|
161
|
+
|
|
100
162
|
return (
|
|
101
|
-
<FavoriteHeartContainer>
|
|
102
|
-
<FavoriteIcon>{icons[iconKey]}</FavoriteIcon>
|
|
163
|
+
<FavoriteHeartContainer customSize={validSize}>
|
|
164
|
+
<FavoriteIcon customSize={validSize}>{icons[iconKey]}</FavoriteIcon>
|
|
103
165
|
<span
|
|
104
166
|
style={{
|
|
105
167
|
position: 'absolute',
|
|
@@ -122,10 +184,10 @@ export const FavoriteHeart = ({
|
|
|
122
184
|
</span>
|
|
123
185
|
|
|
124
186
|
{disabled ? (
|
|
125
|
-
<FavoriteInput {...favoriteInputProps} />
|
|
187
|
+
<FavoriteInput customSize={validSize} {...favoriteInputProps} />
|
|
126
188
|
) : (
|
|
127
189
|
<Tooltip title={tooltipContent} placement="top">
|
|
128
|
-
<FavoriteInput {...favoriteInputProps} />
|
|
190
|
+
<FavoriteInput customSize={validSize} {...favoriteInputProps} />
|
|
129
191
|
</Tooltip>
|
|
130
192
|
)}
|
|
131
193
|
</FavoriteHeartContainer>
|
package/src/lib/Favorites.tsx
CHANGED
|
@@ -5,7 +5,7 @@ import type { Favorite } from './utils';
|
|
|
5
5
|
import { useFavoritesQuery, useSubmitFavorites, sendUpdateMessage, openMaxModal } from './utils';
|
|
6
6
|
import { AV_INTERNAL_GLOBALS, MAX_FAVORITES } from './constants';
|
|
7
7
|
|
|
8
|
-
type StatusUnion = 'idle' | 'error' | 'loading' | 'success';
|
|
8
|
+
type StatusUnion = 'idle' | 'error' | 'loading' | 'reloading' | 'success';
|
|
9
9
|
|
|
10
10
|
type FavoritesContextType = {
|
|
11
11
|
favorites?: Favorite[];
|
|
@@ -21,14 +21,20 @@ const FavoritesContext = createContext<FavoritesContextType | null>(null);
|
|
|
21
21
|
export const FavoritesProvider = ({
|
|
22
22
|
children,
|
|
23
23
|
onFavoritesChange,
|
|
24
|
+
settingsFavorites,
|
|
25
|
+
settingsStatus,
|
|
24
26
|
}: {
|
|
25
27
|
children: React.ReactNode;
|
|
26
28
|
onFavoritesChange?: (favorites: Favorite[]) => void;
|
|
29
|
+
settingsFavorites?: Favorite[];
|
|
30
|
+
settingsStatus?: StatusUnion;
|
|
27
31
|
}): JSX.Element => {
|
|
28
32
|
const [lastClickedFavoriteId, setLastClickedFavoriteId] = useState<string>('');
|
|
29
33
|
|
|
30
34
|
const queryClient = useQueryClient();
|
|
31
|
-
const { data:
|
|
35
|
+
const { data: favoritesData, status: favoritesDataStatus } = useFavoritesQuery(!settingsStatus);
|
|
36
|
+
const favorites = settingsStatus ? settingsFavorites : favoritesData;
|
|
37
|
+
const queryStatus = settingsStatus ? settingsStatus : favoritesDataStatus;
|
|
32
38
|
|
|
33
39
|
const { submitFavorites, status: mutationStatus } = useSubmitFavorites({
|
|
34
40
|
onMutationStart(targetFavoriteId) {
|
|
@@ -155,6 +161,7 @@ export const useFavorites = (
|
|
|
155
161
|
|
|
156
162
|
let status: MergedStatusUnion = 'initLoading';
|
|
157
163
|
if (queryStatus === 'loading') status = 'initLoading';
|
|
164
|
+
if (queryStatus === 'reloading') status = 'reloading';
|
|
158
165
|
if (mutationStatus === 'loading') status = 'reloading';
|
|
159
166
|
if (queryStatus === 'error' || mutationStatus === 'error') status = 'error';
|
|
160
167
|
if (queryStatus === 'success' && (mutationStatus === 'success' || mutationStatus === 'idle')) status = 'success';
|
package/src/lib/utils.ts
CHANGED
|
@@ -35,7 +35,7 @@ const getFavorites = async () => {
|
|
|
35
35
|
return validatedFavorites;
|
|
36
36
|
};
|
|
37
37
|
|
|
38
|
-
export const useFavoritesQuery = (): UseQueryResult<Favorite[], unknown> => useQuery(['favorites'], getFavorites);
|
|
38
|
+
export const useFavoritesQuery = (enabled: boolean): UseQueryResult<Favorite[], unknown> => useQuery(['favorites'], getFavorites, { enabled });
|
|
39
39
|
|
|
40
40
|
type MutationOptions = {
|
|
41
41
|
onMutationStart?: (targetFavoriteId: string) => void;
|