@antscorp/antsomi-ui 1.3.5-beta.272 → 1.3.5-beta.274

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.
Files changed (32) hide show
  1. package/es/components/atoms/ContentEditable/ContentEditable.d.ts +16 -0
  2. package/es/components/atoms/ContentEditable/ContentEditable.js +76 -0
  3. package/es/components/atoms/ContentEditable/index.d.ts +1 -0
  4. package/es/components/atoms/ContentEditable/index.js +1 -0
  5. package/es/components/atoms/ContentEditable/styled.d.ts +4 -0
  6. package/es/components/atoms/ContentEditable/styled.js +20 -0
  7. package/es/components/atoms/index.d.ts +1 -0
  8. package/es/components/atoms/index.js +1 -0
  9. package/es/components/molecules/ChartTab/ChartTab.d.ts +19 -0
  10. package/es/components/molecules/ChartTab/ChartTab.js +36 -0
  11. package/es/components/molecules/ChartTab/components/Item.d.ts +16 -0
  12. package/es/components/molecules/ChartTab/components/Item.js +47 -0
  13. package/es/components/molecules/ChartTab/components/styled.d.ts +3 -0
  14. package/es/components/molecules/ChartTab/components/styled.js +30 -0
  15. package/es/components/molecules/ChartTab/styled.d.ts +1 -0
  16. package/es/components/molecules/ChartTab/styled.js +23 -0
  17. package/es/components/molecules/EditorTab/EditorTab.d.ts +35 -0
  18. package/es/components/molecules/EditorTab/EditorTab.js +159 -0
  19. package/es/components/molecules/EditorTab/index.d.ts +1 -0
  20. package/es/components/molecules/EditorTab/index.js +1 -0
  21. package/es/components/molecules/EditorTab/styled.d.ts +1 -0
  22. package/es/components/molecules/EditorTab/styled.js +132 -0
  23. package/es/components/molecules/index.d.ts +1 -0
  24. package/es/components/molecules/index.js +1 -0
  25. package/es/components/organism/ContentSources/Settings.js +2 -3
  26. package/es/components/organism/ContentSources/constants.js +1 -0
  27. package/es/components/organism/ContentSources/provider.d.ts +1 -0
  28. package/es/components/organism/ContentSources/provider.js +4 -0
  29. package/es/components/organism/ContentSources/reducer.d.ts +2 -1
  30. package/es/components/organism/ContentSources/reducer.js +8 -0
  31. package/es/components/organism/ContentSources/types.d.ts +5 -1
  32. package/package.json +4 -1
