@flowdrop/flowdrop 2.0.0-beta.2 → 2.0.0-beta.4

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 (113) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/MIGRATION-2.0.md +13 -0
  3. package/README.md +5 -5
  4. package/dist/components/App.svelte +36 -191
  5. package/dist/components/App.svelte.d.ts +2 -7
  6. package/dist/components/Button.stories.svelte +65 -0
  7. package/dist/components/Button.stories.svelte.d.ts +19 -0
  8. package/dist/components/Button.svelte +62 -0
  9. package/dist/components/Button.svelte.d.ts +24 -0
  10. package/dist/components/CanvasIconButton.svelte +76 -0
  11. package/dist/components/CanvasIconButton.svelte.d.ts +18 -0
  12. package/dist/components/ConfigForm.svelte +4 -23
  13. package/dist/components/ConfigPanel.svelte +4 -3
  14. package/dist/components/EditorStatusBar.stories.svelte +44 -0
  15. package/dist/components/EditorStatusBar.stories.svelte.d.ts +27 -0
  16. package/dist/components/EditorStatusBar.svelte +99 -0
  17. package/dist/components/EditorStatusBar.svelte.d.ts +15 -0
  18. package/dist/components/IconButton.svelte +80 -0
  19. package/dist/components/IconButton.svelte.d.ts +30 -0
  20. package/dist/components/Input.svelte +74 -0
  21. package/dist/components/Input.svelte.d.ts +17 -0
  22. package/dist/components/LogoWordmark.svelte +113 -0
  23. package/dist/components/LogoWordmark.svelte.d.ts +26 -0
  24. package/dist/components/Navbar.svelte +17 -63
  25. package/dist/components/Navbar.svelte.d.ts +3 -0
  26. package/dist/components/NodeSidebar.svelte +17 -122
  27. package/dist/components/NodeSwapPicker.svelte +10 -28
  28. package/dist/components/PortMappingRow.svelte +0 -2
  29. package/dist/components/SchemaForm.svelte +0 -12
  30. package/dist/components/Select.svelte +53 -0
  31. package/dist/components/Select.svelte.d.ts +15 -0
  32. package/dist/components/SettingsModal.svelte +0 -5
  33. package/dist/components/SettingsPanel.svelte +2 -6
  34. package/dist/components/Textarea.svelte +39 -0
  35. package/dist/components/Textarea.svelte.d.ts +12 -0
  36. package/dist/components/ThemeToggle.svelte +15 -94
  37. package/dist/components/UniversalNode.svelte +32 -1
  38. package/dist/components/WorkflowEditor.svelte +62 -51
  39. package/dist/components/WorkflowEditor.svelte.d.ts +18 -0
  40. package/dist/components/chat/AIChatPanel.svelte +1 -1
  41. package/dist/components/console/ConsoleAutocomplete.svelte +1 -1
  42. package/dist/components/console/ConsoleOutput.svelte +2 -2
  43. package/dist/components/form/FormArray.svelte +37 -173
  44. package/dist/components/form/FormAutocomplete.svelte +10 -6
  45. package/dist/components/form/FormCheckboxGroup.svelte +1 -5
  46. package/dist/components/form/FormCodeEditor.svelte +9 -7
  47. package/dist/components/form/FormField.svelte +5 -44
  48. package/dist/components/form/FormFieldLight.svelte +8 -47
  49. package/dist/components/form/FormFieldset.svelte +1 -1
  50. package/dist/components/form/FormMarkdownEditor.svelte +8 -5
  51. package/dist/components/form/FormNumberField.svelte +4 -36
  52. package/dist/components/form/FormRangeField.svelte +18 -27
  53. package/dist/components/form/FormSelect.svelte +13 -75
  54. package/dist/components/form/FormTemplateEditor.svelte +6 -4
  55. package/dist/components/form/FormTextField.svelte +3 -35
  56. package/dist/components/form/FormTextarea.svelte +4 -39
  57. package/dist/components/form/FormToggle.svelte +0 -4
  58. package/dist/components/form/resolveFieldType.d.ts +24 -0
  59. package/dist/components/form/resolveFieldType.js +55 -0
  60. package/dist/components/icons/CloseIcon.svelte +6 -0
  61. package/dist/components/icons/CloseIcon.svelte.d.ts +26 -0
  62. package/dist/components/icons/CommandLineIcon.svelte +15 -0
  63. package/dist/components/icons/CommandLineIcon.svelte.d.ts +26 -0
  64. package/dist/components/icons/MenuIcon.svelte +4 -0
  65. package/dist/components/icons/MenuIcon.svelte.d.ts +26 -0
  66. package/dist/components/icons/MenuOpenIcon.svelte +6 -0
  67. package/dist/components/icons/MenuOpenIcon.svelte.d.ts +26 -0
  68. package/dist/components/interrupt/ChoicePrompt.svelte +0 -10
  69. package/dist/components/interrupt/ConfirmationPrompt.svelte +0 -5
  70. package/dist/components/interrupt/InterruptBubble.svelte +0 -10
  71. package/dist/components/interrupt/ReviewPrompt.svelte +0 -20
  72. package/dist/components/interrupt/TextInputPrompt.svelte +0 -6
  73. package/dist/components/layouts/MainLayout.svelte +4 -5
  74. package/dist/components/nodes/AtomNode.svelte +46 -34
  75. package/dist/components/nodes/GatewayNode.svelte +91 -99
  76. package/dist/components/nodes/IdeaNode.svelte +62 -90
  77. package/dist/components/nodes/NodeConfigButton.svelte +86 -0
  78. package/dist/components/nodes/NodeConfigButton.svelte.d.ts +15 -0
  79. package/dist/components/nodes/NotesNode.svelte +70 -81
  80. package/dist/components/nodes/SimpleNode.svelte +28 -78
  81. package/dist/components/nodes/SquareNode.svelte +79 -109
  82. package/dist/components/nodes/TerminalNode.svelte +28 -86
  83. package/dist/components/nodes/ToolNode.svelte +82 -95
  84. package/dist/components/nodes/WorkflowNode.svelte +91 -100
  85. package/dist/components/playground/ChatInput.svelte +0 -1
  86. package/dist/components/playground/InputCollector.svelte +11 -48
  87. package/dist/components/playground/PlaygroundApp.svelte +1 -1
  88. package/dist/components/playground/PlaygroundStudio.svelte +0 -5
  89. package/dist/messages/index.d.ts +1 -1
  90. package/dist/messages/index.js +1 -1
  91. package/dist/openapi/v1/openapi.yaml +2 -2
  92. package/dist/playground/mount.d.ts +9 -5
  93. package/dist/playground/mount.js +9 -5
  94. package/dist/skins/drafter.d.ts +30 -0
  95. package/dist/skins/drafter.js +198 -0
  96. package/dist/skins/index.d.ts +2 -1
  97. package/dist/skins/index.js +4 -2
  98. package/dist/styles/base.css +285 -14
  99. package/dist/styles/tokens.css +60 -2
  100. package/dist/svelte-app.d.ts +6 -0
  101. package/dist/svelte-app.js +71 -109
  102. package/dist/themes/drafter.d.ts +2 -0
  103. package/dist/themes/drafter.js +15 -0
  104. package/dist/themes/index.d.ts +2 -1
  105. package/dist/themes/index.js +8 -2
  106. package/dist/types/events.d.ts +18 -0
  107. package/dist/types/events.js +2 -1
  108. package/dist/types/settings.d.ts +1 -1
  109. package/dist/types/settings.js +1 -1
  110. package/dist/types/skin.d.ts +1 -1
  111. package/dist/types/theme.d.ts +16 -2
  112. package/dist/utils/connections.js +14 -50
  113. package/package.json +1 -1
