-
Notifications
You must be signed in to change notification settings - Fork 1
/
custom-element.tsx
108 lines (90 loc) · 3.28 KB
/
custom-element.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import {
attribute,
booleanAttribute,
element,
Element,
ElementAttributes,
stringAttribute,
} from '@lume/element'
import { signal } from 'classy-solid'
import { createShikiTextarea, LanguageProp, ThemeProp } from './core'
import classnames from './index.module.css?classnames'
import css from './index.module.css?raw'
import { sheet } from './utils/sheet.js'
/**********************************************************************************/
/* */
/* Types */
/* */
/**********************************************************************************/
interface ShikiTextareaAttributes
extends Omit<
ElementAttributes<ShikiTextareaElement, 'language' | 'theme' | 'editable'>,
'onInput' | 'oninput'
> {
oninput?: (event: InputEvent & { currentTarget: ShikiTextareaElement }) => any
onInput?: (event: InputEvent & { currentTarget: ShikiTextareaElement }) => any
value: string
}
declare module 'solid-js/jsx-runtime' {
namespace JSX {
interface IntrinsicElements {
'shiki-textarea': ShikiTextareaAttributes
}
}
}
declare global {
namespace JSX {
interface IntrinsicElements {
'shiki-textarea': ShikiTextareaAttributes
}
}
}
/**********************************************************************************/
/* */
/* Custom Element */
/* */
/**********************************************************************************/
const ShikiTextarea = createShikiTextarea(Object.fromEntries(classnames.map(name => [name, name])))
const ShikiTextareaStyleSheet = sheet(css)
@element('shiki-textarea')
class ShikiTextareaElement extends Element {
@attribute() language: LanguageProp = 'tsx'
@attribute() theme: ThemeProp = 'andromeeda'
@stringAttribute stylesheet = ''
@booleanAttribute editable = true
@signal private _value = ''
textarea: HTMLTextAreaElement = null!
template = () => {
const adoptedStyleSheets = this.shadowRoot!.adoptedStyleSheets
// local component stylesheet
adoptedStyleSheets.push(ShikiTextareaStyleSheet)
// user provided stylesheet
if (this.stylesheet) {
adoptedStyleSheets.push(sheet(this.stylesheet))
}
this.createEffect(() => console.log(this.language))
return (
<ShikiTextarea
language={this.language}
theme={this.theme}
code={this._value}
editable={this.editable}
textareaRef={textarea => (this.textarea = textarea)}
/>
)
}
get value() {
return this.textarea.value
}
set value(value) {
this._value = value
}
}
// NOTE: <shiki-textarea/> is already defined with lume's @element() decorator.
// register is a NOOP, but is needed for rollup not to treeshake
// the custom-element declaration out of the bundle.
export function register() {
if (!customElements.get('shiki-textarea')) {
customElements.define('shiki-textarea', ShikiTextareaElement)
}
}