diff --git a/lib/kanban/dev.ts b/lib/kanban/dev.ts index 131ffb4267..eb0cc11a4d 100644 --- a/lib/kanban/dev.ts +++ b/lib/kanban/dev.ts @@ -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); }); diff --git a/lib/kanban/src/component/kanban-link-editor.tsx b/lib/kanban/src/component/kanban-link-editor.tsx index 5e61af71d3..2a39aa3c87 100644 --- a/lib/kanban/src/component/kanban-link-editor.tsx +++ b/lib/kanban/src/component/kanban-link-editor.tsx @@ -11,7 +11,7 @@ const EVENT_NAMESPACE = '.kanban'; export class KanbanLinkEditor extends Component { protected _ref = createRef(); - protected declare _kanban: HTMLElement; + protected declare _container: HTMLElement; protected _raf?: number; @@ -27,7 +27,7 @@ export class KanbanLinkEditor extends Component 1; const eventSelector = '.kanban-item,.kanban-link-editor-from'; @@ -74,7 +74,7 @@ export class KanbanLinkEditor extends Component { - 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; @@ -111,10 +111,11 @@ export class KanbanLinkEditor extends Component { protected _ref = createRef(); @@ -18,23 +20,27 @@ export class KanbanLinks extends Component { 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); @@ -59,15 +65,18 @@ export class KanbanLinks extends Component { _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}); @@ -112,9 +121,9 @@ export class KanbanLinks extends Component { } _renderEditor(props: RenderableProps) { - const {editLinks, onAddLink} = props; + const {editLinks, onAddLink, container} = props; if (editLinks) { - return ; + return ; } return null; } diff --git a/lib/kanban/src/component/kanban-list.tsx b/lib/kanban/src/component/kanban-list.tsx index 79876da964..2b85815671 100644 --- a/lib/kanban/src/component/kanban-list.tsx +++ b/lib/kanban/src/component/kanban-list.tsx @@ -158,6 +158,14 @@ export class KanbanList extends HElement { }); } + protected _handleScroll = () => { + const element = this._ref.current; + if (!element) { + return; + } + $(element).trigger('kanbanListScroll'); + }; + protected _getClassName(props: RenderableProps): ClassNameLike { return ['kanban-list', props.className, props.sticky ? 'has-sticky' : '', props.moveable ? 'is-moveable' : '', props.scrollbarHover ? 'scrollbar-hover' : '']; } @@ -175,6 +183,7 @@ export class KanbanList extends HElement { '--kanban-list-width': `${actualWidth || width}px`, '--kanban-list-height': `${actualHeight || height}px`, }, + onScroll: this._handleScroll, }); } @@ -224,7 +233,7 @@ export class KanbanList extends HElement { 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) { @@ -255,7 +264,7 @@ export class KanbanList extends HElement { } protected _getChildren(props: RenderableProps): 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(kanbanRefs.keys()); const children = [ @@ -278,7 +287,13 @@ export class KanbanList extends HElement { 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 ; }), diff --git a/lib/kanban/src/style/kanban-link-editor.css b/lib/kanban/src/style/kanban-link-editor.css index 35690fcc9e..43637a766b 100644 --- a/lib/kanban/src/style/kanban-link-editor.css +++ b/lib/kanban/src/style/kanban-link-editor.css @@ -1,4 +1,4 @@ -.kanban.is-adding-link { +.is-adding-link { @apply -cursor-crosshair -select-none; } .kanban-link-editor { diff --git a/lib/kanban/src/style/kanban-links.css b/lib/kanban/src/style/kanban-links.css index e3a33d0e4f..a2953bbee6 100644 --- a/lib/kanban/src/style/kanban-links.css +++ b/lib/kanban/src/style/kanban-links.css @@ -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]; diff --git a/lib/kanban/src/types/kanban-link-props.ts b/lib/kanban/src/types/kanban-link-props.ts index 050123dd62..19a5aff1a6 100644 --- a/lib/kanban/src/types/kanban-link-props.ts +++ b/lib/kanban/src/types/kanban-link-props.ts @@ -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; } diff --git a/lib/kanban/src/types/kanban-links-state.ts b/lib/kanban/src/types/kanban-links-state.ts index 358af3fbc2..f2fbadc412 100644 --- a/lib/kanban/src/types/kanban-links-state.ts +++ b/lib/kanban/src/types/kanban-links-state.ts @@ -1,3 +1,5 @@ export type KanbanLinksState = { layout: Record; + scrollTop: number; + scrollLeft: number; };