@djangocfg/ui-core 2.1.382 → 2.1.384

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 (61) hide show
  1. package/package.json +5 -12
  2. package/src/components/boundary/boundary.story.tsx +0 -191
  3. package/src/components/data/avatar/avatar.story.tsx +0 -115
  4. package/src/components/data/badge/badge.story.tsx +0 -56
  5. package/src/components/data/calendar/calendar.story.tsx +0 -127
  6. package/src/components/data/carousel/carousel.story.tsx +0 -122
  7. package/src/components/data/progress/progress.story.tsx +0 -97
  8. package/src/components/data/table/table.story.tsx +0 -148
  9. package/src/components/data/toggle/toggle.story.tsx +0 -104
  10. package/src/components/data/toggle-group/toggle-group.story.tsx +0 -118
  11. package/src/components/feedback/alert/alert.story.tsx +0 -77
  12. package/src/components/feedback/empty/empty.story.tsx +0 -115
  13. package/src/components/feedback/preloader/preloader.story.tsx +0 -86
  14. package/src/components/feedback/spinner/spinner.story.tsx +0 -66
  15. package/src/components/forms/button/button.story.tsx +0 -116
  16. package/src/components/forms/button-download/button-download.story.tsx +0 -112
  17. package/src/components/forms/button-group/button-group.story.tsx +0 -79
  18. package/src/components/forms/checkbox/checkbox.story.tsx +0 -89
  19. package/src/components/forms/input/input.story.tsx +0 -77
  20. package/src/components/forms/input-group/input-group.story.tsx +0 -119
  21. package/src/components/forms/input-otp/input-otp.story.tsx +0 -105
  22. package/src/components/forms/label/label.story.tsx +0 -52
  23. package/src/components/forms/radio-group/radio-group.story.tsx +0 -113
  24. package/src/components/forms/slider/slider.story.tsx +0 -134
  25. package/src/components/forms/switch/switch.story.tsx +0 -98
  26. package/src/components/forms/textarea/textarea.story.tsx +0 -94
  27. package/src/components/layout/aspect-ratio/aspect-ratio.story.tsx +0 -94
  28. package/src/components/layout/card/card.story.tsx +0 -105
  29. package/src/components/layout/resizable/resizable.story.tsx +0 -119
  30. package/src/components/layout/scroll-area/scroll-area.story.tsx +0 -172
  31. package/src/components/layout/separator/separator.story.tsx +0 -69
  32. package/src/components/layout/skeleton/skeleton.story.tsx +0 -101
  33. package/src/components/navigation/accordion/accordion.story.tsx +0 -110
  34. package/src/components/navigation/collapsible/collapsible.story.tsx +0 -133
  35. package/src/components/navigation/command/command.story.tsx +0 -121
  36. package/src/components/navigation/context-menu/context-menu.story.tsx +0 -125
  37. package/src/components/navigation/dropdown-menu/dropdown-menu.story.tsx +0 -208
  38. package/src/components/navigation/menubar/menubar.story.tsx +0 -152
  39. package/src/components/navigation/navigation-menu/navigation-menu.story.tsx +0 -154
  40. package/src/components/navigation/tabs/tabs.story.tsx +0 -98
  41. package/src/components/overlay/alert-dialog/alert-dialog.story.tsx +0 -104
  42. package/src/components/overlay/dialog/dialog.story.tsx +0 -212
  43. package/src/components/overlay/drawer/drawer.story.tsx +0 -359
  44. package/src/components/overlay/hover-card/hover-card.story.tsx +0 -102
  45. package/src/components/overlay/popover/popover.story.tsx +0 -127
  46. package/src/components/overlay/responsive-sheet/responsive-sheet.story.tsx +0 -117
  47. package/src/components/overlay/sheet/sheet.story.tsx +0 -148
  48. package/src/components/overlay/tooltip/tooltip.story.tsx +0 -139
  49. package/src/components/select/combobox-async.story.tsx +0 -215
  50. package/src/components/select/combobox.story.tsx +0 -226
  51. package/src/components/select/country-select.story.tsx +0 -261
  52. package/src/components/select/language-select.story.tsx +0 -264
  53. package/src/components/select/multi-select.story.tsx +0 -122
  54. package/src/components/select/select.story.tsx +0 -112
  55. package/src/components/specialized/copy/copy.story.tsx +0 -77
  56. package/src/components/specialized/flag/flag.story.tsx +0 -82
  57. package/src/components/specialized/image-with-fallback/image-with-fallback.story.tsx +0 -105
  58. package/src/components/specialized/kbd/kbd.story.tsx +0 -113
  59. package/src/lib/dialog-service/dialog-service.story.tsx +0 -263
  60. package/src/stories/index.ts +0 -28
  61. package/src/styles/theme/theme-tokens.story.tsx +0 -157
