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

HDS::CodeEditor with Code Mirror 6 #2573

Open
wants to merge 88 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
56f6840
Install `codemirror` 5
alex-ju Sep 17, 2024
807d606
Generate `CodeEditor` showcase
alex-ju Sep 17, 2024
ed585da
Generate `hds-code-editor` modifier
alex-ju Sep 19, 2024
c55fb2b
Generate `CodeEditor` component
alex-ju Sep 19, 2024
4f887df
Switch to `codemirror` 6 via subpackages
alex-ju Sep 19, 2024
ff44fef
Theme
alex-ju Oct 1, 2024
fbd3137
Clean-up and lint
alex-ju Oct 22, 2024
0cf278b
working on initial structure
zamoore Nov 11, 2024
6abf543
added javascript support
zamoore Nov 11, 2024
268ba8d
added some initial language support
zamoore Nov 11, 2024
bb2014b
can add new lines in the code editor
zamoore Nov 13, 2024
f2bdfa4
added support for history
zamoore Nov 14, 2024
aed7093
rough version of fullscreen mode works
zamoore Nov 14, 2024
e340fae
styling code editor
zamoore Nov 15, 2024
3bae9a9
styling wip
zamoore Nov 15, 2024
5e126d4
copy button works
zamoore Nov 15, 2024
91f7835
updated highlighting
zamoore Nov 15, 2024
074b584
added tab support
zamoore Nov 15, 2024
b77d086
calls the update function
zamoore Nov 15, 2024
222048e
working on showcase docs
zamoore Nov 18, 2024
5ad7e2d
writing tests and cleaning up code
zamoore Nov 18, 2024
7a41b58
added examples to the showcase
zamoore Nov 19, 2024
6250050
added examples to the showcase
zamoore Nov 19, 2024
486a960
cleanup
zamoore Nov 20, 2024
5a64fe7
changed title and description to yielded subcomponents
zamoore Dec 4, 2024
0c618c9
website docs WIP
zamoore Dec 5, 2024
c656018
adjusted styling and header composition to fit the new designs
zamoore Dec 5, 2024
d2419b6
fixed styling for differnet header combos
zamoore Dec 6, 2024
f6ad055
adding keyboard nav support
zamoore Dec 6, 2024
f82b8cb
fixing styling
zamoore Dec 6, 2024
4b2706b
improving keybopard navigation
zamoore Dec 6, 2024
40db1e9
updated the highlight style
zamoore Dec 6, 2024
30026a5
added support for bracket matching
zamoore Dec 6, 2024
8506b0d
working on dynamic package importing
zamoore Dec 10, 2024
aaa9285
wip
zamoore Dec 10, 2024
2fae3af
removed some visibility observers
zamoore Dec 10, 2024
6d2f7b2
will only load once visible
zamoore Dec 10, 2024
0f5f8f7
added customizable option for title tag
zamoore Dec 10, 2024
c97145e
code cleanup
zamoore Dec 10, 2024
22e5cb9
reduced header complexity
zamoore Dec 10, 2024
f670982
fixed header styling
zamoore Dec 10, 2024
126899a
updating active line styles
zamoore Dec 11, 2024
5e80db0
fixing color setup
zamoore Dec 11, 2024
84648c7
moved to local color definitions
zamoore Dec 11, 2024
808ae19
using local colors
zamoore Dec 11, 2024
91d45bc
cleaning up theming
zamoore Dec 11, 2024
0bcd4bd
added support for hcl
zamoore Dec 11, 2024
c359a59
added more examples in the showcase
zamoore Dec 11, 2024
e51524b
got content selection styled
zamoore Dec 12, 2024
e19f4a0
got content selection styled
zamoore Dec 12, 2024
4cfb086
fixing color variables
zamoore Dec 12, 2024
ab89b0c
loading state added
zamoore Dec 16, 2024
dfd6782
fixing linting issues
zamoore Dec 16, 2024
2decd92
fixing linting issues
zamoore Dec 16, 2024
7deea63
added a root margin to the loader intersection observer
zamoore Dec 16, 2024
b486d31
fixing linting issues
zamoore Dec 16, 2024
711b2cf
removed website updates
zamoore Dec 16, 2024
55061d2
cleaning up code for PR
zamoore Dec 16, 2024
30d5d14
fixing tests
zamoore Dec 17, 2024
6b4183f
simplified html structure
zamoore Dec 17, 2024
66dcbc9
figured out padding for custom content
zamoore Dec 17, 2024
83e8a1d
passing tests
zamoore Dec 17, 2024
429bf12
cleaning up tests
zamoore Dec 17, 2024
66dc562
fixed typescript error ignores
zamoore Dec 17, 2024
67e094d
adding support for async tasks
zamoore Dec 17, 2024
b571210
added a changeset
zamoore Dec 17, 2024
ec5be92
fixed typo in test selector
zamoore Dec 17, 2024
00b4eff
a11y changes
zamoore Dec 19, 2024
e711e48
responding to pr feedback
zamoore Dec 19, 2024
dc123c3
added test for expand/collapse
zamoore Dec 19, 2024
15d5120
cleaning up the state in the fullscreen toggle button
zamoore Dec 20, 2024
a6ef709
fixed full screen button
zamoore Dec 20, 2024
68430a0
responding to PR feedback
zamoore Dec 20, 2024
ab6df31
changed to relative path import to fix the import issue
zamoore Dec 23, 2024
773b98a
changed to relative path import to fix the import issue
zamoore Dec 23, 2024
ab9b61a
added modifier usage
zamoore Dec 23, 2024
c855323
removing button component and applying styles to child button elements
zamoore Dec 23, 2024
b5d74f3
updated the copy button so that it works with an internal val
zamoore Dec 23, 2024
80fa243
added a test for the copy button
zamoore Dec 23, 2024
4ffd686
fixed height issue in full screen mode with too much content
zamoore Dec 23, 2024
caf29a1
added some additional tests around copying content
zamoore Dec 24, 2024
904ef46
fixing focus ring on action buttons
zamoore Dec 24, 2024
2896073
handled escape key with a modifier that adds an ecent listener to the…
zamoore Dec 24, 2024
54e858c
fixing full screen button
zamoore Dec 24, 2024
6eb2b51
waiting for the component to load before taking percy screenshot
zamoore Dec 24, 2024
744001e
updating theme to hit docs
zamoore Dec 24, 2024
f1a0280
added a warning
zamoore Dec 24, 2024
ae9ec8f
added exports to components file
zamoore Dec 24, 2024
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
6 changes: 6 additions & 0 deletions .changeset/long-poets-wonder.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@hashicorp/design-system-components": minor
---

