@operato/input 8.0.0-alpha.4 → 8.0.0-alpha.41

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.
Files changed (39) hide show
  1. package/CHANGELOG.md +107 -0
  2. package/dist/src/ox-input-color-stops.d.ts +1 -1
  3. package/dist/src/ox-input-color-stops.js +2 -2
  4. package/dist/src/ox-input-color-stops.js.map +1 -1
  5. package/dist/src/ox-input-direction.d.ts +1 -0
  6. package/dist/src/ox-input-direction.js +37 -4
  7. package/dist/src/ox-input-direction.js.map +1 -1
  8. package/dist/src/ox-input-signature.d.ts +4 -2
  9. package/dist/src/ox-input-signature.js +34 -14
  10. package/dist/src/ox-input-signature.js.map +1 -1
  11. package/dist/src/ox-select-floor.d.ts +35 -0
  12. package/dist/src/ox-select-floor.js +238 -0
  13. package/dist/src/ox-select-floor.js.map +1 -0
  14. package/dist/stories/image-for-select-floor.d.ts +1 -0
  15. package/dist/stories/image-for-select-floor.js +2 -0
  16. package/dist/stories/image-for-select-floor.js.map +1 -0
  17. package/dist/stories/ox-input-direction.stories.js +11 -0
  18. package/dist/stories/ox-input-direction.stories.js.map +1 -1
  19. package/dist/stories/ox-select-floor.stories.d.ts +45 -0
  20. package/dist/stories/ox-select-floor.stories.js +166 -0
  21. package/dist/stories/ox-select-floor.stories.js.map +1 -0
  22. package/dist/tsconfig.tsbuildinfo +1 -1
  23. package/package.json +19 -15
  24. package/src/ox-input-color-stops.ts +2 -2
  25. package/src/ox-input-direction.ts +31 -4
  26. package/src/ox-input-signature.ts +45 -17
  27. package/src/ox-select-floor.ts +246 -0
  28. package/stories/image-for-select-floor.ts +2 -0
  29. package/stories/ox-input-direction.stories.ts +11 -0
  30. package/stories/ox-select-floor.stories.ts +197 -0
  31. package/themes/calendar-theme.css +3 -1
  32. package/assets/images/icon-editor-gradient-direction.png +0 -0
  33. package/assets/images/icon-properties-label.png +0 -0
  34. package/assets/images/icon-properties-line-type.png +0 -0
  35. package/assets/images/icon-properties-table.png +0 -0
  36. package/dist/src/ox-zoomable-image.d.ts +0 -17
  37. package/dist/src/ox-zoomable-image.js +0 -80
  38. package/dist/src/ox-zoomable-image.js.map +0 -1
  39. package/src/ox-zoomable-image.ts +0 -75
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": "8.0.0-alpha.4",
5
+ "version": "8.0.0-alpha.41",
6
6
  "main": "dist/src/index.js",
7
7
  "module": "dist/src/index.js",
8
8
  "license": "MIT",
@@ -58,6 +58,7 @@
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
60
  "./ox-input-signature.js": "./dist/src/ox-input-signature.js",
61
+ "./ox-select-floor.js": "./dist/src/ox-select-floor.js",
61
62
  "./ox-input-table-column-config.js": "./dist/src/ox-input-table-column-config.js"
62
63
  },
