kempo-ui 0.4.0 → 0.4.1

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/bin/get_icon.js CHANGED
File without changes
File without changes
package/bin/icon.js CHANGED
File without changes
package/bin/list_icons.js CHANGED
File without changes
@@ -1,7 +1,19 @@
1
- import{html as e,css as t}from"../lit-all.min.js";import i from"./ShadowComponent.js";import s from"../utils/drag.js";export default class r extends i{static properties={resizing:{type:Boolean,reflect:!0},stacked:{type:Boolean,reflect:!0},stackWidth:{type:Number,attribute:"stack-width"},direction:{type:String,reflect:!0},persistentId:{type:String,reflect:!0,attribute:"persistent-id"}};constructor(){super(),this.resizing=!1,this.stacked=!1,this.stackWidth=0,this.direction="horizontal",this.persistentId=null,this.dragStartSize=0,this.dragCleanup=()=>{},this.resizeObserver=null}firstUpdated(){if(super.firstUpdated(),this.setupDragHandler(),this.setupResizeObserver(),this.persistentId&&window?.localStorage){const e=window.localStorage.getItem(`split-persistent-id-${this.persistentId}`);e&&this.setSize(e)}}disconnectedCallback(){super.disconnectedCallback(),this.dragCleanup(),this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=null)}handleDragStart=()=>{this.resizing=!0,this.dragStartSize=Math.round(this.shadowRoot.getElementById("pane-1").getBoundingClientRect()["vertical"===this.direction?"height":"width"]),this.dispatchEvent(new CustomEvent("resizestart",{detail:{startSize:this.dragStartSize},bubbles:!0}))};handleDrag=({x:e,y:t})=>{const i="vertical"===this.direction?t:e,s=`${this.dragStartSize+i}px`;this.setSize(s),this.dispatchEvent(new CustomEvent("resize",{detail:{size:s},bubbles:!0}))};handleDragEnd=({x:e,y:t})=>{this.resizing=!1;const i="vertical"===this.direction?t:e,s=`${this.dragStartSize+i}px`;this.setSize(s),this.persistentId&&window?.localStorage&&window.localStorage.setItem(`split-persistent-id-${this.persistentId}`,s),this.dispatchEvent(new CustomEvent("resizeend",{detail:{size:s},bubbles:!0}))};setSize(e){this.style.setProperty("--pane_1_size",e)}setupDragHandler(){const e=this.shadowRoot.getElementById("divider-handle");e&&(this.dragCleanup=s({element:e,callback:this.handleDrag,startCallback:this.handleDragStart,endCallback:this.handleDragEnd}))}setupResizeObserver(){this.resizeObserver=new ResizeObserver(e=>{for(const t of e){const e=t.contentRect.width;this.stacked=e<=this.stackWidth}}),this.resizeObserver.observe(this)}static styles=t`
1
+ import{html as e,css as t}from"../lit-all.min.js";import i from"./ShadowComponent.js";import s from"../utils/drag.js";import{boolExists as r}from"../utils/propConverters.js";export default class d extends i{static properties={resizing:{type:Boolean,reflect:!0},stacked:{type:Boolean,reflect:!0},stackWidth:{type:Number,attribute:"stack-width"},direction:{type:String,reflect:!0},persistentId:{type:String,reflect:!0,attribute:"persistent-id"},grip:{type:Boolean,reflect:!0,converter:r}};constructor(){super(),this.resizing=!1,this.stacked=!1,this.stackWidth=0,this.direction="horizontal",this.persistentId=null,this.grip=!1,this.dragStartSize=0,this.dragCleanup=()=>{},this.resizeObserver=null}firstUpdated(){if(super.firstUpdated(),this.grip){const e=document.createElement("div");e.style.cssText="position:absolute;visibility:hidden;width:var(--handle_width)",this.shadowRoot.appendChild(e);const t=e.offsetWidth;this.shadowRoot.removeChild(e);const i=t%2==0?t-1:t;this.style.setProperty("--handle_grip_width",`${i}px`)}if(this.setupDragHandler(),this.setupResizeObserver(),this.persistentId&&window?.localStorage){const e=window.localStorage.getItem(`split-persistent-id-${this.persistentId}`);e&&this.setSize(e)}}disconnectedCallback(){super.disconnectedCallback(),this.dragCleanup(),this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=null)}handleDragStart=()=>{this.resizing=!0,this.dragStartSize=Math.round(this.shadowRoot.getElementById("pane-1").getBoundingClientRect()["vertical"===this.direction?"height":"width"]),this.dispatchEvent(new CustomEvent("resizestart",{detail:{startSize:this.dragStartSize},bubbles:!0}))};handleDrag=({x:e,y:t})=>{const i="vertical"===this.direction?t:e,s=`${this.dragStartSize+i}px`;this.setSize(s),this.dispatchEvent(new CustomEvent("resize",{detail:{size:s},bubbles:!0}))};handleDragEnd=({x:e,y:t})=>{this.resizing=!1;const i="vertical"===this.direction?t:e,s=`${this.dragStartSize+i}px`;this.setSize(s),this.persistentId&&window?.localStorage&&window.localStorage.setItem(`split-persistent-id-${this.persistentId}`,s),this.dispatchEvent(new CustomEvent("resizeend",{detail:{size:s},bubbles:!0}))};setSize(e){this.style.setProperty("--pane_1_size",e)}setupDragHandler(){const e=this.shadowRoot.getElementById("divider-handle");e&&(this.dragCleanup=s({element:e,callback:this.handleDrag,startCallback:this.handleDragStart,endCallback:this.handleDragEnd}))}setupResizeObserver(){this.resizeObserver=new ResizeObserver(e=>{for(const t of e){const e=t.contentRect.width;this.stacked=e<=this.stackWidth}}),this.resizeObserver.observe(this)}render(){return e`
2
+ <div id="pane-1" class="pane">
3
+ <slot></slot>
4
+ </div>
5
+ <div id="divider-handle">
6
+ <div id="divider-border">
7
+ ${this.grip?e`<div id="divider-grip"></div>`:""}
8
+ </div>
9
+ </div>
10
+ <div id="pane-2" class="pane">
11
+ <slot name="right"></slot>
12
+ </div>
13
+ `}static styles=t`
2
14
  :host {
3
15
  --pane_1_size: calc((100% - var(--handle_width)) / 2);
4
- --handle_width: 0.5rem;
16
+ --handle_width: 7px;
5
17
  --min_pane_size: 6rem;
6
18
 
7
19
  height: 100%;
@@ -27,6 +39,7 @@ import{html as e,css as t}from"../lit-all.min.js";import i from"./ShadowComponen
27
39
  }