@@ -0,0 +1,16 @@
1
+ import React, { FocusEvent } from 'react';
2
+ import { TypographyProps } from 'antd';
3
+ import { EllipsisConfig } from 'antd/es/typography/Base';
4
+ interface ContentEditableProps extends Omit<TypographyProps['Text'], 'className' | '$$typeof'> {
5
+ onSave: (innerText: string, e?: FocusEvent<any>) => void;
6
+ value?: string;
7
+ isEdit?: boolean;
8
+ disabledBlur?: boolean;
9
+ maxLength?: number;
10
+ breakWord?: boolean;
11
+ regexPattern?: RegExp;
12
+ className?: string;
13
+ ellipsis?: EllipsisConfig;
14
+ }
15
+ export declare const ContentEditable: React.FC<React.PropsWithChildren<ContentEditableProps>>;
16
+ export {};
@@ -0,0 +1,76 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import React, { useEffect, useRef, useState } from 'react';
13
+ import { ContentEditableWrapper } from './styled';
14
+ // NOTE: User can keypress when value reach max length
15
+ const IGNORE_KEY_CODE = [
16
+ 'Backspace',
17
+ 'Delete',
18
+ 'ArrowRight',
19
+ 'ArrowLeft',
20
+ 'ControlLeft',
21
+ 'ControlRight',
22
+ 'ShiftLeft',
23
+ 'ShiftRight',
24
+ 'Tab',
25
+ ];
26
+ export const ContentEditable = React.memo(props => {
27
+ const { value, onSave, className, isEdit, disabledBlur, maxLength, breakWord, regexPattern, ellipsis } = props, restProps = __rest(props, ["value", "onSave", "className", "isEdit", "disabledBlur", "maxLength", "breakWord", "regexPattern", "ellipsis"]);
28
+ const [isEditable, setIsEditable] = useState(false);
29
+ const elementRef = useRef(null);
30
+ useEffect(() => {
31
+ if (isEdit !== undefined) {
32
+ if (!isEdit)
33
+ onSave(elementRef && elementRef.current ? elementRef.current.innerText : '');
34
+ setIsEditable(isEdit);
35
+ }
36
+ // eslint-disable-next-line react-hooks/exhaustive-deps
37
+ }, [isEdit]);
38
+ return (React.createElement(ContentEditableWrapper, Object.assign({}, restProps, { "$breakWord": breakWord, ref: elementRef, className: `${isEditable ? 'editable' : ''} ${className || ''}`, suppressContentEditableWarning: true, contentEditable: true, spellCheck: false, ellipsis: { tooltip: true }, onClick: () => {
39
+ if (!isEditable) {
40
+ setIsEditable(true);
41
+ }
42
+ }, onBlur: (e) => {
43
+ if (disabledBlur)
44
+ return;
45
+ setIsEditable(false);
46
+ onSave(e.target.innerText, e);
47
+ }, onKeyDown: (e) => {
48
+ var _a;
49
+ if (!isEditable)
50
+ e.preventDefault();
51
+ // Check letters are selected => user want to replace it => allow edit
52
+ const selectedLetter = (_a = window.getSelection()) === null || _a === void 0 ? void 0 : _a.toString().length;
53
+ // Check user want select all text
54
+ const isSelectAll = e.code === 'KeyA' && e.ctrlKey;
55
+ if (!IGNORE_KEY_CODE.includes(e.code) &&
56
+ !selectedLetter &&
57
+ !isSelectAll &&
58
+ regexPattern &&
59
+ !e.code.match(regexPattern) &&
60
+ !isSelectAll)
61
+ e.preventDefault();
62
+ if (e.code === 'Enter') {
63
+ e.preventDefault();
64
+ onSave(e.currentTarget.innerText);
65
+ setIsEditable(false);
66
+ }
67
+ // NOTE: check current text length
68
+ if (maxLength &&
69
+ e.currentTarget.innerText.length >= maxLength &&
70
+ !IGNORE_KEY_CODE.includes(e.code) &&
71
+ !selectedLetter &&
72
+ !isSelectAll) {
73
+ e.preventDefault();
74
+ }
75
+ } }), value));
76
+ });
@@ -0,0 +1 @@
1
+ export { ContentEditable } from './ContentEditable';
@@ -0,0 +1 @@
1
+ export { ContentEditable } from './ContentEditable';
@@ -0,0 +1,4 @@
1
+ /// <reference types="react" />
2
+ export declare const ContentEditableWrapper: import("styled-components").StyledComponent<import("react").ForwardRefExoticComponent<import("antd/es/typography/Text").TextProps & import("react").RefAttributes<HTMLSpanElement>>, any, {
3
+ $breakWord?: boolean | undefined;
4
+ }, never>;
@@ -0,0 +1,20 @@
1
+ // Libraries
2
+ import styled from 'styled-components';
3
+ import { Typography } from '@antscorp/antsomi-ui/es/components';
4
+ export const ContentEditableWrapper = styled(Typography.Text) `
5
+ outline-width: 0;
6
+ caret-color: transparent;
7
+ border-radius: 4px;
8
+ display: inline-flex !important;
9
+ align-items: center !important;
10
+ word-break: ${props => (props.$breakWord ? 'break-word' : 'normal')};
11
+
12
+ &.editable {
13
+ outline: 2px solid var(--text-link-color);
14
+ outline-offset: -2px;
15
+ caret-color: unset;
16
+ }
17
+
18
+ padding: 4px;
19
+ /* font-weight: bold; */
20
+ `;
@@ -32,6 +32,7 @@ export { ScrollBox } from './ScrollBox';
32
32
  export { Rate } from './Rate';
33
33
  export { SliderV2 } from './SliderV2';
34
34
  export { InputDynamic } from './InputDynamic';
35
+ export { ContentEditable } from './ContentEditable';
35
36
  export * from './Flex';
36
37
  export * from './RateV2';
37
38
  export * from './PreviewTabs';
@@ -32,6 +32,7 @@ export { ScrollBox } from './ScrollBox';
32
32
  export { Rate } from './Rate';
33
33
  export { SliderV2 } from './SliderV2';
34
34
  export { InputDynamic } from './InputDynamic';
35
+ export { ContentEditable } from './ContentEditable';
35
36
  export * from './Flex';
36
37
  export * from './RateV2';
