@commonpub/layer 0.8.3 → 0.8.5
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/components/ContentCard.vue +1 -1
- package/components/ImageUpload.vue +1 -1
- package/components/ShareToHubModal.vue +1 -1
- package/components/blocks/BlockCodeView.vue +26 -25
- package/components/contest/ContestEntries.vue +112 -0
- package/components/contest/ContestHero.vue +204 -0
- package/components/contest/ContestJudges.vue +51 -0
- package/components/contest/ContestPrizes.vue +82 -0
- package/components/contest/ContestRules.vue +34 -0
- package/components/contest/ContestSidebar.vue +83 -0
- package/components/editors/BlogEditor.vue +1 -1
- package/components/editors/DocsPageTree.vue +10 -0
- package/components/hub/HubHero.vue +1 -1
- package/composables/useSanitize.ts +112 -9
- package/composables/useTheme.ts +8 -0
- package/layouts/default.vue +7 -7
- package/middleware/feature-gate.global.ts +24 -0
- package/package.json +6 -6
- package/pages/[type]/index.vue +4 -3
- package/pages/admin/audit.vue +3 -2
- package/pages/admin/federation.vue +33 -13
- package/pages/admin/index.vue +7 -1
- package/pages/admin/reports.vue +152 -36
- package/pages/admin/settings.vue +17 -5
- package/pages/admin/theme.vue +5 -3
- package/pages/auth/forgot-password.vue +35 -35
- package/pages/auth/login.vue +6 -5
- package/pages/auth/reset-password.vue +44 -32
- package/pages/contests/[slug]/edit.vue +238 -56
- package/pages/contests/[slug]/index.vue +54 -450
- package/pages/contests/[slug]/judge.vue +141 -53
- package/pages/contests/[slug]/results.vue +182 -0
- package/pages/contests/create.vue +64 -64
- package/pages/contests/index.vue +2 -1
- package/pages/docs/[siteSlug]/[...pagePath].vue +6 -5
- package/pages/docs/[siteSlug]/edit.vue +58 -2
- package/pages/docs/[siteSlug]/index.vue +6 -5
- package/pages/federated-hubs/[id]/posts/[postId].vue +2 -2
- package/pages/hubs/index.vue +3 -2
- package/pages/index.vue +25 -7
- package/pages/learn/index.vue +1 -1
- package/pages/mirror/[id].vue +3 -3
- package/pages/notifications.vue +15 -1
- package/pages/products/[slug].vue +5 -2
- package/pages/settings/notifications.vue +7 -1
- package/pages/tags/[slug].vue +3 -2
- package/pages/tags/index.vue +3 -2
- package/pages/videos/[id].vue +18 -0
- package/server/api/admin/content/[id].patch.ts +1 -1
- package/server/api/admin/federation/mirrors/[id]/backfill.post.ts +1 -1
- package/server/api/admin/federation/refederate.post.ts +7 -3
- package/server/api/admin/federation/repair-types.post.ts +2 -45
- package/server/api/admin/federation/retry.post.ts +7 -4
- package/server/api/admin/reports.get.ts +1 -0
- package/server/api/auth/federated/login.post.ts +22 -2
- package/server/api/auth/sign-in-username.post.ts +42 -0
- package/server/api/content/[id]/products-sync.post.ts +7 -6
- package/server/api/contests/[slug]/entries/[entryId].delete.ts +14 -0
- package/server/api/contests/[slug]/entries.get.ts +6 -1
- package/server/api/contests/[slug]/judge.post.ts +8 -2
- package/server/api/docs/[siteSlug]/nav.get.ts +1 -1
- package/server/api/docs/[siteSlug]/pages/[pageId]/duplicate.post.ts +16 -0
- package/server/api/docs/[siteSlug]/pages/reorder.post.ts +4 -1
- package/server/api/docs/migrate-content.post.ts +1 -7
- package/server/api/federation/hub-follow-status.get.ts +2 -18
- package/server/api/federation/hub-follow.post.ts +9 -27
- package/server/api/federation/hub-post-like.post.ts +9 -98
- package/server/api/federation/hub-post-likes.get.ts +3 -13
- package/server/api/notifications/read.post.ts +6 -1
- package/server/api/profile/theme.put.ts +23 -0
- package/server/api/search/index.get.ts +2 -2
- package/server/api/search/trending.get.ts +3 -3
- package/server/api/users/index.get.ts +9 -2
- package/server/middleware/content-ap.ts +2 -2
- package/server/routes/.well-known/webfinger.ts +2 -2
- package/theme/base.css +23 -0
- package/components/EditorPropertiesPanel.vue +0 -393
- package/components/views/BlogView.vue +0 -735
- package/server/api/resolve-identity.post.ts +0 -34
|
@@ -1,393 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
const props = defineProps<{
|
|
3
|
-
contentType: string;
|
|
4
|
-
metadata: Record<string, unknown>;
|
|
5
|
-
selectedBlock: { type: string; attrs: Record<string, unknown> } | null;
|
|
6
|
-
}>();
|
|
7
|
-
|
|
8
|
-
const emit = defineEmits<{
|
|
9
|
-
'update:metadata': [metadata: Record<string, unknown>];
|
|
10
|
-
'slug-edited': [];
|
|
11
|
-
}>();
|
|
12
|
-
|
|
13
|
-
function updateField(key: string, value: unknown): void {
|
|
14
|
-
emit('update:metadata', { ...props.metadata, [key]: value });
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const visibilityOptions = ['public', 'members', 'private'];
|
|
18
|
-
|
|
19
|
-
// Fetch user's hubs for the hub assignment dropdown
|
|
20
|
-
const { isAuthenticated } = useAuth();
|
|
21
|
-
const { data: userHubs } = useLazyFetch<{ items: Array<{ id: string; name: string; slug: string; role: string }> }>('/api/user/hubs', {
|
|
22
|
-
immediate: isAuthenticated.value,
|
|
23
|
-
default: () => ({ items: [] }),
|
|
24
|
-
});
|
|
25
|
-
const difficultyOptions = [
|
|
26
|
-
{ value: 1, label: 'Beginner' },
|
|
27
|
-
{ value: 2, label: 'Intermediate' },
|
|
28
|
-
{ value: 3, label: 'Advanced' },
|
|
29
|
-
];
|
|
30
|
-
</script>
|
|
31
|
-
|
|
32
|
-
<template>
|
|
33
|
-
<aside class="cpub-properties" aria-label="Document properties">
|
|
34
|
-
<div class="cpub-properties-header">
|
|
35
|
-
<i class="fa-solid fa-sliders"></i>
|
|
36
|
-
<span class="cpub-properties-title">Properties</span>
|
|
37
|
-
</div>
|
|
38
|
-
|
|
39
|
-
<div class="cpub-properties-body">
|
|
40
|
-
<!-- Document properties -->
|
|
41
|
-
<section class="cpub-prop-section">
|
|
42
|
-
<span class="cpub-prop-section-label"><i class="fa-solid fa-file-lines"></i> Document</span>
|
|
43
|
-
|
|
44
|
-
<div class="cpub-prop-field">
|
|
45
|
-
<label for="prop-slug" class="cpub-prop-label">Slug</label>
|
|
46
|
-
<input
|
|
47
|
-
id="prop-slug"
|
|
48
|
-
type="text"
|
|
49
|
-
class="cpub-prop-input"
|
|
50
|
-
:value="metadata.slug"
|
|
51
|
-
placeholder="auto-generated from title"
|
|
52
|
-
@input="updateField('slug', ($event.target as HTMLInputElement).value); emit('slug-edited')"
|
|
53
|
-
/>
|
|
54
|
-
</div>
|
|
55
|
-
|
|
56
|
-
<div class="cpub-prop-field">
|
|
57
|
-
<label for="prop-description" class="cpub-prop-label">Description</label>
|
|
58
|
-
<textarea
|
|
59
|
-
id="prop-description"
|
|
60
|
-
class="cpub-prop-textarea"
|
|
61
|
-
rows="3"
|
|
62
|
-
:value="metadata.description as string"
|
|
63
|
-
placeholder="Brief description..."
|
|
64
|
-
@input="updateField('description', ($event.target as HTMLTextAreaElement).value)"
|
|
65
|
-
/>
|
|
66
|
-
</div>
|
|
67
|
-
|
|
68
|
-
<div class="cpub-prop-field">
|
|
69
|
-
<label for="prop-tags" class="cpub-prop-label">Tags</label>
|
|
70
|
-
<input
|
|
71
|
-
id="prop-tags"
|
|
72
|
-
type="text"
|
|
73
|
-
class="cpub-prop-input"
|
|
74
|
-
:value="(metadata.tags as string[] || []).join(', ')"
|
|
75
|
-
placeholder="tag1, tag2, tag3"
|
|
76
|
-
@input="updateField('tags', ($event.target as HTMLInputElement).value.split(',').map(t => t.trim()).filter(Boolean))"
|
|
77
|
-
/>
|
|
78
|
-
</div>
|
|
79
|
-
|
|
80
|
-
<div class="cpub-prop-field">
|
|
81
|
-
<label for="prop-visibility" class="cpub-prop-label">Visibility</label>
|
|
82
|
-
<select
|
|
83
|
-
id="prop-visibility"
|
|
84
|
-
class="cpub-prop-select"
|
|
85
|
-
:value="metadata.visibility || 'public'"
|
|
86
|
-
@change="updateField('visibility', ($event.target as HTMLSelectElement).value)"
|
|
87
|
-
>
|
|
88
|
-
<option v-for="opt in visibilityOptions" :key="opt" :value="opt">{{ opt }}</option>
|
|
89
|
-
</select>
|
|
90
|
-
</div>
|
|
91
|
-
|
|
92
|
-
<div v-if="userHubs?.items?.length" class="cpub-prop-field">
|
|
93
|
-
<label for="prop-hub" class="cpub-prop-label">Community</label>
|
|
94
|
-
<select
|
|
95
|
-
id="prop-hub"
|
|
96
|
-
class="cpub-prop-select"
|
|
97
|
-
:value="metadata.hubSlug || ''"
|
|
98
|
-
@change="updateField('hubSlug', ($event.target as HTMLSelectElement).value || undefined)"
|
|
99
|
-
>
|
|
100
|
-
<option value="">None</option>
|
|
101
|
-
<option v-for="hub in userHubs.items" :key="hub.id" :value="hub.slug">{{ hub.name }}</option>
|
|
102
|
-
</select>
|
|
103
|
-
<span class="cpub-prop-hint">Link to a community's project gallery. Content visibility is controlled separately above.</span>
|
|
104
|
-
</div>
|
|
105
|
-
|
|
106
|
-
<div class="cpub-prop-field">
|
|
107
|
-
<label for="prop-cover" class="cpub-prop-label">Cover Image</label>
|
|
108
|
-
<input
|
|
109
|
-
id="prop-cover"
|
|
110
|
-
type="text"
|
|
111
|
-
class="cpub-prop-input"
|
|
112
|
-
:value="metadata.coverImage"
|
|
113
|
-
placeholder="URL or upload..."
|
|
114
|
-
@input="updateField('coverImage', ($event.target as HTMLInputElement).value)"
|
|
115
|
-
/>
|
|
116
|
-
</div>
|
|
117
|
-
</section>
|
|
118
|
-
|
|
119
|
-
<!-- Type-specific metadata -->
|
|
120
|
-
<section v-if="contentType === 'article' || contentType === 'blog'" class="cpub-prop-section">
|
|
121
|
-
<span class="cpub-prop-section-label"><i :class="contentType === 'article' ? 'fa-solid fa-newspaper' : 'fa-solid fa-pen-nib'"></i> {{ contentType === 'article' ? 'Article' : 'Blog' }}</span>
|
|
122
|
-
|
|
123
|
-
<div class="cpub-prop-field">
|
|
124
|
-
<label for="prop-category" class="cpub-prop-label">Category</label>
|
|
125
|
-
<input
|
|
126
|
-
id="prop-category"
|
|
127
|
-
type="text"
|
|
128
|
-
class="cpub-prop-input"
|
|
129
|
-
:value="metadata.category"
|
|
130
|
-
placeholder="Category..."
|
|
131
|
-
@input="updateField('category', ($event.target as HTMLInputElement).value)"
|
|
132
|
-
/>
|
|
133
|
-
</div>
|
|
134
|
-
|
|
135
|
-
<div v-if="contentType === 'blog'" class="cpub-prop-field">
|
|
136
|
-
<label for="prop-series" class="cpub-prop-label">Series</label>
|
|
137
|
-
<input
|
|
138
|
-
id="prop-series"
|
|
139
|
-
type="text"
|
|
140
|
-
class="cpub-prop-input"
|
|
141
|
-
:value="metadata.series"
|
|
142
|
-
placeholder="Series name..."
|
|
143
|
-
@input="updateField('series', ($event.target as HTMLInputElement).value)"
|
|
144
|
-
/>
|
|
145
|
-
</div>
|
|
146
|
-
|
|
147
|
-
<div class="cpub-prop-field">
|
|
148
|
-
<label for="prop-seo" class="cpub-prop-label">SEO Description</label>
|
|
149
|
-
<textarea
|
|
150
|
-
id="prop-seo"
|
|
151
|
-
class="cpub-prop-textarea"
|
|
152
|
-
rows="2"
|
|
153
|
-
:value="metadata.seoDescription as string"
|
|
154
|
-
placeholder="SEO description..."
|
|
155
|
-
@input="updateField('seoDescription', ($event.target as HTMLTextAreaElement).value)"
|
|
156
|
-
/>
|
|
157
|
-
</div>
|
|
158
|
-
</section>
|
|
159
|
-
|
|
160
|
-
<section v-if="contentType === 'project'" class="cpub-prop-section">
|
|
161
|
-
<span class="cpub-prop-section-label"><i class="fa-solid fa-microchip"></i> Project</span>
|
|
162
|
-
|
|
163
|
-
<div class="cpub-prop-field">
|
|
164
|
-
<label for="prop-difficulty" class="cpub-prop-label">Difficulty</label>
|
|
165
|
-
<select
|
|
166
|
-
id="prop-difficulty"
|
|
167
|
-
class="cpub-prop-select"
|
|
168
|
-
:value="metadata.difficulty || 1"
|
|
169
|
-
@change="updateField('difficulty', Number(($event.target as HTMLSelectElement).value))"
|
|
170
|
-
>
|
|
171
|
-
<option v-for="opt in difficultyOptions" :key="opt.value" :value="opt.value">{{ opt.label }}</option>
|
|
172
|
-
</select>
|
|
173
|
-
</div>
|
|
174
|
-
|
|
175
|
-
<div class="cpub-prop-field">
|
|
176
|
-
<label for="prop-buildtime" class="cpub-prop-label">Build Time</label>
|
|
177
|
-
<input
|
|
178
|
-
id="prop-buildtime"
|
|
179
|
-
type="text"
|
|
180
|
-
class="cpub-prop-input"
|
|
181
|
-
:value="metadata.buildTime"
|
|
182
|
-
placeholder="e.g., 2 hours"
|
|
183
|
-
@input="updateField('buildTime', ($event.target as HTMLInputElement).value)"
|
|
184
|
-
/>
|
|
185
|
-
</div>
|
|
186
|
-
|
|
187
|
-
<div class="cpub-prop-field">
|
|
188
|
-
<label for="prop-cost" class="cpub-prop-label">Estimated Cost</label>
|
|
189
|
-
<input
|
|
190
|
-
id="prop-cost"
|
|
191
|
-
type="text"
|
|
192
|
-
class="cpub-prop-input"
|
|
193
|
-
:value="metadata.estimatedCost"
|
|
194
|
-
placeholder="e.g., $50"
|
|
195
|
-
@input="updateField('estimatedCost', ($event.target as HTMLInputElement).value)"
|
|
196
|
-
/>
|
|
197
|
-
</div>
|
|
198
|
-
</section>
|
|
199
|
-
|
|
200
|
-
<section v-if="contentType === 'explainer'" class="cpub-prop-section">
|
|
201
|
-
<span class="cpub-prop-section-label"><i class="fa-solid fa-lightbulb"></i> Explainer</span>
|
|
202
|
-
|
|
203
|
-
<div class="cpub-prop-field">
|
|
204
|
-
<label for="prop-exp-difficulty" class="cpub-prop-label">Difficulty</label>
|
|
205
|
-
<select
|
|
206
|
-
id="prop-exp-difficulty"
|
|
207
|
-
class="cpub-prop-select"
|
|
208
|
-
:value="metadata.difficulty || 1"
|
|
209
|
-
@change="updateField('difficulty', Number(($event.target as HTMLSelectElement).value))"
|
|
210
|
-
>
|
|
211
|
-
<option v-for="opt in difficultyOptions" :key="opt.value" :value="opt.value">{{ opt.label }}</option>
|
|
212
|
-
</select>
|
|
213
|
-
</div>
|
|
214
|
-
|
|
215
|
-
<div class="cpub-prop-field">
|
|
216
|
-
<label for="prop-minutes" class="cpub-prop-label">Est. Minutes</label>
|
|
217
|
-
<input
|
|
218
|
-
id="prop-minutes"
|
|
219
|
-
type="number"
|
|
220
|
-
class="cpub-prop-input"
|
|
221
|
-
:value="metadata.estimatedMinutes"
|
|
222
|
-
placeholder="10"
|
|
223
|
-
@input="updateField('estimatedMinutes', Number(($event.target as HTMLInputElement).value))"
|
|
224
|
-
/>
|
|
225
|
-
</div>
|
|
226
|
-
|
|
227
|
-
<div class="cpub-prop-field">
|
|
228
|
-
<label for="prop-objectives" class="cpub-prop-label">Learning Objectives</label>
|
|
229
|
-
<textarea
|
|
230
|
-
id="prop-objectives"
|
|
231
|
-
class="cpub-prop-textarea"
|
|
232
|
-
rows="3"
|
|
233
|
-
:value="metadata.learningObjectives as string"
|
|
234
|
-
placeholder="One per line..."
|
|
235
|
-
@input="updateField('learningObjectives', ($event.target as HTMLTextAreaElement).value)"
|
|
236
|
-
/>
|
|
237
|
-
</div>
|
|
238
|
-
</section>
|
|
239
|
-
|
|
240
|
-
<!-- Selected block properties -->
|
|
241
|
-
<section v-if="selectedBlock" class="cpub-prop-section">
|
|
242
|
-
<span class="cpub-prop-section-label"><i class="fa-solid fa-cube"></i> Block: {{ selectedBlock.type }}</span>
|
|
243
|
-
|
|
244
|
-
<template v-if="selectedBlock.type === 'image'">
|
|
245
|
-
<div class="cpub-prop-field">
|
|
246
|
-
<label class="cpub-prop-label">Alt Text</label>
|
|
247
|
-
<input type="text" class="cpub-prop-input" :value="selectedBlock.attrs.alt" readonly />
|
|
248
|
-
</div>
|
|
249
|
-
<div class="cpub-prop-field">
|
|
250
|
-
<label class="cpub-prop-label">Caption</label>
|
|
251
|
-
<input type="text" class="cpub-prop-input" :value="selectedBlock.attrs.caption" readonly />
|
|
252
|
-
</div>
|
|
253
|
-
</template>
|
|
254
|
-
|
|
255
|
-
<template v-if="selectedBlock.type === 'code_block'">
|
|
256
|
-
<div class="cpub-prop-field">
|
|
257
|
-
<label class="cpub-prop-label">Language</label>
|
|
258
|
-
<input type="text" class="cpub-prop-input" :value="selectedBlock.attrs.language" readonly />
|
|
259
|
-
</div>
|
|
260
|
-
<div class="cpub-prop-field">
|
|
261
|
-
<label class="cpub-prop-label">Filename</label>
|
|
262
|
-
<input type="text" class="cpub-prop-input" :value="selectedBlock.attrs.filename" readonly />
|
|
263
|
-
</div>
|
|
264
|
-
</template>
|
|
265
|
-
|
|
266
|
-
<template v-if="selectedBlock.type === 'callout'">
|
|
267
|
-
<div class="cpub-prop-field">
|
|
268
|
-
<label class="cpub-prop-label">Variant</label>
|
|
269
|
-
<span class="cpub-prop-value">{{ selectedBlock.attrs.variant }}</span>
|
|
270
|
-
</div>
|
|
271
|
-
</template>
|
|
272
|
-
</section>
|
|
273
|
-
</div>
|
|
274
|
-
</aside>
|
|
275
|
-
</template>
|
|
276
|
-
|
|
277
|
-
<style scoped>
|
|
278
|
-
.cpub-properties {
|
|
279
|
-
width: 280px;
|
|
280
|
-
border-left: var(--border-width-default) solid var(--border);
|
|
281
|
-
background: var(--surface);
|
|
282
|
-
overflow-y: auto;
|
|
283
|
-
flex-shrink: 0;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
.cpub-properties-header {
|
|
287
|
-
padding: var(--space-3) var(--space-4);
|
|
288
|
-
border-bottom: var(--border-width-default) solid var(--border2);
|
|
289
|
-
display: flex;
|
|
290
|
-
align-items: center;
|
|
291
|
-
gap: 8px;
|
|
292
|
-
color: var(--text-dim);
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
.cpub-properties-header i {
|
|
296
|
-
font-size: 14px;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
.cpub-properties-title {
|
|
300
|
-
font-family: var(--font-mono);
|
|
301
|
-
font-size: var(--text-label);
|
|
302
|
-
font-weight: var(--font-weight-semibold);
|
|
303
|
-
text-transform: uppercase;
|
|
304
|
-
letter-spacing: var(--tracking-widest);
|
|
305
|
-
color: var(--text-dim);
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
.cpub-properties-body {
|
|
309
|
-
padding: var(--space-3);
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
.cpub-prop-section {
|
|
313
|
-
margin-bottom: var(--space-4);
|
|
314
|
-
padding-bottom: var(--space-4);
|
|
315
|
-
border-bottom: var(--border-width-default) solid var(--border2);
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
.cpub-prop-section:last-child {
|
|
319
|
-
border-bottom: none;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
.cpub-prop-section-label {
|
|
323
|
-
display: flex;
|
|
324
|
-
align-items: center;
|
|
325
|
-
gap: 8px;
|
|
326
|
-
font-family: var(--font-mono);
|
|
327
|
-
font-size: 10px;
|
|
328
|
-
font-weight: var(--font-weight-semibold);
|
|
329
|
-
text-transform: uppercase;
|
|
330
|
-
letter-spacing: var(--tracking-widest);
|
|
331
|
-
color: var(--text-faint);
|
|
332
|
-
margin-bottom: var(--space-3);
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
.cpub-prop-section-label i {
|
|
336
|
-
font-size: 12px;
|
|
337
|
-
color: var(--accent);
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
.cpub-prop-field {
|
|
341
|
-
margin-bottom: var(--space-3);
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
.cpub-prop-label {
|
|
345
|
-
display: block;
|
|
346
|
-
font-size: var(--text-xs);
|
|
347
|
-
font-weight: var(--font-weight-medium);
|
|
348
|
-
color: var(--text-dim);
|
|
349
|
-
margin-bottom: var(--space-1);
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
.cpub-prop-input,
|
|
353
|
-
.cpub-prop-select,
|
|
354
|
-
.cpub-prop-textarea {
|
|
355
|
-
width: 100%;
|
|
356
|
-
padding: var(--space-1) var(--space-2);
|
|
357
|
-
background: var(--surface2);
|
|
358
|
-
border: var(--border-width-default) solid var(--border2);
|
|
359
|
-
color: var(--text);
|
|
360
|
-
font-family: var(--font-sans);
|
|
361
|
-
font-size: var(--text-sm);
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
.cpub-prop-input:focus,
|
|
365
|
-
.cpub-prop-select:focus,
|
|
366
|
-
.cpub-prop-textarea:focus {
|
|
367
|
-
outline: none;
|
|
368
|
-
border-color: var(--accent);
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
.cpub-prop-textarea {
|
|
372
|
-
resize: vertical;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
.cpub-prop-select {
|
|
376
|
-
appearance: none;
|
|
377
|
-
cursor: pointer;
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
.cpub-prop-hint {
|
|
381
|
-
display: block;
|
|
382
|
-
font-size: 0.6875rem;
|
|
383
|
-
color: var(--text-faint);
|
|
384
|
-
margin-top: 4px;
|
|
385
|
-
line-height: 1.4;
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
.cpub-prop-value {
|
|
389
|
-
font-size: var(--text-sm);
|
|
390
|
-
color: var(--text);
|
|
391
|
-
text-transform: capitalize;
|
|
392
|
-
}
|
|
393
|
-
</style>
|