28
40
 
29
41
  #divider-handle {
42
+ position: relative;
30
43
  display: flex;
31
44
  flex-shrink: 0;
32
45
  justify-content: center;
@@ -47,10 +60,21 @@ import{html as e,css as t}from"../lit-all.min.js";import i from"./ShadowComponen
47
60
  }
48
61
 
49
62
  #divider-border {
63
+ position: relative;
50
64
  width: 1px;
51
65
  height: 100%;
52
66
  border-left: 1px solid var(--c_border);
53
67
  }
68
+ #divider-grip {
69
+ position: absolute;
70
+ top: 50%;
71
+ left: 50%;
72
+ transform: translate(-50%, -50%);
73
+ width: var(--handle_grip_width, var(--handle_width));
74
+ height: 2rem;
75
+ border-radius: 0.25rem;
76
+ background-color: var(--c_border);
77
+ }
54
78
 
55
79
  #pane-2 {
56
80
  flex: 1 1;
@@ -105,14 +129,8 @@ import{html as e,css as t}from"../lit-all.min.js";import i from"./ShadowComponen
105
129
  border-left: none;
106
130
  border-top: 1px solid var(--c_border);
107
131
  }
108
- `;render(){return e`
109
- <div id="pane-1" class="pane">
110
- <slot></slot>
111
- </div>
112
- <div id="divider-handle">
113
- <div id="divider-border"></div>
114
- </div>
115
- <div id="pane-2" class="pane">
116
- <slot name="right"></slot>
117
- </div>
118
- `}}customElements.define("k-split",r);
132
+ :host([direction="vertical"]) #divider-grip {
133
+ width: 2rem;
134
+ height: 0.5rem;
135
+ }
136
+ `}customElements.define("k-split",d);
@@ -451,6 +451,7 @@
451
451
  <a href="#resizing">Resizing</a><br />
452
452
  <a href="#verticalSplit">Vertical Split</a><br />
453
453
  <a href="#persistentState">Persistent State</a><br />
454
+ <a href="#grip">Grip</a><br />
454
455
  <h6 class="mt"><a href="#jsRef" class="no-link">JavaScript Reference</a></h6>
455
456
  <a href="#constructor">Constructor</a><br />
456
457
  <a href="#requirements">Requirements</a><br />
@@ -501,11 +502,11 @@
501
502
  <h3>Sizes</h3>
502
503
  <p>Set the CSS Custom Property <code>--pane_1_size</code> to set the initial size of the first pane.</p>
503
504
  <p>Set the CSS Custom Property <code>--min_pane_size</code> to set the minimum size each pane can be.</p>
504
- <p>Set the CSS Custom Property <code>--handle_width</code> to set the size of the handle (the draggable region between the panes).</p>
505
+ <p>Set the CSS Custom Property <code>--handle_width</code> to set the size of the handle (the draggable region between the panes), odd sizes are recommended so it can be centered on the border.</p>
505
506
  <div class="row -mx">
506
507
  <div class="col m-span-12 px">
507
508
  <k-card label="HTML">
