@goodfellow-cms/admin 0.8.0 → 0.9.0

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/text.d.ts ADDED
@@ -0,0 +1,52 @@
1
+ import { r as defaultStrings } from "./strings-CWaRN_0v.js";
2
+ import { AdminTextFile } from "@goodfellow-cms/core";
3
+ import { AdminTextSource } from "@goodfellow-cms/ai";
4
+ //#region src/admin-text-sources.d.ts
5
+ type AdminTextTable = "strings" | "puck" | "labels";
6
+ /** A source's key in one list of every table's: the table, a colon, then its own key, since labels' keys are words. */
7
+ export declare function sourceKey(table: AdminTextTable, key: string): string;
8
+ /** Everything the admin panel says in English, from every table, keyed with `sourceKey()`. */
9
+ export declare function adminTextSources(labels: readonly string[]): AdminTextSource[];
10
+ type SourceState = "missing" | "unusable" | "outdated" | "current";
11
+ /**
12
+ * Where a string stands in a language's file: not there, there but not
13
+ * usable (`adminTextProblem()`), made from English that has changed since,
14
+ * or current. Labels are keyed by their English, so they can't be outdated.
15
+ */
16
+ export declare function sourceState(file: AdminTextFile | undefined, source: AdminTextSource): SourceState;
17
+ interface LanguageStatus {
18
+ total: number;
19
+ current: number;
20
+ outdated: number;
21
+ missing: number;
22
+ unusable: number;
23
+ /** Current strings someone who speaks the language has read. */
24
+ reviewed: number;
25
+ }
26
+ /** How much of the admin panel a language's file says. */
27
+ export declare function languageStatus(file: AdminTextFile | undefined, sources: readonly AdminTextSource[]): LanguageStatus;
28
+ /** The strings to translate: those missing or unusable, and with `outdated`, those made from English that has changed. */
29
+ export declare function sourcesToTranslate(file: AdminTextFile | undefined, sources: readonly AdminTextSource[], options?: {
30
+ outdated?: boolean;
31
+ }): AdminTextSource[];
32
+ //#endregion
33
+ //#region src/languages/en-puck.d.ts
34
+ /**
35
+ * Puck's own English for the text Goodfellow translates, as its built-in
36
+ * dictionary has it (Puck doesn't export it), so the admin panel can have
37
+ * Puck's text translated for a site's own language, and check placeholders
38
+ * against it. A test keeps its keys the same as the Spanish table's.
39
+ */
40
+ export declare const PUCK_ENGLISH: Readonly<Record<string, string>>;
41
+ //#endregion
42
+ //#region src/text.d.ts
43
+ /**
44
+ * The labels Goodfellow's own blocks show, by their English: the built-in
45
+ * blocks', their groups', the page settings' and Goodfellow's registry
46
+ * blocks'. A site's own blocks add theirs.
47
+ */
48
+ export declare const BUILT_IN_LABELS: readonly string[];
49
+ /** Every string the admin panel shows in English, with Goodfellow's own blocks' labels. */
50
+ export declare function goodfellowAdminTextSources(): import("@goodfellow-cms/ai").AdminTextSource[];
51
+ //#endregion
52
+ export { type AdminTextTable, type LanguageStatus, type SourceState, defaultStrings };
package/dist/text.js ADDED
@@ -0,0 +1,22 @@
1
+ import { n as labels } from "./es-labels-DBu66eln.js";
2
+ import { n as defaultStrings } from "./strings-D94noZrv.js";
3
+ import { a as languageStatus, c as sourcesToTranslate, d as PUCK_ENGLISH, o as sourceKey, s as sourceState, t as adminTextSources } from "./admin-text-sources-BTZJPlVK.js";
4
+ //#region src/text.ts
5
+ /**
6
+ * The admin panel's English, with nothing to draw: every string a site's own
7
+ * admin text or a language pack translates, by `sourceKey()`, and how much of
8
+ * it a language's file says. For tools and tests outside the admin panel, such
9
+ * as a language pack's own checks, which can't load the admin panel itself.
10
+ */
11
+ /**
12
+ * The labels Goodfellow's own blocks show, by their English: the built-in
13
+ * blocks', their groups', the page settings' and Goodfellow's registry
14
+ * blocks'. A site's own blocks add theirs.
15
+ */
16
+ const BUILT_IN_LABELS = Object.keys(labels).sort();
17
+ /** Every string the admin panel shows in English, with Goodfellow's own blocks' labels. */
18
+ function goodfellowAdminTextSources() {
19
+ return adminTextSources(BUILT_IN_LABELS);
20
+ }
21
+ //#endregion
22
+ export { BUILT_IN_LABELS, PUCK_ENGLISH, adminTextSources, defaultStrings, goodfellowAdminTextSources, languageStatus, sourceKey, sourceState, sourcesToTranslate };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@goodfellow-cms/admin",
3
- "version": "0.8.0",
4
- "description": "Goodfellow's admin panel: a visual editor for a site's pages, layout and settings.",
3
+ "version": "0.9.0",
4
+ "description": "Goodfellow CMS's admin panel: a visual editor for a site's pages, layout and settings.",
5
5
  "keywords": [
6
6
  "goodfellow",
7
7
  "cms",
@@ -12,6 +12,10 @@
12
12
  ],
