@kestra-io/ui-libs 0.0.263 → 0.0.264

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 (82) hide show
  1. package/dist/{VueFlowUtils-D6fVYEkI.js → VueFlowUtils-DifPO0kH.js} +1229 -1261
  2. package/dist/VueFlowUtils-DifPO0kH.js.map +1 -0
  3. package/dist/VueFlowUtils-DjetWQIy.cjs +2 -0
  4. package/dist/VueFlowUtils-DjetWQIy.cjs.map +1 -0
  5. package/dist/components/index.d.ts +4 -0
  6. package/dist/components/index.d.ts.map +1 -1
  7. package/dist/components/misc/Collapsible.vue.d.ts.map +1 -1
  8. package/dist/components/misc/ElementCard.vue.d.ts +25 -0
  9. package/dist/components/misc/ElementCard.vue.d.ts.map +1 -0
  10. package/dist/components/misc/Status.vue.d.ts.map +1 -1
  11. package/dist/components/misc/SubgroupCard.vue.d.ts +20 -0
  12. package/dist/components/misc/SubgroupCard.vue.d.ts.map +1 -0
  13. package/dist/components/nodes/EdgeNode.vue.d.ts.map +1 -1
  14. package/dist/components/plugins/CollapsibleProperties.vue.d.ts.map +1 -1
  15. package/dist/components/plugins/PluginIndex.vue.d.ts +13 -3
  16. package/dist/components/plugins/PluginIndex.vue.d.ts.map +1 -1
  17. package/dist/components/plugins/PropertyDetail.vue.d.ts.map +1 -1
  18. package/dist/components/plugins/SchemaToHtml.vue.d.ts.map +1 -1
  19. package/dist/components/plugins_v2/CollapsiblePropertiesV2.vue.d.ts +39 -0
  20. package/dist/components/plugins_v2/CollapsiblePropertiesV2.vue.d.ts.map +1 -0
  21. package/dist/components/plugins_v2/CollapsibleV2.vue.d.ts +34 -0
  22. package/dist/components/plugins_v2/CollapsibleV2.vue.d.ts.map +1 -0
  23. package/dist/components/plugins_v2/DefinitionCollapsible.vue.d.ts +34 -0
  24. package/dist/components/plugins_v2/DefinitionCollapsible.vue.d.ts.map +1 -0
  25. package/dist/components/plugins_v2/PropertyBadges.vue.d.ts +13 -0
  26. package/dist/components/plugins_v2/PropertyBadges.vue.d.ts.map +1 -0
  27. package/dist/components/plugins_v2/PropertyDetailV2.vue.d.ts +43 -0
  28. package/dist/components/plugins_v2/PropertyDetailV2.vue.d.ts.map +1 -0
  29. package/dist/components/plugins_v2/PropertyMeta.vue.d.ts +10 -0
  30. package/dist/components/plugins_v2/PropertyMeta.vue.d.ts.map +1 -0
  31. package/dist/components/plugins_v2/SchemaToHtmlV2.vue.d.ts +50 -0
  32. package/dist/components/plugins_v2/SchemaToHtmlV2.vue.d.ts.map +1 -0
  33. package/dist/components/topology/Topology.vue.d.ts +1 -1
  34. package/dist/composables/usePluginElementCounts.d.ts +13 -0
  35. package/dist/composables/usePluginElementCounts.d.ts.map +1 -0
  36. package/dist/index.d.ts +2 -1
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/kestra-index.cjs.js +15 -13
  39. package/dist/kestra-index.cjs.js.map +1 -1
  40. package/dist/kestra-index.es.js +4862 -4017
  41. package/dist/kestra-index.es.js.map +1 -1
  42. package/dist/kestra-vueflowutils.cjs.js +1 -1
  43. package/dist/kestra-vueflowutils.es.js +10 -10
  44. package/dist/ui-libs.css +1 -1
  45. package/dist/utils/Utils.d.ts +2 -0
  46. package/dist/utils/Utils.d.ts.map +1 -1
  47. package/dist/utils/VueFlowUtils.d.ts.map +1 -1
  48. package/dist/utils/constants.d.ts +0 -39
  49. package/dist/utils/constants.d.ts.map +1 -1
  50. package/dist/utils/plugins.d.ts +30 -0
  51. package/dist/utils/plugins.d.ts.map +1 -1
  52. package/dist/utils/schemaUtils.d.ts +6 -0
  53. package/dist/utils/schemaUtils.d.ts.map +1 -1
  54. package/package.json +1 -1
  55. package/src/components/index.ts +4 -0
  56. package/src/components/misc/Collapsible.vue +7 -1
  57. package/src/components/misc/ElementCard.vue +132 -0
  58. package/src/components/misc/Status.vue +0 -1
  59. package/src/components/misc/SubgroupCard.vue +178 -0
  60. package/src/components/nodes/EdgeNode.vue +17 -1
  61. package/src/components/plugins/CollapsibleProperties.vue +2 -13
  62. package/src/components/plugins/PluginIndex.vue +166 -37
  63. package/src/components/plugins/PropertyDetail.vue +5 -5
  64. package/src/components/plugins/SchemaToHtml.vue +7 -3
  65. package/src/components/plugins_v2/CollapsiblePropertiesV2.vue +183 -0
  66. package/src/components/plugins_v2/CollapsibleV2.vue +121 -0
  67. package/src/components/plugins_v2/DefinitionCollapsible.vue +208 -0
  68. package/src/components/plugins_v2/PropertyBadges.vue +93 -0
  69. package/src/components/plugins_v2/PropertyDetailV2.vue +127 -0
  70. package/src/components/plugins_v2/PropertyMeta.vue +169 -0
  71. package/src/components/plugins_v2/SchemaToHtmlV2.vue +213 -0
  72. package/src/composables/usePluginElementCounts.ts +16 -0
  73. package/src/index.ts +2 -1
  74. package/src/scss/_variables.scss +69 -0
  75. package/src/utils/Utils.ts +5 -0
  76. package/src/utils/VueFlowUtils.ts +10 -2
  77. package/src/utils/constants.ts +0 -45
  78. package/src/utils/plugins.ts +76 -1
  79. package/src/utils/schemaUtils.ts +45 -1
  80. package/dist/VueFlowUtils-CF-L3pYu.cjs +0 -2
  81. package/dist/VueFlowUtils-CF-L3pYu.cjs.map +0 -1
  82. package/dist/VueFlowUtils-D6fVYEkI.js.map +0 -1
