@salesforce/ui-bundle-template-app-react-sample-b2e 11.21.0 → 11.22.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.
package/dist/CHANGELOG.md CHANGED
@@ -3,6 +3,22 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [11.22.1](https://github.com/salesforce-experience-platform-emu/webapps/compare/v11.22.0...v11.22.1) (2026-07-10)
7
+
8
+ **Note:** Version bump only for package @salesforce/ui-bundle-template-base-sfdx-project
9
+
10
+
11
+
12
+
13
+
14
+ ## [11.22.0](https://github.com/salesforce-experience-platform-emu/webapps/compare/v11.21.0...v11.22.0) (2026-07-10)
15
+
16
+ **Note:** Version bump only for package @salesforce/ui-bundle-template-base-sfdx-project
17
+
18
+
19
+
20
+
21
+
6
22
  ## [11.21.0](https://github.com/salesforce-experience-platform-emu/webapps/compare/v11.20.0...v11.21.0) (2026-07-10)
7
23
 
8
24
  **Note:** Version bump only for package @salesforce/ui-bundle-template-base-sfdx-project
@@ -18,8 +18,8 @@
18
18
  "graphql:schema": "node scripts/get-graphql-schema.mjs"
19
19
  },
20
20
  "dependencies": {
21
- "@salesforce/platform-sdk": "^11.21.0",
22
- "@salesforce/ui-bundle": "^11.21.0",
21
+ "@salesforce/platform-sdk": "^11.22.1",
22
+ "@salesforce/ui-bundle": "^11.22.1",
23
23
  "@tailwindcss/vite": "^4.1.17",
24
24
  "class-variance-authority": "^0.7.1",
25
25
  "clsx": "^2.1.1",
@@ -46,8 +46,8 @@
46
46
  "@graphql-eslint/eslint-plugin": "^4.1.0",
47
47
  "@graphql-tools/utils": "^11.0.0",
48
48
  "@playwright/test": "^1.49.0",
49
- "@salesforce/graphiti": "^11.21.0",
50
- "@salesforce/vite-plugin-ui-bundle": "^11.21.0",
49
+ "@salesforce/graphiti": "^11.22.1",
50
+ "@salesforce/vite-plugin-ui-bundle": "^11.22.1",
51
51
  "@testing-library/jest-dom": "^6.6.3",
52
52
  "@testing-library/react": "^16.1.0",
53
53
  "@testing-library/user-event": "^14.5.2",
@@ -1,5 +1,11 @@
1
1
  import React, { useState } from "react";
2
- import { X } from "lucide-react";
2
+ import {
3
+ Dialog,
4
+ DialogContent,
5
+ DialogHeader,
6
+ DialogTitle,
7
+ DialogFooter,
8
+ } from "../ui/dialog";
3
9
  import { Button } from "../ui/button";
4
10
  import type { ApplicationSearchNode } from "../../api/applications/applicationSearchService";
5
11
 
@@ -39,8 +45,6 @@ export const ApplicationDetailsModal: React.FC<ApplicationDetailsModalProps> = (
39
45
  }
40
46
  };
41
47
 
42
- if (!isOpen) return null;
43
-
44
48
  const applicantName = application.User__r?.Name?.value || "Unknown";
45
49
  const propertyName = application.Property__r?.Name?.value;
46
50
  const propertyAddress = application.Property__r?.Address__c?.value || "";
