Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support glob patterns in editor.fileTree.allowEdits #332

Merged
merged 9 commits into from
Sep 18, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ A component to list files in a tree view.
}
```

* `allowEditPatterns?: string[]` - Glob patterns for paths that allow editing files and folders. Defaults to `['**']`.
* `allowEditPatterns?: string[]` - Glob patterns for paths that allow editing files and folders. Disabled by default.

* `hideRoot: boolean` - Whether or not to hide the root directory in the tree. Defaults to `false`.

Expand Down
19 changes: 3 additions & 16 deletions packages/astro/src/default/components/LoginButton.tsx
AriPerkkio marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useStore } from '@nanostores/react';
import { classNames } from '@tutorialkit/react';
import { Button } from '@tutorialkit/react';
import { useEffect, useRef, useState } from 'react';
import { authStore } from '../stores/auth-store';
import { login, logout } from './webcontainer';
Expand Down Expand Up @@ -48,21 +48,8 @@ export function LoginButton() {
}, [authStatus.status]);

return (
<button
className={classNames('flex font-500 disabled:opacity-32 items-center text-sm ml-2 px-4 py-1 rounded-md', {
'bg-tk-elements-topBar-primaryButton-backgroundColor text-tk-elements-topBar-primaryButton-textColor':
showLogin,
'bg-tk-elements-topBar-secondaryButton-backgroundColor text-tk-elements-topBar-secondaryButton-textColor':
!showLogin,
'hover:bg-tk-elements-topBar-primaryButton-backgroundColorHover hover:text-tk-elements-topBar-primaryButton-textColorHover':
!disabled && showLogin,
'hover:bg-tk-elements-topBar-secondaryButton-backgroundColorHover hover:text-tk-elements-topBar-secondaryButton-textColorHover':
!disabled && !showLogin,
})}
disabled={disabled}
onClick={onClick}
>
<Button variant={showLogin ? 'primary' : 'secondary'} disabled={disabled} onClick={onClick}>
AriPerkkio marked this conversation as resolved.
Show resolved Hide resolved
{showLogin ? 'Login' : 'Logout'}
</button>
</Button>
);
}
32 changes: 16 additions & 16 deletions packages/astro/src/default/styles/variables.css
AriPerkkio marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,22 @@
--tk-elements-link-secondaryColor: var(--tk-text-secondary);
--tk-elements-link-secondaryColorHover: var(--tk-text-primary);

/* Primary Button */
--tk-elements-primaryButton-backgroundColor: var(--tk-background-accent-secondary);
--tk-elements-primaryButton-backgroundColorHover: var(--tk-background-accent-active);
--tk-elements-primaryButton-textColor: var(--tk-text-primary-inverted);
--tk-elements-primaryButton-textColorHover: var(--tk-text-primary-inverted);
--tk-elements-primaryButton-iconColor: var(--tk-text-primary-inverted);
--tk-elements-primaryButton-iconColorHover: var(--tk-text-primary-inverted);

/* Secondary Button */
--tk-elements-secondaryButton-backgroundColor: var(--tk-elements-app-backgroundColor);
--tk-elements-secondaryButton-backgroundColorHover: var(--tk-background-secondary);
--tk-elements-secondaryButton-textColor: var(--tk-text-secondary);
--tk-elements-secondaryButton-textColorHover: var(--tk-text-primary);
--tk-elements-secondaryButton-iconColor: var(--tk-text-secondary);
--tk-elements-secondaryButton-iconColorHover: var(--tk-text-primary);

/* Content */
--tk-elements-content-textColor: var(--tk-text-body);
--tk-elements-content-headingTextColor: var(--tk-text-primary);
Expand All @@ -163,22 +179,6 @@
--tk-elements-topBar-logo-color: var(--tk-text-active);
--tk-elements-topBar-logo-colorHover: var(--tk-text-active);

/* Top Bar > Primary Button */
--tk-elements-topBar-primaryButton-backgroundColor: var(--tk-background-accent-secondary);
--tk-elements-topBar-primaryButton-backgroundColorHover: var(--tk-background-accent-active);
--tk-elements-topBar-primaryButton-textColor: var(--tk-text-primary-inverted);
--tk-elements-topBar-primaryButton-textColorHover: var(--tk-text-primary-inverted);
--tk-elements-topBar-primaryButton-iconColor: var(--tk-text-primary-inverted);
--tk-elements-topBar-primaryButton-iconColorHover: var(--tk-text-primary-inverted);

/* Top Bar > Secondary Button */
--tk-elements-topBar-secondaryButton-backgroundColor: var(--tk-elements-topBar-backgroundColor);
--tk-elements-topBar-secondaryButton-backgroundColorHover: var(--tk-background-secondary);
--tk-elements-topBar-secondaryButton-textColor: var(--tk-text-secondary);
--tk-elements-topBar-secondaryButton-textColorHover: var(--tk-text-primary);
--tk-elements-topBar-secondaryButton-iconColor: var(--tk-text-secondary);
--tk-elements-topBar-secondaryButton-iconColorHover: var(--tk-text-primary);

/* Previews */
--tk-elements-previews-borderColor: theme('colors.gray.200');

Expand Down
32 changes: 32 additions & 0 deletions packages/react/src/Button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { type ComponentProps, forwardRef, type Ref } from 'react';
import { classNames } from './utils/classnames.js';

interface Props extends ComponentProps<'button'> {
variant?: 'primary' | 'secondary';
}

export const Button = forwardRef(({ className, variant = 'primary', ...props }: Props, ref: Ref<HTMLButtonElement>) => {
return (
<button
ref={ref}
{...props}
className={classNames(
className,
'flex items-center font-500 text-sm ml-2 px-4 py-1 rounded-md disabled:opacity-32',
AriPerkkio marked this conversation as resolved.
Show resolved Hide resolved
variant === 'primary' &&
'bg-tk-elements-primaryButton-backgroundColor text-tk-elements-primaryButton-textColor',

!props.disabled &&
variant === 'primary' &&
'hover:bg-tk-elements-primaryButton-backgroundColorHover hover:text-tk-elements-primaryButton-textColorHover',

variant === 'secondary' &&
'bg-tk-elements-secondaryButton-backgroundColor text-tk-elements-secondaryButton-textColor',

!props.disabled &&
variant === 'secondary' &&
'hover:bg-tk-elements-secondaryButton-backgroundColorHover hover:text-tk-elements-secondaryButton-textColorHover',
)}
/>
);
});
4 changes: 2 additions & 2 deletions packages/react/src/Panels/WorkspacePanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,8 @@ function EditorSection({ theme, tutorialStore, hasEditor }: PanelProps) {
helpAction={helpAction}
onHelpClick={lessonFullyLoaded ? onHelpClick : undefined}
onFileSelect={(filePath) => tutorialStore.setSelectedFile(filePath)}
onFileTreeChange={editorConfig.fileTree.allowEdits ? onFileTreeChange : undefined}
allowEditPatterns={editorConfig.fileTree.allowEdits ? editorConfig.fileTree.allowEdits : undefined}
onFileTreeChange={onFileTreeChange}
allowEditPatterns={editorConfig.fileTree.allowEdits || undefined}
selectedFile={selectedFile}
onEditorScroll={(position) => tutorialStore.setCurrentDocumentScrollPosition(position)}
onEditorChange={(update) => tutorialStore.setCurrentDocumentContent(update.content)}
Expand Down
16 changes: 10 additions & 6 deletions packages/react/src/core/ContextMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import * as RadixDialog from '@radix-ui/react-dialog';
import { DEFAULT_LOCALIZATION, type FileDescriptor, type I18n } from '@tutorialkit/types';
import picomatch from 'picomatch/posix';
AriPerkkio marked this conversation as resolved.
Show resolved Hide resolved
import { useRef, useState, type ComponentProps, type ReactNode } from 'react';
import { Button } from '../Button.js';
import { classNames } from '../utils/classnames.js';

interface FileChangeEvent {
type: FileDescriptor['type'];
Expand All @@ -19,7 +21,7 @@ interface Props extends ComponentProps<'div'> {
/** Callback invoked when file is changed. */
onFileChange?: (event: FileChangeEvent | FileRenameEvent) => void;

/** Glob patterns for paths that allow editing files and folders. Defaults to `['**']`. */
/** Glob patterns for paths that allow editing files and folders. Disabled by default. */
allowEditPatterns?: string[];

/** Directory of the clicked file. */
Expand All @@ -43,7 +45,7 @@ interface Props extends ComponentProps<'div'> {

export function ContextMenu({
onFileChange,
allowEditPatterns = ['**'],
allowEditPatterns,
directory,
i18n,
position = 'before',
Expand All @@ -54,7 +56,7 @@ export function ContextMenu({
const [state, setState] = useState<'idle' | 'add_file' | 'add_folder' | 'add_failed'>('idle');
const inputRef = useRef<HTMLInputElement>(null);

if (!onFileChange) {
if (!onFileChange || !allowEditPatterns?.length) {
AriPerkkio marked this conversation as resolved.
Show resolved Hide resolved
return children;
}

Expand All @@ -67,7 +69,7 @@ export function ContextMenu({

if (name) {
const value = `${directory}/${name}`;
const isAllowed = picomatch.isMatch(value, allowEditPatterns);
const isAllowed = picomatch.isMatch(value, allowEditPatterns!);

if (isAllowed) {
onFileChange?.({
Expand Down Expand Up @@ -143,7 +145,7 @@ export function ContextMenu({
onClose={() => setState('idle')}
>
{i18n?.fileTreeAllowedPatternsText || DEFAULT_LOCALIZATION.fileTreeAllowedPatternsText}
<ul className="list-disc ml-4 mt-2">
<ul className={classNames('mt-2', allowEditPatterns.length > 1 && 'list-disc ml-4')}>
{allowEditPatterns.map((pattern) => (
<li key={pattern} className="mb-1">
<code>{pattern}</code>
Expand Down Expand Up @@ -180,7 +182,9 @@ function Dialog({ title, onClose, children }: { title: string; onClose: () => vo

<div className="my-4">{children}</div>

<RadixDialog.Close className="px-3 py-1 border border-tk-border-primary rounded">OK</RadixDialog.Close>
<RadixDialog.Close asChild>
<Button>OK</Button>
AriPerkkio marked this conversation as resolved.
Show resolved Hide resolved
</RadixDialog.Close>
</div>
</RadixDialog.Content>
</RadixDialog.Portal>
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './BootScreen.js';
export * from './Button.js';
export * from './Nav.js';
export * from './Panels/EditorPanel.js';
export * from './Panels/PreviewPanel.js';
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/utils/classnames.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* @link http://jedwatson.github.io/classnames
*/

type ClassNamesArg = undefined | string | Record<string, boolean> | ClassNamesArg[];
type ClassNamesArg = undefined | false | string | Record<string, boolean> | ClassNamesArg[];
AriPerkkio marked this conversation as resolved.
Show resolved Hide resolved

/**
* A simple JavaScript utility for conditionally joining classNames together.
Expand Down
32 changes: 16 additions & 16 deletions packages/theme/src/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,22 @@ export const theme = {
secondaryColor: 'var(--tk-elements-link-secondaryColor)',
secondaryColorHover: 'var(--tk-elements-link-secondaryColorHover)',
},
primaryButton: {
backgroundColor: 'var(--tk-elements-primaryButton-backgroundColor)',
backgroundColorHover: 'var(--tk-elements-primaryButton-backgroundColorHover)',
textColor: 'var(--tk-elements-primaryButton-textColor)',
textColorHover: 'var(--tk-elements-primaryButton-textColorHover)',
iconColor: 'var(--tk-elements-primaryButton-iconColor)',
iconColorHover: 'var(--tk-elements-primaryButton-iconColorHover)',
},
secondaryButton: {
backgroundColor: 'var(--tk-elements-secondaryButton-backgroundColor)',
backgroundColorHover: 'var(--tk-elements-secondaryButton-backgroundColorHover)',
textColor: 'var(--tk-elements-secondaryButton-textColor)',
textColorHover: 'var(--tk-elements-secondaryButton-textColorHover)',
iconColor: 'var(--tk-elements-secondaryButton-iconColor)',
iconColorHover: 'var(--tk-elements-secondaryButton-iconColorHover)',
},
content: {
textColor: 'var(--tk-elements-content-textColor)',
headingTextColor: 'var(--tk-elements-content-headingTextColor)',
Expand All @@ -170,22 +186,6 @@ export const theme = {
color: 'var(--tk-elements-topBar-logo-color)',
colorHover: 'var(--tk-elements-topBar-logo-colorHover)',
},
primaryButton: {
backgroundColor: 'var(--tk-elements-topBar-primaryButton-backgroundColor)',
backgroundColorHover: 'var(--tk-elements-topBar-primaryButton-backgroundColorHover)',
textColor: 'var(--tk-elements-topBar-primaryButton-textColor)',
textColorHover: 'var(--tk-elements-topBar-primaryButton-textColorHover)',
iconColor: 'var(--tk-elements-topBar-primaryButton-iconColor)',
iconColorHover: 'var(--tk-elements-topBar-primaryButton-iconColorHover)',
},
secondaryButton: {
backgroundColor: 'var(--tk-elements-topBar-secondaryButton-backgroundColor)',
backgroundColorHover: 'var(--tk-elements-topBar-secondaryButton-backgroundColorHover)',
textColor: 'var(--tk-elements-topBar-secondaryButton-textColor)',
textColorHover: 'var(--tk-elements-topBar-secondaryButton-textColorHover)',
iconColor: 'var(--tk-elements-topBar-secondaryButton-iconColor)',
iconColorHover: 'var(--tk-elements-topBar-secondaryButton-iconColorHover)',
},
},
panel: {
backgroundColor: 'var(--tk-elements-panel-backgroundColor)',
Expand Down