13
13
  "homepage": "https://goodfellow-cms.github.io/goodfellow-cms/docs/edit-pages",
14
14
  "bugs": "https://github.com/goodfellow-cms/goodfellow-cms/issues",
15
+ "funding": {
16
+ "type": "github",
17
+ "url": "https://github.com/sponsors/goodfellow-cms"
18
+ },
15
19
  "license": "MIT",
16
20
  "repository": {
17
21
  "type": "git",
@@ -39,6 +43,10 @@
39
43
  "types": "./dist/plugin.d.ts",
40
44
  "import": "./dist/plugin.js"
41
45
  },
46
+ "./text": {
47
+ "types": "./dist/text.d.ts",
48
+ "import": "./dist/text.js"
49
+ },
42
50
  "./styles.css": "./styles.css",
43
51
  "./plugin.css": "./plugin.css",
44
52
  "./package.json": "./package.json"
@@ -56,11 +64,12 @@
56
64
  "@codemirror/state": "6.7.6",
57
65
  "@codemirror/theme-one-dark": "6.1.3",
58
66
  "@codemirror/view": "6.43.14",
59
- "@goodfellow-cms/ai": "0.8.0",
60
- "@goodfellow-cms/core": "0.8.0",
61
- "@goodfellow-cms/react": "0.8.0",
62
- "@goodfellow-cms/registry": "0.8.0",
67
+ "@goodfellow-cms/ai": "0.9.0",
68
+ "@goodfellow-cms/core": "0.9.0",
69
+ "@goodfellow-cms/react": "0.9.0",
70
+ "@goodfellow-cms/registry": "0.9.0",
63
71
  "codemirror": "6.0.2",
72
+ "fflate": "0.8.3",
64
73
  "lucide-react": "1.52.0",
65
74
  "turndown": "7.2.4",
66
75
  "turndown-plugin-gfm": "1.0.2"
@@ -71,7 +80,7 @@
71
80
  "react-dom": "^19.0.0"
72
81
  },
73
82
  "devDependencies": {
74
- "@goodfellow-cms/blocks": "0.8.0",
83
+ "@goodfellow-cms/blocks": "0.9.0",
75
84
  "@puckeditor/core": "0.23.0",
76
85
  "@types/react": "^19.2.0",
77
86
  "@types/react-dom": "^19.2.0",
package/styles.css CHANGED
@@ -1502,6 +1502,7 @@ body,
1502
1502
  }
1503
1503
 
1504
1504
  .gfa-media-card {
1505
+ position: relative;
1505
1506
  display: flex;
1506
1507
  flex-direction: column;
1507
1508
  gap: 8px;
@@ -1565,6 +1566,209 @@ body,
1565
1566
  gap: 4px;
1566
1567
  }
