Skip to content

Commit

Permalink
* kanban: fix links layout in KanbanList.
Browse files Browse the repository at this point in the history
  • Loading branch information
catouse committed May 28, 2024
1 parent ec4209b commit 18be452
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 22 deletions.
5 changes: 3 additions & 2 deletions lib/kanban/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,8 +279,9 @@ onPageUpdate(() => {
{fromKanban: 'kanban0', toKanban: 'kanban1', from: '5', to: '11'},
],
selectable: true,
showLinkOnSelected: true,
showLinkOnHover: true,
editLinks: true,
// showLinkOnSelected: true,
// showLinkOnHover: true,
});
console.log('> kanbanList', kanbanList);
});
13 changes: 7 additions & 6 deletions lib/kanban/src/component/kanban-link-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const EVENT_NAMESPACE = '.kanban';
export class KanbanLinkEditor extends Component<KanbanLinkEditorProps, KanbanLinkEditorState> {
protected _ref = createRef<HTMLDivElement>();

protected declare _kanban: HTMLElement;
protected declare _container: HTMLElement;

protected _raf?: number;

Expand All @@ -27,7 +27,7 @@ export class KanbanLinkEditor extends Component<KanbanLinkEditorProps, KanbanLin
const element = this._ref.current!;
const {container = '.kanban'} = this.props;
const containerElement = element.closest(container) as HTMLElement;
this._kanban = containerElement;
this._container = containerElement;
this._multiKanban = $(containerElement).find('.kanban').length > 1;

const eventSelector = '.kanban-item,.kanban-link-editor-from';
Expand Down Expand Up @@ -74,7 +74,7 @@ export class KanbanLinkEditor extends Component<KanbanLinkEditorProps, KanbanLin
$(containerElement).addClass('is-adding-link');
},
onMove: (event) => {
const {top: offsetTop, left: offsetLeft} = this._kanban.getBoundingClientRect();
const {top: offsetTop, left: offsetLeft} = this._container.getBoundingClientRect();
const dragPos = {left: event.clientX - offsetLeft, top: event.clientY - offsetTop};
let to: string | undefined;
let toRect: KanbanLinkEditorState['toRect'] | undefined;
Expand Down Expand Up @@ -111,10 +111,11 @@ export class KanbanLinkEditor extends Component<KanbanLinkEditorProps, KanbanLin

protected _getRect(element: HTMLElement) {
const rect = element.getBoundingClientRect();
const {top: offsetTop, left: offsetLeft} = this._kanban.getBoundingClientRect();
const container = this._container;
const {top: offsetTop, left: offsetLeft} = container.getBoundingClientRect();
return {
left: rect.left - offsetLeft,
top: rect.top - offsetTop,
left: rect.left - offsetLeft + container.scrollLeft,
top: rect.top - offsetTop + container.scrollTop,
width: rect.width,
height: rect.height,
};
Expand Down
27 changes: 18 additions & 9 deletions lib/kanban/src/component/kanban-links.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import type {ComponentChild, RenderableProps} from 'preact';
import type {KanbanLinkOptions, KanbanLinksProps, KanbanLinksState} from '../types';
import {createLinkID} from '../helpers/link-helpers';

const EVENT_NAMESPACE = '.kanban';

export class KanbanLinks extends Component<KanbanLinksProps, KanbanLinksState> {
protected _ref = createRef<HTMLDivElement>();

Expand All @@ -18,23 +20,27 @@ export class KanbanLinks extends Component<KanbanLinksProps, KanbanLinksState> {

protected _raf?: number;

state: KanbanLinksState = {layout: {}};
state: KanbanLinksState = {layout: {}, scrollTop: 0, scrollLeft: 0};

componentDidMount(): void {
const {container = '.kanban'} = this.props;
const containerElement = this._ref.current?.closest(container) as HTMLElement;
$(containerElement).on('laneColResize.kanban', () => {
const $container = $(containerElement);
this._multiKanban = $container.find('.kanban').length > 1;
$container.on(`laneColResize${EVENT_NAMESPACE} laneColScroll${EVENT_NAMESPACE}`, () => {
this._tryUpdateLayout();
}).on(`scroll${EVENT_NAMESPACE}`, () => {
// this._tryUpdateLayout();
// this.setState({scrollTop: containerElement.scrollTop, scrollLeft: containerElement.scrollLeft});
});
this._container = containerElement;
this._tryUpdateLayout();
this._multiKanban = $(containerElement).find('.kanban').length > 1;
}

componentWillUnmount(): void {
const containerElement = this._container;
if (containerElement) {
$(containerElement).off('.kanban');
$(containerElement).off(EVENT_NAMESPACE);
}
if (this._raf) {
cancelAnimationFrame(this._raf);
Expand All @@ -59,15 +65,18 @@ export class KanbanLinks extends Component<KanbanLinksProps, KanbanLinksState> {

_updateLayout() {
const watchSet = [...this._watchSet];
const $container = $(this._container);
const {top: offsetTop, left: offsetLeft} = this._container.getBoundingClientRect();
const container = this._container;
const $container = $(container);
const {top: containerTop, left: containerLeft} = container.getBoundingClientRect();
const offsetTop = container.scrollTop - containerTop;
const offsetLeft = container.scrollLeft - containerLeft;
const layout: KanbanLinksState['layout'] = {};
watchSet.forEach(key => {
const [kanban, id] = key.split('_');
const element = $container.find(`${this._multiKanban ? `.kanban[z-key="${kanban}"] ` : ''}.kanban-item[z-key="${id}"]`).children()[0];
if (element) {
const {top, left, bottom, right} = element.getBoundingClientRect();
layout[key] = {top: top - offsetTop, left: left - offsetLeft, bottom: bottom - offsetTop, right: right - offsetLeft};
layout[key] = {top: top + offsetTop, left: left + offsetLeft, bottom: bottom + offsetTop, right: right + offsetLeft};
}
});
this.setState({layout});
Expand Down Expand Up @@ -112,9 +121,9 @@ export class KanbanLinks extends Component<KanbanLinksProps, KanbanLinksState> {
}

_renderEditor(props: RenderableProps<KanbanLinksProps>) {
const {editLinks, onAddLink} = props;
const {editLinks, onAddLink, container} = props;
if (editLinks) {
return <KanbanLinkEditor key="editor" onAddLink={onAddLink} />;
return <KanbanLinkEditor key="editor" container={container} onAddLink={onAddLink} />;
}
return null;
}
Expand Down
21 changes: 18 additions & 3 deletions lib/kanban/src/component/kanban-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,14 @@ export class KanbanList extends HElement<KanbanListProps, KanbanListState> {
});
}

protected _handleScroll = () => {
const element = this._ref.current;
if (!element) {
return;
}
$(element).trigger('kanbanListScroll');
};

protected _getClassName(props: RenderableProps<KanbanListProps>): ClassNameLike {
return ['kanban-list', props.className, props.sticky ? 'has-sticky' : '', props.moveable ? 'is-moveable' : '', props.scrollbarHover ? 'scrollbar-hover' : ''];
}
Expand All @@ -175,6 +183,7 @@ export class KanbanList extends HElement<KanbanListProps, KanbanListState> {
'--kanban-list-width': `${actualWidth || width}px`,
'--kanban-list-height': `${actualHeight || height}px`,
},
onScroll: this._handleScroll,
});
}

Expand Down Expand Up @@ -224,7 +233,7 @@ export class KanbanList extends HElement<KanbanListProps, KanbanListState> {

const {showLinkOnHover, showLinkOnSelected} = props;
let filters: string[] | undefined;
if (showLinkOnSelected || showLinkOnHover) {
if (links.length && (showLinkOnSelected || showLinkOnHover)) {
filters = [];
const {selected = {}, hover} = this.state;
if (showLinkOnSelected && selected) {
Expand Down Expand Up @@ -255,7 +264,7 @@ export class KanbanList extends HElement<KanbanListProps, KanbanListState> {
}

protected _getChildren(props: RenderableProps<KanbanListProps>): ComponentChildren {
const {items = [], kanbanProps: kanbanPropsSetting, showLinkOnSelected, showLinkOnHover, selectable} = props;
const {items = [], kanbanProps: kanbanPropsSetting, showLinkOnSelected, showLinkOnHover, selectable, editLinks} = props;
const kanbanRefs = this._kanbanRefs;
const refKeys = new Set<string>(kanbanRefs.keys());
const children = [
Expand All @@ -278,7 +287,13 @@ export class KanbanList extends HElement<KanbanListProps, KanbanListState> {
kanbanProps = {showLinkOnSelected, showLinkOnHover, selectable, ...kanbanProps};
}
}
kanbanProps = {showLinkOnSelected, showLinkOnHover, ...kanbanProps};
if (editLinks) {
if (isRegion) {
(kanbanProps as KanbanRegionProps).items = ((kanbanProps as KanbanRegionProps).items || []).map(x => ({...x, editLinks: false}));
} else {
kanbanProps = {...kanbanProps, editLinks: false};
}
}
const KanbanComponent = isRegion ? KanbanRegion : Kanban;
return <KanbanComponent key={key} ref={ref} sticky={props.sticky} {...(kanbanProps as KanbanProps)} z-key={key} />;
}),
Expand Down
2 changes: 1 addition & 1 deletion lib/kanban/src/style/kanban-link-editor.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.kanban.is-adding-link {
.is-adding-link {
@apply -cursor-crosshair -select-none;
}
.kanban-link-editor {
Expand Down
2 changes: 1 addition & 1 deletion lib/kanban/src/style/kanban-links.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
@apply -absolute -inset-0 -pointer-events-none -z-[5];
}
.kanban-list > .kanban-links {
@apply -z-[11];
@apply -z-[11] -overflow-visible;
}
.kanban-link {
@apply -absolute -flex -items-center -justify-center -text-[--kanban-link-color];
Expand Down
2 changes: 2 additions & 0 deletions lib/kanban/src/types/kanban-link-props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ export interface KanbanLinkProps extends KanbanLinkOptions {
fromRect: {left: number, top: number, bottom: number, right: number};
toRect: {left: number, top: number, bottom: number, right: number};
onDelete?: (link: KanbanLinkOptions) => void;
offsetX?: number;
offsetY?: number;
}
2 changes: 2 additions & 0 deletions lib/kanban/src/types/kanban-links-state.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export type KanbanLinksState = {
layout: Record<string, {left: number, top: number, bottom: number, right: number}>;
scrollTop: number;
scrollLeft: number;
};

0 comments on commit 18be452

Please sign in to comment.