@bagelink/vue 1.4.77 → 1.4.81

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.
@@ -0,0 +1,544 @@
1
+ import type { BaseBagelField, IconType, Option, Path } from '@bagelink/vue'
2
+
3
+ export type DefaultPathsOptions = Record<string, any>
4
+ export type PathsOptions = Record<string, any>
5
+
6
+ export interface BaseElementField<
7
+ T,
8
+ P extends Path<T, PO>,
9
+ PO extends PathsOptions = DefaultPathsOptions
10
+ > extends Partial<BaseBagelField<T, P, PO>> {
11
+ $el: string
12
+ id?: P
13
+ class?: string
14
+ vIf?: boolean | (() => boolean)
15
+ style?: Record<string, any>
16
+ attrs?: Record<string, any>
17
+ onClick?: () => void
18
+ children?: BaseElementField<T, any>[]
19
+ }
20
+
21
+ export interface BtnElementOptions<
22
+ T = any,
23
+ P extends Path<T, PO> = any,
24
+ PO extends PathsOptions = DefaultPathsOptions
25
+ > extends Partial<BaseElementField<T, P, PO>> {
26
+ text?: string
27
+ variant?: 'primary' | 'secondary' | 'outline' | 'ghost' | 'danger'
28
+ size?: 'sm' | 'md' | 'lg'
29
+ disabled?: boolean
30
+ loading?: boolean
31
+ icon?: IconType
32
+ iconPosition?: 'left' | 'right'
33
+ href?: string
34
+ target?: '_blank' | '_self' | '_parent' | '_top'
35
+ }
36
+
37
+ export interface TxtElementOptions<
38
+ T = any,
39
+ P extends Path<T, PO> = any,
40
+ PO extends PathsOptions = DefaultPathsOptions
41
+ > extends Partial<BaseElementField<T, P, PO>> {
42
+ text?: string
43
+ tag?: 'p' | 'span' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'div'
44
+ size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'
45
+ weight?: 'light' | 'normal' | 'medium' | 'semibold' | 'bold'
46
+ color?: string
47
+ align?: 'left' | 'center' | 'right' | 'justify'
48
+ }
49
+
50
+ export interface ImgElementOptions<
51
+ T = any,
52
+ P extends Path<T, PO> = any,
53
+ PO extends PathsOptions = DefaultPathsOptions
54
+ > extends Partial<BaseElementField<T, P, PO>> {
55
+ src?: string
56
+ alt?: string
57
+ width?: number | string
58
+ height?: number | string
59
+ loading?: 'lazy' | 'eager'
60
+ fit?: 'cover' | 'contain' | 'fill' | 'scale-down' | 'none'
61
+ rounded?: boolean | 'sm' | 'md' | 'lg' | 'full'
62
+ fallback?: string
63
+ }
64
+
65
+ export interface DropdownElementOptions<
66
+ T = any,
67
+ P extends Path<T, PO> = any,
68
+ PO extends PathsOptions = DefaultPathsOptions
69
+ > extends Partial<BaseElementField<T, P, PO>> {
70
+ options?: Option[] | (() => Option[])
71
+ placeholder?: string
72
+ searchable?: boolean
73
+ multiselect?: boolean
74
+ clearable?: boolean
75
+ onSelect?: (value: any) => void
76
+ onSearch?: (search: string) => any
77
+ }
78
+
79
+ export interface ListItemElementOptions<
80
+ T = any,
81
+ P extends Path<T, PO> = any,
82
+ PO extends PathsOptions = DefaultPathsOptions
83
+ > extends Partial<BaseElementField<T, P, PO>> {
84
+ title?: string
85
+ subtitle?: string
86
+ icon?: IconType
87
+ avatar?: string
88
+ badge?: string | number
89
+ actions?: Array<{ label: string, onClick: () => void, icon?: IconType }>
90
+ clickable?: boolean
91
+ divider?: boolean
92
+ }
93
+
94
+ // Magical button overloads with schema support
95
+ export function btn<
96
+ T = any,
97
+ P extends Path<T, PO> = any,
98
+ PO extends PathsOptions = DefaultPathsOptions
99
+ >(options: BtnElementOptions<T, P, PO>): BaseElementField<T, P, PO>
100
+ export function btn<
101
+ T = any,
102
+ P extends Path<T, PO> = any,
103
+ PO extends PathsOptions = DefaultPathsOptions
104
+ >(id: P): BaseElementField<T, P, PO>
105
+ export function btn<
106
+ T = any,
107
+ P extends Path<T, PO> = any,
108
+ PO extends PathsOptions = DefaultPathsOptions
109
+ >(id: P, text: string): BaseElementField<T, P, PO>
110
+ export function btn<
111
+ T = any,
112
+ P extends Path<T, PO> = any,
113
+ PO extends PathsOptions = DefaultPathsOptions
114
+ >(id: P, icon: IconType): BaseElementField<T, P, PO>
115
+ export function btn<
116
+ T = any,
117
+ P extends Path<T, PO> = any,
118
+ PO extends PathsOptions = DefaultPathsOptions
119
+ >(
120
+ id: P,
121
+ text: string,
122
+ options: BtnElementOptions<T, P, PO>
123
+ ): BaseElementField<T, P, PO>
124
+ export function btn<
125
+ T = any,
126
+ P extends Path<T, PO> = any,
127
+ PO extends PathsOptions = DefaultPathsOptions
128
+ >(
129
+ id: P,
130
+ icon: IconType,
131
+ options: BtnElementOptions<T, P, PO>
132
+ ): BaseElementField<T, P, PO>
133
+ export function btn<
134
+ T = any,
135
+ P extends Path<T, PO> = any,
136
+ PO extends PathsOptions = DefaultPathsOptions
137
+ >(
138
+ id: P,
139
+ textOrIcon: string | IconType,
140
+ options: BtnElementOptions<T, P, PO>
141
+ ): BaseElementField<T, P, PO>
142
+ export function btn<
143
+ T = any,
144
+ P extends Path<T, PO> = any,
145
+ PO extends PathsOptions = DefaultPathsOptions
146
+ >(
147
+ idOrOptions?: P | BtnElementOptions<T, P, PO>,
148
+ textOrIcon?: string | IconType,
149
+ options?: BtnElementOptions<T, P, PO>,
150
+ ): BaseElementField<T, P, PO> {
151
+ // Handle different overload patterns
152
+ let id: P | undefined
153
+ let text: string = ''
154
+ let icon: IconType | undefined
155
+ let finalOptions: BtnElementOptions<T, P, PO> = {}
156
+
157
+ if (typeof idOrOptions === 'object' && idOrOptions !== null) {
158
+ // btn(options)
159
+ finalOptions = idOrOptions
160
+ const { id: optionId, text: optionText, icon: optionIcon } = finalOptions
161
+ id = optionId
162
+ text = optionText ?? ''
163
+ icon = optionIcon
164
+ } else {
165
+ // btn(id, ...) patterns
166
+ id = idOrOptions
167
+ if (textOrIcon != null) {
168
+ // Check if textOrIcon is likely an icon vs text
169
+ // Icons are typically: lowercase, contain hyphens/underscores, no spaces, shorter length
170
+ const isLikelyIcon = typeof textOrIcon === 'string'
171
+ && textOrIcon.length <= 30
172
+ && !textOrIcon.includes(' ')
173
+ && (textOrIcon.includes('-')
174
+ || textOrIcon.includes('_')
175
+ || textOrIcon.length <= 12)
176
+ && textOrIcon === textOrIcon.toLowerCase()
177
+
178
+ if (isLikelyIcon) {
179
+ icon = textOrIcon as IconType
180
+ if (options) {
181
+ finalOptions = options
182
+ }
183
+ } else {
184
+ text = textOrIcon
185
+ if (options) {
186
+ finalOptions = options
187
+ }
188
+ }
189
+ }
190
+ }
191
+
192
+ return {
193
+ $el: 'btn',
194
+ id,
195
+ class: finalOptions.class,
196
+ vIf: finalOptions.vIf,
197
+ style: finalOptions.style,
198
+ onClick: finalOptions.onClick,
199
+ attrs: {
200
+ value: text || (finalOptions.text ?? '') || '',
201
+ variant: finalOptions.variant,
202
+ size: finalOptions.size,
203
+ disabled: finalOptions.disabled,
204
+ loading: finalOptions.loading,
205
+ icon: icon ?? finalOptions.icon,
206
+ iconPosition: finalOptions.iconPosition,
207
+ href: finalOptions.href,
208
+ target: finalOptions.target,
209
+ },
210
+ }
211
+ }
212
+
213
+ export function getBaseElementField<
214
+ T = any,
215
+ P extends Path<T, PO> = any,
216
+ PO extends PathsOptions = DefaultPathsOptions
217
+ >(
218
+ elementType: string,
219
+ id?: P,
220
+ options: Partial<BaseElementField<T, P, PO>> = {}
221
+ ): BaseElementField<T, P, PO> {
222
+ return {
223
+ $el: elementType,
224
+ id,
225
+ class: options.class,
226
+ vIf: options.vIf,
227
+ style: options.style,
228
+ attrs: options.attrs || {},
229
+ onClick: options.onClick,
230
+ }
231
+ }
232
+
233
+ // Icon button shorthand
234
+ export function iconBtn<
235
+ T = any,
236
+ P extends Path<T, PO> = any,
237
+ PO extends PathsOptions = DefaultPathsOptions
238
+ >(
239
+ id?: P,
240
+ icon?: IconType,
241
+ options?: BtnElementOptions<T, P, PO>,
242
+ ): BaseElementField<T, P, PO> {
243
+ if (icon != null && id != null) {
244
+ return btn(id, icon, options || {})
245
+ }
246
+ return btn({ id, icon, ...options } as BtnElementOptions<T, P, PO>)
247
+ }
248
+
249
+ // Magical text overloads with schema support
250
+ export function txt<
251
+ T = any,
252
+ P extends Path<T, PO> = any,
253
+ PO extends PathsOptions = DefaultPathsOptions
254
+ >(options: TxtElementOptions<T, P, PO>): BaseElementField<T, P, PO>
255
+ export function txt<
256
+ T = any,
257
+ P extends Path<T, PO> = any,
258
+ PO extends PathsOptions = DefaultPathsOptions
259
+ >(id: P): BaseElementField<T, P, PO>
260
+ export function txt<
261
+ T = any,
262
+ P extends Path<T, PO> = any,
263
+ PO extends PathsOptions = DefaultPathsOptions
264
+ >(id: P, text: string): BaseElementField<T, P, PO>
265
+ export function txt<
266
+ T = any,
267
+ P extends Path<T, PO> = any,
268
+ PO extends PathsOptions = DefaultPathsOptions
269
+ >(
270
+ id: P,
271
+ text: string,
272
+ tag: 'p' | 'span' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'div'
273
+ ): BaseElementField<T, P, PO>
274
+ export function txt<
275
+ T = any,
276
+ P extends Path<T, PO> = any,
277
+ PO extends PathsOptions = DefaultPathsOptions
278
+ >(id: P, text: string, options: TxtElementOptions<T, P, PO>): BaseElementField<T, P, PO>
279
+ export function txt<
280
+ T = any,
281
+ P extends Path<T, PO> = any,
282
+ PO extends PathsOptions = DefaultPathsOptions
283
+ >(
284
+ idOrOptions?: P | TxtElementOptions<T, P, PO>,
285
+ text?: string,
286
+ tagOrOptions?: string | TxtElementOptions<T, P, PO>,
287
+ ): BaseElementField<T, P, PO> {
288
+ // Handle different overload patterns
289
+ let id: P | undefined
290
+ let finalOptions: TxtElementOptions<T, P, PO> = {}
291
+
292
+ if (typeof idOrOptions === 'object' && idOrOptions !== null) {
293
+ // txt(options)
294
+ finalOptions = idOrOptions
295
+ const { id: optionId } = finalOptions
296
+ id = optionId
297
+ } else {
298
+ // txt(id, ...) patterns
299
+ id = idOrOptions
300
+ if (text != null) {
301
+ if (typeof tagOrOptions === 'string') {
302
+ // txt(id, text, tag)
303
+ finalOptions = { tag: tagOrOptions as any, text }
304
+ } else if (tagOrOptions) {
305
+ // txt(id, text, options)
306
+ finalOptions = { ...tagOrOptions, text }
307
+ } else {
308
+ finalOptions = { text }
309
+ }
310
+ }
311
+ }
312
+
313
+ return {
314
+ $el: finalOptions.tag || 'p',
315
+ id,
316
+ class: finalOptions.class,
317
+ vIf: finalOptions.vIf,
318
+ style: finalOptions.style,
319
+ attrs: {
320
+ text: finalOptions.text ?? '',
321
+ size: finalOptions.size,
322
+ weight: finalOptions.weight,
323
+ color: finalOptions.color,
324
+ align: finalOptions.align,
325
+ },
326
+ }
327
+ }
328
+
329
+ // Magical image overloads with schema support
330
+ export function img<
331
+ T = any,
332
+ P extends Path<T, PO> = any,
333
+ PO extends PathsOptions = DefaultPathsOptions
334
+ >(options: ImgElementOptions<T, P, PO>): BaseElementField<T, P, PO>
335
+ export function img<
336
+ T = any,
337
+ P extends Path<T, PO> = any,
338
+ PO extends PathsOptions = DefaultPathsOptions
339
+ >(id: P): BaseElementField<T, P, PO>
340
+ export function img<
341
+ T = any,
342
+ P extends Path<T, PO> = any,
343
+ PO extends PathsOptions = DefaultPathsOptions
344
+ >(id: P, src: string): BaseElementField<T, P, PO>
345
+ export function img<
346
+ T = any,
347
+ P extends Path<T, PO> = any,
348
+ PO extends PathsOptions = DefaultPathsOptions
349
+ >(id: P, src: string, alt: string): BaseElementField<T, P, PO>
350
+ export function img<
351
+ T = any,
352
+ P extends Path<T, PO> = any,
353
+ PO extends PathsOptions = DefaultPathsOptions
354
+ >(id: P, src: string, options: ImgElementOptions<T, P, PO>): BaseElementField<T, P, PO>
355
+ export function img<
356
+ T = any,
357
+ P extends Path<T, PO> = any,
358
+ PO extends PathsOptions = DefaultPathsOptions
359
+ >(
360
+ idOrOptions?: P | ImgElementOptions<T, P, PO>,
361
+ src?: string,
362
+ altOrOptions?: string | ImgElementOptions<T, P, PO>,
363
+ ): BaseElementField<T, P, PO> {
364
+ // Handle different overload patterns
365
+ let id: P | undefined
366
+ let finalSrc: string = ''
367
+ let finalOptions: ImgElementOptions<T, P, PO> = {}
368
+
369
+ if (typeof idOrOptions === 'object' && idOrOptions !== null) {
370
+ // img(options)
371
+ finalOptions = idOrOptions
372
+ const { id: optionId, src: optionSrc } = finalOptions
373
+ id = optionId
374
+ finalSrc = optionSrc ?? ''
375
+ } else {
376
+ // img(id, ...) patterns
377
+ id = idOrOptions
378
+ if (src != null) {
379
+ finalSrc = src
380
+ if (typeof altOrOptions === 'string') {
381
+ // img(id, src, alt)
382
+ finalOptions = { alt: altOrOptions }
383
+ } else if (altOrOptions) {
384
+ // img(id, src, options)
385
+ finalOptions = altOrOptions
386
+ }
387
+ }
388
+ }
389
+
390
+ return {
391
+ $el: 'img',
392
+ id,
393
+ class: finalOptions.class,
394
+ vIf: finalOptions.vIf,
395
+ style: finalOptions.style,
396
+ attrs: {
397
+ src: finalSrc || (finalOptions.src ?? '') || '',
398
+ alt: finalOptions.alt,
399
+ width: finalOptions.width,
400
+ height: finalOptions.height,
401
+ loading: finalOptions.loading,
402
+ fit: finalOptions.fit,
403
+ rounded: finalOptions.rounded,
404
+ fallback: finalOptions.fallback,
405
+ },
406
+ }
407
+ }
408
+
409
+ // Dropdown element function following BagelForm pattern
410
+ export function dropdownElement<
411
+ T = any,
412
+ P extends Path<T, PO> = any,
413
+ PO extends PathsOptions = DefaultPathsOptions
414
+ >(
415
+ id?: P,
416
+ options?: Option[] | (() => Option[]),
417
+ config?: DropdownElementOptions<T, P, PO>,
418
+ ): BaseElementField<T, P, PO> {
419
+ return {
420
+ $el: 'dropdown',
421
+ id,
422
+ class: config?.class,
423
+ vIf: config?.vIf,
424
+ style: config?.style,
425
+ attrs: {
426
+ options: options || config?.options,
427
+ placeholder: config?.placeholder,
428
+ searchable: config?.searchable,
429
+ multiselect: config?.multiselect,
430
+ clearable: config?.clearable,
431
+ onSelect: config?.onSelect,
432
+ onSearch: config?.onSearch,
433
+ },
434
+ }
435
+ }
436
+
437
+ // ListItem element function following BagelForm pattern
438
+ export function listItemElement<
439
+ T = any,
440
+ P extends Path<T, PO> = any,
441
+ PO extends PathsOptions = DefaultPathsOptions
442
+ >(
443
+ id?: P,
444
+ title?: string,
445
+ options?: ListItemElementOptions<T, P, PO>,
446
+ ): BaseElementField<T, P, PO> {
447
+ return {
448
+ $el: 'listItem',
449
+ id,
450
+ class: options?.class,
451
+ vIf: options?.vIf,
452
+ style: options?.style,
453
+ onClick: options?.onClick,
454
+ attrs: {
455
+ title: title ?? options?.title ?? '',
456
+ subtitle: options?.subtitle,
457
+ icon: options?.icon,
458
+ avatar: options?.avatar,
459
+ badge: options?.badge,
460
+ actions: options?.actions,
461
+ clickable: options?.clickable,
462
+ divider: options?.divider,
463
+ },
464
+ }
465
+ }
466
+
467
+ // Container element function following BagelForm pattern
468
+ export function containerElement<
469
+ T = any,
470
+ P extends Path<T, PO> = any,
471
+ PO extends PathsOptions = DefaultPathsOptions
472
+ >(
473
+ id?: P,
474
+ children?: BaseElementField<T, any>[],
475
+ options?: Partial<BaseElementField<T, P, PO>>,
476
+ ): BaseElementField<T, P, PO> {
477
+ return {
478
+ $el: 'div',
479
+ id,
480
+ class: options?.class ?? 'flex gap-2',
481
+ vIf: options?.vIf,
482
+ style: options?.style,
483
+ attrs: options?.attrs || {},
484
+ children: children as any,
485
+ }
486
+ }
487
+
488
+ export function findElementById<T>(
489
+ id: string,
490
+ elements: BaseElementField<T, any>[]
491
+ ): BaseElementField<T, any> | undefined {
492
+ for (const element of elements) {
493
+ if (element.id === id) return element
494
+ if (element.children && element.children.length > 0) {
495
+ const child = findElementById(id, element.children)
496
+ if (child) return child
497
+ }
498
+ }
499
+ return undefined
500
+ }
501
+
502
+ export function column<T = any, P extends Path<T, PO> = any, PO extends PathsOptions = DefaultPathsOptions>(
503
+ id?: P,
504
+ labelOrOptions?: string | Partial<BaseElementField<T, P, PO>>,
505
+ options?: Partial<BaseElementField<T, P, PO>>,
506
+ ): BaseElementField<T, P, PO> {
507
+ let label: string | undefined
508
+ if (typeof labelOrOptions === 'string') {
509
+ label = labelOrOptions
510
+ } else {
511
+ options = labelOrOptions
512
+ }
513
+
514
+ return {
515
+ $el: 'div',
516
+ id,
517
+ class: options?.class ?? 'column-class',
518
+ vIf: options?.vIf,
519
+ style: options?.style,
520
+ attrs: {
521
+ ...options?.attrs,
522
+ label: label ?? options?.attrs?.label ?? '',
523
+ },
524
+ children: options?.children as any,
525
+ }
526
+ }
527
+
528
+ export const col = column
529
+
530
+ export function useElements() {
531
+ return {
532
+ btn,
533
+ iconBtn,
534
+ txt,
535
+ img,
536
+ dropdownElement,
537
+ listItemElement,
538
+ containerElement,
539
+ findElementById,
540
+ getBaseElementField,
541
+ col,
542
+ column,
543
+ }
544
+ }