1567
1568
 
1569
+ .gfa-media-actions[hidden] {
1570
+ display: none;
1571
+ }
1572
+
1573
+ /* What an image shows, from the media library's descriptions, cut to two lines. */
1574
+ .gfa-media-description {
1575
+ display: -webkit-box;
1576
+ overflow: hidden;
1577
+ font-size: 12px;
1578
+ -webkit-line-clamp: 2;
1579
+ -webkit-box-orient: vertical;
1580
+ }
1581
+
1582
+ .gfa-media-card-selected {
1583
+ border-color: var(--gfa-accent);
1584
+ box-shadow: 0 0 0 1px var(--gfa-accent);
1585
+ }
1586
+
1587
+ /* The box that chooses a file to delete with others, over its picture. */
1588
+ .gfa-media-check {
1589
+ position: absolute;
1590
+ top: 14px;
1591
+ left: 14px;
1592
+ width: 20px;
1593
+ height: 20px;
1594
+ accent-color: var(--gfa-accent);
1595
+ }
1596
+
1597
+ .gfa-media-selection {
1598
+ position: sticky;
1599
+ top: 0;
1600
+ z-index: 1;
1601
+ display: flex;
1602
+ flex-wrap: wrap;
1603
+ align-items: center;
1604
+ gap: 8px;
1605
+ margin-bottom: 12px;
1606
+ padding: 8px 12px;
1607
+ background: var(--gfa-surface);
1608
+ border: 1px solid var(--gfa-border);
1609
+ border-radius: var(--gfa-radius);
1610
+ }
1611
+
1612
+ .gfa-media-selection > span {
1613
+ margin-right: auto;
1614
+ font-weight: 600;
1615
+ }
1616
+
1617
+ .gfa-media-tags {
1618
+ overflow: hidden;
1619
+ font-size: 12px;
1620
+ color: var(--gfa-muted);
1621
+ text-overflow: ellipsis;
1622
+ white-space: nowrap;
1623
+ }
1624
+
1625
+ /* An image's focal point: the picture, clicked where it must stay in view, with a dot there. */
1626
+ .gfa-focus-picker {
1627
+ position: relative;
1628
+ display: block;
1629
+ width: fit-content;
1630
+ max-width: 100%;
1631
+ padding: 0;
1632
+ cursor: crosshair;
1633
+ background: repeating-conic-gradient(var(--gfa-checker) 0 25%, var(--gfa-checker-alt) 0 50%) 50% / 16px 16px;
1634
+ border: 1px solid var(--gfa-border);
1635
+ border-radius: 4px;
1636
+ }
1637
+
1638
+ .gfa-focus-picker img {
1639
+ display: block;
1640
+ /* SVGs that give only their shape would otherwise have no width in a box that takes the picture's. */
1641
+ min-width: 200px;
1642
+ max-width: 100%;
1643
+ max-height: 280px;
1644
+ user-select: none;
1645
+ }
1646
+
1647
+ .gfa-focus-dot {
1648
+ position: absolute;
1649
+ width: 18px;
1650
+ height: 18px;
1651
+ background: var(--gfa-accent);
1652
+ border: 3px solid var(--gfa-surface);
1653
+ border-radius: 50%;
1654
+ box-shadow: 0 0 0 1px var(--gfa-text);
1655
+ transform: translate(-50%, -50%);
1656
+ pointer-events: none;
1657
+ }
1658
+
1659
+ .gfa-focus-actions {
1660
+ align-items: center;
1661
+ justify-content: flex-start;
1662
+ }
1663
+
1664
+ .gfa-tags {
1665
+ display: flex;
1666
+ flex-direction: column;
1667
+ gap: 6px;
1668
+ }
1669
+
1670
+ .gfa-tag-list {
1671
+ display: flex;
1672
+ flex-wrap: wrap;
1673
+ gap: 6px;
1674
+ margin: 0;
1675
+ padding: 0;
1676
+ list-style: none;
1677
+ }
1678
+
1679
+ .gfa-tag {
1680
+ display: inline-flex;
1681
+ align-items: center;
1682
+ gap: 4px;
1683
+ padding: 2px 4px 2px 10px;
1684
+ font-size: 13px;
1685
+ background: var(--gfa-bg);
1686
+ border: 1px solid var(--gfa-border);
1687
+ border-radius: 999px;
1688
+ }
1689
+
1690
+ .gfa-tag-remove {
1691
+ width: 22px;
1692
+ height: 22px;
1693
+ padding: 0;
1694
+ font: inherit;
1695
+ line-height: 1;
1696
+ color: var(--gfa-muted);
1697
+ cursor: pointer;
1698
+ background: none;
1699
+ border: 0;
1700
+ border-radius: 50%;
1701
+ }
1702
+
1703
+ .gfa-tag-remove:hover,
1704
+ .gfa-tag-remove:focus-visible {
1705
+ color: var(--gfa-text);
1706
+ background: var(--gfa-surface);
1707
+ }
1708
+
1709
+ .gfa-tag-filter {
1710
+ display: flex;
1711
+ flex-wrap: wrap;
1712
+ align-items: center;
1713
+ gap: 4px;
1714
+ margin: 0 0 12px;
1715
+ padding: 0;
1716
+ border: 0;
1717
+ }
1718
+
1719
+ .gfa-tag-filter legend {
1720
+ float: left;
1721
+ margin-right: 8px;
1722
+ }
1723
+
1724
+ .gfa-crop-tools {
1725
+ display: flex;
1726
+ flex-wrap: wrap;
1727
+ align-items: center;
1728
+ gap: 8px;
1729
+ }
1730
+
1731
+ /* The picture being cropped, with the box that keeps part of it over it. */
1732
+ .gfa-crop-area {
1733
+ position: relative;
1734
+ overflow: hidden;
1735
+ width: fit-content;
1736
+ max-width: 100%;
1737
+ touch-action: none;
1738
+ background: repeating-conic-gradient(var(--gfa-checker) 0 25%, var(--gfa-checker-alt) 0 50%) 50% / 16px 16px;
1739
+ }
1740
+
1741
+ .gfa-crop-area canvas {
1742
+ display: block;
1743
+ max-width: 100%;
1744
+ }
1745
+
1746
+ .gfa-crop-box {
1747
+ position: absolute;
1748
+ padding: 0;
1749
+ cursor: move;
1750
+ background: transparent;
1751
+ border: 2px solid var(--gfa-accent-text);
1752
+ outline: 1px solid var(--gfa-accent);
1753
+ box-shadow: 0 0 0 9999px rgb(0 0 0 / 0.5);
1754
+ }
1755
+
1756
+ .gfa-crop-box:focus-visible {
1757
+ outline: 3px solid var(--gfa-accent);
1758
+ }
1759
+
1760
+ .gfa-crop-handle {
1761
+ position: absolute;
1762
+ right: -8px;
1763
+ bottom: -8px;
1764
+ width: 16px;
1765
+ height: 16px;
1766
+ cursor: nwse-resize;
1767
+ background: var(--gfa-accent);
1768
+ border: 2px solid var(--gfa-accent-text);
1769
+ border-radius: 3px;
1770
+ }
1771
+
1568
1772
  .gfa-media-chooser {
1569
1773
  display: flex;
1570
1774
  align-items: center;
@@ -1648,6 +1852,46 @@ body,
1648
1852
  min-width: 0;
1649
1853
  }