508
- <pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">k-split</span><br /> <span class="hljs-attr">style</span>=<span class="hljs-string">"<br /> --pane_1_size: 100px;<br /> --min_pane_size: 100px;<br /> --handle_width: 20px;<br /> height: 10rem<br /> "</span><br /> <span class="hljs-attr">class</span>=<span class="hljs-string">"b"</span><br />&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>left<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"right"</span>&gt;</span>right<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br /><span class="hljs-tag">&lt;/<span class="hljs-name">k-split</span>&gt;</span></code></pre>
509
+ <pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">k-split</span><br /> <span class="hljs-attr">style</span>=<span class="hljs-string">"<br /> --pane_1_size: 100px;<br /> --min_pane_size: 100px;<br /> --handle_width: 19px;<br /> height: 10rem<br /> "</span><br /> <span class="hljs-attr">class</span>=<span class="hljs-string">"b"</span><br />&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>left<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"right"</span>&gt;</span>right<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br /><span class="hljs-tag">&lt;/<span class="hljs-name">k-split</span>&gt;</span></code></pre>
509
510
  </k-card>
510
511
  </div>
511
512
  <div class="col m-span-12 px">
@@ -514,7 +515,7 @@
514
515
  style="
515
516
  --pane_1_size: 100px;
516
517
  --min_pane_size: 100px;
517
- --handle_width: 20px;
518
+ --handle_width: 19px;
518
519
  height: 10rem
519
520
  "
520
521
  class="b"
@@ -583,6 +584,28 @@
583
584
  </div>
584
585
  </div>
585
586
 
587
+ <h3 id="grip"><a href="#grip" class="no-link">Grip</a></h3>
588
+ <p>Add the <code>grip</code> attribute to render a visual grip indicator centered on the divider handle, making it easier to identify the draggable area.</p>
589
+ <div class="row -mx mb">
590
+ <div class="col d-span-6 m-span-12 px">
591
+ <k-card label="HTML">
592
+ <pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">k-split</span> <span class="hljs-attr">grip</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"height: 10rem"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"b mb"</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Left Pane Content<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"right"</span>&gt;</span>Right Pane Content<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br /><span class="hljs-tag">&lt;/<span class="hljs-name">k-split</span>&gt;</span><br /><span class="hljs-tag">&lt;<span class="hljs-name">k-split</span> <span class="hljs-attr">grip</span> <span class="hljs-attr">direction</span>=<span class="hljs-string">"vertical"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"height: 16rem"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"b"</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Top Pane Content<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"right"</span>&gt;</span>Bottom Pane Content<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br /><span class="hljs-tag">&lt;/<span class="hljs-name">k-split</span>&gt;</span></code></pre>
593
+ </k-card>
594
+ </div>
595
+ <div class="col d-span-6 m-span-12 px">
596
+ <k-card label="Results">
597
+ <k-split grip style="height: 10rem" class="b mb">
598
+ <div>Left Pane Content</div>
599
+ <div slot="right">Right Pane Content</div>
600
+ </k-split>
601
+ <k-split grip direction="vertical" style="height: 16rem" class="b">
602
+ <div>Top Pane Content</div>
603
+ <div slot="right">Bottom Pane Content</div>
604
+ </k-split>
605
+ </k-card>
606
+ </div>
607
+ </div>
608
+
586
609
  <h2 id="jsRef">JavaScript Reference</h2>
587
610
 
588
611
  <h3 id="constructor"><a href="#constructor" class="no-link">Constructor</a></h3>
@@ -607,6 +630,8 @@
607
630
  <p>The direction of the split. Can be <code>"horizontal"</code> (default) or <code>"vertical"</code>. Syncs to <code>direction</code> attribute.</p>
608
631
  <h5><code>persistentId<i>: string</i></code></h5>
609
632
  <p>When set, the pane size is saved to <code>localStorage</code> on resize and restored on initialization. Must be unique per split instance. Syncs to <code>persistent-id</code> attribute.</p>
633
+ <h5><code>grip<i>: boolean</i></code></h5>
634
+ <p>When set, renders a visual grip indicator centered on the divider handle. Syncs to <code>grip</code> attribute.</p>
610
635
 
611
636
  <h3 id="cssCustomProperties"><a href="#cssCustomProperties" class="no-link">CSS Custom Properties</a></h3>
612
637
  <h5><code>--pane_1_size</code></h5>
