Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,12 @@ storybook.serve: .require-compose ## [Build][docker] Runs Storybook for v1-compo
storybook.shot: .require-compose ## [Research][docker] Captures a Storybook screenshot for v1-components docs/story page
$(TARGET_HEADER)
@$(COMPOSE) up -d v1-components
@UID=$$(id -u) GID=$$(id -g) $(COMPOSE) run --rm playwright \
@$(COMPOSE) run --rm --user "$$(id -u):$$(id -g)" playwright \
yarn workspace @retailcrm/embed-ui-v1-components run storybook:shot \
--base-url http://v1-components:6006 \
--path "$(if $(story_path),$(story_path),/iframe.html?viewMode=docs&id=components-uitable--docs)" \
--output "$(if $(output),$(output),artifacts/storybook/UiTable.docs.png)" \
$(if $(selector),--selector "$(selector)",) \
--wait-for-selector "$(if $(wait_for),$(wait_for),#storybook-docs)" \
--settle-ms "$(if $(settle_ms),$(settle_ms),2500)" \
--timeout-ms "$(if $(timeout_ms),$(timeout_ms),60000)" \
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions packages/v1-components/assets/sprites/actions/drag.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
194 changes: 194 additions & 0 deletions packages/v1-components/src/common/components/logic-tree.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
export enum LogicTreeActionKind {
CONDITION = 'condition',
GROUP = 'group',
}

export enum LogicTreeControlKind {
ICON = 'icon',
INPUT = 'input',
SELECT = 'select',
}

export enum LogicTreeIcon {
ADD = 'add',
FOLDER = 'folder',
MORE = 'more',
}

export enum LogicTreeNodeKind {
BRANCH = 'branch',
CONDITION = 'condition',
GROUP = 'group',
}

export enum LogicTreeChildrenView {
GROUPED = 'grouped',
PLAIN = 'plain',
}

export enum LogicTreeConjunction {
AND = 'and',
OR = 'or',
}

export enum LogicTreeRowView {
ACTIONS = 'actions',
SUMMARY = 'summary',
}

export enum LogicTreeTone {
BLUE = 'blue',
GREEN = 'green',
GREY = 'grey',
RED = 'red',
YELLOW = 'yellow',
}

export type UiLogicTreeControl = {
id: string;
kind: LogicTreeControlKind;
label: string;
icon?: LogicTreeIcon;
options?: UiLogicTreeOption[];
value?: string | number | null;
placeholder?: string;
width?: number | string;
clearable?: boolean;
readonly?: boolean;
disabled?: boolean;
invalid?: boolean;
}

export type UiLogicTreeAction = {
id: string;
kind?: LogicTreeActionKind;
label: string;
}

export type UiLogicTreeConnector = {
continues: boolean;
placeholder?: boolean;
tone: LogicTreeTone;
visible: boolean;
}

export type UiLogicTreeOption = {
id: string;
label: string;
value: string | number;
}

export type UiLogicTreeInlineText = {
id: string;
text: string;
tone?: LogicTreeTone | 'default' | 'muted';
weight?: 'regular' | 'semibold';
separated?: boolean;
}

export type UiLogicTreeRow = {
view: LogicTreeRowView;
title: string;
editable: boolean;
icon?: LogicTreeIcon;
inline?: UiLogicTreeInlineText[];
controls?: UiLogicTreeControl[];
actions?: UiLogicTreeAction[];
disabled?: boolean;
draggable?: boolean;
removable?: boolean;
selected?: boolean;
highlighted?: boolean;
}

export type UiLogicTreeNode = {
id: string;
kind: LogicTreeNodeKind;
tone?: LogicTreeTone;
conjunction?: LogicTreeConjunction | string;
collapsible?: boolean;
expanded?: boolean;
childrenView?: LogicTreeChildrenView;
children?: UiLogicTreeNode[];
row: UiLogicTreeRow;
}

export type UiLogicTreeProperties = {
items?: UiLogicTreeNode[];
}

export type UiLogicTreeDropPayload = {
itemId: string;
sourceContainerId: string;
targetContainerId: string;
targetIndex: number | null;
targetItemId: string | null;
placement: 'after' | 'before';
payload?: unknown;
}

export type UiLogicTreeRowAddPayload = {
actionId: string;
kind: Exclude<UiLogicTreeNode['kind'], LogicTreeNodeKind.BRANCH>;
parentNodeId: string | null;
parentPathKey: string | null;
triggerNodeId: string;
}

