@rokkit/core 1.0.0-next.32 → 1.0.0-next.34

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 (50) hide show
  1. package/package.json +13 -11
  2. package/src/ListActions.svelte +1 -1
  3. package/src/NestedPaginator.svelte +3 -4
  4. package/src/PageNavigator.svelte +2 -2
  5. package/src/ResponsiveGrid.svelte +1 -2
  6. package/src/SpinList.svelte +5 -5
  7. package/src/SplitPane.svelte +1 -1
  8. package/src/Splitter.svelte +1 -1
  9. package/src/TabItems.svelte +1 -1
  10. package/src/index.js +15 -15
  11. package/src/Accordion.svelte +0 -80
  12. package/src/Alerts.svelte +0 -39
  13. package/src/BreadCrumbs.svelte +0 -34
  14. package/src/DropDown.svelte +0 -82
  15. package/src/DropSearch.svelte +0 -67
  16. package/src/Icon.svelte +0 -38
  17. package/src/List.svelte +0 -66
  18. package/src/NestedList.svelte +0 -59
  19. package/src/Slider.svelte +0 -17
  20. package/src/Switch.svelte +0 -69
  21. package/src/Tabs.svelte +0 -82
  22. package/src/Tree.svelte +0 -52
  23. package/src/actions/dismissable.js +0 -24
  24. package/src/actions/fillable.js +0 -114
  25. package/src/actions/hierarchy.js +0 -180
  26. package/src/actions/index.js +0 -7
  27. package/src/actions/navigable.js +0 -42
  28. package/src/actions/navigator.js +0 -179
  29. package/src/actions/pannable.js +0 -57
  30. package/src/actions/swipeable.js +0 -55
  31. package/src/actions/themeable.js +0 -23
  32. package/src/constants.js +0 -95
  33. package/src/items/Connector.svelte +0 -28
  34. package/src/items/Item.svelte +0 -29
  35. package/src/items/ItemWrapper.svelte +0 -47
  36. package/src/items/Link.svelte +0 -18
  37. package/src/items/Node.svelte +0 -47
  38. package/src/items/Separator.svelte +0 -1
  39. package/src/items/Summary.svelte +0 -27
  40. package/src/items/index.js +0 -7
  41. package/src/lib/connector.js +0 -12
  42. package/src/lib/index.js +0 -7
  43. package/src/lib/nested.js +0 -45
  44. package/src/list.js +0 -14
  45. package/src/mocks/Custom.svelte +0 -6
  46. package/src/mocks/index.js +0 -17
  47. package/src/stores/alerts.js +0 -2
  48. package/src/stores/index.js +0 -6
  49. package/src/stores/persist.js +0 -63
  50. package/src/stores/theme.js +0 -34