@@ -0,0 +1,178 @@
1
+ <template>
2
+ <a :href="hrefWithDefault">
3
+ <div class="plugin" :class="{'is-active': isActive}">
4
+ <div class="top-row">
5
+ <div class="icon-content">
6
+ <img :src="iconB64Svg" :alt="`${text} icon`">
7
+ </div>
8
+ <div class="text-content">
9
+ <h6>{{ text }}</h6>
10
+ <p v-if="description" class="description">{{ description }}</p>
11
+ </div>
12
+ </div>
13
+ <div class="footer">
14
+ <hr>
15
+ <div class="bottom-row">
16
+ <div class="left">
17
+ <p v-if="props.totalCount">{{ props.totalCount ?? 0 }} <span>Tasks</span></p>
18
+ <p v-if="props.blueprintsCount">{{ props.blueprintsCount ?? 0 }} <span>Blueprints</span></p>
19
+ </div>
20
+ <ChevronRight />
21
+ </div>
22
+ </div>
23
+ </div>
24
+ </a>
25
+ </template>
26
+ <script setup lang="ts">
27
+ import {computed} from "vue";
28
+ import {slugify} from "../../utils/url";
29
+ import ChevronRight from "vue-material-design-icons/ChevronRight.vue";
30
+
31
+ const props = withDefaults(defineProps<{
32
+ iconB64Svg: string,
33
+ text: string,
34
+ routePath: string
35
+ totalCount: number,
36
+ description?: string,
37
+ href?: string | undefined
38
+ isActive?: boolean,
39
+ blueprintsCount?: number
40
+ }>(), {
41
+ totalCount: 0,
42
+ description: "",
43
+ href: undefined,
44
+ isActive: false,
45
+ blueprintsCount: 0,
46
+ });
47
+
48
+ const hrefWithDefault = computed(() => props.href === undefined
49
+ ? `${props.routePath}/${slugify(props.text)}`
50
+ : props.href);
51
+
52
+ </script>
53
+
54
+ <style scoped lang="scss">
55
+ @use "../../scss/variables" as variables;
56
+ @use "../../scss/color-palette" as color-palette;
57
+
58
+ .plugin {
59
+ width: 100%;
60
+ height: 152px;
61
+ border-radius: 12px;
62
+ border: 1px solid var(--kestra-io-token-color-border-secondary);
63
+ padding: 1rem;
64
+ background: var(--kestra-io-token-color-background-secondary);
65
+ display: flex;
66
+ flex-direction: column;
67
+ box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;
68
+ transition: 0.4s ease-out;
69
+
70
+ &:hover {
71
+ border-color: var(--kestra-io-token-color-border-active);
72
+ box-shadow: 0 4px 18px 0 rgba(0, 0, 0, 0.25);
73
+ transform: scale(1.025);
74
+ }
75
+
76
+ &.is-active {
77
+ border-color: variables.$primary;
78
+ }
79
+
80
+ .top-row {
81
+ display: flex;
82
+ flex-direction: row;
83
+ gap: 1rem;
84
+ align-items: flex-start;
85
+ margin-bottom: 1rem;
86
+ }
87
+
88
+ .icon-content {
89
+ width: 60px;
90
+ height: 60px;
91
+ background: variables.$gray-100;
92
+ border-radius: 8px;
93
+ border: 1px solid variables.$white-2;
94
+ display: flex;
95
+ align-items: center;
96
+ justify-content: center;
97
+ flex-shrink: 0;
98
+
99
+ img {
100
+ width: 45px;
101
+ height: 45px;
102
+ }
103
+ }
104
+
105
+ .text-content {
106
+ flex: 1;
107
+ display: flex;
108
+ flex-direction: column;
109
+ gap: 0.5rem;
110
+ overflow: hidden;
111
+
112
+ .description {
113
+ color: var(--ks-content-secondary);
114
+ font-size: 12px !important;
115
+ line-height: 1rem;
116
+ margin: 0;
117
+ overflow: hidden;
118
+ display: -webkit-box;
119
+ line-clamp: 2;
120
+ -webkit-line-clamp: 2;
121
+ -webkit-box-orient: vertical;
122
+ }
123
+ }
124
+
125
+ h6 {
126
+ color: variables.$white;
127
+ font-size: 1rem;
128
+ font-weight: 700;
129
+ margin: 0;
130
+ text-overflow: ellipsis;
131
+ overflow: hidden;
132
+ white-space: nowrap;
133
+ padding-top: 0;
134
+ }
135
+
136
+ hr {
137
+ border: 1px solid var(--ks-border-primary);
138
+ margin: 0;
139
+ }
140
+
141
+ .footer {
142
+ margin-top: auto;
143
+ display: flex;
144
+ flex-direction: column;
145
+ }
146
+
147
+ .bottom-row {
148
+ display: flex;
149
+ justify-content: space-between;
150
+ align-items: center;
151
+ color: color-palette.$base-gray-300;
152
+ height: 45px;
153
+
154
+ .left {
155
+ display: flex;
156
+ gap: 1rem;
157
+ align-items: center;
158
+
159
+ p {
160
+ margin: 0;
161
+ font-weight: 700;
162
+ font-size: 14px !important;
163
+ }
164
+
165
+ span {
166
+ color: color-palette.$base-gray-300;
167
+ font-weight: normal;
168
+ font-size: 12px;
169
+ }
170
+ }
171
+
172
+ :deep(svg) {
173
+ font-size: 1rem;
174
+ color: variables.$purple-36;
175
+ }
176
+ }
177
+ }
178
+ </style>
@@ -17,7 +17,7 @@
17
17
  :style="{