@@ -1,215 +0,0 @@
1
- import { useEffect, useMemo, useState } from 'react';
2
-
3
- import { defineStory, useBoolean } from '@djangocfg/playground';
4
-
5
- import { ComboboxAsync, type ComboboxAsyncOption } from '.';
6
- import { Label } from '../forms/label';
7
-
8
- export default defineStory({
9
- title: 'Core/ComboboxAsync',
10
- component: ComboboxAsync,
11
- description:
12
- 'Single-select combobox where the parent owns search + loading. Pairs with `MultiSelectProAsync` for the "pick one" case against a server-side typeahead endpoint.',
13
- });
14
-
15
- // ─── Fake "server" ──────────────────────────────────────────────────
16
- //
17
- // In real usage, ``options`` would come from an SWR / RQ hook keyed off
18
- // the debounced search value. For the playground we simulate latency
19
- // with a setTimeout so the loading affordance and seedOptions story
20
- // can be exercised without a real backend.
21
-
22
- interface Person {
23
- id: string;
24
- name: string;
25
- email: string;
26
- team: string;
27
- }
28
-
29
- const PEOPLE: Person[] = [
30
- { id: 'p-1', name: 'Alice Lee', email: 'alice@x.co', team: 'Platform' },
31
- { id: 'p-2', name: 'Bob Schmidt', email: 'bob@x.co', team: 'Platform' },
32
- { id: 'p-3', name: 'Carla Romero', email: 'carla@x.co', team: 'Growth' },
33
- { id: 'p-4', name: 'Dmitri Volkov', email: 'dmitri@x.co', team: 'Growth' },
34
- { id: 'p-5', name: 'Evelyn Park', email: 'evelyn@x.co', team: 'Design' },
35
- { id: 'p-6', name: 'Farah Patel', email: 'farah@x.co', team: 'Design' },
36
- { id: 'p-7', name: 'Greta Hahn', email: 'greta@x.co', team: 'Engineering' },
37
- { id: 'p-8', name: 'Hiro Tanaka', email: 'hiro@x.co', team: 'Engineering' },
38
- ];
39
-
40
- function fakeSearch(query: string): Promise<Person[]> {
41
- return new Promise((resolve) => {
42
- const q = query.trim().toLowerCase();
43
- const matches = q
44
- ? PEOPLE.filter(
45
- (p) =>
46
- p.name.toLowerCase().includes(q) ||
47
- p.email.toLowerCase().includes(q) ||
48
- p.team.toLowerCase().includes(q),
49
- )
50
- : PEOPLE.slice(0, 6);
51
- setTimeout(() => resolve(matches), 350);
52
- });
53
- }
54
-
55
- function toOption(p: Person): ComboboxAsyncOption {
56
- return {
57
- value: p.id,
58
- label: p.name,
59
- description: `${p.email} · ${p.team}`,
60
- };
61
- }
62
-
63
- // ─── Stories ────────────────────────────────────────────────────────
64
-
65
- export const Interactive = () => {
66
- const [value, setValue] = useState<string | null>(null);
67
- const [search, setSearch] = useState('');
68
- const [options, setOptions] = useState<ComboboxAsyncOption[]>([]);
69
- const [isLoading, setIsLoading] = useState(false);
70
- const [disabled] = useBoolean('disabled', {
71
- defaultValue: false,
72
- label: 'Disabled',
73
- description: 'Disable picker',
74
- });
75
- const [clearable] = useBoolean('clearable', {
76
- defaultValue: true,
77
- label: 'Clearable',
78
- description: 'Show inline × to reset selection',
79
- });
80
-
81
- useEffect(() => {
82
- let cancelled = false;
83
- setIsLoading(true);
84
- void fakeSearch(search).then((rows) => {
85
- if (cancelled) return;
86
- setOptions(rows.map(toOption));
87
- setIsLoading(false);
88
- });
89
- return () => {
90
- cancelled = true;
91
- };
92
- }, [search]);
93
-
94
- return (
95
- <div className="max-w-sm space-y-2">
96
- <Label>Assignee</Label>
97
- <ComboboxAsync
98
- options={options}
99
- value={value}
100
- onValueChange={setValue}
101
- searchValue={search}
102
- onSearchChange={setSearch}
103
- isLoading={isLoading}
104
- placeholder="Pick a teammate…"
105
- searchPlaceholder="Search by name, email, team…"
106
- emptyText="No teammates found"
107
- loadingText="Searching…"
108
- disabled={disabled}
109
- clearable={clearable}
110
- />
111
- <p className="text-xs text-muted-foreground">
112
- Selected: {value ?? '∅'}
113
- </p>
114
- </div>
115
- );
116
- };
117
-
118
- export const Default = Interactive;
119
-
120
- export const Loading = () => {
121
- // Force ``isLoading`` true and an empty options list to show the
122
- // initial spinner state — the same row that renders before the
123
- // first server response lands.
124
- const [value, setValue] = useState<string | null>(null);
125
- const [search, setSearch] = useState('');
126
-
127
- return (
128
- <div className="max-w-sm space-y-2">
129
- <Label>Assignee</Label>
130
- <ComboboxAsync
131
- options={[]}
132
- value={value}
133
- onValueChange={setValue}
134
- searchValue={search}
135
- onSearchChange={setSearch}
136
- isLoading
137
- placeholder="Pick a teammate…"
138
- />
139
- </div>
140
- );
141
- };
142
-
143
- export const Empty = () => {
144
- // Loaded but no matches — distinct visual from the loading row above.
145
- const [value, setValue] = useState<string | null>(null);
146
-
147
- return (
148
- <div className="max-w-sm space-y-2">
149
- <Label>Assignee</Label>
150
- <ComboboxAsync
151
- options={[]}
152
- value={value}
153
- onValueChange={setValue}
154
- searchValue="zzznoresult"
155
- onSearchChange={() => {}}
156
- isLoading={false}
157
- emptyText="No teammates found"
158
- />
159
- </div>
160
- );
161
- };
162
-
163
- export const SeedOption = () => {
164
- // The dialog opens with a pre-existing value whose row isn't part of
165
- // the live results. ``seedOptions`` keeps the trigger from rendering
166
- // a raw id while the user starts typing.
167
- const [value, setValue] = useState<string | null>('p-stale');
168
- const [search, setSearch] = useState('');
169
- const [options, setOptions] = useState<ComboboxAsyncOption[]>([]);
170
- const [isLoading, setIsLoading] = useState(false);
171
-
172
- useEffect(() => {
173
- let cancelled = false;
174
- setIsLoading(true);
175
- void fakeSearch(search).then((rows) => {
176
- if (cancelled) return;
177
- setOptions(rows.map(toOption));
178
- setIsLoading(false);
179
- });
180
- return () => {
181
- cancelled = true;
182
- };
183
- }, [search]);
184
-
185
- const seedOptions = useMemo<ComboboxAsyncOption[]>(
186
- () => [
187
- {
188
- value: 'p-stale',
189
- label: 'Pre-selected (offline)',
190
- description: 'Fetched once, kept around as a seed',
191
- },
192
- ],
193
- [],
194
- );
195
-
196
- return (
197
- <div className="max-w-sm space-y-2">
198
- <Label>Assignee</Label>
199
- <ComboboxAsync
200
- options={options}
201
- value={value}
202
- onValueChange={setValue}
203
- searchValue={search}
204
- onSearchChange={setSearch}
205
- isLoading={isLoading}
206
- seedOptions={seedOptions}
207
- placeholder="Pick a teammate…"
208
- />
209
- <p className="text-xs text-muted-foreground">
210
- Selected id: <code>{value ?? '∅'}</code> — note the trigger shows the
211
- seed label even though <code>p-stale</code> isn't in the search results.
212
- </p>
213
- </div>
214
- );
215
- };
@@ -1,226 +0,0 @@
1
- import { useState } from 'react';
2
- import { defineStory, useBoolean } from '@djangocfg/playground';
3
- import { Combobox, type ComboboxOption } from '.';
4
- import { Label } from '../forms/label';
5
-
6
- export default defineStory({
7
- title: 'Core/Combobox',
8
- component: Combobox,
9
- description: 'Searchable select with autocomplete.',
10
- });
11
-
12
- const frameworks: ComboboxOption[] = [
13
- { value: 'next.js', label: 'Next.js' },
14
- { value: 'sveltekit', label: 'SvelteKit' },
15
- { value: 'nuxt.js', label: 'Nuxt.js' },
16
- { value: 'remix', label: 'Remix' },
17
- { value: 'astro', label: 'Astro' },
18
- ];
19
-
20
- const countries: ComboboxOption[] = [
21
- { value: 'us', label: 'United States' },
22
- { value: 'uk', label: 'United Kingdom' },
23
- { value: 'de', label: 'Germany' },
24
- { value: 'fr', label: 'France' },
25
- { value: 'jp', label: 'Japan' },
26
- { value: 'kr', label: 'South Korea' },
27
- { value: 'cn', label: 'China' },
28
- { value: 'au', label: 'Australia' },
29
- { value: 'ca', label: 'Canada' },
30
- { value: 'br', label: 'Brazil' },
31
- ];
32
-
33
- export const Interactive = () => {
34
- const [value, setValue] = useState('');
35
- const [disabled] = useBoolean('disabled', {
36
- defaultValue: false,
37
- label: 'Disabled',
38
- description: 'Disable combobox',
39
- });
40
-
41
- return (
42
- <div className="max-w-xs space-y-2">
43
- <Label>Framework</Label>
44
- <Combobox
45
- options={frameworks}
46
- value={value}
47
- onValueChange={setValue}
48
- placeholder="Select framework..."
49
- searchPlaceholder="Search framework..."
50
- emptyText="No framework found."
51
- disabled={disabled}
52
- />
53
- </div>
54
- );
55
- };
56
-
57
- export const Default = () => {
58
- const [value, setValue] = useState('');
59
-
60
- return (
61
- <div className="max-w-xs">
62
- <Combobox
63
- options={frameworks}
64
- value={value}
65
- onValueChange={setValue}
66
- placeholder="Select framework..."
67
- searchPlaceholder="Search framework..."
68
- emptyText="No framework found."
69
- />
70
- </div>
71
- );
72
- };
73
-
74
- export const WithDefaultValue = () => {
75
- const [value, setValue] = useState('next.js');
76
-
77
- return (
78
- <div className="max-w-xs">
79
- <Combobox
80
- options={frameworks}
81
- value={value}
82
- onValueChange={setValue}
83
- placeholder="Select framework..."
84
- />
85
- </div>
86
- );
87
- };
88
-
89
- export const Countries = () => {
90
- const [value, setValue] = useState('');
91
-
92
- return (
93
- <div className="max-w-xs space-y-2">
94
- <Label>Country</Label>
95
- <Combobox
96
- options={countries}
97
- value={value}
98
- onValueChange={setValue}
99
- placeholder="Select country..."
100
- searchPlaceholder="Search countries..."
101
- emptyText="No country found."
102
- />
103
- </div>
104
- );
105
- };
106
-
107
- export const Disabled = () => (
108
- <div className="max-w-xs">
109
- <Combobox
110
- options={frameworks}
111
- value=""
112
- onValueChange={() => {}}
113
- placeholder="Select framework..."
114
- disabled
115
- />
116
- </div>
117
- );
118
-
119
- export const Form = () => {
120
- const [framework, setFramework] = useState('');
121
- const [country, setCountry] = useState('');
122
-
123
- return (
124
- <div className="max-w-xs space-y-4">
125
- <div className="space-y-2">
126
- <Label>Framework</Label>
127
- <Combobox
128
- options={frameworks}
129
- value={framework}
130
- onValueChange={setFramework}
131
- placeholder="Select framework..."
132
- />
133
- </div>
134
- <div className="space-y-2">
135
- <Label>Country</Label>
136
- <Combobox
137
- options={countries}
138
- value={country}
139
- onValueChange={setCountry}
140
- placeholder="Select country..."
141
- />
142
- </div>
143
- </div>
144
- );
145
- };
146
-
147
- // Trading symbols for custom filter demo
148
- const symbols: ComboboxOption[] = [
149
- { value: 'BTCUSDT', label: 'BTCUSDT', description: 'BTC/USDT' },
150
- { value: 'ETHUSDT', label: 'ETHUSDT', description: 'ETH/USDT' },
151
- { value: 'ETHBTC', label: 'ETHBTC', description: 'ETH/BTC' },
152
- { value: 'BNBUSDT', label: 'BNBUSDT', description: 'BNB/USDT' },
153
- { value: 'BNBBTC', label: 'BNBBTC', description: 'BNB/BTC' },
154
- { value: 'SOLUSDT', label: 'SOLUSDT', description: 'SOL/USDT' },
155
- { value: 'SOLBTC', label: 'SOLBTC', description: 'SOL/BTC' },
156
- { value: 'ADAUSDT', label: 'ADAUSDT', description: 'ADA/USDT' },
157
- { value: 'DOGEUSDT', label: 'DOGEUSDT', description: 'DOGE/USDT' },
158
- { value: 'XRPUSDT', label: 'XRPUSDT', description: 'XRP/USDT' },
159
- ];
160
-
161
- /**
162
- * Multi-word filter: all search terms must match.
163
- * "btc eth" matches ETHBTC (contains both "btc" and "eth")
164
- */
165
- function multiWordFilter(option: ComboboxOption, search: string): boolean {
166
- const terms = search.toLowerCase().trim().split(/\s+/).filter(Boolean);
167
- if (terms.length === 0) return true;
168
-
169
- const text = [option.label, option.value, option.description || '']
170
- .join(' ')
171
- .toLowerCase();
172
-
173
- return terms.every((term) => text.includes(term));
174
- }
175
-
176
- export const CustomFilter = () => {
177
- const [value, setValue] = useState('');
178
-
179
- return (
180
- <div className="max-w-xs space-y-2">
181
- <Label>Symbol (try "btc eth" or "usdt sol")</Label>
182
- <Combobox
183
- options={symbols}
184
- value={value}
185
- onValueChange={setValue}
186
- placeholder="Select symbol..."
187
- searchPlaceholder="Search... (e.g. btc usdt)"
188
- emptyText="No symbols found."
189
- filterFunction={multiWordFilter}
190
- renderOption={(option) => (
191
- <div className="flex items-center justify-between w-full">
192
- <span className="font-medium">{option.label}</span>
193
- <span className="text-xs text-muted-foreground">{option.description}</span>
194
- </div>
195
- )}
196
- />
197
- <p className="text-xs text-muted-foreground">
198
- Custom filter: space-separated terms (all must match)
199
- </p>
200
- </div>
201
- );
202
- };
203
-
204
- export const WithDescriptions = () => {
205
- const [value, setValue] = useState('');
206
-
207
- return (
208
- <div className="max-w-xs space-y-2">
209
- <Label>Trading Pair</Label>
210
- <Combobox
211
- options={symbols}
212
- value={value}
213
- onValueChange={setValue}
214
- placeholder="Select trading pair..."
215
- searchPlaceholder="Search pairs..."
216
- emptyText="No pairs found."
217
- renderOption={(option) => (
218
- <div className="flex items-center justify-between w-full">
219
- <span className="font-medium">{option.label}</span>
220
- <span className="text-xs text-muted-foreground">{option.description}</span>
221
- </div>
222
- )}
223
- />
224
- </div>
225
- );
226
- };
@@ -1,261 +0,0 @@
1
- import { useState } from 'react';
2
- import { defineStory } from '@djangocfg/playground';
3
- import { CountrySelect, type TCountryCode } from './country-select';
4
- import { Label } from '../forms/label';
5
-
6
- export default defineStory({
7
- title: 'Core/CountrySelect',
8
- component: CountrySelect,
9
- description: 'Country selector with emoji flags. Supports dropdown and inline variants, single and multiple selection.',
10
- });
11
-
12
- // ============================================================================
13
- // Dropdown Variants
14
- // ============================================================================
15
-
16
- export const SingleDropdown = () => {
17
- const [value, setValue] = useState<string[]>([]);
18
-
19
- return (
20
- <div className="max-w-sm space-y-2">
21
- <Label>Select country</Label>
22
- <CountrySelect
23
- value={value}
24
- onChange={setValue}
25
- placeholder="Choose a country..."
26
- />
27
- {value.length > 0 && (
28
- <p className="text-sm text-muted-foreground">Selected: {value[0]}</p>
29
- )}
30
- </div>
31
- );
32
- };
33
-
34
- export const MultipleDropdown = () => {
35
- const [value, setValue] = useState<string[]>([]);
36
-
37
- return (
38
- <div className="max-w-sm space-y-2">
39
- <Label>Select countries</Label>
40
- <CountrySelect
41
- multiple
42
- value={value}
43
- onChange={setValue}
44
- placeholder="Choose countries..."
45
- />
46
- {value.length > 0 && (
47
- <p className="text-sm text-muted-foreground">Selected: {value.join(', ')}</p>
48
- )}
49
- </div>
50
- );
51
- };
52
-
53
- export const WithDefaultValue = () => {
54
- const [value, setValue] = useState<string[]>(['US', 'GB', 'DE']);
55
-
56
- return (
57
- <div className="max-w-sm space-y-2">
58
- <Label>Preselected countries</Label>
59
- <CountrySelect
60
- multiple
61
- value={value}
62
- onChange={setValue}
63
- />
64
- </div>
65
- );
66
- };
67
-
68
- export const WithNativeNames = () => {
69
- const [value, setValue] = useState<string[]>([]);
70
-
71
- return (
72
- <div className="max-w-sm space-y-2">
73
- <Label>With native names</Label>
74
- <CountrySelect
75
- multiple
76
- value={value}
77
- onChange={setValue}
78
- showNativeName
79
- />
80
- </div>
81
- );
82
- };
83
-
84
- // ============================================================================
85
- // Inline Variants
86
- // ============================================================================
87
-
88
- export const InlineSingle = () => {
89
- const [value, setValue] = useState<string[]>([]);
90
-
91
- return (
92
- <div className="max-w-sm space-y-2">
93
- <Label>Select your country</Label>
94
- <CountrySelect
95
- variant="inline"
96
- value={value}
97
- onChange={setValue}
98
- maxHeight={250}
99
- />
100
- {value.length > 0 && (
101
- <p className="text-sm text-muted-foreground">Selected: {value[0]}</p>
102
- )}
103
- </div>
104
- );
105
- };
106
-
107
- export const InlineMultiple = () => {
108
- const [value, setValue] = useState<string[]>([]);
109
-
110
- return (
111
- <div className="max-w-sm space-y-2">
112
- <Label>Select target markets</Label>
113
- <CountrySelect
114
- variant="inline"
115
- multiple
116
- value={value}
117
- onChange={setValue}
118
- maxHeight={300}
119
- />
120
- </div>
121
- );
122
- };
123
-
124
- export const InlineWithNativeNames = () => {
125
- const [value, setValue] = useState<string[]>(['KR', 'JP']);
126
-
127
- return (
128
- <div className="max-w-sm space-y-2">
129
- <Label>Countries with native names</Label>
130
- <CountrySelect
131
- variant="inline"
132
- multiple
133
- value={value}
134
- onChange={setValue}
135
- showNativeName
136
- maxHeight={300}
137
- />
138
- </div>
139
- );
140
- };
141
-
142
- export const InlineNoSearch = () => {
143
- const [value, setValue] = useState<string[]>([]);
144
-
145
- return (
146
- <div className="max-w-sm space-y-2">
147
- <Label>Without search</Label>
148
- <CountrySelect
149
- variant="inline"
150
- multiple
151
- value={value}
152
- onChange={setValue}
153
- showSearch={false}
154
- maxHeight={200}
155
- />
156
- </div>
157
- );
158
- };
159
-
160
- // ============================================================================
161
- // Filtered Countries
162
- // ============================================================================
163
-
164
- const CIS_COUNTRIES: TCountryCode[] = ['RU', 'KZ', 'UZ', 'KG', 'TJ', 'TM', 'AZ', 'AM', 'GE', 'BY', 'MD', 'UA'];
165
- const ASIAN_AUTO_MARKETS: TCountryCode[] = ['KR', 'JP', 'CN', 'TH', 'MY', 'ID', 'VN', 'PH'];
166
-
167
- export const FilteredCISCountries = () => {
168
- const [value, setValue] = useState<string[]>([]);
169
-
170
- return (
171
- <div className="max-w-sm space-y-2">
172
- <Label>CIS Countries only</Label>
173
- <CountrySelect
174
- variant="inline"
175
- multiple
176
- value={value}
177
- onChange={setValue}
178
- allowedCountries={CIS_COUNTRIES}
179
- maxHeight={300}
180
- />
181
- </div>
182
- );
183
- };
184
-
185
- export const FilteredAsianMarkets = () => {
186
- const [value, setValue] = useState<string[]>([]);
187
-
188
- return (
189
- <div className="max-w-sm space-y-2">
190
- <Label>Asian Auto Markets</Label>
191
- <CountrySelect
192
- multiple
193
- value={value}
194
- onChange={setValue}
195
- allowedCountries={ASIAN_AUTO_MARKETS}
196
- showNativeName
197
- />
198
- </div>
199
- );
200
- };
201
-
202
- export const ExcludeSanctioned = () => {
203
- const [value, setValue] = useState<string[]>([]);
204
- const excluded: TCountryCode[] = ['KP', 'IR', 'SY', 'CU'];
205
-
206
- return (
207
- <div className="max-w-sm space-y-2">
208
- <Label>All except sanctioned</Label>
209
- <CountrySelect
210
- multiple
211
- value={value}
212
- onChange={setValue}
213
- excludedCountries={excluded}
214
- />
215
- </div>
216
- );
217
- };
218
-
219
- // ============================================================================
220
- // States
221
- // ============================================================================
222
-
223
- export const Disabled = () => (
224
- <div className="max-w-sm space-y-4">
225
- <div className="space-y-2">
226
- <Label>Disabled dropdown</Label>
227
- <CountrySelect
228
- value={['US']}
229
- onChange={() => {}}
230
- disabled
231
- />
232
- </div>
233
- <div className="space-y-2">
234
- <Label>Disabled inline</Label>
235
- <CountrySelect
236
- variant="inline"
237
- multiple
238
- value={['US', 'GB']}
239
- onChange={() => {}}
240
- disabled
241
- maxHeight={150}
242
- />
243
- </div>
244
- </div>
245
- );
246
-
247
- export const MaxDisplayBadges = () => {
248
- const [value, setValue] = useState<string[]>(['US', 'GB', 'DE', 'FR', 'IT', 'ES']);
249
-
250
- return (
251
- <div className="max-w-sm space-y-2">
252
- <Label>Max 2 badges displayed</Label>
253
- <CountrySelect
254
- multiple
255
- value={value}
256
- onChange={setValue}
257
- maxDisplay={2}
258
- />
259
- </div>
260
- );
261
- };