@openmrs/esm-styleguide 8.0.1-pre.3511 → 8.0.1-pre.3525

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 (54) hide show
  1. package/.turbo/turbo-build.log +3 -3
  2. package/dist/location-picker/location-picker.resource.d.ts +1 -0
  3. package/dist/openmrs-esm-styleguide.css +1 -1
  4. package/dist/openmrs-esm-styleguide.css.map +1 -1
  5. package/dist/openmrs-esm-styleguide.js +2 -2
  6. package/dist/openmrs-esm-styleguide.js.map +1 -1
  7. package/package.json +15 -13
  8. package/src/location-picker/location-picker.component.tsx +50 -24
  9. package/src/location-picker/location-picker.module.scss +4 -17
  10. package/src/location-picker/location-picker.resource.ts +4 -13
  11. package/src/location-picker/location-picker.test.tsx +347 -51
  12. package/dist/brand.d.ts +0 -1
  13. package/dist/breakpoints/index.d.ts +0 -11
  14. package/dist/config-schema.d.ts +0 -23
  15. package/dist/custom-overflow-menu/custom-overflow-menu.component.d.ts +0 -8
  16. package/dist/custom-overflow-menu/index.d.ts +0 -1
  17. package/dist/datepicker/DatePickerIcon.d.ts +0 -6
  18. package/dist/datepicker/DatePickerInput.d.ts +0 -11
  19. package/dist/datepicker/MonthYear.d.ts +0 -10
  20. package/dist/datepicker/locale-context.d.ts +0 -2
  21. package/dist/datepicker/utils.d.ts +0 -15
  22. package/dist/error-state/error-state.component.d.ts +0 -6
  23. package/dist/error-state/index.d.ts +0 -1
  24. package/dist/icons/icon-registration.d.ts +0 -1
  25. package/dist/icons/icons.d.ts +0 -329
  26. package/dist/icons/index.d.ts +0 -1
  27. package/dist/index.d.ts +0 -1
  28. package/dist/left-nav/index.d.ts +0 -23
  29. package/dist/logo/index.d.ts +0 -1
  30. package/dist/modals/index.d.ts +0 -25
  31. package/dist/notifications/actionable-notification.component.d.ts +0 -20
  32. package/dist/notifications/active-actionable-notifications.component.d.ts +0 -8
  33. package/dist/notifications/active-notifications.component.d.ts +0 -8
  34. package/dist/notifications/index.d.ts +0 -19
  35. package/dist/notifications/notification.component.d.ts +0 -19
  36. package/dist/pictograms/pictogram-registration.d.ts +0 -1
  37. package/dist/pictograms/pictograms.d.ts +0 -64
  38. package/dist/snackbars/active-snackbar.component.d.ts +0 -9
  39. package/dist/snackbars/index.d.ts +0 -12
  40. package/dist/snackbars/snackbar.component.d.ts +0 -22
  41. package/dist/svg-utils.d.ts +0 -1
  42. package/dist/toasts/active-toasts.component.d.ts +0 -9
  43. package/dist/toasts/index.d.ts +0 -12
  44. package/dist/toasts/toast.component.d.ts +0 -19
  45. package/dist/utils.d.ts +0 -6
  46. package/dist/workspaces/action-menu-button/action-menu-button.component.d.ts +0 -11
  47. package/dist/workspaces/container/action-menu.component.d.ts +0 -9
  48. package/dist/workspaces/container/workspace-container.component.d.ts +0 -54
  49. package/dist/workspaces/container/workspace-renderer.component.d.ts +0 -8
  50. package/dist/workspaces/notification/workspace-notification.component.d.ts +0 -6
  51. package/dist/workspaces/public.d.ts +0 -4
  52. package/dist/workspaces/workspace-sidebar-store/useWorkspaceGroupStore.d.ts +0 -11
  53. package/dist/workspaces/workspaces.d.ts +0 -236
  54. package/dist/workspaces2/workspace2-close-prompt.modal.d.ts +0 -11
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openmrs/esm-styleguide",
3
- "version": "8.0.1-pre.3511",
3
+ "version": "8.0.1-pre.3525",
4
4
  "license": "MPL-2.0",
5
5
  "description": "The styleguide for OpenMRS SPA",
6
6
  "main": "dist/openmrs-esm-styleguide.js",
