@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
@@ -1,296 +1,169 @@
1
1
  <script lang="ts">
2
- import { getStudioContext } from "../../context";
3
- import { getFieldRelationTarget, getPolymorphicRelation } from "../../relations";
4
- import { Ban, Check, CircleAlert, X } from "lucide-svelte";
5
- import { getField } from "../dataTable/utils";
6
- import Button from "../ui/button/button.svelte";
7
- import FieldCustomInput from "./fieldCustomInput.svelte";
8
- import Input from "../ui/input/input.svelte";
9
- import NumberInput from "../ui/input/numberInput.svelte";
10
- import * as Select from "../ui/select/index";
11
- import EnumBadge from "../dataTable/enumBadge.svelte";
12
- import type { EnumOption } from "@lobb-js/core";
13
- import Textarea from "../ui/textarea/textarea.svelte";
14
- import ForeingKeyInput from "../foreingKeyInput.svelte";
15
- import PolymorphicInput from "../polymorphicInput.svelte";
16
- import ExtensionsComponents from "../extensionsComponents.svelte";
17
- import { getExtensionUtils } from "../../extensions/extensionUtils";
2
+ import { getStudioContext } from "../../context";
3
+ import { getFieldRelationTarget, getPolymorphicRelation } from "../../relations";
4
+ import { Ban } from "lucide-svelte";
5
+ import { getField, getFieldIcon } from "../dataTable/utils";
6
+ import { getFieldTypeLabel } from "../../utils";
7
+ import Button from "../ui/button/button.svelte";
8
+ import type { EnumOption } from "@lobb-js/core";
18
9
 
19
- const { ctx, lobb } = getStudioContext();
10
+ import ForeignKeyField from "./fields/ForeignKeyField.svelte";
11
+ import PolymorphicField from "./fields/PolymorphicField.svelte";
12
+ import EmbeddedField from "./fields/EmbeddedField.svelte";
13
+ import EmbeddedPolymorphicField from "./fields/EmbeddedPolymorphicField.svelte";
14
+ import RichTextField from "./fields/RichTextField.svelte";
15
+ import CodeField from "./fields/CodeField.svelte";
16
+ import PasswordField from "./fields/PasswordField.svelte";
17
+ import IdField from "./fields/IdField.svelte";
18
+ import StringField from "./fields/StringField.svelte";
19
+ import TextField from "./fields/TextField.svelte";
20
+ import NumberField from "./fields/NumberField.svelte";
21
+ import DateField from "./fields/DateField.svelte";
22
+ import BoolField from "./fields/BoolField.svelte";
23
+ import EnumField from "./fields/EnumField.svelte";
20
24
 
21
- interface Props {
22
- collectionName: string;
23
- fieldName: string;
24
- value: any;
25
- errorMessages?: string[];
26
- entry?: Record<string, any>;
27
- changed?: boolean;
28
- }
25
+ const { ctx } = getStudioContext();
29
26
 
30
- let {
31
- collectionName,
32
- fieldName,
33
- value = $bindable(),
34
- errorMessages = [],
35
- entry = $bindable(),
36
- changed = false,
37
- }: Props = $props();
27
+ interface Props {
28
+ collectionName: string;
29
+ fieldName: string;
30
+ value: any;
31
+ errorMessages?: any;
32
+ entry?: Record<string, any>;
33
+ changed?: boolean;
34
+ }
38
35
 
39
- const ui_input =
40
- ctx.meta.collections[collectionName].fields[fieldName].ui?.input;
41
- const ui =
42
- ctx.meta.collections[collectionName].fields[fieldName].ui;
43
- const field = getField(ctx, fieldName, collectionName);
44
- const fieldRelationTarget = getFieldRelationTarget(ctx, collectionName, fieldName);
45
- const polymorphicRelation = getPolymorphicRelation(ctx, collectionName, fieldName);
46
- const isDisabled = field.key === 'id' || Boolean(ui?.disabled)
47
- const disabledClasses = "pointer-events-none opacity-50";
48
- const destructive: boolean = $derived(!isDisabled && Boolean(errorMessages.length));
49
- const changedClass = $derived(changed && !destructive ? '!bg-orange-500/5' : '');
36
+ let {
37
+ collectionName,
38
+ fieldName,
39
+ value = $bindable(),
40
+ errorMessages = [],
41
+ entry = $bindable(),
42
+ changed = false,
43
+ }: Props = $props();
50
44
 
