@balena/ui-shared-components 15.2.4-build-drop-some-lodash-for-native-alternatives-4770c1a4a0b8e703bbe1a8183d52d22c513cc0a4-1 → 15.2.4-build-drop-some-lodash-for-native-alternatives-2e2165e6ae9420fd623789747910f4a6e6d463fb-1

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.
@@ -16,6 +16,7 @@ import { Spinner } from '../Spinner';
16
16
  import { faDownload } from '@fortawesome/free-solid-svg-icons';
17
17
  import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
18
18
  import * as semver from 'balena-semver';
19
+ import { isObjectEmpty } from '../../utils/objects';
19
20
  const etcherLogoBase64 = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iODAwIiBoZWlnaHQ9IjYwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KIDxnPgogIDx0aXRsZT5FdGNoZXI8L3RpdGxlPgogIDxnIGlkPSJzdmdfMSIgc3Ryb2tlPSJudWxsIj4KICAgPHBhdGggaWQ9InN2Z18yIiBjbGFzcz0ic3QxIiBkPSJtNDEyLjkwMzgzLDM1OC4wNjcxM2wwLDE3MS40OTU4M2M3LjQ5MjU0LC0xLjY2NTAxIDE0LjE1MjU3LC0zLjMzMDAyIDIwLjgxMjYsLTcuNDkyNTRsMTQyLjM1ODE5LC04MS41ODUzOWMyMC44MTI2LC0xMS42NTUwNiAzMy4zMDAxNiwtMzQuMTMyNjYgMzMuMzAwMTYsLTU4LjI3NTI4bDAsLTE2Mi4zMzgyOGMwLC02LjY2MDAzIC0wLjgzMjUsLTEzLjMyMDA2IC0zLjMzMDAyLC0xOS4xNDc1OWwtMTU0LjAxMzI0LDg5LjA3NzkzYy0zMi40Njc2NiwyMi40Nzc2MSAtMzkuMTI3NjksNDMuMjkwMjEgLTM5LjEyNzY5LDY4LjI2NTMzbDAsLTAuMDAwMDF6IiBmaWxsPSIjQTVERTM3IiBzdHJva2U9Im51bGwiLz4KICAgPHBhdGggaWQ9InN2Z18zIiBjbGFzcz0ic3QyIiBkPSJtNjYyLjY1NTAzLDE2Ny40MjM3MWwtNTYuNjEwMjcsMzIuNDY3NjZjMS42NjUwMSw1LjgyNzUzIDMuMzMwMDIsMTIuNDg3NTYgMy4zMzAwMiwxOS4xNDc1OWwwLDE2My4xNzA3OWMwLDI0LjE0MjYyIC0xMy4zMjAwNiw0Ni42MjAyMiAtMzMuMzAwMTYsNTguMjc1MjhsLTE0Mi4zNTgxOSw4MS41ODUzOWMtNi42NjAwMywzLjMzMDAyIC0xMy4zMjAwNiw1LjgyNzUzIC0yMC44MTI2LDcuNDkyNTRsMCw2NC45MzUzMWM5Ljk5MDA1LC0xLjY2NTAxIDE5Ljk4MDEsLTQuOTk1MDIgMjguMzA1MTQsLTkuOTkwMDVsMTg0LjgxNTg5LC0xMDUuNzI4MDFjMjUuODA3NjIsLTE0Ljk4NTA3IDQxLjYyNTIsLTQyLjQ1NzcgNDEuNjI1MiwtNzIuNDI3ODVsMCwtMjExLjQ1NjAyYzAsLTkuMTU3NTQgLTEuNjY1MDEsLTE4LjMxNTA5IC00Ljk5NTAyLC0yNy40NzI2M2wtMC4wMDAwMSwweiIgZmlsbD0iI0M4RjE3OCIgc3Ryb2tlPSJudWxsIi8+CiAgIDxwYXRoIGlkPSJzdmdfNCIgY2xhc3M9InN0MSIgZD0ibTM5OS41ODM3NiwzMDMuOTU0MzZjOC4zMjUwNCwtMTMuMzIwMDYgMjAuODEyNiwtMjUuODA3NjIgMzkuMTI3NjksLTM2LjYzMDE4bDE1NS42NzgyNSwtODkuOTEwNDNjLTQuOTk1MDIsLTYuNjYwMDMgLTExLjY1NTA2LC0xMi40ODc1NiAtMTguMzE1MDksLTE2LjY1MDA4bC0xNDIuMzU4MTksLTgxLjU4NTM5Yy0yMC44MTI2LC0xMS42NTUwNiAtNDYuNjIwMjIsLTExLjY1NTA2IC02Ny40MzI4MiwwbC0xNDEuNTI1NjgsODEuNTg1MzljLTcuNDkyNTQsNC4xNjI1MiAtMTMuMzIwMDYsOS45OTAwNSAtMTkuMTQ3NTksMTYuNjUwMDhsMTU0Ljg0NTc1LDg5LjkxMDQzYzE4LjMxNTA5LDExLjY1NTA2IDMwLjgwMjY1LDIzLjMxMDExIDM5LjEyNzY5LDM2LjYzMDE4bC0wLjAwMDAxLDB6IiBmaWxsPSIjQTVERTM3IiBzdHJva2U9Im51bGwiLz4KICAgPHBhdGggaWQ9InN2Z181IiBjbGFzcz0ic3QyIiBkPSJtMjI0Ljc1NzkyLDE2MS41OTYxOGwxNDEuNTI1NjgsLTgxLjU4NTM5YzIwLjgxMjYsLTExLjY1NTA2IDQ2LjYyMDIyLC0xMS42NTUwNiA2Ny40MzI4MiwwbDE0Mi4zNTgxOSw4MS41ODUzOWM3LjQ5MjU0LDQuMTYyNTIgMTMuMzIwMDYsOS45OTAwNSAxOC4zMTUwOSwxNi42NTAwOGw1Ni42MTAyNywtMzIuNDY3NjZjLTYuNjYwMDMsLTkuMTU3NTQgLTE0Ljk4NTA3LC0xNi42NTAwOCAtMjQuOTc1MTIsLTIxLjY0NTFsLTE4NC44MTU4OSwtMTA3LjM5MzAyYy0yNS44MDc2MiwtMTQuOTg1MDcgLTU3LjQ0Mjc4LC0xNC45ODUwNyAtODMuMjUwNCwwbC0xODMuMTUwODgsMTA2LjU2MDUxYy05Ljk5MDA1LDUuODI3NTMgLTE4LjMxNTA5LDEzLjMyMDA2IC0yNC45NzUxMiwyMi40Nzc2MWw1Ni42MTAyNywzMi40Njc2NmM0LjE2MjUyLC02LjY2MDAzIDEwLjgyMjU1LC0xMi40ODc1NiAxOC4zMTUwOSwtMTYuNjUwMDh6IiBmaWxsPSIjQzhGMTc4IiBzdHJva2U9Im51bGwiLz4KICAgPHBhdGggaWQ9InN2Z182IiBjbGFzcz0ic3QyIiBkPSJtMzY2LjI4MzYsNTIyLjA3MDQxbC0xNDEuNTI1NjgsLTgxLjU4NTM5Yy0yMC44MTI2LC0xMS42NTUwNiAtMzMuMzAwMTYsLTM0LjEzMjY2IC0zMy4zMDAxNiwtNTguMjc1MjhsMCwtMTYzLjE3MDc5YzAsLTYuNjYwMDMgMC44MzI1LC0xMi40ODc1NiAyLjQ5NzUxLC0xOC4zMTUwOWwtNTYuNjEwMjcsLTMyLjQ2NzY2Yy0zLjMzMDAyLDkuMTU3NTQgLTQuOTk1MDIsMTcuNDgyNTggLTQuOTk1MDIsMjYuNjQwMTNsMCwyMTIuMjg4NTJjMCwyOS45NzAxNCAxNS44MTc1OCw1Ny40NDI3OCA0MS42MjUyLDcxLjU5NTM0bDE4My45ODMzOSwxMDUuNzI4MDFjOC4zMjUwNCw0Ljk5NTAyIDE4LjMxNTA5LDguMzI1MDQgMjguMzA1MTQsOS45OTAwNWwwLC02NC45MzUzMWMtNi42NjAwMywtMC44MzI1IC0xMy4zMjAwNiwtMy4zMzAwMiAtMTkuOTgwMSwtNy40OTI1NGwtMC4wMDAwMSwwLjAwMDAxeiIgZmlsbD0iI0M4RjE3OCIgc3Ryb2tlPSJudWxsIi8+CiAgIDxwYXRoIGlkPSJzdmdfNyIgY2xhc3M9InN0MSIgZD0ibTM0Ny4xMzYwMSwyODguOTY5MjlsLTE1My4xODA3NCwtODguMjQ1NDJjLTEuNjY1MDEsNS44Mjc1MyAtMi40OTc1MSwxMi40ODc1NiAtMi40OTc1MSwxOC4zMTUwOWwwLDE2My4xNzA3OWMwLDI0LjE0MjYyIDEyLjQ4NzU2LDQ2LjYyMDIyIDMzLjMwMDE2LDU4LjI3NTI4bDE0MS41MjU2OCw4MS41ODUzOWM2LjY2MDAzLDMuMzMwMDIgMTMuMzIwMDYsNS44Mjc1MyAyMC44MTI2LDcuNDkyNTRsMCwtMTcxLjQ5NTgzYy0wLjgzMjUsLTI0Ljk3NTEyIC03LjQ5MjU0LC00NS43ODc3MiAtMzkuOTYwMTksLTY5LjA5NzgzbDAsLTAuMDAwMDF6IiBmaWxsPSIjQTVERTM3IiBzdHJva2U9Im51bGwiLz4KICA8L2c+CiA8L2c+Cgo8L3N2Zz4=';
