@bagelink/vue 1.9.83 → 1.9.86

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 (37) hide show
  1. package/dist/components/Avatar.vue.d.ts +1 -0
  2. package/dist/components/Avatar.vue.d.ts.map +1 -1
  3. package/dist/components/Badge.vue.d.ts +0 -1
  4. package/dist/components/Badge.vue.d.ts.map +1 -1
  5. package/dist/components/Btn.vue.d.ts.map +1 -1
  6. package/dist/components/Dropdown.vue.d.ts.map +1 -1
  7. package/dist/components/Loading.vue.d.ts +2 -1
  8. package/dist/components/Loading.vue.d.ts.map +1 -1
  9. package/dist/components/form/inputs/RichText/index.vue.d.ts.map +1 -1
  10. package/dist/form-flow/FormFlow.vue.d.ts.map +1 -1
  11. package/dist/form-flow/form-flow.d.ts +9 -9
  12. package/dist/form-flow/form-flow.d.ts.map +1 -1
  13. package/dist/index.cjs +163 -85
  14. package/dist/index.d.ts +1 -0
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.mjs +25737 -25545
  17. package/dist/plugins/useToast.d.ts.map +1 -1
  18. package/dist/style.css +1 -1
  19. package/dist/utils/filterRef.d.ts +15 -0
  20. package/dist/utils/filterRef.d.ts.map +1 -0
  21. package/package.json +1 -1
  22. package/src/components/Avatar.vue +6 -2
  23. package/src/components/Badge.vue +14 -1084
  24. package/src/components/Btn.vue +37 -37
  25. package/src/components/Dropdown.vue +1 -1
  26. package/src/components/Loading.vue +15 -6
  27. package/src/components/form/inputs/RichText/index.vue +325 -221
  28. package/src/form-flow/FormFlow.vue +9 -0
  29. package/src/form-flow/form-flow.ts +13 -3
  30. package/src/index.ts +1 -1
  31. package/src/plugins/useToast.ts +14 -0
  32. package/src/styles/bagel.css +1 -0
  33. package/src/styles/base-colors.css +1429 -46
  34. package/src/styles/text.css +1755 -1755
  35. package/src/styles/toast-overrides.css +10 -0
  36. package/src/utils/filterRef.ts +133 -0
  37. package/src/styles/btnColors.css +0 -847
@@ -1,3 +1,13 @@
1
+ /* Reset popover container used to promote toasts above showModal() dialogs */
2
+ #bgl-toast-container {
3
+ all: unset;
4
+ pointer-events: none;
5
+ }
6
+
7
+ #bgl-toast-container > * {
8
+ pointer-events: auto;
9
+ }
10
+
1
11
  /* Override vue-toastification default styles */
