@usefidel/design-system 0.6.0 → 0.8.0

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.
package/dist/index.css CHANGED
@@ -376,7 +376,6 @@
376
376
  .fds-diff-section__line {
377
377
  display: flex;
378
378
  align-items: center;
379
- justify-content: space-between;
380
379
  width: 100%;
381
380
  }
382
381
  .fds-diff-section__prop {
@@ -392,6 +391,7 @@
392
391
  display: flex;
393
392
  align-items: center;
394
393
  gap: var(--spacing-1);
394
+ margin-left: auto;
395
395
  font-family: var(--font-mono);
396
396
  font-weight: var(--font-weight-medium);
397
397
  font-size: 14px;
@@ -399,6 +399,13 @@
399
399
  letter-spacing: -0.28px;
400
400
  white-space: nowrap;
401
401
  }
402
+ .fds-diff-section__trailing {
403
+ display: flex;
404
+ align-items: center;
405
+ gap: var(--spacing-2);
406
+ margin-left: var(--spacing-3);
407
+ flex-shrink: 0;
408
+ }
402
409
  .fds-diff-section__live {
403
410
  color: #ef4444;
404
411
  }
@@ -409,3 +416,285 @@
409
416
  .fds-diff-section__design {
410
417
  color: #1e8902;
411
418
  }
