Skip to content

Commit fe8854d

Browse files
Merge pull request #213 from gridaco/community
Community Readonly Editor
2 parents 15ede89 + 6be8e7e commit fe8854d

File tree

30 files changed

+436
-245
lines changed

30 files changed

+436
-245
lines changed

editor-packages/editor-figma-file/repository.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,11 @@ export class FigmaDesignRepository {
3939
if (existing) {
4040
// everytime the file is consumed consider it as used, we upsert the file so that the lastUsed can be updated.
4141
metastore.upsert(existing.key, existing);
42-
yield { ...existing, __initial: false } as TFetchFileForApp;
42+
yield {
43+
...existing,
44+
__initial: false,
45+
__type: "file-fetched-for-app",
46+
} as TFetchFileForApp;
4347
}
4448

4549
const _iter = fetch.fetchFile({ file: filekey, auth: this.auth });

editor/components/home/home-side-bar-tree.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,12 @@ const preset_pages: PresetPage[] = [
8989
},
9090
],
9191
},
92+
{
93+
id: "/community/files",
94+
name: "Community Files",
95+
path: "/community/files",
96+
depth: 0,
97+
},
9298
];
9399

94100
export function HomeSidebarTree() {
Lines changed: 49 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import styled from "@emotion/styled";
2-
import React, { useEffect } from "react";
2+
import React from "react";
33
import { useAuthState } from "hooks";
44
import { useRouter } from "next/router";
5-
6-
const __is_dev = process.env.NODE_ENV == "development";
5+
import { ArrowRightIcon } from "@radix-ui/react-icons";
6+
const __is_prod = process.env.NODE_ENV == "production";
7+
const __overide_show_if_dev = true;
78

89
export function SigninToContinuePrmoptProvider({
910
children,
@@ -17,7 +18,9 @@ export function SigninToContinuePrmoptProvider({
1718
return (
1819
<>
1920
{children}
20-
{!__is_dev && shouldshow && <SigninToContinueBannerPrmopt />}
21+
{((__is_prod && shouldshow) || (!__is_prod && __overide_show_if_dev)) && (
22+
<SigninToContinueBannerPrmopt />
23+
)}
2124
</>
2225
);
2326
}
@@ -31,91 +34,93 @@ export function SigninToContinueBannerPrmopt() {
3134

3235
return (
3336
<Positioner>
34-
<Contents>
35-
<Desc>Ready to build your apps with Grida?</Desc>
36-
<NextButton onClick={onnextclick}>Next</NextButton>
37-
</Contents>
37+
<Container>
38+
<h5>Ready to build your Apps with Grida?</h5>
39+
<CTAButton onClick={onnextclick}>
40+
Sign Up
41+
<ArrowRightIcon width={20} height={20} />
42+
</CTAButton>
43+
</Container>
3844
</Positioner>
3945
);
4046
}
4147

4248
const Positioner = styled.div`
43-
display: flex;
44-
align-items: center;
45-
flex-direction: column;
46-
justify-content: center;
47-
align-items: flex-end;
48-
4949
position: fixed;
5050
bottom: 0;
51-
left: 0px;
52-
right: 0px;
51+
left: 0;
52+
right: 0;
53+
padding: 40px 40px;
5354
54-
background-color: #fff;
5555
z-index: 998;
56-
56+
display: flex;
5757
justify-content: center;
5858
flex-direction: column;
59-
align-items: end;
59+
align-items: center;
6060
box-sizing: border-box;
61-
padding: 16px 20px;
6261
6362
a {
6463
margin: 0px 2px;
6564
text-decoration: underline;
6665
}
6766
`;
6867

69-
const Contents = styled.div`
68+
const Container = styled.div`
69+
width: 100%;
70+
max-width: 600px;
71+
min-width: 400px;
72+
background-color: rgba(0, 0, 0, 0.4);
73+
backdrop-filter: blur(21px);
74+
color: white;
7075
display: flex;
71-
justify-content: flex-end;
76+
justify-content: space-between;
7277
flex-direction: row;
7378
align-items: center;
7479
flex: none;
80+
padding: 16px 24px;
81+
border-radius: 48px;
82+
border: 1px solid rgba(255, 255, 255, 0.2);
7583
gap: 48px;
76-
width: 439px;
77-
height: 59px;
7884
box-sizing: border-box;
79-
`;
85+
box-shadow: 0px 4px 32px rgba(0, 0, 0, 0.24);
8086
81-
const Desc = styled.span`
82-
color: rgba(0, 0, 0, 1);
83-
text-overflow: ellipsis;
84-
font-size: 16px;
85-
font-family: "Helvetica Neue", sans-serif;
86-
font-weight: 500;
87-
text-align: center;
87+
h5 {
88+
color: white;
89+
margin: 0;
90+
text-overflow: ellipsis;
91+
font-weight: 500;
92+
}
8893
`;
8994

90-
const NextButton = styled.button`
95+
const CTAButton = styled.button`
96+
cursor: pointer;
9197
display: flex;
9298
justify-content: center;
9399
flex-direction: row;
94100
align-items: center;
95101
flex: none;
96-
gap: 10px;
97-
border-radius: 4px;
98-
width: 116px;
99-
height: 59px;
100-
background-color: rgba(45, 66, 255, 1);
102+
gap: 4px;
103+
border-radius: 24px;
104+
background-color: transparent;
105+
border: 1px solid rgba(255, 255, 255, 0.4);
101106
box-sizing: border-box;
102-
padding: 10px 10px;
107+
padding: 8px 16px;
103108
104109
outline: none;
105-
border: none;
106110
107-
color: rgba(255, 255, 255, 1);
111+
color: white;
108112
text-overflow: ellipsis;
109-
font-size: 21px;
110-
font-family: "Helvetica Neue", sans-serif;
111-
font-weight: 400;
113+
font-weight: 500;
112114
text-align: left;
113115
114116
:hover {
115117
opacity: 0.9;
118+
scale: 1.02;
116119
}
117120
118121
:focus {
119122
opacity: 0.9;
120123
}
124+
125+
transition: all 0.1s ease-in-out;
121126
`;

editor/core/reducers/editor-reducer.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import type {
2121
EnterIsolatedInspectionAction,
2222
ExitIsolatedInspectionAction,
2323
} from "core/actions";
24-
import { EditorState } from "core/states";
24+
import { EditorState, EssentialWorkspaceInfo } from "core/states";
2525
import { NextRouter, useRouter } from "next/router";
2626
import { CanvasStateStore } from "@code-editor/canvas/stores";
2727
import q from "@design-sdk/query";
@@ -31,8 +31,6 @@ import { nanoid } from "nanoid";
3131
import { last_page_by_mode } from "core/stores";
3232
import { track } from "@code-editor/analytics";
3333

34-
const _editor_path_name = "/files/[key]/";
35-
3634
const _DEV_CLEAR_LOG = false;
3735

3836
const clearlog = (by: string) => {
@@ -42,7 +40,10 @@ const clearlog = (by: string) => {
4240
}
4341
};
4442

45-
export function editorReducer(state: EditorState, action: Action): EditorState {
43+
export function editorReducer(
44+
state: EditorState & EssentialWorkspaceInfo,
45+
action: Action
46+
): EditorState {
4647
const router = useRouter();
4748
const filekey = state.design.key;
4849

@@ -395,10 +396,8 @@ function update_route(
395396

396397
// remove undefined fields
397398
Object.keys(q).forEach((k) => q[k] === undefined && delete q[k]);
398-
399399
router.push(
400400
{
401-
pathname: _editor_path_name,
402401
query: { ...router.query, ...q },
403402
},
404403
undefined,

editor/core/states/workspace-initial-state.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { EditorSnapshot } from "./editor-state";
2-
import { WorkspaceState } from "./workspace-state";
2+
import { WorkspaceState, EssentialWorkspaceInfo } from "./workspace-state";
33
import {
44
createInitialHistoryState,
55
createPendingHistoryState,
@@ -23,7 +23,7 @@ export function merge_initial_workspace_state_with_editor_snapshot(
2323
};
2424
}
2525

26-
export function create_initial_pending_workspace_state(): WorkspaceState {
26+
export function create_initial_pending_workspace_state({}: EssentialWorkspaceInfo): WorkspaceState {
2727
return {
2828
taskQueue: {
2929
isBusy: false,

editor/core/states/workspace-state.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import { config } from "@grida/builder-config";
22
import { HistoryState } from "core/states/history-state";
33

4-
export interface WorkspaceState {
4+
export interface EssentialWorkspaceInfo {
5+
// Add workspace seed data here, which cannot be automatically filled on initial state.
6+
}
7+
8+
export interface WorkspaceState extends EssentialWorkspaceInfo {
59
history: HistoryState;
610
/**
711
* hovered layer; single or none.

editor/hooks/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export * from "./use-design";
1+
export * from "./use-figma";
22
export * from "./use-async-effect";
33
export * from "./use-auth-state";
44
export * from "./use-target-node";

editor/hooks/use-figma/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from "./use-figma";
2+
export * from "./use-figma-community";

editor/hooks/use-figma/types.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import type { NextRouter } from "next/router";
2+
import type { TFetchFileForApp } from "@editor/figma-file";
3+
4+
export type UseFigmaInput =
5+
| (UseFigmaFromRouter & UseFigmaOptions)
6+
| (UseFimgaFromUrl & UseFigmaOptions)
7+
| (UseFigmaFromFileNodeKey & UseFigmaOptions);
8+
9+
export interface UseFigmaOptions {
10+
use_session_cache?: boolean;
11+
}
12+
13+
export interface UseFigmaFromRouter {
14+
type: "use-router";
15+
router?: NextRouter;
16+
}
17+
18+
export interface UseFimgaFromUrl {
19+
type: "use-url";
20+
url: string;
21+
}
22+
23+
export interface UseFigmaFromFileNodeKey {
24+
type: "use-file-node-id";
25+
file: string;
26+
node: string;
27+
}
28+
29+
export type TUseDesignFile =
30+
| TFetchFileForApp
31+
| {
32+
__type: "error";
33+
reason: "no-auth" | "unauthorized";
34+
cached?: TFetchFileForApp;
35+
}
36+
| { __type: "error"; reason: "no-file" }
37+
| { __type: "loading" };
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { useState, useEffect } from "react";
2+
import type { TUseDesignFile, UseFigmaInput, UseFimgaFromUrl } from "./types";
3+
import { Client } from "@figma-api/community";
4+
import { TargetNodeConfig } from "query/target-node";
5+
6+
const client = Client();
7+
8+
/**
9+
* Figma Community File Retrieval Hook
10+
* This does not use...
11+
* 1. local store since the api response is static and cached by browser.
12+
* 2. procedual loading since whole file is archived at the server.
13+
* @returns
14+
*/
15+
export function useFigmaCommunityFile({ id }: { id: string }) {
16+
const [file, setFile] = useState<TUseDesignFile>({
17+
__type: "loading",
18+
});
19+
20+
useEffect(() => {
21+
// load with community client
22+
client.file(id).then(({ data }) => {
23+
setFile({
24+
...data,
25+
key: id,
26+
__initial: true, // ?
27+
__type: "file-fetched-for-app",
28+
});
29+
});
30+
}, [id]);
31+
32+
//
33+
return file;
34+
}
35+
36+
export function useFigmaCommunityNode() {
37+
const [design, setDesign] = useState<TargetNodeConfig>(null);
38+
throw new Error("not implemented");
39+
//
40+
}

0 commit comments

Comments
 (0)