Skip to content
Merged
Changes from all 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
79 changes: 72 additions & 7 deletions docs/src/components/CodeTabs/CodeTabs.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,30 @@
import * as React from 'react';
import { useState, useEffect, type FC } from 'react';
import { useState, useEffect, useMemo, type FC } from 'react';
import { langs } from './dictionary';

import classnames from 'classnames/bind';
import * as classes from './CodeTabs.module.css';
const cn = classnames.bind(classes);

interface CustomEventMap {
'codetabs.changed': CustomEvent<{ lang: string }>;
}

declare global {
interface Window {
addEventListener<K extends keyof CustomEventMap>(
type: K,
listener: (this: Document, ev: CustomEventMap[K]) => void
): void;
removeEventListener<K extends keyof CustomEventMap>(
type: K,
listener: (this: Window, ev: CustomEventMap[K]) => any,
options?: boolean | EventListenerOptions
): void;
dispatchEvent<K extends keyof CustomEventMap>(ev: CustomEventMap[K]): void;
}
}

const STORAGE_KEY = 'cube-docs.default-code-lang';

export interface CodeTabsProps {
Expand All @@ -19,17 +38,52 @@ export interface CodeTabsProps {

export const CodeTabs: FC<CodeTabsProps> = ({ children }) => {
const [selectedTab, setSelectedTab] = useState(0);
const tabs = useMemo(
() =>
children.reduce<Record<string, number>>((dict, tab, i) => {
const result = {
...dict,
};
if (result[tab.props['data-language']] === undefined) {
result[tab.props['data-language']] = i;
}
return result;
}, {}),
children
);

useEffect(() => {
const defaultLang = localStorage.getItem(STORAGE_KEY);

if (defaultLang) {
children.some((tab, i) => {
if (tab.props['data-language'] === defaultLang) {
setSelectedTab(i);
}
});
if (tabs[defaultLang] !== undefined) {
setSelectedTab(tabs[defaultLang]);
}
}

const syncHanlder = (e: CustomEvent<{ lang: string }>) => {
const lang = e.detail.lang;
if (tabs[lang] !== undefined) {
setSelectedTab(tabs[lang]);
}
};

const storageHandler = (e: StorageEvent) => {
if (e.key === STORAGE_KEY) {
const lang = e.newValue;
if (lang && tabs[lang] !== undefined) {
setSelectedTab(tabs[lang]);
}
}
};

window.addEventListener('storage', storageHandler);
window.addEventListener('codetabs.changed', syncHanlder);

return () => {
window.removeEventListener('storage', storageHandler);
window.removeEventListener('codetabs.changed', syncHanlder);
};
}, []);

return (
Expand All @@ -44,12 +98,23 @@ export const CodeTabs: FC<CodeTabsProps> = ({ children }) => {
}
return (
<div
key={i}
className={cn('CodeBlocks__tab', {
[classes.SelectedTab]: i === selectedTab,
})}
onClick={() => {
if (lang === 'javascript' || lang === 'yaml') {
if (
i !== selectedTab &&
(lang === 'javascript' || lang === 'yaml')
) {
localStorage.setItem(STORAGE_KEY, lang);
window.dispatchEvent(
new CustomEvent('codetabs.changed', {
detail: {
lang,
},
})
);
}
setSelectedTab(i);
}}
Expand Down