@rokkit/forms 1.0.0-next.124 → 1.0.0-next.127

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 (89) hide show
  1. package/README.md +251 -0
  2. package/dist/src/display/index.d.ts +5 -0
  3. package/dist/src/index.d.ts +9 -0
  4. package/dist/src/input/index.d.ts +3 -0
  5. package/dist/src/lib/builder.svelte.d.ts +114 -4
  6. package/dist/src/lib/lookup.svelte.d.ts +87 -0
  7. package/dist/src/lib/renderers.d.ts +23 -0
  8. package/package.json +6 -4
  9. package/src/FieldLayout.svelte +4 -11
  10. package/src/FormRenderer.svelte +202 -61
  11. package/src/InfoField.svelte +26 -0
  12. package/src/Input.svelte +17 -61
  13. package/src/InputField.svelte +15 -11
  14. package/src/ValidationReport.svelte +52 -0
  15. package/src/display/DisplayCardGrid.svelte +68 -0
  16. package/src/display/DisplayList.svelte +31 -0
  17. package/src/display/DisplaySection.svelte +20 -0
  18. package/src/display/DisplayTable.svelte +68 -0
  19. package/src/display/DisplayValue.svelte +44 -0
  20. package/src/display/index.js +5 -0
  21. package/src/index.js +14 -0
  22. package/src/input/ArrayEditor.svelte +108 -0
  23. package/src/input/InputCheckbox.svelte +2 -3
  24. package/src/input/InputColor.svelte +6 -1
  25. package/src/input/InputDate.svelte +6 -1
  26. package/src/input/InputDateTime.svelte +6 -1
  27. package/src/input/InputEmail.svelte +6 -1
  28. package/src/input/InputFile.svelte +6 -2
  29. package/src/input/InputMonth.svelte +6 -1
  30. package/src/input/InputNumber.svelte +6 -1
  31. package/src/input/InputPassword.svelte +6 -1
  32. package/src/input/InputRange.svelte +6 -1
  33. package/src/input/InputSelect.svelte +31 -53
  34. package/src/input/InputSwitch.svelte +4 -15
  35. package/src/input/InputTel.svelte +6 -1
  36. package/src/input/InputText.svelte +6 -1
  37. package/src/input/InputTextArea.svelte +6 -1
  38. package/src/input/InputTime.svelte +6 -1
  39. package/src/input/InputToggle.svelte +28 -0
  40. package/src/input/InputUrl.svelte +6 -1
  41. package/src/input/InputWeek.svelte +6 -1
  42. package/src/input/index.js +3 -1
  43. package/src/lib/Input.svelte +3 -3
  44. package/src/lib/builder.svelte.js +425 -30
  45. package/src/lib/fields.js +2 -2
  46. package/src/lib/layout.js +2 -2
  47. package/src/lib/lookup.svelte.js +334 -0
  48. package/src/lib/renderers.js +83 -0
  49. package/src/lib/schema.js +1 -1
  50. package/src/types.js +0 -9
  51. package/dist/src/forms-old/input/types.d.ts +0 -7
  52. package/dist/src/forms-old/lib/form.d.ts +0 -95
  53. package/dist/src/forms-old/lib/index.d.ts +0 -1
  54. package/dist/src/lib/deprecated/nested.d.ts +0 -48
  55. package/dist/src/lib/deprecated/nested.spec.d.ts +0 -1
  56. package/dist/src/lib/deprecated/validator.d.ts +0 -30
  57. package/dist/src/lib/deprecated/validator.spec.d.ts +0 -1
  58. package/src/DataEditor.svelte +0 -30
  59. package/src/ListEditor.svelte +0 -44
  60. package/src/NestedEditor.svelte +0 -85
  61. package/src/forms-old/CheckBox.svelte +0 -56
  62. package/src/forms-old/DataEditor.svelte +0 -30
  63. package/src/forms-old/FieldLayout.svelte +0 -48
  64. package/src/forms-old/Form.svelte +0 -17
  65. package/src/forms-old/Icon.svelte +0 -76
  66. package/src/forms-old/Item.svelte +0 -25
  67. package/src/forms-old/ListEditor.svelte +0 -44
  68. package/src/forms-old/Tabs.svelte +0 -57
  69. package/src/forms-old/Wrapper.svelte +0 -12
  70. package/src/forms-old/input/Input.svelte +0 -17
  71. package/src/forms-old/input/InputField.svelte +0 -70
  72. package/src/forms-old/input/InputSelect.svelte +0 -23
  73. package/src/forms-old/input/InputSwitch.svelte +0 -19
  74. package/src/forms-old/input/types.js +0 -29
  75. package/src/forms-old/lib/form.js +0 -72
  76. package/src/forms-old/lib/index.js +0 -12
  77. package/src/forms-old/mocks/CustomField.svelte +0 -7
  78. package/src/forms-old/mocks/CustomWrapper.svelte +0 -8
  79. package/src/forms-old/mocks/Register.svelte +0 -25
  80. package/src/inp/Input.svelte +0 -17
  81. package/src/inp/InputField.svelte +0 -69
  82. package/src/inp/InputSelect.svelte +0 -23
  83. package/src/inp/InputSwitch.svelte +0 -19
  84. package/src/lib/deprecated/Form.svelte +0 -17
  85. package/src/lib/deprecated/FormRenderer.svelte +0 -121
  86. package/src/lib/deprecated/nested.js +0 -192
  87. package/src/lib/deprecated/nested.spec.js +0 -512
  88. package/src/lib/deprecated/validator.js +0 -137
  89. package/src/lib/deprecated/validator.spec.js +0 -348