@@ -48,22 +52,13 @@ export const ApplicationDetailsModal: React.FC<ApplicationDetailsModalProps> = (
48
52
  const references = application.References__c?.value;
49
53
 
50
54
  return (
51
- <div className="fixed inset-0 z-50 flex items-center justify-center">
52
- <div className="fixed inset-0 bg-black/50" onClick={onClose} />
53
-
54
- <div className="relative bg-white rounded-lg shadow-xl w-full max-w-2xl mx-4 max-h-[90vh] overflow-y-auto">
55
- <div className="flex items-center justify-between p-6 border-b border-gray-200">
56
- <h2 className="text-xl font-semibold text-gray-900">Application Details</h2>
57
- <button
58
- onClick={onClose}
59
- aria-label="Close"
60
- className="text-gray-400 hover:text-gray-600 transition-colors"
61
- >
62
- <X className="w-6 h-6" aria-hidden="true" />
63
- </button>
64
- </div>
55
+ <Dialog open={isOpen} onOpenChange={(open) => !open && onClose()}>
56
+ <DialogContent className="sm:max-w-2xl max-h-[90vh] overflow-y-auto">
57
+ <DialogHeader>
58
+ <DialogTitle>Application Details</DialogTitle>
59
+ </DialogHeader>
65
60
 
66
- <div className="p-6 space-y-6">
61
+ <div className="space-y-6">
67
62
  <div>
68
63
  <h3 className="text-sm font-semibold text-gray-500 uppercase tracking-wide mb-2">
69
64
  Applicant
@@ -127,7 +122,7 @@ export const ApplicationDetailsModal: React.FC<ApplicationDetailsModalProps> = (
127
122
  </div>
128
123
  </div>
129
124
 
130
- <div className="flex items-center justify-end gap-3 p-6 border-t border-gray-200">
125
+ <DialogFooter>
131
126
  <Button variant="outline" onClick={onClose} disabled={isSaving}>
132
127
  Close
133
128
  </Button>
@@ -140,8 +135,8 @@ export const ApplicationDetailsModal: React.FC<ApplicationDetailsModalProps> = (
140
135
  {isSaving ? "Saving..." : "Save Changes"}
141
136
  </Button>
142
137
  )}
143
- </div>
144
- </div>
145
- </div>
138
+ </DialogFooter>
139
+ </DialogContent>
140
+ </Dialog>
146
141
  );
147
142
  };
@@ -1,5 +1,11 @@
1
1
  import React, { useState } from "react";
2
- import { X } from "lucide-react";
2
+ import {
3
+ Dialog,
4
+ DialogContent,
5
+ DialogHeader,
6
+ DialogTitle,
7
+ DialogFooter,
8
+ } from "../ui/dialog";
3
9
  import { Button } from "../ui/button";
4
10
  import { Badge } from "../ui/badge";
5
11
  import type { MaintenanceRequestSearchNode } from "../../api/maintenanceRequests/maintenanceRequestSearchService";
@@ -53,8 +59,6 @@ export const MaintenanceDetailsModal: React.FC<MaintenanceDetailsModalProps> = (
53
59
  }
54
60
  };
55
61
 
56
- if (!isOpen) return null;
57
-
58
62
  const description = request.Description__c?.value || "";
59
63
  const issueType = request.Type__c?.value || "General";
60
64
  const propertyAddress = request.Property__r?.Address__c?.value || "Unknown Address";
