@uxf/core 11.85.0 → 11.87.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 +36 -0
- package/package.json +1 -1
- package/utils/filter-aria-and-data-attrs.d.ts +3 -0
- package/utils/filter-aria-and-data-attrs.js +6 -0
- package/utils/filter-aria-and-data-attrs.test.d.ts +1 -0
- package/utils/filter-aria-and-data-attrs.test.js +95 -0
- package/utils/resizer.js +5 -1
- package/utils/resizer.test.js +2 -2
package/README.md
CHANGED
|
@@ -285,6 +285,42 @@ import { filterNullish } from "@uxf/core/utils/filter-nullish";
|
|
|
285
285
|
filterNullish([0, "text", null, undefined, [], {}]); /* returns [0, "text", [], {}] */
|
|
286
286
|
```
|
|
287
287
|
|
|
288
|
+
## filterAriaAndDataAttrs
|
|
289
|
+
|
|
290
|
+
Filters an object to return only properties that start with `aria-` or `data-` prefixes. This utility is useful when you need to pass accessibility and data attributes to HTML elements while excluding other props like event handlers or component-specific props.
|
|
291
|
+
|
|
292
|
+
```tsx
|
|
293
|
+
import { filterAriaAndDataAttrs } from "@uxf/core/utils/filter-aria-and-data-attrs";
|
|
294
|
+
|
|
295
|
+
// Filter accessibility and data attributes from component props
|
|
296
|
+
const props = {
|
|
297
|
+
"aria-label": "Close button",
|
|
298
|
+
"data-testid": "close-btn",
|
|
299
|
+
className: "button",
|
|
300
|
+
onClick: handleClick,
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
const htmlAttrs = filterAriaAndDataAttrs(props);
|
|
304
|
+
// Result: { "aria-label": "Close button", "data-testid": "close-btn" }
|
|
305
|
+
|
|
306
|
+
<button {...htmlAttrs}>Close</button>
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
```tsx
|
|
310
|
+
// Use case: Passing only safe attributes to a native element
|
|
311
|
+
function CustomInput({ label, onChange, ...restProps }) {
|
|
312
|
+
const accessibilityAttrs = filterAriaAndDataAttrs(restProps);
|
|
313
|
+
|
|
314
|
+
return <input {...accessibilityAttrs} onChange={onChange} />;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
<CustomInput
|
|
318
|
+
aria-describedby="helper-text"
|
|
319
|
+
data-analytics="email-input"
|
|
320
|
+
customProp="ignored"
|
|
321
|
+
/>
|
|
322
|
+
```
|
|
323
|
+
|
|
288
324
|
### formatBytes
|
|
289
325
|
|
|
290
326
|
Appends suitable unit to the byte value of data size.
|
package/package.json
CHANGED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.filterAriaAndDataAttrs = filterAriaAndDataAttrs;
|
|
4
|
+
function filterAriaAndDataAttrs(props) {
|
|
5
|
+
return Object.fromEntries(Object.entries(props).filter((p) => { var _a, _b; return Boolean(((_a = p.at(0)) === null || _a === void 0 ? void 0 : _a.startsWith("aria-")) || ((_b = p.at(0)) === null || _b === void 0 ? void 0 : _b.startsWith("data-"))); }));
|
|
6
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const filter_aria_and_data_attrs_1 = require("./filter-aria-and-data-attrs");
|
|
4
|
+
describe("filterAriaAndDataAttrs", () => {
|
|
5
|
+
it("should filter only aria- attributes", () => {
|
|
6
|
+
const props = {
|
|
7
|
+
"aria-label": "test label",
|
|
8
|
+
"aria-hidden": true,
|
|
9
|
+
className: "test-class",
|
|
10
|
+
id: "test-id",
|
|
11
|
+
};
|
|
12
|
+
const result = (0, filter_aria_and_data_attrs_1.filterAriaAndDataAttrs)(props);
|
|
13
|
+
expect(result).toEqual({
|
|
14
|
+
"aria-label": "test label",
|
|
15
|
+
"aria-hidden": true,
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
it("should filter only data- attributes", () => {
|
|
19
|
+
const props = {
|
|
20
|
+
"data-testid": "test",
|
|
21
|
+
"data-value": 123,
|
|
22
|
+
className: "test-class",
|
|
23
|
+
onClick: jest.fn(),
|
|
24
|
+
};
|
|
25
|
+
const result = (0, filter_aria_and_data_attrs_1.filterAriaAndDataAttrs)(props);
|
|
26
|
+
expect(result).toEqual({
|
|
27
|
+
"data-testid": "test",
|
|
28
|
+
"data-value": 123,
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
it("should filter both aria- and data- attributes", () => {
|
|
32
|
+
const props = {
|
|
33
|
+
"aria-label": "label",
|
|
34
|
+
"data-testid": "test",
|
|
35
|
+
"aria-describedby": "desc",
|
|
36
|
+
"data-custom": "value",
|
|
37
|
+
className: "class",
|
|
38
|
+
style: { color: "red" },
|
|
39
|
+
};
|
|
40
|
+
const result = (0, filter_aria_and_data_attrs_1.filterAriaAndDataAttrs)(props);
|
|
41
|
+
expect(result).toEqual({
|
|
42
|
+
"aria-label": "label",
|
|
43
|
+
"data-testid": "test",
|
|
44
|
+
"aria-describedby": "desc",
|
|
45
|
+
"data-custom": "value",
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
it("should return empty object when no aria- or data- attributes present", () => {
|
|
49
|
+
const props = {
|
|
50
|
+
className: "test",
|
|
51
|
+
id: "id",
|
|
52
|
+
onClick: jest.fn(),
|
|
53
|
+
};
|
|
54
|
+
const result = (0, filter_aria_and_data_attrs_1.filterAriaAndDataAttrs)(props);
|
|
55
|
+
expect(result).toEqual({});
|
|
56
|
+
});
|
|
57
|
+
it("should return empty object for empty input", () => {
|
|
58
|
+
const props = {};
|
|
59
|
+
const result = (0, filter_aria_and_data_attrs_1.filterAriaAndDataAttrs)(props);
|
|
60
|
+
expect(result).toEqual({});
|
|
61
|
+
});
|
|
62
|
+
it("should handle attributes with various value types", () => {
|
|
63
|
+
const props = {
|
|
64
|
+
"aria-expanded": false,
|
|
65
|
+
"aria-level": 2,
|
|
66
|
+
"data-object": { nested: "value" },
|
|
67
|
+
"data-array": [1, 2, 3],
|
|
68
|
+
"data-null": null,
|
|
69
|
+
"data-undefined": undefined,
|
|
70
|
+
regularProp: "value",
|
|
71
|
+
};
|
|
72
|
+
const result = (0, filter_aria_and_data_attrs_1.filterAriaAndDataAttrs)(props);
|
|
73
|
+
expect(result).toEqual({
|
|
74
|
+
"aria-expanded": false,
|
|
75
|
+
"aria-level": 2,
|
|
76
|
+
"data-object": { nested: "value" },
|
|
77
|
+
"data-array": [1, 2, 3],
|
|
78
|
+
"data-null": null,
|
|
79
|
+
"data-undefined": undefined,
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
it("should not filter attributes that contain but don't start with aria- or data-", () => {
|
|
83
|
+
const props = {
|
|
84
|
+
"aria-label": "keep",
|
|
85
|
+
"data-id": "keep",
|
|
86
|
+
"my-aria-label": "remove",
|
|
87
|
+
"my-data-id": "remove",
|
|
88
|
+
};
|
|
89
|
+
const result = (0, filter_aria_and_data_attrs_1.filterAriaAndDataAttrs)(props);
|
|
90
|
+
expect(result).toEqual({
|
|
91
|
+
"aria-label": "keep",
|
|
92
|
+
"data-id": "keep",
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
});
|
package/utils/resizer.js
CHANGED
|
@@ -35,7 +35,11 @@ const BASE_PATH = (_b = process.env.NEXT_PUBLIC_BASE_PATH) !== null && _b !== vo
|
|
|
35
35
|
const resizerStaticImageUrl = (src, width = "auto", height = "auto", props = {}, version = 1) => {
|
|
36
36
|
var _a;
|
|
37
37
|
const { fit = "cover", position = "center", toFormat = undefined, trim = "not-trim", background = "FFF" } = props;
|
|
38
|
-
|
|
38
|
+
let filepath = typeof src === "string" ? src : src.src;
|
|
39
|
+
// fix absolute assetPrefix
|
|
40
|
+
if (!filepath.startsWith("/")) {
|
|
41
|
+
filepath = new URL(filepath).pathname;
|
|
42
|
+
}
|
|
39
43
|
const dotIndex = filepath.lastIndexOf(".");
|
|
40
44
|
const filename = filepath.slice(0, dotIndex);
|
|
41
45
|
const extension = filepath.slice(dotIndex + 1);
|
package/utils/resizer.test.js
CHANGED
|
@@ -16,7 +16,7 @@ describe("resizerGetDefaultConfig", () => {
|
|
|
16
16
|
toFormat: "avif",
|
|
17
17
|
quality: 1,
|
|
18
18
|
});
|
|
19
|
-
expect(url).toBe("/generated/static/x_x_cv_b_t_nt_1/
|
|
19
|
+
expect(url).toBe("/generated/static/x_x_cv_b_t_nt_1/1/image.jpg.avif");
|
|
20
20
|
});
|
|
21
21
|
it("should return a valid URL for an ImageResponse source", () => {
|
|
22
22
|
const imageResponse = {
|
|
@@ -29,7 +29,7 @@ describe("resizerGetDefaultConfig", () => {
|
|
|
29
29
|
});
|
|
30
30
|
it("should return a valid URL for a string source", () => {
|
|
31
31
|
const url = (0, resizer_1.resizerImageUrl)("http://example.com/image.png", 250, 250, { toFormat: "webp" });
|
|
32
|
-
expect(url).toBe("/generated/static/250_250_cv_c_FFF_nt_x/
|
|
32
|
+
expect(url).toBe("/generated/static/250_250_cv_c_FFF_nt_x/1/image.png.webp");
|
|
33
33
|
});
|
|
34
34
|
it("should return undefined for null or undefined source", () => {
|
|
35
35
|
expect((0, resizer_1.resizerImageUrl)(null)).toBeUndefined();
|