@bagelink/vue 1.14.15 → 1.15.0
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.
- package/dist/components/Alert.vue.d.ts.map +1 -1
- package/dist/components/Badge.vue.d.ts.map +1 -1
- package/dist/components/Btn.vue.d.ts.map +1 -1
- package/dist/components/Dropdown.vue.d.ts.map +1 -1
- package/dist/components/Image.vue.d.ts.map +1 -1
- package/dist/components/ListItem.vue.d.ts.map +1 -1
- package/dist/components/MapEmbed/Index.vue.d.ts.map +1 -1
- package/dist/components/Pagination.vue.d.ts.map +1 -1
- package/dist/components/Swiper.vue.d.ts.map +1 -1
- package/dist/components/Toast.vue.d.ts.map +1 -1
- package/dist/components/form/index.d.ts.map +1 -1
- package/dist/components/form/inputs/SelectInput.vue.d.ts.map +1 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/layout/AppContent.vue.d.ts.map +1 -1
- package/dist/components/layout/AppLayout.vue.d.ts.map +1 -1
- package/dist/components/layout/AppSidebar.vue.d.ts.map +1 -1
- package/dist/components/layout/Panel.vue.d.ts.map +1 -1
- package/dist/components/layout/Resizable.vue.d.ts.map +1 -1
- package/dist/components/layout/TabsNav.vue.d.ts.map +1 -1
- package/dist/components/layout/appLayoutContext.d.ts +24 -0
- package/dist/components/layout/appLayoutContext.d.ts.map +1 -0
- package/dist/components/layout/index.d.ts.map +1 -1
- package/dist/components/lightbox/Lightbox.vue.d.ts.map +1 -1
- package/dist/composables/index.d.ts.map +1 -1
- package/dist/composables/useDevice.d.ts.map +1 -1
- package/dist/composables/useEscapeKey.d.ts +12 -0
- package/dist/composables/useEscapeKey.d.ts.map +1 -0
- package/dist/composables/useSchemaField.d.ts.map +1 -1
- package/dist/composables/useTheme.d.ts.map +1 -1
- package/dist/form-flow/FormFlow.vue.d.ts.map +1 -1
- package/dist/form-flow/form-flow.d.ts.map +1 -1
- package/dist/index.cjs +203 -207
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +25819 -28870
- package/dist/style.css +1 -1
- package/dist/types/BagelForm.d.ts.map +1 -1
- package/dist/types/BtnOptions.d.ts.map +1 -1
- package/dist/utils/constants.d.ts.map +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/package.json +3 -6
- package/src/components/Alert.vue +34 -14
- package/src/components/Badge.vue +145 -22
- package/src/components/Btn.vue +43 -31
- package/src/components/Dropdown.vue +5 -12
- package/src/components/FilterQuery.vue +1 -1
- package/src/components/Image.vue +3 -2
- package/src/components/JSONSchema.vue +2 -2
- package/src/components/JsonBuilder.vue +1 -1
- package/src/components/ListItem.vue +1 -3
- package/src/components/MapEmbed/Index.vue +10 -9
- package/src/components/NavBar.vue +2 -2
- package/src/components/Spreadsheet/Index.vue +1 -1
- package/src/components/Swiper.vue +3 -1
- package/src/components/Toast.vue +23 -8
- package/src/components/calendar/Index.vue +4 -4
- package/src/components/calendar/views/MonthView.vue +3 -3
- package/src/components/form/index.ts +0 -4
- package/src/components/form/inputs/EmailInput.vue +1 -1
- package/src/components/form/inputs/NumberInput.vue +1 -1
- package/src/components/form/inputs/OTP.vue +2 -2
- package/src/components/form/inputs/SelectInput.vue +3 -3
- package/src/components/form/inputs/TelInput.vue +2 -2
- package/src/components/form/inputs/TextInput.vue +1 -1
- package/src/components/form/inputs/Upload/upload.css +2 -2
- package/src/components/index.ts +2 -6
- package/src/components/layout/AppContent.vue +5 -19
- package/src/components/layout/AppLayout.vue +47 -18
- package/src/components/layout/AppSidebar.vue +16 -33
- package/src/components/layout/Resizable.vue +5 -2
- package/src/components/layout/TabsNav.vue +5 -5
- package/src/components/layout/appLayoutContext.ts +44 -0
- package/src/components/layout/index.ts +2 -0
- package/src/components/lightbox/Lightbox.vue +3 -9
- package/src/composables/index.ts +1 -0
- package/src/composables/useDevice.ts +2 -1
- package/src/composables/useEscapeKey.ts +56 -0
- package/src/composables/useSchemaField.ts +2 -17
- package/src/composables/useTheme.ts +23 -19
- package/src/form-flow/FormFlow.vue +2 -0
- package/src/form-flow/form-flow.ts +7 -0
- package/src/index.ts +0 -2
- package/src/styles/inputs.css +1 -1
- package/src/types/BagelForm.ts +46 -151
- package/src/types/BtnOptions.ts +5 -3
- package/src/utils/constants.ts +7 -0
- package/src/utils/index.ts +19 -3
- package/src/utils/sizeParsing.ts +5 -5
- package/vite.config.ts +5 -1
- package/src/components/Carousel.vue +0 -724
- package/src/components/ImportData.vue +0 -1749
- package/src/components/Pill.vue +0 -150
- package/src/components/Slider.vue +0 -1446
- package/src/components/Title.vue +0 -23
- package/src/components/ToolBar.vue +0 -9
- package/src/components/form/BagelForm.vue +0 -219
- package/src/components/form/BglFieldSet.vue +0 -14
- package/src/components/form/BglMultiStepForm.vue +0 -469
- package/src/components/form/FieldArray.vue +0 -422
- package/src/components/form/useBagelFormState.ts +0 -76
- package/src/composables/useFormField.ts +0 -38
- package/src/dialog/DialogOLD.vue +0 -358
- package/src/utils/BagelFormUtils.ts +0 -684
|
@@ -17,7 +17,7 @@ const props = defineProps<{
|
|
|
17
17
|
iconSize?: number | string
|
|
18
18
|
iconMobileSize?: number | string
|
|
19
19
|
thin?: boolean
|
|
20
|
-
size?: 'xs' | '
|
|
20
|
+
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'
|
|
21
21
|
fullWidth?: boolean
|
|
22
22
|
fullWidthMobile?: boolean
|
|
23
23
|
alignTxt?: 'center' | 'start' | 'end'
|
|
@@ -146,10 +146,10 @@ onBeforeUnmount(() => {
|
|
|
146
146
|
{ active: isActive(tab) },
|
|
147
147
|
{
|
|
148
148
|
'bgl_tab-thin': thin,
|
|
149
|
-
'bgl_tab-xs': size === 'xs'
|
|
150
|
-
'bgl_tab-s': size === '
|
|
151
|
-
'bgl_tab-l': size === '
|
|
152
|
-
'bgl_tab-xl': size === 'xl'
|
|
149
|
+
'bgl_tab-xs': size === 'xs',
|
|
150
|
+
'bgl_tab-s': size === 'sm',
|
|
151
|
+
'bgl_tab-l': size === 'lg',
|
|
152
|
+
'bgl_tab-xl': size === 'xl',
|
|
153
153
|
'w-100p justify-center': fullWidth,
|
|
154
154
|
'w-auto m_w-100p': fullWidthMobile,
|
|
155
155
|
'bgl_tab-align-center': alignTxt === 'center',
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { InjectionKey, Ref } from 'vue'
|
|
2
|
+
import { inject, ref } from 'vue'
|
|
3
|
+
|
|
4
|
+
export const SIDEBAR_COLLAPSED_WIDTH = '66px'
|
|
5
|
+
export const SIDEBAR_COLLAPSED_WIDTH_CARD = '82px'
|
|
6
|
+
|
|
7
|
+
export interface AppLayoutContext {
|
|
8
|
+
/** Sidebar open (expanded) state */
|
|
9
|
+
isOpen: Ref<boolean>
|
|
10
|
+
/** Viewport is below MOBILE_BREAKPOINT */
|
|
11
|
+
isMobile: Ref<boolean>
|
|
12
|
+
toggleMenu: () => void
|
|
13
|
+
/** Close the sidebar when on mobile (e.g. after navigating) */
|
|
14
|
+
closeOnMobile: () => void
|
|
15
|
+
sidebarWidth: string
|
|
16
|
+
sidebarCollapsedWidth: string
|
|
17
|
+
/** Sidebar rendered as a floating card */
|
|
18
|
+
sidebarCardStyle: boolean
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const AppLayoutKey: InjectionKey<AppLayoutContext> = Symbol('AppLayout')
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Access the AppLayout context (sidebar open state, mobile flag, toggle).
|
|
25
|
+
* Works inside AppLayout's slots — including custom header buttons.
|
|
26
|
+
* Outside an AppLayout it warns (dev) and returns an inert fallback.
|
|
27
|
+
*/
|
|
28
|
+
export function useAppLayout(): AppLayoutContext {
|
|
29
|
+
const ctx = inject(AppLayoutKey, null)
|
|
30
|
+
if (ctx) { return ctx }
|
|
31
|
+
|
|
32
|
+
if (import.meta.env?.DEV) {
|
|
33
|
+
console.warn('[bagelink] useAppLayout() called outside <AppLayout>. AppSidebar/AppContent are designed to be used inside it.')
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
isOpen: ref(true),
|
|
37
|
+
isMobile: ref(false),
|
|
38
|
+
toggleMenu: () => {},
|
|
39
|
+
closeOnMobile: () => {},
|
|
40
|
+
sidebarWidth: '260px',
|
|
41
|
+
sidebarCollapsedWidth: SIDEBAR_COLLAPSED_WIDTH,
|
|
42
|
+
sidebarCardStyle: false,
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export { default as AppContent } from './AppContent.vue'
|
|
2
2
|
export { default as AppLayout } from './AppLayout.vue'
|
|
3
3
|
export { default as AppSidebar } from './AppSidebar.vue'
|
|
4
|
+
export { useAppLayout } from './appLayoutContext'
|
|
5
|
+
export type { AppLayoutContext } from './appLayoutContext'
|
|
4
6
|
export { default as BottomMenu } from './BottomMenu.vue'
|
|
5
7
|
export { default as Layout } from './Layout.vue'
|
|
6
8
|
export { default as Panel } from './Panel.vue'
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import type { LightboxItem } from './lightbox.types'
|
|
3
3
|
|
|
4
|
-
import { BglVideo, Btn, Icon, Zoomer, Image, normalizeURL, Swiper, downloadFile } from '@bagelink/vue'
|
|
4
|
+
import { BglVideo, Btn, Icon, Zoomer, Image, normalizeURL, Swiper, downloadFile, useEscapeKey } from '@bagelink/vue'
|
|
5
5
|
import { computed, ref, watch } from 'vue'
|
|
6
6
|
|
|
7
7
|
const isOpen = ref(false)
|
|
@@ -31,14 +31,14 @@ function open(item: LightboxItem, groupItems?: LightboxItem[]) {
|
|
|
31
31
|
})
|
|
32
32
|
if (currentIndex.value === -1) currentIndex.value = 0
|
|
33
33
|
zoom.value = 1
|
|
34
|
-
document.addEventListener('keydown', handleKeydown)
|
|
35
34
|
}
|
|
36
35
|
|
|
37
36
|
function close() {
|
|
38
37
|
isOpen.value = false
|
|
39
|
-
document.removeEventListener('keydown', handleKeydown)
|
|
40
38
|
}
|
|
41
39
|
|
|
40
|
+
useEscapeKey(close, isOpen)
|
|
41
|
+
|
|
42
42
|
function selectItem(index: number) {
|
|
43
43
|
currentIndex.value = index
|
|
44
44
|
zoom.value = 1
|
|
@@ -58,12 +58,6 @@ watch(() => currentIndex.value, () => {
|
|
|
58
58
|
zoom.value = 1
|
|
59
59
|
})
|
|
60
60
|
|
|
61
|
-
function handleKeydown(event: KeyboardEvent) {
|
|
62
|
-
if (event.key === 'Escape') {
|
|
63
|
-
close()
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
61
|
defineExpose({ open, close })
|
|
68
62
|
</script>
|
|
69
63
|
|
package/src/composables/index.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { computed, toValue } from 'vue'
|
|
|
6
6
|
|
|
7
7
|
export { useAddToCalendar } from './useAddToCalendar'
|
|
8
8
|
export { useDevice } from './useDevice'
|
|
9
|
+
export { useEscapeKey } from './useEscapeKey'
|
|
9
10
|
export { useExcel } from './useExcel'
|
|
10
11
|
export { useLocalStore } from './useLocalStore'
|
|
11
12
|
export { usePolling } from './usePolling'
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { onMounted, onUnmounted, ref } from 'vue'
|
|
2
|
+
import { MOBILE_BREAKPOINT } from '../utils/constants'
|
|
2
3
|
|
|
3
4
|
export function useDevice() {
|
|
4
5
|
const innerWidth = ref(0)
|
|
@@ -20,7 +21,7 @@ export function useDevice() {
|
|
|
20
21
|
|
|
21
22
|
// Update current values
|
|
22
23
|
innerWidth.value = window.innerWidth
|
|
23
|
-
isMobile.value = window.innerWidth
|
|
24
|
+
isMobile.value = window.innerWidth <= MOBILE_BREAKPOINT
|
|
24
25
|
scrollY.value = window.scrollY
|
|
25
26
|
scrollX.value = window.scrollX
|
|
26
27
|
innerHeight.value = window.innerHeight
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { MaybeRefOrGetter } from 'vue'
|
|
2
|
+
import { onBeforeUnmount, onMounted, toValue } from 'vue'
|
|
3
|
+
|
|
4
|
+
interface EscapeEntry {
|
|
5
|
+
handler: (e: KeyboardEvent) => void
|
|
6
|
+
enabled: () => boolean
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const stack: EscapeEntry[] = []
|
|
10
|
+
let listening = false
|
|
11
|
+
|
|
12
|
+
function onDocumentKeydown(e: KeyboardEvent) {
|
|
13
|
+
if (e.key !== 'Escape') { return }
|
|
14
|
+
// LIFO: the most recently mounted (topmost) active layer handles Escape
|
|
15
|
+
for (let i = stack.length - 1; i >= 0; i--) {
|
|
16
|
+
if (stack[i].enabled()) {
|
|
17
|
+
stack[i].handler(e)
|
|
18
|
+
return
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function syncListener() {
|
|
24
|
+
if (typeof document === 'undefined') { return }
|
|
25
|
+
if (stack.length > 0 && !listening) {
|
|
26
|
+
document.addEventListener('keydown', onDocumentKeydown)
|
|
27
|
+
listening = true
|
|
28
|
+
} else if (stack.length === 0 && listening) {
|
|
29
|
+
document.removeEventListener('keydown', onDocumentKeydown)
|
|
30
|
+
listening = false
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Run a handler when Escape is pressed, while `enabled` is truthy.
|
|
36
|
+
* - One shared document listener for the whole app
|
|
37
|
+
* - LIFO: the most recently mounted active layer wins (dropdown inside a lightbox closes first)
|
|
38
|
+
* - Automatically cleaned up on unmount
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* useEscapeKey(() => close(), () => isOpen.value)
|
|
42
|
+
*/
|
|
43
|
+
export function useEscapeKey(handler: (e: KeyboardEvent) => void, enabled: MaybeRefOrGetter<boolean> = true) {
|
|
44
|
+
const entry: EscapeEntry = { handler, enabled: () => !!toValue(enabled) }
|
|
45
|
+
|
|
46
|
+
onMounted(() => {
|
|
47
|
+
stack.push(entry)
|
|
48
|
+
syncListener()
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
onBeforeUnmount(() => {
|
|
52
|
+
const i = stack.indexOf(entry)
|
|
53
|
+
if (i !== -1) { stack.splice(i, 1) }
|
|
54
|
+
syncListener()
|
|
55
|
+
})
|
|
56
|
+
}
|
|
@@ -4,7 +4,6 @@ import type { Field, Attributes, Path, SchemaChild, BaseBagelField, VNodeFn } fr
|
|
|
4
4
|
import {
|
|
5
5
|
TextInput,
|
|
6
6
|
NumberInput,
|
|
7
|
-
FieldArray,
|
|
8
7
|
SelectInput,
|
|
9
8
|
ToggleInput,
|
|
10
9
|
CheckInput,
|
|
@@ -12,7 +11,6 @@ import {
|
|
|
12
11
|
UploadInput,
|
|
13
12
|
DateInput,
|
|
14
13
|
TabsNav,
|
|
15
|
-
BglForm,
|
|
16
14
|
bindAttrs,
|
|
17
15
|
classify,
|
|
18
16
|
keyToLabel,
|
|
@@ -74,7 +72,7 @@ export function useSchemaField<T extends { [key: string]: any }>(optns: UseSchem
|
|
|
74
72
|
text: TextInput,
|
|
75
73
|
textarea: TextInput,
|
|
76
74
|
number: NumberInput,
|
|
77
|
-
array:
|
|
75
|
+
array: 'div',
|
|
78
76
|
color: ColorInput,
|
|
79
77
|
tel: TelInput,
|
|
80
78
|
select: SelectInput,
|
|
@@ -85,7 +83,7 @@ export function useSchemaField<T extends { [key: string]: any }>(optns: UseSchem
|
|
|
85
83
|
file: UploadInput,
|
|
86
84
|
date: DateInput,
|
|
87
85
|
tabs: TabsNav,
|
|
88
|
-
form:
|
|
86
|
+
form: 'div',
|
|
89
87
|
range: RangeInput,
|
|
90
88
|
email: EmailInput
|
|
91
89
|
}
|
|
@@ -195,19 +193,6 @@ export function useSchemaField<T extends { [key: string]: any }>(optns: UseSchem
|
|
|
195
193
|
defaultValue,
|
|
196
194
|
}
|
|
197
195
|
|
|
198
|
-
// Special handling for FieldArray component to pass attrs.schema as schema prop
|
|
199
|
-
if (Component === FieldArray && field.attrs?.schema) {
|
|
200
|
-
props.schema = field.attrs.schema
|
|
201
|
-
}
|
|
202
|
-
// Special handling for FieldArray component to pass attrs.type as type prop
|
|
203
|
-
if (Component === FieldArray && field.attrs?.type) {
|
|
204
|
-
props.type = field.attrs.type
|
|
205
|
-
}
|
|
206
|
-
// Special handling for FieldArray component to pass collapsed prop
|
|
207
|
-
if (Component === FieldArray && 'collapsed' in field) {
|
|
208
|
-
props.collapsed = (field as any).collapsed
|
|
209
|
-
}
|
|
210
|
-
|
|
211
196
|
// Wire top-level onClick with conditional args
|
|
212
197
|
if (typeof (field as any).onClick === 'function') {
|
|
213
198
|
const original = (field as any).onClick as (val?: any, row?: T) => void
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// composables/useTheme.ts
|
|
2
|
-
import { ref, computed,
|
|
2
|
+
import { ref, computed, watch } from 'vue'
|
|
3
3
|
|
|
4
4
|
export interface ThemeOption {
|
|
5
5
|
value: string
|
|
@@ -118,33 +118,37 @@ function addTheme(theme: ThemeOption) {
|
|
|
118
118
|
* setTheme('ocean')
|
|
119
119
|
*/
|
|
120
120
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
const validTheme = themeOptions.value.find(t => t.value === saved)
|
|
121
|
+
// Module-level one-time init: a single matchMedia listener and a single
|
|
122
|
+
// colorMode watcher, no matter how many components call useTheme().
|
|
123
|
+
let initialized = false
|
|
125
124
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
125
|
+
function initTheme() {
|
|
126
|
+
if (initialized || !isBrowser) { return }
|
|
127
|
+
initialized = true
|
|
128
|
+
|
|
129
|
+
const saved = window.localStorage.getItem(STORAGE_KEY)
|
|
130
|
+
if (themeOptions.value.some(t => t.value === saved)) {
|
|
131
|
+
colorMode.value = saved!
|
|
132
|
+
}
|
|
129
133
|
|
|
130
|
-
|
|
131
|
-
applyTheme(colorMode.value)
|
|
134
|
+
applyTheme(colorMode.value)
|
|
132
135
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
applyTheme('system')
|
|
138
|
-
}
|
|
136
|
+
// React to system changes when in "system" mode
|
|
137
|
+
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
|
|
138
|
+
if (colorMode.value === 'system') {
|
|
139
|
+
applyTheme('system')
|
|
139
140
|
}
|
|
140
|
-
mq.addEventListener('change', handler)
|
|
141
141
|
})
|
|
142
142
|
|
|
143
|
-
//
|
|
143
|
+
// Persist + apply on mode changes
|
|
144
144
|
watch(colorMode, (newMode) => {
|
|
145
|
-
|
|
145
|
+
localStorage.setItem(STORAGE_KEY, newMode)
|
|
146
146
|
applyTheme(newMode)
|
|
147
147
|
})
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export function useTheme() {
|
|
151
|
+
initTheme()
|
|
148
152
|
|
|
149
153
|
const theme = computed(() => colorMode.value)
|
|
150
154
|
|
|
@@ -10,6 +10,7 @@ import EmailInput from '../components/form/inputs/EmailInput.vue'
|
|
|
10
10
|
import NumberInput from '../components/form/inputs/NumberInput.vue'
|
|
11
11
|
import PasswordInput from '../components/form/inputs/PasswordInput.vue'
|
|
12
12
|
import RadioGroup from '../components/form/inputs/RadioGroup.vue'
|
|
13
|
+
import RangeInput from '../components/form/inputs/RangeInput.vue'
|
|
13
14
|
import RichText from '../components/form/inputs/RichText/index.vue'
|
|
14
15
|
import SelectBtn from '../components/form/inputs/SelectBtn.vue'
|
|
15
16
|
import SelectInput from '../components/form/inputs/SelectInput.vue'
|
|
@@ -223,6 +224,7 @@ function getFieldComponent(fieldOrType: FieldBuilder | string) {
|
|
|
223
224
|
array: ArrayInput,
|
|
224
225
|
upload: UploadInput,
|
|
225
226
|
color: ColorInput,
|
|
227
|
+
range: RangeInput,
|
|
226
228
|
}
|
|
227
229
|
|
|
228
230
|
return (componentMap[type] as typeof TextInput | undefined) ?? TextInput
|
|
@@ -358,6 +358,13 @@ export const $ = {
|
|
|
358
358
|
return new Field('color', parseArgs(labelOrConfig, config))
|
|
359
359
|
},
|
|
360
360
|
|
|
361
|
+
range(
|
|
362
|
+
labelOrConfig?: string | (BaseFieldConfig & { min?: number, max?: number, step?: number, multiRange?: boolean }),
|
|
363
|
+
config?: BaseFieldConfig & { min?: number, max?: number, step?: number, multiRange?: boolean }
|
|
364
|
+
): FieldBuilder<number | [number, number]> {
|
|
365
|
+
return new Field('range', parseArgs(labelOrConfig, config))
|
|
366
|
+
},
|
|
367
|
+
|
|
361
368
|
upload(
|
|
362
369
|
labelOrConfig?: string | (BaseFieldConfig & {
|
|
363
370
|
multiple?: boolean
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import './styles/bagel.css'
|
|
2
2
|
|
|
3
3
|
export * from './components'
|
|
4
|
-
export * from './components/form/useBagelFormState'
|
|
5
4
|
export * from './composables'
|
|
6
5
|
// Dialog (native <dialog> based)
|
|
7
6
|
export * from './dialog'
|
|
@@ -29,7 +28,6 @@ export { type BagelToastOptions, type ToastApi, ToastPlugin, useToast } from './
|
|
|
29
28
|
export * from './types'
|
|
30
29
|
export * from './utils'
|
|
31
30
|
export * from './utils/allCountries'
|
|
32
|
-
export * from './utils/BagelFormUtils'
|
|
33
31
|
export * from './utils/calendar/dateUtils'
|
|
34
32
|
|
|
35
33
|
export * from './utils/constants'
|
package/src/styles/inputs.css
CHANGED
package/src/types/BagelForm.ts
CHANGED
|
@@ -1,83 +1,30 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Schema field types used by DataTable, DataPreview, useSchemaField and elementUtils.
|
|
3
|
+
* (The BagelForm form-rendering system was removed — use FormFlow with defineSchema.)
|
|
4
|
+
*/
|
|
5
|
+
import type { Paths, Get, OmitIndexSignature } from 'type-fest'
|
|
3
6
|
import type { ToString } from 'type-fest/source/internal'
|
|
4
7
|
import type { LiteralStringUnion } from 'type-fest/source/literal-union'
|
|
5
8
|
import type { PathsOptions, DefaultPathsOptions } from 'type-fest/source/paths'
|
|
6
9
|
import type { VNode } from 'vue'
|
|
7
10
|
|
|
8
|
-
type ArrayAttrs = any
|
|
9
|
-
interface Option { label: string, value: any }
|
|
10
|
-
|
|
11
11
|
// BagelInputShellProps is exported from components/form/inputs/bagelInputShell.ts
|
|
12
12
|
// Do not re-export here to avoid duplicate export in src/index.ts
|
|
13
13
|
import type { BagelInputShellProps } from '../components/form/inputs/bagelInputShell'
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
= | string
|
|
17
|
-
| number
|
|
18
|
-
| boolean
|
|
19
|
-
| undefined
|
|
20
|
-
| { [key: string]: any }
|
|
21
|
-
|
|
22
|
-
export type AttributeFn<T, P extends Path<T>> = (
|
|
23
|
-
field: SmartFieldVal<T, P>,
|
|
24
|
-
row?: T
|
|
25
|
-
) => AttributeValue
|
|
26
|
-
|
|
27
|
-
export interface Attributes<T, P extends Path<T>> {
|
|
28
|
-
[key: string]: AttributeValue | AttributeFn<T, P>
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export type BagelFieldOptions<T, P extends Path<T>>
|
|
32
|
-
= | string
|
|
33
|
-
| (
|
|
34
|
-
| {
|
|
35
|
-
label?: string
|
|
36
|
-
value: string | number
|
|
37
|
-
}
|
|
38
|
-
| string
|
|
39
|
-
| number
|
|
40
|
-
| boolean
|
|
41
|
-
| { [key: string]: any }
|
|
42
|
-
)[]
|
|
43
|
-
| ((val?: SmartFieldVal<T, P>, rowData?: T) => Option[] | ((query: string) => Promise<Option[]>))
|
|
44
|
-
| ((query: string, val?: SmartFieldVal<T, P>, rowData?: T) => Promise<Option[]>)
|
|
45
|
-
|
|
46
|
-
export type VIfType<T, P extends Path<T>>
|
|
47
|
-
= | string
|
|
48
|
-
| boolean
|
|
49
|
-
| ((val?: SmartFieldVal<T, P>, rowData?: T) => boolean)
|
|
50
|
-
|
|
51
|
-
export type ValidationFn<T, P extends Path<T>> = (
|
|
52
|
-
val?: SmartFieldVal<T, P>,
|
|
53
|
-
rowData?: T
|
|
54
|
-
) => string | undefined
|
|
15
|
+
interface Option { label: string, value: any }
|
|
55
16
|
|
|
56
|
-
|
|
57
|
-
maxRecursionDepth: 0
|
|
58
|
-
}
|
|
17
|
+
// ---------- Path resolution ----------
|
|
59
18
|
|
|
60
19
|
export type _Path<
|
|
61
20
|
T,
|
|
62
21
|
PO extends PathsOptions = DefaultPathsOptions,
|
|
63
22
|
> = ToString<Paths<OmitIndexSignature<T>, PO>>
|
|
64
23
|
|
|
65
|
-
// Utility type for open-ended object paths
|
|
66
|
-
export type OpenEndedPath<T>
|
|
67
|
-
= keyof T extends infer K
|
|
68
|
-
? K extends keyof T
|
|
69
|
-
? T[K] extends { [key: string]: any }
|
|
70
|
-
? `${K & string}.${string}`
|
|
71
|
-
: never
|
|
72
|
-
: never
|
|
73
|
-
: never
|
|
74
|
-
|
|
75
24
|
// Helper type to get paths for index signature properties
|
|
76
25
|
type IndexSignaturePaths<T> = {
|
|
77
26
|
[K in keyof T]: T[K] extends { [key: string]: any }
|
|
78
|
-
?
|
|
79
|
-
? `${K & string}.${string}`
|
|
80
|
-
: never
|
|
27
|
+
? `${K & string}.${string}`
|
|
81
28
|
: never
|
|
82
29
|
}[keyof T]
|
|
83
30
|
|
|
@@ -87,7 +34,11 @@ export type Path<T, PO extends PathsOptions = DefaultPathsOptions>
|
|
|
87
34
|
? LiteralStringUnion<_Path<T, PO>>
|
|
88
35
|
: _Path<T, PO> | IndexSignaturePaths<T> | `${keyof T & string}.more_info.${string}`
|
|
89
36
|
|
|
90
|
-
|
|
37
|
+
/** The value type at path P in object T. Falls back to unknown if resolution fails. */
|
|
38
|
+
export type FieldVal<T, P extends Path<T>>
|
|
39
|
+
= unknown extends Get<T, P> ? unknown : Get<T, P>
|
|
40
|
+
|
|
41
|
+
/** Field value type that preserves type information when possible. */
|
|
91
42
|
export type SmartFieldVal<T, P extends Path<T>>
|
|
92
43
|
= P extends string
|
|
93
44
|
? P extends keyof T
|
|
@@ -95,8 +46,25 @@ export type SmartFieldVal<T, P extends Path<T>>
|
|
|
95
46
|
: any
|
|
96
47
|
: FieldVal<T, P>
|
|
97
48
|
|
|
98
|
-
//
|
|
99
|
-
|
|
49
|
+
// ---------- Field callbacks & attributes ----------
|
|
50
|
+
|
|
51
|
+
export type AttributeValue
|
|
52
|
+
= | string
|
|
53
|
+
| number
|
|
54
|
+
| boolean
|
|
55
|
+
| undefined
|
|
56
|
+
| { [key: string]: any }
|
|
57
|
+
|
|
58
|
+
export type AttributeFn<T, P extends Path<T>> = (
|
|
59
|
+
field: SmartFieldVal<T, P>,
|
|
60
|
+
row?: T
|
|
61
|
+
) => AttributeValue
|
|
62
|
+
|
|
63
|
+
export interface Attributes<T, P extends Path<T>> {
|
|
64
|
+
[key: string]: AttributeValue | AttributeFn<T, P>
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export type FieldOptions<T, P extends Path<T>>
|
|
100
68
|
= | string
|
|
101
69
|
| (
|
|
102
70
|
| {
|
|
@@ -111,43 +79,27 @@ export type SmartBagelFieldOptions<T, P extends Path<T>>
|
|
|
111
79
|
| ((val?: SmartFieldVal<T, P>, rowData?: T) => Option[] | ((query: string) => Promise<Option[]>))
|
|
112
80
|
| ((query: string, val?: SmartFieldVal<T, P>, rowData?: T) => Promise<Option[]>)
|
|
113
81
|
|
|
114
|
-
|
|
115
|
-
export type SmartVIfType<T, P extends Path<T>>
|
|
82
|
+
export type VIfType<T, P extends Path<T>>
|
|
116
83
|
= | string
|
|
117
84
|
| boolean
|
|
118
85
|
| ((val?: SmartFieldVal<T, P>, rowData?: T) => boolean)
|
|
119
86
|
|
|
120
|
-
|
|
121
|
-
export type SmartValidationFn<T, P extends Path<T>> = (
|
|
87
|
+
export type ValidationFn<T, P extends Path<T>> = (
|
|
122
88
|
val?: SmartFieldVal<T, P>,
|
|
123
89
|
rowData?: T
|
|
124
90
|
) => string | undefined
|
|
125
91
|
|
|
126
|
-
|
|
127
|
-
export type SmartAttributeFn<T, P extends Path<T>> = (
|
|
128
|
-
field: SmartFieldVal<T, P>,
|
|
129
|
-
row?: T
|
|
130
|
-
) => AttributeValue
|
|
131
|
-
|
|
132
|
-
// Smart transform function that preserves type information
|
|
133
|
-
export type SmartTransformFn<T, P extends Path<T>> = (
|
|
92
|
+
export type TransformFn<T, P extends Path<T>> = (
|
|
134
93
|
val?: SmartFieldVal<T, P>,
|
|
135
94
|
rowData?: T
|
|
136
95
|
) => any
|
|
137
96
|
|
|
138
|
-
|
|
139
|
-
export type SmartUpdateFn<T, P extends Path<T>> = (
|
|
97
|
+
export type UpdateFn<T, P extends Path<T>> = (
|
|
140
98
|
val?: SmartFieldVal<T, P>,
|
|
141
99
|
rowData?: T
|
|
142
100
|
) => unknown
|
|
143
101
|
|
|
144
|
-
|
|
145
|
-
// Fall back to unknown if type resolution fails
|
|
146
|
-
export type FieldVal<T, P extends Path<T>>
|
|
147
|
-
= unknown extends Get<T, P> ? unknown : Get<T, P>
|
|
148
|
-
|
|
149
|
-
/** If path P in T is an array, this gives the array's element type. */
|
|
150
|
-
export type ArrayFieldVal<T, P extends Path<T>> = IterableElement<Get<T, P>>
|
|
102
|
+
// ---------- Schema fields ----------
|
|
151
103
|
|
|
152
104
|
export type VNodeFn<T, P extends Path<T>> = (props: {
|
|
153
105
|
row?: T
|
|
@@ -189,50 +141,26 @@ export interface BaseBagelField<
|
|
|
189
141
|
'id'?: P
|
|
190
142
|
'label'?: string
|
|
191
143
|
'placeholder'?: string
|
|
192
|
-
'class'?: AttributeValue |
|
|
144
|
+
'class'?: AttributeValue | AttributeFn<T, P>
|
|
193
145
|
'attrs'?: Attributes<T, P>
|
|
194
146
|
'required'?: boolean
|
|
195
147
|
'disabled'?: boolean
|
|
196
148
|
'helptext'?: string
|
|
197
|
-
'options'?:
|
|
149
|
+
'options'?: FieldOptions<T, P>
|
|
198
150
|
'children'?: SchemaChild<T, Path<T, PO>, PO>[]
|
|
199
151
|
'slots'?: { [key: string]: SchemaChild<T, Path<T, PO>, PO>[] }
|
|
200
152
|
'defaultValue'?: any
|
|
201
|
-
'vIf'?:
|
|
202
|
-
'v-if'?:
|
|
203
|
-
'transform'?:
|
|
204
|
-
'onUpdate'?:
|
|
205
|
-
'validate'?:
|
|
153
|
+
'vIf'?: VIfType<T, P>
|
|
154
|
+
'v-if'?: VIfType<T, P>
|
|
155
|
+
'transform'?: TransformFn<T, P>
|
|
156
|
+
'onUpdate'?: UpdateFn<T, P>
|
|
157
|
+
'validate'?: ValidationFn<T, P>
|
|
206
158
|
}
|
|
207
159
|
|
|
208
|
-
export type _MappedBaseBagelField<
|
|
209
|
-
T,
|
|
210
|
-
PO extends PathsOptions = DefaultPathsOptions,
|
|
211
|
-
> = {
|
|
212
|
-
[P in Path<T, PO>]: BaseBagelField<T, P, PO>
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
export type MappedBaseBagelFieldP<
|
|
216
|
-
T,
|
|
217
|
-
P extends Path<T, PO>,
|
|
218
|
-
PO extends PathsOptions = DefaultPathsOptions,
|
|
219
|
-
> = _MappedBaseBagelField<T, PO>[P]
|
|
220
|
-
|
|
221
|
-
export type FieldByP<
|
|
222
|
-
T,
|
|
223
|
-
P extends Path<T, PO>,
|
|
224
|
-
PO extends PathsOptions = DefaultPathsOptions,
|
|
225
|
-
> = MappedBaseBagelFieldP<T, P, PO>
|
|
226
|
-
|
|
227
160
|
export type Field<
|
|
228
161
|
T,
|
|
229
162
|
PO extends PathsOptions = DefaultPathsOptions,
|
|
230
|
-
> =
|
|
231
|
-
|
|
232
|
-
export type BglFieldT<
|
|
233
|
-
T,
|
|
234
|
-
PO extends PathsOptions = DefaultPathsOptions,
|
|
235
|
-
> = Field<T, PO>
|
|
163
|
+
> = ValidBaseBagelField<T, PO>
|
|
236
164
|
|
|
237
165
|
export type SchemaField<
|
|
238
166
|
T,
|
|
@@ -244,40 +172,7 @@ export type BglFormSchemaT<
|
|
|
244
172
|
PO extends PathsOptions = DefaultPathsOptions,
|
|
245
173
|
> = (SchemaField<T, PO> | BaseBagelField<T, Path<T, PO>, PO>)[]
|
|
246
174
|
|
|
247
|
-
|
|
248
|
-
T,
|
|
249
|
-
PO extends PathsOptions = ShallowPathsOptions,
|
|
250
|
-
> = (SchemaField<T, PO> | BaseBagelField<T, Path<T, PO>, PO>)[]
|
|
251
|
-
|
|
252
|
-
export interface InputBagelField<
|
|
253
|
-
T,
|
|
254
|
-
P extends Path<T, PO>,
|
|
255
|
-
PO extends PathsOptions = DefaultPathsOptions
|
|
256
|
-
>
|
|
257
|
-
extends BaseBagelField<T, P, PO> {
|
|
258
|
-
$el: 'text' | any
|
|
259
|
-
type?: string
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
export interface SelectBagelField<
|
|
263
|
-
T,
|
|
264
|
-
P extends Path<T, PO>,
|
|
265
|
-
PO extends PathsOptions = DefaultPathsOptions,
|
|
266
|
-
>
|
|
267
|
-
extends BaseBagelField<T, P, PO> {
|
|
268
|
-
$el: 'select' | any
|
|
269
|
-
type?: string
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
export interface ArrayBagelField<
|
|
273
|
-
T,
|
|
274
|
-
P extends Path<T, PO>,
|
|
275
|
-
PO extends PathsOptions = DefaultPathsOptions,
|
|
276
|
-
>
|
|
277
|
-
extends BaseBagelField<T, P, PO> {
|
|
278
|
-
$el: 'array' | any
|
|
279
|
-
attrs?: ArrayAttrs
|
|
280
|
-
}
|
|
175
|
+
// ---------- Input component contracts ----------
|
|
281
176
|
|
|
282
177
|
export interface ValidateInputBaseT {
|
|
283
178
|
validate?: ValidationFn<{ [key: string]: unknown }, string>
|
package/src/types/BtnOptions.ts
CHANGED
|
@@ -3,18 +3,20 @@ import type { IconType, ThemeType } from '.'
|
|
|
3
3
|
export interface BtnOptions {
|
|
4
4
|
onClick?: () => void
|
|
5
5
|
color?: ThemeType
|
|
6
|
-
theme?: ThemeType
|
|
7
6
|
disabled?: boolean
|
|
8
7
|
icon?: IconType
|
|
8
|
+
variant?: 'solid' | 'flat' | 'outline'
|
|
9
9
|
flat?: boolean
|
|
10
|
+
outline?: boolean
|
|
11
|
+
/** @deprecated Use `outline` */
|
|
12
|
+
border?: boolean
|
|
10
13
|
thin?: boolean
|
|
11
14
|
type?: 'button' | 'submit' | 'reset'
|
|
12
15
|
loading?: boolean
|
|
13
16
|
role?: string
|
|
14
17
|
value?: string
|
|
15
|
-
border?: boolean
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
export type UnitSize = 'px' | 'rem' | 'vh' | 'vw'
|
|
19
|
-
export type SizeType = '
|
|
21
|
+
export type SizeType = 'xs' | 'sm' | 'md' | 'lg' | 'xl'
|
|
20
22
|
export type SizeUnit = `${number}` | number | `${number}${UnitSize}`
|