export type UiLogicTreeRowEditPayload = {
controlId: string;
nodeId: string;
pathKey: string;
previousValue: string | number | null;
value: string | number | null;
}

export type UiLogicTreeRowRemovePayload = {
index: number;
nodeId: string;
parentNodeId: string | null;
parentPathKey: string | null;
pathKey: string;
}

export type UiLogicTreeRowSlotProps = {
editing: boolean;
expanded: boolean;
grouped: boolean;
groupedHeader: boolean;
groupedPosition?: UiLogicTreeRowProperties['groupedPosition'];
hasChildren: boolean;
highlighted: boolean;
disabled: boolean;
node: UiLogicTreeNode;
path: number[];
pathKey: string;
rowView: LogicTreeRowView;
selected: boolean;
onAction: (action: UiLogicTreeAction) => void;
onControlAction: (controlId: string) => void;
onControlUpdate: (controlId: string, value: string | number | null) => void;
onRemove: () => void;
onToggle: () => void;
}

export type UiLogicTreeRootProperties = Record<string, never>

export type UiLogicTreeRowProperties = {
pathKey?: string;
rowView?: LogicTreeRowView;
connectors?: UiLogicTreeConnector[];
conjunction?: string;
conjunctionEndPathKey?: string;
conjunctionLabel?: string;
conjunctionOffset?: number;
conjunctionStartPathKey?: string;
conjunctionTone?: LogicTreeTone;
groupedHeader?: boolean;
grouped?: boolean;
groupedPosition?: 'end' | 'middle' | 'single' | 'start';
editable?: boolean;
disabled?: boolean;
highlighted?: boolean;
selected?: boolean;
}
2 changes: 2 additions & 0 deletions packages/v1-components/src/host/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ export { default as UiImage } from '@/host/components/image/UiImage.vue'
export { default as UiInfobox } from '@/host/components/infobox/UiInfobox.vue'
export { default as UiLink } from '@/host/components/link/UiLink.vue'
export { default as UiLoader } from '@/host/components/loader/UiLoader.vue'
export { default as UiLogicTreeRoot } from '@/host/components/logic-tree/UiLogicTreeRoot.vue'
export { default as UiLogicTreeRow } from '@/host/components/logic-tree/UiLogicTreeRow.vue'
export { default as UiMenuItem } from '@/host/components/menu/UiMenuItem.vue'
export { default as UiMenuItemGroup } from '@/host/components/menu/UiMenuItemGroup.vue'
export { default as UiModalSidebar } from '@/host/components/modal-sidebar/UiModalSidebar.vue'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<template>
<div
ref="root"
class="ui-v1-logic-tree"
v-bind="$attrs"
@click="onRootClick"
>
<slot />
</div>
</template>

<script lang="ts" setup>
import { onBeforeUnmount, onMounted, ref } from 'vue'

defineOptions({
inheritAttrs: false,
})

const emit = defineEmits<{
'outside-click': [];
}>()

const root = ref<HTMLElement | null>(null)

const resolveEventElement = (target: EventTarget | null): Element | null => {
if (target instanceof Element) {
return target
}

if (target instanceof Node) {
return target.parentElement
}

return null
}

const isIgnoredTarget = (target: EventTarget | null): boolean => {
const element = resolveEventElement(target)

if (!element) {
return false
}

return Boolean(element.closest([
'.ui-v1-logic-tree__surface-row-content',
'.ui-v1-logic-tree__actions-row',
'.ui-v1-popper',
'[role="listbox"]',
'[role="option"]',
].join(', ')))
}

const onRootClick = (event: MouseEvent) => {
if (isIgnoredTarget(event.target)) {
return
}

emit('outside-click')
}

const onDocumentPointerDown = (event: PointerEvent) => {
const element = resolveEventElement(event.target)

if (!root.value || !element) {
return
}

if (root.value.contains(element) || isIgnoredTarget(element)) {
return
}

emit('outside-click')
}

onMounted(() => {
document.addEventListener('pointerdown', onDocumentPointerDown)
})

onBeforeUnmount(() => {
document.removeEventListener('pointerdown', onDocumentPointerDown)
})
</script>

<style lang="less" src="./logic-tree.less" />
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { DefineComponent } from '@/common/vue'

import type { UiLogicTreeRootProperties } from '@/common/components/logic-tree'

declare const UiLogicTreeRoot: DefineComponent<UiLogicTreeRootProperties>

export default UiLogicTreeRoot
Loading
Loading