Skip to content

Commit

Permalink
feat(abc:hotkey): add hotkey component (#1538)
Browse files Browse the repository at this point in the history
  • Loading branch information
cipchk authored Nov 11, 2022
1 parent a197bb1 commit 6913f01
Show file tree
Hide file tree
Showing 16 changed files with 225 additions and 72 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@
"@ng-util/monaco-editor": "^14.0.0",
"@nguniversal/express-engine": "~14.1.0",
"express": "^4.18.1",
"isutf8": "^4.0.0"
"isutf8": "^4.0.0",
"@github/hotkey": "^2.0.1"
},
"devDependencies": {
"@angular-devkit/build-angular": "^14.2.1",
Expand Down
73 changes: 73 additions & 0 deletions packages/abc/hotkey/demo/basic.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
---
order: 1
title:
zh-CN: 基础
en-US: Basic
---

## zh-CN

最简单的用法。

## en-US

Simplest of usage.

```ts
import { Component } from '@angular/core';

import { NzMessageService } from 'ng-zorro-antd/message';

@Component({
selector: 'app-demo',
template: `
<button
nz-button
nzType="primary"
(click)="show('clicked button 1!')"
hotkey="Control+d,Meta+d"
data-hotkey-scope="text-area-1"
>
press meta+d or ctrl+d in text area 1 to click button 1
</button>
<br />
<textarea nz-input id="text-area-1" rows="4" cols="40" hotkey="q" #textArea1 (focus)="selectText(textArea1)">
text area 1, press q to focus this textarea and select all text</textarea
>
<br />
<button
nz-button
nzType="primary"
(click)="show('clicked button 2!')"
hotkey="Control+d,Meta+d"
data-hotkey-scope="text-area-2"
>
press meta+d or ctrl+d in text area 2 to click button 2
</button>
<br />
<textarea nz-input nzType="primary" id="text-area-2" rows="4" cols="40">text area 2</textarea><br />
<label><input nz-input hotkey="t" type="text" />Press <kbd>t</kbd> to focus this field</label><br />
<label><nz-switch hotkey="r"></nz-switch>Press <kbd>r</kbd> to check/uncheck this checkbox</label><br />
<a (click)="show('click link')" nz-button nzType="link" hotkey="o k"> Press <kbd>o k</kbd> click this link </a>
`,
styles: [
`
:host kbd {
color: #f50;
padding: 0 8px;
}
`
]
})
export class DemoComponent {
constructor(private msg: NzMessageService) {}

show(msg: string): void {
this.msg.info(msg);
}

selectText(el: HTMLTextAreaElement): void {
el.select();
}
}
```
27 changes: 27 additions & 0 deletions packages/abc/hotkey/hotkey.directive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Platform } from '@angular/cdk/platform';
import { Directive, ElementRef, Input, NgZone, OnDestroy } from '@angular/core';

import { install, uninstall } from '@github/hotkey';

@Directive({ selector: '[hotkey]' })
export class HotkeyDirective implements OnDestroy {
/**
* Specify [hotkey format](https://github.com/github/hotkey#hotkey-string-format)
*
* 指定[热键格式](https://github.com/github/hotkey#hotkey-string-format)
*/
@Input('hotkey')
set hotkey(key: string) {
if (!this.platform.isBrowser) return;

this.ngZone.runOutsideAngular(() => install(this.el.nativeElement, key));
}

constructor(private el: ElementRef<HTMLElement>, private ngZone: NgZone, private platform: Platform) {}

ngOnDestroy(): void {
if (!this.platform.isBrowser) return;

this.ngZone.runOutsideAngular(() => uninstall(this.el.nativeElement));
}
}
11 changes: 11 additions & 0 deletions packages/abc/hotkey/hotkey.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { NgModule } from '@angular/core';

import { HotkeyDirective } from './hotkey.directive';

const DIRECTIVES = [HotkeyDirective];

@NgModule({
declarations: DIRECTIVES,
exports: DIRECTIVES
})
export class HotkeyModule {}
51 changes: 51 additions & 0 deletions packages/abc/hotkey/hotkey.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Platform } from '@angular/cdk/platform';
import { Component, ViewChild } from '@angular/core';
import { TestBed } from '@angular/core/testing';

import { createTestContext } from '../../testing';
import { HotkeyDirective } from './hotkey.directive';
import { HotkeyModule } from './hotkey.module';

