InspectorBranch.vue 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. <script setup lang="ts">
  2. import { toRaw } from 'vue'
  3. const props = defineProps<{
  4. entry: any
  5. depth?: number
  6. path?: string
  7. }>()
  8. const isObject = value => value && typeof value === 'object' && !Array.isArray(value)
  9. const isString = value => typeof value === 'string'
  10. const isArray = value => Array.isArray(value)
  11. const data = computed(() => {
  12. // Handle both objects and arrays
  13. const entries = isObject(props.entry) ? Object.entries(props.entry) : props.entry
  14. return entries.map((entry, index) => {
  15. const [key, value] = isObject(props.entry) ? entry : [index, entry]
  16. return {
  17. key,
  18. value,
  19. expandable: isObject(value) || isArray(value),
  20. }
  21. })
  22. })
  23. // Reactive state to track collapsed/expanded states
  24. const collapsedKeys = reactive({})
  25. // Toggle the collapsed state
  26. const toggleCollapse = (key) => {
  27. collapsedKeys[key] = !collapsedKeys[key]
  28. }
  29. const isExpanded = key => collapsedKeys[key]
  30. function changeValue(key, value) {
  31. console.log('changeValue', key, value)
  32. }
  33. </script>
  34. <template>
  35. <div
  36. v-for="(item, index) in data"
  37. :key="item.key + index"
  38. class="pb1 text-sm"
  39. >
  40. <!-- Check if the item is expandable (either an object or an array) -->
  41. <template v-if="item.expandable && depth < 2">
  42. <div
  43. class="flex items-center"
  44. @click="toggleCollapse(item.key)"
  45. >
  46. <Icon
  47. class="mr-2"
  48. :name="isExpanded(item.key) ? 'i-carbon-caret-down' : 'i-carbon-caret-right'"
  49. />
  50. <span class="text-gray-400"> {{ item.key }}</span> : {{ isArray(item.value) ? `Array(${item.value.length})` : 'Object' }}
  51. </div>
  52. <div
  53. v-show="isExpanded(item.key)"
  54. class="pl-8 py2"
  55. >
  56. <!-- Handle Objects -->
  57. <template v-if="isObject(item.value)">
  58. <InspectorBranch
  59. :key="item.key"
  60. :entry="{ ...item.value }"
  61. :depth="depth + 1"
  62. :path="path ? `${path}.${item.key}` : item.key"
  63. />
  64. </template>
  65. <!-- Handle Arrays -->
  66. <template v-if="isArray(item.value)">
  67. <span class="text-gray-500 -ml-4">[<span class="text-gray-400">{{ item.value.length > 0 ? '{' : '' }}</span></span>
  68. <div
  69. v-for="(elem, index) in item.value"
  70. :key="index"
  71. class="pl-4"
  72. >
  73. <span
  74. v-if="index > 0"
  75. class="text-gray-400 -ml-4"
  76. >{</span>
  77. <InspectorBranch
  78. :key="index"
  79. :entry="{ ...elem }"
  80. :depth="depth + 1"
  81. />
  82. <!-- This assumes you want to show each array element. Adjust as needed. -->
  83. <!-- <InspectorBranch :entry="elem" /> -->
  84. <span
  85. v-if="index < item.value.length - 1"
  86. class="text-gray-400 -ml-4"
  87. >},</span>
  88. </div>
  89. <span class="text-gray-500"><span class="text-gray-400">{{ item.value.length > 0 ? '}' : '' }}</span>]</span>
  90. </template>
  91. </div>
  92. </template>
  93. <!-- Non-expandable items (primitive types) -->
  94. <template v-else>
  95. <div class="flex gap-1">
  96. <label
  97. for=""
  98. class="text-gray-400"
  99. >{{ item.key }}</label> :
  100. <!-- <UBadge
  101. color="gray"
  102. variant="soft"
  103. >
  104. {{ isString(item.value) ? '"' : '' }} {{ item.value }} {{ isString(item.value) ? '"' : '' }}
  105. </UBadge> -->
  106. <InspectorControl
  107. :label="item.key"
  108. :value="item.value"
  109. :path="path ? `${path}.${item.key}` : item.key"
  110. :type="typeof item.value"
  111. />
  112. </div>
  113. </template>
  114. </div>
  115. </template>