diff --git a/canon-docs/package.json b/canon-docs/package.json index 824a645f99..9fddf08c20 100644 --- a/canon-docs/package.json +++ b/canon-docs/package.json @@ -9,11 +9,15 @@ "watch-css": "node scripts/watch-css.js" }, "dependencies": { + "@codemirror/lang-sass": "^6.0.2", + "@lezer/highlight": "^1.2.1", "@mdx-js/loader": "^3.1.0", "@mdx-js/react": "^3.1.0", "@next/mdx": "^15.1.4", "@storybook/react": "^8.4.7", "@types/mdx": "^2.0.13", + "@uiw/codemirror-themes": "^4.23.7", + "@uiw/react-codemirror": "^4.23.7", "next": "14.2.23", "react": "^18", "react-dom": "^18", diff --git a/canon-docs/src/app/globals.css b/canon-docs/src/app/globals.css index 4b39735a22..5efc0407e7 100644 --- a/canon-docs/src/app/globals.css +++ b/canon-docs/src/app/globals.css @@ -35,3 +35,37 @@ iframe { font-weight: var(--shiki-dark-font-weight) !important; text-decoration: var(--shiki-dark-text-decoration) !important; } + +.cm-editor { + transition: background-color 0.2s ease-in-out; +} + +.ͼ2 .cm-gutters { + background-color: var(--canon-surface-2); + border-right: 1px solid var(--canon-border-base); + transition: background-color 0.2s ease-in-out, border-color 0.2s ease-in-out; +} + +.ͼ1 .cm-lineNumbers .cm-gutterElement { + padding-right: 8px; + padding-left: 8px; + font-size: 0.875rem; + display: flex; + align-items: center; + justify-content: flex-end; + min-width: 34px; +} + +.cm-line { + font-size: 0.875rem; +} + +.ͼ1 .cm-line { + padding-left: 12px; + padding-top: 1px; + padding-bottom: 1px; +} + +.cm-focused { + outline: none !important; +} diff --git a/canon-docs/src/app/layout.tsx b/canon-docs/src/app/layout.tsx index 6eb1856a1d..99b5f22739 100644 --- a/canon-docs/src/app/layout.tsx +++ b/canon-docs/src/app/layout.tsx @@ -2,7 +2,7 @@ import type { Metadata } from 'next'; import { Sidebar } from '../components/Sidebar'; import { Toolbar } from '@/components/Toolbar'; import { Providers } from './providers'; - +import { CustomTheme } from '@/components/CustomTheme'; import styles from './page.module.css'; import './globals.css'; @@ -13,6 +13,7 @@ import '/public/backstage.css'; export const metadata: Metadata = { title: 'Canon', description: 'UI library for Backstage', + metadataBase: new URL('https://canon.backstage.io'), }; export default function RootLayout({ @@ -35,6 +36,7 @@ export default function RootLayout({ {children} + diff --git a/canon-docs/src/components/CustomTheme/customTheme.tsx b/canon-docs/src/components/CustomTheme/customTheme.tsx new file mode 100644 index 0000000000..3d8ed394bd --- /dev/null +++ b/canon-docs/src/components/CustomTheme/customTheme.tsx @@ -0,0 +1,147 @@ +'use client'; + +import { useEffect, useState, useCallback } from 'react'; +import CodeMirror from '@uiw/react-codemirror'; +import { sass } from '@codemirror/lang-sass'; +import styles from './styles.module.css'; +import { usePlayground } from '@/utils/playground-context'; +import { AnimatePresence, motion } from 'framer-motion'; +import { Icon } from '../../../../packages/canon'; +import { createTheme } from '@uiw/codemirror-themes'; +import { tags as t } from '@lezer/highlight'; + +const defaultTheme = `:root { + --canon-accent: #000; +}`; + +const myTheme = createTheme({ + theme: 'light', + settings: { + background: 'var(--canon-surface-1)', + backgroundImage: '', + foreground: '#6182B8', + caret: '#5d00ff', + selection: '#036dd626', + selectionMatch: '#036dd626', + lineHighlight: '#8a91991a', + gutterBackground: '#fff', + gutterForeground: '#8a919966', + }, + styles: [ + { tag: t.comment, color: '#787b8099' }, + { tag: t.variableName, color: '#0080ff' }, + { tag: [t.string, t.special(t.brace)], color: '#6182B8' }, + { tag: t.number, color: '#6182B8' }, + { tag: t.bool, color: '#6182B8' }, + { tag: t.null, color: '#6182B8' }, + { tag: t.keyword, color: '#6182B8' }, + { tag: t.operator, color: '#6182B8' }, + { tag: t.className, color: '#6182B8' }, + { tag: t.definition(t.typeName), color: '#6182B8' }, + { tag: t.typeName, color: '#6182B8' }, + { tag: t.angleBracket, color: '#6182B8' }, + { tag: t.tagName, color: '#6182B8' }, + { tag: t.attributeName, color: '#6182B8' }, + ], +}); + +export const CustomTheme = () => { + const [isClient, setIsClient] = useState(false); + const [open, setOpen] = useState(true); + const [customTheme, setCustomTheme] = useState(undefined); + const { selectedThemeName } = usePlayground(); + const [savedMessage, setSavedMessage] = useState('Save'); + + const updateStyleElement = (theme: string) => { + let styleElement = document.getElementById( + 'custom-theme-style', + ) as HTMLStyleElement; + + if (!styleElement) { + styleElement = document.createElement('style'); + styleElement.id = 'custom-theme-style'; + document.head.appendChild(styleElement); + } + + styleElement.textContent = theme; + }; + + useEffect(() => { + if (selectedThemeName === 'custom') { + let storedTheme = localStorage.getItem('customThemeCss'); + if (!storedTheme) { + storedTheme = defaultTheme; + localStorage.setItem('customThemeCss', storedTheme); + } + setCustomTheme(storedTheme); + updateStyleElement(storedTheme); + } else { + const styleElement = document.getElementById( + 'custom-theme-style', + ) as HTMLStyleElement; + if (styleElement) { + styleElement.remove(); + } + } + }, [selectedThemeName]); + + useEffect(() => { + setIsClient(true); + }, []); + + const handleSave = () => { + if (customTheme) { + localStorage.setItem('customThemeCss', customTheme); + updateStyleElement(customTheme); + setSavedMessage('Saved!'); + setTimeout(() => setSavedMessage('Save'), 1000); + } + }; + + const handleChange = useCallback((val: string) => { + setCustomTheme(val); + }, []); + + if (isClient === false) return null; + + return ( + + {selectedThemeName === 'custom' && ( + +
+
Custom Theme
+
+ {open && ( + + )} + +
+
+
+ +
+
+ )} +
+ ); +}; diff --git a/canon-docs/src/components/CustomTheme/index.ts b/canon-docs/src/components/CustomTheme/index.ts new file mode 100644 index 0000000000..6805b2c087 --- /dev/null +++ b/canon-docs/src/components/CustomTheme/index.ts @@ -0,0 +1 @@ +export { CustomTheme } from './customTheme'; diff --git a/canon-docs/src/components/CustomTheme/styles.module.css b/canon-docs/src/components/CustomTheme/styles.module.css new file mode 100644 index 0000000000..a4f51c8a1d --- /dev/null +++ b/canon-docs/src/components/CustomTheme/styles.module.css @@ -0,0 +1,77 @@ +.container { + position: fixed; + bottom: 16px; + right: 16px; + width: 240px; + height: 47px; + background-color: var(--canon-surface-1); + border-radius: 0.375rem; + border: 1px solid var(--canon-border-base); + display: flex; + flex-direction: column; + overflow: hidden; + transition-property: background-color, border-color, height, width; + transition-duration: 0.2s; + transition-timing-function: ease-in-out; +} + +.open { + width: 36%; + height: 348px; +} + +.editor { + flex: 1; +} + +.editorContainer { + overflow: hidden; +} + +.header { + height: 46px; + flex-shrink: 0; + border-bottom: 1px solid var(--canon-border-base); + background-color: var(--canon-surface-1); + display: flex; + justify-content: space-between; + align-items: center; + padding: 0 12px 0 16px; + transition: background-color 0.2s ease-in-out, border-color 0.2s ease-in-out; +} + +.headerLeft { + font-size: 0.875rem; +} + +.headerRight { + display: flex; + gap: 8px; +} + +.buttonSave { + all: unset; + height: 28px; + padding: 0 8px; + color: #fff; + background-color: #000; + border-radius: 0.25rem; + cursor: pointer; + font-size: 0.75rem; +} + +.buttonClose { + all: unset; + height: 28px; + padding: 0 8px; + color: #fff; + background-color: var(--canon-surface-2); + color: var(--canon-text-primary); + transition: background-color 0.2s ease-in-out; + border-radius: 0.25rem; + cursor: pointer; + font-size: 0.875rem; + display: flex; + align-items: center; + justify-content: center; +} diff --git a/canon-docs/src/components/Sidebar/Sidebar.module.css b/canon-docs/src/components/Sidebar/Sidebar.module.css index 870f504d28..f3bdd3f2e7 100644 --- a/canon-docs/src/components/Sidebar/Sidebar.module.css +++ b/canon-docs/src/components/Sidebar/Sidebar.module.css @@ -35,15 +35,11 @@ position: relative; } -.menu a { - display: flex; - text-decoration: none; - height: 28px; - align-items: center; -} - .section { width: 100%; + display: flex; + flex-direction: column; + gap: 2px; } .sectionTitle { @@ -54,12 +50,14 @@ } .line { + text-decoration: none; + align-items: center; width: 100%; display: flex; flex-direction: row; justify-content: space-between; align-items: center; - height: 28px; + height: 26px; padding: 0 12px; border-radius: 4px; transition: background-color 0.2s ease-in-out; diff --git a/canon-docs/src/components/Sidebar/docs.tsx b/canon-docs/src/components/Sidebar/docs.tsx index 13c1675c20..f207036cfa 100644 --- a/canon-docs/src/components/Sidebar/docs.tsx +++ b/canon-docs/src/components/Sidebar/docs.tsx @@ -2,8 +2,7 @@ import Link from 'next/link'; import { components, overview, layoutComponents, theme } from '@/utils/data'; -import { Box } from '../../../../packages/canon/src/components/Box'; -import { Text } from '../../../../packages/canon/src/components/Text'; +import { Box } from '../../../../packages/canon'; import { motion } from 'framer-motion'; import styles from './Sidebar.module.css'; import { usePathname } from 'next/navigation'; diff --git a/canon-docs/src/components/Toolbar/theme-name.module.css b/canon-docs/src/components/Toolbar/theme-name.module.css index 6f2ceb427f..c9700c571b 100644 --- a/canon-docs/src/components/Toolbar/theme-name.module.css +++ b/canon-docs/src/components/Toolbar/theme-name.module.css @@ -43,7 +43,7 @@ box-sizing: border-box; padding-block: 0.25rem; border-radius: 0.375rem; - background-color: canvas; + background-color: var(--canon-surface-1); color: var(--color-gray-900); border: 1px solid var(--canon-border-base); padding-inline: 0.25rem; diff --git a/canon-docs/src/components/Toolbar/theme-name.tsx b/canon-docs/src/components/Toolbar/theme-name.tsx index 57c858dd44..07b734de34 100644 --- a/canon-docs/src/components/Toolbar/theme-name.tsx +++ b/canon-docs/src/components/Toolbar/theme-name.tsx @@ -6,8 +6,9 @@ import { Icon } from '@backstage/canon'; import { usePlayground } from '@/utils/playground-context'; const themes = [ - { name: 'Backstage Legacy', value: 'legacy' }, { name: 'Backstage Default', value: 'default' }, + { name: 'Backstage Legacy', value: 'legacy' }, + { name: 'Custom theme', value: 'custom' }, ]; export const ThemeNameSelector = () => { @@ -31,7 +32,7 @@ export const ThemeNameSelector = () => { {themes.map(({ name, value }) => ( - + diff --git a/canon-docs/src/mdx-components.tsx b/canon-docs/src/mdx-components.tsx index 59eee5e18f..eec8eec438 100644 --- a/canon-docs/src/mdx-components.tsx +++ b/canon-docs/src/mdx-components.tsx @@ -2,7 +2,6 @@ import React, { ReactNode } from 'react'; import type { MDXComponents } from 'mdx/types'; import Image, { ImageProps } from 'next/image'; import { CodeBlock } from '@/components/CodeBlock'; -import { Heading } from '../../packages/canon/src/components/Heading'; import { Box } from '../../packages/canon/src/components/Box'; export function useMDXComponents(components: MDXComponents): MDXComponents { diff --git a/canon-docs/src/utils/playground-context.tsx b/canon-docs/src/utils/playground-context.tsx index 198c5a9aab..721851c3e4 100644 --- a/canon-docs/src/utils/playground-context.tsx +++ b/canon-docs/src/utils/playground-context.tsx @@ -7,16 +7,19 @@ import React, { } from 'react'; import { components } from './data'; +type Theme = 'light' | 'dark'; +type ThemeName = 'legacy' | 'default' | 'custom'; + // Create a context with an empty array as the default value const PlaygroundContext = createContext<{ selectedScreenSizes: string[]; setSelectedScreenSizes: (screenSizes: string[]) => void; selectedComponents: string[]; setSelectedComponents: (components: string[]) => void; - selectedTheme: string | null; - setSelectedTheme: (theme: string) => void; - selectedThemeName: string; - setSelectedThemeName: (themeName: string) => void; + selectedTheme: Theme; + setSelectedTheme: (theme: Theme) => void; + selectedThemeName: ThemeName; + setSelectedThemeName: (themeName: ThemeName) => void; }>({ selectedScreenSizes: [], setSelectedScreenSizes: () => {}, @@ -37,12 +40,14 @@ export const PlaygroundProvider = ({ children }: { children: ReactNode }) => { const [selectedComponents, setSelectedComponents] = useState( components.map(component => component.slug), ); - const [selectedTheme, setSelectedTheme] = useState(() => { - return isBrowser ? localStorage.getItem('theme') : 'light'; - }); - const [selectedThemeName, setSelectedThemeName] = useState(() => { + const [selectedTheme, setSelectedTheme] = useState(() => { return isBrowser - ? localStorage.getItem('theme-name') || 'default' + ? (localStorage.getItem('theme') as Theme) || 'light' + : 'light'; + }); + const [selectedThemeName, setSelectedThemeName] = useState(() => { + return isBrowser + ? (localStorage.getItem('theme-name') as ThemeName) || 'default' : 'default'; }); diff --git a/canon-docs/yarn.lock b/canon-docs/yarn.lock index fd0b1f8742..e8b236002c 100644 --- a/canon-docs/yarn.lock +++ b/canon-docs/yarn.lock @@ -5,6 +5,133 @@ __metadata: version: 6 cacheKey: 8 +"@babel/runtime@npm:^7.18.6": + version: 7.26.0 + resolution: "@babel/runtime@npm:7.26.0" + dependencies: + regenerator-runtime: ^0.14.0 + checksum: c8e2c0504ab271b3467a261a8f119bf2603eb857a0d71e37791f4e3fae00f681365073cc79f141ddaa90c6077c60ba56448004ad5429d07ac73532be9f7cf28a + languageName: node + linkType: hard + +"@codemirror/autocomplete@npm:^6.0.0": + version: 6.18.4 + resolution: "@codemirror/autocomplete@npm:6.18.4" + dependencies: + "@codemirror/language": ^6.0.0 + "@codemirror/state": ^6.0.0 + "@codemirror/view": ^6.17.0 + "@lezer/common": ^1.0.0 + checksum: 4216f45a17f6cfd8d33df53f940396f7d3707662570bf3a79d8d333f926e273a265fac13c362e29e3fa57ccdf444f1a047862f5f56c672cfc669c87ee975858f + languageName: node + linkType: hard + +"@codemirror/commands@npm:^6.0.0, @codemirror/commands@npm:^6.1.0": + version: 6.8.0 + resolution: "@codemirror/commands@npm:6.8.0" + dependencies: + "@codemirror/language": ^6.0.0 + "@codemirror/state": ^6.4.0 + "@codemirror/view": ^6.27.0 + "@lezer/common": ^1.1.0 + checksum: 7d819bab4830ec7b8c5dffdec4b035dfa664bfd1d2675e639e08a459df65f45be111e1b8b569b1a8a3253d5980cf2ecf4394d8a13509996cca1b65cc16d47a4e + languageName: node + linkType: hard + +"@codemirror/lang-css@npm:^6.2.0": + version: 6.3.1 + resolution: "@codemirror/lang-css@npm:6.3.1" + dependencies: + "@codemirror/autocomplete": ^6.0.0 + "@codemirror/language": ^6.0.0 + "@codemirror/state": ^6.0.0 + "@lezer/common": ^1.0.2 + "@lezer/css": ^1.1.7 + checksum: ed175d75d75bc0a059d1e60b3dcd8464d570da14fc97388439943c9c43e1e9146e37b83fe2ccaad9cd387420b7b411ea1d24ede78ecd1f2045a38acbb4dd36bc + languageName: node + linkType: hard + +"@codemirror/lang-sass@npm:^6.0.2": + version: 6.0.2 + resolution: "@codemirror/lang-sass@npm:6.0.2" + dependencies: + "@codemirror/lang-css": ^6.2.0 + "@codemirror/language": ^6.0.0 + "@codemirror/state": ^6.0.0 + "@lezer/common": ^1.0.2 + "@lezer/sass": ^1.0.0 + checksum: e7665aaab70476a952522b143fd7bd59f6c025746cbf7b542f6965f94eecac483b4afd03f6da98aaa1572e379194309b241c5264eff05c681c637aa26651b9ab + languageName: node + linkType: hard + +"@codemirror/language@npm:^6.0.0": + version: 6.10.8 + resolution: "@codemirror/language@npm:6.10.8" + dependencies: + "@codemirror/state": ^6.0.0 + "@codemirror/view": ^6.23.0 + "@lezer/common": ^1.1.0 + "@lezer/highlight": ^1.0.0 + "@lezer/lr": ^1.0.0 + style-mod: ^4.0.0 + checksum: 679b69d69faa94f028f996a7005d0c6c2a2e4cd7a7a2614f615c23d7b642c31fc1837915248e864cb1ad59a2f032d1a7a8ef486b5f9904e5f6fbe6f7d2882c38 + languageName: node + linkType: hard + +"@codemirror/lint@npm:^6.0.0": + version: 6.8.4 + resolution: "@codemirror/lint@npm:6.8.4" + dependencies: + "@codemirror/state": ^6.0.0 + "@codemirror/view": ^6.35.0 + crelt: ^1.0.5 + checksum: 640e3dd44eb167d952eb5c5b8518919ba46e164aa3471776342f7f9361e676b4627a76a9f01d51b22127b97413f2bc9b8c60299d8dfdd5fc8ad0225d42de7669 + languageName: node + linkType: hard + +"@codemirror/search@npm:^6.0.0": + version: 6.5.8 + resolution: "@codemirror/search@npm:6.5.8" + dependencies: + "@codemirror/state": ^6.0.0 + "@codemirror/view": ^6.0.0 + crelt: ^1.0.5 + checksum: 0f9633037492a7b647b606c30255ea42c4327319e643be7ea3aa2913ed8e4aa662589f457e376636521c7d4d1215fae0e8939f127db9c0790b19ae3b654c3bc4 + languageName: node + linkType: hard + +"@codemirror/state@npm:^6.0.0, @codemirror/state@npm:^6.1.1, @codemirror/state@npm:^6.4.0, @codemirror/state@npm:^6.5.0": + version: 6.5.1 + resolution: "@codemirror/state@npm:6.5.1" + dependencies: + "@marijn/find-cluster-break": ^1.0.0 + checksum: b7d6de9a87d5b55dadfadaeb6e1c991e0a91845d3cdd0bd953391f05363fcbaf21de79a4eec2816ab8c3e31293faeca82cc2bb729d080779df94b14e28ae0d8a + languageName: node + linkType: hard + +"@codemirror/theme-one-dark@npm:^6.0.0": + version: 6.1.2 + resolution: "@codemirror/theme-one-dark@npm:6.1.2" + dependencies: + "@codemirror/language": ^6.0.0 + "@codemirror/state": ^6.0.0 + "@codemirror/view": ^6.0.0 + "@lezer/highlight": ^1.0.0 + checksum: 29bc09f79534115f62658caf3d0db527fe347d058b69a8c7f580ae636827377aadd0606fd0d83dbab8d6f3b0a5df53d3253c619341b5fb93d2c8291a8efb9556 + languageName: node + linkType: hard + +"@codemirror/view@npm:^6.0.0, @codemirror/view@npm:^6.17.0, @codemirror/view@npm:^6.23.0, @codemirror/view@npm:^6.27.0, @codemirror/view@npm:^6.35.0": + version: 6.36.2 + resolution: "@codemirror/view@npm:6.36.2" + dependencies: + "@codemirror/state": ^6.5.0 + style-mod: ^4.1.0 + w3c-keyname: ^2.2.4 + checksum: a58c64b623ddc65bb864917297f3b37f8e95280deec442024c43a9513b26352c829665c5d98e4dfcae104e8ecdfdb774d94a395a29da98a919c83482d2c14152 + languageName: node + linkType: hard + "@esbuild/aix-ppc64@npm:0.24.2": version: 0.24.2 resolution: "@esbuild/aix-ppc64@npm:0.24.2" @@ -261,6 +388,60 @@ __metadata: languageName: node linkType: hard +"@lezer/common@npm:^1.0.0, @lezer/common@npm:^1.0.2, @lezer/common@npm:^1.1.0, @lezer/common@npm:^1.2.0": + version: 1.2.3 + resolution: "@lezer/common@npm:1.2.3" + checksum: 9b5f52d949adae69d077f56c0b1c2295923108c3dfb241dd9f17654ff708f3eab81ff9fa7f0d0e4a668eabdcb9d961c73e75caca87c966ca1436e30e49130fcb + languageName: node + linkType: hard + +"@lezer/css@npm:^1.1.7": + version: 1.1.9 + resolution: "@lezer/css@npm:1.1.9" + dependencies: + "@lezer/common": ^1.2.0 + "@lezer/highlight": ^1.0.0 + "@lezer/lr": ^1.0.0 + checksum: 25c63475061a3c9f87961a7f85c5f547f14fb7e81b0864675d2206999a874a0559d676145c74c6ccde39519dbc8aa33e216265f5366d08060507b6c9e875fe0f + languageName: node + linkType: hard + +"@lezer/highlight@npm:^1.0.0, @lezer/highlight@npm:^1.2.1": + version: 1.2.1 + resolution: "@lezer/highlight@npm:1.2.1" + dependencies: + "@lezer/common": ^1.0.0 + checksum: a8822d7e37f79ff64669eb2df4a9f9d16580e88f2b276a646092e19a9bdccac304e92510e200e35869a8b1f6c27eba5972c508d347a277e9b722d582ab7a23d5 + languageName: node + linkType: hard + +"@lezer/lr@npm:^1.0.0": + version: 1.4.2 + resolution: "@lezer/lr@npm:1.4.2" + dependencies: + "@lezer/common": ^1.0.0 + checksum: 94318ad046c7dfcc8d37e26cb85b99623c39aef60aa51ec2abb30928e7a649f38fa5520f34bd5b356f1db11b6991999589f039e87c8949b0f163be3764f029d8 + languageName: node + linkType: hard + +"@lezer/sass@npm:^1.0.0": + version: 1.0.7 + resolution: "@lezer/sass@npm:1.0.7" + dependencies: + "@lezer/common": ^1.2.0 + "@lezer/highlight": ^1.0.0 + "@lezer/lr": ^1.0.0 + checksum: 32d37aa5d3143033f0b886c33a293b1d28b7eecdf2cb979cf7b4cbba0587be227dfed246c27116060ac9b2b2c0fe4b09df4b672690dd0593e876529583e7ef2a + languageName: node + linkType: hard + +"@marijn/find-cluster-break@npm:^1.0.0": + version: 1.0.2 + resolution: "@marijn/find-cluster-break@npm:1.0.2" + checksum: 0d836de25e04d58325813401ef3c2d34caf040da985a5935fcbc9d84e7b47a21bdb15f57d70c2bf0960bd29ed3dbbb1afd00cdd0fc4fafbee7fd0ffe7d508ae1 + languageName: node + linkType: hard + "@mdx-js/loader@npm:^3.1.0": version: 3.1.0 resolution: "@mdx-js/loader@npm:3.1.0" @@ -904,6 +1085,66 @@ __metadata: languageName: node linkType: hard +"@uiw/codemirror-extensions-basic-setup@npm:4.23.7": + version: 4.23.7 + resolution: "@uiw/codemirror-extensions-basic-setup@npm:4.23.7" + dependencies: + "@codemirror/autocomplete": ^6.0.0 + "@codemirror/commands": ^6.0.0 + "@codemirror/language": ^6.0.0 + "@codemirror/lint": ^6.0.0 + "@codemirror/search": ^6.0.0 + "@codemirror/state": ^6.0.0 + "@codemirror/view": ^6.0.0 + peerDependencies: + "@codemirror/autocomplete": ">=6.0.0" + "@codemirror/commands": ">=6.0.0" + "@codemirror/language": ">=6.0.0" + "@codemirror/lint": ">=6.0.0" + "@codemirror/search": ">=6.0.0" + "@codemirror/state": ">=6.0.0" + "@codemirror/view": ">=6.0.0" + checksum: 656c5f78db4c6216a9a7eeb65455f52b002b7a5426bb1b05f11b896d5dba9887c7b9ee5aee9fe369d6c7b3c69128ee842cb5c8fe029cd07c2e48ec9358039a30 + languageName: node + linkType: hard + +"@uiw/codemirror-themes@npm:^4.23.7": + version: 4.23.7 + resolution: "@uiw/codemirror-themes@npm:4.23.7" + dependencies: + "@codemirror/language": ^6.0.0 + "@codemirror/state": ^6.0.0 + "@codemirror/view": ^6.0.0 + peerDependencies: + "@codemirror/language": ">=6.0.0" + "@codemirror/state": ">=6.0.0" + "@codemirror/view": ">=6.0.0" + checksum: 8c2a9a7ee8df2de3f09ad1f18979c4b407f7dd03e1f6ddfe47837b9e4769b566a70259ec8c398473b6b6db79cdb8809d4acc2f2ed7851743e13ff95308f52e33 + languageName: node + linkType: hard + +"@uiw/react-codemirror@npm:^4.23.7": + version: 4.23.7 + resolution: "@uiw/react-codemirror@npm:4.23.7" + dependencies: + "@babel/runtime": ^7.18.6 + "@codemirror/commands": ^6.1.0 + "@codemirror/state": ^6.1.1 + "@codemirror/theme-one-dark": ^6.0.0 + "@uiw/codemirror-extensions-basic-setup": 4.23.7 + codemirror: ^6.0.0 + peerDependencies: + "@babel/runtime": ">=7.11.0" + "@codemirror/state": ">=6.0.0" + "@codemirror/theme-one-dark": ">=6.0.0" + "@codemirror/view": ">=6.0.0" + codemirror: ">=6.0.0" + react: ">=16.8.0" + react-dom: ">=16.8.0" + checksum: 5f6318b290f479c4718129578bdccbbdf64e3b588fdd79e3d80224779219eae7e249d40e4f88c864ed6ae40ea93036042313e983a022349563698593a2bf2e6c + languageName: node + linkType: hard + "@ungap/structured-clone@npm:^1.0.0, @ungap/structured-clone@npm:^1.2.0": version: 1.2.1 resolution: "@ungap/structured-clone@npm:1.2.1" @@ -1254,6 +1495,8 @@ __metadata: version: 0.0.0-use.local resolution: "canon-docs@workspace:." dependencies: + "@codemirror/lang-sass": ^6.0.2 + "@lezer/highlight": ^1.2.1 "@mdx-js/loader": ^3.1.0 "@mdx-js/react": ^3.1.0 "@next/mdx": ^15.1.4 @@ -1262,6 +1505,8 @@ __metadata: "@types/node": ^20 "@types/react": ^18 "@types/react-dom": ^18 + "@uiw/codemirror-themes": ^4.23.7 + "@uiw/react-codemirror": ^4.23.7 concurrently: ^9.1.2 eslint: ^8 eslint-config-next: 14.2.23 @@ -1339,6 +1584,21 @@ __metadata: languageName: node linkType: hard +"codemirror@npm:^6.0.0": + version: 6.0.1 + resolution: "codemirror@npm:6.0.1" + dependencies: + "@codemirror/autocomplete": ^6.0.0 + "@codemirror/commands": ^6.0.0 + "@codemirror/language": ^6.0.0 + "@codemirror/lint": ^6.0.0 + "@codemirror/search": ^6.0.0 + "@codemirror/state": ^6.0.0 + "@codemirror/view": ^6.0.0 + checksum: 1a78f7077ac5801bdbff162aa0c61bf2b974603c7e9a477198c3ce50c789af674a061d7c293c58b73807eda345c2b5228c38ad2aabb9319d552d5486f785cbef + languageName: node + linkType: hard + "collapse-white-space@npm:^2.0.0": version: 2.1.0 resolution: "collapse-white-space@npm:2.1.0" @@ -1394,6 +1654,13 @@ __metadata: languageName: node linkType: hard +"crelt@npm:^1.0.5": + version: 1.0.6 + resolution: "crelt@npm:1.0.6" + checksum: dad842093371ad702afbc0531bfca2b0a8dd920b23a42f26e66dabbed9aad9acd5b9030496359545ef3937c3aced0fd4ac39f7a2d280a23ddf9eb7fdcb94a69f + languageName: node + linkType: hard + "cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2": version: 7.0.6 resolution: "cross-spawn@npm:7.0.6" @@ -4380,6 +4647,13 @@ __metadata: languageName: node linkType: hard +"regenerator-runtime@npm:^0.14.0": + version: 0.14.1 + resolution: "regenerator-runtime@npm:0.14.1" + checksum: 9f57c93277b5585d3c83b0cf76be47b473ae8c6d9142a46ce8b0291a04bb2cf902059f0f8445dcabb3fb7378e5fe4bb4ea1e008876343d42e46d3b484534ce38 + languageName: node + linkType: hard + "regex-recursion@npm:^5.1.1": version: 5.1.1 resolution: "regex-recursion@npm:5.1.1" @@ -4971,6 +5245,13 @@ __metadata: languageName: node linkType: hard +"style-mod@npm:^4.0.0, style-mod@npm:^4.1.0": + version: 4.1.2 + resolution: "style-mod@npm:4.1.2" + checksum: 7c5c3e82747f9bcf5f288d8d07f50848e4630fe5ff7bfe4d94cc87d6b6a2588227cbf21b4c792ac6406e5852293300a75e710714479a5c59a06af677f0825ef8 + languageName: node + linkType: hard + "style-to-object@npm:^1.0.0": version: 1.0.8 resolution: "style-to-object@npm:1.0.8" @@ -5331,6 +5612,13 @@ __metadata: languageName: node linkType: hard +"w3c-keyname@npm:^2.2.4": + version: 2.2.8 + resolution: "w3c-keyname@npm:2.2.8" + checksum: 95bafa4c04fa2f685a86ca1000069c1ec43ace1f8776c10f226a73296caeddd83f893db885c2c220ebeb6c52d424e3b54d7c0c1e963bbf204038ff1a944fbb07 + languageName: node + linkType: hard + "which-boxed-primitive@npm:^1.1.0, which-boxed-primitive@npm:^1.1.1": version: 1.1.1 resolution: "which-boxed-primitive@npm:1.1.1"