@edgedev/create-edge-app 1.1.23 → 1.1.26

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 (116) hide show
  1. package/.env +1 -0
  2. package/.env.dev +1 -0
  3. package/README.md +55 -20
  4. package/{agent.md → agents.md} +2 -0
  5. package/bin/cli.js +6 -6
  6. package/edge/components/auth/login.vue +384 -0
  7. package/edge/components/auth/register.vue +396 -0
  8. package/edge/components/auth.vue +108 -0
  9. package/edge/components/autoFileUpload.vue +215 -0
  10. package/edge/components/billing.vue +8 -0
  11. package/edge/components/buttonDivider.vue +14 -0
  12. package/edge/components/chip.vue +34 -0
  13. package/edge/components/clipboardButton.vue +42 -0
  14. package/edge/components/cms/block.vue +529 -0
  15. package/edge/components/cms/blockApi.vue +212 -0
  16. package/edge/components/cms/blockEditor.vue +725 -0
  17. package/edge/components/cms/blockInput.vue +66 -0
  18. package/edge/components/cms/blockPicker.vue +486 -0
  19. package/edge/components/cms/blockRender.vue +78 -0
  20. package/edge/components/cms/blockSheetContent.vue +28 -0
  21. package/edge/components/cms/codeEditor.vue +466 -0
  22. package/edge/components/cms/fontUpload.vue +327 -0
  23. package/edge/components/cms/htmlContent.vue +807 -0
  24. package/edge/components/cms/init_blocks/api_with_subarrays.html +17 -0
  25. package/edge/components/cms/init_blocks/array_with_collection.html +7 -0
  26. package/edge/components/cms/init_blocks/array_with_objects.html +7 -0
  27. package/edge/components/cms/init_blocks/carousel.html +103 -0
  28. package/edge/components/cms/init_blocks/contact_us.html +69 -0
  29. package/edge/components/cms/init_blocks/content_with_left_image.html +27 -0
  30. package/edge/components/cms/init_blocks/footer.html +24 -0
  31. package/edge/components/cms/init_blocks/header_divider.html +7 -0
  32. package/edge/components/cms/init_blocks/hero.html +35 -0
  33. package/edge/components/cms/init_blocks/hero_carousel.html +52 -0
  34. package/edge/components/cms/init_blocks/newsletter.html +117 -0
  35. package/edge/components/cms/init_blocks/post_content.html +7 -0
  36. package/edge/components/cms/init_blocks/post_title_header.html +21 -0
  37. package/edge/components/cms/init_blocks/posts_list.html +20 -0
  38. package/edge/components/cms/init_blocks/properties_showcase.html +100 -0
  39. package/edge/components/cms/init_blocks/property_carousel.html +59 -0
  40. package/edge/components/cms/init_blocks/property_detail.html +112 -0
  41. package/edge/components/cms/init_blocks/property_detail_header.html +34 -0
  42. package/edge/components/cms/init_blocks/property_results.html +137 -0
  43. package/edge/components/cms/init_blocks/property_search.html +75 -0
  44. package/edge/components/cms/init_blocks/simple_array.html +7 -0
  45. package/edge/components/cms/mediaCard.vue +116 -0
  46. package/edge/components/cms/mediaManager.vue +386 -0
  47. package/edge/components/cms/menu.vue +1103 -0
  48. package/edge/components/cms/optionsSelect.vue +107 -0
  49. package/edge/components/cms/page.vue +1785 -0
  50. package/edge/components/cms/posts.vue +1083 -0
  51. package/edge/components/cms/site.vue +1298 -0
  52. package/edge/components/cms/themeDefaultMenu.vue +548 -0
  53. package/edge/components/cms/themeEditor.vue +426 -0
  54. package/edge/components/dashboard.vue +776 -0
  55. package/edge/components/editor.vue +671 -0
  56. package/edge/components/fileTree.vue +72 -0
  57. package/edge/components/files.vue +89 -0
  58. package/edge/components/formSubtypes/myOrgs.vue +214 -0
  59. package/edge/components/formSubtypes/users.vue +336 -0
  60. package/edge/components/functionChips.vue +57 -0
  61. package/edge/components/gError.vue +98 -0
  62. package/edge/components/gHelper.vue +67 -0
  63. package/edge/components/gInput.vue +1331 -0
  64. package/edge/components/loggingIn.vue +41 -0
  65. package/edge/components/menu.vue +137 -0
  66. package/edge/components/menuContent.vue +132 -0
  67. package/edge/components/myAccount.vue +317 -0
  68. package/edge/components/myOrganizations.vue +75 -0
  69. package/edge/components/myProfile.vue +122 -0
  70. package/edge/components/orgSwitcher.vue +25 -0
  71. package/edge/components/organizationMembers.vue +522 -0
  72. package/edge/components/organizationSettings.vue +271 -0
  73. package/edge/components/shad/breadcrumbs.vue +35 -0
  74. package/edge/components/shad/button.vue +43 -0
  75. package/edge/components/shad/checkbox.vue +73 -0
  76. package/edge/components/shad/combobox.vue +238 -0
  77. package/edge/components/shad/datepicker.vue +184 -0
  78. package/edge/components/shad/dialog.vue +32 -0
  79. package/edge/components/shad/dropdownMenu.vue +54 -0
  80. package/edge/components/shad/dropdownMenuItem.vue +21 -0
  81. package/edge/components/shad/form.vue +59 -0
  82. package/edge/components/shad/html.vue +877 -0
  83. package/edge/components/shad/input.vue +139 -0
  84. package/edge/components/shad/number.vue +109 -0
  85. package/edge/components/shad/select.vue +151 -0
  86. package/edge/components/shad/selectTags.vue +278 -0
  87. package/edge/components/shad/switch.vue +67 -0
  88. package/edge/components/shad/tags.vue +137 -0
  89. package/edge/components/shad/textarea.vue +102 -0
  90. package/edge/components/shad/typeMoney.vue +167 -0
  91. package/edge/components/sideBar.vue +288 -0
  92. package/edge/components/sideBarContent.vue +268 -0
  93. package/edge/components/sidebarProvider.vue +33 -0
  94. package/edge/components/tooltip.vue +16 -0
  95. package/edge/components/userMenu.vue +148 -0
  96. package/edge/components/v/alert.vue +59 -0
  97. package/edge/components/v/alertTitle.vue +18 -0
  98. package/edge/components/v/card.vue +53 -0
  99. package/edge/components/v/cardActions.vue +18 -0
  100. package/edge/components/v/cardText.vue +18 -0
  101. package/edge/components/v/cardTitle.vue +20 -0
  102. package/edge/components/v/col.vue +56 -0
  103. package/edge/components/v/list.vue +46 -0
  104. package/edge/components/v/listItem.vue +26 -0
  105. package/edge/components/v/listItemTitle.vue +18 -0
  106. package/edge/components/v/row.vue +42 -0
  107. package/edge/components/v/toolbar.vue +24 -0
  108. package/edge/composables/global.ts +519 -0
  109. package/edge-pull.sh +2 -0
  110. package/edge-push.sh +1 -0
  111. package/edge-status.sh +14 -0
  112. package/firebase.json +5 -2
  113. package/firebase_init.sh +21 -6
  114. package/package.json +1 -1
  115. package/plugins/firebase.client.ts +1 -0
  116. package/edge-components-install.sh +0 -1