18
18
  pointerEvents: 'all',
19
19
  position: 'absolute',
20
- transform: `translate(-50%, -50%) translate(${path[1]}px,${path[2]}px)`,
20
+ transform: `translate(-50%, -50%) translate(${path[1] + labelXOffset}px,${path[2] + labelYOffset}px)`,
21
21
  }"
22
22
  >
23
23
  <tooltip :title>
@@ -103,6 +103,22 @@
103
103
 
104
104
 
105
105
  const path = computed(() => getSmoothStepPath(props as any));
106
+ const isVertical = computed(() => {
107
+ const dx = (props.targetX ?? 0) - (props.sourceX ?? 0);
108
+ const dy = (props.targetY ?? 0) - (props.sourceY ?? 0);
109
+ return Math.abs(dy) >= Math.abs(dx);
110
+ });
111
+
112
+ const OFFSET = 14;
113
+ const labelYOffset = computed(() => {
114
+ if (!isVertical.value) return 0;
115
+ const boundary = props.data?.edgeBoundary;
116
+ if (boundary === "top") return -OFFSET;
117
+ if (boundary === "bottom") return OFFSET;
118
+ return 0;
119
+ });
120
+
121
+ const labelXOffset = computed(() => 0);
106
122
 
107
123
  defineOptions({
108
124
  inheritAttrs: false,
@@ -61,7 +61,8 @@
61
61
  extractTypeInfo,
62
62
  className,
63
63
  type JSONProperty,
64
- aggregateAllOf
64
+ aggregateAllOf,
65
+ isDynamic
65
66
  } from "../../utils/schemaUtils";
66
67
  import ChevronDown from "vue-material-design-icons/ChevronDown.vue";
67
68
  import Collapsible from "../misc/Collapsible.vue";
@@ -104,18 +105,6 @@
104
105
  }
