@stubber/form-fields 1.7.1 → 1.7.3

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.
@@ -79,15 +79,23 @@ const move_value_down = (index) => {
79
79
  $fieldStore.value = new_value;
80
80
  }
81
81
  };
82
+ let open = true;
82
83
  </script>
83
84
 
84
- <Collapsible.Root open={true} class="w-full">
85
+ <Collapsible.Root bind:open class="w-full">
85
86
  <Collapsible.Trigger asChild let:builder>
86
- <Button builders={[builder]} variant="ghost" class="w-full justify-between pl-0">
87
+ <Button builders={[builder]} variant="ghost" class="w-full justify-between px-0">
87
88
  <Label>{$fieldStore.label}</Label>
88
89
  <FieldMessage {fieldStore} />
89
90
 
90
- <i class="fa fa-sort" />
91
+ <div class="flex items-center">
92
+ {#if open}
93
+ <i class="fa fa-caret-down pr-1" />
94
+ {:else}
95
+ <i class="fa fa-caret-right pr-1" />
96
+ {/if}
97
+ <FieldExprToggle {fieldStore} />
98
+ </div>
91
99
  </Button>
92
100
  </Collapsible.Trigger>
93
101
  <Collapsible.Content class="flex flex-col gap-y-1 pl-2">
@@ -11,10 +11,7 @@ export const code_field_param_spec = {
11
11
  };
12
12
  </script>
13
13
 
14
- <script>import { Textarea } from "@stubber/ui/textarea";
15
- import FieldLabel from "../FieldLabel.svelte";
16
- import FieldMessage from "../FieldMessage.svelte";
17
- import {
14
+ <script>import {
18
15
  acceptCompletion,
19
16
  autocompletion,
20
17
  CompletionContext,
@@ -25,7 +22,11 @@ import { javascript, javascriptLanguage } from "@codemirror/lang-javascript";
25
22
  import { EditorState } from "@codemirror/state";
26
23
  import { EditorView, keymap } from "@codemirror/view";
27
24
  import { basicSetup } from "codemirror";
25
+ import { getContext } from "svelte";
26
+ import FieldLabel from "../FieldLabel.svelte";
27
+ import FieldMessage from "../FieldMessage.svelte";
28
28
  export let fieldStore;
29
+ const code_fields_ctx_store = getContext("code_fields_ctx");
29
30
  let value = $fieldStore.value || "";
30
31
  let editor_view;
31
32
  const custom_completion_keymap = completionKeymap.filter((binding) => binding.key != "Enter").concat([
@@ -54,16 +55,21 @@ function globalCompletions(ctx) {
54
55
  const text = m?.text ?? "";
55
56
  const trailingDot = text.endsWith(".");
56
57
  const parts = (trailingDot ? text.slice(0, -1) : text).split(".").filter(Boolean);
57
- let container = $fieldStore.params?.globals || {};
58
+ let global_context = {};
59
+ if ($code_fields_ctx_store) {
60
+ global_context = $code_fields_ctx_store;
61
+ } else {
62
+ global_context = $fieldStore.params?.globals || {};
63
+ }
58
64
  for (let i = 0; i < Math.max(0, parts.length - (trailingDot ? 0 : 1)); i++) {
59
- container = container?.[parts[i]];
60
- if (!container) break;
65
+ global_context = global_context?.[parts[i]];
66
+ if (!global_context) break;
61
67
  }
62
68
  const last = trailingDot ? "" : parts[parts.length - 1] ?? "";
63
69
  const from = ctx.pos - last.length;
64
70
  return {
65
71
  from,
66
- options: keysFor(container).map((key) => ({
72
+ options: keysFor(global_context).map((key) => ({
67
73
  label: key,
68
74
  type: "property"
69
75
  // 👈 simplified
@@ -137,7 +143,7 @@ const sync_field_to_value = (new_value) => {
137
143
  };
138
144
  </script>
139
145
 
140
- <div class="flex flex-col w-full my-2">
146
+ <div class="my-2 flex w-full flex-col">
141
147
  <FieldLabel {fieldStore} />
142
148
  <div class="relative rounded-md">
143
149
  <div use:bind_codemirror />
@@ -243,6 +243,13 @@ function update_subfields_from_value(new_value) {
243
243
  subfields_store.set({ fields: cloneDeep(new_value) || {} });
244
244
  }
245
245
  }
246
+ let basic_info_open = true;
247
+ let sub_fields_open = true;
248
+ let params_open = false;
249
+ let details_open = false;
250
+ let initial_value_open = false;
251
+ let conditions_open = false;
252
+ let validations_open = false;
246
253
  </script>
247
254
 
248
255
  <FieldLabel {fieldStore} />
@@ -280,12 +287,18 @@ function update_subfields_from_value(new_value) {
280
287
  </Popover.Content>
281
288
  </Popover.Root>
282
289
  <!-- basic props -->
283
- <Collapsible.Root open={true} class="w-full">
290
+ <Collapsible.Root bind:open={basic_info_open} class="w-full">
284
291
  <Collapsible.Trigger asChild let:builder>
285
292
  <Button builders={[builder]} variant="ghost" class="w-full justify-between pl-0">
286
293
  <Label>Basic Info</Label>
287
294
 
288
- <i class="fa fa-sort" />
295
+ <div class="flex items-center">
296
+ {#if basic_info_open}
297
+ <i class="fa fa-caret-down" />
298
+ {:else}
299
+ <i class="fa fa-caret-right" />
300
+ {/if}
301
+ </div>
289
302
  </Button>
290
303
  </Collapsible.Trigger>
291
304
 
@@ -319,12 +332,18 @@ function update_subfields_from_value(new_value) {
319
332
  <hr />
320
333
  <!-- subfields -->
321
334
  {#if value.fieldtype === "section" || value.fieldtype === "multistep"}
322
- <Collapsible.Root open={false} class="w-full">
335
+ <Collapsible.Root bind:open={sub_fields_open} class="w-full">
323
336
  <Collapsible.Trigger asChild let:builder>
324
337
  <Button builders={[builder]} variant="ghost" class="w-full justify-between pl-0">
325
338
  <Label>Fields</Label>
326
339
 
327
- <i class="fa fa-sort" />
340
+ <div class="flex items-center">
341
+ {#if sub_fields_open}
342
+ <i class="fa fa-caret-down" />
343
+ {:else}
344
+ <i class="fa fa-caret-right" />
345
+ {/if}
346
+ </div>
328
347
  </Button>
329
348
  </Collapsible.Trigger>
330
349
 
@@ -360,12 +379,18 @@ function update_subfields_from_value(new_value) {
360
379
  {/if}
361
380
 
362
381
  <!-- params -->
363
- <Collapsible.Root open={false} class="w-full">
382
+ <Collapsible.Root bind:open={params_open} class="w-full">
364
383
  <Collapsible.Trigger asChild let:builder>
365
384
  <Button builders={[builder]} variant="ghost" class="w-full justify-between pl-0">
366
385
  <Label>Params</Label>
367
386
 
368
- <i class="fa fa-sort" />
387
+ <div class="flex items-center">
388
+ {#if params_open}
389
+ <i class="fa fa-caret-down" />
390
+ {:else}
391
+ <i class="fa fa-caret-right" />
392
+ {/if}
393
+ </div>
369
394
  </Button>
370
395
  </Collapsible.Trigger>
371
396
 
@@ -385,12 +410,18 @@ function update_subfields_from_value(new_value) {
385
410
  </Collapsible.Root>
386
411
  <hr />
387
412
  <!-- details -->
388
- <Collapsible.Root open={false} class="w-full">
413
+ <Collapsible.Root bind:open={details_open} class="w-full">
389
414
  <Collapsible.Trigger asChild let:builder>
390
415
  <Button builders={[builder]} variant="ghost" class="w-full justify-between pl-0">
391
416
  <Label>Details</Label>
392
417
 
393
- <i class="fa fa-sort" />
418
+ <div class="flex items-center">
419
+ {#if details_open}
420
+ <i class="fa fa-caret-down" />
421
+ {:else}
422
+ <i class="fa fa-caret-right" />
423
+ {/if}
424
+ </div>
394
425
  </Button>
395
426
  </Collapsible.Trigger>
396
427
 
@@ -415,12 +446,18 @@ function update_subfields_from_value(new_value) {
415
446
  </Collapsible.Root>
416
447
  <hr />
417
448
  <!-- initial value -->
418
- <Collapsible.Root open={false} class="w-full">
449
+ <Collapsible.Root bind:open={initial_value_open} class="w-full">
419
450
  <Collapsible.Trigger asChild let:builder>
420
451
  <Button builders={[builder]} variant="ghost" class="w-full justify-between pl-0">
421
452
  <Label>Initial Value</Label>
422
453
 
423
- <i class="fa fa-sort" />
454
+ <div class="flex items-center">
455
+ {#if initial_value_open}
456
+ <i class="fa fa-caret-down" />
457
+ {:else}
458
+ <i class="fa fa-caret-right" />
459
+ {/if}
460
+ </div>
424
461
  </Button>
425
462
  </Collapsible.Trigger>
426
463
 
@@ -443,12 +480,18 @@ function update_subfields_from_value(new_value) {
443
480
  </Collapsible.Root>
444
481
  <hr />
445
482
  <!-- conditions -->
446
- <Collapsible.Root open={false} class="w-full">
483
+ <Collapsible.Root bind:open={conditions_open} class="w-full">
447
484
  <Collapsible.Trigger asChild let:builder>
448
485
  <Button builders={[builder]} variant="ghost" class="w-full justify-between pl-0">
449
486
  <Label>Conditions</Label>
450
487
 
451
- <i class="fa fa-sort" />
488
+ <div class="flex items-center">
489
+ {#if conditions_open}
490
+ <i class="fa fa-caret-down" />
491
+ {:else}
492
+ <i class="fa fa-caret-right" />
493
+ {/if}
494
+ </div>
452
495
  </Button>
453
496
  </Collapsible.Trigger>
454
497
 
@@ -498,12 +541,18 @@ function update_subfields_from_value(new_value) {
498
541
  </Collapsible.Root>
499
542
  <hr />
500
543
  <!-- validations -->
501
- <Collapsible.Root open={false} class="w-full">
544
+ <Collapsible.Root bind:open={validations_open} class="w-full">
502
545
  <Collapsible.Trigger asChild let:builder>
503
546
  <Button builders={[builder]} variant="ghost" class="w-full justify-between pl-0">
504
547
  <Label>Validations</Label>
505
548
 
506
- <i class="fa fa-sort" />
549
+ <div class="flex items-center">
550
+ {#if validations_open}
551
+ <i class="fa fa-caret-down" />
552
+ {:else}
553
+ <i class="fa fa-caret-right" />
554
+ {/if}
555
+ </div>
507
556
  </Button>
508
557
  </Collapsible.Trigger>
509
558
 
@@ -68,15 +68,23 @@ const make_key_unique = (key) => {
68
68
  }
69
69
  return unique_key;
70
70
  };
71
+ let open = true;
71
72
  </script>
72
73
 
73
- <Collapsible.Root open={true} class="w-full">
74
+ <Collapsible.Root bind:open class="w-full">
74
75
  <Collapsible.Trigger asChild let:builder>
75
- <Button builders={[builder]} variant="ghost" class="w-full justify-between pl-0">
76
+ <Button builders={[builder]} variant="ghost" class="w-full justify-between px-0">
76
77
  <Label>{$fieldStore.label}</Label>
77
78
  <FieldMessage {fieldStore} />
78
79
 
79
- <i class="fa fa-sort" />
80
+ <div class="flex items-center">
81
+ {#if open}
82
+ <i class="fa fa-caret-down pr-1" />
83
+ {:else}
84
+ <i class="fa fa-caret-right pr-1" />
85
+ {/if}
86
+ <FieldExprToggle {fieldStore} />
87
+ </div>
80
88
  </Button>
81
89
  </Collapsible.Trigger>
82
90
  <Collapsible.Content class="flex flex-col gap-y-1 pl-2">
@@ -121,7 +129,6 @@ const make_key_unique = (key) => {
121
129
  <Button size="icon" variant="outline" on:click={add_value}>
122
130
  <i class="fa fa-plus" />
123
131
  </Button>
124
- <FieldExprToggle {fieldStore} />
125
132
  </div>
126
133
  </Collapsible.Content>
127
134
  </Collapsible.Root>
@@ -3,21 +3,28 @@
3
3
 
4
4
  <script>import { Button } from "@stubber/ui/button";
5
5
  import * as Collapsible from "@stubber/ui/collapsible";
6
- import FieldLabel from "../FieldLabel.svelte";
7
6
  import FieldMessage from "../FieldMessage.svelte";
8
7
  import FormField from "../form-field.svelte";
9
8
  import { Label } from "@stubber/ui/label";
10
9
  import FieldExprToggle from "../FieldExprToggle.svelte";
11
10
  export let fieldStore;
11
+ let open = true;
12
12
  </script>
13
13
 
14
- <Collapsible.Root open={true} class="w-full">
14
+ <Collapsible.Root bind:open class="w-full">
15
15
  <Collapsible.Trigger asChild let:builder>
16
- <Button builders={[builder]} variant="ghost" class="w-full justify-between pl-0">
16
+ <Button builders={[builder]} variant="ghost" class="w-full justify-between px-0">
17
17
  <Label>{$fieldStore.label}</Label>
18
18
  <FieldMessage {fieldStore} />
19
19
 
20
- <i class="fa fa-sort" />
20
+ <div class="flex items-center">
21
+ {#if open}
22
+ <i class="fa fa-caret-down pr-1" />
23
+ {:else}
24
+ <i class="fa fa-caret-right pr-1" />
25
+ {/if}
26
+ <FieldExprToggle {fieldStore} />
27
+ </div>
21
28
  </Button>
22
29
  </Collapsible.Trigger>
23
30
 
@@ -25,6 +32,5 @@ export let fieldStore;
25
32
  {#each $fieldStore.sub_fields || [] as sub_field (get_store_value(sub_field).id)}
26
33
  <FormField fieldStore={sub_field} />
27
34
  {/each}
28
- <FieldExprToggle {fieldStore} />
29
35
  </Collapsible.Content>
30
36
  </Collapsible.Root>
@@ -48,7 +48,7 @@ const map_field_options = (options) => {
48
48
  if (!options || !Array.isArray(options)) {
49
49
  return [];
50
50
  }
51
- return options.map((option, index) => {
51
+ return options.filter(Boolean).map((option, index) => {
52
52
  const key = `${option.label}${index}`;
53
53
  return {
54
54
  label: option.label,
@@ -102,19 +102,19 @@ const handle_select = (item_key, trigger) => {
102
102
  variant="outline"
103
103
  role="combobox"
104
104
  aria-expanded={open}
105
- class="w-full border-input bg-white bg-opacity-[15] ring-offset-background placeholder:text-muted-foreground focus-visible:ring-ring flex h-10 rounded-md border px-3 py-2 text-sm file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 justify-between"
105
+ class="flex h-10 w-full justify-between rounded-md border border-input bg-white bg-opacity-[15] px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
106
106
  style="box-shadow: inset 0px 16px 16px -16px rgba(0, 0, 0, 0.1333);"
107
107
  >
108
108
  {dropdownLabel}
109
109
  <i class="fas fa-sort ml-2 h-4 w-4 shrink-0 opacity-50" />
110
110
  </Button>
111
111
  </Popover.Trigger>
112
- <Popover.Content sameWidth class="p-0 z-[100]">
112
+ <Popover.Content sameWidth class="z-[100] p-0">
113
113
  <Command.Root shouldFilter={!load_options} {state}>
114
114
  <Command.Input class="border-none outline-none focus:ring-0" placeholder="Search..." />
115
115
  <Command.List>
116
116
  {#if loading}
117
- <Command.Loading class="py-6 text-sm text-center">Loading…</Command.Loading>
117
+ <Command.Loading class="py-6 text-center text-sm">Loading…</Command.Loading>
118
118
  {:else}
119
119
  <Command.Empty>No results found.</Command.Empty>
120
120
 
@@ -69,14 +69,15 @@ import {
69
69
  import { find } from "lodash-es";
70
70
  import FieldLabel from "../FieldLabel.svelte";
71
71
  import FieldMessage from "../FieldMessage.svelte";
72
+ import { getContext } from "svelte";
72
73
  export let fieldStore;
73
74
  let editor_view;
74
75
  $: validation_result = $fieldStore.validation_result;
75
76
  $: type = validation_result?.type;
76
77
  $: isValid = type !== "error";
77
78
  $: is_object = typeof $fieldStore.value === "object";
79
+ const smart_text_fields_ctx_store = getContext("smart_text_fields_ctx");
78
80
  $: parse_string = $fieldStore.params?.parse_string;
79
- $: auto_completions = $fieldStore.params?.auto_completions || [];
80
81
  $: code_language = $fieldStore.params?.code_language;
81
82
  const setup_editor = (element) => {
82
83
  const extensions = [
@@ -166,6 +167,7 @@ function fake_handlebars_lang() {
166
167
  );
167
168
  }
168
169
  function myCompletions(context) {
170
+ const auto_completions = $smart_text_fields_ctx_store || $fieldStore.params?.auto_completions || [];
169
171
  for (let completion of auto_completions) {
170
172
  if (!completion.match_before) continue;
171
173
  let before = context.matchBefore(new RegExp(completion.match_before));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stubber/form-fields",
3
- "version": "1.7.1",
3
+ "version": "1.7.3",
4
4
  "description": "An automatic form builder based on field specifications",
5
5
  "keywords": [
6
6
  "components",