37
38
  export * from './PreviewTabs';
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ interface Page {
3
+ id: string;
4
+ name: string;
5
+ mode?: string;
6
+ }
7
+ interface EditorTabProps {
8
+ hiddenMenuOption?: boolean;
9
+ className?: string;
10
+ pages: Page[];
11
+ pageActiveId?: string;
12
+ onChangeActivePage?: (id: string) => void;
13
+ onDuplicate?: (id: string) => void;
14
+ onRemove?: (id: string) => void;
15
+ onSaveName?: (id: string, value: string) => void;
16
+ onDnD?: (page: Page[]) => void;
17
+ }
18
+ export declare const ChartTab: React.FC<EditorTabProps>;
19
+ export {};
@@ -0,0 +1,36 @@
1
+ // Lib
2
+ import React, { useState } from 'react';
3
+ // Utils
4
+ import { ChartTabStyled } from './styled';
5
+ import { Item } from './components/Item';
6
+ import { DndContext } from '@dnd-kit/core';
7
+ import { arrayMove, horizontalListSortingStrategy, SortableContext } from '@dnd-kit/sortable';
8
+ export const ChartTab = props => {
9
+ const { hiddenMenuOption, className, pages, pageActiveId, onChangeActivePage, onDuplicate, onRemove, onSaveName, onDnD, } = props;
10
+ const [activePage, setActivePage] = useState(pageActiveId || (pages === null || pages === void 0 ? void 0 : pages[0].id));
11
+ const [pageList, setPageList] = useState(pages);
12
+ const handleChangeActivePage = (id) => {
13
+ setActivePage(id);
14
+ onChangeActivePage === null || onChangeActivePage === void 0 ? void 0 : onChangeActivePage(id);
15
+ };
16
+ const handleDragEnd = (event) => {
17
+ const { active, over } = event;
18
+ if (active.id !== (over === null || over === void 0 ? void 0 : over.id)) {
19
+ setPageList(items => {
20
+ const oldIndex = items.findIndex(item => item.id === active.id);
21
+ const newIndex = items.findIndex(item => item.id === (over === null || over === void 0 ? void 0 : over.id));
22
+ const newArray = arrayMove(items, oldIndex, newIndex);
23
+ onDnD === null || onDnD === void 0 ? void 0 : onDnD(newArray);
24
+ return arrayMove(items, oldIndex, newIndex);
25
+ });
26
+ }
27
+ };
28
+ return (React.createElement(DndContext, { onDragEnd: handleDragEnd,
29
+ // HACK: trick as click tab => set new active page
30
+ onDragStart: event => {
31
+ var _a;
32
+ handleChangeActivePage((_a = event === null || event === void 0 ? void 0 : event.active) === null || _a === void 0 ? void 0 : _a.id);
33
+ } },
34
+ React.createElement(SortableContext, { items: pageList === null || pageList === void 0 ? void 0 : pageList.map(item => item.id), strategy: horizontalListSortingStrategy },
35
+ React.createElement(ChartTabStyled, { className: className || '' }, pageList.map((pageItem, index) => (React.createElement(Item, { key: pageItem.id, page: pageItem, hiddenMenuOption: hiddenMenuOption, isActive: activePage === pageItem.id, onDuplicate: onDuplicate, onRemove: onRemove, onSaveName: onSaveName })))))));
36
+ };
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ interface Page {
3
+ id: string;
4
+ name: string;
5
+ mode?: string;
6
+ }
7
+ interface ItemProps {
8
+ page: Page;
9
+ hiddenMenuOption?: boolean;
10
+ isActive?: boolean;
11
+ onSaveName?: (id: string, value: string) => void;
12
+ onDuplicate?: (id: string) => void;
13
+ onRemove?: (id: string) => void;
14
+ }
15
+ export declare const Item: React.FC<ItemProps>;
16
+ export {};
@@ -0,0 +1,47 @@
1
+ // Libraries
2
+ import React, { useState } from 'react';
3
+ import { useSortable } from '@dnd-kit/sortable';
4
+ import { CSS } from '@dnd-kit/utilities';
5
+ import Icon from '@antscorp/icons';
6
+ // Styles
7
+ import { ItemStyled } from './styled';
8
+ // Components
9
+ import { ContentEditable, Dropdown, Typography } from '@antscorp/antsomi-ui/es/components';
10
+ export const Item = (props) => {
11
+ const { page, hiddenMenuOption = false, isActive, onSaveName, onDuplicate, onRemove } = props;
12
+ const [isEditable, setIsEditable] = useState(false);
13
+ const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id: page.id });
14
+ const style = {
15
+ transform: CSS.Transform.toString(transform),
16
+ transition,
17
+ };
18
+ return (React.createElement("li", Object.assign({ id: page.id, ref: setNodeRef, style: style }, attributes, listeners),
19
+ React.createElement(ItemStyled, { id: page.id, "$isActive": isActive },
20
+ isEditable ? (React.createElement(ContentEditable, { value: page.name, onSave: newValue => {
21
+ setIsEditable(false);
22
+ onSaveName === null || onSaveName === void 0 ? void 0 : onSaveName(page.id, newValue);
23
+ } })) : (React.createElement(Typography.Text, { ellipsis: { tooltip: true } }, page.name)),
24
+ !hiddenMenuOption ? (React.createElement(Dropdown, { menu: {
25
+ items: [
26
+ { label: 'Rename', key: 'rename' },
27
+ { label: 'Duplicate', key: 'duplicate' },
28
+ { label: 'Remove', key: 'remove' },
29
+ ],
30
+ onClick: ({ key }) => {
31
+ switch (key) {
32
+ case 'rename':
33
+ setIsEditable(true);
34
+ break;
35
+ case 'duplicate':
36
+ onDuplicate === null || onDuplicate === void 0 ? void 0 : onDuplicate(page.id);
37
+ break;
38
+ case 'remove':
39
+ onRemove === null || onRemove === void 0 ? void 0 : onRemove(page.id);
40
+ break;
41
+ default:
42
+ break;
43
+ }
44
+ },
45
+ }, trigger: ['hover'], placement: "topLeft" },
46
+ React.createElement(Icon, { type: "icon-ants-three-dot-vertical", style: { cursor: 'pointer' } }))) : null)));
47
+ };
@@ -0,0 +1,3 @@
1
+ export declare const ItemStyled: import("styled-components").StyledComponent<"div", any, {
2
+ $isActive?: boolean | undefined;
3
+ }, never>;
@@ -0,0 +1,30 @@
1
+ var _a;
2
+ // Libraries
3
+ import styled from 'styled-components';
4
+ // Tokens
5
+ import { THEME } from '@antscorp/antsomi-ui/es/constants';
6
+ export const ItemStyled = styled.div `
7
+ box-sizing: border-box;
8
+ display: flex;
9
+ flex-wrap: nowrap;
10
+ gap: 8px;
11
+ align-items: center;
12
+ justify-content: space-between;
13
+
14
+ height: 32px;
15
+ min-width: 80px;
16
+ max-width: 130px;
17
+
18
+ background-color: ${props => { var _a; return (props.$isActive ? 'white' : (_a = THEME.token) === null || _a === void 0 ? void 0 : _a.bw2); }};
19
+ font-weight: ${props => (props.$isActive ? 500 : 400)};
20
+ padding: 6px 10px;
21
+
22
+ &:hover {
23
+ font-weight: 500;
24
+ background-color: ${(_a = THEME.token) === null || _a === void 0 ? void 0 : _a.blue} !important;
25
+ }
26
+
27
+ span[contenteditable='true'] {
28
+ flex: 1;
29
+ }
30
+ `;
@@ -0,0 +1 @@
1
+ export declare const ChartTabStyled: import("styled-components").StyledComponent<"ul", any, {}, never>;
@@ -0,0 +1,23 @@
1
+ import { globalToken } from '@antscorp/antsomi-ui/es/constants';
2
+ import styled from 'styled-components';
3
+ export const ChartTabStyled = styled.ul `
4
+ list-style-type: none;
5
+ display: flex;
6
+
7
+ & > li {
8
+ border: 1px solid #e5e5e5;
9
+ cursor: default;
10
+
11
+ &:first-child {
12
+ overflow: hidden;
13
+ border-top-left-radius: ${globalToken === null || globalToken === void 0 ? void 0 : globalToken.borderRadius}px;
14
+ border-bottom-left-radius: ${globalToken === null || globalToken === void 0 ? void 0 : globalToken.borderRadius}px;
15
+ /* border-top-left-radius: ${globalToken === null || globalToken === void 0 ? void 0 : globalToken.borderRadius}; */
16
+ }
17
+ &:last-child {
18
+ overflow: hidden;
19
+ border-top-right-radius: ${globalToken === null || globalToken === void 0 ? void 0 : globalToken.borderRadius}px;
20
+ border-bottom-right-radius: ${globalToken === null || globalToken === void 0 ? void 0 : globalToken.borderRadius}px;
21
+ }
22
+ }
23
+ `;
@@ -0,0 +1,35 @@
1
+ import React from 'react';
2
+ interface EditorTabItem {
3
+ showIcon?: boolean;
4
+ showDropdown?: boolean;
5
+ closeable?: boolean;
6
+ formatSelectedText: string;
7
+ formattedQuery: string;
8
+ id: string;
9
+ name: string;
10
+ query: string;
11
+ type: string;
12
+ selectedTextOut: string;
13
+ queryResult: any;
14
+ cursorSql?: string;
15
+ cursorSqlOut?: string;
16
+ refreshAndFocusId?: string;
17
+ }
18
+ interface EditorTabProps {
19
+ showArrow?: boolean;
20
+ showDropdown?: boolean;
21
+ disabledScroll?: boolean;
22
+ showComposeNewQuery?: boolean;
23
+ className?: string;
24
+ leftBlockClassName?: string;
25
+ tabItemClassName?: string;
26
+ listTab?: EditorTabItem[];
27
+ activeId?: string;
28
+ onActiveTab: (id: string) => void;
29
+ onCloseTab: (tab: EditorTabItem, index: number, newTabs: EditorTabItem[]) => void;
30
+ onConfigure: (id: string) => void;
31
+ onSaveName?: (id: string, value: string) => void;
32
+ handleAddTab: () => void;
33
+ }
34
+ export declare const EditorTab: React.FC<EditorTabProps>;
35
+ export {};
@@ -0,0 +1,159 @@
1
+ // Lib
2
+ import React, { useEffect, useMemo, useRef, useState } from 'react';
3
+ import classnames from 'classnames';
4
+ // Components
5
+ import Icon from '@antscorp/icons/main';
6
+ import { Button, Typography, Dropdown, ContentEditable } from '@antscorp/antsomi-ui/es/components';
7
+ // Styles
8
+ import { EditorTabStyled } from './styled';
9
+ // Utils
10
+ import { handleError } from '@antscorp/antsomi-ui/es/utils';
11
+ const PATH = 'src/components/EditorTab/index.jsx';
12
+ const constants = {
13
+ TAB_TYPE: {
14
+ QUERY: 'query',
15
+ TABLE_DETAIL: 'table-detail',
16
+ },
17
+ };
18
+ export const EditorTab = props => {
19
+ var _a;
20
+ const { listTab = [], activeId = '', showArrow, showDropdown, disabledScroll, onCloseTab, onActiveTab, handleAddTab, onConfigure, onSaveName, showComposeNewQuery, className, leftBlockClassName, tabItemClassName, } = props;
21
+ const [activeTabId, setActiveTabId] = useState(activeId || ((_a = listTab === null || listTab === void 0 ? void 0 : listTab[0]) === null || _a === void 0 ? void 0 : _a.id));
22
+ const [arrTabs, setArrTabs] = useState(listTab || []);
23
+ const [isEditable, setIsEditable] = useState();
24
+ // Ref
25
+ const leftBlockRef = useRef(null);
26
+ const activeTabIdx = useMemo(() => {
27
+ return arrTabs.findIndex(tab => tab.id === activeId);
28
+ }, [activeId]);
29
+ useEffect(() => {
30
+ if (listTab.length - arrTabs.length === 1) {
31
+ setActiveTabId(listTab[listTab.length - 1].id);
32
+ }
33
+ setArrTabs(listTab);
34
+ }, [listTab]);
35
+ useEffect(() => {
36
+ onActiveTab(activeTabId);
37
+ setTimeout(() => {
38
+ if (!disabledScroll) {
39
+ const tabEl = document.getElementById(`tab-${activeTabId}`);
40
+ if (tabEl) {
41
+ tabEl.scrollIntoView({ block: 'center', inline: 'center', behavior: 'smooth' });
42
+ }
43
+ }
44
+ }, 500);
45
+ }, [activeTabId]);
46
+ useEffect(() => {
47
+ if (activeId && activeTabId !== activeId) {
48
+ setActiveTabId(activeId);
49
+ }
50
+ }, [activeId]);
51
+ const handleAddNew = () => {
52
+ handleAddTab();
53
+ };
54
+ const handleCloseTab = (e, tab, idx) => {
55
+ e.stopPropagation();
56
+ if (arrTabs.length < 2) {
57
+ return;
58
+ }
59
+ if (activeTabId === tab.id) {
60
+ if (idx === arrTabs.length - 1) {
61
+ setActiveTabId(arrTabs[idx - 1].id);
62
+ }
63
+ else if (arrTabs.length > 1) {
64
+ setActiveTabId(arrTabs[idx + 1].id);
65
+ }
66
+ }
67
+ setArrTabs(prevTabs => {
68
+ const newTabs = [...prevTabs];
69
+ newTabs.splice(idx, 1);
70
+ onCloseTab(tab, idx, newTabs);
71
+ return newTabs;
72
+ });
73
+ };
74
+ const handleActiveTab = (tab, idx) => {
75
+ setActiveTabId(tab.id);
76
+ };
77
+ const onWheelLeftBlock = event => {
78
+ try {
79
+ if (!event.deltaY) {
80
+ return;
81
+ }
82
+ event.currentTarget.scrollLeft += event.deltaY + event.deltaX;
83
+ }
84
+ catch (error) {
85
+ handleError(error, {
86
+ path: PATH,
87
+ name: 'onWheelLeftBlock',
88
+ args: {},
89
+ });
90
+ }
91
+ };
92
+ const onClickArrow = (direction = 'left') => {
93
+ const idx = arrTabs.findIndex(tab => tab.id === activeTabId);
94
+ if (idx !== -1) {
95
+ switch (direction) {
96
+ case 'left':
97
+ if (idx === 0) {
98
+ return;
99
+ }
100
+ setActiveTabId(arrTabs[idx - 1].id);
101
+ break;
102
+ case 'right':
103
+ if (idx === arrTabs.length - 1) {
104
+ return;
105
+ }
106
+ setActiveTabId(arrTabs[idx + 1].id);
107
+ break;
108
+ }
109
+ }
110
+ };
111
+ return (React.createElement(EditorTabStyled, { className: className || '' },
112
+ showArrow && (React.createElement("div", { className: classnames('arrow-btn', {
113
+ '--disabled': activeTabIdx === 0,
114
+ }), onClick: () => onClickArrow('left') },
115
+ React.createElement(Icon, { type: "icon-ants-angle-left" }))),
116
+ React.createElement("div", { ref: leftBlockRef, className: classnames('left-block', leftBlockClassName), onWheel: onWheelLeftBlock }, arrTabs && arrTabs.length
117
+ ? arrTabs.map((tab, idx) => {
118
+ const { showIcon = true, closeable = true } = tab;
119
+ // const { showIcon = true, showDropdown = true, closeable = true } = tab;
120
+ return (React.createElement("div", { key: tab.id, id: `tab-${tab.id}`, onClick: () => handleActiveTab(tab, idx), className: classnames('tab-item', tabItemClassName, {
121
+ active: tab.id === activeTabId,
122
+ }) },
123
+ showIcon &&
124
+ (tab.type === constants.TAB_TYPE.QUERY ? (React.createElement(Icon, { type: "icon-ants-material-outline-manage-search", overlayStyle: { fontSize: 21 } })) : (React.createElement(Icon, { type: "icon-ants-table-vertical", overlayStyle: { fontSize: 21 } }))),
125
+ isEditable === tab.id ? (React.createElement(ContentEditable, { value: tab.name, onSave: newValue => {
126
+ setIsEditable(undefined);
127
+ onSaveName === null || onSaveName === void 0 ? void 0 : onSaveName(tab.id, newValue);
128
+ } })) : (React.createElement(Typography.Text, { ellipsis: { tooltip: true } }, tab.name)),
129
+ showDropdown ? (React.createElement(Dropdown, { menu: {
130
+ items: [
131
+ { label: 'Configure', key: 'configure' },
132
+ { label: 'Remove', key: 'remove' },
133
+ ],
134
+ onClick: ({ key, domEvent }) => {
135
+ switch (key) {
136
+ case 'configure':
137
+ console.log('click configure', domEvent);
138
+ setIsEditable(tab.id);
139
+ onConfigure === null || onConfigure === void 0 ? void 0 : onConfigure(tab.id);
140
+ break;
141
+ case 'remove':
142
+ handleCloseTab(domEvent, tab, idx);
143
+ break;
144
+ default:
145
+ break;
146
+ }
147
+ },
148
+ }, placement: "bottomRight", trigger: ['click'] },
149
+ React.createElement(Button, { icon: React.createElement(Icon, { type: "icon-ants-angle-left", overlayStyle: { fontSize: 12 } }), style: { transform: 'rotate(-90deg)' }, size: "small" }))) : closeable ? (React.createElement(Button, { icon: React.createElement(Icon, { type: "icon-ants-remove-slim", onClick: e => handleCloseTab(e, tab, idx), overlayStyle: { fontSize: 12 } }), size: "small" })) : null));
150
+ })
151
+ : null),
152
+ showArrow && (React.createElement("div", { className: classnames('arrow-btn', '--right', {
153
+ '--disabled': activeTabIdx === arrTabs.length - 1,
154
+ }), onClick: () => onClickArrow('right') },
155
+ React.createElement(Icon, { type: "icon-ants-angle-right" }))),
156
+ showComposeNewQuery && (React.createElement(Button, { onClick: handleAddNew, className: "new-query-btn" },
157
+ React.createElement(Icon, { type: "icon-ants-add-square" }),
158
+ "New query"))));
159
+ };
@@ -0,0 +1 @@
1
+ export { EditorTab } from './EditorTab';
@@ -0,0 +1 @@
1
+ export { EditorTab } from './EditorTab';
@@ -0,0 +1 @@
1
+ export declare const EditorTabStyled: import("styled-components").StyledComponent<"div", any, {}, never>;
@@ -0,0 +1,132 @@
1
+ var _a, _b, _c;
2
+ import styled from 'styled-components';
3
+ import { THEME } from '@antscorp/antsomi-ui/es/constants';
4
+ // const token = theme.getDesignToken(THEME);
5
+ export const EditorTabStyled = styled.div `
6
+ position: relative;
7
+ height: 40px;
8
+ display: flex;
9
+ align-items: center;
10
+
11
+ /* Styled for icon button */
12
+ button.antsomi-btn-icon-only.antsomi-btn-sm {
13
+ margin-left: auto;
14
+ border: none !important;
15
+ background-color: transparent !important;
16
+ flex-shrink: 0;
17
+ width: 20px !important;
18
+ height: 20px !important;
19
+ &:hover {
20
+ background-color: ${(_a = THEME.token) === null || _a === void 0 ? void 0 : _a.blue} !important;
21
+ }
22
+ }
23
+
24
+ .left-block {
25
+ position: relative;
26
+ height: 100%;
27
+ width: 100%;
28
+ flex-grow: 1;
29
+ flex-flow: nowrap;
30
+ display: flex;
31
+ align-items: center;
32
+ overflow-x: auto;
33
+ overflow-y: hidden;
34
+
35
+ font-size: 14px;
36
+ color: #222;
37
+
38
+ &::-webkit-scrollbar {
39
+ display: none;
40
+ }
41
+
42
+ .tab-item {
43
+ position: relative;
44
+ box-sizing: border-box;
45
+
46
+ display: flex;
47
+ align-items: center;
48
+ flex-shrink: 0;
49
+ gap: 7px;
50
+ width: 150px;
51
+ height: 40px;
52
+ padding: 0 10px;
53
+ overflow: hidden;
54
+ max-width: 200px;
55
+ background-color: ${(_b = THEME.token) === null || _b === void 0 ? void 0 : _b.bw2};
56
+
57
+ &:hover {
58
+ background-color: ${(_c = THEME.token) === null || _c === void 0 ? void 0 : _c.blue};
59
+ }
60
+
61
+ white-space: nowrap;
62
+
63
+ transition: background-color 300ms ease-in-out;
64
+ cursor: pointer;
65
+
66
+ i {
67
+ font-size: 20px;
68
+ color: #666;
69
+ }
70
+
71
+ &::after {
72
+ content: '';
73
+ position: absolute;
74
+ bottom: 0;
75
+ left: 0;
76
+ height: 3px;
77
+ width: 100%;
78
+ background-color: #1f5fac;
79
+
80
+ transform-origin: center;
81
+ transform: scaleX(0);
82
+ transition: transform 300ms ease-in-out;
83
+ }
84
+
85
+ &.active {
86
+ &::after {
87
+ transform: scaleX(1);
88
+ }
89
+ background-color: #fff;
90
+ }
91
+ }
92
+
93
+ ::-webkit-scrollbar {
94
+ -webkit-appearance: none;
95
+ display: none !important;
96
+ }
97
+ ::-webkit-scrollbar-thumb {
98
+ display: none !important;
99
+ }
100
+ }
101
+
102
+ button.new-query-btn {
103
+ margin-left: 10px;
104
+ border: none;
105
+ }
106
+
107
+ .arrow-btn {
108
+ /* Structure Block */
109
+ flex-shrink: 0;
110
+ height: 100%;
111
+ width: 40px;
112
+ display: flex;
113
+ align-items: center;
114
+ justify-content: center;
115
+ /* border-right: 1px solid #e0e0e0; */
116
+
117
+ /* Typography Block */
118
+ font-size: 12px;
119
+
120
+ cursor: pointer;
121
+
122
+ &.--right {
123
+ border-right: 1px solid #e0e0e0;
124
+ }
125
+
126
+ &.--disabled {
127
+ cursor: not-allowed;
128
+ pointer-events: none;
129
+ opacity: 0.7;
130
+ }
131
+ }
132
+ `;
@@ -52,6 +52,7 @@ export * from './Drawer';
52
52
  export * from './DrawerDetail';