@@ -19,6 +19,10 @@
19
19
 
20
20
  <script lang="ts">
21
21
  import Icon from '@iconify/svelte';
22
+ import Input from '../Input.svelte';
23
+ import Select from '../Select.svelte';
24
+ import Textarea from '../Textarea.svelte';
25
+ import IconButton from '../IconButton.svelte';
22
26
  import type { FieldSchema } from './types.js';
23
27
  import { m } from '../../messages/index.js';
24
28
 
@@ -284,40 +288,37 @@
284
288
  <!-- Action buttons group -->
285
289
  <div class="form-array__actions">
286
290
  <!-- Move Up button -->
287
- <button
288
- type="button"
289
- class="form-array__action-btn form-array__action-btn--move"
291
+ <IconButton
292
+ variant="primary"
290
293
  onclick={() => moveItemUp(index)}
291
294
  disabled={index === 0 || disabled}
292
- aria-label={t.moveItemUp({ n: index + 1 })}
295
+ ariaLabel={t.moveItemUp({ n: index + 1 })}
293
296
  title={t.moveUp}
294
297
  >
295
298
  <Icon icon="heroicons:arrow-up" />
296
- </button>
299
+ </IconButton>
297
300
 
298
301
  <!-- Move Down button -->
299
- <button
300
- type="button"
301
- class="form-array__action-btn form-array__action-btn--move"
302
+ <IconButton
303
+ variant="primary"
302
304
  onclick={() => moveItemDown(index)}
