diff --git a/src/components/Share.jsx b/src/components/Share.jsx
index 5d9183d..88484c6 100644
--- a/src/components/Share.jsx
+++ b/src/components/Share.jsx
@@ -18,6 +18,55 @@ const TOGGLE_VISIBILITY_API =
? 'http://127.0.0.1:5001/web-maker-app/us-central1/toggleVisibility'
: */ 'https://togglevisibility-ajhkrtmkaq-uc.a.run.app';
+// Layout mode definitions with icons
+const LAYOUT_MODES = [
+ {
+ id: 1,
+ name: 'Preview on right',
+ icon: (
+
+ )
+ },
+ {
+ id: 2,
+ name: 'Preview on bottom',
+ icon: (
+
+ )
+ },
+ {
+ id: 3,
+ name: 'Preview on left',
+ icon: (
+
+ )
+ },
+ {
+ id: 4,
+ name: 'Full screen preview',
+ icon: (
+
+ )
+ },
+ {
+ id: 5,
+ name: 'Three-pane horizontal',
+ icon: (
+
+ )
+ }
+];
+
export function Share({
user,
item,
@@ -26,6 +75,8 @@ export function Share({
onProBtnClick
}) {
const [publicItemCount, setPublicItemCount] = useState();
+ const [selectedLayout, setSelectedLayout] = useState(2); // Default to layout 2
+
useEffect(() => {
if (!user) return;
window.db.getPublicItemCount(user.uid).then(c => {
@@ -75,10 +126,16 @@ export function Share({
}
};
+ const getShareUrl = () => {
+ const baseUrl = `${BASE_URL}/create/${item.id}`;
+ return selectedLayout ? `${baseUrl}?layout=${selectedLayout}` : baseUrl;
+ };
+
const copyUrl = () => {
- navigator.clipboard.writeText(`${BASE_URL}/create/${item.id}`);
+ navigator.clipboard.writeText(getShareUrl());
alertsService.add('URL copied to clipboard');
};
+
if (!user) {
return (
@@ -106,19 +163,70 @@ export function Share({
)}
{item.isPublic && (
-
- Public at{' '}
-
- {BASE_URL}/create/{item.id}
- {' '}
-
-
+
+
+ Public at{' '}
+
+ {getShareUrl()}
+ {' '}
+
+
+
+ {/* Layout Mode Selector */}
+
+
+
+ {LAYOUT_MODES.map(layout => (
+
+ ))}
+
+
+
)}
diff --git a/src/style.css b/src/style.css
index b2cb9ca..6271fec 100644
--- a/src/style.css
+++ b/src/style.css
@@ -14,6 +14,7 @@
--color-text-light: #b0a5d6;
--color-text-lightest-final: #787090;
--clr-brand: purple;
+ --clr-brand-2: #e3ba26;
--color-pro-1: #1fffb3;
--color-pro-2: #f2ff00;
@@ -808,7 +809,7 @@ li.CodeMirror-hint-active {
/*color: white;*/
}
-[data-type="css"] .cm-error {
+[data-type='css'] .cm-error {
background: inherit !important;
}
diff --git a/tests/layout-parameter.test.js b/tests/layout-parameter.test.js
index 431a635..aea69b0 100644
--- a/tests/layout-parameter.test.js
+++ b/tests/layout-parameter.test.js
@@ -54,15 +54,48 @@ describe('Layout Parameter Tests', () => {
const params = new URLSearchParams(global.window.location.search);
global.window.codeHtml = params.get('html') || '';
global.window.codeCss = params.get('css') || '';
- global.window.codeLayout = params.get('layout')
- ? parseInt(params.get('layout'), 10)
- : null;
+ global.window.codeLayout = (() => {
+ const layout = params.get('layout');
+ if (!layout) return null;
+ if (layout === 'full') {
+ return 4;
+ }
+ const _val = parseInt(layout, 10);
+ if (_val >= 1 && _val <= 5) {
+ return _val;
+ }
+ return null;
+ })();
}
expect(global.window.codeLayout).toBe(3);
expect(global.window.codeHtml).toBe('test
');
});
+ test('should handle "full" alias for layout mode 4', () => {
+ // Set up URL with "full" layout parameter
+ global.window.location.search = '?layout=full&html=test
';
+
+ // Simulate the URL parsing logic
+ if (global.window.location.search) {
+ const params = new URLSearchParams(global.window.location.search);
+ global.window.codeLayout = (() => {
+ const layout = params.get('layout');
+ if (!layout) return null;
+ if (layout === 'full') {
+ return 4;
+ }
+ const _val = parseInt(layout, 10);
+ if (_val >= 1 && _val <= 5) {
+ return _val;
+ }
+ return null;
+ })();
+ }
+
+ expect(global.window.codeLayout).toBe(4);
+ });
+
test('should handle invalid layout parameter gracefully', () => {
// Set up URL with invalid layout parameter
global.window.location.search = '?layout=invalid&html=test
';
@@ -70,12 +103,21 @@ describe('Layout Parameter Tests', () => {
// Simulate the URL parsing logic
if (global.window.location.search) {
const params = new URLSearchParams(global.window.location.search);
- global.window.codeLayout = params.get('layout')
- ? parseInt(params.get('layout'), 10)
- : null;
+ global.window.codeLayout = (() => {
+ const layout = params.get('layout');
+ if (!layout) return null;
+ if (layout === 'full') {
+ return 4;
+ }
+ const _val = parseInt(layout, 10);
+ if (_val >= 1 && _val <= 5) {
+ return _val;
+ }
+ return null;
+ })();
}
- expect(global.window.codeLayout).toBe(NaN);
+ expect(global.window.codeLayout).toBe(null);
});
test('should handle layout parameter out of range', () => {
@@ -87,13 +129,22 @@ describe('Layout Parameter Tests', () => {
if (global.window.location.search) {
const params = new URLSearchParams(global.window.location.search);
- global.window.codeLayout = params.get('layout')
- ? parseInt(params.get('layout'), 10)
- : null;
+ global.window.codeLayout = (() => {
+ const layout = params.get('layout');
+ if (!layout) return null;
+ if (layout === 'full') {
+ return 4;
+ }
+ const _val = parseInt(layout, 10);
+ if (_val >= 1 && _val <= 5) {
+ return _val;
+ }
+ return null;
+ })();
}
- // The layout should be parsed but may be outside valid range
- expect(global.window.codeLayout).toBe(layoutValue);
+ // The layout should be null for out-of-range values
+ expect(global.window.codeLayout).toBe(null);
});
});
@@ -120,9 +171,18 @@ describe('Layout Parameter Tests', () => {
const params = new URLSearchParams(global.window.location.search);
global.window.codeHtml = params.get('html') || '';
global.window.codeCss = params.get('css') || '';
- global.window.codeLayout = params.get('layout')
- ? parseInt(params.get('layout'), 10)
- : null;
+ global.window.codeLayout = (() => {
+ const layout = params.get('layout');
+ if (!layout) return null;
+ if (layout === 'full') {
+ return 4;
+ }
+ const _val = parseInt(layout, 10);
+ if (_val >= 1 && _val <= 5) {
+ return _val;
+ }
+ return null;
+ })();
}
expect(global.window.codeLayout).toBe(2);
@@ -138,11 +198,47 @@ describe('Layout Parameter Tests', () => {
// Simulate the URL parsing logic
if (global.window.location.search) {
const params = new URLSearchParams(global.window.location.search);
- global.window.codeLayout = params.get('layout')
- ? parseInt(params.get('layout'), 10)
- : null;
+ global.window.codeLayout = (() => {
+ const layout = params.get('layout');
+ if (!layout) return null;
+ if (layout === 'full') {
+ return 4;
+ }
+ const _val = parseInt(layout, 10);
+ if (_val >= 1 && _val <= 5) {
+ return _val;
+ }
+ return null;
+ })();
}
expect(global.window.codeLayout).toBe(null);
});
+
+ test('should handle all valid layout values', () => {
+ // Test all valid layout values (1-5)
+ const validLayouts = [1, 2, 3, 4, 5];
+
+ validLayouts.forEach(layoutValue => {
+ global.window.location.search = `?layout=${layoutValue}`;
+
+ if (global.window.location.search) {
+ const params = new URLSearchParams(global.window.location.search);
+ global.window.codeLayout = (() => {
+ const layout = params.get('layout');
+ if (!layout) return null;
+ if (layout === 'full') {
+ return 4;
+ }
+ const _val = parseInt(layout, 10);
+ if (_val >= 1 && _val <= 5) {
+ return _val;
+ }
+ return null;
+ })();
+ }
+
+ expect(global.window.codeLayout).toBe(layoutValue);
+ });
+ });
});