@bagelink/vue 1.12.23 → 1.12.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 (31) hide show
  1. package/dist/components/calendar/Index.vue.d.ts.map +1 -1
  2. package/dist/components/dataTable/DataTable.vue.d.ts.map +1 -1
  3. package/dist/components/form/inputs/DatePicker.vue.d.ts.map +1 -1
  4. package/dist/components/form/inputs/SelectInput.vue.d.ts.map +1 -1
  5. package/dist/components/index.d.ts.map +1 -1
  6. package/dist/components/layout/AppLayout.vue.d.ts.map +1 -1
  7. package/dist/components/layout/AppSidebar.vue.d.ts.map +1 -1
  8. package/dist/components/lightbox/Lightbox.vue.d.ts.map +1 -1
  9. package/dist/form-flow/FormFlow.vue.d.ts.map +1 -1
  10. package/dist/i18n/index.d.ts.map +1 -1
  11. package/dist/index.cjs +76 -76
  12. package/dist/index.mjs +7722 -7367
  13. package/dist/style.css +1 -1
  14. package/package.json +2 -2
  15. package/src/components/ListItem.vue +2 -2
  16. package/src/components/calendar/Index.vue +15 -14
  17. package/src/components/dataTable/DataTable.vue +10 -0
  18. package/src/components/form/inputs/DatePicker.vue +17 -0
  19. package/src/components/form/inputs/SelectInput.vue +1 -1
  20. package/src/components/form/inputs/TelInput.vue +1 -1
  21. package/src/components/index.ts +1 -0
  22. package/src/components/layout/AppLayout.vue +4 -2
  23. package/src/components/layout/AppSidebar.vue +21 -8
  24. package/src/components/lightbox/Lightbox.vue +27 -35
  25. package/src/form-flow/FormFlow.vue +1 -2
  26. package/src/i18n/locales/en.json +169 -0
  27. package/src/i18n/locales/he.json +169 -0
  28. package/src/styles/buttons.css +0 -4
  29. package/src/styles/layout.css +48 -2
  30. package/src/styles/mobilLayout.css +41 -0
  31. package/src/utils/elementUtils.ts +1 -1
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bagelink/vue",
3
3
  "type": "module",
4
- "version": "1.12.23",
4
+ "version": "1.12.27",
5
5
  "description": "Bagel core sdk packages",
6
6
  "author": {
7
7
  "name": "Bagel Studio",
@@ -90,7 +90,7 @@
90
90
  "signature_pad": "^5.0.9",
91
91
  "vue-i18n": "^11.2.8",
92
92
  "vue-toastification": "^2.0.0-rc.5",
93
- "@bagelink/utils": "1.12.23"
93
+ "@bagelink/utils": "1.12.27"
94
94
  },
