@bagelink/vue 1.7.80 → 1.7.84

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,177 @@
1
+ /**
2
+ * SCIM 2.0 Query Builder
3
+ *
4
+ * Type-safe query builder for SCIM 2.0 filtering.
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * // Array-based (recommended for UI)
9
+ * const filters: QueryConditions<Person> = [
10
+ * { field: 'first_name', op: 'eq', value: 'John' },
11
+ * { field: 'age', op: 'gt', value: 18, connector: 'and' },
12
+ * ]
13
+ * buildQuery(filters) // → 'first_name eq "John" and age gt 18'
14
+ *
15
+ * // Range query (same field twice)
16
+ * const rangeFilters: QueryConditions<Donation> = [
17
+ * { field: 'amount', op: 'ge', value: 100 },
18
+ * { field: 'amount', op: 'le', value: 500, connector: 'and' },
19
+ * ]
20
+ * buildQuery(rangeFilters) // → 'amount ge 100 and amount le 500'
21
+ * ```
22
+ */
23
+ type Primitive = string | number | boolean | null;
24
+ type DeepKeyOf<T> = T extends Primitive ? never : {
25
+ [K in keyof T & string]: K | `${K}.${DeepKeyOf<T[K]>}`;
26
+ }[keyof T & string];
27
+ /**
28
+ * SCIM 2.0 comparison operators
29
+ */
30
+ export type ComparisonOperator = 'eq' | 'ne' | 'gt' | 'ge' | 'lt' | 'le' | 'co' | 'sw' | 'ew' | 'pr';
31
+ /**
32
+ * SCIM 2.0 logical operators
33
+ */
34
+ export type LogicalOperator = 'and' | 'or';
35
+ /**
36
+ * A single filter condition
37
+ */
38
+ export interface FilterCondition<T extends Record<string, any> = Record<string, any>> {
39
+ field: DeepKeyOf<T> | string;
40
+ op: ComparisonOperator;
41
+ value?: Primitive;
42
+ connector?: LogicalOperator;
43
+ }
44
+ /**
45
+ * Array of filter conditions - the primary way to define queries
46
+ */
47
+ export type QueryConditions<T extends Record<string, any> = Record<string, any>> = FilterCondition<T>[];
48
+ /**
49
+ * Build a SCIM 2.0 query string from conditions array
50
+ *
51
+ * @example
52
+ * ```typescript
53
+ * buildQuery<Person>([
54
+ * { field: 'name', op: 'eq', value: 'John' },
55
+ * { field: 'age', op: 'gt', value: 18, connector: 'and' },
56
+ * ])
57
+ * // → 'name eq "John" and age gt 18'
58
+ * ```
59
+ */
60
+ export declare function buildQuery<T extends Record<string, any>>(conditions: QueryConditions<T>): string;
61
+ /**
62
+ * Query Builder for SCIM 2.0 filtering
63
+ */
64
+ export declare class QueryFilter<T extends Record<string, any>> {
65
+ private parts;
66
+ /**
67
+ * Equal comparison
68
+ */
69
+ eq<K extends DeepKeyOf<T>>(field: K, value: Primitive): this;
70
+ /**
71
+ * Not equal comparison
72
+ */
73
+ ne<K extends DeepKeyOf<T>>(field: K, value: Primitive): this;
74
+ /**
75
+ * Greater than comparison
76
+ */
77
+ gt<K extends DeepKeyOf<T>>(field: K, value: number | string): this;
78
+ /**
79
+ * Greater than or equal comparison
80
+ */
81
+ ge<K extends DeepKeyOf<T>>(field: K, value: number | string): this;
82
+ /**
83
+ * Less than comparison
84
+ */
85
+ lt<K extends DeepKeyOf<T>>(field: K, value: number | string): this;
86
+ /**
87
+ * Less than or equal comparison
88
+ */
89
+ le<K extends DeepKeyOf<T>>(field: K, value: number | string): this;
90
+ /**
91
+ * Contains comparison (for strings)
92
+ */
93
+ co<K extends DeepKeyOf<T>>(field: K, value: string): this;
94
+ /**
95
+ * Starts with comparison (for strings)
96
+ */
97
+ sw<K extends DeepKeyOf<T>>(field: K, value: string): this;
98
+ /**
99
+ * Ends with comparison (for strings)
100
+ */
101
+ ew<K extends DeepKeyOf<T>>(field: K, value: string): this;
102
+ /**
103
+ * Present check (field has a value)
104
+ */
105
+ pr<K extends DeepKeyOf<T>>(field: K): this;
106
+ /**
107
+ * AND logical operator
108
+ */
109
+ and(): this;
110
+ /**
111
+ * OR logical operator
112
+ */
113
+ or(): this;
114
+ /**
115
+ * NOT logical operator
116
+ */
117
+ not(): this;
118
+ /**
119
+ * Group expressions with parentheses
120
+ */
121
+ group(builderFn: (qb: QueryFilter<T>) => QueryFilter<T>): this;
122
+ /**
123
+ * Add raw query string (use with caution)
124
+ */
125
+ raw(query: string): this;
126
+ /**
127
+ * Clear the query
128
+ */
129
+ clear(): this;
130
+ /**
131
+ * Build the final query string
132
+ */
133
+ build(): string;
134
+ /**
135
+ * Convert to string automatically (allows using builder without .build())
136
+ */
137
+ toString(): string;
138
+ /**
139
+ * Allow implicit string conversion
140
+ */
141
+ [Symbol.toPrimitive](hint: string): string | number;
142
+ /**
143
+ * Format value for SCIM 2.0 query
144
+ */
145
+ private formatValue;
146
+ }
147
+ /**
148
+ * Build a query string from conditions
149
+ *
150
+ * @example
151
+ * ```typescript
152
+ * // From conditions array
153
+ * query<Person>([
154
+ * { field: 'first_name', op: 'eq', value: 'John' },
155
+ * { field: 'age', op: 'gt', value: 18, connector: 'and' },
156
+ * ])
157
+ * // → 'first_name eq "John" and age gt 18'
158
+ *
159
+ * // Empty returns empty string
160
+ * query([]) // → ''
161
+ * ```
162
+ */
163
+ export declare function query<T extends Record<string, any>>(conditions: QueryConditions<T>): string;
164
+ /**
165
+ * Create a query that checks if any of the fields match the value
166
+ */
167
+ export declare function anyOf<T extends Record<string, any>>(fields: Array<DeepKeyOf<T> | string>, value: Primitive): string;
168
+ /**
169
+ * Create a range query (field >= min and field <= max)
170
+ */
171
+ export declare function range<T extends Record<string, any>>(field: DeepKeyOf<T> | string, min: number | string, max: number | string): string;
172
+ /**
173
+ * Create a search query across multiple string fields (OR)
174
+ */
175
+ export declare function search<T extends Record<string, any>>(fields: Array<DeepKeyOf<T> | string>, searchTerm: string): string;
176
+ export {};
177
+ //# sourceMappingURL=queryFilter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queryFilter.d.ts","sourceRoot":"","sources":["../../src/utils/queryFilter.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bagelink/vue",
3
3
  "type": "module",