@@ -37,6 +37,7 @@
37
37
  "scripts": {
38
38
  "test": "cross-env TZ=UTC vitest run --passWithNoTests",
39
39
  "test:watch": "cross-env TZ=UTC vitest watch",
40
+ "coverage": "cross-env TZ=UTC vitest run --coverage --passWithNoTests",
40
41
  "build": "concurrently \"rspack --mode=production\" \"tsc --project tsconfig.build.json\"",
41
42
  "build:development": "concurrently \"rspack --mode=development\" \"tsc --project tsconfig.build.json\"",
42
43
  "analyze": "rspack --mode=production --env analyze=true",
@@ -97,20 +98,21 @@
97
98
  "swr": "2.x"
98
99
  },
99
100
  "devDependencies": {
100
- "@openmrs/esm-api": "8.0.1-pre.3511",
101
- "@openmrs/esm-config": "8.0.1-pre.3511",
102
- "@openmrs/esm-emr-api": "8.0.1-pre.3511",
103
- "@openmrs/esm-error-handling": "8.0.1-pre.3511",
104
- "@openmrs/esm-extensions": "8.0.1-pre.3511",
105
- "@openmrs/esm-globals": "8.0.1-pre.3511",
106
- "@openmrs/esm-navigation": "8.0.1-pre.3511",
107
- "@openmrs/esm-react-utils": "8.0.1-pre.3511",
108
- "@openmrs/esm-state": "8.0.1-pre.3511",
109
- "@openmrs/esm-translations": "8.0.1-pre.3511",
110
- "@openmrs/esm-utils": "8.0.1-pre.3511",
101
+ "@openmrs/esm-api": "8.0.1-pre.3525",
102
+ "@openmrs/esm-config": "8.0.1-pre.3525",
103
+ "@openmrs/esm-emr-api": "8.0.1-pre.3525",
104
+ "@openmrs/esm-error-handling": "8.0.1-pre.3525",
105
+ "@openmrs/esm-extensions": "8.0.1-pre.3525",
106
+ "@openmrs/esm-globals": "8.0.1-pre.3525",
107
+ "@openmrs/esm-navigation": "8.0.1-pre.3525",
108
+ "@openmrs/esm-react-utils": "8.0.1-pre.3525",
109
+ "@openmrs/esm-state": "8.0.1-pre.3525",
110
+ "@openmrs/esm-translations": "8.0.1-pre.3525",
111
+ "@openmrs/esm-utils": "8.0.1-pre.3525",
111
112
  "@rspack/cli": "^1.3.11",
112
113
  "@rspack/core": "^1.3.11",
113
114
  "@types/geopattern": "^1.2.9",
115
+ "@vitest/coverage-v8": "^4.0.7",
114
116
  "concurrently": "^9.1.2",
115
117
  "cross-env": "^7.0.3",
116
118
  "happy-dom": "^17.4.7",
@@ -124,7 +126,7 @@
124
126
  "svgo-loader": "^4.0.0",
125
127
  "swr": "2.2.5",
126
128
  "typescript": "^5.8.3",
127
- "vitest": "^3.1.4"
129
+ "vitest": "^4.0.7"
128
130
  },
129
131
  "stableVersion": "8.0.0"
130
132
  }
@@ -1,5 +1,12 @@
1
- import React, { useCallback, useMemo, useState } from 'react';
2
- import { InlineLoading, RadioButton, RadioButtonGroup, RadioButtonSkeleton, Search } from '@carbon/react';
1
+ import React, { useCallback, useId, useMemo, useState } from 'react';
2
+ import {
3
+ InlineLoading,
4
+ InlineNotification,
5
+ RadioButton,
6
+ RadioButtonGroup,
7
+ RadioButtonSkeleton,
8
+ Search,
9
+ } from '@carbon/react';
3
10
  import { getCoreTranslation } from '@openmrs/esm-translations';
4
11
  import { useOnVisible } from '@openmrs/esm-framework';
5
12
  import { useLocationByUuid, useLocations } from './location-picker.resource';