303
305
  disabled={index === items.length - 1 || disabled}
304
- aria-label={t.moveItemDown({ n: index + 1 })}
306
+ ariaLabel={t.moveItemDown({ n: index + 1 })}
305
307
  title={t.moveDown}
306
308
  >
307
309
  <Icon icon="heroicons:arrow-down" />
308
- </button>
310
+ </IconButton>
309
311
 
310
312
  <!-- Delete button -->
311
- <button
312
- type="button"
313
- class="form-array__action-btn form-array__action-btn--delete"
313
+ <IconButton
314
+ variant="danger"
314
315
  onclick={() => removeItem(index)}
315
316
  disabled={!canRemoveItem || disabled}
316
- aria-label={t.deleteItem({ n: index + 1 })}
317
+ ariaLabel={t.deleteItem({ n: index + 1 })}
317
318
  title={t.delete}
318
319
  >
319
320
  <Icon icon="heroicons:trash" />
320
- </button>
321
+ </IconButton>
321
322
  </div>
322
323
  </div>
323
324
 
@@ -330,18 +331,16 @@
330
331
  <!-- Simple type: render inline input -->
331
332
  {#if itemSchema.type === 'string'}
332
333
  {#if itemSchema.format === 'multiline'}
333
- <textarea
334
- class="form-array__input form-array__textarea"
334
+ <Textarea
335
335
  value={String(item ?? '')}
336
336
  placeholder={itemSchema.placeholder ?? ''}
337
337
  rows={3}
338
338
  oninput={(e) => updateItem(index, e.currentTarget.value)}
339
339
  {disabled}
340
- ></textarea>
340
+ />
341
341
  {:else}
342
- <input
342
+ <Input
343
343
  type="text"
344
- class="form-array__input"
345
344
  value={String(item ?? '')}
346
345
  placeholder={itemSchema.placeholder ?? ''}
347
346
  oninput={(e) => updateItem(index, e.currentTarget.value)}
@@ -349,9 +348,9 @@
349
348
  />
350
349
  {/if}
351
350
  {:else if itemSchema.type === 'number' || itemSchema.type === 'integer'}
352
- <input
351
+ <Input
353
352
  type="number"
354
- class="form-array__input form-array__input--number"
353
+ class="flowdrop-input--numeric"
355
354
  value={item as number}
356
355
  placeholder={itemSchema.placeholder ?? ''}
357
356
  min={itemSchema.minimum}
@@ -380,8 +379,7 @@
380
379
  </label>
381
380
  {:else if itemSchema.enum}
382
381
  <!-- Enum: render select -->
383
- <select
384
- class="form-array__select"
382
+ <Select
385
383
  value={String(item ?? '')}
386
384
  onchange={(e) => updateItem(index, e.currentTarget.value)}
387
385
  {disabled}
@@ -389,12 +387,11 @@
389
387
  {#each itemSchema.enum as option (option)}
390
388
  <option value={String(option)}>{String(option)}</option>
391
389
  {/each}
392
- </select>
390
+ </Select>
393
391
  {:else}
394
392
  <!-- Fallback to text -->
395
- <input
393
+ <Input
396
394
  type="text"
397
- class="form-array__input"
398
395
  value={String(item ?? '')}
399
396
  placeholder={itemSchema.placeholder ?? ''}
400
397
  oninput={(e) => updateItem(index, e.currentTarget.value)}
@@ -425,9 +422,8 @@
425
422
 
426
423
  <div class="form-array__subform-input">
427
424
  {#if propFieldSchema.enum}
428
- <select
425
+ <Select
429
426
  id="{id}-{index}-{propKey}"
430
- class="form-array__select"
431
427
  value={String(propValue ?? '')}
432
428
  onchange={(e) =>
433
429
  updateObjectProperty(index, propKey, e.currentTarget.value)}
@@ -436,23 +432,21 @@
436
432
  {#each propFieldSchema.enum as option (option)}
437
433
  <option value={String(option)}>{String(option)}</option>
438
434
  {/each}
439
- </select>
435
+ </Select>
440
436
  {:else if propFieldSchema.type === 'string' && propFieldSchema.format === 'multiline'}
441
- <textarea
437
+ <Textarea
442
438
  id="{id}-{index}-{propKey}"
443
- class="form-array__input form-array__textarea"
444
439
  value={String(propValue ?? '')}
445
440
  placeholder={propFieldSchema.placeholder ?? ''}
446
441
  rows={3}
447
442
  oninput={(e) =>
448
443
  updateObjectProperty(index, propKey, e.currentTarget.value)}
449
444
  {disabled}
450
- ></textarea>
445
+ />
451
446
  {:else if propFieldSchema.type === 'string'}
452
- <input
447
+ <Input
453
448
  id="{id}-{index}-{propKey}"
454
449
  type="text"
455
- class="form-array__input"
456
450
  value={String(propValue ?? '')}
457
451
  placeholder={propFieldSchema.placeholder ?? ''}
458
452
  oninput={(e) =>
@@ -460,10 +454,10 @@
460
454
  {disabled}
461
455
  />
462
456
  {:else if propFieldSchema.type === 'number' || propFieldSchema.type === 'integer'}
463
- <input
457
+ <Input
464
458
  id="{id}-{index}-{propKey}"
465
459
  type="number"
466
- class="form-array__input form-array__input--number"
460
+ class="flowdrop-input--numeric"
467
461
  value={propValue as number}
468
462
  placeholder={propFieldSchema.placeholder ?? ''}
469
463
  min={propFieldSchema.minimum}
@@ -493,10 +487,9 @@
493
487
  </span>
494
488
  </label>
495
489
  {:else}
496
- <input
490
+ <Input
497
491
  id="{id}-{index}-{propKey}"
498
492
  type="text"
499
- class="form-array__input"
500
493
  value={String(propValue ?? '')}
501
494
  placeholder={propFieldSchema.placeholder ?? ''}
502
495
  oninput={(e) =>
@@ -596,7 +589,7 @@
596
589
  flex-direction: column;
597
590
  background-color: var(--fd-muted);
598
591
  border: 1px solid var(--fd-border);
599
- border-radius: var(--fd-radius-lg);
592
+ border-radius: var(--fd-control-radius);
600
593
  overflow: hidden;
601
594
  animation: itemFadeIn 0.25s ease-out forwards;
602
595
  opacity: 0;
@@ -670,9 +663,7 @@
670
663
  }
671
664
 
672
665
  .form-array__item-toggle:focus-visible {
673
- outline: none;
674
666
  border-color: var(--fd-primary);
675
- box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.2);
676
667
  }
677
668
 
678
669
  .form-array__item-toggle :global(svg) {
@@ -699,67 +690,8 @@
699
690
  margin-left: auto;
700
691
  }
701
692
 
702
- .form-array__action-btn {
703
- display: flex;
704
- align-items: center;
705
- justify-content: center;
706
- width: 2rem;
707
- height: 2rem;
708
- padding: 0;
709
- border: 1px solid transparent;
710
- border-radius: 0.375rem;
711
- cursor: pointer;
712
- transition: all 0.15s;
713
- }
714
-
715
- .form-array__action-btn :global(svg) {
716
- width: 1rem;
717
- height: 1rem;
718
- }
719
-
720
- .form-array__action-btn:focus-visible {
721
- outline: none;
722
- box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.3);
723
- }
724
-
725
- .form-array__action-btn:disabled {
726
- opacity: 0.35;
727
- cursor: not-allowed;
728
- }
729
-
730
- /* Move Up/Down buttons - Blue semantic color */
731
- .form-array__action-btn--move {
732
- background-color: var(--fd-primary-muted);
733
- border-color: var(--fd-primary);
734
- color: var(--fd-primary-hover);
735
- }
736
-
737
- .form-array__action-btn--move:hover:not(:disabled) {
738
- background-color: var(--fd-primary-muted);
739
- border-color: var(--fd-primary-hover);
740
- color: var(--fd-primary-hover);
741
- }
742
-
743
- .form-array__action-btn--move:active:not(:disabled) {
744
- background-color: var(--fd-primary);
745
- }
746
-
747
- /* Delete button - Red/Warning semantic color */
748
- .form-array__action-btn--delete {
749
- background-color: var(--fd-error-muted);
750
- border-color: var(--fd-error);
751
- color: var(--fd-error);
752
- }
753
-
754
- .form-array__action-btn--delete:hover:not(:disabled) {
755
- background-color: var(--fd-error-muted);
756
- border-color: var(--fd-error-hover);
757
- color: var(--fd-error-hover);
758
- }
759
-
760
- .form-array__action-btn--delete:active:not(:disabled) {
761
- background-color: var(--fd-error);
762
- }
693
+ /* Action buttons (move/delete) now render through IconButton.svelte
694
+ geometry + semantic tints live in base.css (.flowdrop-btn--icon*). */
763
695
 
764
696
  /* ============================================
765
697
  ITEM CONTENT
@@ -779,69 +711,6 @@
779
711
  INPUTS (Simple Types)
780
712
  ============================================ */
781
713
 
782
- .form-array__input {
783
- width: 100%;
784
- padding: 0.5rem 0.75rem;
785
- border: 1px solid var(--fd-border);
786
- border-radius: var(--fd-radius-md);
787
- font-size: var(--fd-text-sm);
788
- font-family: inherit;
789
- color: var(--fd-foreground);
790
- background-color: var(--fd-background);
791
- transition: all var(--fd-transition-normal);
792
- }
793
-
794
- .form-array__input::placeholder {
795
- color: var(--fd-muted-foreground);
796
- }
797
-
798
- .form-array__input:hover {
799
- border-color: var(--fd-border-strong);
800
- }
801
-
802
- .form-array__input:focus {
803
- outline: none;
804
- border-color: var(--fd-primary);
805
- box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1);
806
- }
807
-
808
- .form-array__input--number {
809
- font-variant-numeric: tabular-nums;
810
- }
811
-
812
- .form-array__textarea {
813
- resize: vertical;
814
- min-height: 4rem;
815
- line-height: 1.5;
816
- }
817
-
818
- .form-array__select {
819
- width: 100%;
820
- padding: 0.5rem 2rem 0.5rem 0.75rem;
821
- border: 1px solid var(--fd-border);
822
- border-radius: var(--fd-radius-md);
823
- font-size: var(--fd-text-sm);
824
- font-family: inherit;
825
- color: var(--fd-foreground);
826
- background-color: var(--fd-background);
827
- cursor: pointer;
828
- appearance: none;
829
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%239ca3af'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M19 9l-7 7-7-7'%3E%3C/path%3E%3C/svg%3E");
830
- background-repeat: no-repeat;
831
- background-position: right 0.5rem center;
832
- background-size: 1rem;
833
- }
834
-
835
- .form-array__select:hover {
836
- border-color: var(--fd-border-strong);
837
- }
838
-
839
- .form-array__select:focus {
840
- outline: none;
841
- border-color: var(--fd-primary);
842
- box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1);
843
- }
844
-
845
714
  /* ============================================
846
715
  TOGGLE (Boolean in Array)
847
716
  ============================================ */
@@ -958,7 +827,7 @@
958
827
  padding: 2rem 1rem;
959
828
  background-color: var(--fd-muted);
960
829
  border: 2px dashed var(--fd-border-strong);
961
- border-radius: var(--fd-radius-lg);
830
+ border-radius: var(--fd-control-radius);
962
831
  }
963
832
 
964
833
  .form-array__empty :global(svg) {
@@ -986,7 +855,7 @@
986
855
  gap: 0.5rem;
987
856
  padding: 0.625rem 1rem;
988
857
  border: 1px solid var(--fd-success);
989
- border-radius: var(--fd-radius-lg);
858
+ border-radius: var(--fd-control-radius);
990
859
  background-color: var(--fd-success-muted);
991
860
  color: var(--fd-success-hover);
992
861
  font-size: 0.8125rem;
@@ -1002,11 +871,6 @@
1002
871
  color: var(--fd-success-hover);
1003
872
  }
1004
873
 
1005
- .form-array__add-btn:focus-visible {
1006
- outline: none;
1007
- box-shadow: 0 0 0 2px rgba(34, 197, 94, 0.3);
1008
- }
1009
-
1010
874
  .form-array__add-btn:active:not(:disabled) {
1011
875
  background-color: var(--fd-success);
1012
876
  }
@@ -787,7 +787,6 @@
787
787
  }
