@mosetta/editor 0.0.0-stage → 0.0.28
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/CHANGELOG.md +185 -0
- package/LICENSE +21 -0
- package/README.md +10 -2
- package/mosetta.json +6 -0
- package/package.json +35 -3
- package/prefabs/workbench/prefab.json +11 -0
- package/prefabs/workbench/versions/1.json +120 -0
- package/prefabs/workbench/versions/2.json +13 -0
- package/prefabs/workbench/versions/3.json +19 -0
- package/prefabs/workbench/versions/4.json +29 -0
- package/prefabs/workbench/versions/5.json +29 -0
- package/tiles/canvas/canvas.component.tsx +2038 -0
- package/tiles/canvas/canvas.css +973 -0
- package/tiles/canvas/canvasTools.ts +66 -0
- package/tiles/canvas/chromeNodes.ts +35 -0
- package/tiles/canvas/ghosts.ts +33 -0
- package/tiles/canvas/insertPopover.tsx +56 -0
- package/tiles/canvas/popoverPlacement.ts +104 -0
- package/tiles/canvas/popoverSize.ts +87 -0
- package/tiles/canvas/providerChrome.tsx +191 -0
- package/tiles/canvas/scrollWatch.ts +43 -0
- package/tiles/canvas/settingsPopover.tsx +257 -0
- package/tiles/canvas/settingsTabs.ts +78 -0
- package/tiles/canvas/toolPanel.tsx +86 -0
- package/tiles/content/autoBind.ts +61 -0
- package/tiles/content/blockPage.css +390 -0
- package/tiles/content/blockPage.tsx +379 -0
- package/tiles/content/blockPicker.css +215 -0
- package/tiles/content/blockPicker.tsx +501 -0
- package/tiles/content/blockUpgrades.ts +145 -0
- package/tiles/content/blockVariants.ts +185 -0
- package/tiles/content/blockVocabulary.ts +77 -0
- package/tiles/content/catalogVersions.ts +106 -0
- package/tiles/content/componentPreview.css +82 -0
- package/tiles/content/componentPreview.tsx +249 -0
- package/tiles/content/content.server.ts +593 -0
- package/tiles/content/contentCommon.ts +133 -0
- package/tiles/content/disconnected.ts +56 -0
- package/tiles/content/distributions.css +256 -0
- package/tiles/content/distributions.tsx +271 -0
- package/tiles/content/editingAutosave.ts +125 -0
- package/tiles/content/editingClipboard.ts +185 -0
- package/tiles/content/editingConflicts.ts +223 -0
- package/tiles/content/editingHotkeys.ts +59 -0
- package/tiles/content/editingNotices.ts +105 -0
- package/tiles/content/formRoot.ts +18 -0
- package/tiles/content/fuzzySearch.ts +121 -0
- package/tiles/content/mediaUpload.ts +55 -0
- package/tiles/content/moduleSiblings.ts +9 -0
- package/tiles/content/mountedTree.ts +136 -0
- package/tiles/content/nodeSettings.css +483 -0
- package/tiles/content/nodeSettings.tsx +963 -0
- package/tiles/content/pasteText.ts +131 -0
- package/tiles/content/prefabFields.tsx +158 -0
- package/tiles/content/prefabParts.ts +105 -0
- package/tiles/content/previewEnvironment.ts +46 -0
- package/tiles/content/projectConfig.ts +46 -0
- package/tiles/content/projectPrefabs.ts +57 -0
- package/tiles/content/publishModal.css +109 -0
- package/tiles/content/publishModal.tsx +92 -0
- package/tiles/content/refsEditing.ts +412 -0
- package/tiles/content/scaledStage.ts +63 -0
- package/tiles/content/searchField.css +32 -0
- package/tiles/content/searchField.tsx +32 -0
- package/tiles/content/settingsDraft.ts +178 -0
- package/tiles/content/settingsIssues.tsx +124 -0
- package/tiles/content/themeScope.ts +72 -0
- package/tiles/content/themeVariables.ts +47 -0
- package/tiles/content/tooltipPlacement.ts +17 -0
- package/tiles/content/tooltips.tsx +131 -0
- package/tiles/content/treeMounter.ts +33 -0
- package/tiles/content/updatesModal.css +124 -0
- package/tiles/content/updatesModal.tsx +110 -0
- package/tiles/content/useCtrlHeld.ts +24 -0
- package/tiles/content/useEditingSession.ts +115 -0
- package/tiles/content/useMountedTree.ts +47 -0
- package/tiles/content/workbenchScale.css +27 -0
- package/tiles/hostFallback/hostFallback.component.tsx +32 -0
- package/tiles/hostFallback/hostFallback.css +12 -0
- package/tiles/hostFallback/hostFallback.editor.tsx +10 -0
- package/tiles/page/page.component.tsx +7 -0
- package/tiles/page/page.script.tsx +5 -0
- package/tiles/pageModules/pageModules.component.tsx +740 -0
- package/tiles/pageModules/pageModules.css +383 -0
- package/tiles/pageModules/pageModules.icon.svg +1 -0
- package/tiles/pageModules/servedPage.ts +465 -0
- package/tiles/pagesPanel/pagesPanel.component.tsx +1645 -0
- package/tiles/pagesPanel/pagesPanel.css +713 -0
- package/tiles/pagesPanel/pagesPanel.editor.tsx +23 -0
- package/tiles/pagesPanel/pagesSearch.ts +194 -0
- package/tiles/pagesPanel/routeTree.ts +98 -0
- package/tiles/previewBridge/landing.ts +66 -0
- package/tiles/previewBridge/previewAgent.ts +457 -0
- package/tiles/previewBridge/previewBridge.component.tsx +137 -0
- package/tiles/previewBridge/previewBridge.editor.tsx +10 -0
- package/tiles/previewBridge/previewBridgeCommon.ts +172 -0
- package/tiles/previewBridge/standIn.ts +22 -0
- package/tiles/treeView/treeView.component.tsx +514 -0
- package/tiles/treeView/treeView.css +303 -0
- package/tiles/treeView/treeView.editor.tsx +12 -0
- package/tiles/workbench/assistant.css +401 -0
- package/tiles/workbench/assistant.tsx +516 -0
- package/tiles/workbench/assistantChat.ts +165 -0
- package/tiles/workbench/dictation.ts +354 -0
- package/tiles/workbench/projectInfo.ts +72 -0
- package/tiles/workbench/recent.ts +67 -0
- package/tiles/workbench/workbench.component.tsx +476 -0
- package/tiles/workbench/workbench.css +376 -0
- package/tiles/workbench/workbenchAddress.ts +202 -0
- package/tiles/workbench/workspace.ts +775 -0
- package/tiles/workbenchEditor/workbenchEditor.component.tsx +461 -0
- package/tiles/workbenchEditor/workbenchEditor.css +370 -0
- package/tiles/workbenchHome/workbenchHome.component.tsx +196 -0
- package/tiles/workbenchHome/workbenchHome.css +271 -0
- package/tsconfig.json +3 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
// The editor↔server contract for the content API: tokens shared by the server facet
|
|
2
|
+
// (content.server.ts) and the client facets via useServerAction. One set of editing actions for
|
|
3
|
+
// both revisioned entities: a PAGE, or — with `kind: 'prefabs'` — a PREFAB, which travels in a
|
|
4
|
+
// page's shape (its root as the page's root, prefabAsPage) and is stored as the prefab it is.
|
|
5
|
+
// Plus the provider catalog.
|
|
6
|
+
import {
|
|
7
|
+
ContentKind,
|
|
8
|
+
ICatalogEntry,
|
|
9
|
+
IDistributionEntry,
|
|
10
|
+
IContentMeta,
|
|
11
|
+
ILibraryPrefabEntry,
|
|
12
|
+
IDraftSummary,
|
|
13
|
+
ILoadedContent,
|
|
14
|
+
ILoadedDraft,
|
|
15
|
+
IPageDoc,
|
|
16
|
+
} from '@mosetta/content';
|
|
17
|
+
import { ServerActionToken } from '@mosetta/server-action/core';
|
|
18
|
+
|
|
19
|
+
// Domain failures are structured results (not transport 5xx): the editor UI branches on `code`
|
|
20
|
+
// (NOT_FOUND / ALREADY_EXISTS / NO_REVISION / NO_DRAFT / CONFLICT / PUBLISH_VALIDATION / …).
|
|
21
|
+
export type ContentActionResult<T>
|
|
22
|
+
= | ({ readonly ok: true } & T)
|
|
23
|
+
| { readonly ok: false; readonly code: string; readonly message: string; readonly issues?: string[] };
|
|
24
|
+
|
|
25
|
+
// ---- pages and prefabs ----
|
|
26
|
+
|
|
27
|
+
/** which entity an editing action is about; a page when absent */
|
|
28
|
+
export interface IKindInput {
|
|
29
|
+
readonly kind?: ContentKind;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** a draft in the pages listing: the summary plus the ROUTE its working copy currently carries
|
|
33
|
+
* (patterns are versioned with the doc — a draft may be moving the page to another path) */
|
|
34
|
+
export interface IPageDraftListItem extends Omit<IDraftSummary, 'pattern'> {
|
|
35
|
+
readonly pattern: string | null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* A page as the panel lists it. The entity name stays the storage key; the PATTERNS are read out
|
|
40
|
+
* of the documents (live revision + each draft) because the meta deliberately knows nothing about
|
|
41
|
+
* content — the panel presents routes, so the listing carries them.
|
|
42
|
+
*/
|
|
43
|
+
export interface IPageListEntry {
|
|
44
|
+
readonly name: string;
|
|
45
|
+
readonly meta: IContentMeta;
|
|
46
|
+
readonly drafts: readonly IPageDraftListItem[];
|
|
47
|
+
/** the live revision's route, or null while nothing is published */
|
|
48
|
+
readonly livePattern: string | null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export const listPagesToken = new ServerActionToken<
|
|
52
|
+
IKindInput,
|
|
53
|
+
ContentActionResult<{ pages: IPageListEntry[] }>
|
|
54
|
+
>({ actionName: 'listPages', serverModuleName: 'content', tags: ['pages'] });
|
|
55
|
+
|
|
56
|
+
export const loadPageToken = new ServerActionToken<
|
|
57
|
+
{ name: string; rev?: number } & IKindInput,
|
|
58
|
+
ContentActionResult<{ page: ILoadedContent<IPageDoc> }>
|
|
59
|
+
>({ actionName: 'loadPage', serverModuleName: 'content', tags: ['pages'] });
|
|
60
|
+
|
|
61
|
+
export const loadPageDraftToken = new ServerActionToken<
|
|
62
|
+
{ name: string; draftId: string } & IKindInput,
|
|
63
|
+
ContentActionResult<{ draft: ILoadedDraft<IPageDoc> }>
|
|
64
|
+
>({ actionName: 'loadPageDraft', serverModuleName: 'content', tags: ['pages'] });
|
|
65
|
+
|
|
66
|
+
export const createPageToken = new ServerActionToken<
|
|
67
|
+
{ name: string; page: IPageDoc } & IKindInput,
|
|
68
|
+
ContentActionResult<{ draftId: string }>
|
|
69
|
+
>({ actionName: 'createPage', serverModuleName: 'content', invalidates: ['pages'] });
|
|
70
|
+
|
|
71
|
+
export const savePageDraftToken = new ServerActionToken<
|
|
72
|
+
{ name: string; draftId: string; page: IPageDoc } & IKindInput,
|
|
73
|
+
ContentActionResult<{ warnings: string[] }>
|
|
74
|
+
>({ actionName: 'savePageDraft', serverModuleName: 'content', invalidates: ['pages'] });
|
|
75
|
+
|
|
76
|
+
export const createPageDraftToken = new ServerActionToken<
|
|
77
|
+
{ name: string; fromRev?: number } & IKindInput,
|
|
78
|
+
ContentActionResult<{ draftId: string; page: IPageDoc }>
|
|
79
|
+
>({ actionName: 'createPageDraft', serverModuleName: 'content', invalidates: ['pages'] });
|
|
80
|
+
|
|
81
|
+
// the conflict modal's "fork": the LOCAL working copy survives under a fresh draft identity
|
|
82
|
+
export const forkPageDraftToken = new ServerActionToken<
|
|
83
|
+
{ name: string; page: IPageDoc } & IKindInput,
|
|
84
|
+
ContentActionResult<{ draftId: string; page: IPageDoc }>
|
|
85
|
+
>({ actionName: 'forkPageDraft', serverModuleName: 'content', invalidates: ['pages'] });
|
|
86
|
+
|
|
87
|
+
export const publishPageToken = new ServerActionToken<
|
|
88
|
+
{ name: string; draftId: string; title?: string } & IKindInput,
|
|
89
|
+
ContentActionResult<{ live: number }>
|
|
90
|
+
>({ actionName: 'publishPage', serverModuleName: 'content', invalidates: ['pages'] });
|
|
91
|
+
|
|
92
|
+
export const discardPageDraftToken = new ServerActionToken<
|
|
93
|
+
{ name: string; draftId: string } & IKindInput,
|
|
94
|
+
ContentActionResult<{}>
|
|
95
|
+
>({ actionName: 'discardPageDraft', serverModuleName: 'content', invalidates: ['pages'] });
|
|
96
|
+
|
|
97
|
+
/** a published prefab of the project as the editor shows it: its live tree, in a page's shape */
|
|
98
|
+
export interface IPrefabTree {
|
|
99
|
+
readonly name: string;
|
|
100
|
+
readonly rev: number;
|
|
101
|
+
readonly doc: IPageDoc;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** the live trees of the project's prefabs named — the palette's previews, the tree's read-only rows,
|
|
105
|
+
* an instance's open fields; a prefab not published is left out */
|
|
106
|
+
export const prefabTreesToken = new ServerActionToken<
|
|
107
|
+
{ names: string[] },
|
|
108
|
+
ContentActionResult<{ prefabs: IPrefabTree[] }>
|
|
109
|
+
>({ actionName: 'prefabTrees', serverModuleName: 'content', tags: ['pages'] });
|
|
110
|
+
|
|
111
|
+
/** the project's content config (config.json) — which languages its addresses serve, and more */
|
|
112
|
+
export const projectConfigToken = new ServerActionToken<
|
|
113
|
+
{},
|
|
114
|
+
ContentActionResult<{ config: Record<string, unknown> }>
|
|
115
|
+
>({ actionName: 'projectConfig', serverModuleName: 'content', tags: ['config'] });
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
/** everything readers kept of the live site is read anew — for a change made to the store by hand */
|
|
119
|
+
export const refreshLiveSiteToken = new ServerActionToken<
|
|
120
|
+
{},
|
|
121
|
+
ContentActionResult<{ refreshed: boolean }>
|
|
122
|
+
>({ actionName: 'refreshLiveSite', serverModuleName: 'content' });
|
|
123
|
+
|
|
124
|
+
export const deletePageToken = new ServerActionToken<
|
|
125
|
+
{ name: string } & IKindInput,
|
|
126
|
+
ContentActionResult<{}>
|
|
127
|
+
>({ actionName: 'deletePage', serverModuleName: 'content', invalidates: ['pages'] });
|
|
128
|
+
|
|
129
|
+
// ---- catalog ----
|
|
130
|
+
export const listComponentsToken = new ServerActionToken<
|
|
131
|
+
{ types?: string[] },
|
|
132
|
+
ContentActionResult<{ components: ICatalogEntry[]; distributions?: IDistributionEntry[]; prefabs?: ILibraryPrefabEntry[] }>
|
|
133
|
+
>({ actionName: 'listComponents', serverModuleName: 'content', tags: ['catalog'] });
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// The distributions the project DISCONNECTED (ADR-0059): the editor offers their blocks no more,
|
|
2
|
+
// and the blocks a page already holds stay in it — the site leaves them out, the editor marks them
|
|
3
|
+
// (the tree, the settings) and its preview shows a placeholder where each stands.
|
|
4
|
+
import { useEffect, useState } from 'react';
|
|
5
|
+
import { namespaceOfReference } from '@mosetta/content/units';
|
|
6
|
+
import { PROJECT_INFO_PATH } from '../workbench/projectInfo';
|
|
7
|
+
|
|
8
|
+
interface IDisconnection {
|
|
9
|
+
/** the disconnected distributions, by namespace */
|
|
10
|
+
readonly disabled: readonly string[];
|
|
11
|
+
/** where the project's settings are — the platform's own site; null on a dev server */
|
|
12
|
+
readonly platformOrigin: string | null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const NOTHING_OFF: IDisconnection = { disabled: [], platformOrigin: null };
|
|
16
|
+
|
|
17
|
+
/** the project's description, asked once per page — a change in the cabinet shows on reload */
|
|
18
|
+
let asked: Promise<IDisconnection> | null = null;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* What the project disconnected, and where that is changed. The project's description says
|
|
22
|
+
* (`/__mosetta__/project`); a host without one disconnects nothing.
|
|
23
|
+
*/
|
|
24
|
+
export function useDisconnection(): IDisconnection {
|
|
25
|
+
const [known, setKnown] = useState<IDisconnection>(NOTHING_OFF);
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
asked ??= fetch(PROJECT_INFO_PATH, { headers: { accept: 'application/json' } })
|
|
28
|
+
.then(async (res) => (res.ok ? (await res.json()) as { disabledDistributions?: unknown; platformOrigin?: unknown } : null))
|
|
29
|
+
.then((body) => ({
|
|
30
|
+
disabled: Array.isArray(body?.disabledDistributions) ? body.disabledDistributions.filter((n): n is string => typeof n === 'string') : [],
|
|
31
|
+
platformOrigin: typeof body?.platformOrigin === 'string' ? body.platformOrigin : null,
|
|
32
|
+
}))
|
|
33
|
+
.catch(() => NOTHING_OFF);
|
|
34
|
+
let alive = true;
|
|
35
|
+
void asked.then((value) => {
|
|
36
|
+
if (alive && value.disabled.length) setKnown(value);
|
|
37
|
+
});
|
|
38
|
+
return () => {
|
|
39
|
+
alive = false;
|
|
40
|
+
};
|
|
41
|
+
}, []);
|
|
42
|
+
return known;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** the project's disconnected distributions, by namespace */
|
|
46
|
+
export function useDisabledDistributions(): readonly string[] {
|
|
47
|
+
return useDisconnection().disabled;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
/** the disconnected distribution a block (or prefab) comes from, or null */
|
|
52
|
+
export function disconnectedOf(reference: string, disabled: readonly string[]): string | null {
|
|
53
|
+
if (!disabled.length) return null;
|
|
54
|
+
const namespace = namespaceOfReference(reference);
|
|
55
|
+
return namespace !== null && disabled.includes(namespace) ? namespace : null;
|
|
56
|
+
}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/* THE DISTRIBUTIONS (distributions.tsx): a grid of cards — cover, icon, title, what it brings —
|
|
2
|
+
and, one opened, a wall of its blocks' live previews, Pinterest-like (columns, each card as tall
|
|
3
|
+
as its block). */
|
|
4
|
+
.distributions {
|
|
5
|
+
/* the workbench's main area is a frame of the window's height: the view scrolls inside it */
|
|
6
|
+
flex: 1 1 auto;
|
|
7
|
+
min-height: 0;
|
|
8
|
+
overflow-y: auto;
|
|
9
|
+
box-sizing: border-box;
|
|
10
|
+
padding: 24px 28px 40px;
|
|
11
|
+
color: #18181b;
|
|
12
|
+
font-family: ui-sans-serif, system-ui, sans-serif;
|
|
13
|
+
font-size: var(--mosetta-wb-font);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.distributions--note {
|
|
17
|
+
color: #71717a;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.distributions__header {
|
|
21
|
+
margin-bottom: 20px;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.distributions__heading {
|
|
25
|
+
margin: 0;
|
|
26
|
+
font-size: 22px;
|
|
27
|
+
font-weight: 650;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.distributions__lead {
|
|
31
|
+
max-width: 640px;
|
|
32
|
+
margin: 6px 0 0;
|
|
33
|
+
color: #52525b;
|
|
34
|
+
line-height: 1.5;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.distributions__cards {
|
|
38
|
+
display: grid;
|
|
39
|
+
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
|
|
40
|
+
gap: 16px;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.distributions__card {
|
|
44
|
+
display: flex;
|
|
45
|
+
flex-direction: column;
|
|
46
|
+
overflow: hidden;
|
|
47
|
+
padding: 0;
|
|
48
|
+
border: 1px solid #e4e4e7;
|
|
49
|
+
border-radius: 12px;
|
|
50
|
+
background: #ffffff;
|
|
51
|
+
color: inherit;
|
|
52
|
+
font: inherit;
|
|
53
|
+
text-align: left;
|
|
54
|
+
cursor: pointer;
|
|
55
|
+
transition: box-shadow 0.15s ease, border-color 0.15s ease;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.distributions__card:hover {
|
|
59
|
+
border-color: #d4d4d8;
|
|
60
|
+
box-shadow: 0 6px 18px rgb(0 0 0 / 8%);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/* the cover keeps its own proportions: a landscape picture, 16:9 */
|
|
64
|
+
.distributions__cover {
|
|
65
|
+
display: block;
|
|
66
|
+
aspect-ratio: 16 / 9;
|
|
67
|
+
background: linear-gradient(135deg, #e4e4e7, #f4f4f5);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.distributions__cover img {
|
|
71
|
+
display: block;
|
|
72
|
+
width: 100%;
|
|
73
|
+
height: 100%;
|
|
74
|
+
object-fit: cover;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.distributions__card-body {
|
|
78
|
+
display: flex;
|
|
79
|
+
flex-direction: column;
|
|
80
|
+
gap: 6px;
|
|
81
|
+
padding: 12px 14px 14px;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.distributions__card-head {
|
|
85
|
+
display: flex;
|
|
86
|
+
align-items: center;
|
|
87
|
+
gap: 8px;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.distributions__icon {
|
|
91
|
+
flex: none;
|
|
92
|
+
width: 24px;
|
|
93
|
+
height: 24px;
|
|
94
|
+
border-radius: 6px;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.distributions__icon--large {
|
|
98
|
+
width: 44px;
|
|
99
|
+
height: 44px;
|
|
100
|
+
border-radius: 11px;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.distributions__title {
|
|
104
|
+
font-size: 15px;
|
|
105
|
+
font-weight: 650;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.distributions__description {
|
|
109
|
+
color: #52525b;
|
|
110
|
+
line-height: 1.45;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.distributions__meta {
|
|
114
|
+
display: flex;
|
|
115
|
+
align-items: center;
|
|
116
|
+
gap: 10px;
|
|
117
|
+
margin: 4px 0 0;
|
|
118
|
+
color: #a1a1aa;
|
|
119
|
+
font-size: var(--mosetta-wb-font-xs);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.distributions__source {
|
|
123
|
+
color: #2563eb;
|
|
124
|
+
text-decoration: none;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.distributions__source:hover {
|
|
128
|
+
text-decoration: underline;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.distributions__back {
|
|
132
|
+
margin: 0 0 14px;
|
|
133
|
+
padding: 0;
|
|
134
|
+
border: 0;
|
|
135
|
+
background: none;
|
|
136
|
+
color: #52525b;
|
|
137
|
+
font: inherit;
|
|
138
|
+
cursor: pointer;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.distributions__back:hover {
|
|
142
|
+
color: #18181b;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.distributions__header-main {
|
|
146
|
+
display: flex;
|
|
147
|
+
align-items: flex-start;
|
|
148
|
+
gap: 14px;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/* the wall: columns, each card as tall as its block — the eye runs down a column of shapes */
|
|
152
|
+
.distributions__wall {
|
|
153
|
+
column-width: 260px;
|
|
154
|
+
column-gap: 16px;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.distributions__specimen {
|
|
158
|
+
display: inline-block;
|
|
159
|
+
box-sizing: border-box;
|
|
160
|
+
width: 100%;
|
|
161
|
+
margin: 0 0 16px;
|
|
162
|
+
overflow: hidden;
|
|
163
|
+
border: 1px solid #e4e4e7;
|
|
164
|
+
border-radius: 12px;
|
|
165
|
+
background: #ffffff;
|
|
166
|
+
break-inside: avoid;
|
|
167
|
+
cursor: pointer;
|
|
168
|
+
transition: border-color 0.15s ease, box-shadow 0.15s ease;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/* a block's card opens its page (blockPage.tsx) */
|
|
172
|
+
.distributions__specimen:hover,
|
|
173
|
+
.distributions__specimen:focus-visible {
|
|
174
|
+
border-color: #d4d4d8;
|
|
175
|
+
box-shadow: 0 6px 18px rgb(0 0 0 / 8%);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.distributions__specimen-open {
|
|
179
|
+
margin-left: auto;
|
|
180
|
+
color: #a1a1aa;
|
|
181
|
+
font-size: var(--mosetta-wb-font-xs);
|
|
182
|
+
opacity: 0;
|
|
183
|
+
transition: opacity 0.15s ease;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.distributions__specimen:hover .distributions__specimen-open,
|
|
187
|
+
.distributions__specimen:focus-visible .distributions__specimen-open {
|
|
188
|
+
opacity: 1;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.distributions__specimen-head {
|
|
192
|
+
display: flex;
|
|
193
|
+
align-items: center;
|
|
194
|
+
gap: 8px;
|
|
195
|
+
padding: 10px 12px;
|
|
196
|
+
border-bottom: 1px solid #f4f4f5;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.distributions__block-icon {
|
|
200
|
+
flex: none;
|
|
201
|
+
width: 20px;
|
|
202
|
+
height: 20px;
|
|
203
|
+
border-radius: 5px;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.distributions__block-name {
|
|
207
|
+
font-weight: 600;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/* the block itself: laid out at the stage's width, scaled to the card's */
|
|
211
|
+
.distributions__specimen-view {
|
|
212
|
+
position: relative;
|
|
213
|
+
overflow: hidden;
|
|
214
|
+
padding: 0;
|
|
215
|
+
pointer-events: none;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.distributions__stage {
|
|
219
|
+
padding: 16px;
|
|
220
|
+
box-sizing: border-box;
|
|
221
|
+
transform-origin: 0 0;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.distributions__no-preview {
|
|
225
|
+
padding: 18px 12px;
|
|
226
|
+
color: #a1a1aa;
|
|
227
|
+
font-size: var(--mosetta-wb-font-xs);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/* the version shown, once several are deployed (ADR-0061) */
|
|
231
|
+
.distributions__version {
|
|
232
|
+
padding: 0 2px;
|
|
233
|
+
border: 1px solid #e4e4e7;
|
|
234
|
+
border-radius: 4px;
|
|
235
|
+
background: #ffffff;
|
|
236
|
+
color: #52525b;
|
|
237
|
+
font: inherit;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/* what the version says it changed — its CHANGELOG section, folded */
|
|
241
|
+
.distributions__changes {
|
|
242
|
+
max-width: 640px;
|
|
243
|
+
margin-top: 8px;
|
|
244
|
+
color: #52525b;
|
|
245
|
+
font-size: var(--mosetta-wb-font-sm);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.distributions__changes summary {
|
|
249
|
+
cursor: pointer;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
.distributions__changes pre {
|
|
253
|
+
margin: 6px 0 0;
|
|
254
|
+
font: inherit;
|
|
255
|
+
white-space: pre-wrap;
|
|
256
|
+
}
|