53
53
  export { EditorScript } from './EditorScript';
54
54
  export { CalendarSelection, CalendarSelectionConstants } from './CalendarSelection';
55
+ export { EditorTab } from './EditorTab';
55
56
  export type { AdvancedPickerProps, TAdvancedPickerOption, TAdvancedRangePickerTimeRange, } from './DatePicker';
56
57
  export type { ColorPickerProps } from './ColorPicker';
57
58
  export type { AlignEditProps, AlignSettingProps } from './AlignSetting';
@@ -52,3 +52,4 @@ export * from './Drawer';
52
52
  export * from './DrawerDetail';
53
53
  export { EditorScript } from './EditorScript';
54
54
  export { CalendarSelection, CalendarSelectionConstants } from './CalendarSelection';
55
+ export { EditorTab } from './EditorTab';
@@ -31,7 +31,7 @@ import { useDeepCompareEffect } from '@antscorp/antsomi-ui/es/hooks';
31
31
  import { useDebounce } from '@antscorp/antsomi-ui/es/hooks/useDebounceV2';
32
32
  // Provider
33
33
  import { useContentSourceDispatch, useSelectBoIdByGroupFromCS, useSelectContentSources, useSelectModeView, } from './provider';
34
- import { deleteContentSourceGroup, setContentSourceGroup, setContentSourceGroupBOData, updateContentSourceSettings, updateModeView, } from './reducer';
34
+ import { deleteContentSourceGroup, setContentSourceGroup, setContentSourceGroupBOData, updateContentSourceSettings, updateModeView, emitItemTypeChange, } from './reducer';
35
35
  // Utils