788
788
 
789
789
  .form-autocomplete--disabled {
790
- opacity: 0.6;
791
790
  pointer-events: none;
792
791
  }
793
792
 
@@ -804,7 +803,7 @@
804
803
  font-size: var(--fd-text-sm);
805
804
  font-family: inherit;
806
805
  color: var(--fd-foreground);
807
- background-color: var(--fd-muted);
806
+ background-color: var(--fd-background);
808
807
  transition: all var(--fd-transition-normal);
809
808
  box-shadow: var(--fd-shadow-sm);
810
809
  cursor: text;
@@ -817,11 +816,16 @@
817
816
  }
818
817
 
819
818
  .form-autocomplete__field--focused {
820
- border-color: var(--fd-primary);
819
+ border-color: var(--fd-ring);
821
820
  background-color: var(--fd-background);
822
- box-shadow:
823
- 0 0 0 3px rgba(59, 130, 246, 0.12),
824
- var(--fd-shadow-sm);
821
+ }
822
+
823
+ .form-autocomplete--disabled .form-autocomplete__field {
824
+ background-color: var(--fd-muted);
825
+ border-color: var(--fd-border-muted);
826
+ color: var(--fd-muted-foreground);
827
+ cursor: not-allowed;
828
+ opacity: 1;
825
829
  }