105
106
  );
106
107
 
107
- const isDynamic = (property: JSONProperty): boolean => {
108
- if (property["$dynamic"] === true) {
109
- return true;
110
- }
111
-
112
- if (property["$dynamic"] === false) {
113
- return false;
114
- }
115
-
116
- return property.anyOf?.some(prop => prop["$dynamic"] === true) ?? false;
117
- };
118
-
119
108
  function sortedAndAggregated(schema: Record<string, JSONProperty>): Record<string, JSONProperty> {
120
109
  const requiredKeys = [];
121
110
  const nonRequiredKeys = [];
@@ -1,50 +1,91 @@
1
1
  <template>
2
2
  <div class="d-flex flex-column gap-4">
3
- <slot v-if="description !== undefined" name="markdown" :content="description.replace(/ *:(?![ /])/g, ': ')" />
4
3
  <!-- Root plugin page with subgroups -->
5
4
  <template v-if="subGroup === undefined && plugins.length > 1">
6
- <div class="d-flex flex-column">
7
- <RowLink
8
- v-for="subGroupWrapper in subGroupsWrappers"
9
- :id="`group-${slugify(subGroupName(subGroupWrapper))}`"
10
- :icon-b64-svg="'data:image/svg+xml;base64,' + (icons[subGroupWrapper.subGroup] ?? icons[subGroupWrapper.group])"
11
- :text="subGroupName(subGroupWrapper)"
12
- :href="subGroupHref(subGroupName(subGroupWrapper))"
13
- :key="subGroupName(subGroupWrapper)"
14
- :route-path="routePath"
15
- class="text-capitalize"
16
- @click="$emit('goTo', {subGroup: subGroupWrapper})"
17
- />
5
+ <div class="pb-2">
6
+ <div class="row g-4 last">
7
+ <div class="col-md-4 col-lg-6 col-xl-6 col-xxl-4" v-for="subGroupWrapper in subGroupsWrappers" :key="subGroupName(subGroupWrapper)">
8
+ <SubgroupCard
9
+ :id="slugify(subGroupName(subGroupWrapper))"
10
+ :icon-b64-svg="'data:image/svg+xml;base64,' + (icons[subGroupWrapper.subGroup] ?? icons[subGroupWrapper.group])"
11
+ :text="getSubgroupTitle(subGroupWrapper)"
12
+ :description="getSubgroupDescription(subGroupWrapper)"
13
+ :href="`${routePath}/${slugify(subGroupName(subGroupWrapper))}`"
14
+ :route-path="routePath"
15
+ :plugin-group="subGroupWrapper.group ?? subGroupWrapper.name"
16
+ :total-count="getTotalElementCount(subGroupWrapper)"
17
+ :blueprints-count="props.subgroupBlueprintCounts?.[`${slugify(subGroupWrapper.group ?? subGroupWrapper.name)}-${slugify(subGroupName(subGroupWrapper))}`] ?? 0"
18
+ :is-active="activeId === slugify(subGroupName(subGroupWrapper))"
19
+ class="text-capitalize h-100"
20
+ @click="$emit('goTo', {subGroup: subGroupWrapper})"
21
+ />
22
+ </div>
23
+ </div>
18
24
  </div>
19
25
  </template>
20
26
  <template v-else>
21
- <div class="d-flex flex-column elements-section" v-for="(elements, elementType) in elementsByType" :key="elementType">
27
+ <div class="d-flex flex-column elements-section pb-3" v-for="(elements, elementType) in elementsByType" :key="elementType">
22
28
  <h4 :id="`section-${slugify(elementType)}`" class="text-capitalize">
23
29
  {{ elementType }}
24
30
  </h4>
25
- <div class="d-flex flex-column">
26
- <RowLink
27
- v-for="element in elements"
28
- :id="slugify(element)"
29
- :icon-b64-svg="'data:image/svg+xml;base64,' + (icons[element] ?? icons[plugin.subGroup ?? plugin.group] ?? icons[plugin.group])"
30
- :text="elementName(element)"
31
- :href="elementHref(element)"
32
- :key="element"
33
- :route-path="routePath"
34
- class="text-capitalize"
35
- @click="$emit('goTo', {element})"
31
+ <div class="row g-4 last">
32
+ <div class="col-md-4 col-lg-6 col-xl-6 col-xxl-4" v-for="element in elements" :key="element">
33
+ <ElementCard
34
+ :id="slugify(element)"
35
+ :icon-b64-svg="'data:image/svg+xml;base64,' + (icons[element] ?? icons[plugin.subGroup ?? plugin.group] ?? icons[plugin.group])"
36
+ :text="elementName(element)"
37
+ :plugin-class="element"
38
+ :href="elementHref(element)"
39
+ :route-path="routePath"
40
+ :is-active="activeId === slugify(element)"
41
+ :title="schemas?.[element]?.title"
42
+ class="h-100"
43
+ @click="$emit('goTo', {element})"
44
+ >
45
+ <template #markdown="{content}">
46
+ <slot name="markdown" :content="content" />
47
+ </template>
48
+ </ElementCard>
49
+ </div>
50
+ </div>
51
+ </div>
52
+ </template>
53
+ <template v-if="description !== undefined && plugin.longDescription">
54
+ <div class="description">
55
+ <h4 id="how-to-use-this-plugin">
56
+ How to use this plugin
57
+ </h4>
58
+ <div ref="contentWrap" class="markdown-container" :class="{expanded: isExpanded}">
59
+ <div ref="contentInner" class="markdown-inner">
60
+ <slot name="markdown" :content="description.replace(/ *:(?![ /])/g, ': ')" />
61
+ </div>
62
+ <div
63
+ v-if="isOverflow && !isExpanded"
64
+ class="gradient-overlay"
36
65
  />
37
66
  </div>
67
+ <div v-if="isOverflow || isExpanded" class="more-wrap text-center">
68
+ <button class="more-btn" @click="toggleExpand">
69
+ {{ isExpanded ? "See less" : "See more" }}
70
+ <component :is="isExpanded ? ChevronUp : ChevronDown" />
71
+ </button>
72
+ </div>
38
73
  </div>
39
74
  </template>
40
75
  </div>
41
76
  </template>
42
77
  <script setup lang="ts">
43
- import RowLink from "../misc/RowLink.vue";
44
- import type {Plugin, PluginElement} from "../../utils/plugins";
45
- import {isEntryAPluginElementPredicate, subGroupName} from "../../utils/plugins";
78
+ import {computed, ref} from "vue";
79
+ import {useElementSize} from "@vueuse/core";
46
80
  import {slugify} from "../../utils/url";
47
- import {computed} from "vue";
81
+ import type {Plugin, PluginMetadata} from "../../utils/plugins";
82
+ import {subGroupName, extractPluginElements} from "../../utils/plugins";
83
+ import {usePluginElementCounts} from "../../composables/usePluginElementCounts";
84
+
85
+ import ElementCard from "../misc/ElementCard.vue";
86
+ import SubgroupCard from "../misc/SubgroupCard.vue";
87
+ import ChevronUp from "vue-material-design-icons/ChevronUp.vue";
88
+ import ChevronDown from "vue-material-design-icons/ChevronDown.vue";
48
89
 
49
90
  const props = defineProps<{
50
91
  plugins: Plugin[],
@@ -52,8 +93,24 @@
52
93
  routePath: string
53
94
  icons: Record<string, string>
54
95
  subGroup?: string | undefined,
96
+ activeId?: string | undefined
97
+ subgroupBlueprintCounts?: Record<string, number>,
98
+ metadataMap?: Record<string, PluginMetadata>,
99
+ schemas?: Record<string, {title?: string}>
55
100
  }>();
56
101
 
102
+ const getSubgroupMetadata = (subGroupWrapper: Plugin) => {
103
+ return props.metadataMap?.[subGroupWrapper.subGroup ?? subGroupWrapper.group];
104
+ };
105
+
106
+ const getSubgroupDescription = (subGroupWrapper: Plugin) => {
107
+ return getSubgroupMetadata(subGroupWrapper)?.description ?? subGroupWrapper.description;
108
+ };
109
+
110
+ const getSubgroupTitle = (subGroupWrapper: Plugin) => {
111
+ return getSubgroupMetadata(subGroupWrapper)?.title ?? subGroupWrapper.title ?? subGroupName(subGroupWrapper);
112
+ };
113
+
57
114
  const plugin = computed(() => props.plugins.find(p => props.subGroup === undefined ? true : (slugify(subGroupName(p)) === props.subGroup)) as Plugin);
58
115
 
59
116
  const description = computed(() => {
@@ -70,20 +127,92 @@
70
127
  return split?.[split.length - 1];
71
128
  }
72
129
 
73
- const subGroupHref = (targetSubGroup: string) => `${props.routePath}/${slugify(targetSubGroup)}`;
74
-
75
130
  const elementHref = (element: string) => `${props.routePath}/${element}`;
76
131
 
77
- function extractPluginElements(plugin: Plugin): Record<string, string[]> {
78
- return Object.fromEntries(
79
- Object.entries(plugin).filter(([key, value]) => isEntryAPluginElementPredicate(key, value))
80
- .map(([key, value]) => [key.replace(/[A-Z]/g, match => ` ${match}`), (value as PluginElement[]).filter(({deprecated}) => !deprecated).map(({cls}) => cls)])
81
- );
132
+ function getTotalElementCount(plugin: Plugin): number {
133
+ const elements = extractPluginElements(plugin);
134
+ return Object.values(elements).reduce((sum, arr) => sum + arr.length, 0);
82
135
  }
83
136
 
84
- const elementsByType = computed<Record<string, string[]>>(() => extractPluginElements(plugin.value));
137
+ const {elementsByType} = usePluginElementCounts(plugin);
138
+
139
+ const contentWrap = ref<HTMLElement | null>(null);
140
+ const contentInner = ref<HTMLElement | null>(null);
141
+ const isExpanded = ref(false);
142
+
143
+ const {height: wrapHeight} = useElementSize(contentWrap);
144
+ const {height: innerHeight} = useElementSize(contentInner);
145
+
146
+ const isOverflow = computed(() => innerHeight.value > wrapHeight.value + 2);
147
+
148
+ const toggleExpand = () => {
149
+ isExpanded.value = !isExpanded.value;
150
+ }
85
151
 
86
152
  defineEmits<{
87
153
  (e: "goTo", target: {subGroup?: Plugin & Pick<Plugin, "subGroup">, element?: string}): void
88
154
  }>()
89
155
  </script>
156
+
157
+ <style lang="scss" scoped>
158
+ @use "../../scss/variables" as variables;
159
+
160
+ h4 {
161
+ font-size: 20px;
162
+ font-weight: 600;
163
+ margin: 0 0 1.5rem;
164
+ color: var(--ks-content-primary);
165
+ }
166
+
167
+ .description {
168
+ border-top: 1px solid variables.$black-3;
169
+ padding: 2rem 3rem;
170
+ margin: 0 -3rem;
171
+ }
172
+
173
+ .row > * {
174
+ padding-inline: 8px;
175
+ margin-top: 1rem;
176
+ }
177
+
178
+ .markdown-container {
179
+ position: relative;
180
+ max-height: 384px;
181
+ overflow: hidden;
182
+ transition: max-height 250ms ease-in-out;
183
+
184
+ &.expanded {
185
+ max-height: none;
186
+ }
187
+ }
188
+
189
+ .markdown-inner {
190
+ color: var(--ks-content-primary);
191
+ }
192
+
193
+ .gradient-overlay {
194
+ pointer-events: none;
195
+ position: absolute;
196
+ inset: auto 0 0;
197
+ height: 140px;
198
+ background: linear-gradient(transparent, rgba(10, 11, 13, 0.85));
199
+ }
200
+
201
+ .more-btn {
202
+ background: rgba(10, 11, 13, 0.85);
203
+ color: var(--ks-content-primary);
204
+ border: none;
205
+ padding: 0.5rem 1rem;
206
+ border-radius: 999px;
207
+ display: inline-flex;
208
+ align-items: center;
209
+ gap: 0.5rem;
210
+ cursor: pointer;
211
+ font-weight: 400;
212
+ font-family: 'Source Code Pro', monospace;
213
+
214
+ :deep(svg) {
215
+ font-size: 1.25rem;
216
+ }
217
+ }
218
+ </style>
@@ -149,10 +149,12 @@
149
149
  </template>
150
150
 
151
151
  <script setup lang="ts">
152
- import {className, extractEnumValues, extractTypeInfo, type JSONProperty} from "../../utils/schemaUtils.ts";
153
152
  import {ref} from "vue";
154
- import EyeOutline from "vue-material-design-icons/EyeOutline.vue";
153
+ import {sanitizeForMarkdown} from "../../utils/Utils";
154
+ import {className, extractEnumValues, extractTypeInfo, type JSONProperty} from "../../utils/schemaUtils.ts";
155
+
155
156
  import Alert from "../content/Alert.vue";
157
+ import EyeOutline from "vue-material-design-icons/EyeOutline.vue";
156
158
 
157
159
  const props = defineProps<{
158
160
  property: JSONProperty
@@ -162,9 +164,7 @@
162
164
 
163
165
  const enumValues = ref(extractEnumValues(props.property));
164
166
 
165
- const codeSanitizer = (str: string): string => {
166
- return str.replace(/(```)(?:bash|yaml|js|console|json)(\n) *([\s\S]*?```)/g, "$1$2$3").replace(/(?<!:):(?![: /])/g, ": ");
167
- }
167
+ const codeSanitizer = sanitizeForMarkdown;
168
168
  </script>
169
169
 
170
170
  <style lang="scss" scoped>
@@ -160,9 +160,13 @@
160
160
  return;
161
161
  }
162
162
 
163
- const definitionKey = hash.includes("#") ? hash.split("#").pop()?.split(".").pop() : hash;
163
+ const cleanHash = hash.replace(/-body$/, "");
164
+
165
+ const definitionKey = Object.keys(props.schema.definitions).find(defKey =>
166
+ cleanHash === defKey || cleanHash.startsWith(defKey + "_")
167
+ );
164
168
 
165
- if (definitionKey && definitionKey in props.schema.definitions) {
169
+ if (definitionKey) {
166
170
  definitionsExpanded.value = true;
167
171
  forceExpandKey.value += 1;
168
172
  expandedDefinitions.value.clear();
@@ -174,7 +178,7 @@
174
178
  const maxAttempts = 30;
175
179
 
176
180
  const attemptScroll = () => {
177
- const element = document.getElementById(definitionKey);
181
+ const element = document.getElementById(cleanHash);
178
182
  if (element) {
179
183
  element.scrollIntoView({behavior: "smooth", block: "start"});
180
184
  } else if (attempts < maxAttempts) {