Skip to content

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

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

Merged
merged 9 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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}>
{showLogin ? 'Login' : 'Logout'}
</button>
</Button>
);
}
32 changes: 16 additions & 16 deletions packages/astro/src/default/styles/variables.css
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',
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';
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) {
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>
</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[];

/**
* 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