826
830
 
827
831
  /* Multiple mode - textarea-like styling */
@@ -86,7 +86,7 @@
86
86
  padding: 0.75rem;
87
87
  background-color: var(--fd-muted);
88
88
  border: 1px solid var(--fd-border);
89
- border-radius: var(--fd-radius-lg);
89
+ border-radius: var(--fd-control-radius);
90
90
  }
91
91
 
92
92
  .form-checkbox-item {
@@ -143,10 +143,6 @@
143
143
  transform: scale(1);
144
144
  }
145
145
 
146
- .form-checkbox__input:focus-visible + .form-checkbox__custom {
147
- box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.2);
148
- }
149
-
150
146
  .form-checkbox__label {
151
147
  font-size: var(--fd-text-sm);
152
148
  color: var(--fd-foreground);
@@ -364,7 +364,9 @@
364
364
  border: 1px solid var(--fd-border);
365
365
  border-radius: var(--fd-radius-lg);
366
366
  overflow: hidden;
367
- background-color: var(--fd-muted);
367
+ /* Match plain form fields (FormTextField/Textarea/Select): rest on the
368
+ input surface, not the recessed --fd-muted. */
369
+ background-color: var(--fd-background);
368
370
  transition: all var(--fd-transition-normal);
369
371
  box-shadow: var(--fd-shadow-sm);
370
372
  }
