Skip to content

Commit 14afa89

Browse files
authored
Merge pull request #22 from wajeshubham/dev
Dev
2 parents 0ea1bae + d6e210c commit 14afa89

File tree

15 files changed

+539
-33
lines changed

15 files changed

+539
-33
lines changed

components/editor/SnippngCodeArea.tsx

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import { addDoc, collection, doc, updateDoc } from "firebase/firestore";
2727

2828
const SnippngCodeArea = () => {
2929
const editorRef = useRef<HTMLDivElement>(null); // useRef to persist existing ref. Might be useful when dealing with background image in future
30+
const wrapperRef = useRef<HTMLDivElement>(null);
3031
const [saving, setSaving] = useState(false);
3132
const [updating, setUpdating] = useState(false);
3233

@@ -53,6 +54,8 @@ const SnippngCodeArea = () => {
5354
gradientAngle,
5455
editorWidth,
5556
uid,
57+
bgImageVisiblePatch,
58+
bgBlur,
5659
} = editorConfig;
5760

5861
const saveSnippet = async () => {
@@ -108,23 +111,42 @@ const SnippngCodeArea = () => {
108111
<NoSSRWrapper>
109112
<div className="rounded-md bg-white dark:bg-zinc-900 md:p-8 p-4 flex justify-center border-[1px] flex-col items-center dark:border-zinc-500 border-zinc-200 shadow-md w-full">
110113
<div className="w-full">
111-
<SnippngControlHeader />
114+
<SnippngControlHeader wrapperRef={wrapperRef} />
112115
</div>
116+
{bgImageVisiblePatch ? (
117+
<button
118+
className="dark:text-white text-zinc-900 ml-auto text-xs py-1 px-1.5 mb-1 hover:bg-zinc-100 dark:hover:bg-zinc-700"
119+
onClick={() => {
120+
handleConfigChange("bgImageVisiblePatch")(null);
121+
}}
122+
>
123+
Remove bg image
124+
</button>
125+
) : null}
113126
<div
114127
id="code-wrapper"
128+
ref={wrapperRef}
115129
className={clsx(
116-
"overflow-auto p-16 max-w-full",
130+
"overflow-auto p-16 max-w-full relative",
117131
editorWidth ? "w-fit" : "w-full"
118132
)}
119133
style={{
120-
background: getEditorWrapperBg(
121-
wrapperBg,
122-
gradients,
123-
gradientAngle
124-
),
134+
background: bgImageVisiblePatch
135+
? "none"
136+
: getEditorWrapperBg(wrapperBg, gradients, gradientAngle),
125137
padding: `${paddingVertical}px ${paddingHorizontal}px`,
126138
}}
127139
>
140+
{bgImageVisiblePatch ? (
141+
<img
142+
src={bgImageVisiblePatch}
143+
alt="bg-image"
144+
className="w-full h-full object-cover z-0 absolute inset-0"
145+
style={{
146+
filter: `blur(${bgBlur || 0}px)`,
147+
}}
148+
/>
149+
) : null}
128150
<div
129151
ref={editorRef}
130152
data-testid="editor-container"
@@ -238,6 +260,7 @@ const SnippngCodeArea = () => {
238260
) : null}
239261
</div>
240262
</div>
263+
{/* TODO: Add CTA to remove background image */}
241264
</div>
242265
{uid ? (
243266
<small className="dark:text-zinc-300 text-left text-zinc-600 py-2 inline-block">

components/editor/SnippngControlHeader.tsx

Lines changed: 86 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
import { useSnippngEditor } from "@/context/SnippngEditorContext";
22
import { useToast } from "@/context/ToastContext";
33
import { ColorPicker } from "@/lib/color-picker";
4-
import { DOWNLOAD_OPTIONS, LANGUAGES, THEMES } from "@/lib/constants";
4+
import {
5+
defaultEditorConfig,
6+
DOWNLOAD_OPTIONS,
7+
LANGUAGES,
8+
THEMES,
9+
} from "@/lib/constants";
10+
import { ImagePicker } from "@/lib/image-picker";
511
import { SelectOptionInterface } from "@/types";
612
import { getEditorWrapperBg } from "@/utils";
713
import { Menu, Transition } from "@headlessui/react";
@@ -11,16 +17,19 @@ import {
1117
Cog6ToothIcon,
1218
CommandLineIcon,
1319
DocumentDuplicateIcon,
20+
PhotoIcon,
1421
SparklesIcon,
1522
} from "@heroicons/react/24/outline";
1623
import * as htmlToImage from "html-to-image";
17-
import { Fragment } from "react";
24+
import { Fragment, RefObject } from "react";
1825
import Button from "../form/Button";
1926
import Checkbox from "../form/Checkbox";
2027
import Range from "../form/Range";
2128
import Select from "../form/Select";
2229

23-
const SnippngControlHeader = () => {
30+
const SnippngControlHeader: React.FC<{
31+
wrapperRef: RefObject<HTMLDivElement>;
32+
}> = ({ wrapperRef }) => {
2433
const { editorConfig, handleConfigChange } = useSnippngEditor();
2534
const { addToast } = useToast();
2635

@@ -41,6 +50,8 @@ const SnippngControlHeader = () => {
4150
gradients,
4251
gradientAngle,
4352
snippetsName,
53+
bgBlur = 0,
54+
bgImageVisiblePatch,
4455
} = editorConfig;
4556

4657
const downloadImage = (type: SelectOptionInterface) => {
@@ -108,6 +119,22 @@ const SnippngControlHeader = () => {
108119
data-testid="wrapper-color-picker"
109120
className="relative lg:w-fit w-full flex lg:justify-start justify-end items-center gap-2"
110121
>
122+
<Button
123+
onClick={() => {
124+
if (!navigator?.clipboard)
125+
return addToast({
126+
message: "navigator unavailable",
127+
type: "error",
128+
});
129+
navigator.clipboard?.writeText(code).then(() => {
130+
addToast({
131+
message: "Code snippet copied!",
132+
});
133+
});
134+
}}
135+
>
136+
<DocumentDuplicateIcon className="h-5 w-5 dark:text-white text-zinc-900" />
137+
</Button>
111138
<ColorPicker
112139
color={wrapperBg}
113140
gradientColors={gradients}
@@ -134,22 +161,18 @@ const SnippngControlHeader = () => {
134161
}}
135162
></button>
136163
</ColorPicker>
137-
<Button
138-
onClick={() => {
139-
if (!navigator?.clipboard)
140-
return addToast({
141-
message: "navigator unavailable",
142-
type: "error",
143-
});
144-
navigator.clipboard?.writeText(code).then(() => {
145-
addToast({
146-
message: "Code snippet copied!",
147-
});
148-
});
149-
}}
164+
<ImagePicker
165+
aspect={
166+
wrapperRef?.current
167+
? wrapperRef.current.clientWidth / wrapperRef.current.clientHeight
168+
: 1
169+
}
170+
onChange={(src) => handleConfigChange("bgImageVisiblePatch")(src)}
150171
>
151-
<DocumentDuplicateIcon className="h-5 w-5 dark:text-white text-zinc-900" />
152-
</Button>
172+
<button className="h-8 cursor-pointer rounded-sm outline justify-center items-center outline-1 dark:outline-white outline-zinc-400 flex aspect-square ">
173+
<PhotoIcon className="h-4 w-4 mx-auto dark:text-white text-zinc-900" />
174+
</button>
175+
</ImagePicker>
153176
</div>
154177

155178
<div className="ml-auto">
@@ -222,6 +245,51 @@ const SnippngControlHeader = () => {
222245
}}
223246
/>
224247
</div>
248+
<div className="py-1 px-2">
249+
<Checkbox
250+
label="Remove background"
251+
id="remove-bg"
252+
data-testid="remove-bg"
253+
checked={
254+
wrapperBg === "transparent" &&
255+
!gradients.length &&
256+
!bgBlur &&
257+
!bgImageVisiblePatch
258+
}
259+
onChange={(e) => {
260+
if (!e.target.checked) {
261+
handleConfigChange("bgImageVisiblePatch")(
262+
defaultEditorConfig.bgImageVisiblePatch
263+
);
264+
handleConfigChange("bgBlur")(defaultEditorConfig.bgBlur);
265+
handleConfigChange("gradients")(
266+
defaultEditorConfig.gradients
267+
);
268+
handleConfigChange("wrapperBg")(
269+
defaultEditorConfig.wrapperBg
270+
);
271+
} else {
272+
handleConfigChange("bgImageVisiblePatch")(null);
273+
handleConfigChange("bgBlur")(0);
274+
handleConfigChange("gradients")([]);
275+
handleConfigChange("wrapperBg")("transparent");
276+
}
277+
}}
278+
/>
279+
</div>
280+
<div className="py-1 px-2 z-30">
281+
<Range
282+
label={`Bg blur (${bgBlur}px)`}
283+
value={bgBlur}
284+
max={20}
285+
min={0}
286+
rangeMax="20"
287+
rangeMin="0"
288+
onChange={(e) => {
289+
handleConfigChange("bgBlur")(+e.target.value);
290+
}}
291+
/>
292+
</div>
225293
<div className="py-1 px-2 z-30">
226294
<Range
227295
label={`Font size (${editorFontSize}px)`}

components/form/Input.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ interface Props extends React.InputHTMLAttributes<HTMLInputElement> {
88

99
const Input: React.FC<Props> = ({ label, containerClassName, ...props }) => {
1010
return (
11-
<div className="flex flex-col">
11+
<div className={clsx("flex flex-col", containerClassName || "")}>
1212
{label ? (
1313
<label
1414
className="text-sm my-0.5 dark:text-white text-zinc-900"

components/form/Range.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ interface Props extends React.InputHTMLAttributes<HTMLInputElement> {
88
}
99
const Range: React.FC<Props> = ({ rangeMax, rangeMin, label, ...props }) => {
1010
return (
11-
<div className="w-full my-2">
11+
<div className="w-full my-2 dark:text-white text-zinc-900">
1212
<div>
1313
<p>{label}</p>
1414
</div>

components/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import SnippngWindowControls from "./editor/SnippngWindowControls";
44
import ErrorText from "./ErrorText";
55
import Button from "./form/Button";
66
import Checkbox from "./form/Checkbox";
7+
import Input from "./form/Input";
78
import Range from "./form/Range";
89
import Select from "./form/Select";
910
import Loader from "./Loader";
@@ -12,7 +13,6 @@ import NoSSRWrapper from "./NoSSRWrapper";
1213
import SigninButton from "./SigninButton";
1314
import ThemeToggle from "./ThemeToggle";
1415
import Toast from "./Toast";
15-
1616
export {
1717
Toast,
1818
ThemeToggle,
@@ -28,4 +28,5 @@ export {
2828
ErrorText,
2929
SigninButton,
3030
Loader,
31+
Input,
3132
};

context/SnippngEditorContext.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,10 @@ const SnippngContextProvider: React.FC<{ children: React.ReactNode }> = ({
4242
key: K
4343
) =>
4444
(value: V) => {
45-
setEditorConfig({
46-
...editorConfig,
45+
setEditorConfig((prevConfig) => ({
46+
...prevConfig,
4747
[key]: value,
48-
});
48+
}));
4949
};
5050

5151
const handleLineHeight = useCallback(() => {

lib/color-picker/components/ColorPicker.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import Input from "@/components/form/Input";
1+
import { Input } from "@/components";
22
import { Menu, Transition } from "@headlessui/react";
33
import React, { Fragment, useCallback, useMemo } from "react";
44
import {

lib/constants.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,44 @@ export const DEFAULT_CODE_SNIPPET = `export const debounce = <F extends (...args
458458
return debounced as (...args: Parameters<F>) => ReturnType<F>;
459459
};`;
460460

461+
export const PEXELS_QUERY_STRINGS = [
462+
"background",
463+
"gradient",
464+
"landscape",
465+
"sky",
466+
"night-sky",
467+
"galaxy",
468+
"coding",
469+
"abstract",
470+
"texture",
471+
"beautiful-zoom-backgrounds",
472+
"colors",
473+
"rainbow",
474+
"programming",
475+
"gray",
476+
"teal",
477+
"blue",
478+
"red",
479+
"fruits",
480+
"orange",
481+
"shine",
482+
"stars",
483+
"green",
484+
"food",
485+
"coffee",
486+
"ice",
487+
"ocean",
488+
"plane",
489+
"seascapes",
490+
"art",
491+
"creative",
492+
"summer",
493+
"tea",
494+
"water",
495+
"juice",
496+
"ice-cream",
497+
];
498+
461499
export const defaultEditorConfig: SnippngEditorConfigInterface = {
462500
code: DEFAULT_CODE_SNIPPET,
463501
snippetsName: "",
@@ -479,6 +517,8 @@ export const defaultEditorConfig: SnippngEditorConfigInterface = {
479517
gradients: ["#ba68c8", "#ffa7c4", "#e57373"],
480518
gradientAngle: 140,
481519
editorWidth: 0,
520+
bgImageVisiblePatch: null,
521+
bgBlur: 0,
482522
};
483523

484524
export const DEFAULT_BASE_SETUP = {

0 commit comments

Comments
 (0)