tsondb 0.7.6 → 0.7.8

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 (74) hide show
  1. package/dist/src/node/schema/Node.d.ts +8 -1
  2. package/dist/src/node/schema/Node.js +34 -18
  3. package/dist/src/node/schema/Schema.js +14 -10
  4. package/dist/src/node/schema/TypeParameter.js +1 -1
  5. package/dist/src/node/schema/declarations/EntityDecl.js +1 -1
  6. package/dist/src/node/schema/declarations/EnumDecl.js +1 -1
  7. package/dist/src/node/schema/declarations/TypeAliasDecl.js +1 -1
  8. package/dist/src/node/schema/types/generic/ArrayType.js +1 -1
  9. package/dist/src/node/schema/types/generic/EnumType.js +1 -1
  10. package/dist/src/node/schema/types/generic/ObjectType.js +1 -1
  11. package/dist/src/node/schema/types/references/ChildEntitiesType.js +1 -1
  12. package/dist/src/node/schema/types/references/IncludeIdentifierType.js +2 -2
  13. package/dist/src/node/schema/types/references/NestedEntityMapType.d.ts +12 -2
  14. package/dist/src/node/schema/types/references/NestedEntityMapType.js +2 -2
  15. package/dist/src/node/schema/types/references/ReferenceIdentifierType.js +2 -2
  16. package/dist/src/node/server/api/git.js +156 -24
  17. package/dist/src/node/server/index.js +4 -0
  18. package/dist/src/node/utils/instanceOperations.d.ts +1 -1
  19. package/dist/src/node/utils/instanceOperations.js +2 -2
  20. package/dist/src/shared/api.d.ts +17 -1
  21. package/dist/src/shared/schema/declarations/EntityDecl.d.ts +2 -0
  22. package/dist/src/shared/schema/declarations/EntityDecl.js +2 -0
  23. package/dist/src/shared/schema/declarations/EnumDecl.d.ts +2 -1
  24. package/dist/src/shared/schema/declarations/EnumDecl.js +2 -0
  25. package/dist/src/shared/schema/declarations/TypeAliasDecl.d.ts +2 -1
  26. package/dist/src/shared/schema/declarations/TypeAliasDecl.js +2 -1
  27. package/dist/src/shared/utils/git.d.ts +4 -0
  28. package/dist/src/shared/utils/git.js +6 -1
  29. package/dist/src/shared/utils/markdown.d.ts +36 -17
  30. package/dist/src/shared/utils/markdown.js +79 -23
  31. package/dist/src/shared/utils/object.d.ts +1 -0
  32. package/dist/src/shared/utils/object.js +1 -0
  33. package/dist/src/web/api/git.d.ts +5 -1
  34. package/dist/src/web/api/git.js +6 -2
  35. package/dist/src/web/components/ContextProviderWrapper.d.ts +7 -0
  36. package/dist/src/web/components/ContextProviderWrapper.js +5 -0
  37. package/dist/src/web/components/InstanceRouteSkeleton.d.ts +6 -0
  38. package/dist/src/web/components/InstanceRouteSkeleton.js +12 -8
  39. package/dist/src/web/components/LoadingOverlay.d.ts +1 -0
  40. package/dist/src/web/components/LoadingOverlay.js +3 -0
  41. package/dist/src/web/components/ModalDialog.js +4 -3
  42. package/dist/src/web/components/git/Git.js +47 -0
  43. package/dist/src/web/components/git/GitBranchManager.d.ts +7 -0
  44. package/dist/src/web/components/git/GitBranchManager.js +17 -0
  45. package/dist/src/web/components/git/GitFileList.d.ts +17 -0
  46. package/dist/src/web/components/git/GitFileList.js +11 -0
  47. package/dist/src/web/components/git/GitFileManager.d.ts +8 -0
  48. package/dist/src/web/components/git/GitFileManager.js +34 -0
  49. package/dist/src/web/components/git/GitStatusIndicator.d.ts +7 -0
  50. package/dist/src/web/components/git/GitStatusIndicator.js +6 -0
  51. package/dist/src/web/components/typeInputs/StringTypeInput.js +1 -1
  52. package/dist/src/web/components/typeInputs/utils/MismatchingTypeError.js +2 -2
  53. package/dist/src/web/context/entities.d.ts +6 -5
  54. package/dist/src/web/context/git.d.ts +2 -1
  55. package/dist/src/web/context/gitClient.d.ts +2 -0
  56. package/dist/src/web/context/gitClient.js +2 -0
  57. package/dist/src/web/hooks/useGitClient.d.ts +37 -0
  58. package/dist/src/web/hooks/useGitClient.js +313 -0
  59. package/dist/src/web/hooks/useSecondaryDeclarations.js +6 -3
  60. package/dist/src/web/hooks/useSettings.js +0 -1
  61. package/dist/src/web/index.js +6 -2
  62. package/dist/src/web/routes/CreateInstance.js +29 -23
  63. package/dist/src/web/routes/Entity.js +10 -4
  64. package/dist/src/web/routes/Instance.js +21 -8
  65. package/dist/src/web/signals/loading.d.ts +2 -0
  66. package/dist/src/web/signals/loading.js +11 -0
  67. package/dist/src/web/utils/BlockMarkdown.js +1 -1
  68. package/dist/src/web/utils/debug.d.ts +1 -0
  69. package/dist/src/web/utils/debug.js +4 -0
  70. package/dist/src/web/utils/typeSkeleton.js +1 -1
  71. package/package.json +3 -3
  72. package/public/css/styles.css +132 -70
  73. package/dist/src/web/components/Git.js +0 -164
  74. /package/dist/src/web/components/{Git.d.ts → git/Git.d.ts} +0 -0