@@ -0,0 +1,67 @@
1
+ <script setup>
2
+ import { useVModel } from '@vueuse/core'
3
+ import { cn } from '@/lib/utils'
4
+ const props = defineProps({
5
+ name: {
6
+ type: String,
7
+ required: true,
8
+ },
9
+ modelValue: {
10
+ type: Boolean,
11
+ default: false,
12
+ },
13
+ class: {
14
+ type: null,
15
+ required: false,
16
+ },
17
+ switchClass: {
18
+ type: null,
19
+ required: false,
20
+ },
21
+ placeholder: {
22
+ type: String,
23
+ required: false,
24
+ },
25
+ label: {
26
+ type: String,
27
+ required: false,
28
+ },
29
+ description: {
30
+ type: String,
31
+ required: false,
32
+ },
33
+ })
34
+
35
+ const emits = defineEmits(['update:modelValue'])
36
+
37
+ const modelValue = useVModel(props, 'modelValue', emits)
38
+ </script>
39
+
40
+ <template>
41
+ <div>
42
+ <FormField :name="props.name">
43
+ <FormItem :class="cn('flex flex-row items-center justify-between', props.class)">
44
+ <div class="flex flex-row items-center w-full">
45
+ <div class="grow">
46
+ <FormLabel class="text-base">
47
+ {{ props.label }}
48
+ </FormLabel>
49
+ <FormDescription>
50
+ <slot />
51
+ </FormDescription>
52
+ </div>
53
+ <FormControl>
54
+ <Switch
55
+ v-model="modelValue"
56
+ :class="cn('', props.switchClass)"
57
+ />
58
+ </FormControl>
59
+ </div>
60
+ </FormItem>
61
+ </FormField>
62
+ </div>
63
+ </template>
64
+
65
+ <style lang="scss" scoped>
66
+
67
+ </style>
@@ -0,0 +1,137 @@
1
+ <script setup>
2
+ import { useVModel } from '@vueuse/core'
3
+ import { useField } from 'vee-validate'
4
+
5
+ const props = defineProps({
6
+ name: { type: String, required: true },
7
+ // Accept either String (CSV) or Array depending on valueAs
8
+ modelValue: { type: [String, Array], default: '' },
9
+ class: { type: null, default: '' },
10
+ placeholder: { type: String, default: '' },
11
+ label: { type: String, default: '' },
12
+ description: { type: String, default: '' },
13
+ disabled: { type: Boolean, default: false },
14
+ // NEW: controls how the component reads/emits the value
15
+ valueAs: { type: String, required: false, validator: v => ['string', 'array'].includes(v) },
16
+ })
17
+
18
+ const emit = defineEmits(['update:modelValue', 'blur'])
19
+
20
+ // Determine operational mode: explicit prop wins only when set; otherwise infer from initial modelValue
21
+ const mode = computed(() =>
22
+ (props.valueAs ?? (Array.isArray(props.modelValue) ? 'array' : 'string')),
23
+ )
24
+
25
+ // raw v-model that mirrors props.modelValue directly
26
+ const rawModel = useVModel(props, 'modelValue', emit, {
27
+ passive: false,
28
+ prop: 'modelValue',
29
+ })
30
+
31
+ const normalize = arr =>
32
+ Array.from(new Set((arr || []).map(s => String(s).trim()).filter(Boolean)))
33
+
34
+ const parseCsv = str => normalize(String(str || '').split(','))
35
+
36
+ const { setValue, setTouched } = useField(props.name)
37
+
38
+ // Public array model used by the Tags UI regardless of underlying type
39
+ const arrayModel = computed({
40
+ get: () => {
41
+ if (mode.value === 'array') {
42
+ return normalize(Array.isArray(rawModel.value) ? rawModel.value : [])
43
+ }
44
+ // 'string' mode -> parse CSV
45
+ return parseCsv(rawModel.value)
46
+ },
47
+ set: (arr) => {
48
+ const cleaned = normalize(arr)
49
+ if (mode.value === 'array') {
50
+ rawModel.value = cleaned
51
+ setValue(cleaned, false)
52
+ emit('update:modelValue', cleaned)
53
+ }
54
+ else {
55
+ const csv = cleaned.join(',')
56
+ rawModel.value = csv
57
+ setValue(csv, false)
58
+ emit('update:modelValue', csv)
59
+ }
60
+ setTouched(true)
61
+ },
62
+ })
63
+
64
+ // Keep vee-validate synced with external changes (resets, programmatic updates)
65
+ watch(
66
+ () => rawModel.value,
67
+ (v) => {
68
+ if (mode.value === 'array') {
69
+ setValue(Array.isArray(v) ? v : [], false)
70
+ }
71
+ else {
72
+ setValue(String(v ?? ''), false)
73
+ }
74
+ },
75
+ { immediate: true },
76
+ )
77
+
78
+ function commitPendingFromInput(el) {
79
+ if (!el)
80
+ return
81
+ const raw = (el.value || '').trim()
82
+ if (!raw)
83
+ return
84
+ arrayModel.value = [...arrayModel.value, raw]
85
+ el.value = ''
86
+ el.dispatchEvent(new Event('input', { bubbles: true }))
87
+ }
88
+
89
+ function onInputBlur(e) {
90
+ commitPendingFromInput(e?.target)
91
+ setTouched(true)
92
+ emit('blur', e)
93
+ }
94
+ </script>
95
+
96
+ <template>
97
+ <FormField :name="props.name">
98
+ <FormItem class="flex flex-col gap-2 p-0 mt-0 space-y-0 [&>*]:!mt-0">
99
+ <div class="flex items-center justify-between">
100
+ <FormLabel v-if="props.label">
101
+ {{ props.label }}
102
+ </FormLabel>
103
+ <slot name="icon" />
104
+ </div>
105
+ <FormControl>
106
+ <TagsInput
107
+ :id="props.name"
108
+ v-model="arrayModel"
109
+ class="mt-0"
110
+ :class="props.class"
111
+ :disabled="props.disabled"
112
+ >
113
+ <TagsInputItem
114
+ v-for="item in arrayModel"
115
+ :key="item"
116
+ :value="item"
117
+ class="bg-secondary"
118
+ >
119
+ <TagsInputItemText />
120
+ <TagsInputItemDelete />
121
+ </TagsInputItem>
122
+
123
+ <!-- Let Enter be handled by the component; commit on blur -->
124
+ <TagsInputInput
125
+ :placeholder="props.placeholder || 'Add…'"
126
+ @blur="onInputBlur"
127
+ />
128
+ </TagsInput>
129
+ </FormControl>
130
+
131
+ <FormDescription v-if="props.description">
132
+ {{ props.description }}
133
+ </FormDescription>
134
+ <FormMessage />
135
+ </FormItem>
136
+ </FormField>
137
+ </template>
@@ -0,0 +1,102 @@
1
+ <script setup>
2
+ import { useVModel } from '@vueuse/core'
3
+ const props = defineProps({
4
+ name: {
5
+ type: String,
6
+ required: true,
7
+ },
8
+ defaultValue: {
9
+ type: [String, Number],
10
+ required: false,
11
+ },
12
+ modelValue: {
13
+ type: [String, Number],
14
+ required: false,
15
+ },
16
+ class: {
17
+ type: null,
18
+ required: false,
19
+ },
20
+ placeholder: {
21
+ type: String,
22
+ required: false,
23
+ },
24
+ label: {
25
+ type: String,
26
+ required: false,
27
+ },
28
+ description: {
29
+ type: String,
30
+ required: false,
31
+ },
32
+ maskOptions: {
33
+ type: [Object],
34
+ required: false,
35
+ default: null,
36
+ },
37
+ disabled: {
38
+ type: Boolean,
39
+ required: false,
40
+ default: false,
41
+ },
42
+ })
43
+
44
+ const emits = defineEmits(['update:modelValue'])
45
+
46
+ const state = reactive({
47
+ showPassword: false,
48
+ type: '',
49
+ })
50
+
51
+ onBeforeMount(() => {
52
+ state.type = props.type
53
+ })
54
+
55
+ const modelValue = useVModel(props, 'modelValue', emits, {
56
+ passive: true,
57
+ defaultValue: props.defaultValue,
58
+ })
59
+
60
+ const classComputed = computed(() => {
61
+ return props.class
62
+ })
63
+ </script>
64
+
65
+ <template>
66
+ <div>
67
+ <FormField v-slot="{ componentField }" :name="props.name">
68
+ <FormItem>
69
+ <FormLabel>
70
+ {{ props.label }}
71
+ <div class="ml-auto inline-block">
72
+ <slot />
73
+ </div>
74
+ </FormLabel>
75
+ <FormControl>
76
+ <div class="relative w-full items-center">
77
+ <Textarea
78
+ v-model="modelValue"
79
+ :class="classComputed"
80
+ :placeholder="props.placeholder"
81
+ :disabled="props.disabled"
82
+ :default-value="modelValue"
83
+ v-bind="componentField"
84
+ />
85
+ <span class="absolute end-0 inset-y-0 flex items-center justify-center px-2">
86
+ <slot name="icon" />
87
+ </span>
88
+ </div>
89
+ </FormControl>
90
+ <FormDescription>
91
+ {{ props.description }}
92
+ <slot name="description" />
93
+ </FormDescription>
94
+ <FormMessage />
95
+ </FormItem>
96
+ </FormField>
97
+ </div>
98
+ </template>
99
+
100
+ <style lang="scss" scoped>
101
+
102
+ </style>
@@ -0,0 +1,167 @@
1
+ <script setup>
2
+ import { useVModel } from '@vueuse/core'
3
+
4
+ const props = defineProps({
5
+ name: { type: String, required: true },
6
+ type: { type: String, default: 'text' },
7
+ defaultValue: { type: [String, Number], required: false },
8
+ class: { type: null, required: false },
9
+ placeholder: { type: String, required: false },
10
+ label: { type: String, required: false },
11
+ description: { type: String, required: false },
12
+ maskOptions: { type: [Object], default: null },
13
+ disabled: { type: Boolean, default: false },
14
+ modelValue: { type: [String, Number], default: '' },
15
+ })
16
+
17
+ const emits = defineEmits(['update:modelValue'])
18
+
19
+ const state = reactive({
20
+ showPassword: false,
21
+ type: '',
22
+ editMode: false,
23
+ isDebit: false, // false = credit, true = debit
24
+ })
25
+
26
+ onBeforeMount(() => {
27
+ state.type = props.type
28
+ })
29
+
30
+ // Initialize useVModel
31
+ const modelValue = useVModel(props, 'modelValue', emits, {
32
+ prop: 'modelValue',
33
+ })
34
+
35
+ watch(modelValue, (val) => {
36
+ const stringValue = String(val || '')
37
+ const newVal = parseFloat(stringValue.replace(/[$,]/g, ''))
38
+ if (isNaN(newVal)) {
39
+ modelValue.value = 0
40
+ return
41
+ }
42
+ emits('update:modelValue', state.isDebit ? -Math.abs(newVal) : Math.abs(newVal))
43
+ })
44
+
45
+ const toggleDebit = () => {
46
+ state.isDebit = !state.isDebit
47
+ if (modelValue.value !== '') {
48
+ modelValue.value = state.isDebit
49
+ ? -Math.abs(modelValue.value)
50
+ : Math.abs(modelValue.value)
51
+ }
52
+ }
53
+
54
+ const classComputed = computed(() => {
55
+ return props.type === 'password' ? `${props.class} pr-10` : props.class
56
+ })
57
+
58
+ const handleKeydown = (event) => {
59
+ const allowedKeys = [
60
+ 'Backspace',
61
+ 'ArrowLeft',
62
+ 'ArrowRight',
63
+ 'Delete',
64
+ 'Tab',
65
+ ]
66
+ const key = event.key
67
+ const value = event.target.value
68
+ const selectionStart = event.target.selectionStart
69
+
70
+ if (
71
+ allowedKeys.includes(key)
72
+ || (key >= '0' && key <= '9')
73
+ || (key === '.' && !value.includes('.'))
74
+ ) {
75
+ if (value.includes('.') && key >= '0' && key <= '9') {
76
+ const decimalPart = value.split('.')[1]
77
+ if (
78
+ decimalPart.length >= 2
79
+ && selectionStart > value.indexOf('.')
80
+ ) {
81
+ event.preventDefault()
82
+ return
83
+ }
84
+ }
85
+ return
86
+ }
87
+
88
+ // Disallow minus and any other invalid input
89
+ event.preventDefault()
90
+ }
91
+
92
+ const moneyMask = {
93
+ preProcess: val => val.replace(/[$,]/g, ''),
94
+ postProcess: (val) => {
95
+ if (!val)
96
+ return ''
97
+ const sub = 3 - (val.includes('.') ? val.length - val.indexOf('.') : 0)
98
+ return Intl.NumberFormat('en-US', {
99
+ style: 'currency',
100
+ currency: 'USD',
101
+ }).format(val).slice(0, sub ? -sub : undefined)
102
+ },
103
+ }
104
+
105
+ const formatDecimal = (event) => {
106
+ const el = event.target
107
+ const cleaned = el.value.replace(/[$,]/g, '')
108
+ const num = parseFloat(cleaned)
109
+
110
+ if (!isNaN(num)) {
111
+ const fixed = num.toFixed(2)
112
+ modelValue.value = state.isDebit
113
+ ? -Math.abs(parseFloat(fixed))
114
+ : Math.abs(parseFloat(fixed))
115
+
116
+ // Force input's displayed value to update
117
+ el.value = fixed
118
+ el.dispatchEvent(new Event('input'))
119
+ }
120
+ }
121
+ </script>
122
+
123
+ <template>
124
+ <div>
125
+ <FormField v-slot="{ componentField }" :name="props.name">
126
+ <FormItem>
127
+ <FormLabel class="flex">
128
+ {{ props.label }}
129
+ <div class="ml-auto inline-block">
130
+ <slot />
131
+ </div>
132
+ </FormLabel>
133
+
134
+ <div class="flex items-center mb-2">
135
+ <button
136
+ type="button"
137
+ class="border px-2 py-2 rounded text-sm w-[100px] bg-primary text-primary-foreground"
138
+ @click="toggleDebit"
139
+ >
140
+ {{ state.isDebit ? 'Debit (−)' : 'Credit (+)' }}
141
+ </button>
142
+ <FormControl>
143
+ <Input
144
+ :id="props.name"
145
+ v-model="modelValue"
146
+ v-maska:[moneyMask]
147
+ :default-value="props.modelValue"
148
+ :class="classComputed"
149
+ :type="state.type"
150
+ v-bind="componentField"
151
+ :placeholder="props.placeholder"
152
+ :disabled="props.disabled"
153
+ @keydown="handleKeydown"
154
+ @blur="formatDecimal"
155
+ />
156
+ </FormControl>
157
+ </div>
158
+
159
+ <FormDescription>
160
+ {{ props.description }}
161
+ <slot name="description" />
162
+ </FormDescription>
163
+ <FormMessage />
164
+ </FormItem>
165
+ </FormField>
166
+ </div>
167
+ </template>