From fba63985999184132952904fad0db70fa577e7e3 Mon Sep 17 00:00:00 2001 From: Pavlo Stasiv <99363993+StasivPavlo@users.noreply.github.com> Date: Thu, 15 Dec 2022 09:54:55 +0200 Subject: [PATCH 01/11] add component Cascade Select --- .../bl-cascadeSelect-component/component.json | 24 ++++++ .../bl-cascadeSelect-component/src/helpers.js | 68 +++++++++++++++++ .../bl-cascadeSelect-component/src/index.js | 62 +++++++++++++++ .../src/subcomponent.js | 76 +++++++++++++++++++ .../styles/index.less | 73 ++++++++++++++++++ 5 files changed, 303 insertions(+) create mode 100644 components/bl-cascadeSelect-component/component.json create mode 100644 components/bl-cascadeSelect-component/src/helpers.js create mode 100644 components/bl-cascadeSelect-component/src/index.js create mode 100644 components/bl-cascadeSelect-component/src/subcomponent.js create mode 100644 components/bl-cascadeSelect-component/styles/index.less diff --git a/components/bl-cascadeSelect-component/component.json b/components/bl-cascadeSelect-component/component.json new file mode 100644 index 000000000..ec2269a94 --- /dev/null +++ b/components/bl-cascadeSelect-component/component.json @@ -0,0 +1,24 @@ +{ + "id": "c_4709a015328b307e652d915fc3f36fb7", + "name": "Cascade Select", + "description": "", + "showInToolbox": true, + "faIcon": "pencil-ruler", + "mainJS": "dist/index.js", + "type": "custom", + "category": "Custom Components", + "properties": [ + { + "type": "json", + "name": "cascade", + "label": "Cascade", + "showInSettings": true, + "hasLogicHandler": true, + "handlerId": "cascadeLogic", + "handlerLabel": "Cascade Logic", + "dataBinding": true + } + ], + "eventHandlers": [], + "actions": [] +} \ No newline at end of file diff --git a/components/bl-cascadeSelect-component/src/helpers.js b/components/bl-cascadeSelect-component/src/helpers.js new file mode 100644 index 000000000..f15a303e6 --- /dev/null +++ b/components/bl-cascadeSelect-component/src/helpers.js @@ -0,0 +1,68 @@ +export function isCyclic(obj) { + const keys = []; + const stack = []; + const stackSet = new Set(); + let detected = false; + let locate; + + function detect(obj, key) { + if (obj && typeof obj != 'object') { + return; + } + + if (stackSet.has(obj)) { + locate = keys.join('.') + '.' + key; + detected = true; + + return; + } + + keys.push(key); + stack.push(obj); + stackSet.add(obj); + + for (const k in obj) { + if (Object.prototype.hasOwnProperty.call(obj, k)) { + detect(obj[k], k); + } + } + + keys.pop(); + stack.pop(); + stackSet.delete(obj); + + return; + } + + detect(obj, 'obj'); + + return [detected, locate]; +} + +export const prepareCascade = (cascade, setParentItems) => { + let levelOfNesting = 0; + + const prepare = (cascade) => { + const validCascade = cascade.map(item => { + let validItem = { ...item, levelOfNesting }; + + if (item.children) { + levelOfNesting++; + validItem = { + ...validItem, + children: prepare(item.children) + }; + + setParentItems(state => [...state, { code: item.code, isOpen: false, levelOfNesting }]); + } + + return validItem; + }); + + levelOfNesting--; + + return validCascade; + }; + + return prepare(cascade); +}; diff --git a/components/bl-cascadeSelect-component/src/index.js b/components/bl-cascadeSelect-component/src/index.js new file mode 100644 index 000000000..0a19dc335 --- /dev/null +++ b/components/bl-cascadeSelect-component/src/index.js @@ -0,0 +1,62 @@ +import { useState, useEffect, useCallback } from 'react'; +import { CollapseButtonIcon, Cascade } from './subcomponent'; +import { prepareCascade, isCyclic } from './helpers'; + +const { cn } = BackendlessUI.CSSUtils; + +export default function CascadeSelect({ component, eventHandlers, settings, instanceId }) { + const { display, classList, style, cascade } = component; + + const [selected, setSelected] = useState({ name: 'Select a...' }); + const [itemsCascade, setItemsCascade] = useState(); + const [parentItems, setParentItems] = useState([]); + const [isOpen, setIsOpen] = useState(false); + + console.log(parentItems); + + useEffect(() => { + const [detected, locate] = isCyclic(cascade); + + if (detected) { + throw new Error('cascade have cycling object in ' + locate); + } + + if (cascade) { + setItemsCascade(prepareCascade(cascade, setParentItems)); + } + }, [cascade]); + + const openCascadeHandler = (item) => { + setParentItems(state => state.map(parentItem => ( + item.code === parentItem.code ? { ...parentItem, isOpen: !item.isOpen } : parentItem + ))); + }; + + const openItemHandler = (item) => { + setSelected(item); + setIsOpen(false); + // setParentItems(state => state.map(parentItem => ({ ...parentItem, isOpen: false }))); + }; + + if (!display) { + return null; + } + + return ( +
+
setIsOpen(state => !state) }> + { selected.name } + +
+ +
+ ); +} diff --git a/components/bl-cascadeSelect-component/src/subcomponent.js b/components/bl-cascadeSelect-component/src/subcomponent.js new file mode 100644 index 000000000..916610dc8 --- /dev/null +++ b/components/bl-cascadeSelect-component/src/subcomponent.js @@ -0,0 +1,76 @@ +const { cn } = BackendlessUI.CSSUtils; + +export function Cascade(props) { + const { isOpen, itemsCascade, parentItems, levelOfNesting, openItemHandler, openCascadeHandler, selected } = props; + + if (!isOpen) { + return null; + } + + return ( + + ); +} + +export function CascadeItem({ item, parentItems, openItemHandler, openCascadeHandler, selected }) { + if (item.children) { + const { isOpen } = parentItems.find(parent => parent.code === item.code); + + return ( +
  • +
    openCascadeHandler(item) }> + { item.name } + + + +
    + + { isOpen && ( + + ) } +
  • + ); + } + + return ( +
  • openItemHandler(item) }> + { item.name } +
  • + ); +} + +export function CollapseButtonIcon() { + return ( + + + + ); +} diff --git a/components/bl-cascadeSelect-component/styles/index.less b/components/bl-cascadeSelect-component/styles/index.less new file mode 100644 index 000000000..b6797dc7c --- /dev/null +++ b/components/bl-cascadeSelect-component/styles/index.less @@ -0,0 +1,73 @@ +// you can use LESS variables from the current Theme and app extensions of the UI-Container + +.bl-cascadeSelect-component { + position: relative; + width: 200px; + + .cascade-select { + &__input { + display: flex; + justify-content: space-between; + align-items: center; + + padding: 10px; + + cursor: pointer; + + border: 1px solid #ced4da; + border-radius: 6px; + + color: #6c757d; + + transition: border-color 0.3s; + + &--selected { + color: @appTextColor; + } + + &:hover { + border-color: @themePrimary; + } + } + + &__list { + margin: 0; + min-width: 200px; + position: absolute; + top: 100%; + padding: 10px 0; + list-style: none; + background: #fff; + border-radius: 6px; + box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px; + } + + &__item { + display: flex; + justify-content: space-between; + padding: 10px 17px; + + transition: background-color 0.3s; + + &:hover { + background-color: #e9ecef; + } + + &--open { + background-color: lighten(@themePrimary, 30%); + } + } + + &__collapse-button-icon { + width: 30px; + height: 30px; + fill: #aaa; + } + + &__collapse-icon { + height: 15px; + width: 15px; + transform: rotate(-90deg); + } + } +} From c374578c8752be926f553b6b2655a27b95f79779 Mon Sep 17 00:00:00 2001 From: Pavlo Stasiv <99363993+StasivPavlo@users.noreply.github.com> Date: Thu, 22 Dec 2022 15:36:49 +0200 Subject: [PATCH 02/11] finished component, added README.md and preview.html --- .../bl-cascadeSelect-component/README.md | 39 +++++++ .../bl-cascadeSelect-component/component.json | 42 ++++++- .../example-images/cascade_example.jpg | Bin 0 -> 61903 bytes .../bl-cascadeSelect-component/preview.html | 1 + .../bl-cascadeSelect-component/src/helpers.js | 26 ++++- .../bl-cascadeSelect-component/src/index.js | 49 ++++++--- .../src/subcomponent.js | 28 ++--- .../styles/index.less | 103 ++++++++++++++---- 8 files changed, 229 insertions(+), 59 deletions(-) create mode 100644 components/bl-cascadeSelect-component/README.md create mode 100644 components/bl-cascadeSelect-component/example-images/cascade_example.jpg create mode 100644 components/bl-cascadeSelect-component/preview.html diff --git a/components/bl-cascadeSelect-component/README.md b/components/bl-cascadeSelect-component/README.md new file mode 100644 index 000000000..70a57a128 --- /dev/null +++ b/components/bl-cascadeSelect-component/README.md @@ -0,0 +1,39 @@ +# Cascade Select + +Cascade Select is a component of Backendless UI-Builder designer. This allows you to select a value from a nested structure of options. + +The component based on external [Cascade Select](https://www.primefaces.org/primereact/cascadeselect/). + +## Properties + +| Property | Type | Default Value | Logic | Data Binding | UI Setting | Description | +|-------------------|---------|---------------------|-----------------------------|--------------|------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| cascade | JSON | | Cascade Logic | YES | YES | Allows determinate an array of select items to display as the available options. Watch [Codeless Examples](#Examples). Signature of polygon: `[{name, code, ?children}]` | +| placeholder | String | | Placeholder Logic | YES | YES | Allows determinate placeholder for input | + +## Events + +| Name | Triggers | Context Blocks | +|---------------|-------------------------------|--------------------------------------------------------------| +| On Click Item | when the user select the item | Item: `{name: String, code: String, levelOfNesting: Number}` | + +## Action + +| Action | Inputs | Return | +|---------------|--------|--------------------------| +| Get Select in | | Object: of a select item | + +## Codeless Examples + +Addition of cascade data + +![](example-images/cascade_example.jpg) + +
    +Try yourself + +``` +AustraliaAUNew South WalesAU-NSWSydneyAU-NSW-SYNewcastleAU-NSW-NCWollongongAU-NSW-WGQueenslandAU-QSBrisbaneAU-QS-BBTownsvilleAU-QS-TSCanadaCAQuebecCA-QBMontrealCA-QB-MRQuebec CityCA-QB-CBCOntarioCA-OTOttawaCA-OT-OWTorontoCA-OT-TR +``` +
    + diff --git a/components/bl-cascadeSelect-component/component.json b/components/bl-cascadeSelect-component/component.json index ec2269a94..f30742ce5 100644 --- a/components/bl-cascadeSelect-component/component.json +++ b/components/bl-cascadeSelect-component/component.json @@ -1,9 +1,9 @@ { "id": "c_4709a015328b307e652d915fc3f36fb7", "name": "Cascade Select", - "description": "", + "description": "Cascade Select is a component to select a value from a nested structure of options.", "showInToolbox": true, - "faIcon": "pencil-ruler", + "faIcon": "check-double", "mainJS": "dist/index.js", "type": "custom", "category": "Custom Components", @@ -16,9 +16,39 @@ "hasLogicHandler": true, "handlerId": "cascadeLogic", "handlerLabel": "Cascade Logic", - "dataBinding": true + "dataBinding": true, + "handlerDescription": "This is a handler for the logic to determine an array of select items to display as the available options." + }, + { + "type": "text", + "name": "placeholder", + "label": "Placeholder", + "showInSettings": true, + "hasLogicHandler": true, + "handlerId": "placeholderLogic", + "handlerLabel": "Placeholder Logic", + "dataBinding": true, + "handlerDescription": "This is a handler for the logic to determine the default text to display when no option is selected." + } + ], + "eventHandlers": [ + { + "name": "onClickItem", + "label": "On Click Item", + "contextBlocks": [ + { + "id": "item", + "label": "Item" + } + ], + "handlerDescription": "This event is triggered when user select item" } ], - "eventHandlers": [], - "actions": [] -} \ No newline at end of file + "actions": [ + { + "id": "getSelected", + "label": "Get Selected in", + "hasReturn": true + } + ] +} diff --git a/components/bl-cascadeSelect-component/example-images/cascade_example.jpg b/components/bl-cascadeSelect-component/example-images/cascade_example.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1e751c58781c46bc069cbbf623d4fe2b0ca9c424 GIT binary patch literal 61903 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 uPhl(!5JiXm1jd0!!f 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
  • *&oQ!z5jzi#K8JxEm4m{E@rrp*fcB+>* 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 literal 0 HcmV?d00001 diff --git a/components/bl-cascadeSelect-component/preview.html b/components/bl-cascadeSelect-component/preview.html new file mode 100644 index 000000000..4dd31a181 --- /dev/null +++ b/components/bl-cascadeSelect-component/preview.html @@ -0,0 +1 @@ +
    \ No newline at end of file diff --git a/components/bl-cascadeSelect-component/src/helpers.js b/components/bl-cascadeSelect-component/src/helpers.js index f15a303e6..44d99528a 100644 --- a/components/bl-cascadeSelect-component/src/helpers.js +++ b/components/bl-cascadeSelect-component/src/helpers.js @@ -41,6 +41,8 @@ export function isCyclic(obj) { export const prepareCascade = (cascade, setParentItems) => { let levelOfNesting = 0; + const parentItems = []; + const groupParentItems = []; const prepare = (cascade) => { const validCascade = cascade.map(item => { @@ -53,7 +55,7 @@ export const prepareCascade = (cascade, setParentItems) => { children: prepare(item.children) }; - setParentItems(state => [...state, { code: item.code, isOpen: false, levelOfNesting }]); + parentItems.push({ code: item.code, isOpen: false, levelOfNesting }); } return validItem; @@ -64,5 +66,25 @@ export const prepareCascade = (cascade, setParentItems) => { return validCascade; }; - return prepare(cascade); + const preparedCascade = prepare(cascade); + + for (let i = 0; i <= levelOfNesting * -1; i++) { + groupParentItems.push(parentItems.filter(item => { + return item.levelOfNesting === i; + })); + } + + setParentItems(groupParentItems); + + return preparedCascade; +}; + +export const findParentItem = (parentItems, item) => { + for (let i = 0; i < parentItems.length; i++) { + for (let j = 0; j < parentItems[i].length; j++) { + if (parentItems[i][j].code === item.code) { + return parentItems[i][j]; + } + } + } }; diff --git a/components/bl-cascadeSelect-component/src/index.js b/components/bl-cascadeSelect-component/src/index.js index 0a19dc335..aecc9539e 100644 --- a/components/bl-cascadeSelect-component/src/index.js +++ b/components/bl-cascadeSelect-component/src/index.js @@ -4,16 +4,15 @@ import { prepareCascade, isCyclic } from './helpers'; const { cn } = BackendlessUI.CSSUtils; -export default function CascadeSelect({ component, eventHandlers, settings, instanceId }) { - const { display, classList, style, cascade } = component; +export default function CascadeSelect({ component, eventHandlers }) { + const { display, classList, style, cascade, placeholder } = component; + const { onClickItem } = eventHandlers; - const [selected, setSelected] = useState({ name: 'Select a...' }); const [itemsCascade, setItemsCascade] = useState(); const [parentItems, setParentItems] = useState([]); + const [selected, setSelected] = useState({ name: placeholder }); const [isOpen, setIsOpen] = useState(false); - console.log(parentItems); - useEffect(() => { const [detected, locate] = isCyclic(cascade); @@ -26,17 +25,34 @@ export default function CascadeSelect({ component, eventHandlers, settings, inst } }, [cascade]); - const openCascadeHandler = (item) => { - setParentItems(state => state.map(parentItem => ( - item.code === parentItem.code ? { ...parentItem, isOpen: !item.isOpen } : parentItem - ))); - }; + const openCascadeHandler = useCallback((item) => { + const { code, levelOfNesting } = item; + + setParentItems(state => { + const currentParentItems = [...state]; + + for (let i = 0; i < currentParentItems[levelOfNesting].length; i++) { + if (currentParentItems[levelOfNesting][i].code === code) { + currentParentItems[levelOfNesting][i].isOpen = !currentParentItems[levelOfNesting][i].isOpen; + } else { + currentParentItems[levelOfNesting][i].isOpen = false; + } + } + + return currentParentItems; + }); + }, []); - const openItemHandler = (item) => { + const openItemHandler = useCallback((item) => { setSelected(item); setIsOpen(false); - // setParentItems(state => state.map(parentItem => ({ ...parentItem, isOpen: false }))); - }; + + onClickItem({ item }); + }, []); + + const onClickInput = () => setIsOpen(state => !state); + + component.getSelected = () => selected; if (!display) { return null; @@ -44,18 +60,19 @@ export default function CascadeSelect({ component, eventHandlers, settings, inst return (
    -
    setIsOpen(state => !state) }> +
    { selected.name }
    ); diff --git a/components/bl-cascadeSelect-component/src/subcomponent.js b/components/bl-cascadeSelect-component/src/subcomponent.js index 916610dc8..0b54e2ddf 100644 --- a/components/bl-cascadeSelect-component/src/subcomponent.js +++ b/components/bl-cascadeSelect-component/src/subcomponent.js @@ -1,3 +1,5 @@ +import { findParentItem } from './helpers'; + const { cn } = BackendlessUI.CSSUtils; export function Cascade(props) { @@ -10,14 +12,14 @@ export function Cascade(props) { return (
      + style={ { top: levelOfNesting ? 0 : '100%', left: levelOfNesting ? '100%' : 0 } }> { itemsCascade.map(item => ( )) }
    @@ -26,18 +28,17 @@ export function Cascade(props) { export function CascadeItem({ item, parentItems, openItemHandler, openCascadeHandler, selected }) { if (item.children) { - const { isOpen } = parentItems.find(parent => parent.code === item.code); + const { isOpen } = findParentItem(parentItems, item); return (
  • openCascadeHandler(item) }> { item.name } - - + +
    @@ -49,7 +50,7 @@ export function CascadeItem({ item, parentItems, openItemHandler, openCascadeHan openCascadeHandler={ openCascadeHandler } openItemHandler={ openItemHandler } levelOfNesting={ item.levelOfNesting + 1 } - selected={selected} + selected={ selected } /> ) }
  • @@ -58,7 +59,8 @@ export function CascadeItem({ item, parentItems, openItemHandler, openCascadeHan return (
  • openItemHandler(item) }> { item.name }
  • @@ -67,10 +69,8 @@ export function CascadeItem({ item, parentItems, openItemHandler, openCascadeHan export function CollapseButtonIcon() { return ( - - + + ); } diff --git a/components/bl-cascadeSelect-component/styles/index.less b/components/bl-cascadeSelect-component/styles/index.less index b6797dc7c..7ee8e4bf4 100644 --- a/components/bl-cascadeSelect-component/styles/index.less +++ b/components/bl-cascadeSelect-component/styles/index.less @@ -1,8 +1,38 @@ -// you can use LESS variables from the current Theme and app extensions of the UI-Container +@bl-cascadeSelect-component-themePrimary: @themePrimary; +@bl-cascadeSelect-component-themeBackgroundColor: @appBackgroundColor; +@bl-cascadeSelect-component-themeTextColor: @appTextColor; + +@bl-cascadeSelect-component-collapse-icon-size: 15px; + +@bl-cascadeSelect-component-input-icon-size: 20px; +@bl-cascadeSelect-component-input-min-width: 200px; +@bl-cascadeSelect-component-input-border-color: if(@isLightTheme, rgba(0, 0, 0, 0.12), rgba(255, 255, 255, 0.12)); +@bl-cascadeSelect-component-input-color: #6c757d; + +@bl-cascadeSelect-component-list-z-index: 1; +@bl-cascadeSelect-component-list: if( + @isLightTheme, + @bl-cascadeSelect-component-themeBackgroundColor, + lighten(@bl-cascadeSelect-component-themeBackgroundColor, 5%) +); + +@bl-cascadeSelect-component-item-backround-color: if(@isLightTheme, rgba(0, 0, 0, 0.12), rgba(255, 255, 255, 0.12)); +@bl-cascadeSelect-component-item-color-open: lighten(@bl-cascadeSelect-component-themePrimary, 10%); +@bl-cascadeSelect-component-item-backround-color-open: if( + @isLightTheme, + lighten(@bl-cascadeSelect-component-themePrimary, 40%), + darken(@bl-cascadeSelect-component-themePrimary, 55%) +); + +@bl-cascadeSelect-component-item-border-focus: if( + @isLightTheme, + lighten(@bl-cascadeSelect-component-themePrimary, 30%), + darken(@bl-cascadeSelect-component-themePrimary, 40%) +); .bl-cascadeSelect-component { position: relative; - width: 200px; + user-select: none; .cascade-select { &__input { @@ -14,32 +44,52 @@ cursor: pointer; - border: 1px solid #ced4da; + border: 1px solid @bl-cascadeSelect-component-input-border-color; border-radius: 6px; - color: #6c757d; + background-color: @bl-cascadeSelect-component-themeBackgroundColor; + color: @bl-cascadeSelect-component-input-color; transition: border-color 0.3s; - &--selected { - color: @appTextColor; + &:hover { + border-color: @bl-cascadeSelect-component-themePrimary; } - &:hover { - border-color: @themePrimary; + &--selected { + color: @bl-cascadeSelect-component-themeTextColor; } } &__list { - margin: 0; - min-width: 200px; position: absolute; top: 100%; + z-index: @bl-cascadeSelect-component-list-z-index; + + min-width: 100%; + + margin: 0; padding: 10px 0; + list-style: none; - background: #fff; + + background: @bl-cascadeSelect-component-list; border-radius: 6px; box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px; + + animation: 0.1s linear list-open; + } + + @keyframes list-open { + from { + opacity: 0; + transform: scale(0.8); + } + + to { + opacity: 1; + transform: scale(1); + } } &__item { @@ -47,27 +97,38 @@ justify-content: space-between; padding: 10px 17px; - transition: background-color 0.3s; + transition: background-color, color 0.2s; &:hover { - background-color: #e9ecef; + background-color: @bl-cascadeSelect-component-item-backround-color; } - &--open { - background-color: lighten(@themePrimary, 30%); + &.open { + background-color: @bl-cascadeSelect-component-item-backround-color-open; + color: @bl-cascadeSelect-component-item-color-open; + } + + &:focus { + border: 2px solid @bl-cascadeSelect-component-item-border-focus; } } - &__collapse-button-icon { - width: 30px; - height: 30px; + &__collapse-input-icon { + width: @bl-cascadeSelect-component-input-icon-size; + height: @bl-cascadeSelect-component-input-icon-size; + fill: #aaa; + + transform: rotate(-90deg); } &__collapse-icon { - height: 15px; - width: 15px; - transform: rotate(-90deg); + height: @bl-cascadeSelect-component-collapse-icon-size; + width: @bl-cascadeSelect-component-collapse-icon-size; + + fill: #aaa; + + transform: rotate(-180deg); } } } From 8314f6e952e1450a4d6ddc4c1852a1c874f4bb89 Mon Sep 17 00:00:00 2001 From: Pavlo Stasiv <99363993+StasivPavlo@users.noreply.github.com> Date: Thu, 22 Dec 2022 15:59:29 +0200 Subject: [PATCH 03/11] code style fixed --- components/bl-cascadeSelect-component/src/helpers.js | 4 ++-- components/bl-cascadeSelect-component/src/index.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/bl-cascadeSelect-component/src/helpers.js b/components/bl-cascadeSelect-component/src/helpers.js index 44d99528a..48ac984d1 100644 --- a/components/bl-cascadeSelect-component/src/helpers.js +++ b/components/bl-cascadeSelect-component/src/helpers.js @@ -44,7 +44,7 @@ export const prepareCascade = (cascade, setParentItems) => { const parentItems = []; const groupParentItems = []; - const prepare = (cascade) => { + const prepare = cascade => { const validCascade = cascade.map(item => { let validItem = { ...item, levelOfNesting }; @@ -52,7 +52,7 @@ export const prepareCascade = (cascade, setParentItems) => { levelOfNesting++; validItem = { ...validItem, - children: prepare(item.children) + children: prepare(item.children), }; parentItems.push({ code: item.code, isOpen: false, levelOfNesting }); diff --git a/components/bl-cascadeSelect-component/src/index.js b/components/bl-cascadeSelect-component/src/index.js index aecc9539e..57bd6ef3e 100644 --- a/components/bl-cascadeSelect-component/src/index.js +++ b/components/bl-cascadeSelect-component/src/index.js @@ -25,7 +25,7 @@ export default function CascadeSelect({ component, eventHandlers }) { } }, [cascade]); - const openCascadeHandler = useCallback((item) => { + const openCascadeHandler = useCallback(item => { const { code, levelOfNesting } = item; setParentItems(state => { @@ -43,7 +43,7 @@ export default function CascadeSelect({ component, eventHandlers }) { }); }, []); - const openItemHandler = useCallback((item) => { + const openItemHandler = useCallback(item => { setSelected(item); setIsOpen(false); From 3bf0e3ede76204fa366d51928a3b1b1dac0d47a5 Mon Sep 17 00:00:00 2001 From: Pavlo Stasiv <99363993+StasivPavlo@users.noreply.github.com> Date: Tue, 3 Jan 2023 11:01:13 +0200 Subject: [PATCH 04/11] minor fixes --- components/bl-cascadeSelect-component/README.md | 4 ++-- components/bl-cascadeSelect-component/src/helpers.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/bl-cascadeSelect-component/README.md b/components/bl-cascadeSelect-component/README.md index 70a57a128..b904be13e 100644 --- a/components/bl-cascadeSelect-component/README.md +++ b/components/bl-cascadeSelect-component/README.md @@ -8,8 +8,8 @@ The component based on external [Cascade Select](https://www.primefaces.org/prim | Property | Type | Default Value | Logic | Data Binding | UI Setting | Description | |-------------------|---------|---------------------|-----------------------------|--------------|------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| cascade | JSON | | Cascade Logic | YES | YES | Allows determinate an array of select items to display as the available options. Watch [Codeless Examples](#Examples). Signature of polygon: `[{name, code, ?children}]` | -| placeholder | String | | Placeholder Logic | YES | YES | Allows determinate placeholder for input | +| Cascade | JSON | | Cascade Logic | YES | YES | Allows determinate an array of select items to display as the available options. Watch [Codeless Examples](#Examples). Signature of polygon: `[{name, code, ?children}]` | +| Placeholder | String | | Placeholder Logic | YES | YES | Allows determinate placeholder for input | ## Events diff --git a/components/bl-cascadeSelect-component/src/helpers.js b/components/bl-cascadeSelect-component/src/helpers.js index 44d99528a..94203e572 100644 --- a/components/bl-cascadeSelect-component/src/helpers.js +++ b/components/bl-cascadeSelect-component/src/helpers.js @@ -68,7 +68,7 @@ export const prepareCascade = (cascade, setParentItems) => { const preparedCascade = prepare(cascade); - for (let i = 0; i <= levelOfNesting * -1; i++) { + for (let i = 0; i <= -levelOfNesting; i++) { groupParentItems.push(parentItems.filter(item => { return item.levelOfNesting === i; })); From 95a4a7dc0aea8061cb9b1b6dc985213758ba02e2 Mon Sep 17 00:00:00 2001 From: Pavlo Stasiv <99363993+StasivPavlo@users.noreply.github.com> Date: Wed, 4 Jan 2023 14:50:28 +0200 Subject: [PATCH 05/11] minor and code style fixes --- .../bl-cascadeSelect-component/src/helpers.js | 58 ++++++++++++------- .../bl-cascadeSelect-component/src/index.js | 24 ++------ .../src/subcomponent.js | 30 ++++++---- 3 files changed, 62 insertions(+), 50 deletions(-) diff --git a/components/bl-cascadeSelect-component/src/helpers.js b/components/bl-cascadeSelect-component/src/helpers.js index 5237fd831..9d57c3f8b 100644 --- a/components/bl-cascadeSelect-component/src/helpers.js +++ b/components/bl-cascadeSelect-component/src/helpers.js @@ -1,9 +1,9 @@ -export function isCyclic(obj) { +export function analyzeCircularDependencies(obj) { const keys = []; const stack = []; const stackSet = new Set(); - let detected = false; - let locate; + let isCircular = false; + let cycleLocation; function detect(obj, key) { if (obj && typeof obj != 'object') { @@ -11,8 +11,8 @@ export function isCyclic(obj) { } if (stackSet.has(obj)) { - locate = keys.join('.') + '.' + key; - detected = true; + cycleLocation = keys.join('.') + '.' + key; + isCircular = true; return; } @@ -36,13 +36,35 @@ export function isCyclic(obj) { detect(obj, 'obj'); - return [detected, locate]; + return { isCircular, cycleLocation }; } +export const openCascade = (state, item) => { + const currentParentItems = [...state]; + const { code, levelOfNesting } = item; + + for (let i = 0; i < currentParentItems[levelOfNesting].length; i++) { + const { code: parentItemCode, isOpen } = currentParentItems[levelOfNesting][i]; + + currentParentItems[levelOfNesting][i].isOpen = parentItemCode === code ? !isOpen : false; + } + + return currentParentItems; +}; + +export const findParentItem = (parentItems, item) => { + for (let i = 0; i < parentItems.length; i++) { + for (let j = 0; j < parentItems[i].length; j++) { + if (parentItems[i][j].code === item.code) { + return parentItems[i][j]; + } + } + } +}; + export const prepareCascade = (cascade, setParentItems) => { let levelOfNesting = 0; const parentItems = []; - const groupParentItems = []; const prepare = cascade => { const validCascade = cascade.map(item => { @@ -68,23 +90,17 @@ export const prepareCascade = (cascade, setParentItems) => { const preparedCascade = prepare(cascade); - for (let i = 0; i <= -levelOfNesting; i++) { - groupParentItems.push(parentItems.filter(item => { - return item.levelOfNesting === i; - })); - } - - setParentItems(groupParentItems); + setParentItems(getNestedItems(parentItems, levelOfNesting)); return preparedCascade; }; -export const findParentItem = (parentItems, item) => { - for (let i = 0; i < parentItems.length; i++) { - for (let j = 0; j < parentItems[i].length; j++) { - if (parentItems[i][j].code === item.code) { - return parentItems[i][j]; - } - } +const getNestedItems = (items, levelOfNesting) => { + const groupParentItems = []; + + for (let i = 0; i <= -levelOfNesting; i++) { + groupParentItems.push(items.filter(({ levelOfNesting }) => levelOfNesting === i)); } + + return groupParentItems; }; diff --git a/components/bl-cascadeSelect-component/src/index.js b/components/bl-cascadeSelect-component/src/index.js index 57bd6ef3e..5573b1ca9 100644 --- a/components/bl-cascadeSelect-component/src/index.js +++ b/components/bl-cascadeSelect-component/src/index.js @@ -1,6 +1,6 @@ import { useState, useEffect, useCallback } from 'react'; import { CollapseButtonIcon, Cascade } from './subcomponent'; -import { prepareCascade, isCyclic } from './helpers'; +import { prepareCascade, analyzeCircularDependencies, openCascade } from './helpers'; const { cn } = BackendlessUI.CSSUtils; @@ -14,10 +14,10 @@ export default function CascadeSelect({ component, eventHandlers }) { const [isOpen, setIsOpen] = useState(false); useEffect(() => { - const [detected, locate] = isCyclic(cascade); + const { isCircular, cycleLocation } = analyzeCircularDependencies(cascade); - if (detected) { - throw new Error('cascade have cycling object in ' + locate); + if (isCircular) { + throw new Error('cascade have cycling object in ' + cycleLocation); } if (cascade) { @@ -26,21 +26,7 @@ export default function CascadeSelect({ component, eventHandlers }) { }, [cascade]); const openCascadeHandler = useCallback(item => { - const { code, levelOfNesting } = item; - - setParentItems(state => { - const currentParentItems = [...state]; - - for (let i = 0; i < currentParentItems[levelOfNesting].length; i++) { - if (currentParentItems[levelOfNesting][i].code === code) { - currentParentItems[levelOfNesting][i].isOpen = !currentParentItems[levelOfNesting][i].isOpen; - } else { - currentParentItems[levelOfNesting][i].isOpen = false; - } - } - - return currentParentItems; - }); + setParentItems(state => openCascade(state, item)); }, []); const openItemHandler = useCallback(item => { diff --git a/components/bl-cascadeSelect-component/src/subcomponent.js b/components/bl-cascadeSelect-component/src/subcomponent.js index 0b54e2ddf..436747c68 100644 --- a/components/bl-cascadeSelect-component/src/subcomponent.js +++ b/components/bl-cascadeSelect-component/src/subcomponent.js @@ -27,7 +27,9 @@ export function Cascade(props) { } export function CascadeItem({ item, parentItems, openItemHandler, openCascadeHandler, selected }) { - if (item.children) { + const { name, levelOfNesting, children, code } = item; + + if (children) { const { isOpen } = findParentItem(parentItems, item); return ( @@ -36,20 +38,18 @@ export function CascadeItem({ item, parentItems, openItemHandler, openCascadeHan tabIndex={ 0 } className={ cn('cascade-select__item', { open: isOpen }) } onClick={ () => openCascadeHandler(item) }> - { item.name } - - - + { name } + { isOpen && ( ) } @@ -60,9 +60,9 @@ export function CascadeItem({ item, parentItems, openItemHandler, openCascadeHan return (
  • openItemHandler(item) }> - { item.name } + { name }
  • ); } @@ -70,7 +70,17 @@ export function CascadeItem({ item, parentItems, openItemHandler, openCascadeHan export function CollapseButtonIcon() { return ( - + + + ); +} + +function CollapseParentIcon() { + return ( + + ); } From c1ffbc2dae78ebbade2e1c9ee363cbe62b375c09 Mon Sep 17 00:00:00 2001 From: Pavlo Stasiv <99363993+StasivPavlo@users.noreply.github.com> Date: Tue, 10 Jan 2023 15:43:22 +0200 Subject: [PATCH 06/11] added action get and set for Code, Cascade --- .../bl-cascadeSelect-component/src/helpers.js | 65 ++++++++++++------- .../bl-cascadeSelect-component/src/index.js | 19 +++--- 2 files changed, 49 insertions(+), 35 deletions(-) diff --git a/components/bl-cascadeSelect-component/src/helpers.js b/components/bl-cascadeSelect-component/src/helpers.js index 9d57c3f8b..773a4edc5 100644 --- a/components/bl-cascadeSelect-component/src/helpers.js +++ b/components/bl-cascadeSelect-component/src/helpers.js @@ -1,4 +1,15 @@ -export function analyzeCircularDependencies(obj) { +export const validate = (cascade, setItemsCascade, setParentItems, setItems) => { + const { isCircular, cycleLocation } = analyzeCircularDependencies(cascade); + + if (isCircular) { + throw new Error('cascade have cycling object in ' + cycleLocation); + } + + if (cascade) { + setItemsCascade(prepareCascade(cascade, setParentItems, setItems)); + } +} +function analyzeCircularDependencies(obj) { const keys = []; const stack = []; const stackSet = new Set(); @@ -39,32 +50,10 @@ export function analyzeCircularDependencies(obj) { return { isCircular, cycleLocation }; } -export const openCascade = (state, item) => { - const currentParentItems = [...state]; - const { code, levelOfNesting } = item; - - for (let i = 0; i < currentParentItems[levelOfNesting].length; i++) { - const { code: parentItemCode, isOpen } = currentParentItems[levelOfNesting][i]; - - currentParentItems[levelOfNesting][i].isOpen = parentItemCode === code ? !isOpen : false; - } - - return currentParentItems; -}; - -export const findParentItem = (parentItems, item) => { - for (let i = 0; i < parentItems.length; i++) { - for (let j = 0; j < parentItems[i].length; j++) { - if (parentItems[i][j].code === item.code) { - return parentItems[i][j]; - } - } - } -}; - -export const prepareCascade = (cascade, setParentItems) => { +const prepareCascade = (cascade, setParentItems, setItems) => { let levelOfNesting = 0; const parentItems = []; + const items = []; const prepare = cascade => { const validCascade = cascade.map(item => { @@ -78,6 +67,8 @@ export const prepareCascade = (cascade, setParentItems) => { }; parentItems.push({ code: item.code, isOpen: false, levelOfNesting }); + } else { + items.push(validItem); } return validItem; @@ -91,6 +82,7 @@ export const prepareCascade = (cascade, setParentItems) => { const preparedCascade = prepare(cascade); setParentItems(getNestedItems(parentItems, levelOfNesting)); + setItems(items); return preparedCascade; }; @@ -104,3 +96,26 @@ const getNestedItems = (items, levelOfNesting) => { return groupParentItems; }; + +export const openCascade = (state, item) => { + const currentParentItems = [...state]; + const { code, levelOfNesting } = item; + + for (let i = 0; i < currentParentItems[levelOfNesting].length; i++) { + const { code: parentItemCode, isOpen } = currentParentItems[levelOfNesting][i]; + + currentParentItems[levelOfNesting][i].isOpen = parentItemCode === code ? !isOpen : false; + } + + return currentParentItems; +}; + +export const findParentItem = (parentItems, item) => { + for (let i = 0; i < parentItems.length; i++) { + for (let j = 0; j < parentItems[i].length; j++) { + if (parentItems[i][j].code === item.code) { + return parentItems[i][j]; + } + } + } +}; diff --git a/components/bl-cascadeSelect-component/src/index.js b/components/bl-cascadeSelect-component/src/index.js index 5573b1ca9..37d69c56e 100644 --- a/components/bl-cascadeSelect-component/src/index.js +++ b/components/bl-cascadeSelect-component/src/index.js @@ -1,6 +1,6 @@ import { useState, useEffect, useCallback } from 'react'; import { CollapseButtonIcon, Cascade } from './subcomponent'; -import { prepareCascade, analyzeCircularDependencies, openCascade } from './helpers'; +import { openCascade, validate } from './helpers'; const { cn } = BackendlessUI.CSSUtils; @@ -10,19 +10,12 @@ export default function CascadeSelect({ component, eventHandlers }) { const [itemsCascade, setItemsCascade] = useState(); const [parentItems, setParentItems] = useState([]); + const [items, setItems] = useState([]); const [selected, setSelected] = useState({ name: placeholder }); const [isOpen, setIsOpen] = useState(false); useEffect(() => { - const { isCircular, cycleLocation } = analyzeCircularDependencies(cascade); - - if (isCircular) { - throw new Error('cascade have cycling object in ' + cycleLocation); - } - - if (cascade) { - setItemsCascade(prepareCascade(cascade, setParentItems)); - } + validate(cascade, setItemsCascade, setParentItems, setItems); }, [cascade]); const openCascadeHandler = useCallback(item => { @@ -40,6 +33,12 @@ export default function CascadeSelect({ component, eventHandlers }) { component.getSelected = () => selected; + component.setCode = (code) => setSelected(state => items.find(item => item.code === code) || state); + component.getCode = () => selected.code || ''; + + component.getCascade = () => itemsCascade; + component.setCascade = (cascade) => validate(cascade, setItemsCascade, setParentItems, setItems); + if (!display) { return null; } From 17372beee221ef58ef51720a245b8c74c2b21846 Mon Sep 17 00:00:00 2001 From: Pavlo Stasiv <99363993+StasivPavlo@users.noreply.github.com> Date: Wed, 18 Jan 2023 23:46:37 +0200 Subject: [PATCH 07/11] added component.el --- components/bl-cascadeSelect-component/src/index.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/components/bl-cascadeSelect-component/src/index.js b/components/bl-cascadeSelect-component/src/index.js index 37d69c56e..9a10f0c24 100644 --- a/components/bl-cascadeSelect-component/src/index.js +++ b/components/bl-cascadeSelect-component/src/index.js @@ -1,4 +1,4 @@ -import { useState, useEffect, useCallback } from 'react'; +import { useState, useEffect, useCallback, useRef } from 'react'; import { CollapseButtonIcon, Cascade } from './subcomponent'; import { openCascade, validate } from './helpers'; @@ -14,6 +14,8 @@ export default function CascadeSelect({ component, eventHandlers }) { const [selected, setSelected] = useState({ name: placeholder }); const [isOpen, setIsOpen] = useState(false); + const cascadeSelectRef = useRef(); + useEffect(() => { validate(cascade, setItemsCascade, setParentItems, setItems); }, [cascade]); @@ -39,12 +41,14 @@ export default function CascadeSelect({ component, eventHandlers }) { component.getCascade = () => itemsCascade; component.setCascade = (cascade) => validate(cascade, setItemsCascade, setParentItems, setItems); + component.el = cascadeSelectRef.current; + if (!display) { return null; } return ( -
    +
    From 998d6390224bce2ebe8db83cc0c0f01adaef89c6 Mon Sep 17 00:00:00 2001 From: Pavlo Stasiv <99363993+StasivPavlo@users.noreply.github.com> Date: Tue, 24 Jan 2023 17:21:57 +0200 Subject: [PATCH 08/11] minor fixes --- components/bl-cascadeSelect-component/README.md | 2 -- .../bl-cascadeSelect-component/src/helpers.js | 15 +++++---------- .../bl-cascadeSelect-component/src/index.js | 4 ++-- 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/components/bl-cascadeSelect-component/README.md b/components/bl-cascadeSelect-component/README.md index b904be13e..f64bf46f3 100644 --- a/components/bl-cascadeSelect-component/README.md +++ b/components/bl-cascadeSelect-component/README.md @@ -2,8 +2,6 @@ Cascade Select is a component of Backendless UI-Builder designer. This allows you to select a value from a nested structure of options. -The component based on external [Cascade Select](https://www.primefaces.org/primereact/cascadeselect/). - ## Properties | Property | Type | Default Value | Logic | Data Binding | UI Setting | Description | diff --git a/components/bl-cascadeSelect-component/src/helpers.js b/components/bl-cascadeSelect-component/src/helpers.js index 773a4edc5..d21dde8e1 100644 --- a/components/bl-cascadeSelect-component/src/helpers.js +++ b/components/bl-cascadeSelect-component/src/helpers.js @@ -8,7 +8,8 @@ export const validate = (cascade, setItemsCascade, setParentItems, setItems) => if (cascade) { setItemsCascade(prepareCascade(cascade, setParentItems, setItems)); } -} +}; + function analyzeCircularDependencies(obj) { const keys = []; const stack = []; @@ -41,8 +42,6 @@ function analyzeCircularDependencies(obj) { keys.pop(); stack.pop(); stackSet.delete(obj); - - return; } detect(obj, 'obj'); @@ -111,11 +110,7 @@ export const openCascade = (state, item) => { }; export const findParentItem = (parentItems, item) => { - for (let i = 0; i < parentItems.length; i++) { - for (let j = 0; j < parentItems[i].length; j++) { - if (parentItems[i][j].code === item.code) { - return parentItems[i][j]; - } - } - } + const { levelOfNesting, code } = item; + + return parentItems[levelOfNesting].find(item => item.code === code); }; diff --git a/components/bl-cascadeSelect-component/src/index.js b/components/bl-cascadeSelect-component/src/index.js index 9a10f0c24..fed634b26 100644 --- a/components/bl-cascadeSelect-component/src/index.js +++ b/components/bl-cascadeSelect-component/src/index.js @@ -17,7 +17,7 @@ export default function CascadeSelect({ component, eventHandlers }) { const cascadeSelectRef = useRef(); useEffect(() => { - validate(cascade, setItemsCascade, setParentItems, setItems); + component.setCascade(cascade); }, [cascade]); const openCascadeHandler = useCallback(item => { @@ -41,7 +41,7 @@ export default function CascadeSelect({ component, eventHandlers }) { component.getCascade = () => itemsCascade; component.setCascade = (cascade) => validate(cascade, setItemsCascade, setParentItems, setItems); - component.el = cascadeSelectRef.current; + useEffect(() => component.el = cascadeSelectRef.current, []); if (!display) { return null; From adbe54cfb21857b23e013f709ac69c6e54e4073a Mon Sep 17 00:00:00 2001 From: StasivPavlo Date: Thu, 8 Jun 2023 12:21:36 +0300 Subject: [PATCH 09/11] minor fixes --- .../bl-cascadeSelect-component/src/helpers.js | 6 +++--- .../bl-cascadeSelect-component/src/index.js | 17 +++++++---------- .../src/subcomponent.js | 2 +- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/components/bl-cascadeSelect-component/src/helpers.js b/components/bl-cascadeSelect-component/src/helpers.js index d21dde8e1..f2aee761a 100644 --- a/components/bl-cascadeSelect-component/src/helpers.js +++ b/components/bl-cascadeSelect-component/src/helpers.js @@ -17,7 +17,7 @@ function analyzeCircularDependencies(obj) { let isCircular = false; let cycleLocation; - function detect(obj, key) { + function detectCircular(obj, key) { if (obj && typeof obj != 'object') { return; } @@ -35,7 +35,7 @@ function analyzeCircularDependencies(obj) { for (const k in obj) { if (Object.prototype.hasOwnProperty.call(obj, k)) { - detect(obj[k], k); + detectCircular(obj[k], k); } } @@ -44,7 +44,7 @@ function analyzeCircularDependencies(obj) { stackSet.delete(obj); } - detect(obj, 'obj'); + detectCircular(obj, 'obj'); return { isCircular, cycleLocation }; } diff --git a/components/bl-cascadeSelect-component/src/index.js b/components/bl-cascadeSelect-component/src/index.js index fed634b26..271148f52 100644 --- a/components/bl-cascadeSelect-component/src/index.js +++ b/components/bl-cascadeSelect-component/src/index.js @@ -1,10 +1,11 @@ -import { useState, useEffect, useCallback, useRef } from 'react'; -import { CollapseButtonIcon, Cascade } from './subcomponent'; +import { useCallback, useEffect, useState } from 'react'; + import { openCascade, validate } from './helpers'; +import { Cascade, CollapseButtonIcon } from './subcomponent'; const { cn } = BackendlessUI.CSSUtils; -export default function CascadeSelect({ component, eventHandlers }) { +export default function CascadeSelect({ component, eventHandlers, elRef }) { const { display, classList, style, cascade, placeholder } = component; const { onClickItem } = eventHandlers; @@ -14,8 +15,6 @@ export default function CascadeSelect({ component, eventHandlers }) { const [selected, setSelected] = useState({ name: placeholder }); const [isOpen, setIsOpen] = useState(false); - const cascadeSelectRef = useRef(); - useEffect(() => { component.setCascade(cascade); }, [cascade]); @@ -35,20 +34,18 @@ export default function CascadeSelect({ component, eventHandlers }) { component.getSelected = () => selected; - component.setCode = (code) => setSelected(state => items.find(item => item.code === code) || state); + component.setCode = code => setSelected(state => items.find(item => item.code === code) || state); component.getCode = () => selected.code || ''; component.getCascade = () => itemsCascade; - component.setCascade = (cascade) => validate(cascade, setItemsCascade, setParentItems, setItems); - - useEffect(() => component.el = cascadeSelectRef.current, []); + component.setCascade = cascade => validate(cascade, setItemsCascade, setParentItems, setItems); if (!display) { return null; } return ( -
    +
    diff --git a/components/bl-cascadeSelect-component/src/subcomponent.js b/components/bl-cascadeSelect-component/src/subcomponent.js index 436747c68..69bdb105a 100644 --- a/components/bl-cascadeSelect-component/src/subcomponent.js +++ b/components/bl-cascadeSelect-component/src/subcomponent.js @@ -12,7 +12,7 @@ export function Cascade(props) { return (
      + style={{ top: levelOfNesting ? 0 : '100%', left: levelOfNesting ? '100%' : 0 }}> { itemsCascade.map(item => ( Date: Mon, 2 Oct 2023 14:06:27 +0300 Subject: [PATCH 10/11] added actions to the component.json and README.md --- .../bl-cascadeSelect-component/README.md | 10 +++++-- .../bl-cascadeSelect-component/component.json | 30 +++++++++++++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/components/bl-cascadeSelect-component/README.md b/components/bl-cascadeSelect-component/README.md index f64bf46f3..07a865ccf 100644 --- a/components/bl-cascadeSelect-component/README.md +++ b/components/bl-cascadeSelect-component/README.md @@ -17,9 +17,13 @@ Cascade Select is a component of Backendless UI-Builder designer. This allows yo ## Action -| Action | Inputs | Return | -|---------------|--------|--------------------------| -| Get Select in | | Object: of a select item | +| Action | Inputs | Return | +|---------------|------------------|-----------------------------| +| Get Select in | | Object: of a select item | +| Set Cascade | cascade: `Array` | | +| Get Cascade | | Array: of s cascade | +| Set Code | code: `String` | | +| Get Code | | String: code of select item | ## Codeless Examples diff --git a/components/bl-cascadeSelect-component/component.json b/components/bl-cascadeSelect-component/component.json index f30742ce5..4033118c4 100644 --- a/components/bl-cascadeSelect-component/component.json +++ b/components/bl-cascadeSelect-component/component.json @@ -49,6 +49,36 @@ "id": "getSelected", "label": "Get Selected in", "hasReturn": true + }, + { + "id": "setCascade", + "label": "Set Cascade", + "inputs": [ + { + "id": "cascade", + "label": "Cascade" + } + ] + }, + { + "id": "getCascade", + "label": "Get Cascade", + "hasReturn": true + }, + { + "id": "setCode", + "label": "Set Code", + "inputs": [ + { + "id": "code", + "label": "Code" + } + ] + }, + { + "id": "getCode", + "label": "Get Code", + "hasReturn": true } ] } From 557a11be714467ecf06092be5f9b151ee46aad51 Mon Sep 17 00:00:00 2001 From: pavlo Date: Mon, 2 Oct 2023 14:09:48 +0300 Subject: [PATCH 11/11] renamed directory --- .../README.md | 0 .../component.json | 0 .../example-images/cascade_example.jpg | Bin .../preview.html | 0 .../src/helpers.js | 0 .../src/index.js | 2 +- .../src/subcomponent.js | 0 .../styles/index.less | 0 8 files changed, 1 insertion(+), 1 deletion(-) rename components/{bl-cascadeSelect-component => bl-cascade-select}/README.md (100%) rename components/{bl-cascadeSelect-component => bl-cascade-select}/component.json (100%) rename components/{bl-cascadeSelect-component => bl-cascade-select}/example-images/cascade_example.jpg (100%) rename components/{bl-cascadeSelect-component => bl-cascade-select}/preview.html (100%) rename components/{bl-cascadeSelect-component => bl-cascade-select}/src/helpers.js (100%) rename components/{bl-cascadeSelect-component => bl-cascade-select}/src/index.js (95%) rename components/{bl-cascadeSelect-component => bl-cascade-select}/src/subcomponent.js (100%) rename components/{bl-cascadeSelect-component => bl-cascade-select}/styles/index.less (100%) diff --git a/components/bl-cascadeSelect-component/README.md b/components/bl-cascade-select/README.md similarity index 100% rename from components/bl-cascadeSelect-component/README.md rename to components/bl-cascade-select/README.md diff --git a/components/bl-cascadeSelect-component/component.json b/components/bl-cascade-select/component.json similarity index 100% rename from components/bl-cascadeSelect-component/component.json rename to components/bl-cascade-select/component.json diff --git a/components/bl-cascadeSelect-component/example-images/cascade_example.jpg b/components/bl-cascade-select/example-images/cascade_example.jpg similarity index 100% rename from components/bl-cascadeSelect-component/example-images/cascade_example.jpg rename to components/bl-cascade-select/example-images/cascade_example.jpg diff --git a/components/bl-cascadeSelect-component/preview.html b/components/bl-cascade-select/preview.html similarity index 100% rename from components/bl-cascadeSelect-component/preview.html rename to components/bl-cascade-select/preview.html diff --git a/components/bl-cascadeSelect-component/src/helpers.js b/components/bl-cascade-select/src/helpers.js similarity index 100% rename from components/bl-cascadeSelect-component/src/helpers.js rename to components/bl-cascade-select/src/helpers.js diff --git a/components/bl-cascadeSelect-component/src/index.js b/components/bl-cascade-select/src/index.js similarity index 95% rename from components/bl-cascadeSelect-component/src/index.js rename to components/bl-cascade-select/src/index.js index 271148f52..9db2638ab 100644 --- a/components/bl-cascadeSelect-component/src/index.js +++ b/components/bl-cascade-select/src/index.js @@ -45,7 +45,7 @@ export default function CascadeSelect({ component, eventHandlers, elRef }) { } return ( -
      +
      diff --git a/components/bl-cascadeSelect-component/src/subcomponent.js b/components/bl-cascade-select/src/subcomponent.js similarity index 100% rename from components/bl-cascadeSelect-component/src/subcomponent.js rename to components/bl-cascade-select/src/subcomponent.js diff --git a/components/bl-cascadeSelect-component/styles/index.less b/components/bl-cascade-select/styles/index.less similarity index 100% rename from components/bl-cascadeSelect-component/styles/index.less rename to components/bl-cascade-select/styles/index.less