@salesforce/ui-bundle-template-app-react-sample-b2e 11.7.0 → 11.8.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 +16 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/package.json +4 -4
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/dashboard/IssuesDonutChart.tsx +50 -29
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/properties/PropertyCard.tsx +10 -1
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/button.tsx +1 -1
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/datePicker.tsx +2 -2
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/table.tsx +9 -2
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/components/filters/DateFilter.tsx +1 -1
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/components/filters/FilterFieldWrapper.tsx +6 -1
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/components/filters/MultiSelectFilter.tsx +9 -1
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/pages/ApplicationSearch.tsx +11 -2
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/pages/MaintenanceRequestSearch.tsx +11 -2
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/pages/MaintenanceWorkerSearch.tsx +11 -2
- package/dist/package-lock.json +2 -2
- package/dist/package.json +1 -1
- package/package.json +2 -2
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.8.1](https://github.com/salesforce-experience-platform-emu/webapps/compare/v11.8.0...v11.8.1) (2026-07-06)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @salesforce/ui-bundle-template-base-sfdx-project
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## [11.8.0](https://github.com/salesforce-experience-platform-emu/webapps/compare/v11.7.0...v11.8.0) (2026-07-06)
|
|
15
|
+
|
|
16
|
+
**Note:** Version bump only for package @salesforce/ui-bundle-template-base-sfdx-project
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
6
22
|
## [11.7.0](https://github.com/salesforce-experience-platform-emu/webapps/compare/v11.6.0...v11.7.0) (2026-07-06)
|
|
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.
|
|
22
|
-
"@salesforce/ui-bundle": "^11.
|
|
21
|
+
"@salesforce/platform-sdk": "^11.8.1",
|
|
22
|
+
"@salesforce/ui-bundle": "^11.8.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.
|
|
50
|
-
"@salesforce/vite-plugin-ui-bundle": "^11.
|
|
49
|
+
"@salesforce/graphiti": "^11.8.1",
|
|
50
|
+
"@salesforce/vite-plugin-ui-bundle": "^11.8.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",
|
|
@@ -45,10 +45,24 @@ export const IssuesDonutChart: React.FC<IssuesDonutChartProps> = ({ data, loadin
|
|
|
45
45
|
const maxValue = data.length > 0 ? Math.max(...data.map((item) => item.value)) : 0;
|
|
46
46
|
const mainPercentage = total > 0 ? Math.round((maxValue / total) * 100) : 0;
|
|
47
47
|
|
|
48
|
+
// Recharts renders each sector as an <svg><path role="img">, but arbitrary ARIA
|
|
49
|
+
// props on <Cell> are not reliably forwarded to that path. Instead of labelling
|
|
50
|
+
// each slice, expose the whole chart as a single labelled image summarizing the
|
|
51
|
+
// data, and hide the decorative SVG internals from assistive technology.
|
|
52
|
+
const chartSummary =
|
|
53
|
+
total > 0
|
|
54
|
+
? `Top maintenance issues: ${data
|
|
55
|
+
.map((item) => `${item.name} ${Math.round((item.value / total) * 100)}%`)
|
|
56
|
+
.join(", ")}.`
|
|
57
|
+
: "Top maintenance issues: no data available.";
|
|
58
|
+
|
|
48
59
|
return (
|
|
49
60
|
<Card className="p-4 border-gray-200 shadow-sm flex flex-col relative">
|
|
50
61
|
{/* Three-dot menu */}
|
|
51
|
-
<button
|
|
62
|
+
<button
|
|
63
|
+
className="absolute top-4 right-4 p-1 hover:bg-gray-100 rounded-md transition-colors z-10"
|
|
64
|
+
aria-label="More options"
|
|
65
|
+
>
|
|
52
66
|
<MoreVertical className="w-4 h-4 text-gray-400" />
|
|
53
67
|
</button>
|
|
54
68
|
|
|
@@ -71,34 +85,41 @@ export const IssuesDonutChart: React.FC<IssuesDonutChartProps> = ({ data, loadin
|
|
|
71
85
|
</>
|
|
72
86
|
) : (
|
|
73
87
|
<>
|
|
74
|
-
<div
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
88
|
+
<div
|
|
89
|
+
className="relative flex items-center justify-center"
|
|
90
|
+
role="img"
|
|
91
|
+
aria-label={chartSummary}
|
|
92
|
+
>
|
|
93
|
+
<div aria-hidden="true" className="w-full">
|
|
94
|
+
<ResponsiveContainer width="100%" height={300}>
|
|
95
|
+
<PieChart>
|
|
96
|
+
<Pie
|
|
97
|
+
data={data}
|
|
98
|
+
cx="50%"
|
|
99
|
+
cy="50%"
|
|
100
|
+
innerRadius={70}
|
|
101
|
+
outerRadius={110}
|
|
102
|
+
paddingAngle={2}
|
|
103
|
+
dataKey="value"
|
|
104
|
+
rootTabIndex={-1}
|
|
105
|
+
>
|
|
106
|
+
{data.map((entry, index) => (
|
|
107
|
+
<Cell key={`cell-${index}`} fill={entry.color} />
|
|
108
|
+
))}
|
|
109
|
+
</Pie>
|
|
110
|
+
<Tooltip
|
|
111
|
+
content={(props) => (
|
|
112
|
+
<CustomTooltip
|
|
113
|
+
active={props.active}
|
|
114
|
+
payload={props.payload as CustomTooltipProps["payload"]}
|
|
115
|
+
total={total}
|
|
116
|
+
/>
|
|
117
|
+
)}
|
|
118
|
+
wrapperStyle={{ zIndex: 1000 }}
|
|
119
|
+
/>
|
|
120
|
+
</PieChart>
|
|
121
|
+
</ResponsiveContainer>
|
|
122
|
+
</div>
|
|
102
123
|
{/* Center text */}
|
|
103
124
|
<div className="absolute inset-0 flex items-center justify-center pointer-events-none">
|
|
104
125
|
<div className="text-center">
|
|
@@ -32,8 +32,17 @@ export const PropertyCard: React.FC<PropertyCardProps> = ({ property, onClick })
|
|
|
32
32
|
|
|
33
33
|
return (
|
|
34
34
|
<div
|
|
35
|
-
|
|
35
|
+
role="button"
|
|
36
|
+
tabIndex={0}
|
|
37
|
+
aria-label={name}
|
|
38
|
+
className="bg-white rounded-lg shadow-md overflow-hidden hover:shadow-lg transition-shadow cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-purple focus-visible:ring-offset-2"
|
|
36
39
|
onClick={handleClick}
|
|
40
|
+
onKeyDown={(e) => {
|
|
41
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
42
|
+
e.preventDefault();
|
|
43
|
+
handleClick();
|
|
44
|
+
}
|
|
45
|
+
}}
|
|
37
46
|
>
|
|
38
47
|
<div className="relative h-48 bg-gray-200">
|
|
39
48
|
{heroImage && !imageError ? (
|
package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/button.tsx
CHANGED
|
@@ -17,7 +17,7 @@ const buttonVariants = cva(
|
|
|
17
17
|
ghost:
|
|
18
18
|
'hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground',
|
|
19
19
|
destructive:
|
|
20
|
-
'bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30',
|
|
20
|
+
'bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-red-700 dark:text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30',
|
|
21
21
|
link: 'text-primary underline-offset-4 hover:underline',
|
|
22
22
|
},
|
|
23
23
|
size: {
|
package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/datePicker.tsx
CHANGED
|
@@ -38,7 +38,7 @@ function DatePickerTrigger({
|
|
|
38
38
|
data-slot="date-picker-trigger"
|
|
39
39
|
data-empty={!date}
|
|
40
40
|
className={cn(
|
|
41
|
-
'w-[280px] justify-start text-left font-normal data-[empty=true]:text-
|
|
41
|
+
'w-[280px] justify-start text-left font-normal data-[empty=true]:text-gray-600',
|
|
42
42
|
className
|
|
43
43
|
)}
|
|
44
44
|
{...props}
|
|
@@ -87,7 +87,7 @@ function DatePickerRangeTrigger({
|
|
|
87
87
|
data-slot="date-picker-range-trigger"
|
|
88
88
|
data-empty={!hasDate}
|
|
89
89
|
className={cn(
|
|
90
|
-
'justify-start text-left font-normal data-[empty=true]:text-
|
|
90
|
+
'justify-start text-left font-normal data-[empty=true]:text-gray-600',
|
|
91
91
|
className
|
|
92
92
|
)}
|
|
93
93
|
{...props}
|
package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/table.tsx
CHANGED
|
@@ -2,11 +2,18 @@ import * as React from 'react';
|
|
|
2
2
|
|
|
3
3
|
import { cn } from '../../lib/utils';
|
|
4
4
|
|
|
5
|
-
function Table({
|
|
5
|
+
function Table({
|
|
6
|
+
className,
|
|
7
|
+
'aria-label': ariaLabel = 'Table',
|
|
8
|
+
...props
|
|
9
|
+
}: React.ComponentProps<'table'>) {
|
|
6
10
|
return (
|
|
7
11
|
<div
|
|
8
12
|
data-slot="table-container"
|
|
9
|
-
|
|
13
|
+
role="region"
|
|
14
|
+
aria-label={ariaLabel}
|
|
15
|
+
tabIndex={0}
|
|
16
|
+
className="relative w-full overflow-x-auto focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-purple"
|
|
10
17
|
>
|
|
11
18
|
<table
|
|
12
19
|
data-slot="table"
|
|
@@ -83,7 +83,7 @@ export function DateFilter({
|
|
|
83
83
|
<FilterFieldWrapper label={label} helpText={helpText} className={className} {...props}>
|
|
84
84
|
<div className="flex gap-2">
|
|
85
85
|
<Select value={operator} onValueChange={(v) => handleOperatorChange(v as DateOperator)}>
|
|
86
|
-
<SelectTrigger className="w-full flex-1">
|
|
86
|
+
<SelectTrigger className="w-full flex-1" aria-label={label}>
|
|
87
87
|
<SelectValue />
|
|
88
88
|
</SelectTrigger>
|
|
89
89
|
<SelectContent>
|
|
@@ -4,6 +4,8 @@ import { cn } from "../../../../lib/utils";
|
|
|
4
4
|
interface FilterFieldWrapperProps extends React.ComponentProps<"div"> {
|
|
5
5
|
label: string;
|
|
6
6
|
htmlFor?: string;
|
|
7
|
+
/** id applied to the visible label so a non-native control can reference it via aria-labelledby */
|
|
8
|
+
labelId?: string;
|
|
7
9
|
helpText?: string;
|
|
8
10
|
error?: string;
|
|
9
11
|
}
|
|
@@ -11,6 +13,7 @@ interface FilterFieldWrapperProps extends React.ComponentProps<"div"> {
|
|
|
11
13
|
export function FilterFieldWrapper({
|
|
12
14
|
label,
|
|
13
15
|
htmlFor,
|
|
16
|
+
labelId,
|
|
14
17
|
helpText,
|
|
15
18
|
error,
|
|
16
19
|
className,
|
|
@@ -19,7 +22,9 @@ export function FilterFieldWrapper({
|
|
|
19
22
|
}: FilterFieldWrapperProps) {
|
|
20
23
|
return (
|
|
21
24
|
<div className={cn("space-y-1", className)} {...props}>
|
|
22
|
-
<Label htmlFor={htmlFor}>
|
|
25
|
+
<Label id={labelId} htmlFor={htmlFor}>
|
|
26
|
+
{label}
|
|
27
|
+
</Label>
|
|
23
28
|
{children}
|
|
24
29
|
<div className="min-h-4">
|
|
25
30
|
{error ? (
|
|
@@ -28,6 +28,7 @@ export function MultiSelectFilter({
|
|
|
28
28
|
}: MultiSelectFilterProps) {
|
|
29
29
|
const { value, onChange } = useFilterField(field);
|
|
30
30
|
const selected = value?.value ? value.value.split(",") : [];
|
|
31
|
+
const labelId = `filter-${field}-label`;
|
|
31
32
|
|
|
32
33
|
const triggerLabel =
|
|
33
34
|
selected.length === 0
|
|
@@ -54,12 +55,19 @@ export function MultiSelectFilter({
|
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
return (
|
|
57
|
-
<FilterFieldWrapper
|
|
58
|
+
<FilterFieldWrapper
|
|
59
|
+
label={label}
|
|
60
|
+
labelId={labelId}
|
|
61
|
+
helpText={helpText}
|
|
62
|
+
className={className}
|
|
63
|
+
{...props}
|
|
64
|
+
>
|
|
58
65
|
<Popover>
|
|
59
66
|
<PopoverTrigger asChild>
|
|
60
67
|
<Button
|
|
61
68
|
variant="outline"
|
|
62
69
|
role="combobox"
|
|
70
|
+
aria-labelledby={labelId}
|
|
63
71
|
className={cn(
|
|
64
72
|
"w-full justify-between font-normal",
|
|
65
73
|
selected.length === 0 && "text-muted-foreground",
|
package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/pages/ApplicationSearch.tsx
CHANGED
|
@@ -142,7 +142,7 @@ export default function ApplicationSearch() {
|
|
|
142
142
|
resetAll={resetAll}
|
|
143
143
|
/>
|
|
144
144
|
<div className="bg-white rounded-lg shadow-sm border border-gray-200 overflow-hidden">
|
|
145
|
-
<Table>
|
|
145
|
+
<Table aria-label="Applications">
|
|
146
146
|
<ApplicationSearchTableHeader />
|
|
147
147
|
<TableBody>
|
|
148
148
|
{loading && <ApplicationSearchSkeleton pageSize={pagination.pageSize} />}
|
|
@@ -282,8 +282,17 @@ function ApplicationSearchTable({
|
|
|
282
282
|
return (
|
|
283
283
|
<TableRow
|
|
284
284
|
key={application.Id}
|
|
285
|
+
role="button"
|
|
286
|
+
tabIndex={0}
|
|
287
|
+
aria-label={applicationName}
|
|
285
288
|
onClick={() => setSelectedApplication(application)}
|
|
286
|
-
|
|
289
|
+
onKeyDown={(e) => {
|
|
290
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
291
|
+
e.preventDefault();
|
|
292
|
+
setSelectedApplication(application);
|
|
293
|
+
}
|
|
294
|
+
}}
|
|
295
|
+
className="hover:bg-gray-50 transition-colors cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-purple focus-visible:ring-inset"
|
|
287
296
|
>
|
|
288
297
|
<TableCell className="px-6 py-4">
|
|
289
298
|
<div className="text-sm font-medium text-gray-900">{applicationName}</div>
|
|
@@ -162,7 +162,7 @@ export default function MaintenanceRequestSearch() {
|
|
|
162
162
|
/>
|
|
163
163
|
|
|
164
164
|
<div className="bg-white rounded-lg shadow-sm border border-gray-200 overflow-hidden">
|
|
165
|
-
<Table>
|
|
165
|
+
<Table aria-label="Maintenance requests">
|
|
166
166
|
<MaintenanceRequestSearchTableHeader />
|
|
167
167
|
<TableBody>
|
|
168
168
|
{loading && <MaintenanceRequestSearchSkeleton pageSize={pagination.pageSize} />}
|
|
@@ -328,8 +328,17 @@ function MaintenanceRequestSearchTable({
|
|
|
328
328
|
return (
|
|
329
329
|
<TableRow
|
|
330
330
|
key={request.Id}
|
|
331
|
+
role="button"
|
|
332
|
+
tabIndex={0}
|
|
333
|
+
aria-label={requestName}
|
|
331
334
|
onClick={() => setSelectedRequest(request)}
|
|
332
|
-
|
|
335
|
+
onKeyDown={(e) => {
|
|
336
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
337
|
+
e.preventDefault();
|
|
338
|
+
setSelectedRequest(request);
|
|
339
|
+
}
|
|
340
|
+
}}
|
|
341
|
+
className="hover:bg-gray-50 transition-colors cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-purple focus-visible:ring-inset"
|
|
333
342
|
>
|
|
334
343
|
<TableCell className="max-w-xs px-6 py-5">
|
|
335
344
|
<div className="flex items-center gap-4">
|
|
@@ -109,7 +109,7 @@ export default function MaintenanceWorkerSearch() {
|
|
|
109
109
|
/>
|
|
110
110
|
|
|
111
111
|
<div className="bg-white rounded-lg shadow-sm border border-gray-200 overflow-hidden">
|
|
112
|
-
<Table>
|
|
112
|
+
<Table aria-label="Maintenance workers">
|
|
113
113
|
<MaintenanceWorkerSearchTableHeader />
|
|
114
114
|
<TableBody>
|
|
115
115
|
{loading && <MaintenanceWorkerSearchSkeleton pageSize={pagination.pageSize} />}
|
|
@@ -265,8 +265,17 @@ function MaintenanceWorkerSearchTable({
|
|
|
265
265
|
return (
|
|
266
266
|
<TableRow
|
|
267
267
|
key={worker.Id}
|
|
268
|
+
role="button"
|
|
269
|
+
tabIndex={0}
|
|
270
|
+
aria-label={name}
|
|
268
271
|
onClick={() => setSelectedWorker(worker)}
|
|
269
|
-
|
|
272
|
+
onKeyDown={(e) => {
|
|
273
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
274
|
+
e.preventDefault();
|
|
275
|
+
setSelectedWorker(worker);
|
|
276
|
+
}
|
|
277
|
+
}}
|
|
278
|
+
className="hover:bg-gray-50 transition-colors cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-purple focus-visible:ring-inset"
|
|
270
279
|
>
|
|
271
280
|
<TableCell className="px-6 py-4 font-medium text-gray-900">{name}</TableCell>
|
|
272
281
|
<TableCell className="px-6 py-4 text-gray-600">
|
package/dist/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/webapp-template-base-sfdx-project-experimental",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.8.1",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@salesforce/webapp-template-base-sfdx-project-experimental",
|
|
9
|
-
"version": "11.
|
|
9
|
+
"version": "11.8.1",
|
|
10
10
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
11
11
|
"devDependencies": {
|
|
12
12
|
"@lwc/eslint-plugin-lwc": "^3.3.0",
|
package/dist/package.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/ui-bundle-template-app-react-sample-b2e",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.8.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.
|
|
19
|
+
"@salesforce/ui-bundle": "^11.8.1",
|
|
20
20
|
"sonner": "^1.7.0"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|