@warkypublic/svelix 0.1.14 → 0.1.15

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.
@@ -90,6 +90,7 @@
90
90
  let popupWidth = $state(0);
91
91
  let backdropZ = $state(1090);
92
92
  let dropdownZ = $state(1100);
93
+ let pointerInteractingWithDropdown = $state(false);
93
94
  // Plain variable — NOT $state to avoid deep proxy on the complex virtualizer object.
94
95
  let rawVirtualizer: SvelteVirtualizer<
95
96
  HTMLDivElement,
@@ -334,6 +335,13 @@
334
335
  );
335
336
  }
336
337
 
338
+ function markDropdownPointerInteraction() {
339
+ pointerInteractingWithDropdown = true;
340
+ setTimeout(() => {
341
+ pointerInteractingWithDropdown = false;
342
+ }, 0);
343
+ }
344
+
337
345
  // Public API via bind:this
338
346
  export function clear() {
339
347
  onClear();
@@ -403,6 +411,7 @@
403
411
  class="relative w-full"
404
412
  bind:this={anchorEl}
405
413
  onfocusout={(e) => {
414
+ if (pointerInteractingWithDropdown) return;
406
415
  const currentTarget = e.currentTarget as HTMLElement;
407
416
  const relatedTarget = e.relatedTarget as Node | null;
408
417
  const insideDropdown = !!(relatedTarget && dropdownEl?.contains(relatedTarget));
@@ -452,6 +461,7 @@
452
461
  : "fixed"} card bg-surface-50-950 shadow-lg border border-surface-300-700 overflow-hidden`}
453
462
  role="listbox"
454
463
  aria-label={label ?? "Options"}
464
+ onpointerdown={markDropdownPointerInteraction}
455
465
  style:z-index={dropdownZ}
456
466
  style:top={!disablePortal ? `${popupTop}px` : undefined}
457
467
  style:left={!disablePortal ? `${popupLeft}px` : undefined}
@@ -8,6 +8,7 @@
8
8
  import NativeSelectCtrl from '../FormerControllers/NativeSelectCtrl.svelte';
9
9
  import TextAreaCtrl from '../FormerControllers/TextAreaCtrl.svelte';
10
10
  import SwitchCtrl from '../FormerControllers/SwitchCtrl.svelte';
11
+ import Boxer from '../Boxer/Boxer.svelte';
11
12
 
12
13
  interface UserForm {
13
14
  id?: number;
@@ -18,6 +19,7 @@
18
19
  age?: number;
19
20
  role: string;
20
21
  department: string;
22
+ skills: string[];
21
23
  bio: string;
22
24
  website: string;
23
25
  emailNotifications: boolean;
@@ -38,6 +40,7 @@
38
40
  age: undefined,
39
41
  role: '',
40
42
  department: '',
43
+ skills: [],
41
44
  bio: '',
42
45
  website: '',
43
46
  emailNotifications: true,
@@ -53,6 +56,7 @@
53
56
  age: 32,
54
57
  role: 'admin',
55
58
  department: 'engineering',
59
+ skills: ['typescript', 'svelte'],
56
60
  bio: 'Senior software engineer with 10 years of experience building scalable systems.',
57
61
  website: 'https://janesmith.dev',
58
62
  emailNotifications: true,
@@ -73,6 +77,14 @@
73
77
  { label: 'Operations', value: 'operations' },
74
78
  ];
75
79
 
80
+ const skillOptions = [
81
+ { label: 'Svelte', value: 'svelte' },
82
+ { label: 'TypeScript', value: 'typescript' },
83
+ { label: 'Node.js', value: 'nodejs' },
84
+ { label: 'Testing', value: 'testing' },
85
+ { label: 'UX', value: 'ux' },
86
+ ];
87
+
76
88
  let values = $state<UserForm>(request === 'insert' ? { ...emptyUser } : { ...filledUser });
77
89
  let lastSaved = $state<UserForm | undefined>(undefined);
78
90
  let opened = $state(false);
@@ -194,6 +206,25 @@
194
206
  />
195
207
  </div>
196
208
 
209
+ <Boxer
210
+ label="Skills"
211
+ name="skills"
212
+ data={skillOptions}
213
+ dataSource="local"
214
+ disablePortal
215
+ multiSelect
216
+ searchable
217
+ clearable
218
+ placeholder="Search skills..."
219
+ disabled={isReadonly}
220
+ value={state.values?.skills ?? []}
221
+ onChange={(v) =>
222
+ state.setState('values', {
223
+ ...state.values,
224
+ skills: Array.isArray(v) ? v : v ? [v] : [],
225
+ })}
226
+ />
227
+
197
228
  <TextAreaCtrl
198
229
  label="Bio"
199
230
  name="bio"
@@ -8,6 +8,7 @@
8
8
  import NativeSelectCtrl from '../FormerControllers/NativeSelectCtrl.svelte';
9
9
  import TextAreaCtrl from '../FormerControllers/TextAreaCtrl.svelte';
10
10
  import SwitchCtrl from '../FormerControllers/SwitchCtrl.svelte';
11
+ import Boxer from '../Boxer/Boxer.svelte';
11
12
 
12
13
  interface UserForm {
13
14
  id?: number;
@@ -18,6 +19,7 @@
18
19
  age?: number;
19
20
  role: string;
20
21
  department: string;
22
+ skills: string[];
21
23
  bio: string;
22
24
  website: string;
23
25
  emailNotifications: boolean;
@@ -38,6 +40,7 @@
38
40
  age: undefined,
39
41
  role: '',
40
42
  department: '',
43
+ skills: [],
41
44
  bio: '',
42
45
  website: '',
43
46
  emailNotifications: true,
@@ -53,6 +56,7 @@
53
56
  age: 32,
54
57
  role: 'admin',
55
58
  department: 'engineering',
59
+ skills: ['typescript', 'svelte'],
56
60
  bio: 'Senior software engineer with 10 years of experience building scalable systems.',
57
61
  website: 'https://janesmith.dev',
58
62
  emailNotifications: true,
@@ -73,6 +77,14 @@
73
77
  { label: 'Operations', value: 'operations' },
74
78
  ];
75
79
 
80
+ const skillOptions = [
81
+ { label: 'Svelte', value: 'svelte' },
82
+ { label: 'TypeScript', value: 'typescript' },
83
+ { label: 'Node.js', value: 'nodejs' },
84
+ { label: 'Testing', value: 'testing' },
85
+ { label: 'UX', value: 'ux' },
86
+ ];
87
+
76
88
  let values = $state<UserForm>(request === 'insert' ? { ...emptyUser } : { ...filledUser });
77
89
  let lastSaved = $state<UserForm | undefined>(undefined);
78
90
  let opened = $state(false);
@@ -194,6 +206,24 @@
194
206
  />
195
207
  </div>
196
208
 
209
+ <Boxer
210
+ label="Skills"
211
+ name="skills"
212
+ data={skillOptions}
213
+ dataSource="local"
214
+ multiSelect
215
+ searchable
216
+ clearable
217
+ placeholder="Search skills..."
218
+ disabled={isReadonly}
219
+ value={state.values?.skills ?? []}
220
+ onChange={(v) =>
221
+ state.setState('values', {
222
+ ...state.values,
223
+ skills: Array.isArray(v) ? v : v ? [v] : [],
224
+ })}
225
+ />
226
+
197
227
  <TextAreaCtrl
198
228
  label="Bio"
199
229
  name="bio"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@warkypublic/svelix",
3
- "version": "0.1.14",
3
+ "version": "0.1.15",
4
4
  "description": "Svelte 5 component library with Skeleton UI and Tailwind CSS",
5
5
  "license": "Apache-2.0",
6
6
  "exports": {