Skip to content

Commit 5032007

Browse files
Merge pull request #669 from riccardoperra/668-allow-to-create-multiple-files-without-displaying-it-in-exported-image
feat: allow to create multiple files without displaying it in exported image
2 parents b91d38b + f21e2e8 commit 5032007

File tree

10 files changed

+90
-5
lines changed

10 files changed

+90
-5
lines changed

.changeset/breezy-balloons-taste.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@codeimage/app': minor
3+
---
4+
5+
allow to display only active tab while exporting image

apps/codeimage/src/components/Frame/Frame.css.ts

+20
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {backgroundColorVar, themeVars, withThemeMode} from '@codeimage/ui';
2+
import {themeTokens} from '@codeui/kit';
23
import {createTheme, style} from '@vanilla-extract/css';
34

45
export const [frame, frameVars] = createTheme({
@@ -63,6 +64,25 @@ export const previewPortal = style({
6364
height: 'auto',
6465
opacity: 0,
6566
transformOrigin: 'left top',
67+
selectors: {
68+
'&[data-dev-mode]': {
69+
opacity: 1,
70+
zIndex: 999,
71+
zoom: '50%',
72+
},
73+
},
74+
':after': {
75+
content: 'Debug preview',
76+
position: 'absolute',
77+
left: 0,
78+
top: 0,
79+
zIndex: 999,
80+
borderRadius: themeTokens.radii.md,
81+
padding: themeTokens.spacing['2'],
82+
backgroundColor: '#333',
83+
color: 'white',
84+
margin: themeTokens.spacing['1'],
85+
},
6686
});
6787

6888
export const container = style([

apps/codeimage/src/components/Frame/PreviewFrame.tsx

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import {getAssetsStore, isAssetUrl} from '@codeimage/store/assets/assets';
22
import {AssetsImage} from '@codeimage/store/assets/AssetsImage';
3+
import {getExportCanvasStore} from '@codeimage/store/canvas';
34
import {getRootEditorStore} from '@codeimage/store/editor';
45
import {getActiveEditorStore} from '@codeimage/store/editor/activeEditor';
6+
import {EditorConfigStore} from '@codeimage/store/editor/config.store';
57
import {getFrameState} from '@codeimage/store/editor/frame';
68
import {getTerminalState} from '@codeimage/store/editor/terminal';
79
import {dispatchCopyToClipboard} from '@codeimage/store/effects/onCopyToClipboard';
@@ -17,6 +19,7 @@ import {
1719
VoidProps,
1820
} from 'solid-js';
1921
import {Portal} from 'solid-js/web';
22+
import {provideState} from 'statebuilder';
2023
import {setPreviewEditorView} from '../../hooks/export-snippet';
2124
import {useHotkey} from '../../hooks/use-hotkey';
2225
import {DynamicTerminal} from '../Terminal/DynamicTerminal/DynamicTerminal';
@@ -32,9 +35,13 @@ const PreviewExportEditor = lazy(
3235
);
3336

3437
function PreviewPortal(props: ParentProps) {
38+
const config = provideState(EditorConfigStore);
3539
return (
3640
<Portal>
37-
<div class={styles.previewPortal}>
41+
<div
42+
data-dev-mode={config.get.devMode ? '' : undefined}
43+
class={styles.previewPortal}
44+
>
3845
<Suspense fallback={<FrameSkeleton />}>{props.children}</Suspense>
3946
</div>
4047
</Portal>
@@ -47,6 +54,7 @@ export function PreviewFrame(props: VoidProps<PreviewFrameProps>) {
4754
const terminal = getTerminalState().state;
4855
const editor = getRootEditorStore();
4956
const assetsStore = getAssetsStore();
57+
const exportCanvasStore = getExportCanvasStore();
5058

5159
const filterHotKey = () =>
5260
editor.state.options.focused ||
@@ -112,6 +120,7 @@ export function PreviewFrame(props: VoidProps<PreviewFrameProps>) {
112120
type={terminal.type}
113121
readonlyTab={true}
114122
showTab={true}
123+
showOnlyActiveTab={exportCanvasStore.get.showOnlyActiveTab}
115124
shadow={terminal.shadow}
116125
background={terminal.background}
117126
accentVisible={terminal.accentVisible}

apps/codeimage/src/components/Terminal/MacOsTerminal/MacOsTerminal.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ export const MacOsTerminal: ParentComponent<MacOsTerminalProps> = props => {
5252
<Show when={props.showTab && (!props.lite || props.preview)}>
5353
<TerminalWindowTabList
5454
lite={props.lite}
55+
showOnlyActiveTab={props.showOnlyActiveTab}
5556
preview={props.preview ?? false}
5657
readOnly={props.readonlyTab}
5758
accent={props.accentVisible && !props.alternativeTheme}

apps/codeimage/src/components/Terminal/Tabs/TerminalWindowTabList.tsx

+11-3
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export interface TerminalWindowTabListProps {
2727
lite?: boolean;
2828
preview?: boolean;
2929
small?: boolean;
30+
showOnlyActiveTab?: boolean;
3031
}
3132

3233
export function TerminalWindowTabList(
@@ -61,7 +62,14 @@ export function TerminalWindowTabListContent(
6162
isActive,
6263
} = getRootEditorStore();
6364

64-
const sortableIds = createMemo(() => state.editors.map(editor => editor.id));
65+
const editors = () => {
66+
if (props.showOnlyActiveTab) {
67+
return state.editors.filter(editor => isActive(editor.id));
68+
}
69+
return state.editors;
70+
};
71+
72+
const sortableIds = createMemo(() => editors().map(editor => editor.id));
6573

6674
function handleDragEnd(handler: DragEventParam) {
6775
if (handler.draggable && handler.droppable) {
@@ -102,7 +110,7 @@ export function TerminalWindowTabListContent(
102110
<DragDropSensors />
103111
<ConstrainDragAxis />
104112
<SortableProvider ids={sortableIds()}>
105-
<For each={state.editors}>
113+
<For each={editors()}>
106114
{(editor, index) => {
107115
const icon = createTabIcon(
108116
() => editor.tab.tabName ?? null,
@@ -138,7 +146,7 @@ export function TerminalWindowTabListContent(
138146
handleTabNameChange(editor.id, tabName)
139147
}
140148
onClose={
141-
state.editors.length > 1
149+
!props.readOnly && state.editors.length > 1
142150
? () => removeEditor(editor.id)
143151
: null
144152
}

apps/codeimage/src/components/Terminal/TerminalHost.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export interface BaseTerminalProps
1919
tabIcon?: LanguageIconDefinition['content'];
2020
onTabChange?: (tab: string) => void;
2121
lite?: boolean;
22+
showOnlyActiveTab?: boolean;
2223
themeId: string;
2324
}
2425

apps/codeimage/src/components/Toolbar/ExportButton.tsx

+10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {useI18n} from '@codeimage/locale';
2+
import {getExportCanvasStore} from '@codeimage/store/canvas';
23
import {
34
Box,
45
FieldLabel,
@@ -14,6 +15,7 @@ import {
1415

1516
import {
1617
Button,
18+
Checkbox,
1719
Dialog,
1820
DialogPanelContent,
1921
DialogPanelFooter,
@@ -130,6 +132,7 @@ export type ExportDialogProps = {
130132
export function ExportDialog(props: ExportDialogProps & DialogProps) {
131133
const [t] = useI18n<AppLocaleEntries>();
132134
const [supportWebShare] = useWebshare();
135+
const exportCanvasStore = getExportCanvasStore();
133136
const [mode, setMode] = createSignal<ExportMode>(ExportMode.export);
134137
const [extension, setExtension] = createSignal<ExportExtension>(
135138
ExportExtension.png,
@@ -285,6 +288,13 @@ export function ExportDialog(props: ExportDialogProps & DialogProps) {
285288
step={1}
286289
/>
287290
</FlexField>
291+
292+
<Checkbox
293+
checked={exportCanvasStore.get.showOnlyActiveTab}
294+
onChange={exportCanvasStore.setShowOnlyActiveTab}
295+
size={'md'}
296+
label={'(Export only) Show only active tab'}
297+
/>
288298
</VStack>
289299
</DynamicSizedContainer>
290300
</DialogPanelContent>

apps/codeimage/src/components/Toolbar/ExportContent.tsx

+8-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
Text,
1212
VStack,
1313
} from '@codeimage/ui';
14-
import {PopoverContent} from '@codeui/kit';
14+
import {Checkbox, PopoverContent} from '@codeui/kit';
1515
import {DynamicSizedContainer} from '@ui/DynamicSizedContainer/DynamicSizedContainer';
1616
import {SegmentedField} from '@ui/SegmentedField/SegmentedField';
1717
import {createSignal, Show} from 'solid-js';
@@ -116,6 +116,13 @@ export function ExportPopoverContent() {
116116
</Box>
117117
</HStack>
118118
</FlexField>
119+
120+
<Checkbox
121+
checked={exportCanvasStore.get.showOnlyActiveTab}
122+
onChange={exportCanvasStore.setShowOnlyActiveTab}
123+
size={'md'}
124+
label={'(Export only) Show only active tab'}
125+
/>
119126
</VStack>
120127
</div>
121128
</DynamicSizedContainer>

apps/codeimage/src/state/canvas.ts

+7
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export interface PersistedExportCanvasSettings {
99
devicePixelRatio: number;
1010
jpegQuality: number;
1111
extension: ExportExtension;
12+
showOnlyActiveTab: boolean;
1213
}
1314

1415
export const ExportCanvasStore = defineStore(() => ({
@@ -19,12 +20,14 @@ export const ExportCanvasStore = defineStore(() => ({
1920
devicePixelRatio: 3,
2021
jpegQuality: 100,
2122
extension: ExportExtension.png,
23+
showOnlyActiveTab: false,
2224
}))
2325
.extend(
2426
withIndexedDbPlugin<PersistedExportCanvasSettings>('exportSettings', {
2527
devicePixelRatio: 3,
2628
jpegQuality: 100,
2729
extension: ExportExtension.png,
30+
showOnlyActiveTab: false,
2831
}),
2932
)
3033
.extend((store, context) => {
@@ -34,6 +37,7 @@ export const ExportCanvasStore = defineStore(() => ({
3437
devicePixelRatio: value.devicePixelRatio,
3538
jpegQuality: value.jpegQuality,
3639
extension: value.extension,
40+
showOnlyActiveTab: value.showOnlyActiveTab,
3741
});
3842
}),
3943
);
@@ -56,6 +60,9 @@ export const ExportCanvasStore = defineStore(() => ({
5660
setCanvasSize(width: number, height: number) {
5761
store.set('canvasSize', {width, height});
5862
},
63+
setShowOnlyActiveTab(value: boolean) {
64+
store.set('showOnlyActiveTab', value);
65+
},
5966
initCanvas(el: Accessor<HTMLElement | undefined>) {
6067
createResizeObserver(el, ref => {
6168
setTimeout(() => {

apps/codeimage/src/state/editor/config.store.ts

+17
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,21 @@ export interface ConfigState {
2121
ready: boolean;
2222
fonts: (CustomFontConfiguration & {type: 'web'})[];
2323
systemFonts: (CustomFontConfiguration & {type: 'system'})[];
24+
devMode: boolean;
25+
}
26+
27+
declare global {
28+
interface Window {
29+
toggleDevMode: () => void;
30+
}
2431
}
2532

2633
function getDefaultConfig(): ConfigState {
2734
return {
2835
ready: false,
2936
fonts: [...SUPPORTED_FONTS],
3037
systemFonts: [],
38+
devMode: false,
3139
};
3240
}
3341

@@ -58,6 +66,11 @@ export const EditorConfigStore = defineStore(() => getDefaultConfig())
5866
.extend(_ => {
5967
const fonts = createMemo(() => _.localFontsApi.state().fonts);
6068

69+
const toggleDevMode = () => _.set('devMode', debug => !debug);
70+
onMount(() => {
71+
window.toggleDevMode = toggleDevMode;
72+
});
73+
6174
const buildSystemFontConfiguration = (font: LoadedFont) =>
6275
({
6376
type: 'system',
@@ -77,4 +90,8 @@ export const EditorConfigStore = defineStore(() => getDefaultConfig())
7790
_.set('systemFonts', fontsConfiguration);
7891
}),
7992
);
93+
94+
return {
95+
toggleDevMode,
96+
};
8097
});

0 commit comments

Comments
 (0)