@@ -374,12 +376,15 @@
374
376
  background-color: var(--fd-background);
375
377
  }
376
378
 
379
+ /* Compound widget: the focusable CodeMirror lives inside this container, so
380
+ the standard ring (centralized for simple elements) is drawn here via
381
+ :focus-within using the same --fd-ring tokens. Outline paints outside the
382
+ container's overflow, so it isn't clipped. */
377
383
  .form-code-editor__container:focus-within {
378
384
  border-color: var(--fd-primary);
379
385
  background-color: var(--fd-background);
380
- box-shadow:
381
- 0 0 0 3px rgba(59, 130, 246, 0.12),
382
- var(--fd-shadow-sm);
386
+ outline: var(--fd-ring-width) solid var(--fd-ring);
387
+ outline-offset: var(--fd-ring-offset);
383
388
  }
384
389
 
385
390
  .form-code-editor--error .form-code-editor__container {
@@ -388,9 +393,6 @@
388
393
 
389
394
  .form-code-editor--error .form-code-editor__container:focus-within {
390
395
  border-color: var(--fd-error);
391
- box-shadow:
392
- 0 0 0 3px rgba(239, 68, 68, 0.12),
393
- var(--fd-shadow-sm);
394
396
  }
395
397
 
396
398
  /* Dark theme overrides */
@@ -43,6 +43,7 @@
43
43
  import FormAutocomplete from './FormAutocomplete.svelte';
44
44
  import type { FieldSchema } from './types.js';
45
45
  import { getSchemaOptions } from './types.js';
46
+ import { resolveBaseFieldType } from './resolveFieldType.js';
46
47
  import type { WorkflowNode, WorkflowEdge, AuthProvider } from '../../types/index.js';
47
48
  import { getResolvedTheme } from '../../stores/settingsStore.svelte.js';
48
49
  import { getInstance } from '../../stores/getInstance.svelte.js';
@@ -139,50 +140,10 @@
139
140
  return 'template-editor';
140
141
  }