@@ -11,29 +11,31 @@ const titleBuilder = ({ entity }) => {
11
11
  const entityName = entity.name;
12
12
  return "New " + toTitleCase(entityName) + " — TSONDB";
13
13
  };
14
- const onSubmit = async ({ locales, entity, buttonName, instanceContent, isLocaleEntity, customId, childInstances, setInstanceContent, setCustomId, route, getDeclFromDeclName, }) => {
14
+ const onSubmit = async ({ locales, entity, buttonName, instanceContent, isLocaleEntity, customId, childInstances, setInstanceContent, setCustomId, route, getDeclFromDeclName, updateLocalGitState, }) => {
15
15
  try {
16
- const createdInstance = await createInstanceByEntityNameAndId(locales, entity.name, {
17
- childInstances,
18
- entityName: entity.name,
19
- content: instanceContent,
20
- id: undefined,
21
- }, isLocaleEntity ? customId : undefined);
22
- switch (buttonName) {
23
- case "saveandcontinue": {
24
- route(`/entities/${entity.name}/instances/${createdInstance.instance.id}`);
25
- break;
26
- }
27
- case "saveandaddanother": {
28
- setInstanceContent(createTypeSkeleton(getDeclFromDeclName, entity.type));
29
- setCustomId("");
30
- alert(`Instance of entity ${entity.name} created successfully with identifier ${createdInstance.instance.id}. You can add another instance now.`);
31
- break;
32
- }
33
- case "save":
34
- default: {
35
- route(`/entities/${entity.name}?created=${encodeURIComponent(createdInstance.instance.id)}`);
36
- break;
16
+ if (buttonName) {
17
+ const createdInstance = await createInstanceByEntityNameAndId(locales, entity.name, {
18
+ childInstances,
19
+ entityName: entity.name,
20
+ content: instanceContent,
21
+ id: undefined,
22
+ }, isLocaleEntity ? customId : undefined);
23
+ await updateLocalGitState?.();
24
+ switch (buttonName) {
25
+ case "saveandcontinue": {
26
+ route(`/entities/${entity.name}/instances/${createdInstance.instance.id}`);
27
+ break;
28
+ }
29
+ case "saveandaddanother": {
30
+ setInstanceContent(createTypeSkeleton(getDeclFromDeclName, entity.type));
31
+ setCustomId("");
32
+ alert(`Instance of entity ${entity.name} created successfully with identifier ${createdInstance.instance.id}. You can add another instance now.`);
33
+ break;
34
+ }
35
+ case "save": {
36
+ route(`/entities/${entity.name}?created=${encodeURIComponent(createdInstance.instance.id)}`);
37
+ break;
38
+ }
37
39
  }
38
40
  }
39
41
  }
@@ -43,4 +45,8 @@ const onSubmit = async ({ locales, entity, buttonName, instanceContent, isLocale
43
45
  }
44
46
  }
45
47
  };
46
- export const CreateInstance = () => (_jsx(InstanceRouteSkeleton, { mode: "create", init: init, titleBuilder: titleBuilder, onSubmit: onSubmit }));
48
+ export const CreateInstance = () => (_jsx(InstanceRouteSkeleton, { mode: "create", buttons: [
49
+ { label: "Save", name: "save", primary: true },
50
+ { label: "Save and continue", name: "saveandcontinue" },
51
+ { label: "Save and add another", name: "saveandaddanother" },
52
+ ], init: init, titleBuilder: titleBuilder, onSubmit: onSubmit }));
@@ -1,12 +1,14 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
2
2
  import { useRoute } from "preact-iso";
3
3
  import { useContext, useEffect, useState } from "preact/hooks";
4
- import { getGitStatusForDisplay, getLabelForGitStatus } from "../../shared/utils/git.js";
4
+ import { getGitStatusForDisplay } from "../../shared/utils/git.js";
5
5
  import { toTitleCase } from "../../shared/utils/string.js";
6
6
  import { deleteInstanceByEntityNameAndId, getInstancesByEntityName, getLocaleInstances, } from "../api/declarations.js";
7
+ import { GitStatusIndicator } from "../components/git/GitStatusIndicator.js";
7
8
  import { Layout } from "../components/Layout.js";
8
9
  import { ConfigContext } from "../context/config.js";
9
10
  import { EntitiesContext } from "../context/entities.js";
11
+ import { GitClientContext } from "../context/gitClient.js";
10
12
  import { useEntityFromRoute } from "../hooks/useEntityFromRoute.js";
11
13
  import { useMappedAPIResource } from "../hooks/useMappedAPIResource.js";
12
14
  import { useSetting } from "../hooks/useSettings.js";
@@ -21,6 +23,7 @@ export const Entity = () => {
21
23
  const [searchText, setSearchText] = useState("");
22
24
  const entityFromRoute = useEntityFromRoute();
23
25
  const config = useContext(ConfigContext);
26
+ const gitClient = useContext(GitClientContext);
24
27
  const { reloadEntities } = useContext(EntitiesContext);
25
28
  const { declaration: entity, isLocaleEntity } = entityFromRoute ?? {};
26
29
  const [instances, reloadInstances] = useMappedAPIResource(getInstancesByEntityName, mapInstances, locales, name ?? "");
@@ -43,10 +46,13 @@ export const Entity = () => {
43
46
  return (_jsxs(Layout, { breadcrumbs: [{ url: "/", label: homeTitle }], children: [_jsxs("div", { class: "header-with-btns", children: [_jsx("h1", { children: toTitleCase(entity?.namePlural ?? name) }), _jsx("a", { class: "btn btn--primary", "aria-disabled": true, children: "Add" })] }), _jsx("p", { class: "loading", children: "Loading \u2026" })] }));
44
47
  }
45
48
  const lowerSearchText = searchText.toLowerCase();
46
- const filteredInstances = searchText.length === 0
49
+ const filteredInstances = (searchText.length === 0
47
50
  ? instances
48
51
  : instances.filter(instance => instance.id.includes(searchText) ||
49
- instance.displayName.toLowerCase().includes(lowerSearchText));
52
+ instance.displayName.toLowerCase().includes(lowerSearchText))).map(instance => ({
53
+ ...instance,
54
+ gitStatus: gitClient?.getGitStatusOfInstance(entity.name, instance.id),
55
+ }));
50
56
  const instancesByLocale = Object.groupBy(filteredInstances, instance => instance.displayNameLocaleId ?? "undefined");
51
57
  const groupedInstances = [...locales, "undefined"]
52
58
  .map(key => ({
@@ -59,7 +65,7 @@ export const Entity = () => {
59
65
  .filter(group => group.instances.length > 0);
60
66
  const instanceMapper = (instance) => {
61
67
  const gitStatusForDisplay = getGitStatusForDisplay(instance.gitStatus);
62
- return (_jsxs("li", { id: `instance-${instance.id}`, class: `entries-item ${created === instance.id ? "entries-item--created" : ""} ${gitStatusForDisplay === undefined ? "" : `git-status--${gitStatusForDisplay}`}`, children: [_jsx("h2", { class: "entries-item__title", children: instance.displayName }), _jsx("p", { "aria-hidden": true, class: "entries-item__subtitle entries-item__subtitle--id", children: instance.id }), _jsxs("div", { class: "entries-item__side", children: [gitStatusForDisplay !== undefined && (_jsx("p", { class: `git-status git-status--${gitStatusForDisplay}`, title: getLabelForGitStatus(gitStatusForDisplay), children: gitStatusForDisplay })), _jsxs("div", { class: "btns", children: [_jsx("a", { href: `/entities/${entity.name}/instances/${instance.id}`, class: "btn", children: "Edit" }), _jsx("button", { class: "destructive", onClick: () => {
68
+ return (_jsxs("li", { id: `instance-${instance.id}`, class: `entries-item ${created === instance.id ? "entries-item--created" : ""} ${gitStatusForDisplay === undefined ? "" : `git-status--${gitStatusForDisplay}`}`, children: [_jsx("h2", { class: "entries-item__title", children: instance.displayName }), _jsx("p", { "aria-hidden": true, class: "entries-item__subtitle entries-item__subtitle--id", children: instance.id }), _jsxs("div", { class: "entries-item__side", children: [_jsx(GitStatusIndicator, { status: instance.gitStatus }), _jsxs("div", { class: "btns", children: [_jsx("a", { href: `/entities/${entity.name}/instances/${instance.id}`, class: "btn", children: "Edit" }), _jsx("button", { class: "destructive", onClick: () => {
63
69
  if (confirm("Are you sure you want to delete this instance?")) {
64
70
  deleteInstanceByEntityNameAndId(locales, entity.name, instance.id)
65
71
  .then(() => reloadInstances())
@@ -21,23 +21,36 @@ const titleBuilder = ({ locales, entity, instanceId, instanceContent, }) => {
21
21
  }
22
22
  return undefined;
23
23
  };
24
- const onSubmit = async ({ locales, entity, instanceId, instanceContent, buttonName, childInstances, }) => {
25
- if (instanceId && buttonName === "save") {
26
- try {
24
+ const onSubmit = async ({ locales, entity, instanceId, instanceContent, buttonName, childInstances, route, updateLocalGitState, }) => {
25
+ try {
26
+ if (instanceId && buttonName) {
27
27
  await updateInstanceByEntityNameAndId(locales, entity.name, instanceId, {
28
28
  childInstances,
29
29
  entityName: entity.name,
30
30
  content: instanceContent,
31
31
  id: instanceId,
32
32
  });
33
- }
34
- catch (error) {
35
- if (error instanceof Error) {
36
- alert(`Error updating instance:\n\n${error}`);
33
+ await updateLocalGitState?.();
34
+ switch (buttonName) {
35
+ case "saveandcontinue": {
36
+ break;
37
+ }
38
+ case "save": {
39
+ route(`/entities/${entity.name}`);
40
+ break;
41
+ }
37
42
  }
38
43
  }
39
44
  }
45
+ catch (error) {
46
+ if (error instanceof Error) {
47
+ alert(`Error updating instance:\n\n${error}`);
48
+ }
49
+ }
40
50
  };
41
51
  export const Instance = () => {
42
- return (_jsx(InstanceRouteSkeleton, { mode: "edit", init: init, titleBuilder: titleBuilder, onSubmit: onSubmit }));
52
+ return (_jsx(InstanceRouteSkeleton, { mode: "edit", buttons: [
53
+ { label: "Save", name: "save", primary: true },
54
+ { label: "Save and continue", name: "saveandcontinue" },
55
+ ], init: init, titleBuilder: titleBuilder, onSubmit: onSubmit }));
43
56
  };
@@ -0,0 +1,2 @@
1
+ export declare const loading: import("@preact/signals-core").Signal<boolean>;
2
+ export declare const runWithLoading: <T>(fn: () => Promise<T>) => Promise<T>;
@@ -0,0 +1,11 @@
1
+ import { signal } from "@preact/signals";
2
+ export const loading = signal(false);
3
+ export const runWithLoading = async (fn) => {
4
+ loading.value = true;
5
+ try {
6
+ return await fn();
7
+ }
8
+ finally {
9
+ loading.value = false;
10
+ }
11
+ };
@@ -15,7 +15,7 @@ export const BlockMarkdown = ({ node, outerHeadingLevel = 0 }) => {
15
15
  return (_jsx("ul", { children: node.content.map((item, ii) => (_jsx("li", { children: item.content.map((inline, iii) => (_jsx(InlineMarkdown, { node: inline }, iii))) }, ii))) }));
16
16
  }
17
17
  case "table":
18
- return (_jsxs("table", { children: [_jsx("thead", { children: _jsx("tr", { children: node.header.map((th, hi) => (_jsx("th", { children: th.map((inline, hii) => (_jsx(InlineMarkdown, { node: inline }, hii))) }, hi))) }) }), _jsx("tbody", { children: node.rows.map((tr, ri) => (_jsx("tr", { children: tr.map((tc, ci) => (_jsx("td", { children: tc.map((inline, cii) => (_jsx(InlineMarkdown, { node: inline }, cii))) }, ci))) }, ri))) })] }));
18
+ return (_jsxs("table", { children: [node.caption !== undefined && (_jsx("caption", { children: node.caption.map((inline, ci) => (_jsx(InlineMarkdown, { node: inline }, ci))) })), _jsx("thead", { children: _jsx("tr", { children: node.header.map((th, hi) => (_jsx("th", { children: th.map((inline, hii) => (_jsx(InlineMarkdown, { node: inline }, hii))) }, hi))) }) }), _jsx("tbody", { children: node.rows.map((tr, ri) => (_jsx("tr", { children: tr.map((tc, ci) => (_jsx("td", { children: tc.map((inline, cii) => (_jsx(InlineMarkdown, { node: inline }, cii))) }, ci))) }, ri))) })] }));
19
19
  default:
20
20
  return null;
21
21
  }
@@ -1 +1,2 @@
1
1
  export declare const printJson: (data: unknown) => string;
2
+ export declare const logAndAlertError: (error: unknown, prependedMessage?: string) => void;
@@ -3,3 +3,7 @@ export const printJson = (data) => JSON.stringify(data, undefined, 2)
3
3
  .replace(/((?:^|\n *)[{[])\n +/g, "$1 ")
4
4
  .replace(/"(.+?)":/g, '<span style="color: darkorange">$1</span>:')
5
5
  .replace(/ "(.*?)"([ ,])/g, ' <span style="color: darkgreen">"$1"</span>$2');
6
+ export const logAndAlertError = (error, prependedMessage) => {
7
+ console.error(error);
8
+ alert((prependedMessage ?? "") + (error instanceof Error ? error.toString() : String(error)));
9
+ };
@@ -43,7 +43,7 @@ export const createTypeSkeleton = (getDeclFromDeclName, type) => {
43
43
  };
44
44
  }
45
45
  case "ChildEntitiesType":
46
- return [];
46
+ return undefined;
47
47
  default:
48
48
  return assertExhaustive(type);
49
49
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tsondb",
3
- "version": "0.7.6",
3
+ "version": "0.7.8",
4
4
  "description": "",
5
5
  "license": "ISC",
6
6
  "author": "Lukas Obermann",
@@ -47,13 +47,13 @@
47
47
  "typescript-eslint": "^8.45.0"
48
48
  },
49
49
  "dependencies": {
50
+ "@preact/signals": "^2.3.2",
50
51
  "debug": "^4.4.3",
51
52
  "express": "^5.1.0",
52
53
  "preact": "^10.27.2",
53
54
  "preact-iso": "^2.11.0",
54
55
  "simple-cli-args": "^0.1.3",
55
- "simple-git": "^3.28.0",
56
- "uuid": "^13.0.0"
56
+ "simple-git": "^3.28.0"
57
57
  },
58
58
  "repository": "github:elyukai/tsondb",
59
59
  "bugs": {
@@ -81,6 +81,7 @@
81
81
  --button-color-destructive: #fff;
82
82
  --button-color-destructive-hover: #fff;
83
83
  --button-color-disabled: hsl(260, 6%, 54%);
84
+ --disabled-color: #606164;
84
85
  --highlight-color: #f2d600;
85
86
  --highlight-background: #333300;
86
87
  --highlight-color-bold: rgb(236, 170, 105);
@@ -722,43 +723,43 @@ form > .field--container {
722
723
  color: var(--disabled-color);
723
724
  }
724
725
 
725
- .field--string .preview {
726
+ .preview {
726
727
  padding: 1rem;
727
728
  background: var(--markdown-background);
728
729
  flex: 1 1 0;
729
730
  }
730
731
 
731
- .field--string .preview p {
732
+ .preview p {
732
733
  margin: 0.5rem 0 0;
733
734
  }
734
735
 
735
- .field--string .preview > :first-child {
736
+ .preview > :first-child {
736
737
  margin-top: 0;
737
738
  }
738
739
 
739
- .field--string .preview > :last-child {
740
+ .preview > :last-child {
740
741
  margin-bottom: 0;
741
742
  }
742
743
 
743
- .field--string .preview table {
744
+ .preview table {
744
745
  border-collapse: collapse;
745
746
  margin: 0.5rem 0;
746
747
  }
747
748
 
748
- .field--string .preview table :is(th, td) {
749
+ .preview table :is(th, td) {
749
750
  vertical-align: top;
750
751
  padding: 0.25rem 0.5rem;
751
752
  }
752
753
 
753
- .field--string .preview table :is(th, td):first-child {
754
+ .preview table :is(th, td):first-child {
754
755
  padding-left: 0;
755
756
  }
756
757
 
757
- .field--string .preview table :is(th, td):last-child {
758
+ .preview table :is(th, td):last-child {
758
759
  padding-right: 0;
759
760
  }
760
761
 
761
- .field--string .preview table tbody tr {
762
+ .preview table tbody tr {
762
763
  border-top: 1px solid var(--tertiary-color);
763
764
  }
764
765
 
@@ -886,12 +887,7 @@ main:has(.form-footer) {
886
887
 
887
888
  aside.git {
888
889
  grid-area: aside;
889
- position: absolute;
890
- top: 5rem;
891
- right: 0;
892
- width: 30rem;
893
- max-width: calc(100% - 1.5rem);
894
- max-height: calc(100% - 6.5rem);
890
+ display: none;
895
891
  }
896
892
 
897
893
  aside.git h2 {
@@ -900,14 +896,10 @@ aside.git h2 {
900
896
 
901
897
  @media (min-width: 80rem) {
902
898
  aside.git {
899
+ display: block;
903
900
  width: 30rem;
904
901
  border-left: 1px solid var(--separator-color);
905
902
  padding-left: 1rem;
906
- top: unset;
907
- right: unset;
908
- position: static;
909
- max-height: none;
910
- max-width: none;
911
903
  }
912
904
 
913
905
  aside.git h2 {
@@ -919,103 +911,80 @@ aside.git h2 {
919
911
  }
920
912
  }
921
913
 
922
- aside.git h3 {
914
+ .git-files h3 {
923
915
  font-size: 1.25rem;
924
916
  margin: 0;
925
917
  }
926
918
 
927
- aside.git ul {
919
+ .git-files ul {
928
920
  list-style-type: " ";
929
921
  padding: 0;
930
922
  margin: 0;
931
923
  display: block;
932
924
  }
933
925
 
934
- aside.git .git-entity-list-item > .title {
935
- margin: 1rem 0 0.5rem;
936
- }
937
-
938
- aside.git .git-instance-list-item {
939
- display: flex;
940
- justify-content: space-between;
941
- margin: 0.25rem 0 0;
942
- gap: 0.25rem;
926
+ .git-files .git-entity-list-item > .title {
927
+ margin: 1.5rem 0 0.75rem;
943
928
  }
944
929
 
945
- aside.git li .title {
930
+ .git-files li .title {
946
931
  display: block;
947
932
  margin: 0.25rem 0;
948
933
  flex: 1 1 0;
949
934
  }
950
935
 
951
- aside.git li.git-entity-list-item > .title {
936
+ .git-files li.git-entity-list-item > .title {
952
937
  font-weight: 600;
953
938
  }
954
939
 
955
- aside.git li button {
940
+ .git-files li button {
956
941
  padding: 0 0.5rem;
957
942
  line-height: 1.75rem;
958
943
  height: 1.75rem;
959
944
  }
960
945
 
961
- aside.git .git-section-title {
946
+ .git-files .git-section-title {
962
947
  display: flex;
963
948
  justify-content: space-between;
964
949
  align-items: center;
965
950
  gap: 0.5rem;
966
- margin: 1rem 0 0.5rem;
951
+ margin: 2rem 0 1rem;
967
952
  }
968
953
 
969
- aside.git .git-section-title h2 {
954
+ .git-files .git-section-title h2 {
970
955
  margin: 0;
971
956
  }
972
957
 
973
- aside.git p.no-changes {
958
+ .git-files p.no-changes {
974
959
  color: var(--tertiary-color);
975
960
  margin: 0;
976
961
  }
977
962
 
978
- aside.git .commit,
979
- aside.git .sync,
980
- aside.git .branch {
981
- display: flex;
982
- gap: 0.5rem;
963
+ .git-branches ul {
964
+ padding: 0;
965
+ margin: 0;
983
966
  }
984
967
 
985
- aside.git .sync,
986
- aside.git .branch {
987
- margin-bottom: 1rem;
968
+ .git-branches ul li {
969
+ display: flex;
970
+ align-items: start;
971
+ margin-top: 0.5rem;
988
972
  }
989
973
 
990
- aside.git .commit input,
991
- aside.git .branch .select-wrapper {
974
+ .branch__full-name {
975
+ text-overflow: ellipsis;
976
+ overflow: hidden;
977
+ white-space: nowrap;
992
978
  flex: 1 1 0;
993
979
  }
994
980
 
995
- .git-overlay {
996
- display: none;
997
- position: absolute;
998
- right: 1.5rem;
999
- box-shadow: 0 0.5rem 2rem var(--shadow-color);
1000
- z-index: 1000;
1001
- padding: 1rem;
1002
- background: var(--background);
1003
- overflow-y: auto;
1004
- max-height: calc(90vh - 5rem);
1005
- }
1006
-
1007
- @media (min-width: 80rem) {
1008
- .git-overlay {
1009
- display: block;
1010
- position: static;
1011
- box-shadow: none;
1012
- padding: 0.5rem 0 0;
1013
- max-height: none;
1014
- }
981
+ .branch__origin {
982
+ color: var(--secondary-color);
1015
983
  }
1016
984
 
1017
- .git-overlay.git-overlay--open {
1018
- display: block;
985
+ .branch__current-indicator {
986
+ color: var(--secondary-color);
987
+ flex: none;
1019
988
  }
1020
989
 
1021
990
  dialog {
@@ -1026,14 +995,24 @@ dialog {
1026
995
  padding: 1.6rem 1.5rem;
1027
996
  max-height: calc(100% - 2rem);
1028
997
  max-width: calc(100% - 2rem);
998
+ overscroll-behavior: contain;
1029
999
  }
1030
1000
 
1031
1001
  dialog::backdrop {
1032
1002
  background: rgba(0, 0, 0, 0.5);
1003
+ transition: background 0.25s ease-in-out;
1004
+ }
1005
+
1006
+ dialog header {
1007
+ display: flex;
1008
+ align-items: center;
1009
+ gap: 0.5rem;
1010
+ margin-bottom: 1.6rem;
1033
1011
  }
1034
1012
 
1035
1013
  dialog header :is(h1, h2, h3, h4, h5, h6) {
1036
1014
  margin: 0;
1015
+ flex: 1 1 0;
1037
1016
  }
1038
1017
 
1039
1018
  dialog.settings {
@@ -1049,6 +1028,17 @@ dialog.settings section.locale-settings ol li:not(:first-child) {
1049
1028
  margin-top: 0.5rem;
1050
1029
  }
1051
1030
 
1031
+ dialog.git {
1032
+ max-width: min(calc(100% - 2rem), 36rem);
1033
+ width: 100%;
1034
+ }
1035
+
1036
+ @media (min-width: 80rem) {
1037
+ dialog.git header .git__tab--files {
1038
+ display: none;
1039
+ }
1040
+ }
1041
+
1052
1042
  .locale-content {
1053
1043
  display: flex;
1054
1044
  gap: 0.25rem;
@@ -1058,3 +1048,75 @@ dialog.settings section.locale-settings ol li:not(:first-child) {
1058
1048
  .locale-content span {
1059
1049
  flex: 1 1 0;
1060
1050
  }
1051
+
1052
+ .form-row {
1053
+ display: flex;
1054
+ gap: 0.5rem;
1055
+ flex-wrap: wrap;
1056
+ margin-block: 1rem;
1057
+ }
1058
+
1059
+ .form-row--sides {
1060
+ justify-content: space-between;
1061
+ }
1062
+
1063
+ .form-row--compact {
1064
+ gap: 0.25rem;
1065
+ margin-block: 0.5rem;
1066
+ }
1067
+
1068
+ .form-row__group {
1069
+ display: flex;
1070
+ gap: 0.5rem;
1071
+ }
1072
+
1073
+ .form-row--compact .form-row__group {
1074
+ gap: 0.25rem;
1075
+ }
1076
+
1077
+ .form-row__text {
1078
+ padding-block: 0.5rem;
1079
+ }
1080
+
1081
+ .form-row--compact .form-row__text {
1082
+ padding-block: 0.175rem;
1083
+ }
1084
+
1085
+ .form-row__fill {
1086
+ flex: 1 1 0;
1087
+ }
1088
+
1089
+ .form-row--compact button {
1090
+ padding: 0.175rem 0.5rem;
1091
+ height: 1.75rem;
1092
+ }
1093
+
1094
+ .loading-overlay {
1095
+ position: fixed;
1096
+ top: 0;
1097
+ left: 0;
1098
+ width: 100vw;
1099
+ height: 100vh;
1100
+ background: rgba(0, 0, 0, 0.5);
1101
+ color: white;
1102
+ display: flex;
1103
+ align-items: center;
1104
+ justify-content: center;
1105
+ font-size: 2rem;
1106
+ z-index: 1000;
1107
+ font-weight: 200;
1108
+ letter-spacing: 0.05em;
1109
+ transition: opacity 0.25s ease-in-out;
1110
+ opacity: 0;
1111
+ pointer-events: none;
1112
+ }
1113
+
1114
+ #app:not(:has(dialog[open])) > .loading-overlay--open,
1115
+ dialog[open] > .loading-overlay--open {
1116
+ opacity: 1;
1117
+ pointer-events: auto;
1118
+ }
1119
+
1120
+ dialog[open]:has(> .loading-overlay--open)::backdrop {
1121
+ background: rgba(0, 0, 0, 0.75);
1122
+ }