2
12
  .custom-toast-wrapper {
3
13
  padding: 0 !important;
@@ -0,0 +1,133 @@
1
+ import type { Ref } from 'vue'
2
+ import { computed, isRef, shallowReactive } from 'vue'
3
+
4
+ const htmlReplacers = {
5
+ '': /<[^>]*>?/g,
6
+ ' ': /&nbsp;/g,
7
+ '"': /&quot;/g,
8
+ '\'': /&apos;/g,
9
+ '&': /&amp;/g,
10
+ '<': /&lt;/g,
11
+ '>': /&gt;/g,
12
+ } as const
13
+
14
+ function clearHtml(value?: string): string {
15
+ if (!value) { return '' }
16
+ return Object.entries(htmlReplacers).reduce(
17
+ (text, [replacement, regex]) => text.replace(regex, replacement),
18
+ value
19
+ )
20
+ }
21
+
22
+ const normalizeSearchChars = /[\p{N}\p{L}\s]/gu
23
+ function normalizeText(text: string): string {
24
+ return text.match(normalizeSearchChars)?.join('').toLowerCase() ?? ''
25
+ }
26
+
27
+ function getValueByPath(obj: any, path: string): any {
28
+ let result = obj
29
+ for (const key of path.split('.')) {
30
+ if (result === null || result === undefined || typeof result !== 'object') { return undefined }
31
+ result = result[key]
32
+ }
33
+ return result
34
+ }
35
+
36
+ function collectAllLeafPaths(obj: any, prefix = ''): string[] {
37
+ if (!obj || typeof obj !== 'object') { return [] }
38
+ return Object.keys(obj).flatMap((key) => {
39
+ const value = obj[key]
40
+ const path = prefix ? `${prefix}.${key}` : key
41
+ if (value && typeof value === 'object' && !Array.isArray(value) && !(value instanceof Date)) {
42
+ return collectAllLeafPaths(value, path)
43
+ }
44
+ return [path]
45
+ })
46
+ }
47
+
48
+ function toSearchableString(value: unknown): string {
49
+ if (value === null || value === undefined) { return '' }
50
+ if (typeof value === 'string') { return clearHtml(value) }
51
+ if (typeof value === 'number' || typeof value === 'boolean') { return String(value) }
52
+ if (value instanceof Date) { return value.toISOString() }
53
+ return ''
54
+ }
55
+
56
+ interface FilterRefOptions<Item extends Record<string, any>> {
57
+ filter?: Ref<(item: Item) => boolean> | ((item: Item) => boolean)
58
+ /** Dot-path keys to index (e.g. 'user.address.city'). Defaults to all leaf fields. */
59
+ keys?: string[]
60
+ minChars?: number
61
+ }
62
+
63
+ export function filterRef<T extends Record<string, any>[]>(
64
+ initialValue: T = [] as unknown as T,
65
+ options: FilterRefOptions<T[number]> = {}
66
+ ) {
67
+ type Item = T[number]
68
+ const { minChars = 1 } = options
69
+ const state = shallowReactive({ _list: initialValue as Item[], searchTerm: '' })
70
+
71
+ let searchIndex: string[] = []
72
+
73
+ function buildIndexEntry(item: Item, seen = new WeakSet()): string {
74
+ if (seen.has(item as object)) { return '' }
75
+ seen.add(item as object)
76
+
77
+ const paths = options.keys ?? collectAllLeafPaths(item)
78
+ const parts: string[] = []
79
+ for (const path of paths) {
80
+ const value = getValueByPath(item, path)
81
+ if (Array.isArray(value)) {
82
+ for (const el of value) {
83
+ if (el && typeof el === 'object' && !(el instanceof Date)) {
84
+ parts.push(buildIndexEntry(el as Item, seen))
85
+ } else {
86
+ const s = toSearchableString(el)
87
+ if (s) { parts.push(normalizeText(s)) }
88
+ }
89
+ }
90
+ } else {
91
+ const s = toSearchableString(value)
92
+ if (s) { parts.push(normalizeText(s)) }
93
+ }
94
+ }
95
+ return parts.join(' ')
96
+ }
97
+
98
+ function buildIndex(list: Item[]) {
99
+ searchIndex = list.map(item => buildIndexEntry(item))
100
+ }
101
+
102
+ buildIndex(initialValue as Item[])
103
+
104
+ const filtered = computed(() => {
105
+ let result = state._list
106
+
107
+ if (state.searchTerm.length >= minChars) {
108
+ const terms = normalizeText(state.searchTerm).split(/\s+/).filter(t => t.length > 0)
109
+ if (terms.length > 0) {
110
+ result = result.filter((_, i) => {
111
+ const entry = searchIndex[i] ?? ''
112
+ return terms.every(term => entry.includes(term))
113
+ })
114
+ }
115
+ }
116
+
117
+ if (options.filter) {
118
+ const fn = isRef(options.filter) ? options.filter.value : options.filter
119
+ result = result.filter(fn)
120
+ }
121
+
122
+ return result
123
+ })
124
+
125
+ return {
126
+ get searchTerm() { return state.searchTerm },
127
+ set searchTerm(v: string) { state.searchTerm = v },
128
+ get value() { return filtered.value },
129
+ set value(v: Item[]) { state._list = v; buildIndex(v) },
130
+ get length() { return filtered.value.length },
131
+ [Symbol.iterator](): IterableIterator<Item> { return filtered.value[Symbol.iterator]() },
132
+ }
133
+ }