95
95
  "scripts": {
96
96
  "dev": "tsx watch src/index.ts",
@@ -73,11 +73,11 @@ const bind = computed(() => {
73
73
  <Icon v-if="icon" size="1.2" class="color-primary" :icon="icon" />
74
74
 
75
75
  <div class="txt-start">
76
- <p v-if="lead" class="txt10 m-0 p-0 txt-gray" :class="{ ellipsis }">
76
+ <p v-if="lead" class="txt10 m-0 p-0 txt-gray " :class="{ ellipsis }">
77
77
  {{ lead }}
78
78
  <slot name="lead" />
79
79
  </p>
80
- <p class="m-0 p-0 line-height-14 pb-025" :class="{ 'ellipsis-1': ellipsis }">
80
+ <p class="m-0 p-0 line-height-14 pb-025 item-title" :class="{ 'ellipsis-1': ellipsis }">
81
81
  {{ title }}
82
82
  <slot />
83
83
  </p>
@@ -51,6 +51,13 @@ const views: Record<CalendarView, Component> = {
51
51
  Agenda: AgendaView
52
52
  }
53
53
 
54
+ const viewToDeltaKey: Record<CalendarView, string> = {
55
+ Week: 'weeks',
56
+ Month: 'months',
57
+ Day: 'days',
58
+ Agenda: 'months'
59
+ }
60
+
54
61
  const visibleDateRange = computed(() => {
55
62
  const start = new Date(currentDate.value)
56
63
  let end = new Date(currentDate.value)
@@ -81,7 +88,6 @@ const state = computed<CalendarViewState>(() => ({
81
88
  }))
82
89
 
83
90
  function handleDateChange(date: Date) {
84
- console.log('handleDateChange', date)
85
91
  currentDate.value = new Date(date)
86
92
  emit('dateChange', state.value)
87
93
  }
@@ -130,11 +136,6 @@ defineExpose({
130
136
  })
131
137
 
132
138
  onMounted(() => {
133
- console.log('[Calendar] props:', {
134
- availabilityMode: props.availabilityMode,
135
- availabilityEditable: props.availabilityEditable,
136
- availabilitySlots: props.availabilitySlots?.length
137
- })
138
139
  emit('ready', state.value)
139
140
  })
140
141
  </script>
@@ -151,14 +152,14 @@ onMounted(() => {
151
152
  <ListItem v-for="(_, key) in views" :key="key" thin :title="key" @click="handleViewChange(key)" />
152
153
  </Dropdown>
153
154
  <Btn icon="calendar" thin color="gray" value="Today" @click="handleDateChange(new Date())" />
154
- <Btn
155
- icon="chevron_left" color="gray" thin
156
- @click="handleDateChange(timeDelta(currentDate, { [currentView]: -1 }))"
157
- />
158
- <Btn
159
- icon="chevron_right" color="gray" thin
160
- @click="handleDateChange(timeDelta(currentDate, { [currentView]: 1 }))"
161
- />
155
+ <Btn
156
+ icon="chevron_left" color="gray" thin
157
+ @click="handleDateChange(timeDelta(currentDate, { [viewToDeltaKey[currentView]]: -1 }))"
158
+ />
159
+ <Btn
160
+ icon="chevron_right" color="gray" thin
161
+ @click="handleDateChange(timeDelta(currentDate, { [viewToDeltaKey[currentView]]: 1 }))"
162
+ />
162
163
  </div>
163
164
  </div>
164
165
  <component
@@ -412,4 +412,14 @@ tbody tr {
412
412
  tbody tr:hover {
413
413
  background: var(--bgl-gray-light);
414
414
  }
415
+
416
+ @media (max-width: 910px) {
417
+ .col {
418
+ max-width: 60vw !important;
419
+ }
420
+ .max-col-width {
421
+ max-width: 60vw !important;
422
+ }
423
+ }
424
+
415
425
  </style>
@@ -16,6 +16,7 @@ const props = withDefaults(
16
16
  enableTime?: boolean
17
17
  highlightedDates?: MaybeRefOrGetter<(string | Date)[]>
18
18
  disabledDates?: MaybeRefOrGetter<(string | Date)[]>
19
+ allowedDates?: MaybeRefOrGetter<(string | Date)[]>
19
20
  autoSize?: boolean
20
21
  }>(),
21
22
  {
@@ -30,6 +31,7 @@ const emit = defineEmits(['update:modelValue'])
30
31
 
31
32
  const computedHighlightedDates = computed(() => toValue(props.highlightedDates))
32
33
  const computedDisabledDates = computed(() => toValue(props.disabledDates))
34
+ const computedAllowedDates = computed(() => toValue(props.allowedDates))
33
35
 
34
36
  // State
35
37
  const currentMonth = ref(new Date())
@@ -70,6 +72,21 @@ function useDateValidation() {
70
72
  if (isInDisabledDates) { return true }
71
73
  }
72
74
 
75
+ // If allowedDates is set, only those dates are enabled
76
+ if (Array.isArray(computedAllowedDates.value) && computedAllowedDates.value.length > 0) {
77
+ const dateKey = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`
78
+ const isAllowed = computedAllowedDates.value.some((allowedDate) => {
79
+ if (typeof allowedDate === 'string') {
80
+ // Direct string comparison (YYYY-MM-DD)
81
+ return allowedDate === dateKey
82
+ }
83
+ return allowedDate.getFullYear() === date.getFullYear()
84
+ && allowedDate.getMonth() === date.getMonth()
85
+ && allowedDate.getDate() === date.getDate()
86
+ })
87
+ if (!isAllowed) { return true }
88
+ }
89
+
73
90
  return false
74
91
  }
75
92
 
@@ -239,7 +239,7 @@ watch(
239
239
  })
240
240
  }
241
241
  },
242
- { deep: true },
242
+ { deep: true, immediate: true },
243
243
  )
244
244
 
245
245
  onMounted(() => {
@@ -253,7 +253,7 @@ onMounted(initializeCountry)
253
253
  aria-label="Search by country name or country code" placeholder="Search" icon="search"
254
254
  />
255
255
 
256
- <ul class="overflow-y p-0 max-h-300px" role="listbox">
256
+ <ul class="overflow-y p-0 max-h-300px m-0" role="listbox">
257
257
  <li
258
258
  v-for="(pb) in countries" :key="pb.iso2" role="option"
259
259
  class="flex gap-075 pointer hover" tabindex="-1"
@@ -23,6 +23,7 @@ export { default as Filter } from './Filter.vue'
23
23
  export { default as Flag } from './Flag.vue'
24
24
  export * from './form'
25
25
  export { default as Icon } from './Icon/Icon.vue'
26
+ export { FONT_AWESOME_ICONS, FONT_AWESOME_BRANDS_ICONS, MATERIAL_ICONS } from './Icon/constants'
26
27
  export { default as IframeVue } from './IframeVue.vue'
27
28
  export { default as Image } from './Image.vue'
28
29
  export { default as ImportData } from './ImportData.vue'
@@ -4,15 +4,17 @@ import { ref, provide, onMounted, onUnmounted, computed } from 'vue'
4
4
  interface Props {
5
5
  sidebarWidth?: string
6
6
  sidebarCardStyle?: boolean
7
+ defaultOpen?: boolean
7
8
  }
8
9
 
9
10
  const props = withDefaults(defineProps<Props>(), {
10
11
  sidebarWidth: '260px',
11
- sidebarCardStyle: false
12
+ sidebarCardStyle: false,
13
+ defaultOpen: true,
12
14
  })
13
15
 
14
16
  // Menu state
15
- const isOpen = ref(true)
17
+ const isOpen = ref(props.defaultOpen)
16
18
  const isMobile = ref(false)
17
19
 
18
20
  // Check if mobile
@@ -7,7 +7,7 @@ import { resolveI18n } from '../../i18n'
7
7
 
8
8
  // Extended interface for links with active route tracking
9
9
  interface LinkWithAction extends NavLink {
10
- activeRoutes?: string[] // נתיבים שצריכים להיות מסומנים כאקטיביים עבור הלינק הזה
10
+ activeRoutes?: string[] // Routes that should be marked as active for this link
11
11
  }
12
12
 
13
13
  interface Props {
@@ -23,10 +23,14 @@ interface Props {
23
23
  name?: string
24
24
  frame?: boolean
25
25
  activeRoutes?: string[]
26
+ centerlinks?: boolean
27
+ defaultOpen?: boolean
26
28
  }
27
29
 
28
30
  const props = withDefaults(defineProps<Props>(), {
29
31
  card: true,
32
+ centerlinks: false,
33
+ defaultOpen: true,
30
34
  bgColor: 'var(--bgl-white)',
31
35
  textColor: 'var(--bgl-black)',
32
36
  activeColor: 'var(--bgl-black)',
@@ -40,9 +44,12 @@ const route = useRoute()
40
44
  const isTransitioning = ref(false)
41
45
 
42
46
  // Inject menu state from parent
47
+ const _fallbackIsOpen = ref(props.defaultOpen)
48
+ const _fallbackIsMobile = ref(false)
49
+
43
50
  const menuState = inject('menuState', {
44
- isOpen: { value: true },
45
- isMobile: { value: false },
51
+ isOpen: _fallbackIsOpen,
52
+ isMobile: _fallbackIsMobile,
46
53
  closeOnMobile: () => void 0,
47
54
  sidebarWidth: '260px',
48
55
  sidebarCollapsedWidth: '66px',
@@ -160,7 +167,7 @@ const sidebarStyles = computed(() => {
160
167
  >
161
168
  <!-- Logo/Brand -->
162
169
  <router-link
163
- to="/" class="decoration-none flex px-05" :class="{
170
+ to="/" class="decoration-none flex siderbarLogoWrap" :class="{
164
171
  'gap-05': menuState.isOpen.value,
165
172
  'gap-0': !menuState.isOpen.value,
166
173
  }"
@@ -175,7 +182,7 @@ const sidebarStyles = computed(() => {
175
182
  </router-link>
176
183
 
177
184
  <!-- Navigation Links -->
178
- <nav class="sidebar-nav flex column flex-stretch gap-025 align-items-start scrollbar-gutter-stable">
185
+ <nav class="sidebar-nav flex column flex-stretch gap-025 align-items-start scrollbar-gutter-stable" :class="{ 'justify-content-center': props.centerlinks }">
179
186
  <Btn
180
187
  v-for="link in props.navLinks" :key="link.to"
181
188
  :title="!menuState.isOpen.value && !menuState.isMobile.value ? resolveI18n(link.label) : ''" fullWidth
@@ -183,7 +190,8 @@ const sidebarStyles = computed(() => {
183
190
  :style="{
184
191
  backgroundColor: isActiveRoute(link) ? props.activeColor : props.bgColor,
185
192
  color: isActiveRoute(link) ? 'white' : props.textColor,
186
- }" :to="link.to || '/'" @click="link.action"
193
+ }"
194
+ :to="link.to || '/'" @click="link.action"
187
195
  >
188
196
  <Icon :name="link.icon" size="1.2" />
189
197
  <span class="nav-text">
@@ -196,8 +204,13 @@ const sidebarStyles = computed(() => {
196
204
  <!-- Footer Links -->
197
205
  <Btn
198
206
  v-for="link in props.footerLinks" :key="link.to || link.label"
199
- :title="!menuState.isOpen.value && !menuState.isMobile.value ? resolveI18n(link.label) : ''" alignTxt="start"
200
- fullWidth flat :icon="link.icon" class="flex-shrink-0 px-1" :to="link.to" @click="link.action"
207
+ :title="!menuState.isOpen.value && !menuState.isMobile.value ? resolveI18n(link.label) : ''"
208
+ :style="{
209
+ color: isActiveRoute(link) ? 'white' : props.textColor,
210
+ }"
211
+ fullWidth
212
+ alignTxt="start"
213
+ flat :icon="link.icon" class="flex-shrink-0 px-1" :to="link.to" @click="link.action"
201
214
  >
202
215
  <span class="nav-text">
203
216
  {{ resolveI18n(link.label) }}
@@ -3,9 +3,6 @@ import type { LightboxItem } from './lightbox.types'
3
3
 
4
4
  import { BglVideo, Btn, Icon, Zoomer, Image, normalizeURL, Swiper, downloadFile } from '@bagelink/vue'
5
5
  import { computed, ref, watch } from 'vue'
6
- import { useI18n } from '../../i18n'
7
-
8
- const { $t } = useI18n()
9
6
 
10
7
  const isOpen = ref(false)
11
8
  const group = ref<LightboxItem[]>([])
@@ -80,44 +77,31 @@ defineExpose({ open, close })
80
77
  <Btn flat class="color-white" icon="zoom_in" :disabled="zoom === 1" @click="zoom = 1" />
81
78
  <Btn flat class="color-white" icon="add" :disabled="zoom === 3" @click="zoom++" />
82
79
  </div>
83
- <Btn
84
- v-if="currentItem?.openFile && currentItem?.src" class="color-white" round thin flat
85
- iconEnd="arrow_outward" value="$t:lightbox.openFile" :href="currentItem?.src" target="_blank"
86
- />
87
- <Btn
88
- v-if="currentItem?.download && currentItem?.src" class="color-white" round thin flat
89
- icon="download" value="Download File" @click="downloadFile(currentItem?.src)"
90
- />
80
+ <Btn v-if="currentItem?.openFile && currentItem?.src" class="color-white" round thin flat
81
+ iconEnd="arrow_outward" value="$t:lightbox.openFile" :href="currentItem?.src" target="_blank" />
82
+ <Btn v-if="currentItem?.download && currentItem?.src" class="color-white" round thin flat
83
+ icon="download" value="Download File" @click="downloadFile(currentItem?.src)" />
91
84
  <div v-if="!currentItem?.openFile && !currentItem?.download" />
92
85
  </div>
93
86
 
94
- <Swiper
95
- v-if="group && group.length > 0" v-model:index="currentIndex" :items="group"
87
+ <Swiper v-if="group && group.length > 0" v-model:index="currentIndex" :items="group"
96
88
  :initial-slide="currentIndex" class="bgl-lightbox-swiper" :class="{ zoomed: zoom > 1 }"
97
89
  :navigation="group.length > 1" :grab-cursor="canSwipe" :keyboard="true" :loop="false" :speed="400"
98
90
  :slides-per-view="1" :space-between="0" effect="slide" :advanced-options="swiperAdvancedOptions"
99
- @click.stop
100
- >
91
+ @click.stop>
101
92
  <template #default="{ item }">
102
93
  <div class="bgl-lightbox-item">
103
- <Zoomer
104
- v-if="item.type === 'image'" v-model:zoom="zoom" :disabled="!item?.enableZoom"
94
+ <Zoomer v-if="item.type === 'image'" v-model:zoom="zoom" :disabled="!item?.enableZoom"
105
95
  :mouse-wheel-to-zoom="false" :double-click-to-zoom="true" :max-scale="5" :min-scale="1"
106
- :aspect-ratio="0" :limit-translation="true" @click.stop
107
- >
96
+ :aspect-ratio="0" :limit-translation="true" @click.stop>
108
97
  <Image :draggable="false" :src="item?.src" alt="Preview" class="lightbox-image" />
109
98
  </Zoomer>
110
99
 
111
- <BglVideo
112
- v-else-if="item?.type === 'video' && item?.src" :src="item?.src" autoplay controls
113
- class="lightbox-video"
114
- />
100
+ <BglVideo v-else-if="item?.type === 'video' && item?.src" :src="item?.src" autoplay controls
101
+ class="lightbox-video" />
115
102
 
116
103
  <div v-else-if="item?.type === 'pdf' && item?.src" class="lightbox-pdf">
117
- <embed
118
- :src="normalizeURL(item?.src)" type="application/pdf" width="100%" height="1080"
119
- :title="item?.name"
120
- >
104
+ <embed :src="normalizeURL(item?.src)" type="application/pdf" :title="item?.name">
121
105
  </div>
122
106
 
123
107
  <div v-else class="lightbox-file">
@@ -152,14 +136,10 @@ defineExpose({ open, close })
152
136
 
153
137
  <div v-if="group && group.length > 1" class="lightbox-thumbnails" @click.stop>
154
138
  <template v-for="(item, index) in group" :key="index">
155
- <Image
156
- v-if="item.type === 'image'" class="thumbnail" :src="item.src" alt=""
157
- :class="{ active: currentIndex === index }" @click.stop="selectItem(index)"
158
- />
159
- <Icon
160
- v-else class="thumbnail thumbnail-icon" icon="description"
161
- :class="{ active: currentIndex === index }" @click.stop="selectItem(index)"
162
- />
139
+ <Image v-if="item.type === 'image'" class="thumbnail" :src="item.src" alt=""
140
+ :class="{ active: currentIndex === index }" @click.stop="selectItem(index)" />
141
+ <Icon v-else class="thumbnail thumbnail-icon" icon="description"
142
+ :class="{ active: currentIndex === index }" @click.stop="selectItem(index)" />
163
143
  </template>
164
144
  </div>
165
145
  </div>
@@ -299,6 +279,18 @@ defineExpose({ open, close })
299
279
  margin: auto;
300
280
  }
301
281
 
282
+ .lightbox-pdf {
283
+ width: 90vw;
284
+ height: calc(100vh - 140px);
285
+ }
286
+
287
+ .lightbox-pdf embed {
288
+ width: 100%;
289
+ height: 100%;
290
+ border: none;
291
+ border-radius: 3px;
292
+ }
293
+
302
294
  .lightbox-video iframe {
303
295
  width: 90vw;
304
296
  }
@@ -239,7 +239,7 @@ function getFieldProps(field: FieldBuilder, key: string) {
239
239
  }
240
240
 
241
241
  if (field._type === 'multiselect') {
242
- baseProps.multiple = true
242
+ baseProps.multiselect = true
243
243
  }
244
244
 
245
245
  if (field._type === 'json') {
@@ -254,7 +254,6 @@ function getFieldProps(field: FieldBuilder, key: string) {
254
254
  baseProps.allowAdd = baseProps.allowAdd ?? true
255
255
  baseProps.allowDelete = baseProps.allowDelete ?? true
256
256
  }
257
-
258
257
  return baseProps
259
258
  }
260
259
 
@@ -243,6 +243,7 @@
243
243
  "reorderSaving": "Saving order..."
244
244
  },
245
245
  "datastores": {
246
+ "selectCollection": "Select a collection from the list",
246
247
  "fieldName": "Name",
247
248
  "fieldStore": "Store",
248
249
  "fieldStoreHint": "e.g.: default",
@@ -294,5 +295,173 @@
294
295
  "deleteInviteConfirm": "Delete the invitation?",
295
296
  "deleteInviteError": "Error deleting invitation",
296
297
  "removeUserConfirm": "Remove {email}?"
298
+ },
299
+ "forms": {
300
+ "title": "Forms",
301
+ "refresh": "Refresh",
302
+ "newForm": "New Form",
303
+ "createForm": "Create Form",
304
+ "noForms": "No forms yet",
305
+ "noFormsDesc": "Create your first form to get started",
306
+ "active": "Active",
307
+ "inactive": "Inactive",
308
+ "submissionsOnly": "Submissions only",
309
+ "noDefinition": "No form definition - view submissions",
310
+ "fieldCount": "{n} fields",
311
+ "createdAt": "Created {date}",
312
+ "editor": {
313
+ "newForm": "New Form",
314
+ "builder": "Builder",
315
+ "submissions": "Submissions",
316
+ "edit": "Edit",
317
+ "preview": "Preview",
318
+ "save": "Save",
319
+ "create": "Create",
320
+ "formName": "Form Name *",
321
+ "formNamePlaceholder": "Enter form name",
322
+ "description": "Description",
323
+ "descriptionPlaceholder": "Optional description",
324
+ "active": "Active",
325
+ "deleteForm": "Delete Form",
326
+ "deleteConfirm": "Are you sure you want to delete this form?",
327
+ "submit": "Submit"
328
+ },
329
+ "submissions": {
330
+ "title": "Submissions",
331
+ "exportCsv": "Export CSV",
332
+ "statusPlaceholder": "Status",
333
+ "noSubmissions": "No submissions found",
334
+ "count": "No submissions | 1 submission | {n} submissions",
335
+ "date": "Date",
336
+ "status": "Status",
337
+ "statusAll": "All",
338
+ "statusSaved": "Saved",
339
+ "statusDraft": "Draft",
340
+ "statusProcessed": "Processed",
341
+ "statusAbandoned": "Abandoned",
342
+ "statusError": "Error",
343
+ "statusSpam": "Spam"
344
+ },
345
+ "builder": {
346
+ "noFields": "No fields yet",
347
+ "noFieldsDesc": "Click + to add your first field",
348
+ "noFieldsDefined": "No fields defined",
349
+ "selectField": "Select a field to edit its settings",
350
+ "tooSmall": "Window too small",
351
+ "tooSmallDesc": "Expand the window to at least 1000px to edit the form"
352
+ },
353
+ "fieldSettings": {
354
+ "headingText": "Heading Text",
355
+ "noDividerSettings": "No settings for divider",
356
+ "label": "Label",
357
+ "fieldKey": "Field Key",
358
+ "placeholder": "Placeholder",
359
+ "helpText": "Help Text",
360
+ "required": "Required",
361
+ "options": "Options",
362
+ "addOption": "Add Option",
363
+ "validation": "Validation",
364
+ "minLength": "Min Length",
365
+ "maxLength": "Max Length",
366
+ "pattern": "Pattern (RegEx)",
367
+ "min": "Min",
368
+ "max": "Max",
369
+ "step": "Step",
370
+ "removeField": "Remove Field",
371
+ "columnWidth": "Column Width",
372
+ "columnHeight": "Column Height",
373
+ "optionLabel": "Label",
374
+ "optionValue": "Value",
375
+ "sectionHeader": "Section Header",
376
+ "fieldPrefix": "Field",
377
+ "removeFieldTitle": "Remove field",
378
+ "removeTitle": "Remove",
379
+ "richTextVariant": "Toolbar",
380
+ "richTextVariantFull": "Full",
381
+ "richTextVariantBasic": "Basic",
382
+ "richTextVariantSimple": "Simple",
383
+ "textareaRows": "Rows",
384
+ "textareaAutoHeight": "Auto Height",
385
+ "numberLayout": "Spinner Layout",
386
+ "numberLayoutDefault": "Default",
387
+ "numberLayoutVertical": "Vertical",
388
+ "numberLayoutHorizontal": "Horizontal",
389
+ "numberSpinner": "Show Spinner",
390
+ "phoneOnlyCountries": "Allowed Countries",
391
+ "phoneOnlyCountriesPlaceholder": "e.g. IL, US, GB",
392
+ "phoneOnlyCountriesHelp": "Comma-separated ISO 3166-1 alpha-2 country codes. Leave empty to show all countries.",
393
+ "selectMultiselect": "Multiple Selection",
394
+ "dateEnableTime": "Enable Time",
395
+ "dateMin": "Min Date",
396
+ "dateMax": "Max Date",
397
+ "rangeMulti": "Range (Two Handles)",
398
+ "radioThin": "Compact Style",
399
+ "radioHideRadio": "Hide Radio Circle",
400
+ "radioAlign": "Item Alignment",
401
+ "radioAlignStart": "Start",
402
+ "radioAlignCenter": "Center",
403
+ "radioAlignEnd": "End",
404
+ "textIcon": "End Icon",
405
+ "textIconStart": "Start Icon",
406
+ "fileMultiple": "Allow Multiple Files",
407
+ "fileHeight": "Height",
408
+ "fileAccept": "Accepted File Types",
409
+ "fileAcceptPlaceholder": "e.g. image/*,.pdf",
410
+ "fileTheme": "Theme",
411
+ "fileThemeDropzone": "Dropzone",
412
+ "fileThemeBasic": "Basic",
413
+ "fileShowIcon": "Show Icon",
414
+ "fileIcon": "Icon Name"
415
+ },
416
+ "iconPicker": {
417
+ "none": "None",
418
+ "search": "Search icons...",
419
+ "noResults": "No icons found"
420
+ },
421
+ "schemaBuilder": {
422
+ "fieldId": "Field ID",
423
+ "fieldIdDesc": "Technical name for API/database",
424
+ "fieldLabel": "Field Label",
425
+ "fieldLabelPlaceholder": "Enter field label",
426
+ "description": "Description (optional)",
427
+ "descriptionPlaceholder": "Help text for this field",
428
+ "requiredField": "Required field",
429
+ "required": "Required",
430
+ "textValidations": "Text Validations",
431
+ "format": "Format",
432
+ "minimumLength": "Minimum Length",
433
+ "maximumLength": "Maximum Length",
434
+ "noMinimum": "No minimum",
435
+ "noMaximum": "No maximum",
436
+ "numberValidations": "Number Validations",
437
+ "minimumValue": "Minimum Value",
438
+ "maximumValue": "Maximum Value",
439
+ "stepMultipleOf": "Step / Multiple Of",
440
+ "anyValue": "Any value",
441
+ "addField": "Add Field",
442
+ "noFieldsClickAbove": "Click a button above to add your first field",
443
+ "patternPlaceholder": "e.g., ^[A-Z]+$",
444
+ "fieldTypes": {
445
+ "shortText": "Short Text",
446
+ "longText": "Long Text",
447
+ "number": "Number",
448
+ "integer": "Integer",
449
+ "yesNo": "Yes/No",
450
+ "dropdown": "Dropdown",
451
+ "email": "Email",
452
+ "phone": "Phone",
453
+ "date": "Date",
454
+ "unknown": "Unknown"
455
+ },
456
+ "formats": {
457
+ "plainText": "Plain Text",
458
+ "email": "Email",
459
+ "url": "URL",
460
+ "date": "Date",
461
+ "dateTime": "Date & Time",
462
+ "time": "Time",
463
+ "phone": "Phone"
464
+ }
465
+ }
297
466
  }
298
467
  }