@gogitcms/design-system 0.16.0-next.8 → 0.16.0-next.9
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gogitcms/design-system",
|
|
3
|
-
"version": "0.16.0-next.
|
|
3
|
+
"version": "0.16.0-next.9",
|
|
4
4
|
"main": "src/index.ts",
|
|
5
5
|
"types": "src/index.ts",
|
|
6
6
|
"// exports": "The root entry is the react-native source the SPAs, desktop app and mobile app consume. ./web is the plain-DOM build for server-rendered surfaces (the Astro docs site) that don't run react-native-web, and ./css ships the tokens as custom properties. The trailing wildcard keeps deep paths resolvable — plugin bundling and the Vite aliases reach into src/ directly.",
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { render, screen, fireEvent } from "@testing-library/react";
|
|
3
|
+
import { ThemeProvider } from "../ThemeProvider";
|
|
4
|
+
import { BranchDeletedModal } from "../components/BranchDeletedModal";
|
|
5
|
+
|
|
6
|
+
const wrap = (ui: React.ReactElement) => <ThemeProvider>{ui}</ThemeProvider>;
|
|
7
|
+
|
|
8
|
+
const others = [
|
|
9
|
+
{ id: "b-main", name: "main" },
|
|
10
|
+
{ id: "b-draft", name: "draft/spring" },
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
test("names the deleted branch and switches to the one picked", () => {
|
|
14
|
+
const onSwitch = jest.fn();
|
|
15
|
+
render(wrap(
|
|
16
|
+
<BranchDeletedModal branch="feat/pricing" repository="acme/site" branches={others} onSwitch={onSwitch} />,
|
|
17
|
+
));
|
|
18
|
+
|
|
19
|
+
expect(screen.getByTestId("branch-deleted-title")).toHaveTextContent("feat/pricing was deleted");
|
|
20
|
+
expect(screen.getByText(/removed with it/)).toBeInTheDocument();
|
|
21
|
+
|
|
22
|
+
fireEvent.click(screen.getByTestId("branch-deleted-switch-b-draft"));
|
|
23
|
+
expect(onSwitch).toHaveBeenCalledWith(others[1]);
|
|
24
|
+
// The repository exit is not offered unless the host provides it.
|
|
25
|
+
expect(screen.queryByTestId("branch-deleted-choose-repository")).toBeNull();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test("a stale link (no branch name) still explains and offers the others", () => {
|
|
29
|
+
render(wrap(<BranchDeletedModal branches={others} onSwitch={() => {}} />));
|
|
30
|
+
expect(screen.getByTestId("branch-deleted-title")).toHaveTextContent("This branch no longer exists");
|
|
31
|
+
expect(screen.getByTestId("branch-deleted-switch-b-main")).toBeInTheDocument();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test("with nothing to switch to, the repository picker is the exit", () => {
|
|
35
|
+
const onChoose = jest.fn();
|
|
36
|
+
render(wrap(
|
|
37
|
+
<BranchDeletedModal branch="main" repository="acme/site" branches={[]} onSwitch={() => {}} onChooseRepository={onChoose} />,
|
|
38
|
+
));
|
|
39
|
+
expect(screen.getByTestId("branch-deleted-none")).toHaveTextContent("No other branch of acme/site");
|
|
40
|
+
fireEvent.click(screen.getByTestId("branch-deleted-choose-repository"));
|
|
41
|
+
expect(onChoose).toHaveBeenCalled();
|
|
42
|
+
});
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { View, ScrollView } from "react-native";
|
|
3
|
+
import { useTheme } from "../ThemeProvider";
|
|
4
|
+
import { Text } from "./Text";
|
|
5
|
+
import { Icon } from "./Icon";
|
|
6
|
+
import { Button } from "./Button";
|
|
7
|
+
import type { BranchRef } from "./BranchMenu";
|
|
8
|
+
|
|
9
|
+
export type BranchDeletedModalProps = {
|
|
10
|
+
/**
|
|
11
|
+
* The branch that no longer exists. Omitted when only its id is known — a
|
|
12
|
+
* link into a branch that was deleted before the page loaded.
|
|
13
|
+
*/
|
|
14
|
+
branch?: string;
|
|
15
|
+
/** "owner/name", when the host knows it. */
|
|
16
|
+
repository?: string;
|
|
17
|
+
/** The branches still connected, to switch to. The deleted one is not among them. */
|
|
18
|
+
branches: BranchRef[];
|
|
19
|
+
/** Open the editor on `branch` instead. */
|
|
20
|
+
onSwitch: (branch: BranchRef) => void;
|
|
21
|
+
/**
|
|
22
|
+
* Leave this repository for the picker. Offered as the way out when there is
|
|
23
|
+
* no other branch to switch to; omitted → the list is the only exit.
|
|
24
|
+
*/
|
|
25
|
+
onChooseRepository?: () => void;
|
|
26
|
+
testID?: string;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Shown when the branch the editor is on stops existing — deleted on the
|
|
31
|
+
* provider, or disconnected from the CMS — while someone is looking at it.
|
|
32
|
+
*
|
|
33
|
+
* It is a modal rather than a redirect because the screen behind it may hold
|
|
34
|
+
* work in progress. Nothing on it can be saved to this branch any more, but
|
|
35
|
+
* bouncing the user to another branch without a word would make that content
|
|
36
|
+
* vanish mid-thought; the modal says what happened and leaves the page visible
|
|
37
|
+
* while they decide where to go. It cannot be dismissed into the dead branch,
|
|
38
|
+
* because there is nothing there to go back to: every exit is another branch.
|
|
39
|
+
*/
|
|
40
|
+
export function BranchDeletedModal({
|
|
41
|
+
branch, repository, branches, onSwitch, onChooseRepository, testID,
|
|
42
|
+
}: BranchDeletedModalProps) {
|
|
43
|
+
const t = useTheme();
|
|
44
|
+
const title = branch ? `${branch} was deleted` : "This branch no longer exists";
|
|
45
|
+
const where = repository ? ` in ${repository}` : "";
|
|
46
|
+
const detail = branch
|
|
47
|
+
? `The ${branch} branch${where} was deleted on the remote or disconnected from the CMS, and its content was removed with it. Nothing on this screen can be saved to it any more.`
|
|
48
|
+
: `The branch this link points to${where} was deleted on the remote or disconnected from the CMS, so there is nothing here to edit.`;
|
|
49
|
+
const hasOthers = branches.length > 0;
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<View
|
|
53
|
+
testID={testID ?? "branch-deleted-modal"}
|
|
54
|
+
style={{
|
|
55
|
+
position: "absolute", top: 0, left: 0, right: 0, bottom: 0, zIndex: 50,
|
|
56
|
+
alignItems: "center", justifyContent: "center", padding: t.space(4),
|
|
57
|
+
backgroundColor: "rgba(0,0,0,0.45)",
|
|
58
|
+
}}
|
|
59
|
+
>
|
|
60
|
+
<View
|
|
61
|
+
style={{
|
|
62
|
+
width: 460, maxWidth: "100%", maxHeight: "100%", gap: t.space(4), padding: t.space(5),
|
|
63
|
+
borderRadius: t.radius.lg, borderWidth: 1, borderColor: t.color.borderDefault,
|
|
64
|
+
backgroundColor: t.color.surfaceRaised,
|
|
65
|
+
}}
|
|
66
|
+
>
|
|
67
|
+
<View style={{ flexDirection: "row", alignItems: "center", gap: t.space(2) }}>
|
|
68
|
+
<Icon name="alert" size={16} color={t.color.diffDelFg} />
|
|
69
|
+
<Text variant="h3" weight="semibold" testID="branch-deleted-title">{title}</Text>
|
|
70
|
+
</View>
|
|
71
|
+
|
|
72
|
+
<Text variant="body" color="secondary">{detail}</Text>
|
|
73
|
+
|
|
74
|
+
{hasOthers ? (
|
|
75
|
+
<>
|
|
76
|
+
<Text variant="sm" weight="semibold">Switch to another branch to keep working</Text>
|
|
77
|
+
<ScrollView style={{ maxHeight: 280 }} contentContainerStyle={{ gap: t.space(2) }}>
|
|
78
|
+
{branches.map((b) => (
|
|
79
|
+
<Button
|
|
80
|
+
key={b.id}
|
|
81
|
+
title={b.name}
|
|
82
|
+
fullWidth
|
|
83
|
+
onPress={() => onSwitch(b)}
|
|
84
|
+
testID={`branch-deleted-switch-${b.id}`}
|
|
85
|
+
/>
|
|
86
|
+
))}
|
|
87
|
+
</ScrollView>
|
|
88
|
+
</>
|
|
89
|
+
) : (
|
|
90
|
+
<Text variant="sm" color="secondary" testID="branch-deleted-none">
|
|
91
|
+
{repository
|
|
92
|
+
? `No other branch of ${repository} is connected to the CMS.`
|
|
93
|
+
: "No other branch of this repository is connected to the CMS."}
|
|
94
|
+
</Text>
|
|
95
|
+
)}
|
|
96
|
+
|
|
97
|
+
{onChooseRepository ? (
|
|
98
|
+
<View style={{ flexDirection: "row", justifyContent: "flex-end" }}>
|
|
99
|
+
<Button
|
|
100
|
+
title="Choose a repository"
|
|
101
|
+
variant={hasOthers ? "ghost" : "primary"}
|
|
102
|
+
size="md"
|
|
103
|
+
onPress={onChooseRepository}
|
|
104
|
+
testID="branch-deleted-choose-repository"
|
|
105
|
+
/>
|
|
106
|
+
</View>
|
|
107
|
+
) : null}
|
|
108
|
+
</View>
|
|
109
|
+
</View>
|
|
110
|
+
);
|
|
111
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -57,6 +57,8 @@ export type {
|
|
|
57
57
|
// Change-request summary surface (developer escalation)
|
|
58
58
|
export { ProtectedBranchModal } from "./components/ProtectedBranchModal";
|
|
59
59
|
export type { ProtectedBranchModalProps } from "./components/ProtectedBranchModal";
|
|
60
|
+
export { BranchDeletedModal } from "./components/BranchDeletedModal";
|
|
61
|
+
export type { BranchDeletedModalProps } from "./components/BranchDeletedModal";
|
|
60
62
|
export { ChangeRequestSummary } from "./components/ChangeRequestSummary";
|
|
61
63
|
export type {
|
|
62
64
|
ChangeRequestSummaryProps,
|