@@ -1,72 +0,0 @@
1
- export const messages = {
2
- required: '{name} is required',
3
- email: '{name} should be a valid email address',
4
- url: '{name} should be a valid URL',
5
- color: '{name} should be a valid color',
6
- number: '{name} should be a valid number',
7
- min: '{name} should be greater than or equal to {min}',
8
- max: '{name} should be less than or equal to {max}',
9
- pattern: '{name} should match the pattern {pattern}',
10
- exclusiveMin: '{name} should be greater than {min}',
11
- exclusiveMax: '{name} should be less than {max}',
12
- minLength: '{name} should be at least {minLength} characters',
13
- maxLength: '{name} should be at most {maxLength} characters',
14
- minItems: '{name} should have at least {minItems} items',
15
- maxItems: '{name} should have at most {maxItems} items',
16
- uniqueItems: '{name} should have unique items',
17
- contains: '{name} should contain {contains}',
18
- exclude: '{name} should not contain {exclude}',
19
- integer: '{name} should be an integer'
20
- }
21
-
22
- export const dataTypes = {
23
- integer: {
24
- editor: 'inputText',
25
- props: { type: 'number', step: 1 },
26
- availableProps: ['min', 'max']
27
- },
28
- number: {
29
- editor: 'inputText',
30
- props: { type: 'number', step: 0.01 },
31
- availableProps: ['min', 'max']
32
- },
33
- range: {
34
- editor: 'inputRange',
35
- props: { type: 'range' }
36
- },
37
-
38
- string: {
39
- default: 'inputText',
40
- text: 'inputText',
41
- password: 'inputPassword',
42
- email: 'inputEmail',
43
- url: 'inputUrl',
44
- tel: 'inputTel',
45
- date: 'inputDate',
46
- 'datetime-local': 'inputDateTimeLocal',
47
- time: 'inputTime',
48
- week: 'inputWeek',
49
- month: 'inputMonth',
50
- file: 'inputFile',
51
- hidden: 'inputHidden',
52
- color: 'inputColor',
53
- colorpicker: 'inputColorPicker'
54
- },
55
- enum: {
56
- default: 'inputSelect',
57
- select: 'inputSelect',
58
- radio: 'inputRadio'
59
- },
60
- boolean: {
61
- default: 'inputCheckbox',
62
- checkbox: 'inputCheckbox',
63
- switch: 'inputSwitch',
64
- radio: 'inputRadio'
65
- },
66
- array: {
67
- default: 'inputArray'
68
- },
69
- object: {
70
- default: 'inputObject'
71
- }
72
- }
@@ -1,12 +0,0 @@
1
- export { messages, dataTypes } from './form'
2
- export { deriveSchemaFromValue } from './schema'
3
- export { deriveLayoutFromValue } from './layout'
4
- export { getSchemaWithLayout, findAttributeByPath } from './fields'
5
- export {
6
- deriveNestedSchema,
7
- flattenAttributes,
8
- flattenObject,
9
- flattenElement,
10
- generateIndex,
11
- generateTreeTable
12
- } from './nested'
@@ -1,7 +0,0 @@
1
- <script>
2
- let { value, name, label, type, ...extraProps } = $props()
3
- </script>
4
-
5
- <h1>{type}:{label}</h1>
6
- <p>{name}:{JSON.stringify(value)}</p>
7
- <p>{JSON.stringify(Object.keys(extraProps))}</p>
@@ -1,8 +0,0 @@
1
- <script>
2
- let { title, type, children } = $props()
3
- </script>
4
-
5
- <field-layout class={type}>
6
- <h1>{title}</h1>
7
- {@render children?.()}
8
- </field-layout>
@@ -1,25 +0,0 @@
1
- <script>
2
- import { setContext } from 'svelte'
3
- // import { writable } from 'svelte/store'
4
- import Wrapper from '..//Wrapper.svelte'
5
- import Item from '../Item.svelte'
6
- import Tabs from '../Tabs.svelte'
7
- const registry = $state({})
8
- setContext('registry', registry)
9
-
10
- let { Template, using, properties } = $props()
11
-
12
- using = {
13
- editors: {},
14
- components: {},
15
- wrappers: {},
16
- navigators: {},
17
- ...using
18
- }
19
- registry.editors = { ...using.editors }
20
- registry.components = { default: Item, ...using.components }
21
- registry.wrappers = { default: Wrapper, ...using.wrappers }
22
- registry.navigators = { default: Tabs, ...using.navigators }
23
- </script>
24
-
25
- <Template {...properties} />
@@ -1,17 +0,0 @@
1
- <script>
2
- import { getContext } from 'svelte'
3
- import { types } from './types'
4
-
5
- const registry = getContext('registry')
6
-
7
- let { value, type = 'text', using = {}, ...restProps } = $props()
8
-
9
- using = { ...types, ...using, ...registry?.editors }
10
- let Template = using[type]
11
- </script>
12
-
13
- {#if type in using}
14
- <Template bind:value {...restProps} on:change on:focus on:blur />
15
- {:else}
16
- <error>Type "{type}" is not supported by Input</error>
17
- {/if}
@@ -1,69 +0,0 @@
1
- <script>
2
- import { getContext } from 'svelte'
3
- import { pick, omit } from 'ramda'
4
- import Icon from '../Icon.svelte'
5
- import Input from './Input.svelte'
6
- import { types } from './types'
7
-
8
- const registry = getContext('registry')
9
-
10
- let {
11
- class: className,
12
- name,
13
- value,
14
- type,
15
- required,
16
- status,
17
- disabled,
18
- message,
19
- using,
20
- nolabel,
21
- icon,
22
- label,
23
- description,
24
- ...restProps
25
- } = $props()
26
-
27
- using = { ...types, ...registry, ...using }
28
- let pass = status === 'pass'
29
- let fail = status === 'fail'
30
- let warn = status === 'warn'
31
- let rootProps = pick(['id'], restProps)
32
- let properties = {
33
- required,
34
- readOnly: disabled,
35
- ...omit(['id'], restProps),
36
- name
37
- }
38
- </script>
39
-
40
- <input-field
41
- {...rootProps}
42
- class="flex flex-col input-{type} {className} "
43
- class:disabled
44
- class:pass
45
- class:fail
46
- class:warn
47
- class:empty={!value}
48
- >
49
- {#if label && !nolabel && !['switch', 'checkbox'].includes(type)}
50
- <label for={name} class:required>
51
- {label}
52
- </label>
53
- {/if}
54
- <field class="flex w-full flex-row items-center" aria-label={description ?? label ?? name}>
55
- {#if icon}
56
- <Icon name={icon} />
57
- {/if}
58
- {#if type === 'switch'}
59
- <label for={name} class:required>{label}</label>
60
- {/if}
61
- <Input id={name} bind:value {type} {...properties} {using} on:change />
62
- {#if type === 'checkbox'}
63
- <label for={name} class:required>{label}</label>
64
- {/if}
65
- </field>
66
- {#if message}
67
- <message class={status}>{message}</message>
68
- {/if}
69
- </input-field>
@@ -1,23 +0,0 @@
1
- <script>
2
- import { getValue, defaultFields } from '@rokkit/core'
3
- import Select from '../Select.svelte'
4
-
5
- let { name, value, options = [], fields, onchange, ...restProps } = $props()
6
-
7
- let selected = $state()
8
- let configFields = $derived({ ...defaultFields, ...fields })
9
-
10
- function handle(data) {
11
- value = getValue(data.value, configFields)
12
- onchange?.(data)
13
- }
14
-
15
- $effect(() => {
16
- if (value !== getValue(selected, configFields)) {
17
- selected = options.find((option) => getValue(option, configFields) === value)
18
- }
19
- })
20
- </script>
21
-
22
- <input {name} type="hidden" bind:value />
23
- <Select name="" value={selected} {options} {fields} {...restProps} onchange={handle} />
@@ -1,19 +0,0 @@
1
- <script>
2
- import { getValue, defaultFields } from '@rokkit/core'
3
- import Switch from '../Switch.svelte'
4
-
5
- let { name, value, options, fields, ...restProps } = $props()
6
- // let selected = $state(null)
7
- let configFields = $derived({ ...defaultFields, ...fields })
8
- function handle(data) {
9
- value = getValue(data.value, configFields)
10
- dispatch('change', data.value)
11
- }
12
- let selected = $derived(options.find((option) => getValue(option, configFields) === value))
13
- // $effect(() => {
14
- // selected = options.find((option) => getValue(option, configFields) === value)
15
- // })
16
- </script>
17
-
18
- <input {name} type="hidden" bind:value />
19
- <Switch bind:value={selected} {options} {fields} {...restProps} onchange={handle} />
@@ -1,17 +0,0 @@
1
- <script>
2
- import DataEditor from './DataEditor.svelte'
3
-
4
- export let value
5
- export let schema = null
6
- export let layout = null
7
- export let using = {}
8
- </script>
9
-
10
- <form on:submit>
11
- <DataEditor bind:value {schema} {layout} {using} />
12
- <span>
13
- <slot>
14
- <button type="submit">Submit</button>
15
- </slot>
16
- </span>
17
- </form>
@@ -1,121 +0,0 @@
1
- <script>
2
- // Props using Svelte 5 runes
3
- let { elements = [], onUpdate = null } = $props()
4
-
5
- /**
6
- * Handle field value changes
7
- * @param {string} scope - Field scope/path
8
- * @param {any} value - New value
9
- */
10
- function handleChange(scope, value) {
11
- onUpdate?.(scope, value)
12
- }
13
-
14
- /**
15
- * Handle range input changes (convert to number)
16
- * @param {string} scope - Field scope/path
17
- * @param {Event} event - Input event
18
- */
19
- function handleRangeChange(scope, event) {
20
- const value = Number(event.target.value)
21
- handleChange(scope, value)
22
- }
23
-
24
- /**
25
- * Handle number input changes (convert to number)
26
- * @param {string} scope - Field scope/path
27
- * @param {Event} event - Input event
28
- */
29
- function handleNumberChange(scope, event) {
30
- const value = Number(event.target.value)
31
- handleChange(scope, value)
32
- }
33
-
34
- /**
35
- * Handle checkbox changes
36
- * @param {string} scope - Field scope/path
37
- * @param {Event} event - Input event
38
- */
39
- function handleCheckboxChange(scope, event) {
40
- const value = event.target.checked
41
- handleChange(scope, value)
42
- }
43
-
44
- /**
45
- * Handle text input changes
46
- * @param {string} scope - Field scope/path
47
- * @param {Event} event - Input event
48
- */
49
- function handleTextChange(scope, event) {
50
- const value = event.target.value
51
- handleChange(scope, value)
52
- }
53
- </script>
54
-
55
- <div class="space-y-4">
56
- {#each elements as element (element.scope)}
57
- <div class="form-element">
58
- {#if element.type === 'range'}
59
- <label class="text-surface-700 dark:text-surface-300 block text-sm font-medium">
60
- {element.label}: {element.value}
61
- <input
62
- type="range"
63
- value={element.value}
64
- min={element.constraints?.min}
65
- max={element.constraints?.max}
66
- step={element.constraints?.step}
67
- oninput={(e) => handleRangeChange(element.scope, e)}
68
- class="bg-surface-200 dark:bg-surface-700 mt-1 h-2 w-full cursor-pointer appearance-none rounded-lg"
69
- />
70
- </label>
71
- {:else if element.type === 'number'}
72
- <label class="text-surface-700 dark:text-surface-300 block text-sm font-medium">
73
- {element.label}
74
- <input
75
- type="number"
76
- value={element.value}
77
- min={element.constraints?.min}
78
- max={element.constraints?.max}
79
- step={element.constraints?.step}
80
- oninput={(e) => handleNumberChange(element.scope, e)}
81
- class="focus:border-primary-500 focus:ring-primary-500 border-surface-300 dark:border-surface-600 dark:bg-surface-700 mt-1 block w-full rounded-md border px-3 py-2 shadow-sm focus:outline-none dark:text-white"
82
- />
83
- </label>
84
- {:else if element.type === 'checkbox'}
85
- <label class="text-surface-700 dark:text-surface-300 flex items-center text-sm font-medium">
86
- <input
87
- type="checkbox"
88
- checked={element.value}
89
- onchange={(e) => handleCheckboxChange(element.scope, e)}
90
- class="text-primary-600 focus:ring-primary-500 border-surface-300 dark:border-surface-600 mr-2 h-4 w-4 rounded"
91
- />
92
- {element.label}
93
- </label>
94
- {:else if element.type === 'select'}
95
- <label class="text-surface-700 dark:text-surface-300 block text-sm font-medium">
96
- {element.label}
97
- <select
98
- value={element.value}
99
- onchange={(e) => handleTextChange(element.scope, e)}
100
- class="focus:border-primary-500 focus:ring-primary-500 border-surface-300 dark:border-surface-600 dark:bg-surface-700 mt-1 block w-full rounded-md border px-3 py-2 shadow-sm focus:outline-none dark:text-white"
101
- >
102
- {#each element.constraints?.options || [] as option, index (index)}
103
- <option value={option}>{option}</option>
104
- {/each}
105
- </select>
106
- </label>
107
- {:else}
108
- <!-- Default text input -->
109
- <label class="text-surface-700 dark:text-surface-300 block text-sm font-medium">
110
- {element.label}
111
- <input
112
- type="text"
113
- value={element.value || ''}
114
- oninput={(e) => handleTextChange(element.scope, e)}
115
- class="focus:border-primary-500 focus:ring-primary-500 border-surface-300 dark:border-surface-600 dark:bg-surface-700 mt-1 block w-full rounded-md border px-3 py-2 shadow-sm focus:outline-none dark:text-white"
116
- />
117
- </label>
118
- {/if}
119
- </div>
120
- {/each}
121
- </div>
@@ -1,192 +0,0 @@
1
- import { omit, pick } from 'ramda'
2
- import { isObject } from '@rokkit/core'
3
- import { typeOf } from '@rokkit/data'
4
- import { deriveSchemaFromValue } from '../schema'
5
- import { deriveLayoutFromValue } from '../layout'
6
-
7
- /**
8
- * Flattens an object into a flat object
9
- *
10
- * @param {Object} input - The object to flatten
11
- * @param {String} scope - The scope of the object
12
- */
13
- export function flattenObject(input, scope = '#') {
14
- // eslint-disable-next-line no-use-before-define
15
- return flattenAttributes(input, scope).reduce(
16
- // eslint-disable-next-line no-use-before-define
17
- (acc, item) => ({ ...acc, ...flattenElement(item) }),
18
- {
19
- [scope]: {
20
- type: 'object',
21
- value: input,
22
- scope,
23
- key: scope.split('/').slice(-1)[0]
24
- }
25
- }
26
- )
27
- }
28
- /**
29
- * Flattens an object into an array of key-value pairs
30
- *
31
- * @param {Object} input - The object to flatten
32
- * @param {String} scope - The scope of the object
33
- */
34
- export function flattenAttributes(input, scope = '#') {
35
- return Object.entries(input).map(([key, value]) => ({
36
- key,
37
- value,
38
- type: typeOf(value),
39
- scope: [scope, key].join('/')
40
- }))
41
- }
42
-
43
- /**
44
- * Derives a nested schema from an object
45
- *
46
- * @param {Object} input - The object to derive the schema from
47
- * @param {String} scope - The scope of the object
48
- * @returns {Object} The derived schema
49
- */
50
- export function deriveNestedSchema(input, scope = '#') {
51
- const elements = flattenAttributes(input)
52
- const atoms = elements.filter(({ type }) => !['object', 'array'].includes(type))
53
-
54
- const schema = {
55
- type: 'object'
56
- }
57
-
58
- if (atoms.length > 0) {
59
- schema.properties = atoms.reduce(
60
- (acc, { key, type, value }) => ({
61
- ...acc,
62
- [key]: {
63
- type,
64
- default: value
65
- }
66
- }),
67
- {}
68
- )
69
- schema.layout = {
70
- type: 'vertical',
71
- elements: atoms.map((el) => ({ label: el.key, scope: el.scope }))
72
- }
73
- }
74
-
75
- if (atoms.length < elements.length) {
76
- // eslint-disable-next-line no-use-before-define
77
- schema.children = deriveSchemaForChildren(elements, scope)
78
- }
79
-
80
- if (scope !== '#') return schema
81
- return schema.properties ? [schema] : schema.children
82
- }
83
-
84
- /**
85
- * Derives the children of an object
86
- *
87
- * @param {Array} elements - The elements to derive children from
88
- * @param {String} scope - The scope of the object
89
- * @returns {Array} The derived children
90
- */
91
- function deriveSchemaForChildren(elements, scope) {
92
- return [
93
- ...elements
94
- .filter(({ type }) => type === 'object')
95
- .map((item) => ({
96
- ...omit(['value', 'scope'], item),
97
- scope: [scope, item.key].join('/'),
98
- ...deriveNestedSchema(item.value, [scope, item.key].join('/'))
99
- })),
100
- ...elements
101
- .filter(({ type }) => type === 'array')
102
- .map((item) => ({
103
- ...omit(['value'], item),
104
- default: [],
105
- scope: [scope, item.key].join('/'),
106
- items: deriveSchemaFromValue(item.value.length ? item.value[0] : null),
107
- layout: deriveLayoutFromValue(item.value.length ? item.value[0] : null)
108
- }))
109
- ]
110
- }
111
-
112
- /**
113
- * Flattens an element into a flat object
114
- *
115
- * @param {Object} element - The element to flatten
116
- */
117
- export function flattenElement(element) {
118
- if (element.type === 'object') {
119
- return flattenObject(element.value, element.scope)
120
- } else if (element.type === 'array') {
121
- return element.value
122
- .map((item, index) => ({
123
- value: item,
124
- scope: [element.scope, `[${index}]`].join('/'),
125
- key: `[${index}]`,
126
- type: typeOf(item)
127
- }))
128
- .reduce((acc, item) => ({ ...acc, ...flattenElement(item) }), {
129
- [element.scope]: pick(['key', 'type', 'scope', 'value'], element)
130
- })
131
- }
132
- return { [element.scope]: element }
133
- }
134
-
135
- /**
136
- * Generates an index array referencing the input data
137
- *
138
- * @param {Object} data - The flat object to index
139
- * @param {String} key - The key to use as index
140
- */
141
- export function generateIndex(data, key = 'scope') {
142
- const index = data
143
- .map((item) => ({
144
- ...item,
145
- _path: item[key],
146
- _isParent: false,
147
- _isExpanded: true,
148
- _levels: []
149
- }))
150
- .sort((a, b) => a[key].localeCompare(b[key]))
151
- .filter((item) => item[key] !== '#')
152
-
153
- let levels = [0]
154
- let current = 0
155
-
156
- index.forEach((item, row) => {
157
- const path = item._path.split('/').slice(1)
158
- item._depth = path.length - 1
159
- if (row === 0) {
160
- item._levels = [0]
161
- } else if (path.length > levels.length) {
162
- index[row - 1]._isParent = true
163
- item._levels = [...levels, 0]
164
- } else {
165
- current = levels[path.length - 1] + 1
166
- item._levels = [...levels.slice(0, path.length - 1), current]
167
- }
168
- levels = item._levels
169
- })
170
- return index
171
- }
172
-
173
- /**
174
- * Generates a tree table from the input data
175
- *
176
- * @param {Object} data - The data to generate the tree table from
177
- * @param {String} key - The key to use as index
178
- * @param {Boolean} ellipsis - Whether to truncate the value
179
- */
180
- export function generateTreeTable(data, key = 'scope', ellipsis = false) {
181
- let result = []
182
- if (Array.isArray(data)) result = generateIndex(data, key)
183
- if (isObject(data)) result = generateIndex(Object.values(flattenObject(data)), key)
184
-
185
- if (ellipsis) {
186
- result = result.map((item) => ({
187
- ...omit(['value'], item),
188
- value: ['array', 'object'].includes(item.type) ? '...' : item.value
189
- }))
190
- }
191
- return result
192
- }