@@ -1,7 +1,19 @@
1
- import{html as e,css as t}from"../lit-all.min.js";import i from"./ShadowComponent.js";import s from"../utils/drag.js";export default class r extends i{static properties={resizing:{type:Boolean,reflect:!0},stacked:{type:Boolean,reflect:!0},stackWidth:{type:Number,attribute:"stack-width"},direction:{type:String,reflect:!0},persistentId:{type:String,reflect:!0,attribute:"persistent-id"}};constructor(){super(),this.resizing=!1,this.stacked=!1,this.stackWidth=0,this.direction="horizontal",this.persistentId=null,this.dragStartSize=0,this.dragCleanup=()=>{},this.resizeObserver=null}firstUpdated(){if(super.firstUpdated(),this.setupDragHandler(),this.setupResizeObserver(),this.persistentId&&window?.localStorage){const e=window.localStorage.getItem(`split-persistent-id-${this.persistentId}`);e&&this.setSize(e)}}disconnectedCallback(){super.disconnectedCallback(),this.dragCleanup(),this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=null)}handleDragStart=()=>{this.resizing=!0,this.dragStartSize=Math.round(this.shadowRoot.getElementById("pane-1").getBoundingClientRect()["vertical"===this.direction?"height":"width"]),this.dispatchEvent(new CustomEvent("resizestart",{detail:{startSize:this.dragStartSize},bubbles:!0}))};handleDrag=({x:e,y:t})=>{const i="vertical"===this.direction?t:e,s=`${this.dragStartSize+i}px`;this.setSize(s),this.dispatchEvent(new CustomEvent("resize",{detail:{size:s},bubbles:!0}))};handleDragEnd=({x:e,y:t})=>{this.resizing=!1;const i="vertical"===this.direction?t:e,s=`${this.dragStartSize+i}px`;this.setSize(s),this.persistentId&&window?.localStorage&&window.localStorage.setItem(`split-persistent-id-${this.persistentId}`,s),this.dispatchEvent(new CustomEvent("resizeend",{detail:{size:s},bubbles:!0}))};setSize(e){this.style.setProperty("--pane_1_size",e)}setupDragHandler(){const e=this.shadowRoot.getElementById("divider-handle");e&&(this.dragCleanup=s({element:e,callback:this.handleDrag,startCallback:this.handleDragStart,endCallback:this.handleDragEnd}))}setupResizeObserver(){this.resizeObserver=new ResizeObserver(e=>{for(const t of e){const e=t.contentRect.width;this.stacked=e<=this.stackWidth}}),this.resizeObserver.observe(this)}static styles=t`
1
+ import{html as e,css as t}from"../lit-all.min.js";import i from"./ShadowComponent.js";import s from"../utils/drag.js";import{boolExists as r}from"../utils/propConverters.js";export default class d extends i{static properties={resizing:{type:Boolean,reflect:!0},stacked:{type:Boolean,reflect:!0},stackWidth:{type:Number,attribute:"stack-width"},direction:{type:String,reflect:!0},persistentId:{type:String,reflect:!0,attribute:"persistent-id"},grip:{type:Boolean,reflect:!0,converter:r}};constructor(){super(),this.resizing=!1,this.stacked=!1,this.stackWidth=0,this.direction="horizontal",this.persistentId=null,this.grip=!1,this.dragStartSize=0,this.dragCleanup=()=>{},this.resizeObserver=null}firstUpdated(){if(super.firstUpdated(),this.grip){const e=document.createElement("div");e.style.cssText="position:absolute;visibility:hidden;width:var(--handle_width)",this.shadowRoot.appendChild(e);const t=e.offsetWidth;this.shadowRoot.removeChild(e);const i=t%2==0?t-1:t;this.style.setProperty("--handle_grip_width",`${i}px`)}if(this.setupDragHandler(),this.setupResizeObserver(),this.persistentId&&window?.localStorage){const e=window.localStorage.getItem(`split-persistent-id-${this.persistentId}`);e&&this.setSize(e)}}disconnectedCallback(){super.disconnectedCallback(),this.dragCleanup(),this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=null)}handleDragStart=()=>{this.resizing=!0,this.dragStartSize=Math.round(this.shadowRoot.getElementById("pane-1").getBoundingClientRect()["vertical"===this.direction?"height":"width"]),this.dispatchEvent(new CustomEvent("resizestart",{detail:{startSize:this.dragStartSize},bubbles:!0}))};handleDrag=({x:e,y:t})=>{const i="vertical"===this.direction?t:e,s=`${this.dragStartSize+i}px`;this.setSize(s),this.dispatchEvent(new CustomEvent("resize",{detail:{size:s},bubbles:!0}))};handleDragEnd=({x:e,y:t})=>{this.resizing=!1;const i="vertical"===this.direction?t:e,s=`${this.dragStartSize+i}px`;this.setSize(s),this.persistentId&&window?.localStorage&&window.localStorage.setItem(`split-persistent-id-${this.persistentId}`,s),this.dispatchEvent(new CustomEvent("resizeend",{detail:{size:s},bubbles:!0}))};setSize(e){this.style.setProperty("--pane_1_size",e)}setupDragHandler(){const e=this.shadowRoot.getElementById("divider-handle");e&&(this.dragCleanup=s({element:e,callback:this.handleDrag,startCallback:this.handleDragStart,endCallback:this.handleDragEnd}))}setupResizeObserver(){this.resizeObserver=new ResizeObserver(e=>{for(const t of e){const e=t.contentRect.width;this.stacked=e<=this.stackWidth}}),this.resizeObserver.observe(this)}render(){return e`
2
+ <div id="pane-1" class="pane">
3
+ <slot></slot>
4
+ </div>
5
+ <div id="divider-handle">
6
+ <div id="divider-border">
7
+ ${this.grip?e`<div id="divider-grip"></div>`:""}
8
+ </div>
9
+ </div>
10
+ <div id="pane-2" class="pane">
11
+ <slot name="right"></slot>
12
+ </div>
13
+ `}static styles=t`
2
14
  :host {
3
15
  --pane_1_size: calc((100% - var(--handle_width)) / 2);
4
- --handle_width: 0.5rem;
16
+ --handle_width: 7px;
5
17
  --min_pane_size: 6rem;
6
18
 
7
19
  height: 100%;
@@ -27,6 +39,7 @@ import{html as e,css as t}from"../lit-all.min.js";import i from"./ShadowComponen
27
39
  }