45
+ const fieldDef = ctx.meta.collections[collectionName].fields[fieldName];
46
+ const ui_input = fieldDef?.ui?.input;
47
+ const ui = fieldDef?.ui;
48
+ const field = getField(ctx, fieldName, collectionName);
49
+ const fieldRelationTarget = getFieldRelationTarget(ctx, collectionName, fieldName);
50
+ const polymorphicRelation = getPolymorphicRelation(ctx, collectionName, fieldName);
51
+ const isDisabled = field.key === 'id' || Boolean(ui?.disabled);
52
+ const destructive: boolean = $derived(Array.isArray(errorMessages) && errorMessages.length > 0);
53
+ const changedClass = $derived(changed && !destructive ? '!bg-orange-500/5' : '');
54
+ const isEmbedded = !!(fieldRelationTarget && entry && (fieldDef as any)?.embedded);
55
+ const isEmbeddedPolymorphic = !!(polymorphicRelation && entry && (fieldDef as any)?.embedded);
56
+
57
+ const FieldIcon = getFieldIcon(ctx, fieldName, collectionName);
58
+ const labelData = {
59
+ text: field.label,
60
+ icon: FieldIcon,
61
+ typeText: getFieldTypeLabel(field.type),
62
+ description: fieldDef?.description as string | undefined,
63
+ };
64
+
65
+ function handleClear(e: MouseEvent) {
66
+ e.stopPropagation();
67
+ value = null;
68
+ if (polymorphicRelation && entry) {
69
+ entry[polymorphicRelation.from.collection_field] = null;
70
+ entry[polymorphicRelation.from.id_field] = null;
71
+ }
72
+ }
51
73
  </script>
52
74
 