141
142
 
142
- // Enum with multiple selection -> checkbox group
143
- if (schema.enum && schema.multiple) {
144
- return 'checkbox-group';
145
- }
146
-
147
- // Enum with single selection -> select
148
- if (schema.enum) {
149
- return 'select-enum';
150
- }
151
-
152
- // oneOf with labeled options (standard JSON Schema) -> select
153
- // Must be checked before basic type checks since oneOf schemas often have type: 'string'
154
- if (schema.oneOf && schema.oneOf.length > 0) {
155
- return 'select-options';
156
- }
157
-
158
- // Multiline string -> textarea
159
- if (schema.type === 'string' && schema.format === 'multiline') {
160
- return 'textarea';
161
- }
162
-
163
- // Range slider for number/integer with format: "range"
164
- if ((schema.type === 'number' || schema.type === 'integer') && schema.format === 'range') {
165
- return 'range';
166
- }
167
-
168
- // String -> text field
169
- if (schema.type === 'string') {
170
- return 'text';
171
- }
172
-
173
- // Number or integer -> number field
174
- if (schema.type === 'number' || schema.type === 'integer') {
175
- return 'number';
176
- }
177
-
178
- // Boolean -> toggle
179
- if (schema.type === 'boolean') {
180
- return 'toggle';
181
- }
182
-
183
- // Future: Array type support
184
- if (schema.type === 'array') {
185
- return 'array';
143
+ // Shared basic field resolution (enum/oneOf/primitive types).
144
+ const base = resolveBaseFieldType(schema);
145
+ if (base) {
146
+ return base;
186
147
  }
187
148
 
188
149
  // Object type without specific format -> CodeMirror JSON editor
@@ -48,6 +48,7 @@
48
48
  const fd = getInstance();
49
49
  import type { FieldSchema } from './types.js';
50
50
  import { getSchemaOptions } from './types.js';
51
+ import { resolveBaseFieldType } from './resolveFieldType.js';
51
52
  import type { WorkflowNode, WorkflowEdge } from '../../types/index.js';
52
53
  import type { AuthProvider } from '../../types/auth.js';
53
54
 
@@ -144,50 +145,10 @@
144
145
  return 'code-editor-fallback';
145
146
  }
146
147
 