1650
1854
 
1855
+ .gfa-table-field-rich {
1856
+ min-height: 2.25em;
1857
+ white-space: pre-wrap;
1858
+ overflow-wrap: anywhere;
1859
+ cursor: text;
1860
+ }
1861
+
1862
+ .gfa-table-field-rich a {
1863
+ color: var(--gfa-accent);
1864
+ text-decoration: underline;
1865
+ }
1866
+
1867
+ .gfa-table-field-toolbar {
1868
+ display: flex;
1869
+ flex-wrap: wrap;
1870
+ gap: 4px;
1871
+ margin-bottom: 8px;
1872
+ }
1873
+
1874
+ .gfa-table-field-tool {
1875
+ padding: 2px 8px;
1876
+ border: 1px solid var(--gfa-border);
1877
+ border-radius: var(--gfa-radius);
1878
+ background: var(--gfa-surface);
1879
+ color: var(--gfa-text);
1880
+ cursor: pointer;
1881
+ }
1882
+
1883
+ .gfa-table-field-tool:disabled {
1884
+ cursor: default;
1885
+ opacity: 0.4;
1886
+ }
1887
+
1888
+ .gfa-table-field-link {
1889
+ display: flex;
1890
+ flex-wrap: wrap;
1891
+ gap: 4px;
1892
+ width: 100%;
1893
+ }
1894
+
1651
1895
  .gfa-table-field-remove {
1652
1896
  border: 1px solid var(--gfa-border);
1653
1897
  border-radius: var(--gfa-radius);
@@ -2392,6 +2636,73 @@ body,
2392
2636
  border: 0;
2393
2637
  }