28
40
 
29
41
  #divider-handle {
42
+ position: relative;
30
43
  display: flex;
31
44
  flex-shrink: 0;
32
45
  justify-content: center;
@@ -47,10 +60,21 @@ import{html as e,css as t}from"../lit-all.min.js";import i from"./ShadowComponen
47
60
  }
48
61
 
49
62
  #divider-border {
63
+ position: relative;
50
64
  width: 1px;
51
65
  height: 100%;
52
66
  border-left: 1px solid var(--c_border);
53
67
  }
68
+ #divider-grip {
69
+ position: absolute;
70
+ top: 50%;
71
+ left: 50%;
72
+ transform: translate(-50%, -50%);
73
+ width: var(--handle_grip_width, var(--handle_width));
74
+ height: 2rem;
75
+ border-radius: 0.25rem;
76
+ background-color: var(--c_border);
77
+ }
54
78
 
55
79
  #pane-2 {
56
80
  flex: 1 1;
@@ -105,14 +129,8 @@ import{html as e,css as t}from"../lit-all.min.js";import i from"./ShadowComponen
105
129
  border-left: none;
106
130
  border-top: 1px solid var(--c_border);
107
131
  }
108
- `;render(){return e`
109
- <div id="pane-1" class="pane">
110
- <slot></slot>
111
- </div>
112
- <div id="divider-handle">
113
- <div id="divider-border"></div>
114
- </div>
115
- <div id="pane-2" class="pane">
116
- <slot name="right"></slot>
117
- </div>
118
- `}}customElements.define("k-split",r);
132
+ :host([direction="vertical"]) #divider-grip {
133
+ width: 2rem;
134
+ height: 0.5rem;
135
+ }
136
+ `}customElements.define("k-split",d);
@@ -9,6 +9,7 @@
9
9
  <a href="#resizing">Resizing</a><br />
10
10
  <a href="#verticalSplit">Vertical Split</a><br />
11
11
  <a href="#persistentState">Persistent State</a><br />
12
+ <a href="#grip">Grip</a><br />
12
13
  <h6 class="mt"><a href="#jsRef" class="no-link">JavaScript Reference</a></h6>
13
14
  <a href="#constructor">Constructor</a><br />
14
15
  <a href="#requirements">Requirements</a><br />
@@ -59,11 +60,11 @@
59
60
  <h3>Sizes</h3>
60
61
  <p>Set the CSS Custom Property <code>--pane_1_size</code> to set the initial size of the first pane.</p>
61
62
  <p>Set the CSS Custom Property <code>--min_pane_size</code> to set the minimum size each pane can be.</p>
62
- <p>Set the CSS Custom Property <code>--handle_width</code> to set the size of the handle (the draggable region between the panes).</p>
63
+ <p>Set the CSS Custom Property <code>--handle_width</code> to set the size of the handle (the draggable region between the panes), odd sizes are recommended so it can be centered on the border.</p>
63
64
  <div class="row -mx">
64
65
  <div class="col m-span-12 px">
65
66
  <k-card label="HTML">
66
- <pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">k-split</span><br /> <span class="hljs-attr">style</span>=<span class="hljs-string">"<br /> --pane_1_size: 100px;<br /> --min_pane_size: 100px;<br /> --handle_width: 20px;<br /> height: 10rem<br /> "</span><br /> <span class="hljs-attr">class</span>=<span class="hljs-string">"b"</span><br />&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>left<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"right"</span>&gt;</span>right<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br /><span class="hljs-tag">&lt;/<span class="hljs-name">k-split</span>&gt;</span></code></pre>
67
+ <pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">k-split</span><br /> <span class="hljs-attr">style</span>=<span class="hljs-string">"<br /> --pane_1_size: 100px;<br /> --min_pane_size: 100px;<br /> --handle_width: 19px;<br /> height: 10rem<br /> "</span><br /> <span class="hljs-attr">class</span>=<span class="hljs-string">"b"</span><br />&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>left<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"right"</span>&gt;</span>right<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br /><span class="hljs-tag">&lt;/<span class="hljs-name">k-split</span>&gt;</span></code></pre>
67
68
  </k-card>