53
- <div class="{isDisabled ? "cursor-not-allowed" : ''}">
54
- <div
55
- class="
56
- relative flex flex-col gap-2
57
- {isDisabled ? disabledClasses : ''}
58
- "
59
- style="flex: 2;"
60
- >
61
- <Button
62
- onclick={() => {
63
- value = null;
64
- if (polymorphicRelation && entry) {
65
- entry[polymorphicRelation.from.collection_field] = null;
66
- entry[polymorphicRelation.from.id_field] = null;
67
- }
68
- }}
69
- variant="outline"
70
- class="absolute right-0 top-0 z-10 mr-1.5 mt-1.5 aspect-square h-6 w-6 p-0"
71
- Icon={Ban}
72
- tabindex={-1}
73
- ></Button>
74
- {#if polymorphicRelation && entry}
75
- <PolymorphicInput
76
- collectionField={polymorphicRelation.from.collection_field}
77
- idField={polymorphicRelation.from.id_field}
78
- virtualField={polymorphicRelation.from.virtual_field ?? ''}
79
- targetCollections={polymorphicRelation.to}
80
- bind:entry
81
- {destructive}
82
- />
83
- {:else if ui_input}
84
- <FieldCustomInput
85
- bind:value
86
- type={ui_input.type}
87
- args={ui_input.args}
88
- {field}
89
- {destructive}
90
- />
91
- {:else if field.label === "id"}
92
- <Input
93
- placeholder="AUTO GENERATED"
94
- class="bg-muted text-xs {changedClass}"
95
- bind:value
96
- />
97
- {:else if fieldRelationTarget && entry}
98
- <ExtensionsComponents
99
- name="detailView.fields.foreignKey.{fieldRelationTarget}"
100
- utils={getExtensionUtils(lobb, ctx)}
101
- parentCollectionName={collectionName}
102
- collectionName={fieldRelationTarget}
103
- bind:value
104
- {entry}
105
- fieldName={field.key}
106
- {destructive}
107
- >
108
- <ForeingKeyInput
109
- parentCollectionName={collectionName}
110
- collectionName={fieldRelationTarget}
111
- bind:value
112
- {entry}
113
- fieldName={field.key}
114
- {destructive}
115
- />
116
- </ExtensionsComponents>
117
- {:else if field.enum}
118
- {@const rawEnum = field.enum as (string | number | EnumOption)[]}
119
- {@const isEnumOption = rawEnum.length > 0 && typeof rawEnum[0] === "object"}
120
- {@const enumOptions = isEnumOption ? rawEnum as EnumOption[] : undefined}
121
- <Select.Root
122
- type="single"
123
- bind:value={
124
- () => value != null ? String(value) : null,
125
- (v) => {
126
- if (v == null) { value = null; return; }
127
- const isNumeric = field.type === "integer" || field.type === "long" || field.type === "decimal" || field.type === "float";
128
- value = isNumeric ? Number(v) : v;
129
- }
130
- }
131
- >
132
- <Select.Trigger
133
- class="h-9 w-full bg-muted pr-8 {changedClass} {destructive ? 'border-destructive !bg-destructive/10' : ''}"
134
- >
135
- {#if value != null && enumOptions}
136
- <EnumBadge value={String(value)} enum={enumOptions} />
137
- {:else if value != null}
138
- {value}
139
- {:else}
140
- <span class="text-muted-foreground">{ui?.placeholder ?? "NULL"}</span>
141
- {/if}
142
- </Select.Trigger>
143
- <Select.Content>
144
- <Select.Group>
145
- {#each rawEnum as option}
146
- {@const optionValue = typeof option === "object" ? String(option.value) : String(option)}
147
- <Select.Item value={optionValue} label={optionValue}>
148
- {#if enumOptions}
149
- <EnumBadge value={optionValue} enum={enumOptions} />
150
- {:else}
151
- {optionValue}
152
- {/if}
153
- </Select.Item>
154
- {/each}
155
- </Select.Group>
156
- </Select.Content>
157
- </Select.Root>
158
- {:else if field.type === "string"}
159
- <Input
160
- placeholder={ui?.placeholder ? ui.placeholder : "NULL"}
161
- type="text"
162
- class="
163
- bg-muted text-xs {changedClass}
164
- {destructive ? 'border-destructive bg-destructive/10' : ''}
165
- "
166
- bind:value
167
- />
168
- {:else if field.type === "text"}
169
- <Textarea
170
- placeholder={ui?.placeholder ? ui.placeholder : value === "" ? "EMPTY STRING" : "NULL"}
171
- rows={5}
172
- class="
173
- bg-muted text-xs {changedClass}
174
- {destructive ? 'border-destructive bg-destructive/10' : ''}
175
- "
176
- bind:value
177
- />
178
- {:else if field.type === "date"}
179
- <Input
180
- type="date"
181
- placeholder={ui?.placeholder ? ui.placeholder : "NULL"}
182
- class="
183
- dateInput block w-full bg-muted pr-9 text-xs
184
- {destructive ? 'border-destructive bg-destructive/10' : ''}
185
- "
186
- bind:value={
187
- () => {
188
- if (!value) {
189
- return;
190
- }
191
- const date = new Date(value);
192
- return date.toISOString().split("T")[0];
193
- },
194
- (v) => (value = v)
195
- }
196
- />
197
- {:else if field.type === "time"}
198
- <Input
199
- type="time"
200
- placeholder={ui?.placeholder ? ui.placeholder : "NULL"}
201
- class="
202
- dateInput block w-full bg-muted pr-9 text-xs
203
- {destructive ? 'border-destructive bg-destructive/10' : ''}
204
- "
205
- bind:value={
206
- () => {
207
- if (!value) {
208
- return;
209
- }
210
- return value;
211
- },
212
- (v) => (value = v)
213
- }
214
- />
215
- {:else if field.type === "datetime"}
216
- <Input
217
- type="datetime-local"
218
- placeholder={ui?.placeholder ? ui.placeholder : "NULL"}
219
- class="
220
- dateInput block w-full bg-muted pr-9 text-xs
221
- {destructive ? 'border-destructive bg-destructive/10' : ''}
222
- "
223
- bind:value={
224
- () => {
225
- if (!value) {
226
- return;
227
- }
228
- const date = new Date(value);
229
- return date.toISOString().slice(0, 16);
230
- },
231
- (v) => {
232
- value = v;
233
- }
234
- }
235
- />
236
- {:else if field.type === "bool"}
237
- <Select.Root type="single" bind:value>
238
- <Select.Trigger
239
- placeholder={ui?.placeholder ? ui.placeholder : "NULL"}
240
- class="
241
- bg-muted pr-9
242
- {destructive ? 'border-destructive bg-destructive/10' : ''}
243
- "
244
- >
245
- {String(value).toUpperCase()}
246
- </Select.Trigger>
247
- <Select.Content>
248
- <Select.Item value={"true"} class="flex gap-1.5">
249
- <Check size="15" />
250
- TRUE
251
- </Select.Item>
252
- <Select.Item value={"false"} class="flex gap-1.5">
253
- <X size="15" />
254
- FALSE
255
- </Select.Item>
256
- <Select.Item value={"null"} class="flex gap-1.5">
257
- <Ban size="15" />
258
- NULL
259
- </Select.Item>
260
- </Select.Content>
261
- </Select.Root>
262
- {:else if field.type === "decimal" || field.type === "float" || field.type === "integer" || field.type === "long"}
263
- {@const isFloat = field.type === "decimal" || field.type === "float"}
264
- <NumberInput
265
- placeholder={ui?.placeholder ? ui.placeholder : "NULL"}
266
- scale={isFloat ? 20 : 0}
267
- groupDigits={ui?.groupDigits ?? false}
268
- class="
269
- bg-muted text-xs {changedClass}
270
- {destructive ? 'border-destructive bg-destructive/10' : ''}
271
- "
272
- bind:value
273
- />
274
- {:else}
275
- <Input
276
- placeholder={ui?.placeholder ? ui.placeholder : "NULL"}
277
- type="text"
278
- class="
279
- bg-muted text-xs {changedClass}
280
- {destructive ? 'border-destructive bg-destructive/10' : ''}
281
- "
282
- bind:value
283
- />
284
- {/if}
285
- {#if !isDisabled && errorMessages}
286
- {#each errorMessages as message}
287
- <div class="flex gap-1 text-destructive">
288
- <CircleAlert size="15" class="translate-y-[0.025rem]" />
289
- <div class="text-[0.7rem]">
290
- {message}
291
- </div>
292
- </div>
293
- {/each}
294
- {/if}
295
- </div>
296
- </div>
75
+ {#snippet clearBtn()}
76
+ {#if !isDisabled}
77
+ <Button
78
+ onclick={handleClear}
79
+ variant="outline"
80
+ class="aspect-square h-6 w-6 shrink-0 p-0"
81
+ Icon={Ban}
82
+ tabindex={-1}
83
+ />
84
+ {/if}
85
+ {/snippet}
86
+
87
+ {#if isEmbeddedPolymorphic && entry}
88
+ <EmbeddedPolymorphicField
89
+ virtualField={polymorphicRelation!.from.virtual_field ?? fieldName}
90
+ collectionField={polymorphicRelation!.from.collection_field}
91
+ idField={polymorphicRelation!.from.id_field}
92
+ targetCollections={polymorphicRelation!.to}
93
+ bind:entry
94
+ {isDisabled}
95
+ {errorMessages}
96
+ header={labelData}
97
+ />
98
+ {:else if polymorphicRelation && entry}
99
+ <PolymorphicField
100
+ collectionField={polymorphicRelation.from.collection_field}
101
+ idField={polymorphicRelation.from.id_field}
102
+ virtualField={polymorphicRelation.from.virtual_field ?? ''}
103
+ targetCollections={polymorphicRelation.to}
104
+ bind:entry
105
+ {destructive}
106
+ {isDisabled}
107
+ {errorMessages}
108
+ header={labelData}
109
+ {clearBtn}
110
+ />
111
+ {:else if isEmbedded}
112
+ <EmbeddedField
113
+ collectionName={fieldRelationTarget!}
114
+ {fieldName}
115
+ bind:value
116
+ entry={entry!}
117
+ {isDisabled}
118
+ {errorMessages}
119
+ header={labelData}
120
+ onClear={handleClear}
121
+ />
122
+ {:else if ui_input?.type === 'richtext'}
123
+ <RichTextField bind:value {field} {destructive} {isDisabled} {errorMessages} header={labelData} {clearBtn} />
124
+ {:else if ui_input?.type === 'code'}
125
+ <CodeField bind:value {field} args={ui_input.args} {isDisabled} {errorMessages} header={labelData} {clearBtn} />
126
+ {:else if ui_input?.type === 'password'}
127
+ <PasswordField bind:value {destructive} {isDisabled} {errorMessages} header={labelData} {clearBtn} />
128
+ {:else if fieldRelationTarget && entry}
129
+ <ForeignKeyField
130
+ parentCollectionName={collectionName}
131
+ collectionName={fieldRelationTarget}
132
+ {fieldName}
133
+ bind:value
134
+ bind:entry
135
+ {destructive}
136
+ {isDisabled}
137
+ {errorMessages}
138
+ header={labelData}
139
+ {clearBtn}
140
+ />
141
+ {:else if field.label === "id"}
142
+ <IdField bind:value {changedClass} {isDisabled} {errorMessages} header={labelData} {clearBtn} />
143
+ {:else if field.enum}
144
+ <EnumField
145
+ bind:value
146
+ rawEnum={field.enum as (string | number | EnumOption)[]}
147
+ isNumeric={field.type === "integer" || field.type === "long" || field.type === "decimal" || field.type === "float"}
148
+ placeholder={ui?.placeholder}
149
+ {destructive} {changedClass} {isDisabled} {errorMessages} header={labelData} {clearBtn}
150
+ />
151
+ {:else if field.type === "string"}
152
+ <StringField bind:value placeholder={ui?.placeholder} {destructive} {changedClass} {isDisabled} {errorMessages} header={labelData} {clearBtn} />
153
+ {:else if field.type === "text"}
154
+ <TextField bind:value placeholder={ui?.placeholder ?? (value === "" ? "EMPTY STRING" : "NULL")} {destructive} {changedClass} {isDisabled} {errorMessages} header={labelData} {clearBtn} />
155
+ {:else if field.type === "date" || field.type === "time" || field.type === "datetime"}
156
+ <DateField bind:value type={field.type} placeholder={ui?.placeholder} {destructive} {isDisabled} {errorMessages} header={labelData} {clearBtn} />
157
+ {:else if field.type === "bool"}
158
+ <BoolField bind:value placeholder={ui?.placeholder} {destructive} {isDisabled} {errorMessages} header={labelData} {clearBtn} />
159
+ {:else if field.type === "decimal" || field.type === "float" || field.type === "integer" || field.type === "long"}
160
+ <NumberField
161
+ bind:value
162
+ scale={field.type === "decimal" || field.type === "float" ? 20 : 0}
163
+ groupDigits={ui?.groupDigits ?? false}
164
+ placeholder={ui?.placeholder}
165
+ {destructive} {changedClass} {isDisabled} {errorMessages} header={labelData} {clearBtn}
166
+ />
167
+ {:else}
168
+ <StringField bind:value placeholder={ui?.placeholder} {destructive} {changedClass} {isDisabled} {errorMessages} header={labelData} {clearBtn} />
169
+ {/if}
@@ -0,0 +1,42 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+ import { Ban, Check, X } from "lucide-svelte";
4
+ import * as Select from "../../ui/select/index";
5
+ import FieldWrapper from "./FieldWrapper.svelte";
6
+
7
+ interface Props {
8
+ value?: any;
9
+ placeholder?: string;
10
+ destructive?: boolean;
11
+ isDisabled?: boolean;
12
+ errorMessages?: any;
13
+ header?: any;
14
+ clearBtn?: Snippet<[]>;
15
+ }
16
+ let { value = $bindable(), placeholder = "NULL", destructive = false, 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
+ <Select.Root type="single" bind:value>
28
+ <Select.Trigger
29
+ {placeholder}
30
+ class="bg-muted pr-9 {destructive ? 'border-destructive' : ''}"
31
+ >
32
+ {String(value).toUpperCase()}
33
+ </Select.Trigger>
34
+ <Select.Content>
35
+ <Select.Item value={"true"} class="flex gap-1.5"><Check size="15" />TRUE</Select.Item>
36
+ <Select.Item value={"false"} class="flex gap-1.5"><X size="15" />FALSE</Select.Item>
37
+ <Select.Item value={"null"} class="flex gap-1.5"><Ban size="15" />NULL</Select.Item>
38
+ </Select.Content>
39
+ </Select.Root>
40
+ </div>
41
+ {/snippet}
42
+ </FieldWrapper>
@@ -0,0 +1,30 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+ import CodeEditor from "../../codeEditor.svelte";
4
+ import FieldWrapper from "./FieldWrapper.svelte";
5
+
6
+ interface Props {
7
+ value?: any;
8
+ field: any;
9
+ args?: any;
10
+ isDisabled?: boolean;
11
+ errorMessages?: any;
12
+ header?: any;
13
+ clearBtn?: Snippet<[]>;
14
+ }
15
+
16
+ let { value = $bindable(), field, args, 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
+ <CodeEditor name={field.key} type={args?.type ?? 'javascript'} bind:value />
28
+ </div>
29
+ {/snippet}
30
+ </FieldWrapper>
@@ -0,0 +1,50 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+ import FieldCustomInput from "../fieldCustomInput.svelte";
4
+ import FieldWrapper from "./FieldWrapper.svelte";
5
+
6
+ interface Props {
7
+ value?: any;
8
+ field: any;
9
+ uiInput: { type: string; args?: any };
10
+ destructive?: boolean;
11
+ changedClass?: string;
12
+ isDisabled?: boolean;
13
+ errorMessages?: any;
14
+ header?: any;
15
+ clearBtn?: Snippet<[]>;
16
+ }
17
+
18
+ let {
19
+ value = $bindable(),
20
+ field,
21
+ uiInput,
22
+ destructive = false,
23
+ changedClass = '',
24
+ isDisabled = false,
25
+ errorMessages = [],
26
+ header,
27
+ clearBtn,
28
+ }: Props = $props();
29
+
30
+ const isFullWidth = uiInput.type === "richtext";
31
+ </script>
32
+
33
+ <FieldWrapper span={isFullWidth ? 2 : 1} {isDisabled} {errorMessages} {header}>
34
+ {#snippet children()}
35
+ <div class="relative {destructive ? 'rounded-md ring-1 ring-destructive bg-destructive/10' : ''}">
36
+ {#if clearBtn}
37
+ <div class="absolute right-1 z-10 {isFullWidth ? 'top-1' : 'inset-y-0 flex items-center'}">
38
+ {@render clearBtn()}
39
+ </div>
40
+ {/if}
41
+ <FieldCustomInput
42
+ bind:value
43
+ type={uiInput.type}
44
+ args={uiInput.args}
45
+ {field}
46
+ {destructive}
47
+ />
48
+ </div>
49
+ {/snippet}
50
+ </FieldWrapper>
@@ -0,0 +1,47 @@
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
+ type: "date" | "time" | "datetime";
9
+ placeholder?: string;
10
+ destructive?: boolean;
11
+ isDisabled?: boolean;
12
+ errorMessages?: any;
13
+ header?: any;
14
+ clearBtn?: Snippet<[]>;
15
+ }
16
+ let { value = $bindable(), type, placeholder = "NULL", destructive = false, isDisabled = false, errorMessages = [], header, clearBtn }: Props = $props();
17
+
18
+ const inputType = type === "datetime" ? "datetime-local" : type;
19
+
20
+ function getDisplayValue() {
21
+ if (!value) return;
22
+ if (type === "date") return new Date(value).toISOString().split("T")[0];
23
+ if (type === "datetime") return new Date(value).toISOString().slice(0, 16);
24
+ return value;
25
+ }
26
+ </script>
27
+
28
+ <FieldWrapper span={1} {isDisabled} {errorMessages} {header}>
29
+ {#snippet children()}
30
+ <div class="relative">
31
+ {#if clearBtn}
32
+ <div class="absolute right-1 inset-y-0 z-10 flex items-center">
33
+ {@render clearBtn()}
34
+ </div>
35
+ {/if}
36
+ <Input
37
+ type={inputType}
38
+ {placeholder}
39
+ class="dateInput block w-full bg-muted pr-9 text-xs {destructive ? 'border-destructive' : ''}"
40
+ bind:value={
41
+ () => getDisplayValue(),
42
+ (v) => { value = v; }
43
+ }
44
+ />
45
+ </div>
46
+ {/snippet}
47
+ </FieldWrapper>