36
36
  import { handleError } from '@antscorp/antsomi-ui/es/utils';
37
37
  const PATH = 'src/components/organism/ContentSources/Settings.tsx';
@@ -150,8 +150,7 @@ const Settings = (props) => {
150
150
  const { itemTypeId } = action.payload;
151
151
  if (itemTypeId) {
152
152
  handleChangeItemTypeId({ groupId, id: itemTypeId });
153
- if (onBOChange)
154
- onBOChange({ itemTypeId });
153
+ contentSourceDispatch(emitItemTypeChange());
155
154
  }
156
155
  break;
157
156
  }
@@ -20,6 +20,7 @@ export const CONTENT_SOURCES_SETTINGS_DEFAULT = {
20
20
  groups: [],
21
21
  expanded: [],
22
22
  isLoadingDataBO: false,
23
+ emitItemTypeChange: 0,
23
24
  };
24
25
  export const ARTICLE_RANKING_DEFAULT = {
25
26
  type: 'algorithms',
@@ -13,5 +13,6 @@ export declare const useSelectServiceAuth: () => import("@antscorp/antsomi-ui/es
13
13
  export declare const useSelectContentSources: () => import("./types").TContentSourceSettings;
14
14
  export declare const useSelectCSGroups: () => import("./types").TContentSourceGroup[];
15
15
  export declare const useSelectModeView: () => import("./types").ContentSourceModeView;
16
+ export declare const useSelectEmitContentSourceItemType: () => number;
16
17
  export declare const useSelectBoIdByGroupFromCS: () => Record<string, number>;
17
18
  export declare const useSelectDataTableBOByGroupId: (groupId: string) => Record<string, any>[];
@@ -30,6 +30,10 @@ export const useSelectModeView = () => {
30
30
  const { mode } = useContentSourceState();
31
31
  return useMemo(() => mode, [mode]);
32
32
  };
33
+ export const useSelectEmitContentSourceItemType = () => {
34
+ const { emitItemTypeChange } = useSelectContentSources();
35
+ return useMemo(() => emitItemTypeChange, [emitItemTypeChange]);
36
+ };
33
37
  export const useSelectBoIdByGroupFromCS = () => {
34
38
  const csGroups = useSelectCSGroups();
35
39
  const result = useMemo(() => {
@@ -1,4 +1,4 @@
1
- import { UpdateGroupAction, TContentSourceSettings, TContentSourceGroup, ActionSetContentSourceGroup, ActionDeleteContentSourceGroup, ContentSourceModeView, ActionUpdateModeView, ActionUpdateContentSourceSettings, ActionSetContentSourceGroupBOData } from './types';
1
+ import { UpdateGroupAction, TContentSourceSettings, TContentSourceGroup, ActionSetContentSourceGroup, ActionDeleteContentSourceGroup, ContentSourceModeView, ActionUpdateModeView, ActionUpdateContentSourceSettings, ActionSetContentSourceGroupBOData, ActionEmitItemTypeChange } from './types';
2
2
  import { TServiceAuth } from '@antscorp/antsomi-ui/es/types';
3
3
  export interface ContentSourceState {
4
4
  serviceAuth: TServiceAuth;
@@ -16,3 +16,4 @@ export declare const deleteContentSourceGroup: (groupId: string) => ActionDelete
16
16
  export declare const updateModeView: (mode: ContentSourceModeView) => ActionUpdateModeView;
17
17
  export declare const updateContentSourceSettings: (contentSources: TContentSourceSettings) => ActionUpdateContentSourceSettings;
18
18
  export declare const setContentSourceGroupBOData: (boDataByGroupId: Record<string, any[]>) => ActionSetContentSourceGroupBOData;
19
+ export declare const emitItemTypeChange: () => ActionEmitItemTypeChange;
@@ -72,6 +72,10 @@ export const contentSourceReducer = (state, action) => produce(state, draft => {
72
72
  });
73
73
  break;
74
74
  }
75
+ case 'EMIT_ITEM_TYPE_CHANGE': {
76
+ draft.contentSources.emitItemTypeChange += 1;
77
+ break;
78
+ }
75
79
  default: {
76
80
  return state;
77
81
  }
@@ -102,3 +106,7 @@ export const setContentSourceGroupBOData = (boDataByGroupId) => ({
102
106
  boDataByGroupId,
103
107
  },
104
108
  });
109
+ export const emitItemTypeChange = () => ({
110
+ type: 'EMIT_ITEM_TYPE_CHANGE',
111
+ payload: null,
112
+ });
@@ -43,6 +43,7 @@ export type TContentSourceSettings = {
43
43
  groups: TContentSourceGroup[];
44
44
  expanded: string[];
45
45
  isLoadingDataBO: boolean;
46
+ emitItemTypeChange: number;
46
47
  };
47
48
  export interface HideOptionTypes {
48
49
  filter?: boolean;
@@ -141,5 +142,8 @@ export interface ActionSetContentSourceGroupBOData extends Action {
141
142
  boDataByGroupId: Record<string, any[]>;
142
143
  };
143
144
  }
144
- export type UpdateGroupAction = ActionUpdateContentSourceSettings | ActionSetContentSourceGroupBOData | ActionServiceAuth | ActionAddContentSource | ActionUpdateModeView | ActionDeleteContentSourceGroup | ActionSetContentSourceGroup | ActionUpdateSource | ActionUpdateFilter | ActionUpdateFallback | ActionUpdateName | ActionUpdateAlgorithms | ActionUpdateExpanded | ActionUpdateLevel;
145
+ export interface ActionEmitItemTypeChange extends Action {
146
+ type: 'EMIT_ITEM_TYPE_CHANGE';
147
+ }
148
+ export type UpdateGroupAction = ActionUpdateContentSourceSettings | ActionSetContentSourceGroupBOData | ActionServiceAuth | ActionAddContentSource | ActionUpdateModeView | ActionDeleteContentSourceGroup | ActionSetContentSourceGroup | ActionUpdateSource | ActionUpdateFilter | ActionUpdateFallback | ActionUpdateName | ActionUpdateAlgorithms | ActionUpdateExpanded | ActionUpdateLevel | ActionEmitItemTypeChange;
145
149
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antscorp/antsomi-ui",
3
- "version": "1.3.5-beta.272",
3
+ "version": "1.3.5-beta.274",
4
4
  "description": "An enterprise-class UI design language and React UI library.",
5
5
  "sideEffects": [
6
6
  "dist/*",
@@ -63,6 +63,9 @@
63
63
  "@antscorp/icons": "^0.27.23",
64
64
  "@antscorp/image-editor": "1.0.2",
65
65
  "@antscorp/processing-notification": "^1.0.3",
66
+ "@dnd-kit/core": "^6.1.0",
67
+ "@dnd-kit/sortable": "^8.0.0",
68
+ "@dnd-kit/utilities": "^3.2.2",
66
69
  "@emotion/react": "^11.11.1",
67
70
  "@fortawesome/fontawesome-svg-core": "6.1.1",
68
71
  "@fortawesome/free-brands-svg-icons": "6.1.1",