@@ -1,179 +0,0 @@
1
- import {
2
- moveNext,
3
- movePrevious,
4
- isNested,
5
- hasChildren,
6
- pathFromIndices,
7
- indicesFromPath,
8
- getCurrentNode
9
- } from './hierarchy'
10
- /**
11
- * @typedef NavigatorOptions
12
- * @property {Array<*>} items - An array containing the data set to navigate
13
- * @property {boolean} [vertical=true] - Identifies whether navigation shoud be vertical or horizontal
14
- * @property {string} [idPrefix='id-'] - id prefix used for identifying individual node
15
- * @property {import('../constants').FieldMapping} fields - Field mapping to identify attributes to be used for state and identification of children
16
- */
17
-
18
- /**
19
- * Keyboard navigation for Lists and NestedLists. The data is either nested or not and is not
20
- * expected to switch from nested to simple list or vice-versa.
21
- *
22
- * @param {HTMLElement} node - The node on which the action is to be used on
23
- * @param {NavigatorOptions} options - Configuration options for the action
24
- * @returns
25
- */
26
- export function navigator(node, options) {
27
- const { fields, enabled = true, vertical = true, idPrefix = 'id-' } = options
28
- let items, path, currentNode
29
-
30
- if (!enabled) return { destroy: () => {} }
31
-
32
- const update = (options) => {
33
- items = options.items
34
- path = pathFromIndices(options.indices ?? [], items, fields)
35
- currentNode = getCurrentNode(path)
36
- }
37
-
38
- const next = () => {
39
- const previousNode = currentNode
40
- path = moveNext(path, items, fields)
41
- currentNode = getCurrentNode(path)
42
-
43
- if (previousNode !== currentNode) moveTo(node, path, currentNode, idPrefix)
44
- }
45
- const previous = () => {
46
- const previousNode = currentNode
47
- path = movePrevious(path)
48
- if (path.length > 0) {
49
- currentNode = getCurrentNode(path)
50
- if (previousNode !== currentNode)
51
- moveTo(node, path, currentNode, idPrefix)
52
- }
53
- }
54
- const select = () => {
55
- if (currentNode)
56
- node.dispatchEvent(
57
- new CustomEvent('select', {
58
- detail: { path: indicesFromPath(path), node: currentNode }
59
- })
60
- )
61
- }
62
- const collapse = () => {
63
- if (currentNode) {
64
- const collapse =
65
- hasChildren(currentNode, path[path.length - 1].fields) &&
66
- currentNode[path[path.length - 1].fields.isOpen]
67
- if (collapse) {
68
- currentNode[path[path.length - 1].fields.isOpen] = false
69
- node.dispatchEvent(
70
- new CustomEvent('collapse', {
71
- detail: { path: indicesFromPath(path), node: currentNode }
72
- })
73
- )
74
- } else if (path.length > 0) {
75
- path = path.slice(0, -1)
76
- currentNode = getCurrentNode(path)
77
- select()
78
- }
79
- }
80
- }
81
- const expand = () => {
82
- if (currentNode && hasChildren(currentNode, path[path.length - 1].fields)) {
83
- currentNode[path[path.length - 1].fields.isOpen] = true
84
- node.dispatchEvent(
85
- new CustomEvent('expand', {
86
- detail: { path: indicesFromPath(path), node: currentNode }
87
- })
88
- )
89
- }
90
- }
91
-
92
- update(options)
93
-
94
- const nested = isNested(items, fields)
95
- const movement = vertical
96
- ? { ArrowDown: next, ArrowUp: previous }
97
- : { ArrowRight: next, ArrowLeft: previous }
98
- const states = !nested
99
- ? {}
100
- : vertical
101
- ? { ArrowRight: expand, ArrowLeft: collapse }
102
- : { ArrowDown: expand, ArrowUp: collapse }
103
- const actions = { ...movement, Enter: select, ...states }
104
-
105
- const handleKeyDown = (event) => {
106
- if (actions[event.key]) {
107
- event.preventDefault()
108
- event.stopPropagation()
109
- actions[event.key]()
110
- }
111
- }
112
-
113
- const handleClick = (event) => {
114
- let target = findParentWithDataPath(event.target)
115
- let indices = !target
116
- ? []
117
- : target.dataset.path
118
- .split(',')
119
- .filter((item) => item !== '')
120
- .map((item) => +item)
121
-
122
- if (indices.length > 0 && event.target.tagName != 'DETAIL') {
123
- path = pathFromIndices(indices, items, fields)
124
- currentNode = getCurrentNode(path)
125
- if (hasChildren(currentNode, path[path.length - 1].fields)) {
126
- currentNode[path[path.length - 1].fields.isOpen] =
127
- !currentNode[path[path.length - 1].fields.isOpen]
128
- const event = currentNode[path[path.length - 1].fields.isOpen]
129
- ? 'expand'
130
- : 'collapse'
131
- node.dispatchEvent(
132
- new CustomEvent(event, {
133
- detail: { path: indices, node: currentNode }
134
- })
135
- )
136
- }
137
- node.dispatchEvent(
138
- new CustomEvent('select', {
139
- detail: { path: indices, node: currentNode }
140
- })
141
- )
142
- }
143
- }
144
-
145
- node.addEventListener('keydown', handleKeyDown)
146
- node.addEventListener('click', handleClick)
147
-
148
- return {
149
- update,
150
- destroy() {
151
- node.removeEventListener('keydown', handleKeyDown)
152
- node.removeEventListener('click', handleClick)
153
- }
154
- }
155
- }
156
-
157
- export function moveTo(node, path, currentNode, idPrefix) {
158
- const indices = indicesFromPath(path)
159
-
160
- let current = node.querySelector('#' + idPrefix + indices.join('-'))
161
- if (current) current.scrollIntoView({ behavior: 'smooth', block: 'nearest' })
162
-
163
- node.dispatchEvent(
164
- new CustomEvent('move', {
165
- detail: { path: indices, node: currentNode }
166
- })
167
- )
168
- }
169
-
170
- export function findParentWithDataPath(element) {
171
- if (element.hasAttribute('data-path')) return element
172
- let parent = element.parentNode
173
-
174
- while (parent && !parent.hasAttribute('data-path')) {
175
- parent = parent.parentNode
176
- }
177
-
178
- return parent
179
- }
@@ -1,57 +0,0 @@
1
- // pannable.js
2
- /**
3
- * Handle drag and move events
4
- *
5
- * @param {*} node
6
- * @returns
7
- */
8
- export function pannable(node) {
9
- let x
10
- let y
11
-
12
- function track(event, name, delta = {}) {
13
- x = event.clientX || event.touches[0].clientX
14
- y = event.clientY || event.touches[0].clientY
15
- event.stopPropagation()
16
- event.preventDefault()
17
- node.dispatchEvent(
18
- new CustomEvent(name, {
19
- detail: { x, y, ...delta }
20
- })
21
- )
22
- }
23
-
24
- function handleMousedown(event) {
25
- track(event, 'panstart')
26
- window.addEventListener('mousemove', handleMousemove)
27
- window.addEventListener('mouseup', handleMouseup)
28
- window.addEventListener('touchmove', handleMousemove, { passive: false })
29
- window.addEventListener('touchend', handleMouseup)
30
- }
31
-
32
- function handleMousemove(event) {
33
- const dx = (event.clientX || event.touches[0].clientX) - x
34
- const dy = (event.clientY || event.touches[0].clientY) - y
35
-
36
- track(event, 'panmove', { dx, dy })
37
- }
38
-
39
- function handleMouseup(event) {
40
- track(event, 'panend')
41
-
42
- window.removeEventListener('mousemove', handleMousemove)
43
- window.removeEventListener('mouseup', handleMouseup)
44
- window.removeEventListener('touchmove', handleMousemove)
45
- window.removeEventListener('touchend', handleMouseup)
46
- }
47
-
48
- node.addEventListener('mousedown', handleMousedown)
49
- node.addEventListener('touchstart', handleMousedown, { passive: false })
50
-
51
- return {
52
- destroy() {
53
- node.removeEventListener('mousedown', handleMousedown)
54
- node.removeEventListener('touchstart', handleMousedown)
55
- }
56
- }
57
- }
@@ -1,55 +0,0 @@
1
- export function swipeable(
2
- node,
3
- { horizontal = true, vertical = false, threshold = 100, enabled = true } = {}
4
- ) {
5
- if (!enabled) return { destroy() {} }
6
-
7
- let startX
8
- let startY
9
-
10
- function touchStart(event) {
11
- const touch = event.touches ? event.touches[0] : event
12
- startX = touch.clientX
13
- startY = touch.clientY
14
- }
15
-
16
- function touchEnd(event) {
17
- const touch = event.changedTouches ? event.changedTouches[0] : event
18
- const distX = touch.clientX - startX
19
- const distY = touch.clientY - startY
20
-
21
- if (horizontal) {
22
- if (Math.abs(distX) > Math.abs(distY) && Math.abs(distX) >= threshold) {
23
- if (distX > 0) {
24
- node.dispatchEvent(new CustomEvent('swipeRight'))
25
- } else {
26
- node.dispatchEvent(new CustomEvent('swipeLeft'))
27
- }
28
- }
29
- }
30
-
31
- if (vertical) {
32
- if (Math.abs(distY) > Math.abs(distX) && Math.abs(distY) >= threshold) {
33
- if (distY > 0) {
34
- node.dispatchEvent(new CustomEvent('swipeDown'))
35
- } else {
36
- node.dispatchEvent(new CustomEvent('swipeUp'))
37
- }
38
- }
39
- }
40
- }
41
-
42
- node.addEventListener('touchstart', touchStart)
43
- node.addEventListener('touchend', touchEnd)
44
- node.addEventListener('mousedown', touchStart)
45
- node.addEventListener('mouseup', touchEnd)
46
-
47
- return {
48
- destroy() {
49
- node.removeEventListener('touchstart', touchStart)
50
- node.removeEventListener('touchend', touchEnd)
51
- node.removeEventListener('mousedown', touchStart)
52
- node.removeEventListener('mouseup', touchEnd)
53
- }
54
- }
55
- }
@@ -1,23 +0,0 @@
1
- import { theme } from '../stores'
2
-
3
- /**
4
- * Sets theme level classes based on the theme store
5
- *
6
- * @param {HTMLElement} node
7
- */
8
- export function themable(node) {
9
- let previous = {}
10
-
11
- theme.subscribe((data) => {
12
- if (data.name && data.name !== previous.name) {
13
- node.classList.remove(previous.name)
14
- node.classList.add(data.name)
15
- }
16
- if (data.mode && data.mode !== previous.mode) {
17
- node.classList.remove(previous.mode)
18
- node.classList.add(data.mode)
19
- }
20
-
21
- previous = data
22
- })
23
- }
package/src/constants.js DELETED
@@ -1,95 +0,0 @@
1
- export const defaultIcons = [
2
- 'accordion-opened',
3
- 'accordion-closed',
4
- 'action-remove',
5
- 'action-add',
6
- 'action-clear',
7
- 'action-search',
8
- 'action-close',
9
- 'action-close-filled',
10
- 'node-opened',
11
- 'node-closed',
12
- 'selector-opened',
13
- 'selector-closed',
14
- 'checkbox-checked',
15
- 'checkbox-unchecked',
16
- 'checkbox-unknown',
17
- 'rating-filled',
18
- 'rating-empty',
19
- 'radio-off',
20
- 'radio-on',
21
- 'mode-dark',
22
- 'mode-light',
23
- 'navigate-left',
24
- 'navigate-right',
25
- 'navigate-up',
26
- 'navigate-down'
27
- ]
28
-
29
- export const defaultOptions = {
30
- id: 'id',
31
- label: 'label',
32
- value: 'value',
33
- checked: 'checked'
34
- }
35
-
36
- /**
37
- * Structure to map custom fields for rendering
38
- *
39
- * @typedef FieldMapping
40
- * @property {string} [id='id'] - Unique id for the item
41
- * @property {string} [text='text'] - Attribute to identify the text to render
42
- * @property {string} [url='url'] - Attribute to identify a URL
43
- * @property {string} [icon='icon'] - Attribute to identify an icon class to render
44
- * @property {string} [image='image'] - Attribute to identify an image to render
45
- * @property {string} [children='children'] - Attribute to identify children of the current item
46
- * @property {string} [summary='summary']
47
- * @property {string} [notes='notes']
48
- * @property {string} [props='props']
49
- * @property {string} [isOpen='_open'] - Attribute to identify if the current item is open
50
- * @property {string} [level='level'] - Attribute to identify level of current item
51
- * @property {string} [parent='parent'] - Attribute to identify if the current item is a parent
52
- * @property {string} [isDeleted='_deleted'] - Attribute to identify if the current item is deleted
53
- * @property {FieldMapping} [fields?] - Field mapping to be used on children in the next level
54
- */
55
- export const defaultFields = {
56
- id: 'id',
57
- url: 'url',
58
- text: 'text',
59
- children: 'children',
60
- icon: 'icon',
61
- image: 'image',
62
- component: 'component',
63
- summary: 'summary',
64
- notes: 'notes',
65
- props: 'props',
66
- target: 'target',
67
- state: 'state',
68
- isOpen: '_open',
69
- isDeleted: '_deleted',
70
- level: 'level',
71
- parent: 'parent'
72
- }
73
-
74
- export const defaultKeyMap = {
75
- ArrowRight: 'open',
76
- ArrowLeft: 'close',
77
- ArrowDown: 'down',
78
- ArrowUp: 'up',
79
- Enter: 'select',
80
- Escape: 'deselect'
81
- }
82
-
83
- export function stateIconsFromNames(icons) {
84
- return icons
85
- .map((k) => [...k.split('-')])
86
- .reduce(
87
- (acc, parts) => ({
88
- ...acc,
89
- [parts[0]]: { ...acc[parts[0]], [parts[1]]: parts.join('-') }
90
- }),
91
- {}
92
- )
93
- }
94
-
95
- export const defaultStateIcons = stateIconsFromNames(defaultIcons)
@@ -1,28 +0,0 @@
1
- <script>
2
- export let type = null
3
- export let rtl = false
4
-
5
- $: type = ['last', 'child', 'sibling'].includes(type) ? type : 'empty'
6
- </script>
7
-
8
- <span class="grid grid-rows-2 grid-cols-2 h-full min-w-4 w-4 line-{type}">
9
- {#if type === 'last'}
10
- {#if rtl}
11
- <i class="border-b border-r" />
12
- {:else}
13
- <i class="border-r" />
14
- <i class="border-b" />
15
- {/if}
16
- {:else if type === 'child'}
17
- {#if rtl}
18
- <i class="grid row-span-2 grid-rows-2 border-r">
19
- <i class="border-b" />
20
- </i>
21
- {:else}
22
- <i class="col-span-1 row-span-2 border-r" />
23
- <i class="border-b" />
24
- {/if}
25
- {:else if type === 'sibling'}
26
- <i class="row-span-2 border-r" />
27
- {/if}
28
- </span>
@@ -1,29 +0,0 @@
1
- <script>
2
- import { defaultFields } from '../constants'
3
- import Icon from '../Icon.svelte'
4
-
5
- export let value
6
- export let fields = defaultFields
7
-
8
- $: isObject = typeof value == 'object'
9
- $: text = isObject ? value[fields.text] : value
10
- </script>
11
-
12
- {#if isObject}
13
- {#if value[fields.icon]}
14
- {@const iconName =
15
- typeof value[fields.icon] == 'object'
16
- ? value[fields.icon][value[fields.state]]
17
- : value[fields.icon]}
18
- <Icon name={iconName} />
19
- {:else if value[fields.image]}
20
- <img
21
- class="h-4 w-4 object-cover"
22
- alt={value[fields.text]}
23
- src={value[fields.image]}
24
- />
25
- {/if}
26
- {/if}
27
- {#if text}
28
- <p class="w-full flex">{text}</p>
29
- {/if}
@@ -1,47 +0,0 @@
1
- <script>
2
- import { createEventDispatcher } from 'svelte'
3
- import { defaultFields, defaultStateIcons } from '../constants'
4
- import Item from './Item.svelte'
5
- import Icon from '../Icon.svelte'
6
-
7
- const dispatch = createEventDispatcher()
8
-
9
- let className = ''
10
- export { className as class }
11
- export let value
12
- export let fields = defaultFields
13
- export let using = { default: Item }
14
- export let removable = false
15
- export let selected = false
16
- export let index = null
17
- export let icons = defaultStateIcons.action
18
-
19
- function handleClick() {
20
- dispatch('remove', value)
21
- }
22
-
23
- $: component =
24
- typeof value == 'object'
25
- ? using[value[fields.component] ?? 'default']
26
- : using.default
27
- </script>
28
-
29
- <wrap-item
30
- class="flex flex-row items-center {className}"
31
- role="option"
32
- aria-selected={selected}
33
- data-path={index}
34
- >
35
- <item class="flex flex-row items-center">
36
- <svelte:component this={component} bind:value {fields} />
37
- </item>
38
- {#if removable}
39
- <Icon
40
- name={icons.remove}
41
- role="button"
42
- label="Remove"
43
- size="small"
44
- on:click={handleClick}
45
- />
46
- {/if}
47
- </wrap-item>
@@ -1,18 +0,0 @@
1
- <script>
2
- import Item from './Item.svelte'
3
- import { defaultFields } from '../constants'
4
-
5
- export let value
6
- export let fields = defaultFields
7
-
8
- $: target = fields.target ? value[fields.target] : ''
9
- </script>
10
-
11
- <a
12
- class="flex flex-grow flex-row items-center"
13
- href={value[fields.url]}
14
- {target}
15
- tabindex="-1"
16
- >
17
- <Item {value} {fields} />
18
- </a>
@@ -1,47 +0,0 @@
1
- <script>
2
- import { defaultFields, defaultStateIcons } from '../constants'
3
- import Icon from '../Icon.svelte'
4
- import Connector from './Connector.svelte'
5
-
6
- export let value
7
- export let fields = defaultFields
8
- export let types = []
9
- export let stateIcons = defaultStateIcons.node
10
-
11
- export let selected = false
12
- export let using = {}
13
- export let rtl = false
14
- export let path = []
15
-
16
- $: stateIcons = { ...defaultStateIcons.node, ...(stateIcons ?? {}) }
17
- $: hasChildren = fields.children in value
18
- $: state =
19
- hasChildren && value[fields.isOpen]
20
- ? { icon: stateIcons.opened, label: 'collapse' }
21
- : { icon: stateIcons.closed, label: 'expand' }
22
- $: component = value[fields.component]
23
- ? using[value[fields.component]] || using.default
24
- : using.default
25
- </script>
26
-
27
- <!-- svelte-ignore a11y-click-events-have-key-events -->
28
- <node
29
- id={'id-' + path.join('-')}
30
- class="min-h-5 flex flex-row cursor-pointer select-none items-center"
31
- class:is-selected={selected}
32
- class:flex-row-reverse={rtl}
33
- aria-selected={selected}
34
- role="option"
35
- data-path={path.join(',')}
36
- >
37
- {#each types as type}
38
- {#if type === 'icon'}
39
- <Icon name={state.icon} label={state.label} class="small w-4" />
40
- {:else}
41
- <Connector {type} />
42
- {/if}
43
- {/each}
44
- <item>
45
- <svelte:component this={component} bind:value {fields} />
46
- </item>
47
- </node>
@@ -1 +0,0 @@
1
- <span class="separator my-4 flex flex-grow" />
@@ -1,27 +0,0 @@
1
- <script>
2
- import { defaultFields } from '../constants'
3
- import Item from './Item.svelte'
4
-
5
- export let value
6
- export let fields = {}
7
- export let using = {}
8
-
9
- $: fields = { ...defaultFields, ...fields }
10
- $: using = { default: Item, ...using }
11
- $: hasItems = value[fields.children] && value[fields.children].length > 0
12
- $: component = using[value[fields.component] ?? 'default']
13
- </script>
14
-
15
- <summary
16
- class="w-full flex flex-shrink-0 flex-row cursor-pointer items-center"
17
- tabindex="-1"
18
- >
19
- <svelte:component this={component} bind:value {fields} />
20
- {#if hasItems}
21
- {#if value[fields.isOpen]}
22
- <icon class="accordion-opened sm" aria-label="expand" />
23
- {:else}
24
- <icon class="accordion-closed sm" aria-label="collapse" />
25
- {/if}
26
- {/if}
27
- </summary>
@@ -1,7 +0,0 @@
1
- export { default as Item } from './Item.svelte'
2
- export { default as Link } from './Link.svelte'
3
- export { default as Node } from './Node.svelte'
4
- export { default as ItemWrapper } from './ItemWrapper.svelte'
5
- export { default as Connector } from './Connector.svelte'
6
- export { default as Separator } from './Separator.svelte'
7
- export { default as Summary } from './Summary.svelte'
@@ -1,12 +0,0 @@
1
- export function getLineTypes(
2
- hasChildren = false,
3
- parentTypes = [],
4
- position = 'child'
5
- ) {
6
- let types = parentTypes.slice(0, -1).map((type) => {
7
- return type === 'child' ? 'sibling' : type === 'last' ? 'empty' : type
8
- })
9
- if (parentTypes.length > 0) types.push(position)
10
- types.push(hasChildren ? 'icon' : 'empty')
11
- return types
12
- }
package/src/lib/index.js DELETED
@@ -1,7 +0,0 @@
1
- export * from './nested'
2
-
3
- export function getComponent(item, fields, using) {
4
- return fields.component
5
- ? item[fields.component] ?? using.default
6
- : using.default
7
- }
package/src/lib/nested.js DELETED
@@ -1,45 +0,0 @@
1
- import { omit } from 'ramda'
2
- import { defaultFields } from '../constants'
3
-
4
- export function flattenNestedList(items, fields = defaultFields, level = 0) {
5
- fields = { ...defaultFields, ...fields }
6
- let data = []
7
- items.map((item) => {
8
- const children = item[fields.children] ?? []
9
- data = [
10
- ...data,
11
- {
12
- ...omit([fields.children], item),
13
- [fields.level]: level,
14
- [fields.parent]: children.length > 0
15
- },
16
- ...flattenNestedList(children, fields, level + 1)
17
- ]
18
- })
19
- return data
20
- }
21
-
22
- /**
23
- * Converts a path slug to a value in the menu
24
- *
25
- * @param {string} slug
26
- * @returns {any}
27
- */
28
- export function findValueFromPath(slug, data, fields) {
29
- fields = { ...defaultFields, ...fields }
30
- const keys = slug.split('/')
31
- let items = data
32
- let value = null
33
- keys.map((key, index) => {
34
- const match = items.find((item) => item[fields.key] === key)
35
- if (match) {
36
- if (index < keys.length - 1) {
37
- match[fields.isOpen] = true
38
- items = match[fields.children]
39
- } else {
40
- value = match
41
- }
42
- }
43
- })
44
- return value
45
- }