1/*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16export class LitSlicer extends HTMLElement {
17  static get observedAttributes(): string[] {
18    return ['direction']; //direction = 'horizontal'或者'vertical'
19  }
20
21  constructor() {
22    super();
23    const shadowRoot = this.attachShadow({ mode: 'open' });
24    shadowRoot.innerHTML = `
25        <style>
26        :host{  
27            display: flex;
28        }
29       
30        #root{
31            display: flex;
32            width: 100%;
33            height: 100%;
34            overflow: auto;
35        }
36        </style>
37        <div id="root"  style="${this.style}">
38            <slot></slot>
39        </div>
40        `;
41  }
42
43  set direction(val: unknown) {
44    // @ts-ignore
45    if (val.startsWith('h')) {
46      this.shadowRoot!.querySelector('div')!.style.flexDirection = 'row'; // @ts-ignore
47    } else if (val.startsWith('v')) {
48      this.shadowRoot!.querySelector('div')!.style.flexDirection = 'column';
49    }
50  }
51
52  connectedCallback(): void {}
53
54  disconnectedCallback(): void {}
55
56  attributeChangedCallback(name: unknown, oldValue: unknown, newValue: unknown): void {
57    // @ts-ignore
58    (this as unknown)[name] = newValue;
59  }
60  // @ts-ignore
61  set style(v: unknown) {}
62}
63
64if (!customElements.get('lit-slicer')) {
65  // @ts-ignore
66  customElements.define('lit-slicer', LitSlicer);
67}
68
69export class LitSlicerTrack extends HTMLElement {
70  private line: HTMLElement | null | undefined;
71  private draging: boolean = false;
72  private normalWidth: number = 0;
73  private rightWidth: number = 0;
74
75  static get observedAttributes(): string[] {
76    return ['range-left', 'range-right'];
77  }
78
79  get rangeLeft(): number {
80    return parseInt(this.getAttribute('range-left') || '200');
81  }
82
83  set rangeLeft(val: number) {
84    this.setAttribute('range-left', `${val}`);
85  }
86
87  get rangeRight(): number {
88    return parseInt(this.getAttribute('range-right') || '300');
89  }
90
91  set rangeRight(val: number) {
92    this.setAttribute('range-right', `${val}`);
93  }
94
95  constructor() {
96    super();
97    const shadowRoot = this.attachShadow({ mode: 'open' });
98    shadowRoot.innerHTML = `
99        <style>
100        :host{ 
101            flex
102        }
103        .rootH{
104            width:var(--lit-slicer-track--width,5px);
105            background-color: var(--lit-slicer-track--background-color,#d1d1d1);
106            height: 100%;
107            cursor: ew-resize;
108        }
109        .rootV{
110            height:var(--lit-slicer-track--height,5px);
111            background-color: var(--lit-slicer-track--background-color,#d1d1d1);
112            width: 100%;
113            cursor: ns-resize;
114        }
115        </style>
116        <div id="root">
117        </div>
118        `;
119  }
120
121  //当 custom element首次被插入文档DOM时,被调用。
122  connectedCallback(): void {
123    this.line = this.shadowRoot?.querySelector('#root');
124    let parentDirection = this.parentElement!.getAttribute('direction') || 'horizontal';
125    if (parentDirection.startsWith('h')) {
126      this.line!.className = 'rootH';
127      let previousElementSibling = this.previousElementSibling as HTMLElement;
128      let nextElementSibling = this.nextElementSibling as HTMLElement;
129      let preX: number;
130      let preY: number;
131      let preWidth: number;
132      let nextWidth: number;
133      this.line!.onmousedown = (e): void => {
134        this.draging = true;
135        preX = e.pageX;
136        preWidth = previousElementSibling!.clientWidth;
137        nextWidth = nextElementSibling!.clientWidth;
138        if (this.normalWidth === 0) {
139          this.normalWidth = previousElementSibling!.clientWidth;
140          this.rightWidth = nextElementSibling!.clientWidth;
141        }
142        previousElementSibling!.style.width = preWidth + 'px';
143        nextElementSibling!.style.width = nextWidth + 'px';
144        document.body.style.userSelect = 'none';
145        document.body.style.webkitUserSelect = 'none';
146        // @ts-ignore
147        document.body.style.msUserSelect = 'none';
148        document.onmousemove = (e1): void => {
149          if (this.draging) {
150            if (
151              preWidth + e1.pageX - preX >= this.normalWidth - this.rangeLeft &&
152              preWidth + e1.pageX - preX <= this.normalWidth + this.rangeRight
153            ) {
154              previousElementSibling!.style.width = preWidth + e1.pageX - preX + 'px';
155              nextElementSibling!.style.width = nextWidth + preX - e1.pageX + 'px';
156            }
157          }
158        };
159        document.onmouseleave = (e2): void => {
160          this.draging = false;
161          document.body.style.userSelect = 'auto';
162          document.body.style.webkitUserSelect = 'auto';
163          // @ts-ignore
164          document.body.style.msUserSelect = 'auto';
165        };
166        document.onmouseup = (e3): void => {
167          this.draging = false;
168          document.body.style.userSelect = 'auto';
169          document.body.style.webkitUserSelect = 'auto';
170          // @ts-ignore
171          document.body.style.msUserSelect = 'auto';
172        };
173      };
174    } else {
175      this.isDirection();
176    }
177  }
178
179  isDirection(): void {
180    this.line!.className = 'rootV';
181    let previousElementSibling = this.previousElementSibling as HTMLElement;
182    let preY: number;
183    let preHeight: number;
184    this.line!.onmousedown = (e): void => {
185      this.draging = true;
186      preY = e.pageY;
187      preHeight = previousElementSibling?.clientHeight;
188      previousElementSibling!.style!.height = preHeight + 'px';
189      document.onmousemove = (e1): void => {
190        if (this.draging) {
191          previousElementSibling.style.height = preHeight + e1.pageY - preY + 'px';
192        }
193      };
194      document.onmouseleave = (e2): void => {
195        this.draging = false;
196      };
197      document.onmouseup = (e3): void => {
198        this.draging = false;
199      };
200    };
201  }
202
203  //当 custom element从文档DOM中删除时,被调用。
204  disconnectedCallback(): void {
205    this.line!.onmousedown = null;
206  }
207
208  //当 custom element被移动到新的文档时,被调用。
209  adoptedCallback(): void {}
210
211  //当 custom element增加、删除、修改自身属性时,被调用。
212  attributeChangedCallback(name: unknown, oldValue: unknown, newValue: unknown): void {}
213}
214
215if (!customElements.get('lit-slicer-track')) {
216  customElements.define('lit-slicer-track', LitSlicerTrack);
217}
218