Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 16 additions & 26 deletions src/lib/elements/forms/inputSelect.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,7 @@
export let placeholder = '';
export let required = false;
export let disabled = false;
export let options: {
value: string | boolean | number | null;
label: string;
disabled?: boolean;
leadingIcon?: ComponentType;
leadingHtml?: string;
badge?: string;
}[];

export let leadingIcon: ComponentType | undefined = undefined;

let error: string;
Expand All @@ -44,22 +37,19 @@
}
</script>

<Input.Select
{id}
{label}
{options}
{optionalText}
{placeholder}
{disabled}
{autofocus}
{leadingIcon}
helper={error ?? helper}
{required}
state={error ? 'error' : 'default'}
data-command-center-ignore
on:invalid={handleInvalid}
on:input
on:change
bind:value>
<Input
{id}
{label}
{placeholder}
{disabled}
{autofocus}
{leadingIcon}
helper={error ?? helper}
{required}
state={error ? 'error' : 'default'}
data-command-center-ignore
on:invalid={handleInvalid}
on:input={(e) => value = e.target.value}
Comment on lines +51 to +52
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 on:change no longer forwarded — breaks all callers that depend on it

The original component forwarded on:change to parent components. This PR removes that forwarding and only handles on:input internally. All existing callers that pass on:change handlers will receive no event.

For example, in relationship.svelte:

<InputSelect ... on:change={() => { if (!relatedList[0]) relatedList = [''] ; updateRelatedList(); }} />
<InputSelect ... on:change={updateRelatedList} />

These handlers won't fire, so relatedList and value will never be updated when the user selects/types a value.

Also in lib/components/limit.svelte:

<InputSelect id="rows" {options} bind:value={limit} on:change={limitChange} />

The row limit change callback will be silently dropped.

The on:change event should be forwarded alongside on:input:

Suggested change
on:invalid={handleInvalid}
on:input={(e) => value = e.target.value}
on:invalid={handleInvalid}
on:input={(e) => value = (e.target as HTMLInputElement).value}
on:change
bind:value>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 e.target is not typed as HTMLInputElement

e.target is typed as EventTarget | null, so accessing .value directly is not type-safe and will cause a TypeScript error.

Suggested change
on:input={(e) => value = e.target.value}
on:input={(e) => value = (e.target as HTMLInputElement).value}

bind:value>
<slot name="info" slot="info" />
Comment on lines +40 to 54
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 optionalText prop is no longer passed to the inner component

The optionalText prop is declared on line 10 and was passed to Input.Select in the original code. It is not forwarded to the new Input component, so any caller relying on optional text display (e.g. "optional" labels) will silently lose that feature.

</Input.Select>
</Input>
Comment on lines +40 to +55
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P0 Shared component change breaks all dropdown usages across the codebase

inputSelect.svelte is a shared component used in ~69 files throughout the app. Replacing Input.Select with a plain Input and removing the options prop means every caller that passes options to <InputSelect> will silently receive a plain text field instead of a dropdown — with all option data being silently discarded.

Affected components (non-exhaustive):

  • columns/types/boolean.svelte — true/false selection becomes free-text input, allowing invalid values
  • columns/types/enum.svelte — enum value selection breaks; users can type arbitrary strings not in the enum
  • lib/components/filters/content.svelte and filtersModal.svelte — filter operator/value dropdowns break
  • lib/components/limit.svelte — row limit picker becomes free-text
  • databases/.../createColumn.svelte — column type picker breaks
  • databases/.../indexes/create.svelte — index type picker breaks
  • Every InputSelect call with options in relationship.svelte (to-many section, lines 303, 322, 352) — these now show plain text inputs too

The intent of this PR (restoring typing ability in the relationship field) is valid, but it should target only the relevant relationship input rather than changing this shared wrapper component. The fix should be applied directly in relationship.svelte where the relationship-specific InputSelect calls exist, or a separate component/prop should be introduced.

Comment on lines +40 to +55
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

optionalText no longer has any effect.

Line 10 still exposes optionalText, but the new <Input> call never uses it. Any caller passing that prop will stop rendering its optional-label text with no compile-time signal. Either keep honoring the prop here or remove/update the public API in the same change.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/elements/forms/inputSelect.svelte` around lines 40 - 55, The
component currently exports optionalText but never passes it to the child
<Input>, so callers’ optional-labels stop rendering; fix by either forwarding
optionalText into the <Input> (e.g., add optionalText={optionalText} to the
<Input> element in inputSelect.svelte) or remove the optionalText export from
this component and update the public API/consumers accordingly; locate the
optionalText export in this file and the <Input> usage to implement the chosen
change.

⚠️ Potential issue | 🔴 Critical

Don't convert the shared select wrapper into a plain text input.

InputSelect is still used as a real dropdown in src/lib/components/billing/selectPaymentMethod.svelte:59-75, src/routes/(console)/organization-[organization]/billing/budgetAlert.svelte:105-115, src/routes/(console)/organization-[organization]/members/edit.svelte:81-93, and src/routes/(console)/organization-[organization]/createMember.svelte:73-85. With this change those screens silently ignore options, lose select-specific behavior like on:select, and coerce non-string option values into plain text. Please scope the free-form behavior to the relationship field, or make it opt-in instead of changing the shared default.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/elements/forms/inputSelect.svelte` around lines 40 - 55, The change
replaced the shared select wrapper (InputSelect) with a plain text <Input>,
which breaks select-specific features (options, on:select, non-string option
values); restore the original select element and its select-specific behavior
(ensure props like options, on:select, bind:value and handlers such as
handleInvalid remain functional and the info slot stays in place). If free-form
text is needed only for the relationship field, add an explicit opt-in prop
(e.g., allowCustom or freeForm) to InputSelect and only render the plain <Input>
when that prop is true; otherwise render the select component (preserving option
value types and select events).