@telegraph/select 0.0.55 → 0.0.56

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 (3) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +677 -7
  3. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # @telegraph/select
2
2
 
3
+ ## 0.0.56
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [[`c0244e3`](https://github.com/knocklabs/telegraph/commit/c0244e3f4b6232f633ba4d99bb0eb603909c87fa)]:
8
+ - @telegraph/combobox@0.1.2
9
+
3
10
  ## 0.0.55
4
11
 
5
12
  ### Patch Changes
package/README.md CHANGED
@@ -1,17 +1,687 @@
1
- ![Telegraph by Knock](https://github.com/knocklabs/telegraph/assets/29106675/9b5022e3-b02c-4582-ba57-3d6171e45e44)
1
+ # 📋 Select
2
+
3
+ > Simplified dropdown select component built on Telegraph's Combobox with streamlined API for common selection patterns.
2
4
 
3
- [![npm version](https://img.shields.io/npm/v/@telegraph/button.svg)](https://www.npmjs.com/package/@telegraph/select)
5
+ ![Telegraph by Knock](https://github.com/knocklabs/telegraph/assets/29106675/9b5022e3-b02c-4582-ba57-3d6171e45e44)
4
6
 
5
- # @telegraph/select
6
- > A simple select component built on top of @telegraph/combobox
7
+ [![npm version](https://img.shields.io/npm/v/@telegraph/select.svg)](https://www.npmjs.com/package/@telegraph/select)
8
+ [![minzipped size](https://img.shields.io/bundlephobia/minzip/@telegraph/select)](https://bundlephobia.com/result?p=@telegraph/select)
9
+ [![license](https://img.shields.io/npm/l/@telegraph/select)](https://github.com/knocklabs/telegraph/blob/main/LICENSE)
7
10
 
8
- ## Installation Instructions
11
+ ## Installation
9
12
 
10
- ```
13
+ ```bash
11
14
  npm install @telegraph/select
12
15
  ```
13
16
 
14
17
  ### Add stylesheet
18
+
19
+ Pick one:
20
+
21
+ Via CSS (preferred):
22
+
23
+ ```css
24
+ @import "@telegraph/select";
25
+ ```
26
+
27
+ Via Javascript:
28
+
29
+ ```tsx
30
+ import "@telegraph/select/default.css";
31
+ ```
32
+
33
+ > Then, include `className="tgph"` on the farthest parent element wrapping the telegraph components
34
+
35
+ ## Quick Start
36
+
37
+ ```tsx
38
+ import { Select } from "@telegraph/select";
39
+
40
+ export const CountrySelector = () => {
41
+ const [country, setCountry] = useState("us");
42
+
43
+ return (
44
+ <Select.Root value={country} onValueChange={setCountry}>
45
+ <Select.Option value="us">United States</Select.Option>
46
+ <Select.Option value="ca">Canada</Select.Option>
47
+ <Select.Option value="mx">Mexico</Select.Option>
48
+ <Select.Option value="uk">United Kingdom</Select.Option>
49
+ <Select.Option value="de">Germany</Select.Option>
50
+ </Select.Root>
51
+ );
52
+ };
53
+ ```
54
+
55
+ ## When to Use Select vs Combobox
56
+
57
+ **Use Select when:**
58
+
59
+ - Simple dropdown selection
60
+ - Predefined list of options
61
+ - No search/filtering needed
62
+ - Standard selection patterns
63
+
64
+ **Use Combobox when:**
65
+
66
+ - Need search functionality
67
+ - Large option lists
68
+ - Custom option rendering
69
+ - Advanced filtering
70
+ - Multi-select with complex UI
71
+
72
+ ## API Reference
73
+
74
+ ### `<Select.Root>`
75
+
76
+ The main select container component.
77
+
78
+ | Prop | Type | Default | Description |
79
+ | --------------- | ------------------------------------- | ------------- | --------------------------------------- |
80
+ | `value` | `string \| string[]` | `undefined` | Selected value(s) |
81
+ | `onValueChange` | `(value: string \| string[]) => void` | `undefined` | Called when selection changes |
82
+ | `size` | `"0" \| "1" \| "2" \| "3" \| "4"` | `"1"` | Size of the trigger button |
83
+ | `placeholder` | `string` | `"Select..."` | Placeholder text when no value selected |
84
+ | `disabled` | `boolean` | `false` | Whether the select is disabled |
85
+ | `triggerProps` | `ComboboxTriggerProps` | `{}` | Props passed to the trigger button |
86
+ | `contentProps` | `ComboboxContentProps` | `{}` | Props passed to the dropdown content |
87
+ | `optionsProps` | `ComboboxOptionsProps` | `{}` | Props passed to the options container |
88
+
89
+ ### `<Select.Option>`
90
+
91
+ Individual option within the select dropdown.
92
+
93
+ | Prop | Type | Default | Description |
94
+ | ---------- | ----------- | ------- | ----------------------------------- |
95
+ | `value` | `string` | - | Unique value for this option |
96
+ | `disabled` | `boolean` | `false` | Whether this option is disabled |
97
+ | `children` | `ReactNode` | - | Display text/content for the option |
98
+
99
+ ## Usage Patterns
100
+
101
+ ### Basic Selection
102
+
103
+ ```tsx
104
+ import { Select } from "@telegraph/select";
105
+
106
+ export const LanguageSelector = () => {
107
+ const [language, setLanguage] = useState("en");
108
+
109
+ return (
110
+ <Select.Root
111
+ value={language}
112
+ onValueChange={setLanguage}
113
+ placeholder="Choose language"
114
+ >
115
+ <Select.Option value="en">English</Select.Option>
116
+ <Select.Option value="es">Spanish</Select.Option>
117
+ <Select.Option value="fr">French</Select.Option>
118
+ <Select.Option value="de">German</Select.Option>
119
+ </Select.Root>
120
+ );
121
+ };
122
+ ```
123
+
124
+ ### Multiple Selection
125
+
126
+ ```tsx
127
+ import { Select } from "@telegraph/select";
128
+
129
+ export const SkillSelector = () => {
130
+ const [skills, setSkills] = useState([]);
131
+
132
+ return (
133
+ <Select.Root
134
+ value={skills}
135
+ onValueChange={setSkills}
136
+ placeholder="Select skills"
137
+ >
138
+ <Select.Option value="javascript">JavaScript</Select.Option>
139
+ <Select.Option value="typescript">TypeScript</Select.Option>
140
+ <Select.Option value="react">React</Select.Option>
141
+ <Select.Option value="vue">Vue</Select.Option>
142
+ <Select.Option value="angular">Angular</Select.Option>
143
+ </Select.Root>
144
+ );
145
+ };
146
+ ```
147
+
148
+ ### Different Sizes
149
+
150
+ ```tsx
151
+ import { Select } from "@telegraph/select";
152
+
153
+ export const SizedSelects = () => (
154
+ <div>
155
+ {/* Small */}
156
+ <Select.Root size="0" value="" onValueChange={console.log}>
157
+ <Select.Option value="small">Small Option</Select.Option>
158
+ </Select.Root>
159
+
160
+ {/* Medium (default) */}
161
+ <Select.Root size="1" value="" onValueChange={console.log}>
162
+ <Select.Option value="medium">Medium Option</Select.Option>
163
+ </Select.Root>
164
+
165
+ {/* Large */}
166
+ <Select.Root size="3" value="" onValueChange={console.log}>
167
+ <Select.Option value="large">Large Option</Select.Option>
168
+ </Select.Root>
169
+ </div>
170
+ );
171
+ ```
172
+
173
+ ### With Disabled Options
174
+
175
+ ```tsx
176
+ <Select.Root value={selectedOption} onValueChange={setSelectedOption}>
177
+ <Select.Option value="available">Available Option</Select.Option>
178
+ <Select.Option value="disabled" disabled>
179
+ Disabled Option
180
+ </Select.Option>
181
+ <Select.Option value="premium">Premium Feature</Select.Option>
182
+ </Select.Root>
183
+ ```
184
+
185
+ ### Empty State
186
+
187
+ ```tsx
188
+ import { Select } from "@telegraph/select";
189
+
190
+ export const EmptySelect = () => {
191
+ const [value, setValue] = useState("");
192
+ const options = []; // Empty options array
193
+
194
+ return (
195
+ <Select.Root value={value} onValueChange={setValue}>
196
+ {options.length === 0 ? (
197
+ <Select.Option value="" disabled>
198
+ No options available
199
+ </Select.Option>
200
+ ) : (
201
+ options.map((option) => (
202
+ <Select.Option key={option.value} value={option.value}>
203
+ {option.label}
204
+ </Select.Option>
205
+ ))
206
+ )}
207
+ </Select.Root>
208
+ );
209
+ };
210
+ ```
211
+
212
+ ## Advanced Usage
213
+
214
+ ### Form Integration
215
+
216
+ ```tsx
217
+ import { Select } from "@telegraph/select";
218
+ import { Controller, useForm } from "react-hook-form";
219
+
220
+ type FormData = {
221
+ priority: string;
222
+ categories: string[];
223
+ };
224
+
225
+ export const TaskForm = () => {
226
+ const {
227
+ control,
228
+ handleSubmit,
229
+ formState: { errors },
230
+ } = useForm<FormData>();
231
+
232
+ return (
233
+ <form onSubmit={handleSubmit(console.log)}>
234
+ <div>
235
+ <label htmlFor="priority">Priority</label>
236
+ <Controller
237
+ name="priority"
238
+ control={control}
239
+ rules={{ required: "Priority is required" }}
240
+ render={({ field }) => (
241
+ <Select.Root
242
+ value={field.value || ""}
243
+ onValueChange={field.onChange}
244
+ placeholder="Select priority"
245
+ >
246
+ <Select.Option value="low">Low Priority</Select.Option>
247
+ <Select.Option value="medium">Medium Priority</Select.Option>
248
+ <Select.Option value="high">High Priority</Select.Option>
249
+ <Select.Option value="urgent">Urgent</Select.Option>
250
+ </Select.Root>
251
+ )}
252
+ />
253
+ {errors.priority && (
254
+ <span className="error">{errors.priority.message}</span>
255
+ )}
256
+ </div>
257
+
258
+ <div>
259
+ <label htmlFor="categories">Categories</label>
260
+ <Controller
261
+ name="categories"
262
+ control={control}
263
+ render={({ field }) => (
264
+ <Select.Root
265
+ value={field.value || []}
266
+ onValueChange={field.onChange}
267
+ placeholder="Select categories"
268
+ >
269
+ <Select.Option value="frontend">Frontend</Select.Option>
270
+ <Select.Option value="backend">Backend</Select.Option>
271
+ <Select.Option value="design">Design</Select.Option>
272
+ <Select.Option value="testing">Testing</Select.Option>
273
+ </Select.Root>
274
+ )}
275
+ />
276
+ </div>
277
+ </form>
278
+ );
279
+ };
280
+ ```
281
+
282
+ ### Dynamic Options
283
+
284
+ ```tsx
285
+ import { Select } from "@telegraph/select";
286
+
287
+ export const DynamicSelect = () => {
288
+ const [category, setCategory] = useState("");
289
+ const [options, setOptions] = useState([]);
290
+ const [loading, setLoading] = useState(false);
291
+
292
+ useEffect(() => {
293
+ if (category) {
294
+ setLoading(true);
295
+ fetchOptionsForCategory(category)
296
+ .then(setOptions)
297
+ .finally(() => setLoading(false));
298
+ }
299
+ }, [category]);
300
+
301
+ return (
302
+ <div>
303
+ <Select.Root value={category} onValueChange={setCategory}>
304
+ <Select.Option value="electronics">Electronics</Select.Option>
305
+ <Select.Option value="clothing">Clothing</Select.Option>
306
+ <Select.Option value="books">Books</Select.Option>
307
+ </Select.Root>
308
+
309
+ {category && (
310
+ <Select.Root
311
+ disabled={loading}
312
+ value=""
313
+ onValueChange={console.log}
314
+ placeholder={loading ? "Loading..." : "Select subcategory"}
315
+ >
316
+ {options.map((option) => (
317
+ <Select.Option key={option.id} value={option.id}>
318
+ {option.name}
319
+ </Select.Option>
320
+ ))}
321
+ </Select.Root>
322
+ )}
323
+ </div>
324
+ );
325
+ };
326
+ ```
327
+
328
+ ### Custom Trigger Styling
329
+
330
+ ```tsx
331
+ import { Select } from "@telegraph/select";
332
+
333
+ export const CustomStyledSelect = () => {
334
+ const [value, setValue] = useState("");
335
+
336
+ return (
337
+ <Select.Root
338
+ value={value}
339
+ onValueChange={setValue}
340
+ triggerProps={{
341
+ variant: "outline",
342
+ color: "accent",
343
+ }}
344
+ contentProps={{
345
+ align: "start",
346
+ sideOffset: 4,
347
+ }}
348
+ >
349
+ <Select.Option value="option1">Option 1</Select.Option>
350
+ <Select.Option value="option2">Option 2</Select.Option>
351
+ <Select.Option value="option3">Option 3</Select.Option>
352
+ </Select.Root>
353
+ );
354
+ };
355
+ ```
356
+
357
+ ### Conditional Rendering
358
+
359
+ ```tsx
360
+ import { Select } from "@telegraph/select";
361
+
362
+ export const ConditionalSelect = ({ userRole, permissions }) => {
363
+ const [access, setAccess] = useState("");
364
+
365
+ const availableRoles = [
366
+ { value: "read", label: "Read Only", permission: "read" },
367
+ { value: "write", label: "Read & Write", permission: "write" },
368
+ { value: "admin", label: "Administrator", permission: "admin" },
369
+ ].filter((role) => permissions.includes(role.permission));
370
+
371
+ return (
372
+ <Select.Root value={access} onValueChange={setAccess}>
373
+ {availableRoles.map((role) => (
374
+ <Select.Option key={role.value} value={role.value}>
375
+ {role.label}
376
+ </Select.Option>
377
+ ))}
378
+ </Select.Root>
379
+ );
380
+ };
381
+ ```
382
+
383
+ ### Loading State
384
+
385
+ ```tsx
386
+ import { Select } from "@telegraph/select";
387
+ import { Skeleton } from "@telegraph/skeleton";
388
+
389
+ export const SelectWithLoading = ({ loading, options, ...props }) => {
390
+ if (loading) {
391
+ return <Skeleton width="200px" height="32px" />;
392
+ }
393
+
394
+ return (
395
+ <Select.Root {...props}>
396
+ {options.map((option) => (
397
+ <Select.Option key={option.value} value={option.value}>
398
+ {option.label}
399
+ </Select.Option>
400
+ ))}
401
+ </Select.Root>
402
+ );
403
+ };
404
+ ```
405
+
406
+ ### Grouped Options
407
+
408
+ ```tsx
409
+ import { Select } from "@telegraph/select";
410
+
411
+ export const GroupedSelect = () => {
412
+ const [value, setValue] = useState("");
413
+
414
+ const optionGroups = [
415
+ {
416
+ label: "Fruits",
417
+ options: [
418
+ { value: "apple", label: "Apple" },
419
+ { value: "banana", label: "Banana" },
420
+ { value: "orange", label: "Orange" },
421
+ ],
422
+ },
423
+ {
424
+ label: "Vegetables",
425
+ options: [
426
+ { value: "carrot", label: "Carrot" },
427
+ { value: "lettuce", label: "Lettuce" },
428
+ { value: "tomato", label: "Tomato" },
429
+ ],
430
+ },
431
+ ];
432
+
433
+ return (
434
+ <Select.Root value={value} onValueChange={setValue}>
435
+ {optionGroups.map((group) => (
436
+ <React.Fragment key={group.label}>
437
+ <Select.Option value="" disabled>
438
+ {group.label}
439
+ </Select.Option>
440
+ {group.options.map((option) => (
441
+ <Select.Option key={option.value} value={option.value}>
442
+ {option.label}
443
+ </Select.Option>
444
+ ))}
445
+ </React.Fragment>
446
+ ))}
447
+ </Select.Root>
448
+ );
449
+ };
450
+ ```
451
+
452
+ ## Accessibility
453
+
454
+ Since Select is built on Combobox, it inherits all accessibility features:
455
+
456
+ - ✅ **Keyboard Navigation**: Arrow keys, Enter, Escape support
457
+ - ✅ **Screen Reader Support**: Proper ARIA attributes and announcements
458
+ - ✅ **Focus Management**: Logical focus order and indicators
459
+ - ✅ **High Contrast**: Compatible with high contrast modes
460
+ - ✅ **Touch Support**: Optimized for mobile and touch devices
461
+
462
+ ### Keyboard Shortcuts
463
+
464
+ | Key | Action |
465
+ | ----------------- | ------------------------- |
466
+ | `Space` / `Enter` | Open/close dropdown |
467
+ | `Arrow Up/Down` | Navigate options |
468
+ | `Escape` | Close dropdown |
469
+ | `Home` / `End` | Jump to first/last option |
470
+ | `Type to search` | Quick option selection |
471
+
472
+ ### ARIA Attributes
473
+
474
+ - `role="combobox"` - Applied to the trigger
475
+ - `aria-expanded` - Indicates dropdown state
476
+ - `aria-haspopup="listbox"` - Describes dropdown content
477
+ - `role="listbox"` - Applied to options container
478
+ - `role="option"` - Applied to each option
479
+ - `aria-selected` - Indicates selected options
480
+
481
+ ### Best Practices
482
+
483
+ 1. **Provide Clear Labels**: Use descriptive labels for the select
484
+ 2. **Meaningful Placeholders**: Write helpful placeholder text
485
+ 3. **Logical Option Order**: Order options alphabetically or by relevance
486
+ 4. **Handle Empty States**: Provide feedback when no options available
487
+ 5. **Error Messaging**: Show clear validation errors
488
+
489
+ ## Examples
490
+
491
+ ### Basic Example
492
+
493
+ ```tsx
494
+ import { Select } from "@telegraph/select";
495
+
496
+ export const StatusSelector = () => {
497
+ const [status, setStatus] = useState("pending");
498
+
499
+ return (
500
+ <div>
501
+ <label htmlFor="status">Status</label>
502
+ <Select.Root value={status} onValueChange={setStatus}>
503
+ <Select.Option value="pending">Pending</Select.Option>
504
+ <Select.Option value="approved">Approved</Select.Option>
505
+ <Select.Option value="rejected">Rejected</Select.Option>
506
+ <Select.Option value="cancelled">Cancelled</Select.Option>
507
+ </Select.Root>
508
+ </div>
509
+ );
510
+ };
511
+ ```
512
+
513
+ ### Advanced Example
514
+
515
+ ```tsx
516
+ import { Select } from "@telegraph/select";
517
+ import { Controller, useForm } from "react-hook-form";
518
+
519
+ export const UserPreferencesForm = () => {
520
+ const { control, handleSubmit, watch } = useForm({
521
+ defaultValues: {
522
+ theme: "system",
523
+ language: "en",
524
+ notifications: [],
525
+ },
526
+ });
527
+
528
+ const theme = watch("theme");
529
+
530
+ return (
531
+ <form onSubmit={handleSubmit(console.log)}>
532
+ <div className="form-group">
533
+ <label>Theme Preference</label>
534
+ <Controller
535
+ name="theme"
536
+ control={control}
537
+ render={({ field }) => (
538
+ <Select.Root
539
+ value={field.value}
540
+ onValueChange={field.onChange}
541
+ size="2"
542
+ >
543
+ <Select.Option value="light">Light Mode</Select.Option>
544
+ <Select.Option value="dark">Dark Mode</Select.Option>
545
+ <Select.Option value="system">System Default</Select.Option>
546
+ </Select.Root>
547
+ )}
548
+ />
549
+ </div>
550
+
551
+ <div className="form-group">
552
+ <label>Language</label>
553
+ <Controller
554
+ name="language"
555
+ control={control}
556
+ render={({ field }) => (
557
+ <Select.Root
558
+ value={field.value}
559
+ onValueChange={field.onChange}
560
+ triggerProps={{ variant: "outline" }}
561
+ >
562
+ <Select.Option value="en">English</Select.Option>
563
+ <Select.Option value="es">Español</Select.Option>
564
+ <Select.Option value="fr">Français</Select.Option>
565
+ <Select.Option value="de">Deutsch</Select.Option>
566
+ </Select.Root>
567
+ )}
568
+ />
569
+ </div>
570
+
571
+ <div className="form-group">
572
+ <label>Notification Types</label>
573
+ <Controller
574
+ name="notifications"
575
+ control={control}
576
+ render={({ field }) => (
577
+ <Select.Root
578
+ value={field.value}
579
+ onValueChange={field.onChange}
580
+ placeholder="Select notification types"
581
+ >
582
+ <Select.Option value="email">Email Updates</Select.Option>
583
+ <Select.Option value="push">Push Notifications</Select.Option>
584
+ <Select.Option value="sms">SMS Alerts</Select.Option>
585
+ <Select.Option value="desktop">
586
+ Desktop Notifications
587
+ </Select.Option>
588
+ </Select.Root>
589
+ )}
590
+ />
591
+ </div>
592
+
593
+ <button type="submit">Save Preferences</button>
594
+ </form>
595
+ );
596
+ };
15
597
  ```
16
- @import "@telegraph/select"
598
+
599
+ ### Real-world Example
600
+
601
+ ```tsx
602
+ import { Select } from "@telegraph/select";
603
+ import { useEffect, useState } from "react";
604
+
605
+ export const CountryRegionSelector = () => {
606
+ const [country, setCountry] = useState("");
607
+ const [region, setRegion] = useState("");
608
+ const [regions, setRegions] = useState([]);
609
+ const [loading, setLoading] = useState(false);
610
+
611
+ useEffect(() => {
612
+ if (country) {
613
+ setLoading(true);
614
+ setRegion(""); // Reset region when country changes
615
+
616
+ fetchRegionsForCountry(country)
617
+ .then(setRegions)
618
+ .finally(() => setLoading(false));
619
+ }
620
+ }, [country]);
621
+
622
+ const countries = [
623
+ { value: "us", label: "United States" },
624
+ { value: "ca", label: "Canada" },
625
+ { value: "mx", label: "Mexico" },
626
+ { value: "uk", label: "United Kingdom" },
627
+ ];
628
+
629
+ return (
630
+ <div className="address-form">
631
+ <div className="form-row">
632
+ <div className="form-group">
633
+ <label htmlFor="country">Country</label>
634
+ <Select.Root
635
+ value={country}
636
+ onValueChange={setCountry}
637
+ placeholder="Select country"
638
+ size="2"
639
+ >
640
+ {countries.map((country) => (
641
+ <Select.Option key={country.value} value={country.value}>
642
+ {country.label}
643
+ </Select.Option>
644
+ ))}
645
+ </Select.Root>
646
+ </div>
647
+
648
+ <div className="form-group">
649
+ <label htmlFor="region">State/Province</label>
650
+ <Select.Root
651
+ value={region}
652
+ onValueChange={setRegion}
653
+ disabled={!country || loading}
654
+ placeholder={
655
+ !country
656
+ ? "Select country first"
657
+ : loading
658
+ ? "Loading..."
659
+ : "Select region"
660
+ }
661
+ size="2"
662
+ >
663
+ {regions.map((region) => (
664
+ <Select.Option key={region.code} value={region.code}>
665
+ {region.name}
666
+ </Select.Option>
667
+ ))}
668
+ </Select.Root>
669
+ </div>
670
+ </div>
671
+ </div>
672
+ );
673
+ };
17
674
  ```
675
+
676
+ ## References
677
+
678
+ - [Storybook Demo](https://storybook.telegraph.dev/?path=/docs/select)
679
+ - [Combobox Component](../combobox/README.md) - Full-featured dropdown with search
680
+
681
+ ## Contributing
682
+
683
+ See our [Contributing Guide](../../CONTRIBUTING.md) for more details.
684
+
685
+ ## License
686
+
687
+ MIT License - see [LICENSE](../../LICENSE) for details.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@telegraph/select",
3
- "version": "0.0.55",
3
+ "version": "0.0.56",
4
4
  "description": "A simple select component built on top of @telegraph/combobox",
5
5
  "repository": "https://github.com/knocklabs/telegraph/tree/main/packages/select",
6
6
  "author": "@knocklabs",
@@ -30,7 +30,7 @@
30
30
  "preview": "vite preview"
31
31
  },
32
32
  "dependencies": {
33
- "@telegraph/combobox": "0.1.1",
33
+ "@telegraph/combobox": "0.1.2",
34
34
  "@telegraph/helpers": "0.0.13"
35
35
  },
36
36
  "devDependencies": {