@goodfellow-cms/admin 0.6.0 → 0.7.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodfellow-cms/admin",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Goodfellow's admin panel: a visual editor for a site's pages, layout and settings.",
5
5
  "keywords": [
6
6
  "goodfellow",
@@ -56,10 +56,10 @@
56
56
  "@codemirror/state": "6.7.6",
57
57
  "@codemirror/theme-one-dark": "6.1.3",
58
58
  "@codemirror/view": "6.43.14",
59
- "@goodfellow-cms/ai": "0.6.0",
60
- "@goodfellow-cms/core": "0.6.0",
61
- "@goodfellow-cms/react": "0.6.0",
62
- "@goodfellow-cms/registry": "0.6.0",
59
+ "@goodfellow-cms/ai": "0.7.0",
60
+ "@goodfellow-cms/core": "0.7.0",
61
+ "@goodfellow-cms/react": "0.7.0",
62
+ "@goodfellow-cms/registry": "0.7.0",
63
63
  "codemirror": "6.0.2",
64
64
  "lucide-react": "1.52.0",
65
65
  "turndown": "7.2.4",
package/plugin.css CHANGED
@@ -1,8 +1,10 @@
1
1
  /*
2
2
  * The base look of a plugin's admin frame: the admin panel's colors, as
3
- * `--gfa-*` custom properties that follow its light or dark choice, its
4
- * font, and plain buttons, fields and headings. A plugin's screens can use
5
- * the properties in styles of their own.
3
+ * `--gfa-*` custom properties that follow its light or dark choice, and its
4
+ * font, and on screens, the screens' spacing and plain buttons, fields and
5
+ * headings. A plugin's screens can use the properties in styles of their own.
6
+ * An editor plugin's frame (`gfa-plugin-editor`) gets the colors and font
7
+ * only, since what it draws is its own, and the site's blocks among it.
6
8
  */
7
9
  :root {
8
10
  color-scheme: light dark;
@@ -66,65 +68,67 @@ body {
66
68
  sans-serif;
67
69
  }
68
70
 
71
+ *,
72
+ *::before,
73
+ *::after {
74
+ box-sizing: border-box;
75
+ }
76
+
77
+ /* The rest is for screens only. */
78
+
69
79
  /* Spaced as the admin panel's other screens, since a screen's frame fills the screen. */
70
- body {
80
+ :where(html:not(.gfa-plugin-editor)) body {
71
81
  padding: 24px;
72
82
  max-width: 960px;
73
83
  }
74
84
 
75
85
  /* Nothing in a screen's frame scrolls on its own: the frame grows with it. */
76
- html {
86
+ html:not(.gfa-plugin-editor) {
77
87
  overflow: hidden;
78
88
  }
79
89
 
80
- *,
81
- *::before,
82
- *::after {
83
- box-sizing: border-box;
84
- }
85
-
86
- h1,
87
- h2,
88
- h3 {
90
+ :where(html:not(.gfa-plugin-editor)) h1,
91
+ :where(html:not(.gfa-plugin-editor)) h2,
92
+ :where(html:not(.gfa-plugin-editor)) h3 {
89
93
  line-height: 1.25;
90
94
  margin: 0 0 0.75rem;
91
95
  }
92
96
 
93
- h1 {
97
+ :where(html:not(.gfa-plugin-editor)) h1 {
94
98
  font-size: 24px;
95
99
  margin-bottom: 16px;
96
100
  }
97
101
 
98
- h2 {
102
+ :where(html:not(.gfa-plugin-editor)) h2 {
99
103
  font-size: 17px;
100
104
  }
101
105
 
102
- h3 {
106
+ :where(html:not(.gfa-plugin-editor)) h3 {
103
107
  font-size: 15px;
104
108
  margin-top: 1.25rem;
105
109
  }
106
110
 
107
- section {
111
+ :where(html:not(.gfa-plugin-editor)) section {
108
112
  margin-top: 2rem;
109
113
  }
110
114
 
111
- p {
115
+ :where(html:not(.gfa-plugin-editor)) p {
112
116
  margin: 0 0 0.75rem;
113
117
  }
114
118
 
115
- a {
119
+ :where(html:not(.gfa-plugin-editor)) a {
116
120
  color: var(--gfa-accent);
117
121
  }
118
122
 
119
- label {
123
+ :where(html:not(.gfa-plugin-editor)) label {
120
124
  display: block;
121
125
  font-weight: 600;
122
126
  margin-bottom: 0.25rem;
123
127
  }
124
128
 
125
- input,
126
- select,
127
- textarea {
129
+ :where(html:not(.gfa-plugin-editor)) input,
130
+ :where(html:not(.gfa-plugin-editor)) select,
131
+ :where(html:not(.gfa-plugin-editor)) textarea {
128
132
  font: inherit;
129
133
  color: inherit;
130
134
  background: var(--gfa-surface);
@@ -135,7 +139,7 @@ textarea {
135
139
  max-width: 32rem;
136
140
  }
137
141
 
138
- button {
142
+ :where(html:not(.gfa-plugin-editor)) button {
139
143
  font: inherit;
140
144
  font-weight: 600;
141
145
  cursor: pointer;
@@ -146,24 +150,24 @@ button {
146
150
  padding: 0.4rem 0.9rem;
147
151
  }
148
152
 
149
- button:disabled {
153
+ :where(html:not(.gfa-plugin-editor)) button:disabled {
150
154
  cursor: default;
151
155
  opacity: 0.6;
152
156
  }
153
157
 
154
- :focus-visible {
158
+ :where(html:not(.gfa-plugin-editor)) :focus-visible {
155
159
  outline: 2px solid var(--gfa-accent);
156
160
  outline-offset: 2px;
157
161
  }
158
162
 
159
- input[type="checkbox"],
160
- input[type="radio"] {
163
+ :where(html:not(.gfa-plugin-editor)) input[type="checkbox"],
164
+ :where(html:not(.gfa-plugin-editor)) input[type="radio"] {
161
165
  width: auto;
162
166
  margin: 0 0.4rem 0 0;
163
167
  }
164
168
 
165
- small,
166
- .gfa-hint {
169
+ :where(html:not(.gfa-plugin-editor)) small,
170
+ :where(html:not(.gfa-plugin-editor)) .gfa-hint {
167
171
  display: block;
168
172
  color: var(--gfa-muted);
169
173
  font-size: 13px;
@@ -171,24 +175,24 @@ small,
171
175
  max-width: 40rem;
172
176
  }
173
177
 
174
- ol,
175
- ul {
178
+ :where(html:not(.gfa-plugin-editor)) ol,
179
+ :where(html:not(.gfa-plugin-editor)) ul {
176
180
  padding-left: 1.25rem;
177
181
  margin: 0 0 0.75rem;
178
182
  max-width: 44rem;
179
183
  }
180
184
 
181
- li {
185
+ :where(html:not(.gfa-plugin-editor)) li {
182
186
  margin-bottom: 0.5rem;
183
187
  }
184
188
 
185
- code,
186
- pre {
189
+ :where(html:not(.gfa-plugin-editor)) code,
190
+ :where(html:not(.gfa-plugin-editor)) pre {
187
191
  font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
188
192
  font-size: 13px;
189
193
  }
190
194
 
191
- pre {
195
+ :where(html:not(.gfa-plugin-editor)) pre {
192
196
  margin: 0.4rem 0 0;
193
197
  padding: 0.5rem 0.75rem;
194
198
  max-width: 40rem;
@@ -198,11 +202,11 @@ pre {
198
202
  border-radius: var(--gfa-radius);
199
203
  }
200
204
 
201
- details {
205
+ :where(html:not(.gfa-plugin-editor)) details {
202
206
  margin: 0.75rem 0;
203
207
  }
204
208
 
205
- summary {
209
+ :where(html:not(.gfa-plugin-editor)) summary {
206
210
  cursor: pointer;
207
211
  font-weight: 600;
208
212
  }
package/styles.css CHANGED
@@ -1013,6 +1013,39 @@ body,
1013
1013
  min-height: 0;
1014
1014
  }
1015
1015
 
1016
+ /* The search box at the top of Puck's block list, and what it finds. */
1017
+ .gfa-block-search-box {
1018
+ padding: 12px 16px 4px;
1019
+ }
1020
+
1021
+ .gfa-block-search-input {
1022
+ box-sizing: border-box;
1023
+ width: 100%;
1024
+ padding: 6px 10px;
1025
+ border: 1px solid var(--gfa-input-border);
1026
+ border-radius: 6px;
1027
+ background: var(--gfa-surface);
1028
+ color: var(--gfa-text);
1029
+ font: inherit;
1030
+ font-size: 14px;
1031
+ }
1032
+
1033
+ .gfa-block-search-input:focus-visible {
1034
+ outline: 2px solid var(--gfa-accent);
1035
+ outline-offset: 1px;
1036
+ }
1037
+
1038
+ .gfa-block-search-results {
1039
+ padding: 8px 16px 16px;
1040
+ }
1041
+
1042
+ .gfa-block-search-none {
1043
+ margin: 0;
1044
+ padding: 12px 16px;
1045
+ color: var(--gfa-muted);
1046
+ font-size: 14px;
1047
+ }
1048
+
1016
1049
  /* The editor's header, outside the frame that runs the site's code. */
1017
1050
  .gfa-editor-header {
1018
1051
  display: flex;
@@ -1097,6 +1130,47 @@ body,
1097
1130
  background: var(--gfa-bg);
1098
1131
  }
1099
1132
 
1133
+ /* An editor plugin's frame, with what shows over it until the editor has opened. */
1134
+ .gfa-plugin-editor-wrap {
1135
+ position: relative;
1136
+ flex: 1;
1137
+ min-width: 0;
1138
+ display: flex;
1139
+ }
1140
+
1141
+ .gfa-editor-loading {
1142
+ position: absolute;
1143
+ inset: 0;
1144
+ display: flex;
1145
+ flex-direction: column;
1146
+ align-items: center;
1147
+ justify-content: center;
1148
+ gap: 12px;
1149
+ background: var(--gfa-bg);
1150
+ color: var(--gfa-muted);
1151
+ }
1152
+
1153
+ .gfa-spinner {
1154
+ width: 28px;
1155
+ height: 28px;
1156
+ border: 3px solid var(--gfa-border);
1157
+ border-top-color: var(--gfa-accent);
1158
+ border-radius: 50%;
1159
+ animation: gfa-spin 0.8s linear infinite;
1160
+ }
1161
+
1162
+ @keyframes gfa-spin {
1163
+ to {
1164
+ transform: rotate(360deg);
1165
+ }
1166
+ }
1167
+
1168
+ @media (prefers-reduced-motion: reduce) {
1169
+ .gfa-spinner {
1170
+ animation-duration: 2.4s;
1171
+ }
1172
+ }
1173
+
1100
1174
  /* The frames that run the site's code: the editor fills its page, and its canvas can be a phone's width. */
1101
1175
  :root.gfa-frame,
1102
1176
  .gfa-frame body {
@@ -1418,6 +1492,138 @@ body,
1418
1492
  margin-top: 8px;
1419
1493
  }
1420
1494
 
1495
+ /* A block's Style field in the editor (frame/style-field.tsx). */
1496
+ .gfa-style-field {
1497
+ display: grid;
1498
+ gap: 14px;
1499
+ padding: 0 16px 16px;
1500
+ font:
1501
+ 14px / 1.5 ui-sans-serif,
1502
+ system-ui,
1503
+ sans-serif;
1504
+ }
1505
+
1506
+ .gfa-style-title {
1507
+ font-weight: 600;
1508
+ }
1509
+
1510
+ .gfa-style-group {
1511
+ display: grid;
1512
+ gap: 6px;
1513
+ min-width: 0;
1514
+ margin: 0;
1515
+ padding: 0;
1516
+ border: 0;
1517
+ }
1518
+
1519
+ .gfa-style-choice {
1520
+ display: grid;
1521
+ gap: 4px;
1522
+ }
1523
+
1524
+ .gfa-style-label {
1525
+ padding: 0;
1526
+ color: var(--gfa-text);
1527
+ font-size: 13px;
1528
+ font-weight: 600;
1529
+ }
1530
+
1531
+ .gfa-style-segments {
1532
+ display: flex;
1533
+ flex-wrap: wrap;
1534
+ gap: 4px;
1535
+ }
1536
+
1537
+ .gfa-style-segment {
1538
+ padding: 4px 8px;
1539
+ border: 1px solid var(--gfa-input-border);
1540
+ border-radius: var(--gfa-radius);
1541
+ background: var(--gfa-surface);
1542
+ color: var(--gfa-text);
1543
+ font: inherit;
1544
+ font-size: 13px;
1545
+ cursor: pointer;
1546
+ }
1547
+
1548
+ .gfa-style-segment[aria-pressed="true"] {
1549
+ border-color: var(--gfa-accent);
1550
+ background: var(--gfa-accent);
1551
+ color: var(--gfa-accent-text);
1552
+ }
1553
+
1554
+ .gfa-style-swatches {
1555
+ display: flex;
1556
+ flex-wrap: wrap;
1557
+ gap: 6px;
1558
+ }
1559
+
1560
+ .gfa-style-swatch {
1561
+ position: relative;
1562
+ width: 26px;
1563
+ height: 26px;
1564
+ padding: 0;
1565
+ overflow: hidden;
1566
+ border: 1px solid var(--gfa-input-border);
1567
+ border-radius: 50%;
1568
+ cursor: pointer;
1569
+ }
1570
+
1571
+ .gfa-style-swatch[aria-pressed="true"] {
1572
+ outline: 2px solid var(--gfa-accent);
1573
+ outline-offset: 2px;
1574
+ }
1575
+
1576
+ /* "As the block has it": a struck-through swatch. */
1577
+ .gfa-style-swatch-none {
1578
+ background: linear-gradient(
1579
+ 135deg,
1580
+ var(--gfa-surface) 45%,
1581
+ var(--gfa-muted) 45%,
1582
+ var(--gfa-muted) 55%,
1583
+ var(--gfa-surface) 55%
1584
+ );
1585
+ }
1586
+
1587
+ /* A color of the editor's own: the browser's color picker, filling the swatch. */
1588
+ .gfa-style-swatch-own {
1589
+ background: conic-gradient(red, yellow, lime, aqua, blue, magenta, red);
1590
+ }
1591
+
1592
+ .gfa-style-swatch-own input {
1593
+ position: absolute;
1594
+ inset: 0;
1595
+ width: 100%;
1596
+ height: 100%;
1597
+ opacity: 0;
1598
+ cursor: pointer;
1599
+ }
1600
+
1601
+ .gfa-style-swatch:disabled,
1602
+ .gfa-style-segment:disabled {
1603
+ cursor: default;
1604
+ opacity: 0.5;
1605
+ }
1606
+
1607
+ .gfa-style-sides {
1608
+ display: grid;
1609
+ grid-template-columns: repeat(2, minmax(0, 1fr));
1610
+ gap: 8px;
1611
+ }
1612
+
1613
+ .gfa-style-check {
1614
+ display: flex;
1615
+ align-items: center;
1616
+ gap: 6px;
1617
+ font-size: 13px;
1618
+ }
1619
+
1620
+ .gfa-style-warning {
1621
+ padding: 6px 8px;
1622
+ border-radius: var(--gfa-radius);
1623
+ background: var(--gfa-warning-bg);
1624
+ color: var(--gfa-warning-text);
1625
+ }
1626
+
1421
1627
  .gfa-media-chooser .gfa-button {
1422
1628
  min-height: 30px;
1423
1629
  padding: 0 10px;
@@ -2123,3 +2329,40 @@ body,
2123
2329
  padding: 0;
2124
2330
  border: 0;
2125
2331
  }
2332
+
2333
+ /* Blocks' icons in the block list, in place of Puck's drag handle, which every block shares. */
2334
+ .gfa-drawer-item {
2335
+ position: relative;
2336
+ }
2337
+
2338
+ .gfa-drawer-item .gfa-block-icon {
2339
+ position: absolute;
2340
+ top: 50%;
2341
+ left: 10px;
2342
+ transform: translateY(-50%);
2343
+ flex-shrink: 0;
2344
+ color: var(--gfa-muted);
2345
+ pointer-events: none;
2346
+ }
2347
+
2348
+ .gfa-drawer-item [class*="_DrawerItem-draggable_"] {
2349
+ justify-content: flex-start;
2350
+ padding-left: 34px;
2351
+ }
2352
+
2353
+ .gfa-drawer-item [class*="_DrawerItem-draggable_"] > :last-child:not([class*="_DrawerItem-name_"]) {
2354
+ display: none;
2355
+ }
2356
+
2357
+ .gfa-fieldset {
2358
+ display: grid;
2359
+ gap: 6px;
2360
+ margin: 0 0 16px;
2361
+ padding: 0;
2362
+ border: 0;
2363
+ }
2364
+
2365
+ .gfa-fieldset legend {
2366
+ margin-bottom: 6px;
2367
+ font-weight: 600;
2368
+ }