68
69
  </div>
69
70
  <div class="col m-span-12 px">
@@ -72,7 +73,7 @@
72
73
  style="
73
74
  --pane_1_size: 100px;
74
75
  --min_pane_size: 100px;
75
- --handle_width: 20px;
76
+ --handle_width: 19px;
76
77
  height: 10rem
77
78
  "
78
79
  class="b"
@@ -141,6 +142,28 @@
141
142
  </div>
142
143
  </div>
143
144
 
145
+ <h3 id="grip"><a href="#grip" class="no-link">Grip</a></h3>
146
+ <p>Add the <code>grip</code> attribute to render a visual grip indicator centered on the divider handle, making it easier to identify the draggable area.</p>
147
+ <div class="row -mx mb">
148
+ <div class="col d-span-6 m-span-12 px">
149
+ <k-card label="HTML">
150
+ <pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">k-split</span> <span class="hljs-attr">grip</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"height: 10rem"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"b mb"</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Left Pane Content<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"right"</span>&gt;</span>Right Pane Content<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br /><span class="hljs-tag">&lt;/<span class="hljs-name">k-split</span>&gt;</span><br /><span class="hljs-tag">&lt;<span class="hljs-name">k-split</span> <span class="hljs-attr">grip</span> <span class="hljs-attr">direction</span>=<span class="hljs-string">"vertical"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"height: 16rem"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"b"</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Top Pane Content<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"right"</span>&gt;</span>Bottom Pane Content<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br /><span class="hljs-tag">&lt;/<span class="hljs-name">k-split</span>&gt;</span></code></pre>
151
+ </k-card>
152
+ </div>
153
+ <div class="col d-span-6 m-span-12 px">
154
+ <k-card label="Results">
155
+ <k-split grip style="height: 10rem" class="b mb">
156
+ <div>Left Pane Content</div>
157
+ <div slot="right">Right Pane Content</div>
158
+ </k-split>
159
+ <k-split grip direction="vertical" style="height: 16rem" class="b">
160
+ <div>Top Pane Content</div>
161
+ <div slot="right">Bottom Pane Content</div>
162
+ </k-split>
163
+ </k-card>
164
+ </div>
165
+ </div>
166
+
144
167
  <h2 id="jsRef">JavaScript Reference</h2>
145
168
 
146
169
  <h3 id="constructor"><a href="#constructor" class="no-link">Constructor</a></h3>
@@ -165,6 +188,8 @@
165
188
  <p>The direction of the split. Can be <code>"horizontal"</code> (default) or <code>"vertical"</code>. Syncs to <code>direction</code> attribute.</p>
166
189
  <h5><code>persistentId<i>: string</i></code></h5>
167
190
  <p>When set, the pane size is saved to <code>localStorage</code> on resize and restored on initialization. Must be unique per split instance. Syncs to <code>persistent-id</code> attribute.</p>
191
+ <h5><code>grip<i>: boolean</i></code></h5>
192
+ <p>When set, renders a visual grip indicator centered on the divider handle. Syncs to <code>grip</code> attribute.</p>
168
193
 
169
194
  <h3 id="cssCustomProperties"><a href="#cssCustomProperties" class="no-link">CSS Custom Properties</a></h3>
170
195
  <h5><code>--pane_1_size</code></h5>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kempo-ui",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "type": "module",
5
5
  "description": "A Lit based web-component library",
6
6
  "main": "index.js",
@@ -1,125 +1,157 @@
1
1
  import { html, css } from '../lit-all.min.js';
2
2
  import ShadowComponent from './ShadowComponent.js';
3
3
  import drag from '../utils/drag.js';
4
+ import { boolExists } from '../utils/propConverters.js';
4
5
 