419
+
420
+ /* src/components/Select/select.css */
421
+ .fds-select-field {
422
+ display: flex;
423
+ flex-direction: column;
424
+ gap: var(--spacing-2, 8px);
425
+ width: 100%;
426
+ }
427
+ .fds-select__label {
428
+ font-family: var(--font-display, "Rethink Sans", system-ui, sans-serif);
429
+ font-size: var(--font-size-label-sm, 14px);
430
+ line-height: var(--line-height-label-sm, 22px);
431
+ font-weight: var(--font-weight-medium, 500);
432
+ color: var(--color-text, #171717);
433
+ }
434
+ .fds-select {
435
+ position: relative;
436
+ width: 100%;
437
+ }
438
+ .fds-select__trigger {
439
+ display: flex;
440
+ align-items: center;
441
+ gap: var(--spacing-2, 8px);
442
+ width: 100%;
443
+ min-height: 44px;
444
+ padding: 0 var(--spacing-3, 12px);
445
+ background: var(--color-surface-raised, #ffffff);
446
+ border: 1px solid var(--color-border-strong, #d4d4d4);
447
+ border-radius: var(--radius-md, 6px);
448
+ font-family: var(--font-body, "Rethink Sans", system-ui, sans-serif);
449
+ font-size: var(--font-size-text-md, 16px);
450
+ color: var(--color-text, #171717);
451
+ cursor: pointer;
452
+ text-align: left;
453
+ transition: border-color var(--duration-instant, 80ms) ease, box-shadow var(--duration-instant, 80ms) ease;
454
+ }
455
+ .fds-select__trigger:focus-visible,
456
+ .fds-select__trigger--open {
457
+ outline: none;
458
+ border-color: var(--color-accent, #ea580c);
459
+ box-shadow: inset 0 0 0 1px var(--color-accent, #ea580c);
460
+ }
461
+ .fds-select__trigger--error {
462
+ border-color: var(--color-error, #b91c1c);
463
+ }
464
+ .fds-select__trigger--error.fds-select__trigger--open,
465
+ .fds-select__trigger--error:focus-visible {
466
+ box-shadow: inset 0 0 0 1px var(--color-error, #b91c1c);
467
+ }
468
+ .fds-select__trigger:disabled {
469
+ background: var(--color-surface-muted, #fafafa);
470
+ color: var(--color-text-muted, #a3a3a3);
471
+ cursor: not-allowed;
472
+ }
473
+ .fds-select__lead {
474
+ display: inline-flex;
475
+ align-items: center;
476
+ flex-shrink: 0;
477
+ }
478
+ .fds-select__value {
479
+ flex: 1 1 auto;
480
+ min-width: 0;
481
+ overflow: hidden;
482
+ text-overflow: ellipsis;
483
+ white-space: nowrap;
484
+ }
485
+ .fds-select__value--placeholder {
486
+ color: var(--color-text-muted, #a3a3a3);
487
+ }
488
+ .fds-select__chevron {
489
+ display: inline-flex;
490
+ align-items: center;
491
+ flex-shrink: 0;
492
+ color: var(--color-text-muted, #a3a3a3);
493
+ }
494
+ .fds-select__popover {
495
+ position: absolute;
496
+ top: calc(100% + 4px);
497
+ left: 0;
498
+ right: 0;
499
+ z-index: 50;
500
+ background: var(--color-surface-raised, #ffffff);
501
+ border: 1px solid var(--color-border, #e5e5e5);
502
+ border-radius: var(--radius-md, 6px);
503
+ box-shadow: var(--shadow-lg, 0 4px 8px rgba(0, 0, 0, 0.06), 0 16px 40px rgba(0, 0, 0, 0.1));
504
+ overflow: hidden;
505
+ }
506
+ .fds-select__search {
507
+ padding: var(--spacing-2, 8px);
508
+ border-bottom: 1px solid var(--color-border-light, #f5f5f5);
509
+ }
510
+ .fds-select__searchInput {
511
+ width: 100%;
512
+ padding: 8px var(--spacing-3, 12px);
513
+ border: 1px solid var(--color-border-strong, #d4d4d4);
514
+ border-radius: var(--radius-sm, 4px);
515
+ font-family: var(--font-body, "Rethink Sans", system-ui, sans-serif);
516
+ font-size: var(--font-size-text-sm, 14px);
517
+ color: var(--color-text, #171717);
518
+ }
519
+ .fds-select__searchInput:focus {
520
+ outline: none;
521
+ border-color: var(--color-accent, #ea580c);
522
+ box-shadow: inset 0 0 0 1px var(--color-accent, #ea580c);
523
+ }
524
+ .fds-select__list {
525
+ max-height: 280px;
526
+ overflow-y: auto;
527
+ padding: var(--spacing-1, 4px);
528
+ }
529
+ .fds-select__list:focus {
530
+ outline: none;
531
+ }
532
+ .fds-select__empty {
533
+ padding: var(--spacing-3, 12px);
534
+ font-family: var(--font-body, "Rethink Sans", system-ui, sans-serif);
535
+ font-size: var(--font-size-text-sm, 14px);
536
+ color: var(--color-text-muted, #a3a3a3);
537
+ text-align: center;
538
+ }
539
+ .fds-select__option {
540
+ display: flex;
541
+ align-items: center;
542
+ gap: var(--spacing-2, 8px);
543
+ padding: 8px var(--spacing-2, 8px);
544
+ border-radius: var(--radius-sm, 4px);
545
+ cursor: pointer;
546
+ }
547
+ .fds-select__option--active {
548
+ background: var(--color-surface, #fff7ed);
549
+ }
550
+ .fds-select__option--disabled {
551
+ opacity: 0.5;
552
+ cursor: not-allowed;
553
+ }
554
+ .fds-select__optAvatar {
555
+ display: inline-flex;
556
+ align-items: center;
557
+ flex-shrink: 0;
558
+ color: var(--color-text-muted, #a3a3a3);
559
+ }
560
+ .fds-select__optText {
561
+ display: inline-flex;
562
+ align-items: baseline;
563
+ gap: 6px;
564
+ min-width: 0;
565
+ flex: 1 1 auto;
566
+ }
567
+ .fds-select__optLabel {
568
+ font-family: var(--font-body, "Rethink Sans", system-ui, sans-serif);
569
+ font-size: var(--font-size-text-sm, 14px);
570
+ color: var(--color-text, #171717);
571
+ white-space: nowrap;
572
+ overflow: hidden;
573
+ text-overflow: ellipsis;
574
+ }
575
+ .fds-select__optSecondary {
576
+ font-family: var(--font-body, "Rethink Sans", system-ui, sans-serif);
577
+ font-size: var(--font-size-text-sm, 14px);
578
+ color: var(--color-text-muted, #a3a3a3);
579
+ white-space: nowrap;
580
+ }
581
+ .fds-select__check {
582
+ display: inline-flex;
583
+ align-items: center;
584
+ flex-shrink: 0;
585
+ color: var(--color-accent, #ea580c);
586
+ }
587
+ .fds-select__hint,
588
+ .fds-select__error {
589
+ font-family: var(--font-body, "Rethink Sans", system-ui, sans-serif);
590
+ font-size: var(--font-size-text-xs, 12px);
591
+ line-height: var(--line-height-text-xs, 18px);
592
+ }
593
+ .fds-select__hint {
594
+ color: var(--color-text-muted, #a3a3a3);
595
+ }
596
+ .fds-select__error {
597
+ color: var(--color-error, #b91c1c);
598
+ }
599
+
600
+ /* src/components/Toggle/toggle.css */
601
+ .fds-toggle {
602
+ display: inline-flex;
603
+ position: relative;
604
+ }
605
+ .fds-toggle__input {
606
+ position: absolute;
607
+ top: 0;
608
+ left: 0;
609
+ width: 100%;
610
+ height: 100%;
611
+ margin: 0;
612
+ opacity: 0;
613
+ cursor: pointer;
614
+ z-index: 1;
615
+ }
616
+ .fds-toggle__input:disabled {
617
+ cursor: not-allowed;
618
+ }
619
+ .fds-toggle__control {
620
+ display: inline-flex;
621
+ align-items: flex-start;
622
+ gap: var(--spacing-2, 8px);
623
+ cursor: pointer;
624
+ }
625
+ .fds-toggle__input:disabled ~ .fds-toggle__control {
626
+ cursor: not-allowed;
627
+ }
628
+ .fds-toggle__track {
629
+ position: relative;
630
+ display: inline-block;
631
+ flex-shrink: 0;
632
+ background-color: var(--color-border-strong, #d4d4d4);
633
+ border-radius: var(--radius-pill, 9999px);
634
+ transition: background-color var(--duration-quick, 150ms) var(--ease-out, ease);
635
+ }
636
+ .fds-toggle__thumb {
637
+ position: absolute;
638
+ top: 50%;
639
+ transform: translateY(-50%);
640
+ background-color: #ffffff;
641
+ border-radius: var(--radius-full, 9999px);
642
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);
643
+ transition: left var(--duration-quick, 150ms) var(--ease-out, ease);
644
+ }
645
+ .fds-toggle__input:checked ~ .fds-toggle__control .fds-toggle__track {
646
+ background-color: var(--color-accent, #ea580c);
647
+ }
648
+ .fds-toggle__input:focus-visible ~ .fds-toggle__control .fds-toggle__track {
649
+ outline: 2px solid var(--color-accent, #ea580c);
650
+ outline-offset: 2px;
651
+ }
652
+ .fds-toggle[data-disabled] .fds-toggle__track {
653
+ opacity: 0.5;
654
+ }
655
+ .fds-toggle[data-disabled] .fds-toggle__label,
656
+ .fds-toggle[data-disabled] .fds-toggle__description {
657
+ color: var(--color-text-muted, #a3a3a3);
658
+ }
659
+ .fds-toggle--medium .fds-toggle__track {
660
+ width: 44px;
661
+ height: 24px;
662
+ }
663
+ .fds-toggle--medium .fds-toggle__thumb {
664
+ width: 20px;
665
+ height: 20px;
666
+ left: 2px;
667
+ }
668
+ .fds-toggle--medium .fds-toggle__input:checked ~ .fds-toggle__control .fds-toggle__thumb {
669
+ left: 22px;
670
+ }
671
+ .fds-toggle--small .fds-toggle__track {
672
+ width: 36px;
673
+ height: 20px;
674
+ }
675
+ .fds-toggle--small .fds-toggle__thumb {
676
+ width: 16px;
677
+ height: 16px;
678
+ left: 2px;
679
+ }
680
+ .fds-toggle--small .fds-toggle__input:checked ~ .fds-toggle__control .fds-toggle__thumb {
681
+ left: 18px;
682
+ }
683
+ .fds-toggle__text {
684
+ display: inline-flex;
685
+ flex-direction: column;
686
+ gap: 2px;
687
+ }
688
+ .fds-toggle__label {
689
+ font-family: var(--font-body, "Rethink Sans", system-ui, sans-serif);
690
+ font-size: var(--font-size-text-sm, 14px);
691
+ line-height: var(--line-height-text-sm, 22px);
692
+ font-weight: var(--font-weight-medium, 500);
693
+ color: var(--color-text, #171717);
694
+ }
695
+ .fds-toggle__description {
696
+ font-family: var(--font-body, "Rethink Sans", system-ui, sans-serif);
697
+ font-size: var(--font-size-text-sm, 14px);
698
+ line-height: var(--line-height-text-sm, 22px);
699
+ color: var(--color-text-secondary, #525252);
700
+ }
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as react from 'react';
2
- import { ButtonHTMLAttributes, ReactNode, HTMLAttributes } from 'react';
2
+ import { ButtonHTMLAttributes, ReactNode, HTMLAttributes, InputHTMLAttributes } from 'react';
3
3
 
4
4
  type ButtonVariant = 'primary' | 'outlined' | 'text' | 'neutral';
5
5
  type ButtonSize = 'x-small' | 'small' | 'medium' | 'big';
@@ -64,10 +64,23 @@ declare function MismatchCard({ title, properties, collapsedCount, defaultExpand
64
64
  interface DiffPropertyLine {
65
65
  /** Property name, e.g. "font-size". Rendered in mono. */
66
66
  property: string;
67
- /** Value on the live page — what shipped. Left of the arrow (error register). */
68
- live: string;
69
- /** Value in the design — the target. Right of the arrow (success register). */
70
- design: string;
67
+ /**
68
+ * Value on the live page — what shipped. Left of the arrow (error register).
69
+ * A string in the common case; accepts any node so a caller can prefix it
70
+ * with, e.g., a colour swatch.
71
+ */
72
+ live: ReactNode;
73
+ /**
74
+ * Value in the design — the target. Right of the arrow (success register).
75
+ * A string in the common case; accepts any node (see `live`).
76
+ */
77
+ design: ReactNode;
78
+ /**
79
+ * Optional content pinned to the right end of the row, after the delta —
80
+ * e.g. an occurrence count or a per-property review control. Omit for the
81
+ * plain read-only row. Presentational: the caller owns whatever lives here.
82
+ */
83
+ trailing?: ReactNode;
71
84
  }
72
85
  interface DiffElement {
73
86
  /** Element name, e.g. `"Pricing"`. */
@@ -150,5 +163,73 @@ interface DiffSectionProps extends HTMLAttributes<HTMLDivElement> {
150
163
  * decision 2026-04-24): each delta reads `live → design`.
151
164
  */
152
165
  declare function DiffSection({ number, name, mismatchCount, elements, defaultExpanded, headerless, onElementToggle, onElementHover, className, ...rest }: DiffSectionProps): react.JSX.Element;
166
+ interface DiffPropertyListProps extends HTMLAttributes<HTMLDivElement> {
167
+ /** Property mismatch rows to render. */
168
+ properties: DiffPropertyLine[];
169
+ }
170
+ /**
171
+ * The bare list of property-delta rows — `property` on the left, a
172
+ * `live → design` mono delta, and an optional `trailing` slot — with the left
173
+ * rule and indent. Extracted from DiffSection so a caller that owns its own
174
+ * card shell (e.g. the extension's IssueCard) can render exactly these rows
175
+ * without DiffSection's element/section chrome. DiffSection uses it internally,
176
+ * so the two surfaces render byte-identical rows.
177
+ */
178
+ declare function DiffPropertyList({ properties, className, ...rest }: DiffPropertyListProps): react.JSX.Element;
179
+
180
+ interface SelectOption {
181
+ value: string;
182
+ label: string;
183
+ /** Secondary line, e.g. an @handle. */
184
+ secondary?: string;
185
+ /** Leading node (avatar / icon) shown in the option and, when selected, the trigger. */
186
+ avatar?: ReactNode;
187
+ disabled?: boolean;
188
+ }
189
+ interface SelectProps {
190
+ options: SelectOption[];
191
+ value?: string | null;
192
+ onChange?: (value: string) => void;
193
+ placeholder?: string;
194
+ label?: ReactNode;
195
+ hint?: ReactNode;
196
+ error?: ReactNode;
197
+ disabled?: boolean;
198
+ /** Show a filter input at the top of the list. */
199
+ searchable?: boolean;
200
+ searchPlaceholder?: string;
201
+ /** Leading node in the trigger; a selected option's `avatar` takes precedence. */
202
+ leadingIcon?: ReactNode;
203
+ id?: string;
204
+ /** When set, renders a hidden input so the value posts with a form. */
205
+ name?: string;
206
+ className?: string;
207
+ containerClassName?: string;
208
+ }
209
+ /**
210
+ * Fidel design-system Select — a listbox (optionally searchable) with avatar +
211
+ * secondary-line options and a checkmark on the selected row. Controlled via
212
+ * `value`/`onChange`. Keyboard: type/Enter/Space/↓ open; ↑/↓/Home/End move;
213
+ * Enter selects; Esc closes; click-outside closes. Measured from Figma "Fidel
214
+ * Library" Select (node 3521:5948).
215
+ */
216
+ declare const Select: react.ForwardRefExoticComponent<SelectProps & react.RefAttributes<HTMLButtonElement>>;
217
+
218
+ type ToggleSize = 'small' | 'medium';
219
+ interface ToggleProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type' | 'size'> {
220
+ /** Size step. @default 'medium' */
221
+ size?: ToggleSize;
222
+ /** Text beside the switch. */
223
+ label?: ReactNode;
224
+ /** Secondary line under the label. */
225
+ description?: ReactNode;
226
+ }
227
+ /**
228
+ * Fidel design-system Toggle (switch). Renders a native checkbox with
229
+ * `role="switch"`; on/off/disabled are handled in CSS, so all standard input
230
+ * attributes (checked, defaultChecked, onChange, disabled, aria-*, …) pass
231
+ * through. Measured from Figma "Fidel Library" Toggle (node 3528:8473).
232
+ */
233
+ declare const Toggle: react.ForwardRefExoticComponent<ToggleProps & react.RefAttributes<HTMLInputElement>>;
153
234
 
154
- export { Button, type ButtonProps, type ButtonSize, type ButtonVariant, type DiffElement, type DiffPropertyLine, DiffSection, type DiffSectionProps, MismatchCard, type MismatchCardProps, type MismatchProperty };
235
+ export { Button, type ButtonProps, type ButtonSize, type ButtonVariant, type DiffElement, type DiffPropertyLine, DiffPropertyList, type DiffPropertyListProps, DiffSection, type DiffSectionProps, MismatchCard, type MismatchCardProps, type MismatchProperty, Select, type SelectOption, type SelectProps, Toggle, type ToggleProps, type ToggleSize };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as react from 'react';
2
- import { ButtonHTMLAttributes, ReactNode, HTMLAttributes } from 'react';
2
+ import { ButtonHTMLAttributes, ReactNode, HTMLAttributes, InputHTMLAttributes } from 'react';
3
3
 
4
4
  type ButtonVariant = 'primary' | 'outlined' | 'text' | 'neutral';
5
5
  type ButtonSize = 'x-small' | 'small' | 'medium' | 'big';
@@ -64,10 +64,23 @@ declare function MismatchCard({ title, properties, collapsedCount, defaultExpand
64
64
  interface DiffPropertyLine {
65
65
  /** Property name, e.g. "font-size". Rendered in mono. */
66
66
  property: string;
67
- /** Value on the live page — what shipped. Left of the arrow (error register). */
68
- live: string;
69
- /** Value in the design — the target. Right of the arrow (success register). */
70
- design: string;
67
+ /**
68
+ * Value on the live page — what shipped. Left of the arrow (error register).
69
+ * A string in the common case; accepts any node so a caller can prefix it
70
+ * with, e.g., a colour swatch.
71
+ */
72
+ live: ReactNode;
73
+ /**
74
+ * Value in the design — the target. Right of the arrow (success register).
75
+ * A string in the common case; accepts any node (see `live`).
76
+ */
77
+ design: ReactNode;
78
+ /**
79
+ * Optional content pinned to the right end of the row, after the delta —
80
+ * e.g. an occurrence count or a per-property review control. Omit for the
81
+ * plain read-only row. Presentational: the caller owns whatever lives here.
82
+ */
83
+ trailing?: ReactNode;
71
84
  }
72
85
  interface DiffElement {
73
86
  /** Element name, e.g. `"Pricing"`. */
@@ -150,5 +163,73 @@ interface DiffSectionProps extends HTMLAttributes<HTMLDivElement> {
150
163
  * decision 2026-04-24): each delta reads `live → design`.
151
164
  */
152
165
  declare function DiffSection({ number, name, mismatchCount, elements, defaultExpanded, headerless, onElementToggle, onElementHover, className, ...rest }: DiffSectionProps): react.JSX.Element;
166
+ interface DiffPropertyListProps extends HTMLAttributes<HTMLDivElement> {
167
+ /** Property mismatch rows to render. */
168
+ properties: DiffPropertyLine[];
169
+ }
170
+ /**
171
+ * The bare list of property-delta rows — `property` on the left, a
172
+ * `live → design` mono delta, and an optional `trailing` slot — with the left
173
+ * rule and indent. Extracted from DiffSection so a caller that owns its own
174
+ * card shell (e.g. the extension's IssueCard) can render exactly these rows
175
+ * without DiffSection's element/section chrome. DiffSection uses it internally,
176
+ * so the two surfaces render byte-identical rows.
177
+ */
178
+ declare function DiffPropertyList({ properties, className, ...rest }: DiffPropertyListProps): react.JSX.Element;
179
+
180
+ interface SelectOption {
181
+ value: string;
182
+ label: string;
183
+ /** Secondary line, e.g. an @handle. */
184
+ secondary?: string;
185
+ /** Leading node (avatar / icon) shown in the option and, when selected, the trigger. */
186
+ avatar?: ReactNode;
187
+ disabled?: boolean;
188
+ }
189
+ interface SelectProps {
190
+ options: SelectOption[];
191
+ value?: string | null;
192
+ onChange?: (value: string) => void;
193
+ placeholder?: string;
194
+ label?: ReactNode;
195
+ hint?: ReactNode;
196
+ error?: ReactNode;
197
+ disabled?: boolean;
198
+ /** Show a filter input at the top of the list. */
199
+ searchable?: boolean;
200
+ searchPlaceholder?: string;
201
+ /** Leading node in the trigger; a selected option's `avatar` takes precedence. */
202
+ leadingIcon?: ReactNode;
203
+ id?: string;
204
+ /** When set, renders a hidden input so the value posts with a form. */
205
+ name?: string;
206
+ className?: string;
207
+ containerClassName?: string;
208
+ }
209
+ /**
210
+ * Fidel design-system Select — a listbox (optionally searchable) with avatar +
211
+ * secondary-line options and a checkmark on the selected row. Controlled via
212
+ * `value`/`onChange`. Keyboard: type/Enter/Space/↓ open; ↑/↓/Home/End move;
213
+ * Enter selects; Esc closes; click-outside closes. Measured from Figma "Fidel
214
+ * Library" Select (node 3521:5948).
215
+ */
216
+ declare const Select: react.ForwardRefExoticComponent<SelectProps & react.RefAttributes<HTMLButtonElement>>;
217
+
218
+ type ToggleSize = 'small' | 'medium';
219
+ interface ToggleProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type' | 'size'> {
220
+ /** Size step. @default 'medium' */
221
+ size?: ToggleSize;
222
+ /** Text beside the switch. */
223
+ label?: ReactNode;
224
+ /** Secondary line under the label. */
225
+ description?: ReactNode;
226
+ }
227
+ /**
228
+ * Fidel design-system Toggle (switch). Renders a native checkbox with
229
+ * `role="switch"`; on/off/disabled are handled in CSS, so all standard input
230
+ * attributes (checked, defaultChecked, onChange, disabled, aria-*, …) pass
231
+ * through. Measured from Figma "Fidel Library" Toggle (node 3528:8473).
232
+ */
233
+ declare const Toggle: react.ForwardRefExoticComponent<ToggleProps & react.RefAttributes<HTMLInputElement>>;
153
234
 
154
- export { Button, type ButtonProps, type ButtonSize, type ButtonVariant, type DiffElement, type DiffPropertyLine, DiffSection, type DiffSectionProps, MismatchCard, type MismatchCardProps, type MismatchProperty };
235
+ export { Button, type ButtonProps, type ButtonSize, type ButtonVariant, type DiffElement, type DiffPropertyLine, DiffPropertyList, type DiffPropertyListProps, DiffSection, type DiffSectionProps, MismatchCard, type MismatchCardProps, type MismatchProperty, Select, type SelectOption, type SelectProps, Toggle, type ToggleProps, type ToggleSize };