`Hds::CodeEditor` - Added new CodeMirror 6 supported code editor component
`hds-code-editor` modifier - Added new code editor modifier which converts the element it is applied to into a CodeMirror6 code editor
3 changes: 2 additions & 1 deletion packages/components/babel.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
],
["@babel/plugin-proposal-decorators", { "legacy": true }],
"@babel/plugin-transform-class-properties",
"@babel/plugin-transform-private-methods"
"@babel/plugin-transform-private-methods",
"ember-concurrency/async-arrow-task-transform"
]
}
16 changes: 16 additions & 0 deletions packages/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@
"lint:js:fix": "eslint . --fix"
},
"dependencies": {
"@codemirror/commands": "^6.7.1",
"@codemirror/lang-go": "^6.0.1",
"@codemirror/lang-json": "^6.0.1",
"@codemirror/lang-sql": "^6.8.0",
"@codemirror/language": "^6.10.3",
"@codemirror/state": "^6.4.1",
"@codemirror/view": "^6.33.0",
"@ember/render-modifiers": "^2.0.5",
"@ember/string": "^3.1.1",
"@ember/test-waiters": "^3.1.0",
Expand All @@ -43,6 +50,7 @@
"@hashicorp/design-system-tokens": "^2.2.2",
"@hashicorp/flight-icons": "^3.8.0",
"clipboard-polyfill": "^4.1.0",
"codemirror-lang-hcl": "^0.0.0-beta.2",
"decorator-transforms": "^1.1.0",
"ember-a11y-refocus": "^4.1.3",
"ember-cli-sass": "^11.0.1",
Expand Down Expand Up @@ -156,6 +164,10 @@
"./components/hds/code-block/description.js": "./dist/_app_/components/hds/code-block/description.js",
"./components/hds/code-block/index.js": "./dist/_app_/components/hds/code-block/index.js",
"./components/hds/code-block/title.js": "./dist/_app_/components/hds/code-block/title.js",
"./components/hds/code-editor/description.js": "./dist/_app_/components/hds/code-editor/description.js",
"./components/hds/code-editor/full-screen-button.js": "./dist/_app_/components/hds/code-editor/full-screen-button.js",
"./components/hds/code-editor/index.js": "./dist/_app_/components/hds/code-editor/index.js",
"./components/hds/code-editor/title.js": "./dist/_app_/components/hds/code-editor/title.js",
"./components/hds/copy/button/index.js": "./dist/_app_/components/hds/copy/button/index.js",
"./components/hds/copy/snippet/index.js": "./dist/_app_/components/hds/copy/snippet/index.js",
"./components/hds/dialog-primitive/body.js": "./dist/_app_/components/hds/dialog-primitive/body.js",
Expand Down Expand Up @@ -301,6 +313,10 @@
"./instance-initializers/load-sprite.js": "./dist/_app_/instance-initializers/load-sprite.js",
"./modifiers/hds-anchored-position.js": "./dist/_app_/modifiers/hds-anchored-position.js",
"./modifiers/hds-clipboard.js": "./dist/_app_/modifiers/hds-clipboard.js",
"./modifiers/hds-code-editor.js": "./dist/_app_/modifiers/hds-code-editor.js",
"./modifiers/hds-code-editor/highlight-styles/hds-dark-highlight-style.js": "./dist/_app_/modifiers/hds-code-editor/highlight-styles/hds-dark-highlight-style.js",
"./modifiers/hds-code-editor/palettes/hds-dark-palette.js": "./dist/_app_/modifiers/hds-code-editor/palettes/hds-dark-palette.js",
"./modifiers/hds-code-editor/themes/hds-dark-theme.js": "./dist/_app_/modifiers/hds-code-editor/themes/hds-dark-theme.js",
"./modifiers/hds-register-event.js": "./dist/_app_/modifiers/hds-register-event.js",
"./modifiers/hds-tooltip.js": "./dist/_app_/modifiers/hds-tooltip.js",
"./services/hds-time.js": "./dist/_app_/services/hds-time.js"
Expand Down
6 changes: 6 additions & 0 deletions packages/components/src/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ export { default as HdsCodeBlockDescription } from './components/hds/code-block/
export { default as HdsCodeBlockTitle } from './components/hds/code-block/title.ts';
export * from './components/hds/code-block/types.ts';

// CodeEditor
export { default as HdsCodeEditor } from './components/hds/code-editor/index.ts';
export { default as HdsCodeEditorDescription } from './components/hds/code-editor/description.ts';
export { default as HdsCodeEditorTitle } from './components/hds/code-editor/title.ts';
export { default as HdsCodeEditorFullScreenButton } from './components/hds/code-editor/full-screen-button.ts';

// CopyButton
export { default as HdsCopyButton } from './components/hds/copy/button/index.ts';
export * from './components/hds/copy/button/types.ts';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<Hds::Text::Body class="hds-code-editor__description" @tag="p" @size="100" ...attributes>
{{yield}}
</Hds::Text::Body>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/

import TemplateOnlyComponent from '@ember/component/template-only';

import type { HdsTextBodySignature } from '../text/body';

export interface HdsCodeEditorDescriptionSignature {
Blocks: {
default: [];
};
Element: HdsTextBodySignature['Element'];
}

const HdsCodeEditorDescription =
TemplateOnlyComponent<HdsCodeEditorDescriptionSignature>();

export default HdsCodeEditorDescription;
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Hds::Button
class={{this.className}}
aria-pressed={{@isFullScreen}}
@isIconOnly={{true}}
@color="secondary"
@size="small"
@icon={{this.icon}}
@text="Toggle full screen view"
{{on "click" @onToggleFullScreen}}
/>
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/

import Component from '@glimmer/component';

import type { HdsButtonSignature } from '../button';

export interface HdsCodeEditorFullScreenButtonSignature {
Args: {
isFullScreen: boolean;
onToggleFullScreen: () => void;
};
Element: HdsButtonSignature['Element'];
}

export default class HdsCodeEditorFullScreenButton extends Component<HdsCodeEditorFullScreenButtonSignature> {
get state(): 'minimize' | 'maximize' {
return this.args.isFullScreen ? 'minimize' : 'maximize';
}

get className() {
const classes = [
'hds-code-editor__full-screen-button',
'hds-code-editor__button',
];

const stateClass = {
minimize: 'hds-code-editor__full-screen-button--minimize',
maximize: 'hds-code-editor__full-screen-button--maximize',
}[this.state];

classes.push(stateClass);

return classes.join(' ');
}

get icon(): HdsButtonSignature['Args']['icon'] {
const stateIcons = {
minimize: 'minimize',
maximize: 'maximize',
} as const;

return stateIcons[this.state];
}
}
49 changes: 49 additions & 0 deletions packages/components/src/components/hds/code-editor/index.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{{!
Copyright (c) HashiCorp, Inc.
SPDX-License-Identifier: MPL-2.0
}}

<div
class={{this.classNames}}
{{! @glint-expect-error - https://github.com/josemarluedke/ember-focus-trap/issues/86 }}
{{focus-trap isActive=this._isFullScreen}}
{{this._handleEscape}}
...attributes
>
{{#if (and this._isSetupComplete (or this.hasActions (has-block)))}}
<div class="hds-code-editor__header">
<div class="hds-code-editor__header-content">
{{yield (hash Title=(component "hds/code-editor/title") Description=(component "hds/code-editor/description"))}}
</div>

{{#if this.hasActions}}
<div class="hds-code-editor__header-actions">
{{#if @hasCopyButton}}
<Hds::Copy::Button
class="hds-code-editor__button hds-code-editor__copy-button"
zamoore marked this conversation as resolved.
Show resolved Hide resolved
@isIconOnly={{true}}
@size="small"
@text="Copy"
@textToCopy={{this._value}}
/>
{{/if}}
{{#if @hasFullScreenButton}}
<Hds::CodeEditor::FullScreenButton
@isFullScreen={{this._isFullScreen}}
@onToggleFullScreen={{this.toggleFullScreen}}
/>
{{/if}}
</div>
{{/if}}
</div>
{{/if}}
<div
class="hds-code-editor__editor"
{{hds-code-editor value=@value language=@language onInput=this.onInput onSetup=this.onSetup}}
/>
{{#unless this._isSetupComplete}}
<div class="hds-code-editor__loader" aria-live="polite" role="status">
<Hds::Icon @name="loading" @size="24" />
</div>
{{/unless}}
</div>
107 changes: 107 additions & 0 deletions packages/components/src/components/hds/code-editor/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/

import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { modifier } from 'ember-modifier';

import type { ComponentLike } from '@glint/template';
import type { HdsCodeEditorSignature as HdsCodeEditorModifierSignature } from 'src/modifiers/hds-code-editor';
import type { HdsButtonSignature } from 'src/components/hds/button';
import type { HdsCodeEditorDescriptionSignature } from './description';
import type { HdsCodeEditorTitleSignature } from './title';
import type { EditorView } from '@codemirror/view';

export interface HdsCodeEditorSignature {
Args: {
hasCopyButton?: boolean;
hasFullScreenButton?: boolean;
language?: HdsCodeEditorModifierSignature['Args']['Named']['language'];
value?: HdsCodeEditorModifierSignature['Args']['Named']['value'];
onInput?: HdsCodeEditorModifierSignature['Args']['Named']['onInput'];
onSetup?: HdsCodeEditorModifierSignature['Args']['Named']['onSetup'];
};
Blocks: {
default: [
{
Title?: ComponentLike<HdsCodeEditorTitleSignature>;
Description?: ComponentLike<HdsCodeEditorDescriptionSignature>;
Button?: ComponentLike<HdsButtonSignature>;
},
];
};
Element: HTMLDivElement;
}

export default class HdsCodeEditor extends Component<HdsCodeEditorSignature> {
@tracked private _isFullScreen = false;
@tracked private _isSetupComplete = false;
@tracked private _value;

private _handleEscape = modifier(() => {
const handleKeyDown = (event: KeyboardEvent) => {
if (event.key !== 'Escape' || !this._isFullScreen) {
return;
}

this.toggleFullScreen();
};

document.addEventListener('keydown', handleKeyDown);

return () => {
document.removeEventListener('keydown', handleKeyDown);
};
});

constructor(owner: unknown, args: HdsCodeEditorSignature['Args']) {
super(owner, args);

if (args.value) {
this._value = args.value;
}
}

get classNames(): string {
// Currently there is only one theme so the class name is hard-coded.
// In the future, additional themes such as a "light" theme could be added.
const classes = ['hds-code-editor', 'hds-code-editor--theme-dark'];

if (this._isFullScreen) {
classes.push('hds-code-editor--is-full-screen');
}

return classes.join(' ');
}

get hasActions(): boolean {
return (this.args.hasCopyButton || this.args.hasFullScreenButton) ?? false;
}

@action
toggleFullScreen(): void {
this._isFullScreen = !this._isFullScreen;
}

@action
onInput(newVal: string): void {
this._value = newVal;
this.args.onInput?.(newVal);
}

@action
onKeyDown(event: KeyboardEvent): void {
if (event.key === 'Escape' && this._isFullScreen) {
this.toggleFullScreen();
}
}

@action
onSetup(editorView: EditorView): void {
this._isSetupComplete = true;
this.args.onSetup?.(editorView);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<Hds::Text::Body class="hds-code-editor__title" @tag={{this.tag}} @size="200" @weight="semibold" ...attributes>
{{yield}}
</Hds::Text::Body>
24 changes: 24 additions & 0 deletions packages/components/src/components/hds/code-editor/title.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/

import Component from '@glimmer/component';

import type { HdsTextBodySignature } from '../text/body';

export interface HdsCodeEditorTitleSignature {
Args: {
tag?: HdsTextBodySignature['Args']['tag'];
};
Blocks: {
default: [];
};
Element: HdsTextBodySignature['Element'];
}

export default class HdsCodeEditorTitle extends Component<HdsCodeEditorTitleSignature> {
get tag() {
return this.args.tag ?? 'h2';
zamoore marked this conversation as resolved.
Show resolved Hide resolved
}
}
Loading
Loading