@@ -64,22 +68,13 @@ export const MaintenanceDetailsModal: React.FC<MaintenanceDetailsModalProps> = (
64
68
  const priority = request.Priority__c?.value;
65
69
 
66
70
  return (
67
- <div className="fixed inset-0 z-50 flex items-center justify-center">
68
- <div className="fixed inset-0 bg-black/50" onClick={onClose} />
69
-
70
- <div className="relative bg-white rounded-lg shadow-xl w-full max-w-2xl mx-4 max-h-[90vh] overflow-y-auto">
71
- <div className="flex items-center justify-between p-6 border-b border-gray-200">
72
- <h2 className="text-xl font-semibold text-gray-900">Maintenance Request Details</h2>
73
- <button
74
- onClick={onClose}
75
- aria-label="Close"
76
- className="text-gray-400 hover:text-gray-600 transition-colors"
77
- >
78
- <X className="w-6 h-6" aria-hidden="true" />
79
- </button>
80
- </div>
71
+ <Dialog open={isOpen} onOpenChange={(open) => !open && onClose()}>
72
+ <DialogContent className="sm:max-w-2xl max-h-[90vh] overflow-y-auto">
73
+ <DialogHeader>
74
+ <DialogTitle>Maintenance Request Details</DialogTitle>
75
+ </DialogHeader>
81
76
 
82
- <div className="p-6 space-y-6">
77
+ <div className="space-y-6">
83
78
  {/* Description */}
84
79
  <div>
85
80
  <h3 className="text-sm font-semibold text-gray-500 uppercase tracking-wide mb-2">
@@ -160,7 +155,7 @@ export const MaintenanceDetailsModal: React.FC<MaintenanceDetailsModalProps> = (
160
155
  </div>
161
156
  </div>
162
157
 
163
- <div className="flex items-center justify-end gap-3 p-6 border-t border-gray-200">
158
+ <DialogFooter>
164
159
  <Button variant="outline" onClick={onClose} disabled={isSaving}>
165
160
  Close
166
161
  </Button>
@@ -173,9 +168,9 @@ export const MaintenanceDetailsModal: React.FC<MaintenanceDetailsModalProps> = (
173
168
  {isSaving ? "Saving..." : "Save Changes"}
174
169
  </Button>
175
170
  )}
176
- </div>
177
- </div>
178
- </div>
171
+ </DialogFooter>
172
+ </DialogContent>
173
+ </Dialog>
179
174
  );
180
175
  };
181
176
 
@@ -30,7 +30,7 @@ export function SortControl({ configs, sort, onSortChange, className }: SortCont
30
30
  else onSortChange({ field: v, direction: sort?.direction ?? "ASC" });
31
31
  }}
32
32
  >
33
- <SelectTrigger size="sm" className="w-[160px]">
33
+ <SelectTrigger size="sm" className="w-[160px]" aria-label="Sort by">
34
34
  <SelectValue placeholder="Default" />
35
35
  </SelectTrigger>
36
36
  <SelectContent>
@@ -4,7 +4,9 @@ import { Label } from "../../../../../components/ui/label";
4
4
  interface FilterFieldWrapperProps {
5
5
  label: string;
6
6
  htmlFor?: string;
7
+ errorId?: string;
7
8
  helpText?: string;
9
+ error?: string;
8
10
  className?: string;
9
11
  children: ReactNode;
10
12
  }