2394
2638
 
2639
+ /* Links to items: the chosen ones, then a search and what it finds. */
2640
+ .gfa-item-picker {
2641
+ display: grid;
2642
+ gap: 6px;
2643
+ }
2644
+
2645
+ .gfa-item-picker-chosen,
2646
+ .gfa-item-picker-matches,
2647
+ .gfa-images-field ul {
2648
+ display: grid;
2649
+ gap: 4px;
2650
+ margin: 0;
2651
+ padding: 0;
2652
+ list-style: none;
2653
+ }
2654
+
2655
+ .gfa-chosen-row {
2656
+ display: flex;
2657
+ align-items: center;
2658
+ gap: 6px;
2659
+ padding: 2px 4px 2px 8px;
2660
+ border: 1px solid var(--gfa-border);
2661
+ border-radius: 6px;
2662
+ }
2663
+
2664
+ .gfa-chosen-row-name {
2665
+ flex: 1;
2666
+ min-width: 0;
2667
+ overflow: hidden;
2668
+ text-overflow: ellipsis;
2669
+ white-space: nowrap;
2670
+ }
2671
+
2672
+ .gfa-item-picker-matches {
2673
+ max-height: 200px;
2674
+ overflow-y: auto;
2675
+ }
2676
+
2677
+ .gfa-item-picker-matches button {
2678
+ width: 100%;
2679
+ padding: 4px 8px;
2680
+ border: 0;
2681
+ border-radius: 4px;
2682
+ background: none;
2683
+ color: inherit;
2684
+ font: inherit;
2685
+ text-align: start;
2686
+ cursor: pointer;
2687
+ }
2688
+
2689
+ .gfa-item-picker-matches button:hover,
2690
+ .gfa-item-picker-matches button:focus-visible {
2691
+ background: var(--gfa-current-bg);
2692
+ }
2693
+
2694
+ .gfa-images-field {
2695
+ display: grid;
2696
+ gap: 8px;
2697
+ }
2698
+
2699
+ .gfa-images-field-thumb {
2700
+ width: 40px;
2701
+ height: 40px;
2702
+ object-fit: cover;
2703
+ border-radius: 4px;
2704
+ }
2705
+
2395
2706
  .gfa-event-days {
2396
2707
  display: flex;
2397
2708
  flex-wrap: wrap;
@@ -2446,6 +2757,19 @@ body,
2446
2757
  background: var(--gfa-checker);
2447
2758
  }
2448
2759
 