4
- "version": "1.7.80",
4
+ "version": "1.7.84",
5
5
  "description": "Bagel core sdk packages",
6
6
  "author": {
7
7
  "name": "Bagel Studio",
@@ -0,0 +1,267 @@
1
+ <script setup lang="ts" generic="T extends Record<string, any>">
2
+ import type { ComparisonOperator, QueryConditions, FilterCondition, LogicalOperator } from '../utils/queryFilter'
3
+ import { Btn, DateInput, Dropdown, SelectInput, TextInput, type Option } from '@bagelink/vue'
4
+ import { computed } from 'vue'
5
+
6
+ type OptionsSource = Option[] | ((query: string) => Promise<Option[]>)
7
+
8
+ const props = defineProps<{
9
+ fields: Array<{
10
+ label: string
11
+ value: string
12
+ type?: 'string' | 'number' | 'boolean' | 'date'
13
+ options?: OptionsSource
14
+ }>
15
+ }>()
16
+
17
+ const emit = defineEmits<{
18
+ change: [value: QueryConditions<T>]
19
+ }>()
20
+
21
+ const model = defineModel<QueryConditions<T>>({ default: () => [] })
22
+
23
+ const allOperatorOptions: { label: string, value: ComparisonOperator }[] = [
24
+ { label: 'שווה ל', value: 'eq' },
25
+ { label: 'לא שווה ל', value: 'ne' },
26
+ { label: 'גדול מ', value: 'gt' },
27
+ { label: 'גדול או שווה ל', value: 'ge' },
28
+ { label: 'קטן מ', value: 'lt' },
29
+ { label: 'קטן או שווה ל', value: 'le' },
30
+ { label: 'מכיל', value: 'co' },
31
+ { label: 'מתחיל ב', value: 'sw' },
32
+ { label: 'מסתיים ב', value: 'ew' },
33
+ { label: 'קיים', value: 'pr' },
34
+ ]
35
+
36
+ const connectorOptions: { label: string, value: LogicalOperator }[] = [
37
+ { label: 'וגם', value: 'and' },
38
+ { label: 'או', value: 'or' },
39
+ ]
40
+
41
+ function getOperatorsForType(fieldType: string, hasOptions: boolean) {
42
+ if (hasOptions) {
43
+ return allOperatorOptions.filter(o => ['eq', 'ne', 'pr'].includes(o.value))
44
+ }
45
+ switch (fieldType) {
46
+ case 'boolean':
47
+ return allOperatorOptions.filter(o => ['eq', 'ne', 'pr'].includes(o.value))
48
+ case 'number':
49
+ case 'date':
50
+ return allOperatorOptions.filter(o => ['eq', 'ne', 'gt', 'ge', 'lt', 'le', 'pr'].includes(o.value))
51
+ default:
52
+ return allOperatorOptions.filter(o => ['eq', 'ne', 'co', 'sw', 'ew', 'pr'].includes(o.value))
53
+ }
54
+ }
55
+
56
+ function getFieldOptions(fieldValue: string): OptionsSource | undefined {
57
+ return props.fields.find(f => f.value === fieldValue)?.options
58
+ }
59
+
60
+ const booleanOptions = [
61
+ { label: 'כן', value: 'true' },
62
+ { label: 'לא', value: 'false' },
63
+ ]
64
+
65
+ function parseValue(value: any): any {
66
+ const str = String(value ?? '')
67
+ if (str === 'true') return true
68
+ if (str === 'false') return false
69
+ if (str === 'null') return null
70
+ if (str !== '' && !Number.isNaN(Number(str))) return Number(str)
71
+ return value
72
+ }
73
+
74
+ function updateCondition(index: number, updates: Partial<FilterCondition<T>>) {
75
+ const newConditions = [...model.value]
76
+ newConditions[index] = { ...newConditions[index], ...updates }
77
+
78
+ // Parse value if provided
79
+ if ('value' in updates) {
80
+ newConditions[index].value = parseValue(updates.value)
81
+ }
82
+
83
+ model.value = newConditions
84
+ emit('change', newConditions)
85
+ }
86
+
87
+ function addCondition() {
88
+ const field = props.fields[0]?.value || ''
89
+ const newCondition: FilterCondition<T> = {
90
+ field,
91
+ op: 'eq',
92
+ value: '',
93
+ connector: model.value.length > 0 ? 'and' : undefined,
94
+ }
95
+ const newConditions = [...model.value, newCondition]
96
+ model.value = newConditions
97
+ emit('change', newConditions)
98
+ }
99
+
100
+ function removeCondition(index: number) {
101
+ const newConditions = model.value.filter((_, i) => i !== index)
102
+ // Clear connector on first item
103
+ if (newConditions.length > 0 && newConditions[0].connector) {
104
+ newConditions[0] = { ...newConditions[0], connector: undefined }
105
+ }
106
+ model.value = newConditions
107
+ emit('change', newConditions)
108
+ }
109
+
110
+ function clearAll() {
111
+ model.value = []
112
+ emit('change', [])
113
+ }
114
+
115
+ function getFieldType(fieldValue: string): string {
116
+ return props.fields.find(f => f.value === fieldValue)?.type || 'string'
117
+ }
118
+
119
+ function needsValue(op: ComparisonOperator): boolean {
120
+ return op !== 'pr'
121
+ }
122
+
123
+ function displayValue(value: any): string {
124
+ if (value === null) return 'null'
125
+ if (value === true) return 'true'
126
+ if (value === false) return 'false'
127
+ return String(value ?? '')
128
+ }
129
+
130
+ const activeFiltersCount = computed(() => {
131
+ return model.value.filter(c => c.field !== '' && (c.op === 'pr' || (c.value !== undefined && c.value !== ''))).length
132
+ })
133
+ </script>
134
+
135
+ <template>
136
+ <Dropdown
137
+ flat placement="bottom-start" icon="filter_alt"
138
+ :value="activeFiltersCount > 0 ? `פילטר (${activeFiltersCount})` : 'פילטר'" thin :auto-hide="false"
139
+ >
140
+ <div class="filter-builder">
141
+ <TransitionGroup name="condition">
142
+ <div
143
+ v-for="(condition, index) in model" :key="index" class="flex gap-05 bg-gray-20 rounded p-025"
144
+ :class="condition.connector === 'or' ? 'mt-05' : ''"
145
+ >
146
+ <!-- Connector (AND/OR) -->
147
+ <SelectInput
148
+ v-if="index > 0" :model-value="condition.connector" :options="connectorOptions"
149
+ style="width: 75px"
150
+ @update:model-value="(v: LogicalOperator) => updateCondition(index, { connector: v })"
151
+ />
152
+ <div v-else-if="model.length > 1" style="width: 100px" />
153
+
154
+ <!-- Field selector -->
155
+ <SelectInput
156
+ :model-value="condition.field" :options="fields" placeholder="בחר שדה" class="field-select"
157
+ @update:model-value="(v: string) => updateCondition(index, { field: v })"
158
+ />
159
+
160
+ <!-- Operator selector -->
161
+ <SelectInput
162
+ :model-value="condition.op"
163
+ :options="getOperatorsForType(getFieldType(condition.field as string), !!getFieldOptions(condition.field as string))"
164
+ class="operator-select"
165
+ @update:model-value="(v: ComparisonOperator) => updateCondition(index, { op: v })"
166
+ />
167
+
168
+ <!-- Value input - type-specific -->
169
+ <template v-if="needsValue(condition.op)">
170
+ <SelectInput
171
+ v-if="getFieldOptions(condition.field as string)" :model-value="displayValue(condition.value)"
172
+ :options="getFieldOptions(condition.field as string)!" placeholder="בחר" class="value-input" searchable
173
+ @update:model-value="(v: string) => updateCondition(index, { value: v })"
174
+ />
175
+ <SelectInput
176
+ v-else-if="getFieldType(condition.field as string) === 'boolean'"
177
+ :model-value="displayValue(condition.value)" :options="booleanOptions" placeholder="בחר"
178
+ class="value-input" @update:model-value="(v: string) => updateCondition(index, { value: v })"
179
+ />
180
+ <DateInput
181
+ v-else-if="getFieldType(condition.field as string) === 'date'"
182
+ :model-value="displayValue(condition.value)" placeholder="בחר תאריך" class="value-input"
183
+ @update:model-value="(v: any) => updateCondition(index, { value: String(v) })"
184
+ />
185
+ <TextInput
186
+ v-else-if="getFieldType(condition.field as string) === 'number'"
187
+ :model-value="displayValue(condition.value)" placeholder="0" type="number" class="value-input"
188
+ @update:model-value="(v: string) => updateCondition(index, { value: v })"
189
+ />
190
+ <TextInput
191
+ v-else :model-value="displayValue(condition.value)" placeholder="ערך" class="value-input"
192
+ @update:model-value="(v: string) => updateCondition(index, { value: v })"
193
+ />
194
+ </template>
195
+ <div v-else class="value-placeholder" />
196
+
197
+ <!-- Remove button -->
198
+ <Btn icon="close" flat round thin color="gray" @click="removeCondition(index)" />
199
+ </div>
200
+ </TransitionGroup>
201
+
202
+ <div class="flex gap-05 mt-075">
203
+ <Btn icon="add" flat thin value="הוסף תנאי" @click="addCondition" />
204
+ <Btn v-if="model.length > 0" icon="delete_sweep" flat thin color="gray" value="נקה הכל" @click="clearAll" />
205
+ </div>
206
+ </div>
207
+ </Dropdown>
208
+ </template>
209
+
210
+ <style scoped>
211
+ .filter-builder {
212
+ --input-font-size: 12px;
213
+ --input-height: 30px;
214
+ /* --input-border-radius: 100px; */
215
+ /* --input-bg: var(--bgl-primary-light); */
216
+ /* --input-color: var(--bgl-primary); */
217
+ min-width: 520px;
218
+ max-width: 90vw;
219
+ padding: 0.5rem;
220
+ }
221
+
222
+ .field-select {
223
+ flex: 1;
224
+ min-width: 120px;
225
+ margin: 0;
226
+ }
227
+
228
+ .operator-select {
229
+ min-width: 120px;
230
+ margin: 0;
231
+ }
232
+
233
+ .value-input {
234
+ flex: 1;
235
+ min-width: 100px;
236
+ margin: 0;
237
+ }
238
+
239
+ .value-placeholder {
240
+ flex: 1;
241
+ min-width: 100px;
242
+ }
243
+
244
+ /* Transition animations */
245
+ .condition-enter-active,
246
+ .condition-leave-active {
247
+ transition: all 0.25s ease;
248
+ }
249
+
250
+ .condition-enter-from {
251
+ opacity: 0;
252
+ transform: translateX(-10px);
253
+ }
254
+
255
+ .condition-leave-to {
256
+ opacity: 0;
257
+ transform: translateX(10px);
258
+ }
259
+
260
+ :dir(rtl) .condition-enter-from {
261
+ transform: translateX(10px);
262
+ }
263
+
264
+ :dir(rtl) .condition-leave-to {
265
+ transform: translateX(-10px);
266
+ }
267
+ </style>
@@ -19,6 +19,7 @@ export { Draggable, useDraggable, vDraggable } from './draggable'
19
19
  export { default as DragOver } from './DragOver.vue'
20
20
  export { default as Dropdown } from './Dropdown.vue'
21
21
  export { default as FieldSetVue } from './FieldSetVue.vue'
22
+ export { default as Filter } from './Filter.vue'
22
23
  export { default as Flag } from './Flag.vue'
23
24
  export * from './form'
24
25
  export { default as Icon } from './Icon/Icon.vue'
@@ -120,6 +120,18 @@
120
120
  object-fit: scale-down;
121
121
  }
122
122
 
123
+ .object-position-top {
124
+ object-position: top;
125
+ }
126
+
127
+ .object-position-center {
128
+ object-position: center;
129
+ }
130
+
131
+ .object-position-bottom {
132
+ object-position: bottom;
133
+ }
134
+
123
135
  .shadow-10 {
124
136
  box-shadow: 0 0 10px 0 var(--bgl-shadow) !important;
125
137
  }
@@ -435,6 +447,18 @@
435
447
  object-fit: scale-down;
436
448
  }
437
449
 
450
+ .m_object-position-top {
451
+ object-position: top;
452
+ }
453
+
454
+ .m_object-position-center {
455
+ object-position: center;
456
+ }
457
+
458
+ .m_object-position-bottom {
459
+ object-position: bottom;
460
+ }
461
+
438
462
  .m_shadow-light {
439
463
  box-shadow: 0 1px 5px 0 rgba(0, 0, 0, .1), 0 1px 2px -1px rgba(0, 0, 0, .1) !important;
440
464
  }