-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
completed
<Drawer />
component feature and additional updates
- Loading branch information
Showing
11 changed files
with
430 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
<div role="dialog" aria-modal="true" class="next-drawer {{if this.isMinimized 'drawer-is-minimized'}} {{if this.isResizing 'drawer-is-resizing'}} {{if this.isOpen 'drawer-is-open'}} {{if this.noBackdrop 'drawer-no-backdrop'}} {{if @fullHeight 'drawer-full-height'}} {{@overlayClass}}" {{did-insert this.setupComponent}}> | ||
{{#if this._rendered}} | ||
<div class="next-drawer-panel-container {{@containerClass}}" {{did-insert (fn this.setupNode "drawerContainer")}}> | ||
{{#if this.isResizable}} | ||
<div class="gutter" {{did-insert (fn this.setupNode "gutter")}} {{on "mousedown" this.startResize}}> | ||
{{#if @notchEnabled}} | ||
<div class="notch" {{on "dblclick" this.toggleMinimize}}> | ||
<span class="bar"></span> | ||
<span class="bar"></span> | ||
<span class="bar"></span> | ||
</div> | ||
{{/if}} | ||
</div> | ||
{{/if}} | ||
<div class="next-drawer-panel" {{did-insert (fn this.setupNode "drawerPanel")}} {{set-height this.height}} ...attributes>{{yield this.context}}</div> | ||
</div> | ||
{{/if}} | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
import Component from '@glimmer/component'; | ||
import { tracked } from '@glimmer/tracking'; | ||
import { action } from '@ember/object'; | ||
import { later } from '@ember/runloop'; | ||
import getWithDefault from '@fleetbase/ember-core/utils/get-with-default'; | ||
|
||
export default class DrawerComponent extends Component { | ||
@tracked drawerNode; | ||
@tracked drawerContainerNode; | ||
@tracked drawerPanelNode; | ||
@tracked gutterNode; | ||
@tracked noBackdrop = true; | ||
@tracked isOpen = true; | ||
@tracked isResizable = true; | ||
@tracked isResizing = false; | ||
@tracked isMinimized = false; | ||
@tracked mouseX = 0; | ||
@tracked mouseY = 0; | ||
@tracked height = 300; | ||
@tracked _rendered = false; | ||
|
||
context = { | ||
toggle: this.toggle, | ||
open: this.open, | ||
close: this.close, | ||
toggleMinimize: this.toggleMinimize, | ||
minimize: this.minimize, | ||
maximize: this.maximize, | ||
isOpen: this.isOpen, | ||
}; | ||
|
||
@action setupComponent(element) { | ||
this.drawerNode = element; | ||
this.height = getWithDefault(this.args, 'height', this.height); | ||
this.isMinimized = getWithDefault(this.args, 'isMinimized', this.isMinimized); | ||
|
||
later( | ||
this, | ||
() => { | ||
this.isOpen = getWithDefault(this.args, 'isOpen', this.isOpen); | ||
this.isResizable = getWithDefault(this.args, 'isResizable', this.isResizable); | ||
this.noBackdrop = getWithDefault(this.args, 'noBackdrop', this.noBackdrop); | ||
|
||
if (typeof this.args.onLoad === 'function') { | ||
this.args.onLoad(this.context); | ||
} | ||
|
||
this._rendered = true; | ||
}, | ||
300 | ||
); | ||
} | ||
|
||
@action setupNode(property, node) { | ||
this[`${property}Node`] = node; | ||
} | ||
|
||
@action toggle() { | ||
this.isOpen = !this.isOpen; | ||
} | ||
|
||
@action open() { | ||
this.isOpen = true; | ||
} | ||
|
||
@action close() { | ||
this.isOpen = false; | ||
} | ||
|
||
@action toggleMinimize() { | ||
this.isMinimized = !this.isMaximized; | ||
} | ||
|
||
@action minimize() { | ||
this.isMinimized = true; | ||
} | ||
|
||
@action maximize() { | ||
this.isMinimized = false; | ||
} | ||
|
||
@action startResize(event) { | ||
const disableResize = getWithDefault(this.args, 'disableResize', false); | ||
const onResizeStart = getWithDefault(this.args, 'onResizeStart', null); | ||
const { drawerPanelNode, isResizable } = this; | ||
|
||
if (disableResize === true || !isResizable || !drawerPanelNode) { | ||
return; | ||
} | ||
|
||
// if minimized undo | ||
if (this.isMinimized) { | ||
return this.maximize(); | ||
} | ||
|
||
const bounds = drawerPanelNode.getBoundingClientRect(); | ||
|
||
// Set the overlay width/height | ||
this.overlayWidth = bounds.width; | ||
this.overlayHeight = bounds.height; | ||
|
||
// Start resizing | ||
this.isResizing = true; | ||
|
||
// Get the current mouse position | ||
this.mouseX = event.clientX; | ||
this.mouseY = event.clientY; | ||
|
||
// Attach the listeners | ||
document.addEventListener('mousemove', this.resize); | ||
document.addEventListener('mouseup', this.stopResize); | ||
|
||
// Send up event | ||
if (typeof onResizeStart === 'function') { | ||
onResizeStart({ event, drawerPanelNode }); | ||
} | ||
} | ||
|
||
@action resize(event) { | ||
const disableResize = getWithDefault(this.args, 'disableResize', false); | ||
const onResize = getWithDefault(this.args, 'onResize', null); | ||
const { drawerPanelNode, isResizable } = this; | ||
|
||
if (disableResize === true || !isResizable || !drawerPanelNode) { | ||
return; | ||
} | ||
|
||
const dx = event.clientX - this.mouseX; | ||
const dy = event.clientY - this.mouseY; | ||
const multiplier = -1; | ||
const width = dx * multiplier + this.overlayWidth; | ||
const height = dy * multiplier + this.overlayHeight; | ||
const minResizeHeight = getWithDefault(this.args, 'minResizeHeight', 0); | ||
const maxResizeHeight = getWithDefault(this.args, 'maxResizeHeight', 600); | ||
|
||
// Min resize width | ||
if (height <= minResizeHeight) { | ||
drawerPanelNode.style.height = `${minResizeHeight}px`; | ||
return; | ||
} | ||
|
||
// Max resize width | ||
if (height >= maxResizeHeight) { | ||
drawerPanelNode.style.height = `${maxResizeHeight}px`; | ||
return; | ||
} | ||
|
||
// Style changes | ||
drawerPanelNode.style.userSelect = 'none'; | ||
drawerPanelNode.style.height = `${height}px`; | ||
document.body.style.cursor = 'row-resize'; | ||
|
||
// Send callback | ||
if (typeof onResize === 'function') { | ||
onResize({ event, drawerPanelNode }); | ||
} | ||
} | ||
|
||
@action stopResize(event) { | ||
const onResizeEnd = getWithDefault(this.args, 'onResizeEnd', null); | ||
const { drawerPanelNode } = this; | ||
|
||
// End resizing | ||
this.isResizing = false; | ||
|
||
// Remove style changes | ||
document.body.style.removeProperty('cursor'); | ||
drawerPanelNode.style.userSelect = 'auto'; | ||
|
||
// Remove the handlers of `mousemove` and `mouseup` | ||
document.removeEventListener('mousemove', this.resize); | ||
document.removeEventListener('mouseup', this.stopResize); | ||
|
||
if (typeof onResizeEnd === 'function') { | ||
onResizeEnd({ event, drawerPanelNode }); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{{#if this.isClickable}} | ||
<a href="javascript:;" class={{@column.className}} {{on "click" this.onClick}}>{{this.display}}</a> | ||
{{else}} | ||
<span class={{@column.className}}>{{this.display}}</span> | ||
{{/if}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import Component from '@glimmer/component'; | ||
import { tracked } from '@glimmer/tracking'; | ||
import { isArray } from '@ember/array'; | ||
import { get, action } from '@ember/object'; | ||
import { later } from '@ember/runloop'; | ||
|
||
const isPoint = (point) => { | ||
return point && typeof point === 'object' && isArray(point.coordinates); | ||
}; | ||
|
||
export default class TableCellPointComponent extends Component { | ||
@tracked display = ''; | ||
@tracked isClickable = false; | ||
|
||
constructor(owner, { row, column }) { | ||
super(...arguments); | ||
this.isClickable = typeof column === 'object' && (typeof column.onClick === 'function' || typeof column.action === 'function'); | ||
this.displayPointFromRow(row, column); | ||
} | ||
|
||
displayPointFromRow(row, column) { | ||
later( | ||
this, | ||
() => { | ||
const pointColumn = column.valuePath; | ||
|
||
if (pointColumn) { | ||
const point = get(row, pointColumn); | ||
|
||
if (isPoint(point)) { | ||
this.display = `${point.coordinates[1]} ${point.coordinates[0]}`; | ||
} | ||
} | ||
}, | ||
300 | ||
); | ||
} | ||
|
||
@action onClick() { | ||
const { column } = this.args; | ||
const { onClick, action } = column; | ||
|
||
if (typeof onClick === 'funciton') { | ||
onClick(this.args.row, ...arguments); | ||
} | ||
|
||
if (typeof action === 'funciton') { | ||
action(this.args.row); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
.next-drawer { | ||
@apply absolute inset-0 opacity-0 transition duration-300 ease-in-out pointer-events-auto bg-gray-900 bg-opacity-50; | ||
width: 100%; | ||
height: 100%; | ||
z-index: 800; | ||
} | ||
|
||
.next-drawer.drawer-no-backdrop { | ||
@apply bg-transparent pointer-events-none; | ||
} | ||
|
||
.next-drawer.drawer-no-backdrop > * { | ||
@apply pointer-events-auto; | ||
} | ||
|
||
.next-drawer.drawer-is-open { | ||
@apply opacity-100; | ||
} | ||
|
||
.next-drawer.drawer-is-open > .next-drawer-panel-container { | ||
transform: translateY(0); | ||
} | ||
|
||
.next-drawer.drawer-is-minimized { | ||
@apply bg-transparent pointer-events-none; | ||
} | ||
|
||
.next-drawer.drawer-is-minimized > * { | ||
@apply pointer-events-auto; | ||
} | ||
|
||
.next-drawer.drawer-is-minimized > .next-drawer-panel-container > .next-drawer-panel { | ||
height: 0px !important; | ||
} | ||
|
||
.next-drawer.drawer-is-minimized > .next-drawer-panel-container { | ||
@apply pointer-events-auto; | ||
} | ||
|
||
.next-drawer > .next-drawer-panel-container { | ||
@apply left-0 right-0 bottom-0; | ||
transform: translateY(100%); | ||
} | ||
|
||
.next-drawer > .next-drawer-panel-container { | ||
@apply absolute transform transition ease-in-out duration-500 pointer-events-auto; | ||
} | ||
|
||
.next-drawer > .next-drawer-panel-container > .next-drawer-panel { | ||
@apply transform transition ease-in-out duration-500 pointer-events-auto bg-white shadow-next-nav; | ||
} | ||
|
||
.next-drawer.drawer-is-open .next-drawer-panel-container .next-drawer-panel { | ||
@apply shadow-none; | ||
} | ||
|
||
body[data-theme='dark'] .next-drawer > .next-drawer-panel-container > .next-drawer-panel { | ||
@apply bg-gray-900; | ||
} | ||
|
||
.next-drawer > .next-drawer-panel-container > .gutter { | ||
height: auto; | ||
width: 100%; | ||
background-image: none; | ||
background-color: inherit; | ||
cursor: row-resize; | ||
background-position: unset; | ||
background-repeat: unset; | ||
position: relative; | ||
z-index: 9999; | ||
@apply border-2 border-gray-200 border-solid; | ||
} | ||
|
||
body[data-theme="dark"] .next-drawer > .next-drawer-panel-container > .gutter { | ||
@apply border-gray-500; | ||
} | ||
|
||
.next-drawer > .next-drawer-panel-container > .gutter:hover, | ||
.next-drawer.drawer-is-resizing > .next-drawer-panel-container > .gutter, | ||
body[data-theme="dark"] .next-drawer > .next-drawer-panel-container > .gutter:hover, | ||
body[data-theme="dark"] .next-drawer.drawer-is-resizing > .next-drawer-panel-container > .gutter { | ||
@apply border-sky-500 bg-opacity-75; | ||
} | ||
|
||
.next-drawer > .next-drawer-panel-container > .gutter > .notch { | ||
position: absolute; | ||
top: 0; | ||
left: 0; | ||
right: 0; | ||
display: flex; | ||
flex-direction: column; | ||
justify-content: center; | ||
align-items: center; | ||
width: 3.5rem; | ||
height: 1.25rem; | ||
margin-left: auto; | ||
margin-right: auto; | ||
margin-top: -11px; | ||
z-index: 9999999; | ||
padding: 0 0.75rem; | ||
cursor: grab !important; | ||
@apply bg-gray-200 border-2 border-white shadow-md drop-shadow-md rounded-lg; | ||
} | ||
|
||
body[data-theme="dark"] .next-drawer > .next-drawer-panel-container > .gutter > .notch { | ||
@apply bg-gray-600 border-gray-600; | ||
} | ||
|
||
.next-drawer > .next-drawer-panel-container > .gutter > .notch > .bar { | ||
display: block; | ||
height: 0.0955555555rem; | ||
width: 100%; | ||
margin: 0.09rem 0; | ||
border-radius: 2px; | ||
cursor: grab !important; | ||
@apply bg-gray-400; | ||
} | ||
|
||
body[data-theme='dark'] .next-drawer > .next-drawer-panel-container > .gutter > .notch > .bar { | ||
@apply bg-gray-400; | ||
} |
Oops, something went wrong.