@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,386 @@
1
+ <script setup>
2
+ import { ImagePlus, Loader2, Square, SquareCheckBig } from 'lucide-vue-next'
3
+ import { toTypedSchema } from '@vee-validate/zod'
4
+ import * as z from 'zod'
5
+ const props = defineProps({
6
+ site: {
7
+ type: String,
8
+ required: false,
9
+ default: 'all',
10
+ },
11
+ selectMode: {
12
+ type: Boolean,
13
+ required: false,
14
+ default: false,
15
+ },
16
+ defaultTags: {
17
+ type: Array,
18
+ required: false,
19
+ default: () => [],
20
+ },
21
+ })
22
+
23
+ // const edgeGlobal = inject('edgeGlobal')
24
+
25
+ const emits = defineEmits(['select'])
26
+
27
+ const edgeFirebase = inject('edgeFirebase')
28
+ const route = useRoute()
29
+ const router = useRouter()
30
+
31
+ const state = reactive({
32
+ filter: '',
33
+ file: [],
34
+ view: 'list',
35
+ selected: [],
36
+ selectAll: false,
37
+ publishing: false,
38
+ unpublishing: false,
39
+ deleting: false,
40
+ tags: [],
41
+ workingDoc: null,
42
+ editMedia: false,
43
+ filterTags: [],
44
+ newDocs: {
45
+ media: {
46
+ name: { value: '' },
47
+ meta: { tags: [] },
48
+ },
49
+ },
50
+ clearingTags: false,
51
+ showUpload: false,
52
+ })
53
+
54
+ const files = computed(() => {
55
+ return edgeFirebase.data[`${edgeGlobal.edgeState.organizationDocPath}/files`]
56
+ })
57
+
58
+ const filteredFiles = computed(() => {
59
+ const list = Object.values(files.value || {})
60
+ return list
61
+ .filter(m =>
62
+ !state.filter || m.name?.toLowerCase().includes(state.filter.toLowerCase()),
63
+ )
64
+ .sort((a, b) => (b.uploadTime || 0) - (a.uploadTime || 0))
65
+ })
66
+
67
+ const selectAll = computed(() => {
68
+ return state.selectAll
69
+ })
70
+
71
+ watch(selectAll, (newValue) => {
72
+ if (newValue) {
73
+ state.selected = filteredFiles.value.map(item => item.docId)
74
+ }
75
+ else {
76
+ state.selected = []
77
+ }
78
+ })
79
+
80
+ const handleCheckboxChange = (checked, docId) => {
81
+ console.log('Checkbox changed:', checked, docId)
82
+ if (checked && !state.selected.includes(docId)) {
83
+ state.selected.push(docId)
84
+ }
85
+ else if (!checked) {
86
+ state.selected = state.selected.filter(id => id !== docId)
87
+ }
88
+ }
89
+
90
+ const deleteSelected = async () => {
91
+ console.log('Deleting selected files:', state.selected)
92
+ state.deleting = true
93
+ for (const docId of state.selected) {
94
+ await edgeFirebase.removeDoc(`${edgeGlobal.edgeState.organizationDocPath}/files`, docId)
95
+ }
96
+ state.selected = []
97
+ state.selectAll = false
98
+ state.deleting = false
99
+ }
100
+ const getTagsFromMedia = computed(() => {
101
+ const tagsSet = new Set()
102
+ Object.values(files.value || {}).forEach((file) => {
103
+ console.log('File meta tags:', file.meta?.tags)
104
+ if (file.meta?.tags && Array.isArray(file.meta.tags)) {
105
+ file.meta.tags.forEach(tag => tagsSet.add(tag))
106
+ }
107
+ })
108
+ console.log('Unique tags from media:', Array.from(tagsSet))
109
+ return Array.from(tagsSet).map(tag => ({ name: tag, title: tag }))
110
+ })
111
+ const schemas = {
112
+ media: toTypedSchema(z.object({
113
+ name: z.string({
114
+ required_error: 'Name is required',
115
+ }).min(1, { message: 'Name is required' }),
116
+ })),
117
+ }
118
+ const onSubmit = () => {
119
+ state.workingDoc = null
120
+ state.editMedia = false
121
+ }
122
+ const filters = computed(() => {
123
+ const filters = [{ filterFields: ['name'], value: state.filter }]
124
+ if (state.filterTags) {
125
+ filters.push({ filterFields: ['meta.tags'], value: state.filterTags })
126
+ }
127
+ return filters
128
+ })
129
+ const clearTags = async () => {
130
+ state.clearingTags = true
131
+ console.log('Clearing tags')
132
+ state.filterTags = []
133
+ await nextTick()
134
+ state.clearingTags = false
135
+ }
136
+ onBeforeMount(() => {
137
+ console.log('Default tags prop:', props.defaultTags)
138
+ if (props.defaultTags && Array.isArray(props.defaultTags) && props.defaultTags.length > 0) {
139
+ state.filterTags = [...props.defaultTags]
140
+ }
141
+ })
142
+
143
+ const canDeleteMedia = (item) => {
144
+ if (!props.site)
145
+ return true
146
+ if (item?.meta?.cmssite && Array.isArray(item.meta.cmssite)) {
147
+ return item.meta.cmssite.includes(props.site)
148
+ }
149
+ return false
150
+ }
151
+
152
+ const itemClick = (item) => {
153
+ if (props.selectMode) {
154
+ emits('select', edgeGlobal.getImage(item, 'public') || '')
155
+ }
156
+ else {
157
+ state.editMedia = true
158
+ state.workingDoc = item
159
+ }
160
+ }
161
+ </script>
162
+
163
+ <template>
164
+ <div
165
+ v-if="edgeGlobal.edgeState.organizationDocPath"
166
+ class="w-full mx-auto bg-background text-foreground rounded-[9.96px] px-0 border border-border/70 shadow-sm"
167
+ >
168
+ <Sheet v-model:open="state.showUpload">
169
+ <SheetContent side="top" class="w-full max-w-none sm:max-w-none max-w-2xl bg-card text-foreground border border-border">
170
+ <SheetHeader>
171
+ <SheetTitle />
172
+ <SheetDescription />
173
+ </SheetHeader>
174
+ <edge-shad-form class="px-2 sm:px-4">
175
+ <edge-shad-select-tags
176
+ v-model="state.tags"
177
+ :items="getTagsFromMedia"
178
+ name="tags"
179
+ placeholder="Select tags"
180
+ :allow-additions="true"
181
+ class="w-full max-w-[800px] mx-auto mb-4 text-foreground"
182
+ />
183
+ </edge-shad-form>
184
+ <div class="relative">
185
+ <edge-auto-file-upload
186
+ v-model="state.file"
187
+ name="file"
188
+ :multiple="true"
189
+ :accept="['image/jpg', 'image/jpeg', 'image/png', 'image/gif']"
190
+ file-path="images"
191
+ :r2="true"
192
+ :disabled="state.tags.length === 0"
193
+ disabled-text="Tags are required"
194
+ class="w-full mx-auto border-dashed border-primary/60 bg-gradient-to-br from-primary/90 via-primary to-primary/90 dark:from-muted dark:via-muted/90 dark:to-muted border text-primary-foreground dark:text-foreground py-10 rounded-[20px] my-3 shadow-lg shadow-primary/20 dark:shadow-black/30"
195
+ :extra-meta="{ tags: state.tags, cmsmedia: true, cmssite: [props.site] }"
196
+ >
197
+ <template #title>
198
+ <div class="flex items-center gap-2 justify-center gap-5 text-primary-foreground dark:text-foreground drop-shadow">
199
+ <div>
200
+ <ImagePlus class="h-10 w-10" />
201
+ </div>
202
+ <div>
203
+ <h1 class="text-4xl font-[700] leading-none">
204
+ Drag & Drop
205
+ </h1>
206
+ </div>
207
+ <div class="text-xl pt-2 font-sans font-semibold">
208
+ OR
209
+ </div>
210
+ </div>
211
+ </template>
212
+ <template #description>
213
+ <edge-shad-button class="bg-secondary mt-3 text-primary shadow-sm">
214
+ Upload
215
+ </edge-shad-button>
216
+ <div class="hidden" />
217
+ </template>
218
+ </edge-auto-file-upload>
219
+ <div
220
+ v-if="state.tags.length === 0"
221
+ class="pointer-events-auto absolute inset-0 z-20 rounded-[20px] border border-dashed border-border/70 bg-background/85 dark:bg-background/80 backdrop-blur-sm flex flex-col items-center justify-center text-center px-6 text-foreground"
222
+ >
223
+ <div class="text-lg font-semibold">Tags are required</div>
224
+ <div class="text-sm text-muted-foreground">Add tags above to enable upload</div>
225
+ </div>
226
+ </div>
227
+ </SheetContent>
228
+ </Sheet>
229
+ <edge-dashboard
230
+ :filter="state.filter"
231
+ sort-field="uploadTime"
232
+ query-field="meta.cmssite"
233
+ :filters="filters"
234
+ :query-value="['all', props.site]"
235
+ query-operator="array-contains-any"
236
+ header-class=""
237
+ sort-direction="desc" class="w-full flex-1 border-none shadow-none bg-background"
238
+ collection="files"
239
+ >
240
+ <template #header>
241
+ <edge-menu class="bg-transparent text-foreground border-none shadow-none px-2 rounded-none gap-1">
242
+ <template #start>
243
+ <div />
244
+ </template>
245
+ <template #center>
246
+ <div class="w-full px-0">
247
+ <edge-shad-form>
248
+ <div class="flex justify-between items-center gap-2 w-full">
249
+ <div>
250
+ <edge-shad-button @click="state.showUpload = true">
251
+ <ImagePlus class="h-5 w-5 mr-2" />
252
+ Upload Media
253
+ </edge-shad-button>
254
+ </div>
255
+ <div class="w-1/2">
256
+ <edge-shad-select
257
+ v-if="!state.clearingTags"
258
+ v-model="state.filterTags"
259
+ :multiple="true"
260
+ name="tags"
261
+ class="text-foreground w-full"
262
+ :items="getTagsFromMedia"
263
+ placeholder="Filter Tags"
264
+ >
265
+ <template v-if="state.filterTags.length > 0" #icon>
266
+ <X class="h-5 w-5 text-muted-foreground cursor-pointer" @click="clearTags" />
267
+ </template>
268
+ </edge-shad-select>
269
+ </div>
270
+ <div class="w-1/2">
271
+ <edge-shad-input
272
+ v-model="state.filter"
273
+ label=""
274
+ name="filter"
275
+ class="text-foreground w-full"
276
+ placeholder="Search"
277
+ />
278
+ </div>
279
+ </div>
280
+ </edge-shad-form>
281
+ </div>
282
+ </template>
283
+ <template #end>
284
+ <div />
285
+ </template>
286
+ </edge-menu>
287
+ <div v-if="!selectMode" class="flex justify-end gap-2 mt-2 px-3">
288
+ <edge-shad-button
289
+ class="w-[140px] h-[30px]"
290
+ @click="state.selectAll = !state.selectAll"
291
+ >
292
+ <Square v-if="!state.selectAll" class="h-5 w-5" />
293
+ <SquareCheckBig v-else class="h-5 w-5" />
294
+ {{ state.selectAll ? 'Deselect All' : 'Select All' }}
295
+ </edge-shad-button>
296
+ <edge-shad-button
297
+ variant="destructive"
298
+ :disabled="state.deleting || state.selected.length === 0"
299
+ class="h-[30px]"
300
+ @click="deleteSelected"
301
+ >
302
+ <Loader2 v-if="state.deleting" class="animate-spin h-5 w-5 mr-2" />
303
+ Delete Selected
304
+ </edge-shad-button>
305
+ </div>
306
+ </template>
307
+ <template #list="slotProps">
308
+ <div class=" mx-auto px-0 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
309
+ <div v-for="item in slotProps.filtered" :key="item.docId" class="w-full cursor-pointer" @click="itemClick(item)">
310
+ <edge-cms-media-card
311
+ :item="item"
312
+ :selected="state.selected.includes(item.docId)"
313
+ class="block w-full h-full"
314
+ :select-mode="props.selectMode"
315
+ :can-delete="canDeleteMedia(item)"
316
+ @select="(checked, docId) => handleCheckboxChange(checked, docId)"
317
+ @delete="(docId) => slotProps.deleteItem(docId)"
318
+ />
319
+ </div>
320
+ </div>
321
+ </template>
322
+ </edge-dashboard>
323
+ <Sheet v-model:open="state.editMedia">
324
+ <SheetContent class="w-full md:w-1/2 max-w-none sm:max-w-none max-w-2xl bg-card text-foreground border border-border">
325
+ <SheetHeader>
326
+ <SheetTitle>{{ state.workingDoc?.fileName }}</SheetTitle>
327
+ <SheetDescription>
328
+ <img :src="edgeGlobal.getImage(state.workingDoc, 'public')" alt="" class="h-[450px] m-auto object-fit rounded-lg mb-4">
329
+ Original Name: <span class="font-semibold">{{ state.workingDoc?.fileName }}</span>, Size: <span class="font-semibold">{{ (state.workingDoc?.fileSize / 1024).toFixed(2) }} KB</span>
330
+ </SheetDescription>
331
+ </SheetHeader>
332
+
333
+ <edge-editor
334
+ v-if="state.workingDoc"
335
+ :doc-id="state.workingDoc.docId"
336
+ collection="files"
337
+ :new-doc-schema="state.newDocs.media"
338
+ :schema="schemas.media"
339
+ :show-footer="false"
340
+ :show-header="false"
341
+ class="w-full px-0 mx-0 bg-transparent"
342
+ :save-function-override="onSubmit"
343
+ card-content-class="mx-0 px-0"
344
+ >
345
+ <template #main="slotProps">
346
+ <div class="p-6 space-y-4 h-[calc(100vh-628px)] overflow-y-auto">
347
+ <edge-shad-input
348
+ v-model="slotProps.workingDoc.name"
349
+ name="name"
350
+ label="Display Name"
351
+ class="w-full mb-4"
352
+ placeholder="File name"
353
+ />
354
+ <edge-shad-select-tags
355
+ v-model="slotProps.workingDoc.meta.tags"
356
+ :items="getTagsFromMedia"
357
+ label="Tags"
358
+ name="tags"
359
+ placeholder="Select tags"
360
+ :allow-additions="true"
361
+ class="w-full max-w-[800px] mx-auto mb-5 text-foreground"
362
+ />
363
+ </div>
364
+ <SheetFooter class="pt-2 flex justify-between">
365
+ <edge-shad-button variant="destructive" class="text-white" @click="state.editMedia = false">
366
+ Cancel
367
+ </edge-shad-button>
368
+ <edge-shad-button :disabled="slotProps.submitting" type="submit" class="w-full">
369
+ <Loader2 v-if="slotProps.submitting" class=" h-4 w-4 animate-spin" />
370
+ Update
371
+ </edge-shad-button>
372
+ </SheetFooter>
373
+ </template>
374
+ </edge-editor>
375
+ </SheetContent>
376
+ </Sheet>
377
+ </div>
378
+ </template>
379
+
380
+ <style>
381
+ .data-\[state\=on\]\:bg-accent[data-state="on"] {
382
+ background-color: #D9D9D9;
383
+ box-shadow: 0px 4px 4px 0px #202C3E52 inset;
384
+
385
+ }
386
+ </style>