2760
+ /* A small picture beside the words, as links with summary cards show. */
2761
+ .gfa-share-card-small {
2762
+ display: grid;
2763
+ grid-template-columns: 96px 1fr;
2764
+ align-items: center;
2765
+ }
2766
+
2767
+ .gfa-share-card-small .gfa-share-image {
2768
+ height: 100%;
2769
+ min-height: 96px;
2770
+ aspect-ratio: 1;
2771
+ }
2772
+
2449
2773
  .gfa-share-no-image {
2450
2774
  display: grid;
2451
2775
  place-items: center;
@@ -2594,3 +2918,212 @@ body,
2594
2918
  margin-bottom: 6px;
2595
2919
  font-weight: 600;
2596
2920
  }
2921
+
2922
+ /* A synced block on the editor's canvas, drawn read-only in place of its Synced block, with a link to edit it. */
2923
+ .gfa-synced-block {
2924
+ outline: 2px dashed var(--gfa-accent);
2925
+ outline-offset: -2px;
2926
+ }
2927
+
2928
+ .gfa-synced-block-bar {
2929
+ display: flex;
2930
+ flex-wrap: wrap;
2931
+ gap: 4px 12px;
2932
+ align-items: center;
2933
+ justify-content: space-between;
2934
+ padding: 4px 10px;
2935
+ background: var(--gfa-accent);
2936
+ color: var(--gfa-accent-text);
2937
+ font:
2938
+ 13px / 1.4 ui-sans-serif,
2939
+ system-ui,
2940
+ sans-serif;
2941
+ }
2942
+
2943
+ .gfa-synced-block-bar a {
2944
+ color: inherit;
2945
+ font-weight: 600;
2946
+ text-decoration: underline;
2947
+ }
2948
+
2949
+ .gfa-synced-block-missing p {
2950
+ margin: 0;
2951
+ padding: 16px;
2952
+ color: var(--gfa-text);
2953
+ background: var(--gfa-surface);
2954
+ font:
2955
+ 14px / 1.5 ui-sans-serif,
2956
+ system-ui,
2957
+ sans-serif;
2958
+ }
2959
+
2960
+ /* InfoBubble: an "i" whose words show while it's pointed at or focused, and which opens the documentation. */
2961
+ .gfa-info {
2962
+ position: relative;
2963
+ display: inline-flex;
2964
+ vertical-align: middle;
2965
+ margin-inline-start: 6px;
2966
+ }
2967
+
2968
+ .gfa-info-button {
2969
+ display: inline-flex;
2970
+ color: var(--gfa-muted);
2971
+ border-radius: 999px;
2972
+ }
2973
+
2974
+ .gfa-info-button:hover,
2975
+ .gfa-info-button:focus-visible {
2976
+ color: var(--gfa-accent);
2977
+ }
2978
+
2979
+ .gfa-info-text {
2980
+ position: absolute;
2981
+ bottom: calc(100% + 8px);
2982
+ left: 50%;
2983
+ z-index: 30;
2984
+ width: max-content;
2985
+ max-width: min(320px, 80vw);
2986
+ padding: 6px 10px;
2987
+ border-radius: var(--gfa-radius);
2988
+ background: var(--gfa-tooltip-bg);
2989
+ color: var(--gfa-tooltip-text);
2990
+ font-size: 13px;
2991
+ font-weight: 400;
2992
+ line-height: 1.4;
2993
+ box-shadow: 0 4px 12px rgb(15 23 42 / 0.18);
2994
+ pointer-events: none;
2995
+ opacity: 0;
2996
+ transform: translate(-50%, 4px);
2997
+ transition:
2998
+ opacity 140ms ease,
2999
+ transform 140ms ease;
3000
+ }
3001
+
3002
+ .gfa-info:hover .gfa-info-text,
3003
+ .gfa-info:focus-within .gfa-info-text {
3004
+ opacity: 1;
3005
+ transform: translate(-50%, 0);
3006
+ }
3007
+
3008
+ @media (prefers-reduced-motion: reduce) {
3009
+ .gfa-info-text {
3010
+ transition: opacity 140ms ease;
3011
+ transform: translate(-50%, 0);
3012
+ }
3013
+ }
3014
+
3015
+ /* The site's own fonts on the Colors & fonts tab. */
3016
+ .gfa-own-fonts {
3017
+ display: grid;
3018
+ gap: 8px;
3019
+ margin: 0 0 12px;
3020
+ padding: 0;
3021
+ list-style: none;
3022
+ }
3023
+
3024
+ .gfa-own-font {
3025
+ display: flex;
3026
+ align-items: center;
3027
+ gap: 12px;
3028
+ padding: 10px 12px;
3029
+ border: 1px solid var(--gfa-border);
3030
+ border-radius: var(--gfa-radius);
3031
+ background: var(--gfa-surface);
3032
+ }
3033
+
3034
+ .gfa-own-font-name {
3035
+ flex: 1;
3036
+ font-size: 18px;
3037
+ }
3038
+
3039
+ .gfa-font-files {
3040
+ width: 100%;
3041
+ border-collapse: collapse;
3042
+ margin: 8px 0 12px;
3043
+ }
3044
+
3045
+ .gfa-font-files th,
3046
+ .gfa-font-files td {
3047
+ padding: 6px 8px 6px 0;
3048
+ text-align: start;
3049
+ vertical-align: middle;
3050
+ }
3051
+
3052
+ .gfa-font-files th {
3053
+ font-weight: 500;
3054
+ color: var(--gfa-muted);
3055
+ font-size: 13px;
3056
+ }
3057
+
3058
+ .gfa-font-group {
3059
+ padding: 6px 10px 2px;
3060
+ color: var(--gfa-muted);
3061
+ font-size: 12px;
3062
+ font-weight: 600;
3063
+ text-transform: uppercase;
3064
+ letter-spacing: 0.04em;
3065
+ }
3066
+
3067
+ /* The Go to box (Ctrl+K) and the list of shortcuts (?). */
3068
+ .gfa-goto {
3069
+ display: grid;
3070
+ gap: 8px;
3071
+ width: min(520px, calc(100vw - 64px));
3072
+ }
3073
+
3074
+ .gfa-goto input {
3075
+ width: 100%;
3076
+ padding: 8px 10px;
3077
+ font: inherit;
3078
+ border: 1px solid var(--gfa-border);
3079
+ border-radius: var(--gfa-radius);
3080
+ background: var(--gfa-surface);
3081
+ color: inherit;
3082
+ }
3083
+
3084
+ .gfa-goto-list {
3085
+ max-height: min(400px, 60vh);
3086
+ overflow-y: auto;
3087
+ }
3088
+
3089
+ .gfa-goto-option {
3090
+ display: flex;
3091
+ align-items: baseline;
3092
+ justify-content: space-between;
3093
+ gap: 12px;
3094
+ padding: 8px 10px;
3095
+ border-radius: 4px;
3096
+ cursor: pointer;
3097
+ }
3098
+
3099
+ .gfa-goto-option[aria-selected="true"] {
3100
+ background: var(--gfa-bg);
3101
+ }
3102
+
3103
+ .gfa-goto-label {
3104
+ overflow: hidden;
3105
+ text-overflow: ellipsis;
3106
+ white-space: nowrap;
3107
+ }
3108
+
3109
+ .gfa-goto-option .gfa-hint {
3110
+ flex-shrink: 0;
3111
+ margin: 0;
3112
+ }
3113
+
3114
+ .gfa-shortcuts td {
3115
+ padding: 6px 12px 6px 0;
3116
+ vertical-align: top;
3117
+ }
3118
+
3119
+ .gfa-shortcuts kbd {
3120
+ display: inline-block;
3121
+ min-width: 1.6em;
3122
+ padding: 1px 6px;
3123
+ font: inherit;
3124
+ font-size: 13px;
3125
+ text-align: center;
3126
+ border: 1px solid var(--gfa-border);
3127
+ border-radius: 4px;
3128
+ background: var(--gfa-bg);
3129
+ }