compote-ui 0.61.0 → 0.61.1

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.
@@ -1,6 +1,7 @@
1
1
  <script lang="ts">
2
2
  import { Select } from '@ark-ui/svelte/select';
3
3
  import { Portal } from '@ark-ui/svelte/portal';
4
+ import { useFilter } from '@ark-ui/svelte/locale';
4
5
  import { TelInput, countries } from 'svelte-tel-input';
5
6
  import type { CountryCode } from 'svelte-tel-input/types';
6
7
  import type { PhoneInputProps } from './types';
@@ -22,28 +23,35 @@
22
23
  flagClass: `flag-${c.iso2.toLowerCase()}`,
23
24
  dialCode: c.dialCode
24
25
  }));
25
- const collection = createListCollection(countryItems);
26
+ const baseCollection = createListCollection(countryItems);
27
+
28
+ let filterText = $state('');
29
+ const filters = useFilter({ sensitivity: 'base' });
30
+ const collection = $derived(
31
+ filterText
32
+ ? baseCollection.filter((label) => filters().contains(label, filterText))
33
+ : baseCollection
34
+ );
26
35
 
27
36
  let {
28
37
  value = $bindable(''),
29
38
  country = $bindable(null),
30
39
  valid = $bindable(false),
31
40
  label,
32
- placeholder,
33
- name,
34
41
  layout = 'vertical',
35
42
  disabled,
36
43
  readonly,
37
44
  invalid,
38
45
  required,
39
46
  class: className,
40
- options
47
+ ...restProps
41
48
  }: PhoneInputProps = $props();
42
49
 
43
50
  const id = $props.id();
44
51
  const numberId = `${id}-number`;
45
52
 
46
53
  const selectedItem = $derived(countryItems.find((c) => c.value === country));
54
+ const showInvalid = $derived(invalid ?? (value.length > 0 && !valid));
47
55
 
48
56
  const rootClass = $derived(
49
57
  layout === 'horizontal'
@@ -63,7 +71,7 @@
63
71
  class={cn(
64
72
  'flex h-9 w-full items-center rounded-md border bg-surface-1 shadow-sm transition-shadow focus-within:ring-1 focus-within:ring-ring',
65
73
  'data-disabled:cursor-not-allowed data-disabled:opacity-50',
66
- invalid && 'border-danger focus-within:ring-danger',
74
+ showInvalid && 'border-danger focus-within:ring-danger',
67
75
  className
68
76
  )}
69
77
  data-disabled={disabled ? '' : undefined}
@@ -74,6 +82,9 @@
74
82
  onValueChange={(details) => {
75
83
  country = (details.items[0]?.value as CountryCode | undefined) ?? null;
76
84
  }}
85
+ onOpenChange={(details) => {
86
+ if (!details.open) filterText = '';
87
+ }}
77
88
  {disabled}
78
89
  readOnly={readonly}
79
90
  class="h-9 shrink-0"
@@ -87,7 +98,6 @@
87
98
  <span
88
99
  class="flag {selectedItem.flagClass} shrink-0 rounded-xs shadow-[inset_0_0_0_1px_var(--compote-border)]"
89
100
  ></span>
90
- <span class="font-medium tabular-nums">+{selectedItem.dialCode}</span>
91
101
  {:else}
92
102
  <span class="text-ink-dim">Country</span>
93
103
  {/if}
@@ -97,22 +107,33 @@
97
107
  <Portal>
98
108
  <Select.Positioner>
99
109
  <Select.Content
100
- class="z-200 max-h-60 min-w-52 overflow-auto rounded-md border bg-surface-document p-1 shadow-md data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95"
110
+ class="z-200 flex max-h-72 min-w-52 flex-col overflow-hidden rounded-md border bg-surface-document p-1 shadow-md data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95"
101
111
  >
102
- {#each countryItems as item (item.value)}
103
- <Select.Item
104
- {item}
105
- class="relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm text-ink transition-colors select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-highlighted:bg-surface-1 data-[state=checked]:bg-surface-1"
106
- >
107
- <span
108
- class="flag {item.flagClass} shrink-0 rounded-xs shadow-[inset_0_0_0_1px_var(--compote-border)]"
109
- ></span>
110
- <Select.ItemText class="flex-1 truncate">{item.label}</Select.ItemText>
111
- <Select.ItemIndicator class="absolute right-2 flex items-center justify-center">
112
- <PhCheck class="size-3.5" />
113
- </Select.ItemIndicator>
114
- </Select.Item>
115
- {/each}
112
+ <input
113
+ type="text"
114
+ bind:value={filterText}
115
+ placeholder="Search"
116
+ class="mb-1 shrink-0 rounded-sm border bg-surface-1 px-2 py-1 text-sm outline-none focus:ring-1 focus:ring-ring"
117
+ onkeydown={(e) => e.stopPropagation()}
118
+ />
119
+ <div class="overflow-auto">
120
+ {#each collection.items as item (item.value)}
121
+ <Select.Item
122
+ {item}
123
+ class="relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm text-ink transition-colors select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-highlighted:bg-surface-1 data-[state=checked]:bg-surface-1"
124
+ >
125
+ <span
126
+ class="flag {item.flagClass} shrink-0 rounded-xs shadow-[inset_0_0_0_1px_var(--compote-border)]"
127
+ ></span>
128
+ <Select.ItemText class="flex-1 truncate">{item.label}</Select.ItemText>
129
+ <Select.ItemIndicator class="absolute right-2 flex items-center justify-center">
130
+ <PhCheck class="size-3.5" />
131
+ </Select.ItemIndicator>
132
+ </Select.Item>
133
+ {:else}
134
+ <div class="py-2 text-center text-sm text-ink-dim">No results found</div>
135
+ {/each}
136
+ </div>
116
137
  </Select.Content>
117
138
  </Select.Positioner>
118
139
  </Portal>
@@ -122,12 +143,10 @@
122
143
  bind:value
123
144
  bind:country
124
145
  bind:valid
125
- {name}
126
- {placeholder}
127
146
  {disabled}
128
147
  {readonly}
129
148
  {required}
130
- {options}
149
+ {...restProps}
131
150
  class="h-full min-w-0 flex-1 bg-transparent px-3 text-sm outline-none placeholder:text-ink-dim disabled:cursor-not-allowed"
132
151
  />
133
152
  </div>
@@ -1,16 +1,9 @@
1
- import type { CountryCode, TelInputOptions } from 'svelte-tel-input/types';
2
- export interface PhoneInputProps {
1
+ import type { Props as TelInputProps } from 'svelte-tel-input/types';
2
+ export interface PhoneInputProps extends Omit<TelInputProps, 'value' | 'class' | 'id' | 'readonly'> {
3
3
  value?: string;
4
- country?: CountryCode | null;
5
- valid?: boolean;
6
4
  label?: string;
7
- placeholder?: string;
8
- name?: string;
9
5
  layout?: 'vertical' | 'horizontal';
10
- disabled?: boolean;
11
6
  readonly?: boolean;
12
7
  invalid?: boolean;
13
- required?: boolean;
14
8
  class?: string;
15
- options?: TelInputOptions;
16
9
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "compote-ui",
3
- "version": "0.61.0",
3
+ "version": "0.61.1",
4
4
  "license": "MIT",
5
5
  "scripts": {
6
6
  "dev": "vite dev --open",