diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 44f6b6c9f..ccb74b4ae 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -17,7 +17,7 @@ on: - patch - prerelease - auto - default: prerelease + default: auto required: true run-name: release ${{ github.event.inputs.version }}${{ github.event.inputs.dry == 'true' && ' (--dry-run)' || '' }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 1089911e3..06ecafd1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # Changelog +## [1.0.3](https://github.com/DevoInc/genesys-ui/compare/v1.0.3-alpha.35...v1.0.3) (2023-10-27) + ## [1.0.3-alpha.35](https://github.com/DevoInc/genesys-ui/compare/v1.0.3-alpha.34...v1.0.3-alpha.35) (2023-10-26) diff --git a/README.md b/README.md index 02cbc1496..c1a6ea3cd 100644 --- a/README.md +++ b/README.md @@ -10,18 +10,18 @@ Monorepo containing the codebase for the Genesys UI components library. The project is built using `npm workspaces` and includes the following packages: -[![npm version](https://img.shields.io/npm/v/@devoinc/genesys-ui/alpha?label=%40devoinc%2Fgenesys-ui@alpha)](https://www.npmjs.com/package/@devoinc/genesys-ui) +[![npm version](https://img.shields.io/npm/v/@devoinc/genesys-ui/latest?label=%40devoinc%2Fgenesys-ui@latest)](https://www.npmjs.com/package/@devoinc/genesys-ui) -[![npm version](https://img.shields.io/npm/v/@devoinc/genesys-ui-form/alpha?label=%40devoinc%2Fgenesys-ui-form@alpha)](https://www.npmjs.com/package/@devoinc/genesys-ui-form) +[![npm version](https://img.shields.io/npm/v/@devoinc/genesys-ui-form/latest?label=%40devoinc%2Fgenesys-ui-form@latest)](https://www.npmjs.com/package/@devoinc/genesys-ui-form) -[![npm version](https://img.shields.io/npm/v/@devoinc/genesys-ui-datetime/alpha?label=%40devoinc%2Fgenesys-ui-datetime@alpha)](https://www.npmjs.com/package/@devoinc/genesys-ui-datetime) +[![npm version](https://img.shields.io/npm/v/@devoinc/genesys-ui-datetime/latest?label=%40devoinc%2Fgenesys-ui-datetime@latest)](https://www.npmjs.com/package/@devoinc/genesys-ui-datetime) -[![npm version](https://img.shields.io/npm/v/@devoinc/genesys-ui-code/alpha?label=%40devoinc%2Fgenesys-ui-code@alpha)](https://www.npmjs.com/package/@devoinc/genesys-ui-code) +[![npm version](https://img.shields.io/npm/v/@devoinc/genesys-ui-code/latest?label=%40devoinc%2Fgenesys-ui-code@latest)](https://www.npmjs.com/package/@devoinc/genesys-ui-code) - **genesys-ui:** Core package containing base components. - **genesys-ui-form:** Form components. - **genesys-ui-datetime:** Date and time components. -- **genesys-ui-datetime:** Code editing and code visualization components. +- **genesys-ui-code:** Code editing and code visualization components. The packages have the following interdependencies: diff --git a/package-lock.json b/package-lock.json index aaab3b54d..af201c2ca 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "genesys-ui", - "version": "1.0.3-alpha.32", + "version": "1.0.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "genesys-ui", - "version": "1.0.3-alpha.32", + "version": "1.0.3", "license": "MIT", "workspaces": [ "packages/core", @@ -25024,7 +25024,7 @@ }, "packages/code": { "name": "@devoinc/genesys-ui-code", - "version": "1.0.3-alpha.32", + "version": "1.0.3", "license": "MIT", "dependencies": { "ahooks": "^3.7.8" @@ -25034,7 +25034,7 @@ }, "peerDependencies": { "@devoinc/genesys-brand-devo": "^6.1.1", - "@devoinc/genesys-ui": "^1.0.3-alpha.32", + "@devoinc/genesys-ui": "^1.0.3", "monaco-editor-core": "^0.24.0", "react": ">=16.13.1", "react-dom": ">=16.13.1", @@ -25043,7 +25043,7 @@ }, "packages/core": { "name": "@devoinc/genesys-ui", - "version": "1.0.3-alpha.32", + "version": "1.0.3", "license": "MIT", "peerDependencies": { "@devoinc/genesys-icons": "^3.2.2", @@ -25066,11 +25066,11 @@ }, "packages/datetime": { "name": "@devoinc/genesys-ui-datetime", - "version": "1.0.3-alpha.32", + "version": "1.0.3", "license": "MIT", "peerDependencies": { "@devoinc/genesys-icons": "^3.2.2", - "@devoinc/genesys-ui": "^1.0.3-alpha.32", + "@devoinc/genesys-ui": "^1.0.3", "date-fns": "^2.30.0", "react": "16.x || 17.x || 18.x", "react-popper": "^2.3.0", @@ -25079,11 +25079,11 @@ }, "packages/form": { "name": "@devoinc/genesys-ui-form", - "version": "1.0.3-alpha.32", + "version": "1.0.3", "license": "MIT", "peerDependencies": { "@devoinc/genesys-icons": "^3.2.2", - "@devoinc/genesys-ui": "^1.0.3-alpha.32", + "@devoinc/genesys-ui": "^1.0.3", "filepond-plugin-file-validate-size": "^2.2.8", "filepond-plugin-file-validate-type": "^1.2.8", "filepond-plugin-image-preview": "^4.6.11", @@ -25097,14 +25097,14 @@ }, "packages/table": { "name": "@devoinc/genesys-ui-table", - "version": "1.0.3-alpha.32", + "version": "1.0.3", "license": "MIT", "dependencies": { "date-fns": "^2.30.0", "date-fns-tz": "^2.0.0" }, "peerDependencies": { - "@devoinc/genesys-ui": "^1.0.3-alpha.32", + "@devoinc/genesys-ui": "^1.0.3", "react": "16.x || 17.x || 18.x" } } diff --git a/package.json b/package.json index 4a758a634..aec6ddd7b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "genesys-ui", - "version": "1.0.3-alpha.35", + "version": "1.0.3", "description": "", "main": "index.js", "private": true, diff --git a/packages/code/package.json b/packages/code/package.json index b616dddf1..fea9d0efa 100644 --- a/packages/code/package.json +++ b/packages/code/package.json @@ -1,6 +1,6 @@ { "name": "@devoinc/genesys-ui-code", - "version": "1.0.3-alpha.35", + "version": "1.0.3", "description": "", "types": "./dist/types/src/index.d.ts", "main": "./dist/index.umd.js", @@ -31,7 +31,7 @@ }, "peerDependencies": { "@devoinc/genesys-brand-devo": "^6.1.1", - "@devoinc/genesys-ui": "^1.0.3-alpha.35", + "@devoinc/genesys-ui": "^1.0.3", "monaco-editor-core": "^0.24.0", "react": ">=16.13.1", "react-dom": ">=16.13.1", diff --git a/packages/code/src/components/DiffEditor/stories/DiffEditor.cases.stories.tsx b/packages/code/src/components/DiffEditor/stories/DiffEditor.cases.stories.tsx index d77f4fadd..55c6bda8a 100644 --- a/packages/code/src/components/DiffEditor/stories/DiffEditor.cases.stories.tsx +++ b/packages/code/src/components/DiffEditor/stories/DiffEditor.cases.stories.tsx @@ -8,18 +8,17 @@ import { MultipleEds, Programatic, Actions, - MultipleLangs, Shortcuts, CustomThemed, } from './cases'; -import { rawLanguage } from '../../Editor/__stories__/languages/rawConfig'; +import { jason } from '../../Editor/__stories__/languages/jason'; const meta: Meta<typeof DiffEditor> = { title: 'Components/Code/DiffEditor/cases', component: DiffEditor, args: { - originalValue: rawLanguage.value, - modifiedValue: rawLanguage.value.replaceAll('Grid', 'Flex'), + originalValue: jason.value, + modifiedValue: jason.value.replaceAll('Grid', 'Flex'), height: '300px', bordered: true, }, @@ -54,10 +53,3 @@ export const MultipleDiffEditors: DiffEditorStory = { <MultipleEds {...props} /> ), }; - -export const MultipleLanguages: DiffEditorStory = { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - render: ({ originalValue, modifiedValue, ...props }) => ( - <MultipleLangs {...props} /> - ), -}; diff --git a/packages/code/src/components/DiffEditor/stories/DiffEditor.mdx b/packages/code/src/components/DiffEditor/stories/DiffEditor.mdx index 597a53098..8068dcbc6 100644 --- a/packages/code/src/components/DiffEditor/stories/DiffEditor.mdx +++ b/packages/code/src/components/DiffEditor/stories/DiffEditor.mdx @@ -73,6 +73,86 @@ export const CustomThemed = () => { `} /> +## Registering a custom language + +The Editor supports custom languages. To use a custom language, the language and its configuration must be registered with the editor using the `registerLanguage` function. +**Please, refrain from directly using monaco editor's `monaco.languages.register` function, as it might side-effect other editors.** + +For more a more advanced use case, visit [Custom Language With Validation](#custom-language-with-validation). See also [Monaco Editor - Custom Languages](https://microsoft.github.io/monaco-editor/monarch.html) +and [Monaco Editor - Custom Autocompletion](https://microsoft.github.io/monaco-editor/playground.html#extending-language-services-custom-languages) +for more information regarding language definitions and autocompletion. + +<Source + code={` +import * as React from 'react'; +import * as monaco from 'monaco-editor-core'; + +import { DiffEditor, registerLanguage } from '@devoinc/genesys-ui-code'; + +const languageId = 'myLang'; + +const language = { + keywords: ['"keyword"'], + tokenizer: { + root: [ + [ + /"[A-Za-z0-9_]*"/, + { + cases: { + '@keywords': 'keyword', + '@default': 'default', + }, + }, + ], + [/:\s"((.|-|\n|\r)*)"/, 'value'], + ], + }, +}; + +const completionProvider = { + provideCompletionItems: (model, position) => { + const word = model.getWordUntilPosition(position); + const suggestions = [ + { + label: 'keyword', + kind: monaco.languages.CompletionItemKind.Field, + insertText: '"keyword"', + range: { + startLineNumber: position.lineNumber, + endLineNumber: position.lineNumber, + startColumn: word.startColumn, + endColumn: word.endColumn, + }, + }, + ]; + + return { suggestions: suggestions }; + }, +}; + +export const CustomLang = () => { + const registerLanguageProviders = (monaco) => { + registerLanguage(monaco, languageId) + // register highlighting + .registerStyleTokenizer(language) + // register autocompletion + .registerCompletionProvider(completionProvider); + }; + + return ( + <DiffEditor + height="300px" + language={languageId} + bordered={true} + originalValue={'{ "keyword": true, "not_keyword": 123 }'} + modifiedValue={'{\n "keyword": true,\n "not_keyword": 1234\n}'} + beforeMount={registerLanguageProviders} + /> + ); +}; +`} /> + + ## Hooks ### useDiffEditor diff --git a/packages/code/src/components/DiffEditor/stories/cases/CustomLang.tsx b/packages/code/src/components/DiffEditor/stories/cases/CustomLang.tsx index dbf54faf6..c0f89b838 100644 --- a/packages/code/src/components/DiffEditor/stories/cases/CustomLang.tsx +++ b/packages/code/src/components/DiffEditor/stories/cases/CustomLang.tsx @@ -2,12 +2,9 @@ import * as React from 'react'; import type * as monaco from 'monaco-editor-core'; import { DiffEditor, type DiffEditorProps } from '../../'; -import { rawLanguage } from '../../../Editor/__stories__/languages/rawConfig'; -import { dedalLanguage } from '../../../Editor/__stories__/languages/dedal'; -import { - registerCompletionProvider, - registerStyleTokenizer, -} from '../../../Editor'; +import { jason } from '../../../Editor/__stories__/languages/jason'; +import { esql } from '../../../Editor/__stories__/languages/esql'; +import { registerLanguage } from '../../../Editor'; type Monaco = typeof monaco; @@ -23,12 +20,12 @@ const opts: monaco.editor.IDiffEditorOptions = { }; const languages = { - rawConfig: rawLanguage, - dedal: dedalLanguage, + jason: jason, + esql: esql, }; export const CustomLang = ({ - langId = 'rawConfig', + langId = 'jason', options, ...props }: Partial<DiffEditorProps & { langId: string }>) => { @@ -36,18 +33,11 @@ export const CustomLang = ({ const monacoRef = React.useRef<Monaco>(); const registerLanguageProviders = (monaco) => { - // Register highlighting - registerStyleTokenizer( - monaco, - languages[langId].id, - languages[langId].lang, - ); - // Register autocompletion - registerCompletionProvider( - monaco, - languages[langId].id, - languages[langId].completionProvider, - ); + registerLanguage(monaco, languages[langId].id) + // register highlighting + .registerStyleTokenizer(languages[langId].lang) + // register autocompletion + .registerCompletionProvider(languages[langId].completionProvider); }; const handleEditorDidMount = ( diff --git a/packages/code/src/components/DiffEditor/stories/cases/MultipleEds.tsx b/packages/code/src/components/DiffEditor/stories/cases/MultipleEds.tsx index d9cb79074..b77d3a71c 100644 --- a/packages/code/src/components/DiffEditor/stories/cases/MultipleEds.tsx +++ b/packages/code/src/components/DiffEditor/stories/cases/MultipleEds.tsx @@ -9,7 +9,7 @@ export const MultipleEds = ({ ...props }: Partial<DiffEditorProps>) => { <Flex width="100%" flexDirection="column" gap="cmp-md"> <CustomLang {...props} /> <CustomLang options={{ minimap: { enabled: false } }} {...props} /> - <CustomLang langId="dedal" language="dedal" {...props} /> + <CustomLang langId="esql" language="esql" {...props} /> <CustomLang options={{ fontSize: 10 }} {...props} /> </Flex> ); diff --git a/packages/code/src/components/DiffEditor/stories/cases/MultipleLangs.tsx b/packages/code/src/components/DiffEditor/stories/cases/MultipleLangs.tsx deleted file mode 100644 index 0d38c98ff..000000000 --- a/packages/code/src/components/DiffEditor/stories/cases/MultipleLangs.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import * as React from 'react'; -import type * as monaco from 'monaco-editor-core'; - -import { Box, ContentSwitcher, Flex } from '@devoinc/genesys-ui'; -import { DiffEditor, type DiffEditorProps } from '../../'; -import { rawLanguage } from '../../../Editor/__stories__/languages/rawConfig'; -import { dedalLanguage } from '../../../Editor/__stories__/languages/dedal'; -import { - registerCompletionProvider, - registerStyleTokenizer, -} from '../../../Editor'; - -type Monaco = typeof monaco; - -export const MultipleLangs = ({ ...props }: Partial<DiffEditorProps>) => { - const [language, setLanguage] = React.useState<'dedal' | 'rawConfig'>( - 'dedal', - ); - - const registerLanguageProviders = (monaco: Monaco) => { - // DEDAL - // Register highlighting - registerStyleTokenizer(monaco, dedalLanguage.id, dedalLanguage.lang); - // RAW CONFIG - // Register highlighting - registerStyleTokenizer(monaco, rawLanguage.id, rawLanguage.lang); - // Register autocompletion - registerCompletionProvider( - monaco, - rawLanguage.id, - rawLanguage.completionProvider, - ); - }; - - return ( - <Flex width="100%" flexDirection="column" gap="cmp-md"> - <Box> - <ContentSwitcher.Container size="md"> - <ContentSwitcher.Item - id="dedal" - onChange={() => setLanguage('dedal')} - state={language === 'dedal' ? 'selected' : 'enabled'} - > - Dedal - </ContentSwitcher.Item> - <ContentSwitcher.Item - id="rawConfig" - onChange={() => setLanguage('rawConfig')} - state={language === 'rawConfig' ? 'selected' : 'enabled'} - > - RawConfig - </ContentSwitcher.Item> - </ContentSwitcher.Container> - </Box> - <DiffEditor - {...props} - language={language} - originalValue={dedalLanguage.value.concat(rawLanguage.value)} - modifiedValue={dedalLanguage.value - .concat(rawLanguage.value) - .replaceAll('Grid', 'Flex')} - beforeMount={registerLanguageProviders} - /> - </Flex> - ); -}; diff --git a/packages/code/src/components/DiffEditor/stories/cases/index.ts b/packages/code/src/components/DiffEditor/stories/cases/index.ts index 3ba6c5bd7..b064bddbc 100644 --- a/packages/code/src/components/DiffEditor/stories/cases/index.ts +++ b/packages/code/src/components/DiffEditor/stories/cases/index.ts @@ -1,7 +1,6 @@ export * from './Actions'; export * from './CustomLang'; export * from './MultipleEds'; -export * from './MultipleLangs'; export * from './Programatic'; export * from './Shortcuts'; export * from './CustomThemed'; diff --git a/packages/code/src/components/Editor/__stories__/languages/dedal.ts b/packages/code/src/components/Editor/__stories__/languages/esql.ts similarity index 74% rename from packages/code/src/components/Editor/__stories__/languages/dedal.ts rename to packages/code/src/components/Editor/__stories__/languages/esql.ts index 19a936626..9c391bb7b 100644 --- a/packages/code/src/components/Editor/__stories__/languages/dedal.ts +++ b/packages/code/src/components/Editor/__stories__/languages/esql.ts @@ -1,28 +1,15 @@ import { type Language } from '../declarations'; -export const dedalLanguage: Language = { - id: 'dedal', +export const esql: Language = { + id: 'esql', lang: { keywords: [ - // dedal - 'query', - 'sparkline', - // linq 'by', 'every', 'from', 'group', 'select', 'where', - // operations - 'asc', - 'ASC', - 'desc', - 'DESC', - 'order', - 'sort', - 'limit', - // keywords 'and', 'as', 'in', diff --git a/packages/code/src/components/Editor/__stories__/languages/rawConfig.ts b/packages/code/src/components/Editor/__stories__/languages/jason.ts similarity index 84% rename from packages/code/src/components/Editor/__stories__/languages/rawConfig.ts rename to packages/code/src/components/Editor/__stories__/languages/jason.ts index 05194d8ac..7fc5c9d6a 100644 --- a/packages/code/src/components/Editor/__stories__/languages/rawConfig.ts +++ b/packages/code/src/components/Editor/__stories__/languages/jason.ts @@ -27,37 +27,10 @@ export const keywords = [ '"from"', '"to"', '"realTime"', - //layout - '"i"', - '"w"', - '"h"', - '"x"', - '"y"', - '"moved"', - '"static"', - '"theme"', - //wy - '"fields"', - '"xAxis"', - '"yAxis"', - '"series"', - // donut pie - '"aggr"', - // heatmap - '"lat"', - '"lng"', - '"val"', - // simple value - '"field"', - // table - '"columnDefs"', - // voronoi - '"keys"', - '"weight"', ]; -export const rawLanguage: Language = { - id: 'rawConfig', +export const jason: Language = { + id: 'jason', lang: { keywords, tokenizer: { diff --git a/packages/code/src/components/Editor/api/index.ts b/packages/code/src/components/Editor/api/index.ts index 7a442c8f3..69374413e 100644 --- a/packages/code/src/components/Editor/api/index.ts +++ b/packages/code/src/components/Editor/api/index.ts @@ -1,2 +1,3 @@ -export * from './register-completion-provider'; -export * from './register-style-tokenizer'; +export * from './registerCompletionProvider'; +export * from './registerLanguage'; +export * from './registerStyleTokenizer'; diff --git a/packages/code/src/components/Editor/api/register-completion-provider.ts b/packages/code/src/components/Editor/api/registerCompletionProvider.ts similarity index 70% rename from packages/code/src/components/Editor/api/register-completion-provider.ts rename to packages/code/src/components/Editor/api/registerCompletionProvider.ts index 50209cfbc..8cac90f26 100644 --- a/packages/code/src/components/Editor/api/register-completion-provider.ts +++ b/packages/code/src/components/Editor/api/registerCompletionProvider.ts @@ -7,12 +7,6 @@ export const registerCompletionProvider = ( languageID: string, provider: monaco.languages.CompletionItemProvider, ): void => { - if (languageID == '') return; - - if (monaco.languages.getEncodedLanguageId(languageID) == 0) { - monaco.languages.register({ id: languageID }); - } - monaco.languages.onLanguage(languageID, () => { monaco.languages.registerCompletionItemProvider(languageID, provider); }); diff --git a/packages/code/src/components/Editor/api/registerLanguage.ts b/packages/code/src/components/Editor/api/registerLanguage.ts new file mode 100644 index 000000000..8b1036121 --- /dev/null +++ b/packages/code/src/components/Editor/api/registerLanguage.ts @@ -0,0 +1,41 @@ +import type * as monaco from 'monaco-editor-core'; + +import { registerStyleTokenizer } from './registerStyleTokenizer'; +import { registerCompletionProvider } from './registerCompletionProvider'; + +type Monaco = typeof monaco; + +type Register = { + registerStyleTokenizer: ( + tokenizer: + | monaco.languages.IMonarchLanguage + | monaco.Thenable<monaco.languages.IMonarchLanguage>, + ) => Register; + registerCompletionProvider: ( + provider: monaco.languages.CompletionItemProvider, + ) => Register; +}; + +export const registerLanguage = ( + monaco: Monaco, + languageID: string, +): Register => { + if (languageID == '') return; + + if (monaco.languages.getEncodedLanguageId(languageID) == 0) { + monaco.languages.register({ id: languageID }); + } + + const register: Register = { + registerStyleTokenizer: (tokenizer) => { + registerStyleTokenizer(monaco, languageID, tokenizer); + return register; + }, + registerCompletionProvider: (provider) => { + registerCompletionProvider(monaco, languageID, provider); + return register; + }, + }; + + return register; +}; diff --git a/packages/code/src/components/Editor/api/register-style-tokenizer.ts b/packages/code/src/components/Editor/api/registerStyleTokenizer.ts similarity index 73% rename from packages/code/src/components/Editor/api/register-style-tokenizer.ts rename to packages/code/src/components/Editor/api/registerStyleTokenizer.ts index bf5c8b237..d4f358683 100644 --- a/packages/code/src/components/Editor/api/register-style-tokenizer.ts +++ b/packages/code/src/components/Editor/api/registerStyleTokenizer.ts @@ -9,12 +9,6 @@ export const registerStyleTokenizer = ( | monaco.languages.IMonarchLanguage | monaco.Thenable<monaco.languages.IMonarchLanguage>, ): void => { - if (languageID == '') return; - - if (monaco.languages.getEncodedLanguageId(languageID) == 0) { - monaco.languages.register({ id: languageID }); - } - monaco.languages.onLanguage(languageID, () => { monaco.languages.setMonarchTokensProvider(languageID, tokenizer); }); diff --git a/packages/code/src/components/Editor/stories/Editor.cases.stories.tsx b/packages/code/src/components/Editor/stories/Editor.cases.stories.tsx index 1222d0769..101615b73 100644 --- a/packages/code/src/components/Editor/stories/Editor.cases.stories.tsx +++ b/packages/code/src/components/Editor/stories/Editor.cases.stories.tsx @@ -2,14 +2,13 @@ import * as React from 'react'; import { type Meta, type StoryObj } from '@storybook/react'; import { Editor } from '..'; -import { rawLanguage } from '../__stories__/languages/rawConfig'; +import { jason } from '../__stories__/languages/jason'; import { CustomLang, MultipleEds, Programatic, Actions, - MultipleLangs, Shortcuts, CustomThemed, } from './cases'; @@ -18,7 +17,7 @@ const meta: Meta<typeof Editor> = { title: 'Components/Code/Editor/cases', component: Editor, args: { - value: rawLanguage.value, + value: jason.value, height: '300px', bordered: true, }, @@ -27,8 +26,8 @@ const meta: Meta<typeof Editor> = { export default meta; type EditorStory = StoryObj<typeof Editor>; -export const MultipleCustomLanguages: EditorStory = { - render: MultipleLangs, +export const CustomLanguageWithValidation: EditorStory = { + render: CustomLang, }; export const WithActions: EditorStory = { @@ -51,7 +50,3 @@ export const MultipleEditors: EditorStory = { // eslint-disable-next-line @typescript-eslint/no-unused-vars render: ({ value, ...props }) => <MultipleEds {...props} />, }; - -export const CustomLanguageWithValidation: EditorStory = { - render: CustomLang, -}; diff --git a/packages/code/src/components/Editor/stories/Editor.mdx b/packages/code/src/components/Editor/stories/Editor.mdx index a3c162d0a..96d980e8f 100644 --- a/packages/code/src/components/Editor/stories/Editor.mdx +++ b/packages/code/src/components/Editor/stories/Editor.mdx @@ -52,22 +52,99 @@ export const CustomThemed = () => { const theme = useTheme(); const editorTheme = useEditorTheme(theme); +return ( + +<Editor.Container bordered={true}> + <Editor.Editor + height="300px" + bordered={true} + theme={editorTheme} + value="I'm being built from my inner parts" + /> + <Editor.ActionsContainer> + <IconButton icon="gi-heart_full" /> + </Editor.ActionsContainer> +</Editor.Container> +); }; `} /> + +## Registering a custom language + +The Editor supports custom languages. To use a custom language, the language and its configuration must be registered with the editor using the `registerLanguage` function. +**Please, refrain from directly using monaco editor's `monaco.languages.register` function, as it might side-effect other editors.** + +For more a more advanced use case, visit [Custom Language With Validation](#custom-language-with-validation). See also [Monaco Editor - Custom Languages](https://microsoft.github.io/monaco-editor/monarch.html) +and [Monaco Editor - Custom Autocompletion](https://microsoft.github.io/monaco-editor/playground.html#extending-language-services-custom-languages) +for more information regarding language definitions and autocompletion. + +<Source + code={` +import * as React from 'react'; +import * as monaco from 'monaco-editor-core'; + +import { Editor, registerLanguage } from '@devoinc/genesys-ui-code'; + +const languageId = 'myLang'; + +const language = { + keywords: ['"keyword"'], + tokenizer: { + root: [ + [ + /"[A-Za-z0-9_]*"/, + { + cases: { + '@keywords': 'keyword', + '@default': 'default', + }, + }, + ], + [/:\s"((.|-|\n|\r)*)"/, 'value'], + ], + }, +}; + +const completionProvider = { + provideCompletionItems: (model, position) => { + const word = model.getWordUntilPosition(position); + const suggestions = [ + { + label: 'keyword', + kind: monaco.languages.CompletionItemKind.Field, + insertText: '"keyword"', + range: { + startLineNumber: position.lineNumber, + endLineNumber: position.lineNumber, + startColumn: word.startColumn, + endColumn: word.endColumn, + }, + }, + ]; + + return { suggestions: suggestions }; + }, +}; + +export const CustomLang = () => { + const registerLanguageProviders = (monaco) => { + registerLanguage(monaco, languageId) + // register highlighting + .registerStyleTokenizer(language) + // register autocompletion + .registerCompletionProvider(completionProvider); + }; + return ( - <Editor.Container bordered={true}> - <Editor.Editor - height="300px" - bordered={true} - theme={editorTheme} - value="I'm being built from my inner parts" - /> - <Editor.ActionsContainer> - <IconButton icon="gi-heart_full" /> - </Editor.ActionsContainer> - </Editor.Container> + <Editor + height="300px" + language={languageId} + bordered={true} + value={'{ "keyword": true, "not_keyword": 123 }'} + beforeMount={registerLanguageProviders} + /> ); }; -`} -/> + +`} /> ## Hooks @@ -89,28 +166,27 @@ export const CustomThemed = () => { const theme = useTheme(); const editorTheme = useEditorTheme(theme); - const { containerRef } = useEditor({ - originalValue: 'Hey there!', - modifiedValue: 'Hey hey!', - theme: editorTheme, - language: '', - beforeMount: () => console.log('beforeMount'), - onMount: () => console.log('onMount'), - onChange: () => console.log('onChange'), - onValidate: () => console.log('onValidate'), - options: {}, - }); - - return ( - <Editor.Container> - <Box ref={containerRef} height="100%" /> - <Editor.ActionsContainer> - <IconButton icon="gi-heart_full" /> - </Editor.ActionsContainer> - </Editor.Container> - ); -}; -`} /> +const { containerRef } = useEditor({ +originalValue: 'Hey there!', +modifiedValue: 'Hey hey!', +theme: editorTheme, +language: '', +beforeMount: () => console.log('beforeMount'), +onMount: () => console.log('onMount'), +onChange: () => console.log('onChange'), +onValidate: () => console.log('onValidate'), +options: {}, +}); + +return ( + +<Editor.Container> + <Box ref={containerRef} height="100%" /> + <Editor.ActionsContainer> + <IconButton icon="gi-heart_full" /> + </Editor.ActionsContainer> +</Editor.Container> +); }; `} /> ### useEditorTheme @@ -122,7 +198,7 @@ import * as React from 'react'; import { useTheme } from 'styled-components'; import { IconButton } from '@devoinc/genesys-ui'; -import { Editor, useEditorTheme} from '@devoinc/genesys-ui-code'; +import { Editor, useEditorTheme } from '@devoinc/genesys-ui-code'; export const CustomThemed = () => { const theme = useTheme(); @@ -138,21 +214,20 @@ export const CustomThemed = () => { }, }; - return ( - <Editor.Container bordered={true}> - <Editor.Editor - height="300px" - bordered={true} - theme={customEditorTheme} - value="I'm being built from my inner parts" - /> - <Editor.ActionsContainer> - <IconButton icon="gi-heart_full" /> - </Editor.ActionsContainer> - </Editor.Container> - ); -}; -`} /> +return ( + +<Editor.Container bordered={true}> + <Editor.Editor + height="300px" + bordered={true} + theme={customEditorTheme} + value="I'm being built from my inner parts" + /> + <Editor.ActionsContainer> + <IconButton icon="gi-heart_full" /> + </Editor.ActionsContainer> +</Editor.Container> +); }; `} /> ## Custom Configurations diff --git a/packages/code/src/components/Editor/stories/cases/CustomLang.tsx b/packages/code/src/components/Editor/stories/cases/CustomLang.tsx index 79f047129..730df2598 100644 --- a/packages/code/src/components/Editor/stories/cases/CustomLang.tsx +++ b/packages/code/src/components/Editor/stories/cases/CustomLang.tsx @@ -1,14 +1,9 @@ import * as React from 'react'; import type * as monaco from 'monaco-editor-core'; -import { - Editor, - EditorProps, - registerStyleTokenizer, - registerCompletionProvider, -} from '../../'; -import { rawLanguage } from '../../__stories__/languages/rawConfig'; -import { dedalLanguage } from '../../__stories__/languages/dedal'; +import { Editor, EditorProps, registerLanguage } from '../../'; +import { jason } from '../../__stories__/languages/jason'; +import { esql } from '../../__stories__/languages/esql'; type Monaco = typeof monaco; @@ -24,12 +19,12 @@ const opts: monaco.editor.IEditorOptions = { }; const languages = { - rawConfig: rawLanguage, - dedal: dedalLanguage, + jason: jason, + esql: esql, }; export const CustomLang = ({ - langId = 'rawConfig', + langId = 'jason', options, ...props }: Partial<EditorProps & { langId: string }>) => { @@ -37,18 +32,11 @@ export const CustomLang = ({ const monacoRef = React.useRef<Monaco>(); const registerLanguageProviders = (monaco) => { - // Register highlighting - registerStyleTokenizer( - monaco, - languages[langId].id, - languages[langId].lang, - ); - // Register autocompletion - registerCompletionProvider( - monaco, - languages[langId].id, - languages[langId].completionProvider, - ); + registerLanguage(monaco, languages[langId].id) + // register highlighting + .registerStyleTokenizer(languages[langId].lang) + // register autocompletion + .registerCompletionProvider(languages[langId].completionProvider); }; const handleEditorDidMount = ( diff --git a/packages/code/src/components/Editor/stories/cases/MultipleEds.tsx b/packages/code/src/components/Editor/stories/cases/MultipleEds.tsx index 7a38afdfb..a339416a4 100644 --- a/packages/code/src/components/Editor/stories/cases/MultipleEds.tsx +++ b/packages/code/src/components/Editor/stories/cases/MultipleEds.tsx @@ -9,7 +9,7 @@ export const MultipleEds = ({ ...props }: Partial<EditorProps>) => { <Flex width="100%" flexDirection="column" gap="cmp-md"> <CustomLang {...props} /> <CustomLang options={{ minimap: { enabled: false } }} {...props} /> - <CustomLang langId="dedal" language="dedal" {...props} /> + <CustomLang langId="esql" language="esql" {...props} /> <CustomLang options={{ fontSize: 10 }} {...props} /> </Flex> ); diff --git a/packages/code/src/components/Editor/stories/cases/MultipleLangs.tsx b/packages/code/src/components/Editor/stories/cases/MultipleLangs.tsx deleted file mode 100644 index 6c950f73a..000000000 --- a/packages/code/src/components/Editor/stories/cases/MultipleLangs.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import * as React from 'react'; -import type * as monaco from 'monaco-editor-core'; - -import { Box, ContentSwitcher, Flex } from '@devoinc/genesys-ui'; -import { - Editor, - EditorProps, - registerCompletionProvider, - registerStyleTokenizer, -} from '../../'; -import { rawLanguage } from '../../__stories__/languages/rawConfig'; -import { dedalLanguage } from '../../__stories__/languages/dedal'; - -type Monaco = typeof monaco; - -export const MultipleLangs = ({ ...props }: Partial<EditorProps>) => { - const [language, setLanguage] = React.useState<'dedal' | 'rawConfig'>( - 'dedal', - ); - - const registerLanguageProviders = (monaco: Monaco) => { - // DEDAL - // Register highlighting - registerStyleTokenizer(monaco, dedalLanguage.id, dedalLanguage.lang); - // RAW CONFIG - // Register highlighting - registerStyleTokenizer(monaco, rawLanguage.id, rawLanguage.lang); - // Register autocompletion - registerCompletionProvider( - monaco, - rawLanguage.id, - rawLanguage.completionProvider, - ); - }; - - return ( - <Flex width="100%" flexDirection="column" gap="cmp-md"> - <Box> - <ContentSwitcher.Container size="md"> - <ContentSwitcher.Item - id="dedal" - onChange={() => setLanguage('dedal')} - state={language === 'dedal' ? 'selected' : 'enabled'} - > - Dedal - </ContentSwitcher.Item> - <ContentSwitcher.Item - id="rawConfig" - onChange={() => setLanguage('rawConfig')} - state={language === 'rawConfig' ? 'selected' : 'enabled'} - > - RawConfig - </ContentSwitcher.Item> - </ContentSwitcher.Container> - </Box> - <Editor - {...props} - language={language} - value={dedalLanguage.value.concat(rawLanguage.value)} - beforeMount={registerLanguageProviders} - /> - </Flex> - ); -}; diff --git a/packages/code/src/components/Editor/stories/cases/index.ts b/packages/code/src/components/Editor/stories/cases/index.ts index 0bec34341..566297ae3 100644 --- a/packages/code/src/components/Editor/stories/cases/index.ts +++ b/packages/code/src/components/Editor/stories/cases/index.ts @@ -1,7 +1,6 @@ export * from './Actions'; export * from './CustomLang'; export * from './MultipleEds'; -export * from './MultipleLangs'; export * from './Programatic'; export * from './Shortcuts'; export * from './Diff'; diff --git a/packages/core/package.json b/packages/core/package.json index fa7c5e4dd..e3e800376 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@devoinc/genesys-ui", - "version": "1.0.3-alpha.35", + "version": "1.0.3", "description": "", "types": "./dist/types/src/index.d.ts", "main": "./dist/index.umd.js", diff --git a/packages/datetime/package.json b/packages/datetime/package.json index 157b9abc5..a83b4f066 100644 --- a/packages/datetime/package.json +++ b/packages/datetime/package.json @@ -1,6 +1,6 @@ { "name": "@devoinc/genesys-ui-datetime", - "version": "1.0.3-alpha.35", + "version": "1.0.3", "description": "", "scripts": { "compile": "tsc --project tsconfig.build.json", @@ -27,7 +27,7 @@ "license": "MIT", "peerDependencies": { "@devoinc/genesys-icons": "^3.2.2", - "@devoinc/genesys-ui": "^1.0.3-alpha.35", + "@devoinc/genesys-ui": "^1.0.3", "date-fns": "^2.30.0", "react": "16.x || 17.x || 18.x", "react-popper": "^2.3.0", diff --git a/packages/form/package.json b/packages/form/package.json index 4e2198424..32076a268 100644 --- a/packages/form/package.json +++ b/packages/form/package.json @@ -1,6 +1,6 @@ { "name": "@devoinc/genesys-ui-form", - "version": "1.0.3-alpha.35", + "version": "1.0.3", "description": "", "scripts": { "compile": "tsc --project tsconfig.build.json", @@ -27,7 +27,7 @@ "license": "MIT", "peerDependencies": { "@devoinc/genesys-icons": "^3.2.2", - "@devoinc/genesys-ui": "^1.0.3-alpha.35", + "@devoinc/genesys-ui": "^1.0.3", "filepond-plugin-file-validate-size": "^2.2.8", "filepond-plugin-file-validate-type": "^1.2.8", "filepond-plugin-image-preview": "^4.6.11", diff --git a/packages/table/README.md b/packages/table/README.md index f1bb19f2e..f658443d9 100644 --- a/packages/table/README.md +++ b/packages/table/README.md @@ -1,4 +1,53 @@ -# Genesys UI Form +# Genesys UI Table > **Warning** -> This is an `alpha` version and it is not yet production ready. +> This package is still under development and is not yet production ready. + +This package contains the `Table` component. It belongs to the [Genesys UI](https://github.com/DevoInc/genesys-ui) component library and is built on top of the [core](https://github.com/DevoInc/genesys-ui/tree/master/packages/core) package. + +This package contains the following components: + +``` +Table +``` + +## Preview + +The available components can be previewed in the [Genesys UI Storybook](https://devoinc.github.io/genesys-ui/). +The Storybook includes a live preview of the components, as well as their documentation and code examples. + +To visit the components comprised in this package, please refer to the **Components > Table** section of the Storybook. + +## Installation + +To install the package, run the following command: + +```sh +npm install @devoinc/genesys-ui-table +``` + +This package needs [genesys-ui](https://www.npmjs.com/package/@devoinc/genesys-ui) to work. If you don't have it already, you can install it with the following command: + +```sh +npm install @devoinc/genesys-ui +``` + +**Note:** Make sure you have followed the [Installation](https://devoinc.github.io/genesys-ui/?path=/docs/getting-started-installation--docs) steps in the Storybook of the repository before installing the package. This will ensure that you have all the necessary dependencies and stylesheets in place. + +## Usage + +Importing the `genesys-ui-table` package into your project will give you access to all of the components and utilities that are available in the library. + +Using a component is as simple as adding the import, and using it in your code. + +```jsx +// MyView.tsx + +import { Table } from '@devoinc/genesys-ui-table'; + +export const MyEditor = () => <Table />; +``` + +## Development + +Please refer to the main [README](https://github.com/DevoInc/genesys-ui#readme) for information on how to contribute to the library. diff --git a/packages/table/package.json b/packages/table/package.json index 2412f1f02..48e0d2dbf 100644 --- a/packages/table/package.json +++ b/packages/table/package.json @@ -1,6 +1,6 @@ { "name": "@devoinc/genesys-ui-table", - "version": "1.0.3-alpha.35", + "version": "1.0.3", "description": "", "scripts": { "compile": "tsc --project tsconfig.build.json", @@ -26,7 +26,7 @@ "author": "", "license": "MIT", "peerDependencies": { - "@devoinc/genesys-ui": "^1.0.3-alpha.35", + "@devoinc/genesys-ui": "^1.0.3", "react": "16.x || 17.x || 18.x" }, "engine": { diff --git a/stories/getting-started/0.Overview.mdx b/stories/getting-started/0.Overview.mdx index 5bd24cbae..f0dbc7e96 100644 --- a/stories/getting-started/0.Overview.mdx +++ b/stories/getting-started/0.Overview.mdx @@ -4,10 +4,16 @@ import { Meta } from '@storybook/addon-docs'; # Genesys UI +**Warning** +`This is an alpha version and it is not yet production ready.` + + Genesys UI is a library of React UI components that implements **Genesys** Design Guidelines. It is written in Typescript and uses [Styled Components](https://styled-components.com/) for styling. <img src="./images/components-preview.png" alt="components preview" /> +**See a live demo of a full application built with Genesys UI [here](https://devoinc.github.io/genesys-ui-demo-app/), with the codebase available [here](https://github.com/DevoInc/genesys-ui-demo-app)**. + ## Introduction Genesys UI is a library of React UI components that implements Genesys Design Guidelines. @@ -55,7 +61,7 @@ Among others, this package contains the following components: Calendar, DateTimeRangePicker, DateTime, Presets, DateTimePicker, RangeInput, DateTimeRange, ... ``` -### Code +### Code This package contains components for code editing and visualization. @@ -67,4 +73,4 @@ Editor ### Table (WIP) -This package contains final components that can be used to build tables. \ No newline at end of file +This package contains final components that can be used to build tables.