@edgedev/create-edge-app 1.1.25 → 1.1.27

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 (111) hide show
  1. package/README.md +55 -20
  2. package/{agent.md → agents.md} +2 -0
  3. package/bin/cli.js +6 -6
  4. package/edge/components/auth/login.vue +384 -0
  5. package/edge/components/auth/register.vue +396 -0
  6. package/edge/components/auth.vue +108 -0
  7. package/edge/components/autoFileUpload.vue +215 -0
  8. package/edge/components/billing.vue +8 -0
  9. package/edge/components/buttonDivider.vue +14 -0
  10. package/edge/components/chip.vue +34 -0
  11. package/edge/components/clipboardButton.vue +42 -0
  12. package/edge/components/cms/block.vue +529 -0
  13. package/edge/components/cms/blockApi.vue +212 -0
  14. package/edge/components/cms/blockEditor.vue +725 -0
  15. package/edge/components/cms/blockInput.vue +66 -0
  16. package/edge/components/cms/blockPicker.vue +486 -0
  17. package/edge/components/cms/blockRender.vue +78 -0
  18. package/edge/components/cms/blockSheetContent.vue +28 -0
  19. package/edge/components/cms/codeEditor.vue +466 -0
  20. package/edge/components/cms/fontUpload.vue +327 -0
  21. package/edge/components/cms/htmlContent.vue +807 -0
  22. package/edge/components/cms/init_blocks/api_with_subarrays.html +17 -0
  23. package/edge/components/cms/init_blocks/array_with_collection.html +7 -0
  24. package/edge/components/cms/init_blocks/array_with_objects.html +7 -0
  25. package/edge/components/cms/init_blocks/carousel.html +103 -0
  26. package/edge/components/cms/init_blocks/contact_us.html +69 -0
  27. package/edge/components/cms/init_blocks/content_with_left_image.html +27 -0
  28. package/edge/components/cms/init_blocks/footer.html +24 -0
  29. package/edge/components/cms/init_blocks/header_divider.html +7 -0
  30. package/edge/components/cms/init_blocks/hero.html +35 -0
  31. package/edge/components/cms/init_blocks/hero_carousel.html +52 -0
  32. package/edge/components/cms/init_blocks/newsletter.html +117 -0
  33. package/edge/components/cms/init_blocks/post_content.html +7 -0
  34. package/edge/components/cms/init_blocks/post_title_header.html +21 -0
  35. package/edge/components/cms/init_blocks/posts_list.html +20 -0
  36. package/edge/components/cms/init_blocks/properties_showcase.html +100 -0
  37. package/edge/components/cms/init_blocks/property_carousel.html +59 -0
  38. package/edge/components/cms/init_blocks/property_detail.html +112 -0
  39. package/edge/components/cms/init_blocks/property_detail_header.html +34 -0
  40. package/edge/components/cms/init_blocks/property_results.html +137 -0
  41. package/edge/components/cms/init_blocks/property_search.html +75 -0
  42. package/edge/components/cms/init_blocks/simple_array.html +7 -0
  43. package/edge/components/cms/mediaCard.vue +116 -0
  44. package/edge/components/cms/mediaManager.vue +386 -0
  45. package/edge/components/cms/menu.vue +1103 -0
  46. package/edge/components/cms/optionsSelect.vue +107 -0
  47. package/edge/components/cms/page.vue +1785 -0
  48. package/edge/components/cms/posts.vue +1083 -0
  49. package/edge/components/cms/site.vue +1475 -0
  50. package/edge/components/cms/themeDefaultMenu.vue +548 -0
  51. package/edge/components/cms/themeEditor.vue +429 -0
  52. package/edge/components/dashboard.vue +776 -0
  53. package/edge/components/editor.vue +671 -0
  54. package/edge/components/fileTree.vue +72 -0
  55. package/edge/components/files.vue +89 -0
  56. package/edge/components/formSubtypes/myOrgs.vue +214 -0
  57. package/edge/components/formSubtypes/users.vue +336 -0
  58. package/edge/components/functionChips.vue +57 -0
  59. package/edge/components/gError.vue +98 -0
  60. package/edge/components/gHelper.vue +67 -0
  61. package/edge/components/gInput.vue +1331 -0
  62. package/edge/components/loggingIn.vue +41 -0
  63. package/edge/components/menu.vue +137 -0
  64. package/edge/components/menuContent.vue +132 -0
  65. package/edge/components/myAccount.vue +317 -0
  66. package/edge/components/myOrganizations.vue +75 -0
  67. package/edge/components/myProfile.vue +122 -0
  68. package/edge/components/orgSwitcher.vue +25 -0
  69. package/edge/components/organizationMembers.vue +522 -0
  70. package/edge/components/organizationSettings.vue +271 -0
  71. package/edge/components/shad/breadcrumbs.vue +35 -0
  72. package/edge/components/shad/button.vue +43 -0
  73. package/edge/components/shad/checkbox.vue +73 -0
  74. package/edge/components/shad/combobox.vue +238 -0
  75. package/edge/components/shad/datepicker.vue +184 -0
  76. package/edge/components/shad/dialog.vue +32 -0
  77. package/edge/components/shad/dropdownMenu.vue +54 -0
  78. package/edge/components/shad/dropdownMenuItem.vue +21 -0
  79. package/edge/components/shad/form.vue +59 -0
  80. package/edge/components/shad/html.vue +877 -0
  81. package/edge/components/shad/input.vue +139 -0
  82. package/edge/components/shad/number.vue +109 -0
  83. package/edge/components/shad/select.vue +151 -0
  84. package/edge/components/shad/selectTags.vue +278 -0
  85. package/edge/components/shad/switch.vue +67 -0
  86. package/edge/components/shad/tags.vue +137 -0
  87. package/edge/components/shad/textarea.vue +102 -0
  88. package/edge/components/shad/typeMoney.vue +167 -0
  89. package/edge/components/sideBar.vue +288 -0
  90. package/edge/components/sideBarContent.vue +268 -0
  91. package/edge/components/sidebarProvider.vue +33 -0
  92. package/edge/components/tooltip.vue +16 -0
  93. package/edge/components/userMenu.vue +148 -0
  94. package/edge/components/v/alert.vue +59 -0
  95. package/edge/components/v/alertTitle.vue +18 -0
  96. package/edge/components/v/card.vue +53 -0
  97. package/edge/components/v/cardActions.vue +18 -0
  98. package/edge/components/v/cardText.vue +18 -0
  99. package/edge/components/v/cardTitle.vue +20 -0
  100. package/edge/components/v/col.vue +56 -0
  101. package/edge/components/v/list.vue +46 -0
  102. package/edge/components/v/listItem.vue +26 -0
  103. package/edge/components/v/listItemTitle.vue +18 -0
  104. package/edge/components/v/row.vue +42 -0
  105. package/edge/components/v/toolbar.vue +24 -0
  106. package/edge/composables/global.ts +519 -0
  107. package/edge-pull.sh +2 -0
  108. package/edge-push.sh +1 -0
  109. package/edge-status.sh +14 -0
  110. package/package.json +1 -1
  111. package/edge-components-install.sh +0 -1