5
6
  export default class Split extends ShadowComponent {
6
- static properties = {
7
- resizing: { type: Boolean, reflect: true },
8
- stacked: { type: Boolean, reflect: true },
9
- stackWidth: { type: Number, attribute: 'stack-width' },
10
- direction: { type: String, reflect: true },
11
- persistentId: { type: String, reflect: true, attribute: 'persistent-id' }
12
- };
13
-
14
- constructor() {
15
- super();
16
-
17
- this.resizing = false;
18
- this.stacked = false;
19
- this.stackWidth = 0;
20
- this.direction = 'horizontal';
21
- this.persistentId = null;
22
-
23
- // Private state
24
- this.dragStartSize = 0;
25
- this.dragCleanup = () => {};
26
- this.resizeObserver = null;
27
- }
28
-
29
- /*
30
- Lifecycle Callbacks
31
- */
32
- firstUpdated() {
33
- super.firstUpdated();
34
- this.setupDragHandler();
35
- this.setupResizeObserver();
36
- if(this.persistentId && window?.localStorage) {
37
- const size = window.localStorage.getItem(`split-persistent-id-${this.persistentId}`);
38
- if(size) this.setSize(size);
39
- }
40
- }
41
-
42
- disconnectedCallback() {
43
- super.disconnectedCallback();
44
- this.dragCleanup();
45
- if(this.resizeObserver) {
46
- this.resizeObserver.disconnect();
47
- this.resizeObserver = null;
48
- }
49
- }
50
-
51
- /*
52
- Event Handlers
53
- */
54
- handleDragStart = () => {
55
- this.resizing = true;
56
- this.dragStartSize = Math.round(this.shadowRoot.getElementById('pane-1').getBoundingClientRect()[this.direction === 'vertical' ? 'height' : 'width']);
57
- this.dispatchEvent(new CustomEvent('resizestart', {
58
- detail: { startSize: this.dragStartSize },
59
- bubbles: true
60
- }));
61
- };
62
-
63
- handleDrag = ({ x, y }) => {
64
- const delta = this.direction === 'vertical' ? y : x;
65
- const size = `${this.dragStartSize + delta}px`;
66
- this.setSize(size);
67
- this.dispatchEvent(new CustomEvent('resize', {
68
- detail: { size },
69
- bubbles: true
70
- }));
71
- };
72
-
73
- handleDragEnd = ({ x, y }) => {
74
- this.resizing = false;
75
- const delta = this.direction === 'vertical' ? y : x;
76
- const size = `${this.dragStartSize + delta}px`;
77
- this.setSize(size);
78
- if(this.persistentId && window?.localStorage) {
79
- window.localStorage.setItem(`split-persistent-id-${this.persistentId}`, size);
80
- }
81
- this.dispatchEvent(new CustomEvent('resizeend', {
82
- detail: { size },
83
- bubbles: true
84
- }));
85
- };
86
-
87
- /*
88
- Public Methods
89
- */
90
- setSize(size) {
91
- this.style.setProperty('--pane_1_size', size);
92
- }
93
-
94
- setupDragHandler() {
95
- const handle = this.shadowRoot.getElementById('divider-handle');
96
- if(handle) {
97
- this.dragCleanup = drag({
98
- element: handle,
99
- callback: this.handleDrag,
100
- startCallback: this.handleDragStart,
101
- endCallback: this.handleDragEnd
102
- });
103
- }
104
- }
105
-
106
- setupResizeObserver() {
107
- this.resizeObserver = new ResizeObserver(entries => {
108
- for(const entry of entries) {
109
- const width = entry.contentRect.width;
110
- this.stacked = width <= this.stackWidth;
111
- }
112
- });
113
- this.resizeObserver.observe(this);
114
- }
115
-
116
- /*
117
- Styles
118
- */
119
- static styles = css`
7
+ static properties = {
8
+ resizing: { type: Boolean, reflect: true },
9
+ stacked: { type: Boolean, reflect: true },
10
+ stackWidth: { type: Number, attribute: 'stack-width' },
11
+ direction: { type: String, reflect: true },
12
+ persistentId: { type: String, reflect: true, attribute: 'persistent-id' },
13
+ grip: { type: Boolean, reflect: true, converter: boolExists }
14
+ };
15
+
16
+ constructor() {
17
+ super();
18
+
19
+ this.resizing = false;
20
+ this.stacked = false;
21
+ this.stackWidth = 0;
22
+ this.direction = 'horizontal';
23
+ this.persistentId = null;
24
+ this.grip = false;
25
+
26
+ // Private state
27
+ this.dragStartSize = 0;
28
+ this.dragCleanup = () => { };
29
+ this.resizeObserver = null;
30
+ }
31
+
32
+ /*
33
+ Lifecycle Callbacks
34
+ */
35
+ firstUpdated() {
36
+ super.firstUpdated();
37
+ if(this.grip){
38
+ const el = document.createElement('div');
39
+ el.style.cssText = 'position:absolute;visibility:hidden;width:var(--handle_width)';
40
+ this.shadowRoot.appendChild(el);
41
+ const handleWidth = el.offsetWidth;
42
+ this.shadowRoot.removeChild(el);
43
+ const gripWidth = handleWidth % 2 === 0 ? handleWidth - 1 : handleWidth;
44
+ this.style.setProperty('--handle_grip_width', `${gripWidth}px`);
45
+ }
46
+ this.setupDragHandler();
47
+ this.setupResizeObserver();
48
+ if (this.persistentId && window?.localStorage) {
49
+ const size = window.localStorage.getItem(`split-persistent-id-${this.persistentId}`);
50
+ if (size) this.setSize(size);
51
+ }
52
+ }
53
+
54
+ disconnectedCallback() {
55
+ super.disconnectedCallback();
56
+ this.dragCleanup();
57
+ if (this.resizeObserver) {
58
+ this.resizeObserver.disconnect();
59
+ this.resizeObserver = null;
60
+ }
61
+ }
62
+
63
+ /*
64
+ Event Handlers
65
+ */
66
+ handleDragStart = () => {
67
+ this.resizing = true;
68
+ this.dragStartSize = Math.round(this.shadowRoot.getElementById('pane-1').getBoundingClientRect()[this.direction === 'vertical' ? 'height' : 'width']);
69
+ this.dispatchEvent(new CustomEvent('resizestart', {
70
+ detail: { startSize: this.dragStartSize },
71
+ bubbles: true
72
+ }));
73
+ };
74
+
75
+ handleDrag = ({ x, y }) => {
76
+ const delta = this.direction === 'vertical' ? y : x;
77
+ const size = `${this.dragStartSize + delta}px`;
78
+ this.setSize(size);
79
+ this.dispatchEvent(new CustomEvent('resize', {
80
+ detail: { size },
81
+ bubbles: true
82
+ }));
83
+ };
84
+
85
+ handleDragEnd = ({ x, y }) => {
86
+ this.resizing = false;
87
+ const delta = this.direction === 'vertical' ? y : x;
88
+ const size = `${this.dragStartSize + delta}px`;
89
+ this.setSize(size);
90
+ if (this.persistentId && window?.localStorage) {
91
+ window.localStorage.setItem(`split-persistent-id-${this.persistentId}`, size);
92
+ }
93
+ this.dispatchEvent(new CustomEvent('resizeend', {
94
+ detail: { size },
95
+ bubbles: true
96
+ }));
97
+ };
98
+
99
+ /*
100
+ Public Methods
101
+ */
102
+ setSize(size) {
103
+ this.style.setProperty('--pane_1_size', size);
104
+ }
105
+
106
+ setupDragHandler() {
107
+ const handle = this.shadowRoot.getElementById('divider-handle');
108
+ if (handle) {
109
+ this.dragCleanup = drag({
110
+ element: handle,
111
+ callback: this.handleDrag,
112
+ startCallback: this.handleDragStart,
113
+ endCallback: this.handleDragEnd
114
+ });
115
+ }
116
+ }
117
+
118
+ setupResizeObserver() {
119
+ this.resizeObserver = new ResizeObserver(entries => {
120
+ for (const entry of entries) {
121
+ const width = entry.contentRect.width;
122
+ this.stacked = width <= this.stackWidth;
123
+ }
124
+ });
125
+ this.resizeObserver.observe(this);
126
+ }
127
+
128
+ /*
129
+ Styles
130
+ */
131
+
132
+
133
+ /*
134
+ Rendering
135
+ */
136
+ render() {
137
+ return html`
138
+ <div id="pane-1" class="pane">
139
+ <slot></slot>
140
+ </div>
141
+ <div id="divider-handle">
142
+ <div id="divider-border">
143
+ ${this.grip ? html`<div id="divider-grip"></div>` : ''}
144
+ </div>
145
+ </div>
146
+ <div id="pane-2" class="pane">
147
+ <slot name="right"></slot>
148
+ </div>
149
+ `;
150
+ }
151
+ static styles = css`
120
152
  :host {
121
153
  --pane_1_size: calc((100% - var(--handle_width)) / 2);
122
- --handle_width: 0.5rem;
154
+ --handle_width: 7px;
123
155
  --min_pane_size: 6rem;
124
156
 
125
157
  height: 100%;
@@ -145,6 +177,7 @@ export default class Split extends ShadowComponent {
145
177
  }
146
178
 
147
179
  #divider-handle {
180
+ position: relative;
148
181
  display: flex;
149
182
  flex-shrink: 0;
150
183
  justify-content: center;
@@ -165,10 +198,21 @@ export default class Split extends ShadowComponent {
165
198
  }
166
199
 
167
200
  #divider-border {
201
+ position: relative;
168
202
  width: 1px;
169
203
  height: 100%;
170
204
  border-left: 1px solid var(--c_border);
171
205
  }
206
+ #divider-grip {
207
+ position: absolute;
208
+ top: 50%;
209
+ left: 50%;
210
+ transform: translate(-50%, -50%);
211
+ width: var(--handle_grip_width, var(--handle_width));
212
+ height: 2rem;
213
+ border-radius: 0.25rem;
214
+ background-color: var(--c_border);
215
+ }
172
216
 
173
217
  #pane-2 {
174
218
  flex: 1 1;
@@ -223,24 +267,11 @@ export default class Split extends ShadowComponent {
223
267
  border-left: none;
224
268
  border-top: 1px solid var(--c_border);
225
269
  }
270
+ :host([direction="vertical"]) #divider-grip {
271
+ width: 2rem;
272
+ height: 0.5rem;
273
+ }
226
274
  `;
227
-
228
- /*
229
- Rendering
230
- */
231
- render() {
232
- return html`
233
- <div id="pane-1" class="pane">
234
- <slot></slot>
235
- </div>
236
- <div id="divider-handle">
237
- <div id="divider-border"></div>
238
- </div>
239
- <div id="pane-2" class="pane">
240
- <slot name="right"></slot>
241
- </div>
242
- `;
243
- }
244
275
  }
245
276
 
246
277
  customElements.define('k-split', Split);