@lobb-js/studio 0.47.0 → 0.49.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.
Files changed (72) hide show
  1. package/dist/actions.d.ts +2 -28
  2. package/dist/actions.js +4 -60
  3. package/dist/components/detailView/detailView.svelte +12 -62
  4. package/dist/components/detailView/detailView.svelte.d.ts +1 -1
  5. package/dist/components/detailView/fieldInput.svelte +161 -288
  6. package/dist/components/detailView/fieldInput.svelte.d.ts +1 -1
  7. package/dist/components/detailView/fields/BoolField.svelte +42 -0
  8. package/dist/components/detailView/fields/BoolField.svelte.d.ts +13 -0
  9. package/dist/components/detailView/fields/CodeField.svelte +30 -0
  10. package/dist/components/detailView/fields/CodeField.svelte.d.ts +13 -0
  11. package/dist/components/detailView/fields/CustomInputField.svelte +50 -0
  12. package/dist/components/detailView/fields/CustomInputField.svelte.d.ts +18 -0
  13. package/dist/components/detailView/fields/DateField.svelte +47 -0
  14. package/dist/components/detailView/fields/DateField.svelte.d.ts +14 -0
  15. package/dist/components/detailView/fields/EmbeddedField.svelte +139 -0
  16. package/dist/components/detailView/fields/EmbeddedField.svelte.d.ts +13 -0
  17. package/dist/components/detailView/fields/EmbeddedPolymorphicField.svelte +197 -0
  18. package/dist/components/detailView/fields/EmbeddedPolymorphicField.svelte.d.ts +13 -0
  19. package/dist/components/detailView/fields/EnumField.svelte +70 -0
  20. package/dist/components/detailView/fields/EnumField.svelte.d.ts +17 -0
  21. package/dist/components/detailView/fields/FieldWrapper.svelte +68 -0
  22. package/dist/components/detailView/fields/FieldWrapper.svelte.d.ts +18 -0
  23. package/dist/components/detailView/fields/ForeignKeyField.svelte +78 -0
  24. package/dist/components/detailView/fields/ForeignKeyField.svelte.d.ts +17 -0
  25. package/dist/components/detailView/fields/IdField.svelte +21 -0
  26. package/dist/components/detailView/fields/IdField.svelte.d.ts +12 -0
  27. package/dist/components/detailView/fields/NumberField.svelte +38 -0
  28. package/dist/components/detailView/fields/NumberField.svelte.d.ts +16 -0
  29. package/dist/components/detailView/fields/PasswordField.svelte +29 -0
  30. package/dist/components/detailView/fields/PasswordField.svelte.d.ts +12 -0
  31. package/dist/components/detailView/fields/PolymorphicField.svelte +51 -0
  32. package/dist/components/detailView/fields/PolymorphicField.svelte.d.ts +16 -0
  33. package/dist/components/detailView/fields/RichTextField.svelte +30 -0
  34. package/dist/components/detailView/fields/RichTextField.svelte.d.ts +13 -0
  35. package/dist/components/detailView/fields/StringField.svelte +35 -0
  36. package/dist/components/detailView/fields/StringField.svelte.d.ts +14 -0
  37. package/dist/components/detailView/fields/TextField.svelte +35 -0
  38. package/dist/components/detailView/fields/TextField.svelte.d.ts +14 -0
  39. package/dist/components/foreingKeyInput.svelte +1 -1
  40. package/dist/components/polymorphicInput.svelte +1 -1
  41. package/dist/components/popup/popup.svelte +23 -4
  42. package/dist/components/popup/popup.svelte.d.ts +2 -0
  43. package/dist/extensions/extension.types.d.ts +5 -2
  44. package/dist/extensions/extensionUtils.js +4 -1
  45. package/dist/popup.d.ts +31 -0
  46. package/dist/popup.js +104 -0
  47. package/package.json +7 -6
  48. package/src/lib/actions.ts +5 -95
  49. package/src/lib/components/detailView/detailView.svelte +12 -62
  50. package/src/lib/components/detailView/fieldInput.svelte +161 -288
  51. package/src/lib/components/detailView/fields/BoolField.svelte +42 -0
  52. package/src/lib/components/detailView/fields/CodeField.svelte +30 -0
  53. package/src/lib/components/detailView/fields/CustomInputField.svelte +50 -0
  54. package/src/lib/components/detailView/fields/DateField.svelte +47 -0
  55. package/src/lib/components/detailView/fields/EmbeddedField.svelte +139 -0
  56. package/src/lib/components/detailView/fields/EmbeddedPolymorphicField.svelte +197 -0
  57. package/src/lib/components/detailView/fields/EnumField.svelte +70 -0
  58. package/src/lib/components/detailView/fields/FieldWrapper.svelte +68 -0
  59. package/src/lib/components/detailView/fields/ForeignKeyField.svelte +78 -0
  60. package/src/lib/components/detailView/fields/IdField.svelte +21 -0
  61. package/src/lib/components/detailView/fields/NumberField.svelte +38 -0
  62. package/src/lib/components/detailView/fields/PasswordField.svelte +29 -0
  63. package/src/lib/components/detailView/fields/PolymorphicField.svelte +51 -0
  64. package/src/lib/components/detailView/fields/RichTextField.svelte +30 -0
  65. package/src/lib/components/detailView/fields/StringField.svelte +35 -0
  66. package/src/lib/components/detailView/fields/TextField.svelte +35 -0
  67. package/src/lib/components/foreingKeyInput.svelte +1 -1
  68. package/src/lib/components/polymorphicInput.svelte +1 -1
  69. package/src/lib/components/popup/popup.svelte +23 -4
  70. package/src/lib/extensions/extension.types.ts +4 -2
  71. package/src/lib/extensions/extensionUtils.ts +4 -1
  72. package/src/lib/popup.ts +147 -0