@@ -20,7 +27,8 @@ export const LocationPicker: React.FC<LocationPickerProps> = ({
20
27
  locationsPerRequest = 50,
21
28
  onChange,
22
29
  }) => {
23
- const [searchTerm, setSearchTerm] = useState<string>('');
30
+ const [searchTerm, setSearchTerm] = useState('');
31
+ const searchId = useId();
24
32
 
25
33
  const { location: defaultLocation } = useLocationByUuid(defaultLocationUuid);
26
34
 
@@ -29,55 +37,69 @@ export const LocationPicker: React.FC<LocationPickerProps> = ({
29
37
  isLoading,
30
38
  hasMore,
31
39
  loadingNewData,
40
+ error,
32
41
  setPage,
33
42
  } = useLocations(locationTag, locationsPerRequest, searchTerm);
34
43
 
35
44
  const locations = useMemo(() => {
36
45
  if (defaultLocation && !searchTerm && defaultLocationUuid) {
37
- return [defaultLocation, ...fetchedLocations?.filter(({ resource }) => resource.id !== defaultLocationUuid)];
46
+ return [defaultLocation, ...fetchedLocations.filter(({ resource }) => resource.id !== defaultLocationUuid)];
38
47
  }
39
- return fetchedLocations;
48
+ return fetchedLocations ?? [];
40
49
  }, [defaultLocation, fetchedLocations, defaultLocationUuid, searchTerm]);
41
50
 
42
- const search = (location: string) => {
43
- onChange();
44
- setSearchTerm(location);
45
- };
51
+ const handleSearchChange = useCallback(
52
+ (searchQuery: string) => {
53
+ onChange();
54
+ setSearchTerm(searchQuery.trim());
55
+ },
56
+ [onChange],
57
+ );
46
58
 
47
59
  const loadMore = useCallback(() => {
48
60
  if (loadingNewData || !hasMore) {
49
61
  return;
50
- } else {
51
- setPage((page) => page + 1);
52
62
  }
63
+ setPage((page) => page + 1);
53
64
  }, [loadingNewData, hasMore, setPage]);
54
65
 
55
66
  const loadingIconRef = useOnVisible(loadMore);
56
67
 
57
- const reloadIndex = hasMore ? Math.max(0, Math.floor(locations.length - locationsPerRequest / 2)) : -1;
68
+ const infiniteScrollTriggerIndex = hasMore ? Math.max(0, Math.floor(locations.length - locationsPerRequest / 2)) : -1;
58
69
 
59
70
  return (
60
- <div>
71
+ <>
61
72
  <Search
73
+ aria-describedby={error ? `${searchId}-error` : undefined}
62
74
  labelText={getCoreTranslation('searchForLocation')}
63
- id="search-1"
75
+ id={searchId}
64
76
  placeholder={getCoreTranslation('searchForLocation')}
65
- onChange={(event) => search(event.target.value)}
77
+ onChange={(event) => handleSearchChange(event.target.value)}
66
78
  size="lg"
67
79
  />
80
+ {error && (
81
+ <div className={styles.errorNotification} id={`${searchId}-error`}>
82
+ <InlineNotification
83
+ kind="error"
84
+ subtitle={getCoreTranslation(
85
+ 'errorLoadingLoginLocations',
86
+ 'Unable to load login locations. Please try again or contact support if the problem persists.',
87
+ )}
88
+ title={getCoreTranslation('error', 'Error')}
89
+ />
90
+ </div>
91
+ )}
68
92
  <div className={styles.searchResults}>
69
93
  {isLoading ? (
70
94
  <div className={styles.loadingContainer}>
71
- <RadioButtonSkeleton className={styles.radioButtonSkeleton} role="progressbar" />
72
- <RadioButtonSkeleton className={styles.radioButtonSkeleton} role="progressbar" />
73
- <RadioButtonSkeleton className={styles.radioButtonSkeleton} role="progressbar" />
74
- <RadioButtonSkeleton className={styles.radioButtonSkeleton} role="progressbar" />
75
- <RadioButtonSkeleton className={styles.radioButtonSkeleton} role="progressbar" />
95
+ {Array.from({ length: 5 }).map((_, index) => (
96
+ <RadioButtonSkeleton key={index} className={styles.radioButtonSkeleton} role="progressbar" />
97
+ ))}
76
98
  </div>
77
99
  ) : (
78
100
  <>
79
101
  <div className={styles.locationResultsContainer}>
80
- {locations?.length > 0 ? (
102
+ {locations.length > 0 ? (
81
103
  <RadioButtonGroup
82
104
  name="loginLocations"
83
105
  onChange={(value) => {
@@ -89,10 +111,14 @@ export const LocationPicker: React.FC<LocationPickerProps> = ({
89
111
  {locations.map((entry, i) => (
90
112
  <RadioButton
91
113
  className={styles.locationRadioButton}
92
- key={entry.resource.id}
93
114
  id={entry.resource.id}
115
+ key={entry.resource.id}
116
+ labelText={
117
+ <span ref={i === infiniteScrollTriggerIndex ? loadingIconRef : null}>
118
+ {entry.resource.name}
119
+ </span>
120
+ }
94
121
  name={entry.resource.name}
95
- labelText={<span ref={i === reloadIndex ? loadingIconRef : null}>{entry.resource.name}</span>}
96
122
  value={entry.resource.id}
97
123
  />
98
124
  ))}
@@ -111,6 +137,6 @@ export const LocationPicker: React.FC<LocationPickerProps> = ({
111
137
  </>
112
138
  )}
113
139
  </div>
114
- </div>
140
+ </>
115
141
  );
116
142
  };
@@ -15,11 +15,6 @@
15
15
  height: 25.5rem;
16
16
  }
17
17
 
18
- .resultsCount {
19
- @extend .bodyCompact01;
20
- color: $color-gray-70;
21
- }
22
-
23
18
  .locationResultsContainer {
24
19
  display: flex;
25
20
  overflow-y: auto;
@@ -39,18 +34,6 @@
39
34
  margin-bottom: layout.$spacing-05;
40
35
  }
41
36
 
42
- .confirmButton {
43
- padding: layout.$spacing-06;
44
-
45
- .savePreferenceCheckbox {
46
- padding-bottom: layout.$spacing-05 !important;
47
- }
48
-
49
- button {
50
- width: 100%;
51
- }
52
- }
53
-
54
37
  .radioButtonSkeleton {
55
38
  margin-right: 0 !important;
56
39
  margin-bottom: layout.$spacing-07;
@@ -82,3 +65,7 @@
82
65
  justify-content: center;
83
66
  margin: layout.$spacing-06 auto 0;
84
67
  }
68
+
69
+ .errorNotification {
70
+ margin: layout.$spacing-03 0;
71
+ }
@@ -5,7 +5,6 @@ import useSwrInfinite from 'swr/infinite';
5
5
  import { type FetchResponse, fhirBaseUrl, openmrsFetch } from '@openmrs/esm-api';
6
6
  import { type FHIRLocationResource } from '@openmrs/esm-emr-api';
7
7
  import { useDebounce } from '@openmrs/esm-react-utils';
8
- import { showNotification } from '../notifications';
9
8
 
10
9
  export interface LocationResponse {
11
10
  type: string;
@@ -27,6 +26,7 @@ export interface LoginLocationData {
27
26
  totalResults?: number;
28
27
  hasMore: boolean;
29
28
  loadingNewData: boolean;
29
+ error: Error | null;
30
30
  setPage: (size: number | ((_size: number) => number)) => Promise<FetchResponse<LocationResponse>[] | undefined>;
31
31
  }
32
32
 
@@ -53,7 +53,6 @@ export function useLocationByUuid(locationUuid?: string) {
53
53
  }
54
54
 
55
55
  export function useLocations(locationTag?: string, count: number = 0, searchQuery: string = ''): LoginLocationData {
56
- const { t } = useTranslation();
57
56
  const debouncedSearchQuery = useDebounce(searchQuery);
58
57
  function constructUrl(page: number, prevPageData: FetchResponse<LocationResponse>) {
59
58
  if (prevPageData) {
@@ -92,7 +91,7 @@ export function useLocations(locationTag?: string, count: number = 0, searchQuer
92
91
  urlSearchParameters.append('_tag', locationTag);
93
92
  }
94
93
 
95
- if (typeof debouncedSearchQuery === 'string' && debouncedSearchQuery != '') {
94
+ if (typeof debouncedSearchQuery === 'string' && debouncedSearchQuery !== '') {
96
95
  urlSearchParameters.append('name:contains', debouncedSearchQuery);
97
96
  }
98
97
 
@@ -104,15 +103,6 @@ export function useLocations(locationTag?: string, count: number = 0, searchQuer
104
103
  openmrsFetch,
105
104
  );
106
105
 
107
- if (error) {
108
- showNotification({
109
- title: t('errorLoadingLoginLocations', 'Error loading login locations'),
110
- kind: 'error',
111
- critical: true,
112
- description: error?.message,
113
- });
114
- }
115
-
116
106
  const memoizedLocations = useMemo(() => {
117
107
  return {
118
108
  locations: data?.length ? data?.flatMap((entries) => entries?.data?.entry ?? []) : [],
@@ -120,9 +110,10 @@ export function useLocations(locationTag?: string, count: number = 0, searchQuer
120
110
  totalResults: data?.[0]?.data?.total,
121
111
  hasMore: data?.length ? data?.[data.length - 1]?.data?.link?.some((link) => link.relation === 'next') : false,
122
112
  loadingNewData: isValidating,
113
+ error: error || null,
123
114
  setPage: setSize,
124
115
  };
125
- }, [isLoading, data, isValidating, setSize]);
116
+ }, [isLoading, data, isValidating, setSize, error]);
126
117
 
127
118
  return memoizedLocations;
128
119
  }