@@ -12,7 +14,9 @@ interface FilterFieldWrapperProps {
12
14
  export function FilterFieldWrapper({
13
15
  label,
14
16
  htmlFor,
17
+ errorId,
15
18
  helpText,
19
+ error,
16
20
  className,
17
21
  children,
18
22
  }: FilterFieldWrapperProps) {
@@ -20,7 +24,15 @@ export function FilterFieldWrapper({
20
24
  <div className={`space-y-1 ${className ?? ""}`}>
21
25
  <Label htmlFor={htmlFor}>{label}</Label>
22
26
  {children}
23
- {helpText && <p className="text-xs text-muted-foreground min-h-4">{helpText}</p>}
27
+ <div className="min-h-4">
28
+ {error ? (
29
+ <p id={errorId} role="alert" className="text-xs text-destructive">
30
+ {error}
31
+ </p>
32
+ ) : (
33
+ helpText && <p className="text-xs text-muted-foreground">{helpText}</p>
34
+ )}
35
+ </div>
24
36
  </div>
25
37
  );
26
38
  }
@@ -1,4 +1,4 @@
1
- import { useEffect, useRef, useState } from "react";
1
+ import { useEffect, useId, useRef, useState } from "react";
2
2
  import { Input } from "../../../../../components/ui/input";
3
3
  import { useFilterField } from "../FilterContext";
4
4
  import { FilterFieldWrapper } from "./FilterFieldWrapper";
@@ -14,6 +14,7 @@ interface NumericRangeFilterProps {
14
14
 
15
15
  export function NumericRangeFilter({ field, label, helpText, min, max }: NumericRangeFilterProps) {
16
16
  const { value, onChange } = useFilterField(field);
17
+ const errorId = useId();
17
18
  const [draftMin, setDraftMin] = useState(value?.min ?? "");
18
19
  const [draftMax, setDraftMax] = useState(value?.max ?? "");
19
20
 
@@ -44,8 +45,33 @@ export function NumericRangeFilter({ field, label, helpText, min, max }: Numeric
44
45
  setDraftMax(value?.max ?? "");
45
46
  }, [value?.min, value?.max]);
46
47
 
48
+ const isOutOfBounds = (v: string) => {
49
+ if (v === "") return false;
50
+ const n = Number(v);
51
+ return (min != null && n < min) || (max != null && n > max);
52
+ };
53
+ const minOutOfBounds = isOutOfBounds(draftMin);
54
+ const maxOutOfBounds = isOutOfBounds(draftMax);
55
+ const isRangeInverted = draftMin !== "" && draftMax !== "" && Number(draftMin) > Number(draftMax);
56
+ const hasError = minOutOfBounds || maxOutOfBounds || isRangeInverted;
57
+
58
+ const boundsLabel =
59
+ min != null && max != null
60
+ ? `${min}–${max}`
61
+ : min != null
62
+ ? `${min} or more`
63
+ : max != null
64
+ ? `${max} or less`
65
+ : null;
66
+
67
+ const errorMessage = isRangeInverted
68
+ ? "Min must not exceed max"
69
+ : (minOutOfBounds || maxOutOfBounds) && boundsLabel
70
+ ? `Value must be between ${boundsLabel}`
71
+ : undefined;
72
+
47
73
  return (
48
- <FilterFieldWrapper label={label} helpText={helpText}>
74
+ <FilterFieldWrapper label={label} helpText={helpText} error={errorMessage} errorId={errorId}>
49
75
  <div className="flex items-center gap-2">
50
76
  <Input
51
77
  type="number"
@@ -58,6 +84,8 @@ export function NumericRangeFilter({ field, label, helpText, min, max }: Numeric
58
84
  debouncedRef.current?.(e.target.value, draftMax);
59
85
  }}
60
86
  aria-label={`${label} minimum`}
87
+ aria-invalid={hasError || undefined}
88
+ aria-describedby={hasError ? errorId : undefined}
61
89
  />
62
90
  <span className="text-sm text-muted-foreground">–</span>
63
91
  <Input
@@ -71,6 +99,8 @@ export function NumericRangeFilter({ field, label, helpText, min, max }: Numeric
71
99
  debouncedRef.current?.(draftMin, e.target.value);
72
100
  }}
73
101
  aria-label={`${label} maximum`}
102
+ aria-invalid={hasError || undefined}
103
+ aria-describedby={hasError ? errorId : undefined}
74
104
  />
75
105
  </div>
76
106
  </FilterFieldWrapper>
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@salesforce/ui-bundle-template-base-sfdx-project",
3
- "version": "11.21.0",
3
+ "version": "11.22.1",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@salesforce/ui-bundle-template-base-sfdx-project",
9
- "version": "11.21.0",
9
+ "version": "11.22.1",
10
10
  "license": "SEE LICENSE IN LICENSE.txt",
11
11
  "dependencies": {
12
12
  "fast-xml-parser": "^5.9.3",
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/ui-bundle-template-base-sfdx-project",
3
- "version": "11.21.0",
3
+ "version": "11.22.1",
4
4
  "description": "Base SFDX project template",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "publishConfig": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/ui-bundle-template-app-react-sample-b2e",
3
- "version": "11.21.0",
3
+ "version": "11.22.1",
4
4
  "description": "Salesforce sample property rental React app",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "author": "",
@@ -16,7 +16,7 @@
16
16
  "clean": "rm -rf dist"
17
17
  },
18
18
  "dependencies": {
19
- "@salesforce/ui-bundle": "^11.21.0",
19
+ "@salesforce/ui-bundle": "^11.22.1",
20
20
  "sonner": "^1.7.0"
21
21
  },
22
22
  "devDependencies": {