@operato/input 7.0.78 → 7.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/ox-input-signature.d.ts +23 -0
- package/dist/src/ox-input-signature.js +144 -0
- package/dist/src/ox-input-signature.js.map +1 -0
- package/dist/stories/ox-input-/bsignature.stories.d.ts +23 -0
- package/dist/stories/ox-input-/bsignature.stories.js +56 -0
- package/dist/stories/ox-input-/bsignature.stories.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +11 -7
- package/src/index.ts +1 -0
- package/src/ox-input-signature.ts +154 -0
- package/stories/ox-input-/bsignature.stories.ts +71 -0
package/package.json
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
"name": "@operato/input",
|
3
3
|
"description": "Webcomponents for input following open-wc recommendations",
|
4
4
|
"author": "heartyoh@hatiolab.com",
|
5
|
-
"version": "7.
|
5
|
+
"version": "7.1.2",
|
6
6
|
"main": "dist/src/index.js",
|
7
7
|
"module": "dist/src/index.js",
|
8
8
|
"license": "MIT",
|
@@ -57,6 +57,7 @@
|
|
57
57
|
"./ox-input-mass-fraction.js": "./dist/src/ox-input-mass-fraction.js",
|
58
58
|
"./ox-input-textarea.js": "./dist/src/ox-input-textarea.js",
|
59
59
|
"./ox-input-direction.js": "./dist/src/ox-input-direction.js",
|
60
|
+
"./ox-input-signature.js": "./dist/src/ox-input-signature.js",
|
60
61
|
"./ox-input-table-column-config.js": "./dist/src/ox-input-table-column-config.js"
|
61
62
|
},
|
62
63
|
"typesVersions": {
|
@@ -175,6 +176,9 @@
|
|
175
176
|
"./ox-input-direction.js": [
|
176
177
|
"./dist/src/ox-input-direction.d.ts"
|
177
178
|
],
|
179
|
+
"./ox-input-signature.js": [
|
180
|
+
"./dist/src/ox-input-signature.d.ts"
|
181
|
+
],
|
178
182
|
"./ox-input-table-column-config.js": [
|
179
183
|
"./dist/src/ox-input-table-column-config.d.ts"
|
180
184
|
]
|
@@ -206,11 +210,11 @@
|
|
206
210
|
"@ctrl/tinycolor": "^4.1.0",
|
207
211
|
"@lit/localize": "^0.12.1",
|
208
212
|
"@material/web": "^2.0.0",
|
209
|
-
"@operato/color-picker": "^7.
|
210
|
-
"@operato/i18n": "^7.
|
211
|
-
"@operato/popup": "^7.
|
212
|
-
"@operato/styles": "^7.
|
213
|
-
"@operato/utils": "^7.
|
213
|
+
"@operato/color-picker": "^7.1.1",
|
214
|
+
"@operato/i18n": "^7.1.1",
|
215
|
+
"@operato/popup": "^7.1.1",
|
216
|
+
"@operato/styles": "^7.1.1",
|
217
|
+
"@operato/utils": "^7.1.1",
|
214
218
|
"@polymer/paper-dropdown-menu": "^3.2.0",
|
215
219
|
"@polymer/paper-item": "^3.0.1",
|
216
220
|
"@thebespokepixel/es-tinycolor": "^3.1.0",
|
@@ -254,5 +258,5 @@
|
|
254
258
|
"prettier --write"
|
255
259
|
]
|
256
260
|
},
|
257
|
-
"gitHead": "
|
261
|
+
"gitHead": "9e40d6c5fce98a720ef628b576eec76a2283c59e"
|
258
262
|
}
|
package/src/index.ts
CHANGED
@@ -0,0 +1,154 @@
|
|
1
|
+
import '@material/web/icon/icon.js'
|
2
|
+
|
3
|
+
import { css, html, nothing } from 'lit'
|
4
|
+
import { customElement, property } from 'lit/decorators.js'
|
5
|
+
|
6
|
+
import { OxFormField } from './ox-form-field.js'
|
7
|
+
|
8
|
+
@customElement('ox-input-signature')
|
9
|
+
export class OxInputSignature extends OxFormField {
|
10
|
+
static styles = [
|
11
|
+
css`
|
12
|
+
:host {
|
13
|
+
position: relative;
|
14
|
+
box-sizing: border-box;
|
15
|
+
|
16
|
+
display: flex;
|
17
|
+
flex-direction: column;
|
18
|
+
place-content: center;
|
19
|
+
border-radius: var(--border-radius);
|
20
|
+
padding: var(--padding-default, 9px);
|
21
|
+
min-height: 100px;
|
22
|
+
text-transform: capitalize;
|
23
|
+
|
24
|
+
border: var(--file-uploader-border);
|
25
|
+
background-color: var(--md-sys-color-background);
|
26
|
+
font: var(--file-uploader-font) !important;
|
27
|
+
color: var(--file-uploader-color);
|
28
|
+
|
29
|
+
overflow: hidden;
|
30
|
+
}
|
31
|
+
|
32
|
+
canvas {
|
33
|
+
width: 100%;
|
34
|
+
border: 1px solid #000;
|
35
|
+
}
|
36
|
+
|
37
|
+
.controls {
|
38
|
+
margin-top: 10px;
|
39
|
+
}
|
40
|
+
`
|
41
|
+
]
|
42
|
+
|
43
|
+
@property({ type: Boolean }) isDrawing = false
|
44
|
+
@property({ type: String }) value: string | null = null
|
45
|
+
|
46
|
+
private ctx!: CanvasRenderingContext2D
|
47
|
+
private canvas!: HTMLCanvasElement
|
48
|
+
|
49
|
+
render() {
|
50
|
+
return html`
|
51
|
+
<canvas
|
52
|
+
width="400"
|
53
|
+
height="200"
|
54
|
+
@mousedown=${this.startDrawing}
|
55
|
+
@mouseup=${this.stopDrawing}
|
56
|
+
@mousemove=${this.draw}
|
57
|
+
@mouseleave=${this.stopDrawing}
|
58
|
+
@touchstart=${this.startDrawing}
|
59
|
+
@touchend=${this.stopDrawing}
|
60
|
+
@touchmove=${this.draw}
|
61
|
+
></canvas>
|
62
|
+
|
63
|
+
${!this.disabled
|
64
|
+
? html` <div class="controls">
|
65
|
+
<button @click="${this.clearCanvas}">Clear</button>
|
66
|
+
<button @click="${this.saveSignature}">Save</button>
|
67
|
+
</div>`
|
68
|
+
: nothing}
|
69
|
+
`
|
70
|
+
}
|
71
|
+
|
72
|
+
firstUpdated() {
|
73
|
+
this.canvas = this.shadowRoot!.querySelector('canvas')!
|
74
|
+
this.ctx = this.canvas.getContext('2d')!
|
75
|
+
this.ctx.strokeStyle = '#000'
|
76
|
+
this.ctx.lineWidth = 2
|
77
|
+
|
78
|
+
// 처음 로딩 시 서명 데이터를 캔버스에 표시
|
79
|
+
if (this.value) {
|
80
|
+
this.loadSignature(this.value)
|
81
|
+
}
|
82
|
+
}
|
83
|
+
|
84
|
+
updated(changedProperties: Map<string | number | symbol, unknown>) {
|
85
|
+
if (changedProperties.has('value') && this.value) {
|
86
|
+
this.loadSignature(this.value)
|
87
|
+
}
|
88
|
+
}
|
89
|
+
|
90
|
+
startDrawing(event: MouseEvent | TouchEvent) {
|
91
|
+
if (this.disabled) {
|
92
|
+
return
|
93
|
+
}
|
94
|
+
|
95
|
+
this.isDrawing = true
|
96
|
+
this.ctx.beginPath()
|
97
|
+
const position = this.getEventPosition(event)
|
98
|
+
this.ctx.moveTo(position.x, position.y)
|
99
|
+
}
|
100
|
+
|
101
|
+
stopDrawing() {
|
102
|
+
this.isDrawing = false
|
103
|
+
}
|
104
|
+
|
105
|
+
draw(event: MouseEvent | TouchEvent) {
|
106
|
+
if (!this.isDrawing) return
|
107
|
+
const position = this.getEventPosition(event)
|
108
|
+
this.ctx.lineTo(position.x, position.y)
|
109
|
+
this.ctx.stroke()
|
110
|
+
}
|
111
|
+
|
112
|
+
clearCanvas() {
|
113
|
+
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
|
114
|
+
}
|
115
|
+
|
116
|
+
saveSignature() {
|
117
|
+
this.value = this.canvas.toDataURL()
|
118
|
+
this._notifyChange()
|
119
|
+
}
|
120
|
+
|
121
|
+
loadSignature(dataUrl: string) {
|
122
|
+
const image = new Image()
|
123
|
+
image.onload = () => {
|
124
|
+
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height) // 이전 내용을 지움
|
125
|
+
this.ctx.drawImage(image, 0, 0) // 이미지를 캔버스에 그림
|
126
|
+
}
|
127
|
+
image.src = dataUrl
|
128
|
+
}
|
129
|
+
|
130
|
+
getEventPosition(event: MouseEvent | TouchEvent) {
|
131
|
+
const rect = this.canvas.getBoundingClientRect()
|
132
|
+
|
133
|
+
// 캔버스의 실제 크기와 CSS 크기 간의 비율을 계산
|
134
|
+
const scaleX = this.canvas.width / rect.width
|
135
|
+
const scaleY = this.canvas.height / rect.height
|
136
|
+
|
137
|
+
// 실제 좌표 계산
|
138
|
+
const isTouchEvent = event instanceof TouchEvent
|
139
|
+
const x = (isTouchEvent ? event.touches[0].clientX - rect.left : (event as MouseEvent).clientX - rect.left) * scaleX
|
140
|
+
const y = (isTouchEvent ? event.touches[0].clientY - rect.top : (event as MouseEvent).clientY - rect.top) * scaleY
|
141
|
+
|
142
|
+
return { x, y }
|
143
|
+
}
|
144
|
+
|
145
|
+
_notifyChange() {
|
146
|
+
this.dispatchEvent(
|
147
|
+
new CustomEvent('change', {
|
148
|
+
bubbles: true,
|
149
|
+
composed: true,
|
150
|
+
detail: this.value
|
151
|
+
})
|
152
|
+
)
|
153
|
+
}
|
154
|
+
}
|
@@ -0,0 +1,71 @@
|
|
1
|
+
import '../src/ox-input-signature.js'
|
2
|
+
|
3
|
+
import { html, TemplateResult } from 'lit'
|
4
|
+
import { styles as MDTypeScaleStyles } from '@material/web/typography/md-typescale-styles'
|
5
|
+
|
6
|
+
export default {
|
7
|
+
title: 'ox-input-signature',
|
8
|
+
component: 'ox-input-signature',
|
9
|
+
argTypes: {
|
10
|
+
disabled: { control: 'boolean' }
|
11
|
+
}
|
12
|
+
}
|
13
|
+
|
14
|
+
interface Story<T> {
|
15
|
+
(args: T): TemplateResult
|
16
|
+
args?: Partial<T>
|
17
|
+
argTypes?: Record<string, unknown>
|
18
|
+
}
|
19
|
+
|
20
|
+
interface ArgTypes {
|
21
|
+
label?: string
|
22
|
+
name?: string
|
23
|
+
disabled?: boolean
|
24
|
+
}
|
25
|
+
|
26
|
+
const Template: Story<ArgTypes> = ({ label = 'signature', name = 'signature', disabled }: ArgTypes) => html`
|
27
|
+
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" rel="stylesheet" />
|
28
|
+
|
29
|
+
<link href="/themes/light.css" rel="stylesheet" />
|
30
|
+
<link href="/themes/dark.css" rel="stylesheet" />
|
31
|
+
<link href="/themes/spacing.css" rel="stylesheet" />
|
32
|
+
|
33
|
+
<link
|
34
|
+
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL@20..48,100..700,0..1"
|
35
|
+
rel="stylesheet"
|
36
|
+
/>
|
37
|
+
<link
|
38
|
+
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL@20..48,100..700,0..1"
|
39
|
+
rel="stylesheet"
|
40
|
+
/>
|
41
|
+
<link
|
42
|
+
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Sharp:opsz,wght,FILL@20..48,100..700,0..1"
|
43
|
+
rel="stylesheet"
|
44
|
+
/>
|
45
|
+
|
46
|
+
<style>
|
47
|
+
${MDTypeScaleStyles.cssText}
|
48
|
+
</style>
|
49
|
+
|
50
|
+
<style>
|
51
|
+
.container {
|
52
|
+
height: 500px;
|
53
|
+
text-align: center;
|
54
|
+
padding: 20px;
|
55
|
+
|
56
|
+
background-color: var(--md-sys-color-primary-container);
|
57
|
+
color: var(--md-sys-color-on-primary-container);
|
58
|
+
}
|
59
|
+
</style>
|
60
|
+
|
61
|
+
<div class="container md-typescale-body-large-prominent">
|
62
|
+
<ox-input-signature
|
63
|
+
?disabled=${disabled}
|
64
|
+
@change=${(e: Event) => console.log(((e as CustomEvent).target as any)!.value)}
|
65
|
+
>
|
66
|
+
</ox-input-signature>
|
67
|
+
</div>
|
68
|
+
`
|
69
|
+
|
70
|
+
export const Regular = Template.bind({})
|
71
|
+
Regular.args = {}
|