describe('abc: hotkey', () => {
let context: TestComponent;

function genModule(isBrowser: boolean): void {
TestBed.configureTestingModule({
imports: [HotkeyModule],
providers: [{ provide: Platform, useValue: { isBrowser } }],
declarations: [TestComponent]
});
({ context } = createTestContext(TestComponent));
spyOn(context, 'focus');
}

afterEach(() => {
context.comp.ngOnDestroy();
});

it('should be working', done => {
genModule(true);
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'q' }));
setTimeout(() => {
expect(context.focus).toHaveBeenCalled();
done();
}, 60);
});

it('when in ssr', done => {
genModule(false);
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'q' }));
setTimeout(() => {
expect(context.focus).not.toHaveBeenCalled();
done();
}, 60);
});
});

@Component({ template: `<input #el hotkey="q" class="ipt" (focus)="focus()" />` })
class TestComponent {
@ViewChild(HotkeyDirective, { static: true }) readonly comp!: HotkeyDirective;
hotkey = 'q';

focus(): void {}
}
20 changes: 20 additions & 0 deletions packages/abc/hotkey/index.en-US.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
type: Basic
order: 1
title: hotkey
subtitle: Hotkey
cols: 2
module: import { HotkeyModule } from '@delon/abc/hotkey';
---

Based on the [@github/hotke](https://github.com/github/hotkey) hotkey library.

> If you don't know the hotkey value, you can get it through [Hotkey Code](https://github.github.io/hotkey/examples/hotkey_mapper.html).
## API

### LoadingShowOptions

| Property | Description | Type | Default |
|----------|-------------|------|---------|
| `hotkey` | Specify [hotkey format](https://github.com/github/hotkey#hotkey-string-format) | `string` | - |
1 change: 1 addition & 0 deletions packages/abc/hotkey/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './public_api';
20 changes: 20 additions & 0 deletions packages/abc/hotkey/index.zh-CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
type: Basic
order: 1
title: hotkey
subtitle: 热键
cols: 2
module: import { HotkeyModule } from '@delon/abc/hotkey';
---

基于 [@github/hotke](https://github.com/github/hotkey) 热键库。

> 如果不清楚热键值,可通过[热键代码](https://github.github.io/hotkey/examples/hotkey_mapper.html)来获取。
## API

### [hotkey]

| 成员 | 说明 | 类型 | 默认值 |
|----|----|----|-----|
| `hotkey` | 指定[热键格式](https://github.com/github/hotkey#hotkey-string-format) | `string` | - |
6 changes: 6 additions & 0 deletions packages/abc/hotkey/ng-package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"lib": {
"flatModuleFile": "hotkey",
"entryFile": "public_api.ts"
}
}
2 changes: 2 additions & 0 deletions packages/abc/hotkey/public_api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './hotkey.module';
export * from './hotkey.directive';
1 change: 1 addition & 0 deletions packages/abc/ng-package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"xlsx",
"plyr",
"pdfjs-dist",
"@github/hotkey",
"ngx-countdown",
"@delon/theme",
"@delon/util",
Expand Down
1 change: 1 addition & 0 deletions packages/abc/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"xlsx": "@LIB-PLACEHOLDER",
"plyr": "@LIB-PLACEHOLDER",
"pdfjs-dist": "@LIB-PLACEHOLDER",
"@github/hotkey": "@LIB-PLACEHOLDER",
"ngx-countdown": "@LIB-PLACEHOLDER",
"@delon/theme": "PEER-0.0.0-PLACEHOLDER",
"@delon/util": "PEER-0.0.0-PLACEHOLDER",
Expand Down
3 changes: 2 additions & 1 deletion scripts/ci/utils.sh
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ DEPENDENCIES=$(node -p "
'husky',
'lint-staged',
'rxjs',
'swagger-typescript-api'
'swagger-typescript-api',
'@github/hotkey'
].map(key => key.replace(/\@/g, '\\\\@').replace(/\//g, '\\\\/').replace(/-/g, '\\\\-') + '|' + (vs[key] || dvs[key])).join('\n\t');
")
VERSION=$(node -p "require('./package.json').version")
Expand Down
2 changes: 2 additions & 0 deletions src/app/core/code/files/delon-abc.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { FullContentModule } from '@delon/abc/full-content';
import { GlobalFooterModule } from '@delon/abc/global-footer';
import { ImageModule } from '@delon/abc/image';
import { LoadingModule } from '@delon/abc/loading';
import { HotkeyModule } from '@delon/abc/hotkey';
import { LodopModule } from '@delon/abc/lodop';
import { NoticeIconModule } from '@delon/abc/notice-icon';
import { ObserversModule } from '@delon/abc/observers';
Expand Down Expand Up @@ -62,6 +63,7 @@ const MODULES = [
SGModule,
DatePickerModule,
LoadingModule,
HotkeyModule,
MediaModule,
OnboardingModule,
LetModule,
Expand Down
4 changes: 3 additions & 1 deletion src/app/shared/shared-delon.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { ErrorCollectModule } from '@delon/abc/error-collect';
import { ExceptionModule } from '@delon/abc/exception';
import { FooterToolbarModule } from '@delon/abc/footer-toolbar';
import { GlobalFooterModule } from '@delon/abc/global-footer';
import { HotkeyModule } from '@delon/abc/hotkey';
import { LetModule } from '@delon/abc/let';
import { LoadingModule } from '@delon/abc/loading';
import { MediaModule } from '@delon/abc/media';
Expand Down Expand Up @@ -94,5 +95,6 @@ export const SHARED_DELON_MODULES = [
FormatPipeModule,
FilterPipeModule,
AutoFocusModule,
LetModule
LetModule,
HotkeyModule
];
72 changes: 3 additions & 69 deletions src/dev/demo.component.ts
Original file line number Diff line number Diff line change
@@ -1,77 +1,11 @@
import { Component } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';

import { SEErrorRefresh } from '@delon/abc/se';
import { NzMessageService } from 'ng-zorro-antd/message';

@Component({
selector: 'app-demo',
template: `
<h3>Operating</h3>
<div class="mb-md">
<button nz-button (click)="resetErrors()">Reset all errors</button>
</div>
<form nz-form #f="ngForm" se-container [errors]="ngModelErrors" gutter="32">
<se label="App Key" [error]="{ required: '请填写', pattern: '只能包含a-z, 0-9之间' }">
<input
type="text"
nz-input
[(ngModel)]="i.ak"
name="ak"
required
pattern="^[a-z0-9]*$"
placeholder="必填项,且只能包含a-z, 0-9之间"
/>
</se>
<ng-template #appSecretRequired> 请填写,密钥<a (click)="msg.success('success')">生成</a>地址。 </ng-template>
<se label="App Secret" [error]="{ required: appSecretRequired, pattern: '只能包含0-9之间' }">
<input
type="text"
nz-input
[(ngModel)]="i.sk"
name="sk"
required
maxlength="32"
pattern="^[0-9]*$"
placeholder="必填项,且只能包含0-9之间"
/>
</se>
<se>
<button nz-button nzType="primary" [disabled]="f.invalid">Save</button>
</se>
</form>
<h3>Reactive</h3>
<form nz-form [formGroup]="validateForm" se-container gutter="32" [errors]="reactiveErrors">
<se label="App Key" [error]="{ required: 'Please input your username!', pattern: 'Incorrect format, muse be A' }">
<input formControlName="userName" nz-input placeholder="Username" />
</se>
<se label="App Secret" error="Please input your Password!">
<input formControlName="password" nz-input type="password" placeholder="Password" />
</se>
<se>
<button nz-button nzType="primary" [disabled]="!validateForm.valid">Log in</button>
</se>
</form>
`
template: ``
})
export class DemoComponent {
validateForm = new FormGroup({
userName: new FormControl<string | null>(null, [Validators.required, Validators.pattern(/A/)]),
password: new FormControl(null, [Validators.required]),
remember: new FormControl(true)
});

i: { ak?: string; sk?: string } = {};
ngModelErrors: SEErrorRefresh[] = [];
reactiveErrors: SEErrorRefresh[] = [];

constructor(public msg: NzMessageService) {}

resetErrors(): void {
this.ngModelErrors = [{ name: 'ak', error: 'Required field, and can only contain a-z, 0-9' }];
this.reactiveErrors = [
{ name: 'userName', error: 'Required username' },
{ name: 'password', error: 'Required password' }
];
_n(): void {
console.log('n');
}
}

0 comments on commit 6913f01

Please sign in to comment.