63
64
  "typesVersions": {
@@ -179,6 +180,9 @@
179
180
  "./ox-input-signature.js": [
180
181
  "./dist/src/ox-input-signature.d.ts"
181
182
  ],
183
+ "./ox-select-floor.js": [
184
+ "./dist/src/ox-select-floor.d.ts"
185
+ ],
182
186
  "./ox-input-table-column-config.js": [
183
187
  "./dist/src/ox-input-table-column-config.d.ts"
184
188
  ]
@@ -210,11 +214,11 @@
210
214
  "@ctrl/tinycolor": "^4.1.0",
211
215
  "@lit/localize": "^0.12.1",
212
216
  "@material/web": "^2.0.0",
213
- "@operato/color-picker": "^8.0.0-alpha.0",
214
- "@operato/i18n": "^8.0.0-alpha.0",
215
- "@operato/popup": "^8.0.0-alpha.4",
216
- "@operato/styles": "^8.0.0-alpha.4",
217
- "@operato/utils": "^8.0.0-alpha.0",
217
+ "@operato/color-picker": "^8.0.0-alpha.33",
218
+ "@operato/i18n": "^8.0.0-alpha.37",
219
+ "@operato/popup": "^8.0.0-alpha.41",
220
+ "@operato/styles": "^8.0.0-alpha.37",
221
+ "@operato/utils": "^8.0.0-alpha.37",
218
222
  "@polymer/paper-dropdown-menu": "^3.2.0",
219
223
  "@polymer/paper-item": "^3.0.1",
220
224
  "@thebespokepixel/es-tinycolor": "^3.1.0",
@@ -225,18 +229,18 @@
225
229
  "lodash-es": "^4.17.21"
226
230
  },
227
231
  "devDependencies": {
228
- "@custom-elements-manifest/analyzer": "^0.9.2",
232
+ "@custom-elements-manifest/analyzer": "^0.10.0",
229
233
  "@hatiolab/prettier-config": "^1.0.0",
230
234
  "@lit/localize-tools": "^0.7.2",
231
235
  "@open-wc/eslint-config": "^12.0.3",
232
- "@open-wc/testing": "^3.1.6",
233
- "@typescript-eslint/eslint-plugin": "^7.0.1",
234
- "@typescript-eslint/parser": "^7.0.1",
235
- "@web/dev-server": "^0.3.0",
236
+ "@open-wc/testing": "^4.0.0",
237
+ "@typescript-eslint/eslint-plugin": "^8.0.0",
238
+ "@typescript-eslint/parser": "^8.0.0",
239
+ "@web/dev-server": "^0.4.0",
236
240
  "@web/dev-server-storybook": "^2.0.1",
237
- "@web/test-runner": "^0.18.0",
238
- "concurrently": "^8.0.1",
239
- "eslint": "^8.39.0",
241
+ "@web/test-runner": "^0.19.0",
242
+ "concurrently": "^9.0.0",
243
+ "eslint": "^9.0.0",
240
244
  "eslint-config-prettier": "^9.1.0",
241
245
  "husky": "^9.0.11",
242
246
  "lint-staged": "^15.2.2",
@@ -258,5 +262,5 @@
258
262
  "prettier --write"
259
263
  ]
260
264
  },
261
- "gitHead": "ac097b448ea96721b3418132e92988afdf764519"
265
+ "gitHead": "0c2adcc994cd105055c9355810fa9c7c8196ca41"
262
266
  }