20
21
  const ETCHER_OPEN_IMAGE_URL = 'https://www.balena.io/etcher/open-image-url';
21
22
  export var ActionType;
@@ -26,7 +27,7 @@ export var ActionType;
26
27
  })(ActionType || (ActionType = {}));
27
28
  const getUniqueOsTypes = (osVersions, deviceTypeSlug) => {
28
29
  var _a;
29
- if (Object.keys(osVersions).length === 0 ||
30
+ if (isObjectEmpty(osVersions) ||
30
31
  !deviceTypeSlug ||
31
32
  ((_a = osVersions[deviceTypeSlug]) === null || _a === void 0 ? void 0 : _a.length) === 0) {
32
33
  return [];
@@ -98,7 +99,7 @@ export const DownloadImageDialog = ({ open, applicationId, releaseId, compatible
98
99
  [initialDeviceType.slug]: osTypes.includes(OsTypesEnum.ESR),
99
100
  }
100
101
  : {});
101
- const [isFetching, setIsFetching] = useState(Object.keys(osVersions).length === 0);
102
+ const [isFetching, setIsFetching] = useState(isObjectEmpty(osVersions));
102
103
  const [downloadSize, setDownloadSize] = useState(null);
103
104
  const [isValidatingUrl, setIsValidatingUrl] = useState(false);
104
105
  const defaultDisplayName = useMemo(() => { var _a, _b; return (_b = (_a = formModel.deviceType) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : '-'; }, [(_a = formModel.deviceType) === null || _a === void 0 ? void 0 : _a.name]);
@@ -265,7 +266,7 @@ export const DownloadImageDialog = ({ open, applicationId, releaseId, compatible
265
266
  sm: 12,
266
267
  md: 6,
267
268
  lg: 7,
268
- }, children: isFetching ? (_jsx(Spinner, {})) : (_jsxs(_Fragment, { children: [Object.keys(osVersions).length === 0 && (_jsx(Callout, { severity: "warning", children: "No OS versions available for download" })), !!osType && !!compatibleDeviceTypes && (_jsx(ImageForm, { applicationId: applicationId, releaseId: releaseId, compatibleDeviceTypes: compatibleDeviceTypes, osVersions: osVersions, isInitialDefault: isInitialDefault, hasEsrVersions: deviceTypeHasEsr[formModel.deviceType.slug], formElement: formElement, downloadUrl: downloadUrl, authToken: authToken, osType: osType, osTypes: osTypes, model: formModel, onSelectedOsTypeChange: setOsTypeCallback, onChange: handleChange }))] })) }), _jsxs(Grid, { pb: 0, size: {
269
+ }, children: isFetching ? (_jsx(Spinner, {})) : (_jsxs(_Fragment, { children: [isObjectEmpty(osVersions) && (_jsx(Callout, { severity: "warning", children: "No OS versions available for download" })), !!osType && !!compatibleDeviceTypes && (_jsx(ImageForm, { applicationId: applicationId, releaseId: releaseId, compatibleDeviceTypes: compatibleDeviceTypes, osVersions: osVersions, isInitialDefault: isInitialDefault, hasEsrVersions: deviceTypeHasEsr[formModel.deviceType.slug], formElement: formElement, downloadUrl: downloadUrl, authToken: authToken, osType: osType, osTypes: osTypes, model: formModel, onSelectedOsTypeChange: setOsTypeCallback, onChange: handleChange }))] })) }), _jsxs(Grid, { pb: 0, size: {
269
270
  xs: 12,
270
271
  sm: 12,
271
272
  md: 6,
@@ -2,6 +2,7 @@ import { FULL_TEXT_SLUG, createModelFilter, } from '../components/Filters/Schema
2
2
  import { getDataTypeSchema } from './utils';
3
3
  import { getDataModel } from '.';
4
4
  import { getRefSchema, isJSONSchema } from '../schemaOps';
5
+ import { isObjectEmpty } from '../../../utils/objects';
5
6
  export const operators = () => ({
6
7
  contains: 'contains',
7
8
  not_contains: 'does not contain',
@@ -17,7 +18,7 @@ const isArrayOfObjectSchema = (schema) => {
17
18
  };
18
19
  const buildFilterForPropertySchema = (field, operator, value, schema) => {
19
20
  const filter = getFilter(field, schema, value, operator);
20
- if (!Object.keys(filter).length) {
21
+ if (isObjectEmpty(filter)) {
21
22
  return {};
22
23
  }
23
24
  return {
@@ -55,7 +56,7 @@ const getFilter = (field, schema, value, operator) => {
55
56
  operator: effectiveOperator,
56
57
  value,
57
58
  });
58
- if (!filter || typeof filter !== 'object' || !Object.keys(filter).length) {
59
+ if (!filter || typeof filter !== 'object' || isObjectEmpty(filter)) {
59
60
  return {};
60
61
  }
61
62
  const recursiveFilter = hasPrimitiveItems
@@ -63,7 +64,7 @@ const getFilter = (field, schema, value, operator) => {
63
64
  : filter;
64
65
  return recursiveFilter &&
65
66
  isJSONSchema(recursiveFilter) &&
66
- Object.keys(recursiveFilter).length
67
+ !isObjectEmpty(recursiveFilter)
67
68
  ? wrapFilter(recursiveFilter)
68
69
  : {};
69
70
  };
@@ -1,5 +1,6 @@
1
1
  import { convertRefSchemeToSchemaPath, getRefSchemeTitle, getRefSchemePrefix, isJSONSchema, parseDescription, parseDescriptionProperty, } from '../schemaOps';
2
2
  import get from 'lodash/get';
3
+ import { isObjectEmpty } from '../../../utils/objects';
3
4
  const X_FOREIGN_KEY_SCHEMA_SEPARATOR = '___ref_scheme_separator_';
4
5
  export const removeFieldsWithNoFilter = (schema) => {
5
6
  const processProperties = (properties, parentXNoFilterSet) => {
@@ -40,10 +41,10 @@ export const removeFieldsWithNoFilter = (schema) => {
40
41
  newValue.items = Object.assign(Object.assign({}, value.items), { properties: processProperties(value.items.properties, xNoFilterSet) });
41
42
  }
42
43
  }
43
- const hasEmptyProperties = newValue.properties && Object.keys(newValue.properties).length === 0;
44
+ const hasEmptyProperties = newValue.properties && isObjectEmpty(newValue.properties);
44
45
  const hasEmptyItemsProperties = isJSONSchema(newValue.items) &&
45
46
  'properties' in newValue.items &&
46
- Object.keys((_a = newValue.items.properties) !== null && _a !== void 0 ? _a : {}).length === 0;
47
+ isObjectEmpty((_a = newValue.items.properties) !== null && _a !== void 0 ? _a : {});
47
48
  if (hasEmptyProperties || hasEmptyItemsProperties) {
48
49
  continue;
49
50
  }
@@ -4,6 +4,7 @@ import addFormats from 'ajv-formats';
4
4
  import pickBy from 'lodash/pickBy';
5
5
  import Ajv from 'ajv';
6
6
  import { enqueueSnackbar } from 'notistack';
7
+ import { isObjectEmpty } from '../../../../utils/objects';
7
8
  const ajv = new Ajv();
8
9
  ajvKeywords(ajv, ['regexp']);
9
10
  // TODO: check why is this needed
@@ -71,9 +72,7 @@ export const createFilter = (schema, formData) => {
71
72
  operator,
72
73
  value,
73
74
  });
74
- if (!filter ||
75
- typeof filter !== 'object' ||
76
- !Object.keys(filter).length) {
75
+ if (!filter || typeof filter !== 'object' || isObjectEmpty(filter)) {
77
76
  return {};
78
77
  }
79
78
  return Object.assign({ $id: randomUUID(), title: operator, description: JSON.stringify({
@@ -1,3 +1,4 @@
1
+ import { isObjectEmpty } from '../../../utils/objects';
1
2
  import { rjstJsonSchemaPick } from '../schemaOps';
2
3
  export const rjstDefaultPermissions = {
3
4
  read: [],
@@ -9,7 +10,7 @@ export const rjstRunTransformers = (data, transformers, context) => {
9
10
  if (!data) {
10
11
  return data;
11
12
  }
12
- if (!transformers || Object.keys(transformers).length === 0) {
13
+ if (!transformers || isObjectEmpty(transformers)) {
13
14
  return data;
14
15
  }
15
16
  const transformEntry = (entry) => {
@@ -1,6 +1,7 @@
1
1
  import get from 'lodash/get';
2
2
  import pick from 'lodash/pick';
3
3
  import { findInObject } from './utils';
4
+ import { isObjectEmpty } from '../../utils/objects';
4
5
  export const isJson = (str) => {
5
6
  try {
6
7
  JSON.parse(str);
@@ -42,7 +43,7 @@ export const isJSONSchema = (value) => {
42
43
  return (typeof value === 'object' &&
43
44
  value !== null &&
44
45
  typeof value !== 'boolean' &&
45
- !!Object.keys(value).length);
46
+ !isObjectEmpty(value));
46
47
  };
47
48
  export const parseDescription = (filter) => {
48
49
  if (!filter.description) {
@@ -0,0 +1 @@
1
+ export declare const isObjectEmpty: (obj: Record<string, unknown> | object) => boolean;
@@ -0,0 +1,3 @@
1
+ export const isObjectEmpty = (obj) => {
2
+ return Object.keys(obj).length === 0;
3
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@balena/ui-shared-components",
3
- "version": "15.2.4-build-drop-some-lodash-for-native-alternatives-4770c1a4a0b8e703bbe1a8183d52d22c513cc0a4-1",
3
+ "version": "15.2.4-build-drop-some-lodash-for-native-alternatives-2e2165e6ae9420fd623789747910f4a6e6d463fb-1",
4
4
  "main": "./dist/index.js",
5
5
  "sideEffects": false,
6
6
  "files": [
@@ -135,7 +135,7 @@
135
135
  },
136
136
  "homepage": "https://github.com/balena-io/ui-shared-components#readme",
137
137
  "versionist": {
138
- "publishedAt": "2025-11-13T18:45:24.808Z"
138
+ "publishedAt": "2025-11-14T13:41:36.403Z"
139
139
  },
140
140
  "overrides": {
141
141
  "storybook": "$storybook",