@@ -0,0 +1,78 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+ import { getStudioContext } from "../../../context";
4
+ import { getExtensionUtils, loadExtensionComponents } from "../../../extensions/extensionUtils";
5
+ import ForeingKeyInput from "../../foreingKeyInput.svelte";
6
+ import ExtensionsComponents from "../../extensionsComponents.svelte";
7
+ import FieldWrapper from "./FieldWrapper.svelte";
8
+
9
+ const { lobb, ctx } = getStudioContext();
10
+
11
+ interface Props {
12
+ parentCollectionName: string;
13
+ collectionName: string;
14
+ fieldName: string;
15
+ value?: any;
16
+ entry?: Record<string, any>;
17
+ destructive?: boolean;
18
+ changedClass?: string;
19
+ isDisabled?: boolean;
20
+ errorMessages?: any;
21
+ header?: any;
22
+ clearBtn?: Snippet<[]>;
23
+ }
24
+
25
+ let {
26
+ parentCollectionName,
27
+ collectionName,
28
+ fieldName,
29
+ value = $bindable(),
30
+ entry = $bindable(),
31
+ destructive = false,
32
+ isDisabled = false,
33
+ errorMessages = [],
34
+ header,
35
+ clearBtn,
36
+ }: Props = $props();
37
+
38
+ const hasExtension = $derived(
39
+ loadExtensionComponents(ctx, `detailView.fields.foreignKey.${collectionName}`).length > 0
40
+ );
41
+ </script>
42
+
43
+ {#if hasExtension}
44
+ <ExtensionsComponents
45
+ name="detailView.fields.foreignKey.{collectionName}"
46
+ utils={getExtensionUtils(lobb, ctx)}
47
+ {parentCollectionName}
48
+ {collectionName}
49
+ bind:value
50
+ entry={entry!}
51
+ {fieldName}
52
+ {destructive}
53
+ {header}
54
+ {isDisabled}
55
+ {errorMessages}
56
+ {clearBtn}
57
+ />
58
+ {:else}
59
+ <FieldWrapper span={1} {isDisabled} {errorMessages} {header}>
60
+ {#snippet children()}
61
+ <div class="relative">
62
+ {#if clearBtn}
63
+ <div class="absolute right-1 top-1 z-10">
64
+ {@render clearBtn()}
65
+ </div>
66
+ {/if}
67
+ <ForeingKeyInput
68
+ {parentCollectionName}
69
+ {collectionName}
70
+ bind:value
71
+ entry={entry!}
72
+ {fieldName}
73
+ {destructive}
74
+ />
75
+ </div>
76
+ {/snippet}
77
+ </FieldWrapper>
78
+ {/if}
@@ -0,0 +1,17 @@
1
+ import type { Snippet } from "svelte";
2
+ interface Props {
3
+ parentCollectionName: string;
4
+ collectionName: string;
5
+ fieldName: string;
6
+ value?: any;
7
+ entry?: Record<string, any>;
8
+ destructive?: boolean;
9
+ changedClass?: string;
10
+ isDisabled?: boolean;
11
+ errorMessages?: any;
12
+ header?: any;
13
+ clearBtn?: Snippet<[]>;
14
+ }
15
+ declare const ForeignKeyField: import("svelte").Component<Props, {}, "value" | "entry">;
16
+ type ForeignKeyField = ReturnType<typeof ForeignKeyField>;
17
+ export default ForeignKeyField;
@@ -0,0 +1,21 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+ import Input from "../../ui/input/input.svelte";
4
+ import FieldWrapper from "./FieldWrapper.svelte";
5
+
6
+ interface Props {
7
+ value?: any;
8
+ changedClass?: string;
9
+ isDisabled?: boolean;
10
+ errorMessages?: any;
11
+ header?: any;
12
+ clearBtn?: Snippet<[]>;
13
+ }
14
+ let { value = $bindable(), changedClass = '', isDisabled = false, errorMessages = [], header, clearBtn }: Props = $props();
15
+ </script>
16
+
17
+ <FieldWrapper span={1} {isDisabled} {errorMessages} {header}>
18
+ {#snippet children()}
19
+ <Input placeholder="AUTO GENERATED" class="bg-muted text-xs {changedClass}" bind:value />
20
+ {/snippet}
21
+ </FieldWrapper>
@@ -0,0 +1,12 @@
1
+ import type { Snippet } from "svelte";
2
+ interface Props {
3
+ value?: any;
4
+ changedClass?: string;
5
+ isDisabled?: boolean;
6
+ errorMessages?: any;
7
+ header?: any;
8
+ clearBtn?: Snippet<[]>;
9
+ }
10
+ declare const IdField: import("svelte").Component<Props, {}, "value">;
11
+ type IdField = ReturnType<typeof IdField>;
12
+ export default IdField;
@@ -0,0 +1,38 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+ import NumberInput from "../../ui/input/numberInput.svelte";
4
+ import FieldWrapper from "./FieldWrapper.svelte";
5
+
6
+ interface Props {
7
+ value?: any;
8
+ scale?: number;
9
+ groupDigits?: boolean;
10
+ placeholder?: string;
11
+ destructive?: boolean;
12
+ changedClass?: string;
13
+ isDisabled?: boolean;
14
+ errorMessages?: any;
15
+ header?: any;
16
+ clearBtn?: Snippet<[]>;
17
+ }
18
+ let { value = $bindable(), scale = 0, groupDigits = false, placeholder = "NULL", destructive = false, changedClass = '', isDisabled = false, errorMessages = [], header, clearBtn }: Props = $props();
19
+ </script>
20
+
21
+ <FieldWrapper span={1} {isDisabled} {errorMessages} {header}>
22
+ {#snippet children()}
23
+ <div class="relative">
24
+ {#if clearBtn}
25
+ <div class="absolute right-1 inset-y-0 z-10 flex items-center">
26
+ {@render clearBtn()}
27
+ </div>
28
+ {/if}
29
+ <NumberInput
30
+ {placeholder}
31
+ {scale}
32
+ {groupDigits}
33
+ class="bg-muted text-xs pr-9 {changedClass} {destructive ? 'border-destructive' : ''}"
34
+ bind:value
35
+ />
36
+ </div>
37
+ {/snippet}
38
+ </FieldWrapper>
@@ -0,0 +1,16 @@
1
+ import type { Snippet } from "svelte";
2
+ interface Props {
3
+ value?: any;
4
+ scale?: number;
5
+ groupDigits?: boolean;
6
+ placeholder?: string;
7
+ destructive?: boolean;
8
+ changedClass?: string;
9
+ isDisabled?: boolean;
10
+ errorMessages?: any;
11
+ header?: any;
12
+ clearBtn?: Snippet<[]>;
13
+ }
14
+ declare const NumberField: import("svelte").Component<Props, {}, "value">;
15
+ type NumberField = ReturnType<typeof NumberField>;
16
+ export default NumberField;
@@ -0,0 +1,29 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+ import PasswordInput from "../passwordInput.svelte";
4
+ import FieldWrapper from "./FieldWrapper.svelte";
5
+
6
+ interface Props {
7
+ value?: any;
8
+ destructive?: boolean;
9
+ isDisabled?: boolean;
10
+ errorMessages?: any;
11
+ header?: any;
12
+ clearBtn?: Snippet<[]>;
13
+ }
14
+
15
+ let { value = $bindable(), destructive = false, isDisabled = false, errorMessages = [], header, clearBtn }: Props = $props();
16
+ </script>
17
+
18
+ <FieldWrapper span={1} {isDisabled} {errorMessages} {header}>
19
+ {#snippet children()}
20
+ <div class="relative">
21
+ {#if clearBtn}
22
+ <div class="absolute right-1 inset-y-0 z-10 flex items-center">
23
+ {@render clearBtn()}
24
+ </div>
25
+ {/if}
26
+ <PasswordInput bind:value {destructive} />
27
+ </div>
28
+ {/snippet}
29
+ </FieldWrapper>
@@ -0,0 +1,12 @@
1
+ import type { Snippet } from "svelte";
2
+ interface Props {
3
+ value?: any;
4
+ destructive?: boolean;
5
+ isDisabled?: boolean;
6
+ errorMessages?: any;
7
+ header?: any;
8
+ clearBtn?: Snippet<[]>;
9
+ }
10
+ declare const PasswordField: import("svelte").Component<Props, {}, "value">;
11
+ type PasswordField = ReturnType<typeof PasswordField>;
12
+ export default PasswordField;
@@ -0,0 +1,51 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+ import PolymorphicInput from "../../polymorphicInput.svelte";
4
+ import FieldWrapper from "./FieldWrapper.svelte";
5
+
6
+ interface Props {
7
+ collectionField: string;
8
+ idField: string;
9
+ virtualField: string;
10
+ targetCollections: string[];
11
+ entry: Record<string, any>;
12
+ destructive?: boolean;
13
+ isDisabled?: boolean;
14
+ errorMessages?: any;
15
+ header?: any;
16
+ clearBtn?: Snippet<[]>;
17
+ }
18
+
19
+ let {
20
+ collectionField,
21
+ idField,
22
+ virtualField,
23
+ targetCollections,
24
+ entry = $bindable(),
25
+ destructive = false,
26
+ isDisabled = false,
27
+ errorMessages = [],
28
+ header,
29
+ clearBtn,
30
+ }: Props = $props();
31
+ </script>
32
+
33
+ <FieldWrapper span={2} {isDisabled} {errorMessages} {header}>
34
+ {#snippet children()}
35
+ <div class="relative">
36
+ {#if clearBtn}
37
+ <div class="absolute right-1 inset-y-0 z-10 flex items-center">
38
+ {@render clearBtn()}
39
+ </div>
40
+ {/if}
41
+ <PolymorphicInput
42
+ {collectionField}
43
+ {idField}
44
+ {virtualField}
45
+ {targetCollections}
46
+ bind:entry
47
+ {destructive}
48
+ />
49
+ </div>
50
+ {/snippet}
51
+ </FieldWrapper>
@@ -0,0 +1,16 @@
1
+ import type { Snippet } from "svelte";
2
+ interface Props {
3
+ collectionField: string;
4
+ idField: string;
5
+ virtualField: string;
6
+ targetCollections: string[];
7
+ entry: Record<string, any>;
8
+ destructive?: boolean;
9
+ isDisabled?: boolean;
10
+ errorMessages?: any;
11
+ header?: any;
12
+ clearBtn?: Snippet<[]>;
13
+ }
14
+ declare const PolymorphicField: import("svelte").Component<Props, {}, "entry">;
15
+ type PolymorphicField = ReturnType<typeof PolymorphicField>;
16
+ export default PolymorphicField;
@@ -0,0 +1,30 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+ import RichTextEditor from "../../richTextEditor.svelte";
4
+ import FieldWrapper from "./FieldWrapper.svelte";
5
+
6
+ interface Props {
7
+ value?: any;
8
+ field: any;
9
+ destructive?: boolean;
10
+ isDisabled?: boolean;
11
+ errorMessages?: any;
12
+ header?: any;
13
+ clearBtn?: Snippet<[]>;
14
+ }
15
+
16
+ let { value = $bindable(), field, destructive = false, isDisabled = false, errorMessages = [], header, clearBtn }: Props = $props();
17
+ </script>
18
+
19
+ <FieldWrapper span={2} {isDisabled} {errorMessages} {header}>
20
+ {#snippet children()}
21
+ <div class="relative {destructive ? 'rounded-md ring-1 ring-destructive' : ''}">
22
+ {#if clearBtn}
23
+ <div class="absolute right-1 top-1 z-10">
24
+ {@render clearBtn()}
25
+ </div>
26
+ {/if}
27
+ <RichTextEditor name={field.key} bind:value />
28
+ </div>
29
+ {/snippet}
30
+ </FieldWrapper>
@@ -0,0 +1,13 @@
1
+ import type { Snippet } from "svelte";
2
+ interface Props {
3
+ value?: any;
4
+ field: any;
5
+ destructive?: boolean;
6
+ isDisabled?: boolean;
7
+ errorMessages?: any;
8
+ header?: any;
9
+ clearBtn?: Snippet<[]>;
10
+ }
11
+ declare const RichTextField: import("svelte").Component<Props, {}, "value">;
12
+ type RichTextField = ReturnType<typeof RichTextField>;
13
+ export default RichTextField;
@@ -0,0 +1,35 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+ import Input from "../../ui/input/input.svelte";
4
+ import FieldWrapper from "./FieldWrapper.svelte";
5
+
6
+ interface Props {
7
+ value?: any;
8
+ placeholder?: string;
9
+ destructive?: boolean;
10
+ changedClass?: string;
11
+ isDisabled?: boolean;
12
+ errorMessages?: any;
13
+ header?: any;
14
+ clearBtn?: Snippet<[]>;
15
+ }
16
+ let { value = $bindable(), placeholder = "NULL", destructive = false, changedClass = '', isDisabled = false, errorMessages = [], header, clearBtn }: Props = $props();
17
+ </script>
18
+
19
+ <FieldWrapper span={1} {isDisabled} {errorMessages} {header}>
20
+ {#snippet children()}
21
+ <div class="relative">
22
+ {#if clearBtn}
23
+ <div class="absolute right-1 inset-y-0 z-10 flex items-center">
24
+ {@render clearBtn()}
25
+ </div>
26
+ {/if}
27
+ <Input
28
+ {placeholder}
29
+ type="text"
30
+ class="bg-muted text-xs pr-9 {changedClass} {destructive ? 'border-destructive' : ''}"
31
+ bind:value
32
+ />
33
+ </div>
34
+ {/snippet}
35
+ </FieldWrapper>
@@ -0,0 +1,14 @@
1
+ import type { Snippet } from "svelte";
2
+ interface Props {
3
+ value?: any;
4
+ placeholder?: string;
5
+ destructive?: boolean;
6
+ changedClass?: string;
7
+ isDisabled?: boolean;
8
+ errorMessages?: any;
9
+ header?: any;
10
+ clearBtn?: Snippet<[]>;
11
+ }
12
+ declare const StringField: import("svelte").Component<Props, {}, "value">;
13
+ type StringField = ReturnType<typeof StringField>;
14
+ export default StringField;
@@ -0,0 +1,35 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+ import Textarea from "../../ui/textarea/textarea.svelte";
4
+ import FieldWrapper from "./FieldWrapper.svelte";
5
+
6
+ interface Props {
7
+ value?: any;
8
+ placeholder?: string;
9
+ destructive?: boolean;
10
+ changedClass?: string;
11
+ isDisabled?: boolean;
12
+ errorMessages?: any;
13
+ header?: any;
14
+ clearBtn?: Snippet<[]>;
15
+ }
16
+ let { value = $bindable(), placeholder = "NULL", destructive = false, changedClass = '', isDisabled = false, errorMessages = [], header, clearBtn }: Props = $props();
17
+ </script>
18
+
19
+ <FieldWrapper span={2} {isDisabled} {errorMessages} {header}>
20
+ {#snippet children()}
21
+ <div class="relative">
22
+ {#if clearBtn}
23
+ <div class="absolute right-1 top-1 z-10">
24
+ {@render clearBtn()}
25
+ </div>
26
+ {/if}
27
+ <Textarea
28
+ {placeholder}
29
+ rows={5}
30
+ class="bg-muted text-xs pr-9 {changedClass} {destructive ? 'border-destructive' : ''}"
31
+ bind:value
32
+ />
33
+ </div>
34
+ {/snippet}
35
+ </FieldWrapper>
@@ -0,0 +1,14 @@
1
+ import type { Snippet } from "svelte";
2
+ interface Props {
3
+ value?: any;
4
+ placeholder?: string;
5
+ destructive?: boolean;
6
+ changedClass?: string;
7
+ isDisabled?: boolean;
8
+ errorMessages?: any;
9
+ header?: any;
10
+ clearBtn?: Snippet<[]>;
11
+ }
12
+ declare const TextField: import("svelte").Component<Props, {}, "value">;
13
+ type TextField = ReturnType<typeof TextField>;
14
+ export default TextField;
@@ -80,7 +80,7 @@
80
80
  <Input
81
81
  placeholder={isPendingCreate ? "AUTO GENERATED" : isEmpty ? "NULL" : ""}
82
82
  type="number"
83
- class="bg-muted text-xs {bgClass} {destructive ? '!bg-destructive/10 border-destructive' : ''}"
83
+ class="bg-muted text-xs {bgClass} {destructive ? 'border-destructive' : ''}"
84
84
  bind:value={
85
85
  () => hasRealId ? value : "",
86
86
  (v) => { value = (v === "" || v == null) ? null : Number(v); }
@@ -80,7 +80,7 @@
80
80
  }
81
81
  </script>
82
82
 
83
- <div class="flex h-9 w-full items-center gap-1.5 rounded-md border pl-1.5 pr-9 text-xs bg-muted {bgClass} {destructive ? '!bg-destructive/10 border-destructive' : ''}">
83
+ <div class="flex h-9 w-full items-center gap-1.5 rounded-md border pl-1.5 pr-9 text-xs bg-muted {bgClass} {destructive ? 'border-destructive' : ''}">
84
84
  <Popover.Root bind:open={collectionPopoverOpen}>
85
85
  <Popover.Trigger>
86
86
  {#snippet child({ props })}
@@ -6,7 +6,7 @@
6
6
  // `openPopup` mounts this; specialised popup helpers like
7
7
  // `openDataTablePopup` are thin wrappers that supply the body
8
8
  // component + props.
9
- import { X } from "lucide-svelte";
9
+ import { ArrowLeft, X } from "lucide-svelte";
10
10
  import { fade, scale } from "svelte/transition";
11
11
  import { cubicOut } from "svelte/easing";
12
12
  import Portal from "svelte-portal";
@@ -28,6 +28,12 @@
28
28
  // Use when the body brings its own header.
29
29
  hideHeader?: boolean;
30
30
  onClose?: () => void;
31
+ // Set by the action layer when there's a popup-history entry to
32
+ // pop. The chrome renders a back arrow in the title bar; bodies
33
+ // that `hideHeader: true` get `canGoBack` + `onBack` forwarded
34
+ // so they can render their own back affordance.
35
+ canGoBack?: boolean;
36
+ onBack?: () => void;
31
37
  }
32
38
 
33
39
  let {
@@ -37,6 +43,8 @@
37
43
  size = "default",
38
44
  hideHeader = false,
39
45
  onClose,
46
+ canGoBack = false,
47
+ onBack,
40
48
  }: Props = $props();
41
49
  </script>
42
50
 
@@ -54,8 +62,19 @@
54
62
  {size === 'sm' ? 'max-h-[calc(100vh-6rem)] max-w-2xl' : 'h-[85vh] max-w-7xl'}"
55
63
  >
56
64
  {#if !hideHeader}
57
- <div class="flex h-12 shrink-0 items-center justify-between gap-4 border-b px-4">
58
- <div class="text-sm font-medium">{title ?? ""}</div>
65
+ <div class="flex h-12 shrink-0 items-center justify-between gap-2 border-b px-4">
66
+ <div class="flex min-w-0 items-center gap-2">
67
+ {#if canGoBack}
68
+ <Button
69
+ variant="ghost"
70
+ size="icon"
71
+ onclick={() => onBack?.()}
72
+ class="h-8 w-8 rounded-full text-muted-foreground"
73
+ Icon={ArrowLeft}
74
+ />
75
+ {/if}
76
+ <div class="truncate text-sm font-medium">{title ?? ""}</div>
77
+ </div>
59
78
  <Button
60
79
  variant="ghost"
61
80
  size="icon"
@@ -73,7 +92,7 @@
73
92
  percentages, which don't resolve when the popup uses
74
93
  `max-h` (size="sm") instead of a fixed `h`. -->
75
94
  <div class="flex min-h-0 flex-1 flex-col overflow-hidden">
76
- <Body {...componentProps} {onClose} />
95
+ <Body {...componentProps} {onClose} {canGoBack} {onBack} />
77
96
  </div>
78
97
  </div>
79
98
  </Portal>
@@ -5,6 +5,8 @@ interface Props {
5
5
  size?: "default" | "sm";
6
6
  hideHeader?: boolean;
7
7
  onClose?: () => void;
8
+ canGoBack?: boolean;
9
+ onBack?: () => void;
8
10
  }
9
11
  declare const Popup: import("svelte").Component<Props, {}, "">;
10
12
  type Popup = ReturnType<typeof Popup>;
@@ -17,13 +17,15 @@ import type RangeCalendarButton from "../components/rangeCalendarButton.svelte";
17
17
  import type DataTable from "../components/dataTable/dataTable.svelte";
18
18
  import type Drawer from "../components/drawer.svelte";
19
19
  import type SelectRecord from "../components/selectRecord.svelte";
20
+ import type FieldWrapper from "../components/detailView/fields/FieldWrapper.svelte";
20
21
  import * as Popover from "../components/ui/popover";
21
22
  import * as intlDate from "@internationalized/date";
22
23
  import * as Icons from "lucide-svelte";
23
24
  import { ContextMenu } from "bits-ui";
24
25
  import * as Tooltip from "../components/ui/tooltip";
25
26
  import * as Breadcrumb from "../components/ui/breadcrumb";
26
- import { showDialog, type OpenDataTableDrawerProps, type OpenDataTablePopupProps, type OpenPopupProps } from "../actions";
27
+ import { showDialog, type OpenDataTableDrawerProps } from "../actions";
28
+ import type { OpenDataTablePopupProps, OpenPopupProps } from "../popup";
27
29
  import { toast } from "svelte-sonner";
28
30
  import { Switch } from "../components/ui/switch";
29
31
  export interface Components {
@@ -47,6 +49,7 @@ export interface Components {
47
49
  Drawer: typeof Drawer;
48
50
  SelectRecord: typeof SelectRecord;
49
51
  Switch: typeof Switch;
52
+ FieldWrapper: typeof FieldWrapper;
50
53
  }
51
54
  export interface ExtensionUtils {
52
55
  ctx: CTX;
@@ -121,7 +124,7 @@ export interface ExtensionProps {
121
124
  utils: ExtensionUtils;
122
125
  [key: string]: any;
123
126
  }
124
- export type ExtensionComponentKey = `pages.${string}` | `publicPages.${string}` | "studio.listView" | `dvFields.topRight.${string}.${string}` | `detailView.update.subRecords.${string}` | `detailView.create.subRecords.${string}` | `detailView.fields.topRight.${string}.${string}` | "detailView.field.label" | `detailView.fields.foreignKey.${string}` | `listView.entry.children.${string}` | `listView.entry.actions` | `listView.header.actions` | (string & {});
127
+ export type ExtensionComponentKey = `pages.${string}` | `publicPages.${string}` | "studio.listView" | `detailView.update.subRecords.${string}` | `detailView.create.subRecords.${string}` | `detailView.fields.topRight.${string}.${string}` | "detailView.field.label" | `detailView.fields.foreignKey.${string}` | `listView.entry.children.${string}` | `listView.entry.actions` | `listView.header.actions` | (string & {});
125
128
  export type ExtensionComponent = any | {
126
129
  component: any;
127
130
  when: (props: Record<string, any>) => boolean;
@@ -1,5 +1,6 @@
1
1
  import { toast } from "svelte-sonner";
2
- import { showDialog, openDataTableDrawer, openDataTablePopup, openPopup } from "../actions";
2
+ import { showDialog, openDataTableDrawer } from "../actions";
3
+ import { openDataTablePopup, openPopup } from "../popup";
3
4
  import { emitEvent } from "../eventSystem";
4
5
  import { Button } from "../components/ui/button";
5
6
  import { Input } from "../components/ui/input";
@@ -24,6 +25,7 @@ import RangeCalendarButton from "../components/rangeCalendarButton.svelte";
24
25
  import DataTable from "../components/dataTable/dataTable.svelte";
25
26
  import Drawer from "../components/drawer.svelte";
26
27
  import SelectRecord from "../components/selectRecord.svelte";
28
+ import FieldWrapper from "../components/detailView/fields/FieldWrapper.svelte";
27
29
  import { Switch } from "../components/ui/switch";
28
30
  export function getComponents() {
29
31
  return {
@@ -47,6 +49,7 @@ export function getComponents() {
47
49
  Drawer: Drawer,
48
50
  SelectRecord: SelectRecord,
49
51
  Switch: Switch,
52
+ FieldWrapper: FieldWrapper,
50
53
  };
51
54
  }
52
55
  export function getExtensionUtils(lobb, ctx) {
@@ -0,0 +1,31 @@
1
+ import { type StudioContext } from "./context";
2
+ import type { CollectionTab } from "./store.types";
3
+ export interface OpenPopupProps {
4
+ component: any;
5
+ componentProps?: Record<string, any>;
6
+ title?: string;
7
+ size?: "default" | "sm";
8
+ hideHeader?: boolean;
9
+ replaceLast?: boolean;
10
+ }
11
+ export interface OpenDataTablePopupProps {
12
+ collectionName: string;
13
+ filter?: Record<string, any>;
14
+ sort?: Record<string, "asc" | "desc">;
15
+ limit?: number;
16
+ title?: string;
17
+ showHeader?: boolean;
18
+ showFooter?: boolean;
19
+ showFilter?: boolean;
20
+ tabs?: CollectionTab[];
21
+ view?: {
22
+ id: string;
23
+ [key: string]: any;
24
+ };
25
+ replaceLast?: boolean;
26
+ size?: "default" | "sm";
27
+ hideHeader?: boolean;
28
+ }
29
+ export declare function openPopup(studioContext: StudioContext, props: OpenPopupProps): void;
30
+ export declare function goBackPopup(studioContext: StudioContext): void;
31
+ export declare function openDataTablePopup(studioContext: StudioContext, props: OpenDataTablePopupProps): void;