r/w/rw multi toggle

This commit is contained in:
Diego Imbert
2025-07-03 01:29:09 +02:00
parent 00f6750cd4
commit 2d6b34a574
5 changed files with 71 additions and 40 deletions
@@ -0,0 +1,42 @@
<!-- A component similar to Toggle but with more than two values -->
<script lang="ts" generics="T">
import { twMerge } from 'tailwind-merge'
import { getLabel } from './select/utils.svelte'
let {
items,
value = $bindable(),
class: className,
error,
disabled
}: {
items: { label?: string; value: T }[]
value: T
class?: string
error?: boolean
disabled?: boolean
} = $props()
</script>
<ul
class={twMerge(
'flex text-nowrap bg-gray-300 rounded-full items-center select-none border',
error ? 'border-red-300 bg-red-100' : '',
className
)}
>
{#each items as item}
<li class="h-6 mx-[1px] text-xs flex items-center">
<button
class={twMerge(
'rounded-full px-1.5 h-[22px] min-w-[22px] flex items-center justify-center',
value === item.value ? 'bg-white' : ''
)}
{disabled}
onclick={() => !disabled && (value = item.value)}
>
{getLabel(item)}
</button>
</li>
{/each}
</ul>
@@ -10,15 +10,15 @@
} from '../../../routes/(root)/(logged)/assets/ExploreAssetButton.svelte'
import { assetEq, formatAsset, type Asset, type AssetWithAccessType } from './lib'
import DbManagerDrawer from '../DBManagerDrawer.svelte'
import { untrack } from 'svelte'
import { ResourceService, type AssetUsageAccessType } from '$lib/gen'
import { tick, untrack } from 'svelte'
import { ResourceService } from '$lib/gen'
import { workspaceStore } from '$lib/stores'
import Button from '../common/button/Button.svelte'
import Tooltip from '../meltComponents/Tooltip.svelte'
import ResourceEditorDrawer from '../ResourceEditorDrawer.svelte'
import type { Placement } from '@floating-ui/core'
import Select from '../select/Select.svelte'
import { safeSelectItems } from '../select/utils.svelte'
import MultiToggle from '../MultiToggle.svelte'
let {
assets,
@@ -27,10 +27,9 @@
noBtnText = false,
popoverPlacement = 'bottom-end',
disableLiTooltip = false,
accessTypeOverrides,
alternativeAccessTypes = $bindable(),
onHoverLi,
liSubtitle,
onAccessTypeChanged
liSubtitle
}: {
assets: AssetWithAccessType[]
enableChangeAnimation?: boolean
@@ -38,10 +37,9 @@
noBtnText?: boolean
popoverPlacement?: Placement
disableLiTooltip?: boolean
accessTypeOverrides?: AssetWithAccessType[]
alternativeAccessTypes?: AssetWithAccessType[]
onHoverLi?: (asset: Asset, eventType: 'enter' | 'leave') => void
liSubtitle?: (asset: Asset) => string
onAccessTypeChanged?: (asset: AssetWithAccessType, accessType: AssetUsageAccessType) => void
} = $props()
let prevAssets = $state<typeof assets>([])
@@ -117,6 +115,9 @@
<svelte:fragment slot="content">
<ul class="divide-y rounded-md">
{#each assets as asset}
{@const alternativeAccessType = alternativeAccessTypes?.find((a) =>
assetEq(a, asset)
)?.access_type}
<li
class="text-sm px-4 h-12 flex gap-4 items-center justify-between hover:bg-surface-hover"
onmouseenter={() => onHoverLi?.(asset, 'enter')}
@@ -134,7 +135,7 @@
</span>
</div>
<div class="flex gap-2">
<div class="flex gap-2 items-center">
{#if asset.kind === 'resource' && resourceDataCache[asset.path] !== undefined}
<Button
startIcon={{ icon: Edit2 }}
@@ -161,20 +162,20 @@
_resourceMetadata={{ resource_type: resourceDataCache[asset.path] }}
/>
{/if}
{#if onAccessTypeChanged}
<Select
disablePortal
items={safeSelectItems(['r', 'w', 'rw'])}
bind:value={
() =>
accessTypeOverrides?.find((a) => assetEq(a, asset))?.access_type ??
asset.access_type,
(a) => {
a && onAccessTypeChanged?.(asset, a)
}
<MultiToggle
items={safeSelectItems(['r', 'w', 'rw'])}
error={!asset.access_type && !alternativeAccessType}
disabled={!!asset.access_type}
bind:value={
() => asset.access_type ?? alternativeAccessType,
async (access_type) => {
alternativeAccessTypes = alternativeAccessTypes?.filter((a) => !assetEq(a, asset))
alternativeAccessTypes ??= []
await tick()
alternativeAccessTypes.push({ ...asset, access_type })
}
/>
{/if}
}
/>
</div>
</li>
{/each}
@@ -56,7 +56,6 @@
import { getStepHistoryLoaderContext } from '$lib/components/stepHistoryLoader.svelte'
import AssetsDropdownButton from '$lib/components/assets/AssetsDropdownButton.svelte'
import { inferAssets } from '$lib/infer'
import { assetEq } from '$lib/components/assets/lib'
const {
selectedId,
@@ -420,20 +419,9 @@
{#if assets.value?.length}
<AssetsDropdownButton
assets={assets.value}
accessTypeOverrides={flowModule.value.asset_access_type_overrides}
onAccessTypeChanged={async (asset, access_type) => {
if (flowModule.value.type !== 'rawscript') return
flowModule.value.asset_access_type_overrides =
flowModule.value.asset_access_type_overrides?.filter(
(a) => !assetEq(a, asset)
)
flowModule.value.asset_access_type_overrides ??= []
await tick()
flowModule.value.asset_access_type_overrides.push({
...asset,
access_type
})
}}
bind:alternativeAccessTypes={
flowModule.value.asset_alternative_access_types
}
/>
{/if}
</div>
@@ -741,11 +741,11 @@
{#if mod.value.type === 'rawscript'}
{@const v = mod.value}
<OnChange
key={[v.content, v.asset_access_type_overrides]}
key={[v.content, v.asset_alternative_access_types]}
runFirstEffect
onChange={() =>
inferAssets(v.language, v.content).then((assets) => {
for (const override of v.asset_access_type_overrides ?? []) {
for (const override of v.asset_alternative_access_types ?? []) {
assets = assets.map((asset) => {
if (assetEq(asset, override)) return { ...asset, access_type: override.access_type }
return asset
+1 -1
View File
@@ -270,7 +270,7 @@ components:
type: string
is_trigger:
type: boolean
asset_access_type_overrides:
asset_alternative_access_types:
type: array
items:
type: object