147
- // Enum with multiple selection -> checkbox group
148
- if (schema.enum && schema.multiple) {
149
- return 'checkbox-group';
150
- }
151
-
152
- // Enum with single selection -> select
153
- if (schema.enum) {
154
- return 'select-enum';
155
- }
156
-
157
- // oneOf with labeled options (standard JSON Schema) -> select
158
- // Must be checked before basic type checks since oneOf schemas often have type: 'string'
159
- if (schema.oneOf && schema.oneOf.length > 0) {
160
- return 'select-options';
161
- }
162
-
163
- // Multiline string -> textarea
164
- if (schema.type === 'string' && schema.format === 'multiline') {
165
- return 'textarea';
166
- }
167
-
168
- // Range slider for number/integer with format: "range"
169
- if ((schema.type === 'number' || schema.type === 'integer') && schema.format === 'range') {
170
- return 'range';
171
- }
172
-
173
- // String -> text field
174
- if (schema.type === 'string') {
175
- return 'text';
176
- }
177
-
178
- // Number or integer -> number field
179
- if (schema.type === 'number' || schema.type === 'integer') {
180
- return 'number';
181
- }
182
-
183
- // Boolean -> toggle
184
- if (schema.type === 'boolean') {
185
- return 'toggle';
186
- }
187
-
188
- // Array type
189
- if (schema.type === 'array') {
190
- return 'array';
148
+ // Shared basic field resolution (enum/oneOf/primitive types).
149
+ const base = resolveBaseFieldType(schema);
150
+ if (base) {
151
+ return base;
191
152
  }
192
153
 
193
154
  // Fallback to text
@@ -233,11 +194,11 @@
233
194
  function getEditorHint(editorType: string): string {
234
195
  switch (editorType) {
235
196
  case 'code-editor-fallback':
236
- return "Code editor requires: import { registerCodeEditorField } from '@flowdrop/flowdrop/form/code'; registerCodeEditorField();";
197
+ return "Code editor not registered. Register it on the instance's field registry: import { registerCodeEditorField } from '@flowdrop/flowdrop/form/code'; registerCodeEditorField(instance.fields);";
237
198
  case 'markdown-editor-fallback':
238
- return "Markdown editor requires: import { registerMarkdownEditorField } from '@flowdrop/flowdrop/form/markdown'; registerMarkdownEditorField();";
199
+ return "Markdown editor not registered. Register it on the instance's field registry: import { registerMarkdownEditorField } from '@flowdrop/flowdrop/form/markdown'; registerMarkdownEditorField(instance.fields);";
239
200
  case 'template-editor-fallback':
240
- return "Template editor requires: import { registerTemplateEditorField } from '@flowdrop/flowdrop/form/code'; registerTemplateEditorField();";
201
+ return "Template editor not registered. Register it on the instance's field registry: import { registerTemplateEditorField } from '@flowdrop/flowdrop/form/code'; registerTemplateEditorField(instance.fields);";
241
202
  default:
242
203
  return 'This field type requires additional registration.';
243
204
  }
@@ -121,7 +121,7 @@
121
121
 
122
122
  .form-fieldset--static {
123
123
  border: 1px solid var(--fd-border-muted);
124
- border-radius: var(--fd-radius-lg);
124
+ border-radius: var(--fd-control-radius);
125
125
  padding: var(--fd-space-xl);
126
126
  margin: 0;
127
127
  }
@@ -641,7 +641,8 @@
641
641
  border: 1px solid var(--fd-border);
642
642
  border-radius: var(--fd-radius-lg);
643
643
  overflow: hidden;
644
- background-color: var(--fd-muted);
644
+ /* Match plain form fields: rest on the input surface, not --fd-muted. */
645
+ background-color: var(--fd-background);
645
646
  transition: border-color var(--fd-transition-normal);
646
647
  }
647
648
 
@@ -655,12 +656,13 @@
655
656
  border-color: var(--fd-border-strong);
656
657
  }
657
658
 
659
+ /* Compound widget: ring drawn on the body via :focus-within, using the
660
+ standard --fd-ring tokens (outline isn't clipped by the container overflow). */
658
661
  .form-markdown-editor__body:focus-within {
659
662
  border-color: var(--fd-primary);
660
663
  background-color: var(--fd-background);
661
- box-shadow:
662
- 0 0 0 3px var(--fd-primary-muted),
663
- var(--fd-shadow-sm);
664
+ outline: var(--fd-ring-width) solid var(--fd-ring);
665
+ outline-offset: var(--fd-ring-offset);
664
666
  }
665
667
 
666
668
  /* ── Status bar ────────────────────────────────── */
@@ -702,7 +704,8 @@
702
704
 
703
705
  .form-markdown-editor__body :global(.cm-editor) {
704
706
  height: var(--editor-height, 300px);
705
- background-color: var(--fd-muted) !important;
707
+ /* Match plain form fields: white input surface (overrides oneDark in dark mode). */
708
+ background-color: var(--fd-background) !important;
706
709
  color: var(--fd-foreground) !important;
707
710
  }
708
711