@operato/input 8.0.0-alpha.10 → 8.0.0-alpha.19

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 CHANGED
@@ -3,6 +3,15 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [8.0.0-alpha.19](https://github.com/hatiolab/operato/compare/v8.0.0-alpha.18...v8.0.0-alpha.19) (2024-10-04)
7
+
8
+
9
+ ### :rocket: New Features
10
+
11
+ * ox-select-floor input component ([3d5c53e](https://github.com/hatiolab/operato/commit/3d5c53e8ecac718b3713fc244c36739c977f5dcf))
12
+
13
+
14
+
6
15
  ## [8.0.0-alpha.10](https://github.com/hatiolab/operato/compare/v8.0.0-alpha.9...v8.0.0-alpha.10) (2024-09-18)
7
16
 
8
17
 
@@ -0,0 +1,38 @@
1
+ import { PropertyValues } from 'lit';
2
+ import { OxFormField } from './ox-form-field';
3
+ type Card = {
4
+ name: string;
5
+ image: string;
6
+ };
7
+ export declare class OxSelectFloor extends OxFormField {
8
+ static styles: import("lit").CSSResult[];
9
+ cards: Card[];
10
+ value?: string;
11
+ bottomLimit: number;
12
+ private selectedIndex;
13
+ private activeIndex;
14
+ private carouselContainer;
15
+ private isDragging;
16
+ private lastTouchY;
17
+ private lastMouseY;
18
+ render(): import("lit-html").TemplateResult<1>;
19
+ updated(changes: PropertyValues<this>): void;
20
+ firstUpdated(): void;
21
+ getClassForCard(index: number): "selected" | "compressed";
22
+ isActive(index: number): boolean;
23
+ handleWheel(event: WheelEvent): void;
24
+ handleTouchStart(event: TouchEvent): void;
25
+ handleTouchMove(event: TouchEvent): void;
26
+ handleTouchEnd(): void;
27
+ handleMouseDown(event: MouseEvent): void;
28
+ handleMouseMove(event: MouseEvent): void;
29
+ handleMouseUp(): void;
30
+ handleMouseLeave(): void;
31
+ private toggleActiveCard;
32
+ private updateSelectedIndex;
33
+ private scrollToSelectedCard;
34
+ private selectCard;
35
+ private _notifySelection;
36
+ private adjustCardHeight;
37
+ }
38
+ export {};
@@ -0,0 +1,246 @@
1
+ import { __decorate } from "tslib";
2
+ import { css, html } from 'lit';
3
+ import { customElement, property, query, state } from 'lit/decorators.js';
4
+ import { OxFormField } from './ox-form-field';
5
+ let OxSelectFloor = class OxSelectFloor extends OxFormField {
6
+ constructor() {
7
+ super(...arguments);
8
+ this.cards = [];
9
+ this.bottomLimit = 70;
10
+ this.selectedIndex = 0;
11
+ this.activeIndex = null;
12
+ this.isDragging = false;
13
+ this.lastTouchY = 0;
14
+ this.lastMouseY = 0;
15
+ }
16
+ static { this.styles = [
17
+ css `
18
+ :host {
19
+ display: block;
20
+ position: relative;
21
+ overflow: hidden;
22
+ height: 100%;
23
+
24
+ --ox-select-floor-rotate-x: 60deg;
25
+ --ox-select-floor-rotate-x-active: 40deg;
26
+ --ox-select-floor-perspective: 1200px;
27
+ }
28
+
29
+ .carousel-container {
30
+ position: relative;
31
+ height: 100%;
32
+ width: 100%;
33
+ overflow: hidden;
34
+ user-select: none;
35
+ }
36
+
37
+ .card {
38
+ position: absolute;
39
+ bottom: 0;
40
+ width: 100%;
41
+ background-color: white;
42
+ transition:
43
+ transform 0.3s ease,
44
+ opacity 0.3s ease,
45
+ box-shadow 0.3s ease,
46
+ border 0.3s ease;
47
+ transform-origin: bottom;
48
+ transform: perspective(var(--ox-select-floor-perspective)) rotateX(var(--ox-select-floor-rotate-x));
49
+ opacity: 0.5;
50
+ border: 2px solid transparent;
51
+ border-radius: 12px;
52
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
53
+ }
54
+
55
+ .card img {
56
+ width: 100%;
57
+ height: auto;
58
+ display: block;
59
+ pointer-events: none;
60
+ border-radius: 12px;
61
+ }
62
+
63
+ .selected {
64
+ z-index: 10;
65
+ opacity: 0.8;
66
+ border: 4px solid #3b82f6;
67
+ box-shadow: 0 8px 16px rgba(59, 130, 246, 0.4);
68
+ }
69
+
70
+ .selected.active {
71
+ opacity: 1;
72
+ transform: perspective(var(--ox-select-floor-perspective)) rotateX(var(--ox-select-floor-rotate-x-active));
73
+ box-shadow: 0 12px 24px rgba(59, 130, 246, 0.4);
74
+ }
75
+
76
+ [template-container] {
77
+ position: absolute;
78
+ right: 10px;
79
+ z-index: 20;
80
+ }
81
+ `
82
+ ]; }
83
+ render() {
84
+ const length = this.cards.length;
85
+ return html `
86
+ <div
87
+ class="carousel-container"
88
+ @wheel=${this.handleWheel}
89
+ @mousedown=${this.handleMouseDown}
90
+ @mousemove=${this.handleMouseMove}
91
+ @mouseup=${this.handleMouseUp}
92
+ @mouseleave=${this.handleMouseLeave}
93
+ @touchstart=${this.handleTouchStart}
94
+ @touchmove=${this.handleTouchMove}
95
+ @touchend=${this.handleTouchEnd}
96
+ >
97
+ ${this.cards.map(({ image, name }, index) => {
98
+ const reverse = length - index - 1;
99
+ return html `
100
+ <div
101
+ class="card ${this.getClassForCard(reverse)} ${this.isActive(reverse) ? 'active' : ''}"
102
+ style="bottom: ${(this.bottomLimit * reverse) / length}%;"
103
+ @click=${() => this.selectCard(reverse)}
104
+ @tap=${() => this.toggleActiveCard(reverse)}
105
+ >
106
+ <img src="${image}" @load=${(e) => this.adjustCardHeight(e, reverse)} />
107
+ </div>
108
+ `;
109
+ })}
110
+ ${this.cards.map(({ image, name }, index) => {
111
+ const reverse = length - index - 1;
112
+ return html `
113
+ <div
114
+ style="bottom: ${(this.bottomLimit * reverse) / length}%;"
115
+ @click=${() => this.selectCard(reverse)}
116
+ template-container
117
+ >
118
+ <slot name="template-${reverse}"></slot>
119
+ </div>
120
+ `;
121
+ })}
122
+ </div>
123
+ `;
124
+ }
125
+ updated(changes) {
126
+ if (changes.has('value')) {
127
+ if (this.value) {
128
+ this.selectedIndex = this.cards.findIndex(card => card.name == this.value);
129
+ }
130
+ else {
131
+ this.selectedIndex = -1;
132
+ }
133
+ }
134
+ }
135
+ firstUpdated() {
136
+ this.scrollToSelectedCard();
137
+ }
138
+ getClassForCard(index) {
139
+ return index === this.selectedIndex ? 'selected' : 'compressed';
140
+ }
141
+ isActive(index) {
142
+ return this.activeIndex === index;
143
+ }
144
+ handleWheel(event) {
145
+ event.preventDefault();
146
+ const delta = Math.sign(event.deltaY);
147
+ this.updateSelectedIndex(this.selectedIndex + delta);
148
+ }
149
+ handleTouchStart(event) {
150
+ this.lastTouchY = event.touches[0].clientY;
151
+ }
152
+ handleTouchMove(event) {
153
+ const touch = event.touches[0];
154
+ const deltaY = touch.clientY - this.lastTouchY;
155
+ this.lastTouchY = touch.clientY;
156
+ if (Math.abs(deltaY) > 30) {
157
+ const direction = deltaY < 0 ? -1 : 1;
158
+ this.updateSelectedIndex(this.selectedIndex + direction);
159
+ }
160
+ }
161
+ handleTouchEnd() {
162
+ this.isDragging = false;
163
+ }
164
+ handleMouseDown(event) {
165
+ this.isDragging = true;
166
+ this.lastMouseY = event.clientY;
167
+ }
168
+ handleMouseMove(event) {
169
+ if (!this.isDragging) {
170
+ return;
171
+ }
172
+ const deltaY = event.clientY - this.lastMouseY;
173
+ if (!this.lastMouseY) {
174
+ this.lastMouseY = event.clientY;
175
+ }
176
+ if (Math.abs(deltaY) > 30) {
177
+ this.lastMouseY = event.clientY;
178
+ const direction = deltaY > 0 ? -1 : 1;
179
+ this.updateSelectedIndex(this.selectedIndex + direction);
180
+ }
181
+ }
182
+ handleMouseUp() {
183
+ this.isDragging = false;
184
+ }
185
+ handleMouseLeave() {
186
+ this.isDragging = false;
187
+ }
188
+ toggleActiveCard(index) {
189
+ if (this.activeIndex === index) {
190
+ this.activeIndex = null;
191
+ }
192
+ else {
193
+ this.activeIndex = index;
194
+ }
195
+ }
196
+ updateSelectedIndex(newIndex) {
197
+ this.activeIndex = null;
198
+ this.selectedIndex = Math.max(0, Math.min(newIndex, this.cards.length - 1));
199
+ this.scrollToSelectedCard();
200
+ }
201
+ scrollToSelectedCard() {
202
+ const cardHeight = 320;
203
+ const targetScrollTop = this.selectedIndex * cardHeight - (window.innerHeight / 2 - cardHeight / 2);
204
+ this.carouselContainer.scrollTo({ top: targetScrollTop, behavior: 'smooth' });
205
+ }
206
+ selectCard(index) {
207
+ this.selectedIndex = index;
208
+ this._notifySelection();
209
+ this.scrollToSelectedCard();
210
+ }
211
+ _notifySelection() {
212
+ this.value = this.selectedIndex !== -1 ? this.cards[this.selectedIndex]?.name : undefined;
213
+ this.dispatchEvent(new CustomEvent('change', {
214
+ detail: this.value
215
+ }));
216
+ }
217
+ adjustCardHeight(e, index) {
218
+ const imgElement = e.target;
219
+ const aspectRatio = imgElement.naturalWidth / imgElement.naturalHeight;
220
+ const newHeight = imgElement.offsetWidth / aspectRatio;
221
+ imgElement.style.height = `${newHeight}px`;
222
+ }
223
+ };
224
+ __decorate([
225
+ property({ type: Array })
226
+ ], OxSelectFloor.prototype, "cards", void 0);
227
+ __decorate([
228
+ property({ type: String })
229
+ ], OxSelectFloor.prototype, "value", void 0);
230
+ __decorate([
231
+ property({ type: Number })
232
+ ], OxSelectFloor.prototype, "bottomLimit", void 0);
233
+ __decorate([
234
+ state()
235
+ ], OxSelectFloor.prototype, "selectedIndex", void 0);
236
+ __decorate([
237
+ state()
238
+ ], OxSelectFloor.prototype, "activeIndex", void 0);
239
+ __decorate([
240
+ query('.carousel-container')
241
+ ], OxSelectFloor.prototype, "carouselContainer", void 0);
242
+ OxSelectFloor = __decorate([
243
+ customElement('ox-select-floor')
244
+ ], OxSelectFloor);
245
+ export { OxSelectFloor };
246
+ //# sourceMappingURL=ox-select-floor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ox-select-floor.js","sourceRoot":"","sources":["../../src/ox-select-floor.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, PropertyValues } from 'lit'\nimport { customElement, property, query, state } from 'lit/decorators.js'\nimport { OxFormField } from './ox-form-field'\n\ntype Card = {\n name: string\n image: string\n}\n\n@customElement('ox-select-floor')\nexport class OxSelectFloor extends OxFormField {\n static styles = [\n css`\n :host {\n display: block;\n position: relative;\n overflow: hidden;\n height: 100%;\n\n --ox-select-floor-rotate-x: 60deg;\n --ox-select-floor-rotate-x-active: 40deg;\n --ox-select-floor-perspective: 1200px;\n }\n\n .carousel-container {\n position: relative;\n height: 100%;\n width: 100%;\n overflow: hidden;\n user-select: none;\n }\n\n .card {\n position: absolute;\n bottom: 0;\n width: 100%;\n background-color: white;\n transition:\n transform 0.3s ease,\n opacity 0.3s ease,\n box-shadow 0.3s ease,\n border 0.3s ease;\n transform-origin: bottom;\n transform: perspective(var(--ox-select-floor-perspective)) rotateX(var(--ox-select-floor-rotate-x));\n opacity: 0.5;\n border: 2px solid transparent;\n border-radius: 12px;\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n }\n\n .card img {\n width: 100%;\n height: auto;\n display: block;\n pointer-events: none;\n border-radius: 12px;\n }\n\n .selected {\n z-index: 10;\n opacity: 0.8;\n border: 4px solid #3b82f6;\n box-shadow: 0 8px 16px rgba(59, 130, 246, 0.4);\n }\n\n .selected.active {\n opacity: 1;\n transform: perspective(var(--ox-select-floor-perspective)) rotateX(var(--ox-select-floor-rotate-x-active));\n box-shadow: 0 12px 24px rgba(59, 130, 246, 0.4);\n }\n\n [template-container] {\n position: absolute;\n right: 10px;\n z-index: 20;\n }\n `\n ]\n\n @property({ type: Array }) cards: Card[] = []\n @property({ type: String }) value?: string\n @property({ type: Number }) bottomLimit = 70\n\n @state() private selectedIndex = 0\n @state() private activeIndex: number | null = null\n @query('.carousel-container') private carouselContainer!: HTMLDivElement\n\n private isDragging = false\n private lastTouchY = 0\n private lastMouseY = 0\n\n render() {\n const length = this.cards.length\n\n return html`\n <div\n class=\"carousel-container\"\n @wheel=${this.handleWheel}\n @mousedown=${this.handleMouseDown}\n @mousemove=${this.handleMouseMove}\n @mouseup=${this.handleMouseUp}\n @mouseleave=${this.handleMouseLeave}\n @touchstart=${this.handleTouchStart}\n @touchmove=${this.handleTouchMove}\n @touchend=${this.handleTouchEnd}\n >\n ${this.cards.map(({ image, name }, index) => {\n const reverse = length - index - 1\n return html`\n <div\n class=\"card ${this.getClassForCard(reverse)} ${this.isActive(reverse) ? 'active' : ''}\"\n style=\"bottom: ${(this.bottomLimit * reverse) / length}%;\"\n @click=${() => this.selectCard(reverse)}\n @tap=${() => this.toggleActiveCard(reverse)}\n >\n <img src=\"${image}\" @load=${(e: Event) => this.adjustCardHeight(e, reverse)} />\n </div>\n `\n })}\n ${this.cards.map(({ image, name }, index) => {\n const reverse = length - index - 1\n return html`\n <div\n style=\"bottom: ${(this.bottomLimit * reverse) / length}%;\"\n @click=${() => this.selectCard(reverse)}\n template-container\n >\n <slot name=\"template-${reverse}\"></slot>\n </div>\n `\n })}\n </div>\n `\n }\n\n updated(changes: PropertyValues<this>) {\n if (changes.has('value')) {\n if (this.value) {\n this.selectedIndex = this.cards.findIndex(card => card.name == this.value)\n } else {\n this.selectedIndex = -1\n }\n }\n }\n\n firstUpdated() {\n this.scrollToSelectedCard()\n }\n\n getClassForCard(index: number) {\n return index === this.selectedIndex ? 'selected' : 'compressed'\n }\n\n isActive(index: number): boolean {\n return this.activeIndex === index\n }\n\n handleWheel(event: WheelEvent) {\n event.preventDefault()\n const delta = Math.sign(event.deltaY)\n this.updateSelectedIndex(this.selectedIndex + delta)\n }\n\n handleTouchStart(event: TouchEvent) {\n this.lastTouchY = event.touches[0].clientY\n }\n\n handleTouchMove(event: TouchEvent) {\n const touch = event.touches[0]\n const deltaY = touch.clientY - this.lastTouchY\n this.lastTouchY = touch.clientY\n\n if (Math.abs(deltaY) > 30) {\n const direction = deltaY < 0 ? -1 : 1\n this.updateSelectedIndex(this.selectedIndex + direction)\n }\n }\n\n handleTouchEnd() {\n this.isDragging = false\n }\n\n handleMouseDown(event: MouseEvent) {\n this.isDragging = true\n this.lastMouseY = event.clientY\n }\n\n handleMouseMove(event: MouseEvent) {\n if (!this.isDragging) {\n return\n }\n\n const deltaY = event.clientY - this.lastMouseY\n\n if (!this.lastMouseY) {\n this.lastMouseY = event.clientY\n }\n\n if (Math.abs(deltaY) > 30) {\n this.lastMouseY = event.clientY\n const direction = deltaY > 0 ? -1 : 1\n this.updateSelectedIndex(this.selectedIndex + direction)\n }\n }\n\n handleMouseUp() {\n this.isDragging = false\n }\n\n handleMouseLeave() {\n this.isDragging = false\n }\n\n private toggleActiveCard(index: number) {\n if (this.activeIndex === index) {\n this.activeIndex = null\n } else {\n this.activeIndex = index\n }\n }\n\n private updateSelectedIndex(newIndex: number) {\n this.activeIndex = null\n\n this.selectedIndex = Math.max(0, Math.min(newIndex, this.cards.length - 1))\n this.scrollToSelectedCard()\n }\n\n private scrollToSelectedCard() {\n const cardHeight = 320\n const targetScrollTop = this.selectedIndex * cardHeight - (window.innerHeight / 2 - cardHeight / 2)\n this.carouselContainer.scrollTo({ top: targetScrollTop, behavior: 'smooth' })\n }\n\n private selectCard(index: number) {\n this.selectedIndex = index\n this._notifySelection()\n this.scrollToSelectedCard()\n }\n\n private _notifySelection() {\n this.value = this.selectedIndex !== -1 ? this.cards[this.selectedIndex]?.name : undefined\n\n this.dispatchEvent(\n new CustomEvent('change', {\n detail: this.value\n })\n )\n }\n\n private adjustCardHeight(e: Event, index: number) {\n const imgElement = e.target as HTMLImageElement\n const aspectRatio = imgElement.naturalWidth / imgElement.naturalHeight\n const newHeight = imgElement.offsetWidth / aspectRatio\n imgElement.style.height = `${newHeight}px`\n }\n}\n"]}