@@ -210,7 +210,7 @@ export class OxInputColorStops extends OxFormField {
210
210
  <div
211
211
  id="markers"
212
212
  @dblclick=${(e: MouseEvent) => this._onDblClickMarkers(e)}
213
- @mousedown=${(e: MouseEvent) => this._onMouseDown(e)}
213
+ @pointerdown=${(e: PointerEvent) => this._onPointerDown(e)}
214
214
  @dragstart=${(e: DragEvent) => this._onDragStart(e)}
215
215
  @drag=${this._throttled(100, this._onDrag.bind(this))}
216
216
  @dragend=${(e: DragEvent) => this._onDragEnd(e)}
@@ -422,7 +422,7 @@ export class OxInputColorStops extends OxFormField {
422
422
  this.colorEditor.showPicker()
423
423
  }
424
424
 
425
- _onMouseDown(e: MouseEvent) {
425
+ _onPointerDown(e: PointerEvent) {
426
426
  if (this.disabled) {
427
427
  return
428
428
  }
@@ -31,19 +31,46 @@ export class OxInputDirection extends OxFormField {
31
31
  color: var(--md-sys-color-on-primary);
32
32
  background-color: var(--md-sys-color-primary);
33
33
  }
34
+
35
+ /* 아이콘 회전 */
36
+ md-icon[data-value='W'] {
37
+ transform: rotate(-90deg);
38
+ }
39
+
40
+ md-icon[data-value='N'] {
41
+ transform: rotate(0deg);
42
+ }
43
+
44
+ md-icon[data-value='S'] {
45
+ transform: rotate(180deg);
46
+ }
47
+
48
+ md-icon[data-value='E'] {
49
+ transform: rotate(90deg);
50
+ }
34
51
  `
35
52
 
36
53
  @property({ type: String }) value?: string
54
+ @property({ type: Boolean }) inbound?: boolean = false
37
55
 
38
56
  render() {
39
57
  const value = this.value
40
58
 
41
59
  return html`
42
60
  <div @click=${this.onClick.bind(this)}>
43
- <md-icon ?selected=${value == 'W'} data-value="W">arrow_back</md-icon>
44
- <md-icon ?selected=${value == 'N'} data-value="N">arrow_upward</md-icon>
45
- <md-icon ?selected=${value == 'S'} data-value="S">arrow_downward</md-icon>
46
- <md-icon ?selected=${value == 'E'} data-value="E">arrow_forward</md-icon>
61
+ ${this.inbound
62
+ ? html`
63
+ <md-icon ?selected=${value == 'W'} data-value="W">step_into</md-icon>
64
+ <md-icon ?selected=${value == 'N'} data-value="N">step_into</md-icon>
65
+ <md-icon ?selected=${value == 'S'} data-value="S">step_into</md-icon>
66
+ <md-icon ?selected=${value == 'E'} data-value="E">step_into</md-icon>
67
+ `
68
+ : html`
69
+ <md-icon ?selected=${value == 'W'} data-value="W">step_out</md-icon>
70
+ <md-icon ?selected=${value == 'N'} data-value="N">step_out</md-icon>
71
+ <md-icon ?selected=${value == 'S'} data-value="S">step_out</md-icon>
72
+ <md-icon ?selected=${value == 'E'} data-value="E">step_out</md-icon>
73
+ `}
47
74
  </div>
48
75
  `
49
76
  }
@@ -1,7 +1,7 @@
1
1
  import '@material/web/icon/icon.js'
2
2
 
3
- import { css, html, nothing } from 'lit'
4
- import { customElement, property, query, state } from 'lit/decorators.js'
3
+ import { css, html, PropertyValues } from 'lit'
4
+ import { customElement, property, query } from 'lit/decorators.js'
5
5
 
6
6
  import { OxFormField } from './ox-form-field.js'
7
7
 
@@ -31,8 +31,6 @@ export class OxInputSignature extends OxFormField {
31
31
  }
32
32
 
33
33
  dialog canvas {
34
- width: 100%;
35
- height: 100%;
36
34
  border: 1px solid var(--md-sys-color-outline);
37
35
  }
38
36
 
@@ -46,6 +44,19 @@ export class OxInputSignature extends OxFormField {
46
44
  .filler {
47
45
  flex: 1;
48
46
  }
47
+
48
+ /* 버튼 스타일 */
49
+ button {
50
+ background-color: var(--md-sys-color-primary);
51
+ color: var(--md-sys-color-on-primary);
52
+ padding: 10px 20px;
53
+ border: none;
54
+ border-radius: var(--spacing-small);
55
+ font-family: 'Roboto', sans-serif;
56
+ font-size: 14px;
57
+ cursor: pointer;
58
+ transition: background-color 0.3s ease;
59
+ }
49
60
  `
50
61
  ]
51
62
 
@@ -69,13 +80,10 @@ export class OxInputSignature extends OxFormField {
69
80
  <canvas
70
81
  width="800"
71
82
  height="400"
72
- @mousedown=${this.startDrawing}
73
- @mouseup=${this.stopDrawing}
74
- @mousemove=${this.draw}
75
- @mouseleave=${this.stopDrawing}
76
- @touchstart=${this.startDrawing}
77
- @touchend=${this.stopDrawing}
78
- @touchmove=${this.draw}
83
+ @pointerdown=${this.startDrawing}
84
+ @pointerup=${this.stopDrawing}
85
+ @pointermove=${this.draw}
86
+ @pointerleave=${this.stopDrawing}
79
87
  ></canvas>
80
88
  <div class="controls">
81
89
  <button @click="${this.clearCanvas}">Clear</button>
@@ -98,11 +106,19 @@ export class OxInputSignature extends OxFormField {
98
106
  }
99
107
  }
100
108
 
109
+ updated(changes: PropertyValues<this>) {
110
+ if (changes.has('value')) {
111
+ this.loadSignature(this.value)
112
+ }
113
+ }
114
+
101
115
  openDialog() {
102
- if (this.disabled) return
116
+ if (this.disabled) {
117
+ return
118
+ }
119
+
103
120
  this.dialog.showModal()
104
121
 
105
- // 다이아로그가 열릴 때 현재 value를 캔버스에 그리기
106
122
  if (this.value) {
107
123
  const img = new Image()
108
124
  img.onload = () => {
@@ -121,18 +137,30 @@ export class OxInputSignature extends OxFormField {
121
137
  return
122
138
  }
123
139
 
140
+ event.preventDefault()
141
+ event.stopPropagation()
142
+
124
143
  this.isDrawing = true
125
144
  this.ctx.beginPath()
126
145
  const position = this.getEventPosition(event)
127
146
  this.ctx.moveTo(position.x, position.y)
128
147
  }
129
148
 
130
- stopDrawing() {
149
+ stopDrawing(event: MouseEvent | TouchEvent) {
150
+ event.preventDefault()
151
+ event.stopPropagation()
152
+
131
153
  this.isDrawing = false
132
154
  }
133
155
 
134
156
  draw(event: MouseEvent | TouchEvent) {
135
- if (!this.isDrawing) return
157
+ if (!this.isDrawing) {
158
+ return
159
+ }
160
+
161
+ event.preventDefault()
162
+ event.stopPropagation()
163
+
136
164
  const position = this.getEventPosition(event)
137
165
  this.ctx.lineTo(position.x, position.y)
138
166
  this.ctx.stroke()
@@ -149,8 +177,8 @@ export class OxInputSignature extends OxFormField {
149
177
  this.closeDialog()
150
178
  }
151
179
 
152
- loadSignature(dataUrl: string) {
153
- this.previewDiv.style.backgroundImage = `url(${dataUrl})`
180
+ loadSignature(dataUrl: string | null) {
181
+ this.previewDiv.style.backgroundImage = dataUrl ? `url(${dataUrl})` : 'none'
154
182
  }
155
183
 
156
184
  getEventPosition(event: MouseEvent | TouchEvent) {
@@ -0,0 +1,246 @@
1
+ import { css, html, PropertyValues } from 'lit'
2
+ import { customElement, property, query, state } from 'lit/decorators.js'
3
+ import { OxFormField } from './ox-form-field'
4
+
5
+ type Card = {
6
+ name: string
7
+ image: string
8
+ }
9
+
10
+ @customElement('ox-select-floor')
11
+ export class OxSelectFloor extends OxFormField {
12
+ static styles = [
13
+ css`
14
+ :host {
15
+ display: block;
16
+ position: relative;
17
+ overflow: hidden;
18
+ height: 100%;
19
+
20
+ --ox-select-floor-rotate-x: 60deg;
21
+ --ox-select-floor-rotate-x-active: 40deg;
22
+ --ox-select-floor-perspective: 1200px;
23
+ }
24
+
25
+ .carousel-container {
26
+ position: relative;
27
+ width: 100%;
28
+ overflow: hidden;
29
+ user-select: none;
30
+ }
31
+
32
+ .card {
33
+ position: absolute;
34
+ bottom: 0;
35
+ width: 100%;
36
+ background-color: white;
37
+ transition:
38
+ transform 0.3s ease,
39
+ opacity 0.3s ease,
40
+ box-shadow 0.3s ease,
41
+ border 0.3s ease;
42
+ transform-origin: bottom;
43
+ transform: perspective(var(--ox-select-floor-perspective)) rotateX(var(--ox-select-floor-rotate-x));
44
+ opacity: 0.5;
45
+ border: 2px solid transparent;
46
+ border-radius: 12px;
47
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
48
+ }
49
+
50
+ .card img {
51
+ width: 100%;
52
+ height: auto;
53
+ display: block;
54
+ pointer-events: none;
55
+ border-radius: 12px;
56
+ }
57
+
58
+ .selected {
59
+ opacity: 0.8;
60
+ z-index: 1;
61
+ border: 4px solid #3b82f6;
62
+ box-shadow: 0 8px 16px rgba(59, 130, 246, 0.4);
63
+ }
64
+
65
+ .selected.active {
66
+ opacity: 1;
67
+ z-index: 2;
68
+ transform: perspective(var(--ox-select-floor-perspective)) rotateX(var(--ox-select-floor-rotate-x-active));
69
+ box-shadow: 0 12px 24px rgba(59, 130, 246, 0.4);
70
+ }
71
+
72
+ [template-container] {
73
+ position: absolute;
74
+ right: 10px;
75
+ z-index: 1;
76
+ }
77
+ `
78
+ ]
79
+
80
+ @property({ type: Array }) cards: Card[] = []
81
+ @property({ type: String }) value?: string
82
+ @property({ type: Number }) bottomLimit = 70
83
+ @property({ type: Number }) interval = 0
84
+
85
+ @state() private selectedIndex = -1
86
+ @state() private activeIndex: number | null = null
87
+ @query('.carousel-container') private carouselContainer!: HTMLDivElement
88
+
89
+ private isDragging = false
90
+ private lastMouseY = 0
91
+
92
+ render() {
93
+ const length = this.cards.length
94
+ const cards = this.cards
95
+ const interval = this.interval
96
+
97
+ return html`
98
+ <div
99
+ class="carousel-container"
100
+ @wheel=${interval ? () => {} : this.handleWheel}
101
+ @pointerdown=${this.handlePointerDown}
102
+ @pointermove=${this.handlePointerMove}
103
+ @pointerup=${this.handlePointerUp}
104
+ @pointerleave=${this.handlePointerLeave}
105
+ style=${interval ? `height: ${interval * length + 200}px;` : 'height: 100%;'}
106
+ >
107
+ ${cards.map(({ image, name }, index) => {
108
+ return html`
109
+ <div
110
+ class="card ${this.getClassForCard(index)} ${this.isActive(index) ? 'active' : ''}"
111
+ style=${`bottom: ${interval ? interval * index + 'px' : (this.bottomLimit * index) / length + '%'};`}
112
+ @click=${() => {
113
+ this.selectCard(index)
114
+ this.toggleActiveCard(index)
115
+ }}
116
+ >
117
+ <img src="${image}" @load=${(e: Event) => this.adjustCardHeight(e, index)} />
118
+ </div>
119
+ `
120
+ })}
121
+ ${cards.map(({ image, name }, index) => {
122
+ return html`
123
+ <div
124
+ style=${`bottom: ${interval ? interval * index + 'px' : (this.bottomLimit * index) / length + '%'};`}
125
+ @click=${() => this.selectCard(index)}
126
+ template-container
127
+ >
128
+ <slot name="template-${index}"></slot>
129
+ </div>
130
+ `
131
+ })}
132
+ </div>
133
+ `
134
+ }
135
+
136
+ updated(changes: PropertyValues<this>) {
137
+ if (changes.has('value')) {
138
+ if (this.value) {
139
+ this.selectedIndex = this.cards.findIndex(card => card.name == this.value)
140
+ } else {
141
+ this.selectedIndex = -1
142
+ }
143
+ }
144
+ }
145
+
146
+ firstUpdated() {
147
+ this.scrollToSelectedCard()
148
+ }
149
+
150
+ getClassForCard(index: number) {
151
+ return index === this.selectedIndex ? 'selected' : 'compressed'
152
+ }
153
+
154
+ isActive(index: number): boolean {
155
+ return this.activeIndex === index
156
+ }
157
+
158
+ handleWheel(event: WheelEvent) {
159
+ event.preventDefault()
160
+ const delta = Math.sign(event.deltaY)
161
+ this.updateSelectedIndex(this.selectedIndex + delta)
162
+ }
163
+
164
+ handlePointerDown(event: PointerEvent) {
165
+ event.preventDefault()
166
+
167
+ this.isDragging = true
168
+ this.lastMouseY = event.clientY
169
+ }
170
+
171
+ handlePointerMove(event: PointerEvent) {
172
+ if (!this.isDragging) {
173
+ return
174
+ }
175
+
176
+ event.preventDefault()
177
+
178
+ const deltaY = event.clientY - this.lastMouseY
179
+
180
+ if (!this.lastMouseY) {
181
+ this.lastMouseY = event.clientY
182
+ }
183
+
184
+ if (Math.abs(deltaY) > 30) {
185
+ this.lastMouseY = event.clientY
186
+ const direction = deltaY > 0 ? -1 : 1
187
+ this.updateSelectedIndex(this.selectedIndex + direction)
188
+ }
189
+ }
190
+
191
+ handlePointerUp(event: PointerEvent) {
192
+ event.preventDefault()
193
+ this.isDragging = false
194
+ }
195
+
196
+ handlePointerLeave(event: PointerEvent) {
197
+ event.preventDefault()
198
+
199
+ this.isDragging = false
200
+ }
201
+
202
+ private toggleActiveCard(index: number) {
203
+ if (this.activeIndex === index) {
204
+ this.activeIndex = null
205
+ } else {
206
+ this.activeIndex = index
207
+ }
208
+ }
209
+
210
+ private updateSelectedIndex(newIndex: number) {
211
+ this.activeIndex = null
212
+
213
+ this.selectedIndex = Math.max(-1, Math.min(newIndex, this.cards.length - 1))
214
+ this.scrollToSelectedCard()
215
+ }
216
+
217
+ private scrollToSelectedCard() {
218
+ const cardHeight = 320
219
+ const targetScrollTop = this.selectedIndex * cardHeight - (window.innerHeight / 2 - cardHeight / 2)
220
+
221
+ this.carouselContainer.scrollTo({ top: targetScrollTop, behavior: 'smooth' })
222
+ }
223
+
224
+ private selectCard(index: number) {
225
+ this.selectedIndex = index
226
+ this.notifySelection()
227
+ this.scrollToSelectedCard()
228
+ }
229
+
230
+ private notifySelection() {
231
+ this.value = this.selectedIndex !== -1 ? this.cards[this.selectedIndex]?.name : undefined
232
+
233
+ this.dispatchEvent(
234
+ new CustomEvent('change', {
235
+ detail: this.value
236
+ })
237
+ )
238
+ }
239
+
240
+ private adjustCardHeight(e: Event, index: number) {
241
+ const imgElement = e.target as HTMLImageElement
242
+ const aspectRatio = imgElement.naturalWidth / imgElement.naturalHeight
243
+ const newHeight = imgElement.offsetWidth / aspectRatio
244
+ imgElement.style.height = `${newHeight}px`
245
+ }
246
+ }