@@ -0,0 +1,288 @@
1
+ <script setup>
2
+ import { useAttrs } from 'vue'
3
+ import { useRoute } from 'vue-router'
4
+ import {
5
+ Sidebar,
6
+ useSidebar,
7
+ } from '@/components/ui/sidebar'
8
+ const props = defineProps({
9
+ title: {
10
+ type: String,
11
+ default: '',
12
+ },
13
+ settingsTitle: {
14
+ type: String,
15
+ default: '',
16
+ },
17
+ organizationTitle: {
18
+ type: String,
19
+ default: 'Organization(s)',
20
+ },
21
+ menuItems: {
22
+ type: Array,
23
+ default: () => [],
24
+ },
25
+ settingsMenuItems: {
26
+ type: Array,
27
+ default: () => [],
28
+ },
29
+ singleOrg: {
30
+ type: Boolean,
31
+ default: false,
32
+ },
33
+ headerClasses: {
34
+ type: String,
35
+ default: '',
36
+ },
37
+ contentClasses: {
38
+ type: String,
39
+ default: '',
40
+ },
41
+ footerClasses: {
42
+ type: String,
43
+ default: '',
44
+ },
45
+ collapsible: {
46
+ type: String,
47
+ default: 'icon',
48
+ },
49
+ showRail: {
50
+ type: Boolean,
51
+ default: true,
52
+ },
53
+ showSettingsSection: {
54
+ type: Boolean,
55
+ default: true,
56
+ },
57
+ groupLabelClasses: {
58
+ type: String,
59
+ default: '',
60
+ },
61
+ buttonClasses: {
62
+ type: String,
63
+ default: '',
64
+ },
65
+ hideLogout: {
66
+ type: Boolean,
67
+ default: false,
68
+ },
69
+ iconClasses: {
70
+ type: String,
71
+ default: '',
72
+ },
73
+ })
74
+
75
+ const edgeFirebase = inject('edgeFirebase')
76
+
77
+ const attrs = useAttrs()
78
+
79
+ const DEV_TAP_TARGET = 7
80
+ const DEV_TAP_WINDOW_MS = 2000
81
+ const DEV_OVERRIDE_KEY = 'edgeDevOverride'
82
+ const devTapTimes = ref([])
83
+ const devOverride = ref(false)
84
+
85
+ onMounted(() => {
86
+ try {
87
+ devOverride.value = localStorage.getItem(DEV_OVERRIDE_KEY) === '1'
88
+ edgeGlobal.edgeState.devOverride = devOverride.value
89
+ } catch (error) {
90
+ console.warn('dev override read failed', error)
91
+ }
92
+ })
93
+
94
+ const toggleDevOverride = () => {
95
+ devOverride.value = !devOverride.value
96
+ edgeGlobal.edgeState.devOverride = devOverride.value
97
+ try {
98
+ if (devOverride.value) {
99
+ localStorage.setItem(DEV_OVERRIDE_KEY, '1')
100
+ } else {
101
+ localStorage.removeItem(DEV_OVERRIDE_KEY)
102
+ }
103
+ } catch (error) {
104
+ console.warn('dev override write failed', error)
105
+ }
106
+ }
107
+
108
+ const handleDevTap = () => {
109
+ const now = Date.now()
110
+ devTapTimes.value = devTapTimes.value.filter(time => now - time <= DEV_TAP_WINDOW_MS)
111
+ devTapTimes.value.push(now)
112
+ if (devTapTimes.value.length >= DEV_TAP_TARGET) {
113
+ devTapTimes.value = []
114
+ toggleDevOverride()
115
+ }
116
+ }
117
+
118
+ watch(() => props.modelValue, (newValue) => {
119
+ setOpen(newValue)
120
+ })
121
+
122
+ const {
123
+ state: sidebarState,
124
+ toggleSidebar: sidebarToggle,
125
+ open: sidebarOpen,
126
+ setOpen: sidebarSetOpen,
127
+ setOpenMobile: sidebarSetOpenMobile,
128
+ isMobile: sidebarIsMobile,
129
+ } = useSidebar()
130
+
131
+ edgeGlobal.edgeState.sidebar = useSidebar()
132
+
133
+ // Sidebar props:
134
+ // variant: 'sidebar' | 'floating'
135
+ // collapsible: 'offcanvas' | 'icon' | 'none' | 'slack' | 'submenu'
136
+ // side: 'left' | 'right'
137
+
138
+ // https://ui.shadcn.com/docs/components/sidebar
139
+
140
+ const collapsible = computed(() => {
141
+ if (props.collapsible === 'slack') {
142
+ if (sidebarIsMobile.value) {
143
+ return 'offcanvas'
144
+ }
145
+ return 'none'
146
+ }
147
+ if (props.collapsible === 'submenu') {
148
+ if (sidebarIsMobile.value) {
149
+ return 'offcanvas'
150
+ }
151
+ return 'none'
152
+ }
153
+ return props.collapsible
154
+ })
155
+
156
+ const styleOverrides = computed(() => {
157
+ const styles = {}
158
+
159
+ if (props.collapsible === 'slack' && !sidebarIsMobile.value) {
160
+ styles['--sidebar-width'] = '97px'
161
+ styles['--sidebar-width-icon'] = '97px'
162
+ }
163
+
164
+ return styles
165
+ })
166
+
167
+ const route = useRoute()
168
+
169
+ const submenu = computed(() => {
170
+ // Direct match on top-level item
171
+ let match = props.menuItems.find(item => item.to === route.path)
172
+
173
+ // Exact match on a submenu item
174
+ if (!match) {
175
+ match = props.menuItems.find(item =>
176
+ item.submenu?.some(sub => sub.to === route.path),
177
+ )
178
+ }
179
+
180
+ // Match route starting with submenu.to (e.g., dynamic routes like /blocks/abc)
181
+ if (!match) {
182
+ match = props.menuItems.find(item =>
183
+ item.submenu?.some(sub => route.path.startsWith(`${sub.to}/`)),
184
+ )
185
+ }
186
+
187
+ // Fallback: match route starting with top-level item.to
188
+ if (!match) {
189
+ match = props.menuItems.find(item =>
190
+ route.path.startsWith(`${item.to}/`),
191
+ )
192
+ }
193
+
194
+ return match?.submenu || []
195
+ })
196
+
197
+ const isDev = computed(() => {
198
+ return process.dev || devOverride.value
199
+ })
200
+
201
+ const isAdmin = computed(() => {
202
+ return edgeGlobal.isAdminGlobal(edgeFirebase).value
203
+ })
204
+
205
+ const subMenuItems = (items) => {
206
+ console.log('submenu items', items)
207
+ return items
208
+ .filter(item => edgeGlobal.allowMenuItem(item, isAdmin.value))
209
+ .map(item => ({
210
+ ...item,
211
+ submenu: Array.isArray(item.submenu)
212
+ ? item.submenu.filter(subItem => edgeGlobal.allowMenuItem(subItem, isAdmin.value))
213
+ : item.submenu,
214
+ }))
215
+ }
216
+ </script>
217
+
218
+ <template>
219
+ <div class="flex h-full">
220
+ <!-- Primary Sidebar -->
221
+ <Sidebar :style="styleOverrides" side="left" v-bind="attrs" :collapsible="collapsible">
222
+ <SidebarHeader :class="props.headerClasses" @click="handleDevTap">
223
+ <div v-if="isDev" :class="edgeGlobal.edgeState.isEmulator ? 'bg-yellow-500' : 'bg-red-500'" class="text-xs text-white px-0 text-center ">
224
+ {{ edgeGlobal.edgeState.isEmulator ? 'Emulator' : '! Production !' }}
225
+ </div>
226
+ <slot name="header" :side-bar-state="sidebarState" />
227
+ </SidebarHeader>
228
+ <slot name="content">
229
+ <edge-side-bar-content
230
+ v-bind="props"
231
+ />
232
+ </slot>
233
+ <SidebarFooter :class="props.footerClasses">
234
+ <slot name="footer" :side-bar-state="sidebarState" />
235
+ </SidebarFooter>
236
+ <SidebarRail v-if="props.showRail && props.collapsible !== 'slack'">
237
+ <slot name="rail" :side-bar-state="sidebarState" />
238
+ </SidebarRail>
239
+ </Sidebar>
240
+
241
+ <!-- Submenu Sidebar -->
242
+ <Transition name="slide-submenu">
243
+ <Sidebar
244
+ v-if="subMenuItems(submenu).length > 0 && !sidebarIsMobile"
245
+ side="left"
246
+ :collapsible="collapsible"
247
+ class="border-solid border-r w-[60px]"
248
+ >
249
+ <edge-side-bar-content
250
+ :menu-items="submenu"
251
+ :submenu="true"
252
+ :collapsible="props.collapsible"
253
+ :show-settings-section="false"
254
+ :header-classes="props.headerClasses"
255
+ :content-classes="props.contentClasses"
256
+ :footer-classes="props.footerClasses"
257
+ :group-label-classes="props.groupLabelClasses"
258
+ :button-classes="`gap-0 h-[52px] ${props.buttonClasses}`"
259
+ :icon-classes="props.iconClasses"
260
+ :hide-logout="props.hideLogout"
261
+ class="mt-4"
262
+ />
263
+ </Sidebar>
264
+ </Transition>
265
+ </div>
266
+ </template>
267
+
268
+ <style scoped>
269
+ .slide-submenu-enter-active, .slide-submenu-leave-active {
270
+ transition: transform 0.3s ease, opacity 0.3s ease;
271
+ }
272
+ .slide-submenu-enter-from {
273
+ transform: translateX(-100%);
274
+ opacity: 0;
275
+ }
276
+ .slide-submenu-enter-to {
277
+ transform: translateX(0);
278
+ opacity: 1;
279
+ }
280
+ .slide-submenu-leave-from {
281
+ transform: translateX(0);
282
+ opacity: 1;
283
+ }
284
+ .slide-submenu-leave-to {
285
+ transform: translateX(-100%);
286
+ opacity: 0;
287
+ }
288
+ </style>
@@ -0,0 +1,268 @@
1
+ <script setup>
2
+ import {
3
+ useSidebar,
4
+ } from '@/components/ui/sidebar'
5
+ const props = defineProps({
6
+ title: {
7
+ type: String,
8
+ default: '',
9
+ },
10
+ submenu: {
11
+ type: Boolean,
12
+ default: false,
13
+ },
14
+ settingsTitle: {
15
+ type: String,
16
+ default: '',
17
+ },
18
+ organizationTitle: {
19
+ type: String,
20
+ default: 'Organization(s)',
21
+ },
22
+ singleOrg: {
23
+ type: Boolean,
24
+ default: false,
25
+ },
26
+ menuItems: {
27
+ type: Array,
28
+ default: () => [],
29
+ },
30
+ settingsMenuItems: {
31
+ type: Array,
32
+ default: () => [],
33
+ },
34
+ headerClasses: {
35
+ type: String,
36
+ default: '',
37
+ },
38
+ contentClasses: {
39
+ type: String,
40
+ default: '',
41
+ },
42
+ footerClasses: {
43
+ type: String,
44
+ default: '',
45
+ },
46
+ collapsible: {
47
+ type: String,
48
+ default: 'icon',
49
+ },
50
+ showRail: {
51
+ type: Boolean,
52
+ default: true,
53
+ },
54
+ showSettingsSection: {
55
+ type: Boolean,
56
+ default: true,
57
+ },
58
+ groupLabelClasses: {
59
+ type: String,
60
+ default: '',
61
+ },
62
+ buttonClasses: {
63
+ type: String,
64
+ default: '',
65
+ },
66
+ hideLogout: {
67
+ type: Boolean,
68
+ default: false,
69
+ },
70
+ iconClasses: {
71
+ type: String,
72
+ default: '',
73
+ },
74
+ })
75
+
76
+ const config = useRuntimeConfig()
77
+
78
+ const {
79
+ state: sidebarState,
80
+ isMobile: sidebarIsMobile,
81
+ } = useSidebar()
82
+
83
+ const sidebarMenuItemClasses = computed(() => {
84
+ if (props.collapsible === 'slack' && !sidebarIsMobile.value) {
85
+ return 'justify-center flex w-full'
86
+ }
87
+ return ''
88
+ })
89
+
90
+ const sideBarMenuButtonClasses = computed(() => {
91
+ if (props.collapsible === 'slack' && !sidebarIsMobile.value) {
92
+ return `w-full h-[78px] rounded-[0px] flex flex-col items-center justify-center ${props.buttonClasses}`
93
+ }
94
+ return ''
95
+ })
96
+
97
+ const sideBarButtonStyles = computed(() => {
98
+ if (props.collapsible === 'slack' && !sidebarIsMobile.value) {
99
+ return {
100
+ padding: '0 !important',
101
+ width: 'auto !important',
102
+ height: 'auto !important',
103
+ }
104
+ }
105
+ return {}
106
+ })
107
+
108
+ const sideBarIconClasses = computed(() => {
109
+ if (props.collapsible === 'slack' && !sidebarIsMobile.value) {
110
+ return `!w-5 !h-5${props.iconClasses ? ` ${props.iconClasses}` : ''}`
111
+ }
112
+ return `${props.iconClasses ? ` ${props.iconClasses}` : ''}`
113
+ })
114
+
115
+ const sidebarGroupClasses = computed(() => {
116
+ if (props.collapsible === 'slack' && !sidebarIsMobile.value) {
117
+ return 'px-0 pt-0'
118
+ }
119
+ return ''
120
+ })
121
+
122
+ const sidebarMenuClasses = computed(() => {
123
+ if (props.collapsible === 'slack' && !sidebarIsMobile.value) {
124
+ return 'gap-0'
125
+ }
126
+ return ''
127
+ })
128
+
129
+ const isSlack = computed(() => {
130
+ if (sidebarIsMobile.value) {
131
+ return false
132
+ }
133
+ return props.collapsible === 'slack'
134
+ })
135
+
136
+ const edgeFirebase = inject('edgeFirebase')
137
+
138
+ const route = useRoute()
139
+ const router = useRouter()
140
+ const goTo = (path) => {
141
+ console.log(path)
142
+ edgeGlobal.edgeState.sidebar.toggleSidebar()
143
+ router.push(path)
144
+ }
145
+
146
+ const currentRoutePath = computed(() => {
147
+ return route.fullPath.endsWith('/') ? route.fullPath.slice(0, -1) : route.fullPath
148
+ })
149
+ const isAdmin = computed(() => {
150
+ return edgeGlobal.isAdminGlobal(edgeFirebase).value
151
+ })
152
+ const menuItems = computed(() => {
153
+ return props.menuItems
154
+ .filter(item => edgeGlobal.allowMenuItem(item, isAdmin.value))
155
+ .map(item => ({
156
+ ...item,
157
+ submenu: Array.isArray(item.submenu)
158
+ ? item.submenu.filter(subItem => edgeGlobal.allowMenuItem(subItem, isAdmin.value))
159
+ : item.submenu,
160
+ }))
161
+ })
162
+
163
+ onMounted(() => {
164
+ })
165
+
166
+ const processedMenuItems = computed(() => {
167
+ if (!sidebarIsMobile.value)
168
+ return menuItems.value
169
+
170
+ return menuItems.value.flatMap((item) => {
171
+ const base = [{ ...item, isSub: false }]
172
+ if (Array.isArray(item.submenu) && item.submenu.length) {
173
+ const subItems = item.submenu.map(sub => ({
174
+ ...sub,
175
+ isSub: true,
176
+ parentTo: item.to,
177
+ }))
178
+ return [...base, ...subItems]
179
+ }
180
+ return base
181
+ })
182
+ })
183
+ </script>
184
+
185
+ <template>
186
+ <SidebarContent class="gap-0" :class="props.contentClasses">
187
+ <slot name="content" :side-bar-state="sidebarState">
188
+ <SidebarGroup class="pb-0" :class="sidebarGroupClasses">
189
+ <SidebarGroupLabel v-if="props.title" :class="props.groupLabelClasses">
190
+ {{ props.title }}
191
+ </SidebarGroupLabel>
192
+ <SidebarGroupContent>
193
+ <SidebarMenu :class="sidebarMenuClasses">
194
+ <slot name="menu">
195
+ <SidebarMenuItem v-for="item in processedMenuItems" :key="item.title" :class="sidebarMenuItemClasses">
196
+ <div
197
+ class="flex flex-col items-center w-full"
198
+ :class="item.isSub && sidebarIsMobile ? 'pl-6' : ''"
199
+ >
200
+ <SidebarMenuButton
201
+ type="button"
202
+ :is-active="currentRoutePath.startsWith(item.to) || (item.submenu && item.submenu.some(sub => currentRoutePath.startsWith(sub.to)))"
203
+ :tooltip="item.title"
204
+ :class="sideBarMenuButtonClasses"
205
+ @click.prevent="goTo(item.to)"
206
+ >
207
+ <component :is="item.icon" class="[stroke-width:1]" :class="sideBarIconClasses" />
208
+ <span v-if="!isSlack">{{ item.title }}</span>
209
+ <span v-else :class="submenu ? 'text-[10px]' : 'text-xs'">{{ item.title }}</span>
210
+ </SidebarMenuButton>
211
+ </div>
212
+ </SidebarMenuItem>
213
+ </slot>
214
+ </SidebarMenu>
215
+ </SidebarGroupContent>
216
+ </SidebarGroup>
217
+ <SidebarGroup class="pt-0" :class="sidebarGroupClasses">
218
+ <SidebarGroupLabel v-if="props.settingsTitle && props.settingsMenuItems.length > 0" :class="props.groupLabelClasses">
219
+ {{ props.settingsTitle }}
220
+ </SidebarGroupLabel>
221
+ <SidebarGroupContent>
222
+ <SidebarMenu :class="sidebarMenuClasses">
223
+ <SidebarMenuItem v-for="item in props.settingsMenuItems" :key="item.title" :class="sidebarMenuItemClasses">
224
+ <div class="flex flex-col items-center w-full">
225
+ <SidebarMenuButton
226
+ type="button"
227
+ :is-active="currentRoutePath.startsWith(item.to)"
228
+ :tooltip="item.title"
229
+ :class="sideBarMenuButtonClasses"
230
+ :style="sideBarButtonStyles"
231
+ @click.prevent="goTo(item.to)"
232
+ >
233
+ <component :is="item.icon" class="[stroke-width:1]" :class="sideBarIconClasses" />
234
+ <span v-if="!isSlack">{{ item.title }}</span>
235
+ <span v-else class="text-xs">{{ item.title }}</span>
236
+ </SidebarMenuButton>
237
+ </div>
238
+ </SidebarMenuItem>
239
+ <template v-if="props.showSettingsSection">
240
+ <SidebarMenuItem :class="sidebarMenuItemClasses">
241
+ <edge-user-menu class="w-full" :single-org="props.singleOrg" :title="props.organizationTitle">
242
+ <template #trigger>
243
+ <div class="flex flex-col items-center w-full">
244
+ <SidebarMenuButton type="button" :is-active="currentRoutePath.startsWith('/app/account')" :class="sideBarMenuButtonClasses" tooltip="Settings">
245
+ <Settings2 :class="sideBarIconClasses" class="[stroke-width:1]" />
246
+ <span v-if="!isSlack">Settings</span>
247
+ <span v-else class="text-xs">Settings</span>
248
+ </SidebarMenuButton>
249
+ </div>
250
+ </template>
251
+ </edge-user-menu>
252
+ </SidebarMenuItem>
253
+ <SidebarMenuItem v-if="!props.hideLogout" :class="sidebarMenuItemClasses">
254
+ <div class="flex flex-col items-center w-full">
255
+ <SidebarMenuButton type="button" :class="sideBarMenuButtonClasses" tooltip="Logout" @click.prevent="edgeGlobal.edgeLogOut(edgeFirebase)">
256
+ <LogOut :class="sideBarIconClasses" class="[stroke-width:1]" />
257
+ <span v-if="!isSlack">Logout</span>
258
+ <span v-else class="text-xs">Logout</span>
259
+ </SidebarMenuButton>
260
+ </div>
261
+ </SidebarMenuItem>
262
+ </template>
263
+ </SidebarMenu>
264
+ </SidebarGroupContent>
265
+ </SidebarGroup>
266
+ </slot>
267
+ </SidebarContent>
268
+ </template>
@@ -0,0 +1,33 @@
1
+ <script setup>
2
+ const props = defineProps({
3
+ collapsible: {
4
+ type: String,
5
+ default: 'icon',
6
+ },
7
+ enableNestedMenu: {
8
+ type: Boolean,
9
+ default: false,
10
+ },
11
+ })
12
+ const styleOverrides = computed(() => {
13
+ if (props.collapsible === 'slack' && props.enableNestedMenu) {
14
+ return {
15
+ '--sidebar-width': '300px',
16
+ '--sidebar-width-icon': '80px',
17
+ }
18
+ }
19
+ return null
20
+ })
21
+ </script>
22
+
23
+ <template>
24
+ <SidebarProvider :style="styleOverrides">
25
+ <slot
26
+ :collapsible="props.collapsible"
27
+ />
28
+ </SidebarProvider>
29
+ </template>
30
+
31
+ <style>
32
+
33
+ </style>
@@ -0,0 +1,16 @@
1
+ <script setup>
2
+
3
+ </script>
4
+
5
+ <template>
6
+ <TooltipProvider>
7
+ <Tooltip>
8
+ <TooltipTrigger as-child>
9
+ <slot />
10
+ </TooltipTrigger>
11
+ <TooltipContent>
12
+ <p><slot name="content" /></p>
13
+ </TooltipContent>
14
+ </Tooltip>
15
+ </TooltipProvider>
16
+ </template>