feat(frontend): disable tabs (#1623)

* feat(frontend): disable tabs

* feat(frontend): disable tabs

* feat(frontend): remove console.log

* feat(frontend): remove GridTabDisabled for Stepper component
This commit is contained in:
Faton Ramadani
2023-05-22 14:37:11 +02:00
committed by GitHub
parent 791170aef9
commit aa243f6dcf
7 changed files with 137 additions and 23 deletions
@@ -4,7 +4,12 @@
import { initConfig, initOutput } from '../../editor/appUtils'
import { components } from '../../editor/component'
import SubGridEditor from '../../editor/SubGridEditor.svelte'
import type { AppViewerContext, ComponentCustomCSS, RichConfigurations } from '../../types'
import type {
AppViewerContext,
ComponentCustomCSS,
RichConfiguration,
RichConfigurations
} from '../../types'
import { concatCustomCss } from '../../utils'
import InputValue from '../helpers/InputValue.svelte'
import InitializeComponent from '../helpers/InitializeComponent.svelte'
@@ -15,6 +20,7 @@
export let tabs: string[]
export let customCss: ComponentCustomCSS<'tabscomponent'> | undefined = undefined
export let render: boolean
export let disabledTabs: RichConfiguration[]
let resolvedConfig = initConfig(
components['tabscomponent'].initialData.configuration,
@@ -76,23 +82,30 @@
$: selected != undefined && handleTabSelection()
let selectedIndex = tabs?.indexOf(selected) ?? -1
$: css = concatCustomCss($app.css?.tabscomponent, customCss)
let resolvedDisabledTabs: boolean[] = []
</script>
<InputValue {id} input={configuration.tabsKind} bind:value={resolvedConfig.tabsKind} />
<InitializeComponent {id} />
{#each disabledTabs ?? [] as disableTab, index}
<InputValue {id} input={disableTab} bind:value={resolvedDisabledTabs[index]} />
{/each}
<div class={resolvedConfig.tabsKind == 'sidebar' ? 'flex gap-4 w-full' : 'w-full'}>
{#if !resolvedConfig.tabsKind || resolvedConfig.tabsKind == 'tabs' || (resolvedConfig.tabsKind == 'invisibleOnView' && $mode == 'dnd')}
<div bind:clientHeight={tabHeight}>
<Tabs bind:selected class={css?.tabRow?.class} style={css?.tabRow?.style}>
{#each tabs ?? [] as res}
{#each tabs ?? [] as res, index}
<Tab
value={res}
class={css?.allTabs?.class}
style={css?.allTabs?.style}
selectedClass={css?.selectedTab?.class}
selectedStyle={css?.selectedTab?.style}
disabled={resolvedDisabledTabs[index]}
>
<span class="font-semibold">{res}</span>
</Tab>
@@ -421,6 +421,7 @@
configuration={component.configuration}
id={component.id}
tabs={component.tabs}
disabledTabs={component.disabledTabs}
customCss={component.customCss}
{componentContainerHeight}
{render}
@@ -106,6 +106,7 @@ export type VerticalDividerComponent = BaseComponent<'verticaldividercomponent'>
export type FileInputComponent = BaseComponent<'fileinputcomponent'>
export type TabsComponent = BaseComponent<'tabscomponent'> & {
tabs: string[]
disabledTabs: RichConfiguration[]
}
export type ContainerComponent = BaseComponent<'containercomponent'>
export type DrawerComponent = BaseComponent<'drawercomponent'>
@@ -245,7 +245,9 @@
{#if componentSettings.item.data.type === 'tabscomponent'}
<GridTab
bind:tabs={componentSettings.item.data.tabs}
bind:disabledTabs={componentSettings.item.data.disabledTabs}
bind:component={componentSettings.item.data}
canDisableTabs
/>
{:else if componentSettings.item.data.type === 'steppercomponent'}
<GridTab
@@ -3,15 +3,29 @@
import CloseButton from '$lib/components/common/CloseButton.svelte'
import { faPlus } from '@fortawesome/free-solid-svg-icons'
import { getContext, tick } from 'svelte'
import type { AppViewerContext } from '../../types'
import type { AppViewerContext, RichConfiguration } from '../../types'
import { deleteGridItem } from '../appUtils'
import type { AppComponent } from '../component'
import PanelSection from './common/PanelSection.svelte'
import { dndzone } from 'svelte-dnd-action'
import { generateRandomString } from '$lib/utils'
import { GripVertical } from 'lucide-svelte'
import GridTabDisabled from './GridTabDisabled.svelte'
export let tabs: string[] = []
export let disabledTabs: RichConfiguration[] = []
export let canDisableTabs: boolean = false
// Migration code
$: if (tabs.length !== disabledTabs?.length && canDisableTabs) {
disabledTabs = Array(tabs.length).fill({
type: 'static',
value: false,
fieldType: 'boolean'
})
}
export let word: string = 'Tab'
export let component: AppComponent
@@ -42,6 +56,8 @@
}
]
component.numberOfSubgrids = items.length
disabledTabs = [...disabledTabs, { type: 'static', value: false, fieldType: 'boolean' }]
}
function deleteSubgrid(index: number) {
@@ -61,12 +77,16 @@
// Remove the corresponding item from the items array
items = items.filter((item) => item.originalIndex !== index)
// Delete the item in the disabledTabs array
disabledTabs = disabledTabs.filter((_, i) => i !== index)
component.numberOfSubgrids = items.length
// Update the originalIndex of the remaining items
items.forEach((item, i) => {
item.originalIndex = i
})
items = items
delete $app!.subgrids![items.length]
$app = $app
}
@@ -96,6 +116,12 @@
$app!.subgrids![`${component.id}-${items[i].originalIndex}`] ?? []
}
const newDisabledTabs: RichConfiguration[] = []
for (let i = 0; i < items.length; i++) {
newDisabledTabs.push(disabledTabs[items[i].originalIndex])
}
disabledTabs = newDisabledTabs
// update originalIndex
items.forEach((item, i) => {
item.originalIndex = i
@@ -145,26 +171,34 @@
on:finalize={handleFinalize}
>
{#each items as item, index (item.id)}
<div class="w-full flex flex-row gap-2 items-center relative my-1">
<input
on:keydown|stopPropagation
on:input={(e) => updateItemValue(index, e)}
type="text"
bind:value={items[index].value}
/>
<div class="absolute right-6">
<CloseButton noBg on:close={() => deleteSubgrid(index)} />
</div>
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<div
tabindex={dragDisabled ? 0 : -1}
class="w-4 h-4"
on:mousedown={startDrag}
on:touchstart={startDrag}
on:keydown={handleKeyDown}
>
<GripVertical size={16} />
<div class="border rounded-md p-2 mb-2 bg-white">
<div class="w-full flex flex-row gap-2 items-center relative my-1">
<input
on:keydown|stopPropagation
on:input={(e) => updateItemValue(index, e)}
type="text"
bind:value={items[index].value}
/>
<div class="absolute right-6">
<CloseButton noBg on:close={() => deleteSubgrid(index)} />
</div>
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<div
tabindex={dragDisabled ? 0 : -1}
class="w-4 h-4"
on:mousedown={startDrag}
on:touchstart={startDrag}
on:keydown={handleKeyDown}
>
<GripVertical size={16} />
</div>
</div>
{#if canDisableTabs}
<GridTabDisabled bind:field={disabledTabs[index]} id={component.id} />
{/if}
</div>
{/each}
</section>
@@ -0,0 +1,59 @@
<script lang="ts">
import Toggle from '$lib/components/Toggle.svelte'
import type { RichConfiguration } from '../../types'
import InputsSpecEditor from './InputsSpecEditor.svelte'
import { slide } from 'svelte/transition'
export let id: string
export let field: RichConfiguration
let disablable = !(field.type === 'static' && field.value === false)
</script>
<Toggle
bind:checked={disablable}
size="xs"
options={{
right: 'Can be disabled'
}}
on:change={() => {
if (disablable) {
field = {
type: 'eval',
expr: 'false',
fieldType: 'boolean'
}
} else {
field = {
type: 'static',
value: false,
fieldType: 'boolean'
}
}
}}
/>
{#if disablable}
<div transition:slide|local>
<InputsSpecEditor
key={`Tab disabled`}
bind:componentInput={field}
{id}
userInputEnabled={false}
shouldCapitalize={true}
resourceOnly={false}
hasRows={false}
fieldType={field?.['fieldType']}
subFieldType={field?.['subFieldType']}
format={field?.['format']}
selectOptions={field?.['selectOptions']}
tooltip={field?.['tooltip']}
onlyStatic={field?.['onlyStatic']}
fileUpload={field?.['fileUpload']}
placeholder={field?.['placeholder']}
customTitle={field?.['customTitle']}
displayType={false}
noVariablePicker={true}
/>
</div>
{/if}
@@ -11,6 +11,8 @@
export let selectedClass = ''
export let selectedStyle = ''
export let disabled: boolean = false
const fontSizeClasses = {
xs: 'text-xs',
sm: 'text-sm',
@@ -30,7 +32,8 @@
: 'border-gray-300 border-opacity-0 hover:border-opacity-100 text-gray-600',
fontSizeClasses[size],
c,
$selected?.startsWith(value) ? selectedClass : ''
$selected?.startsWith(value) ? selectedClass : '',
disabled ? 'cursor-not-allowed text-gray-400' : ''
)}
style={`${style} ${$selected?.startsWith(value) ? selectedStyle : ''}`}
on:click={() => {
@@ -41,6 +44,7 @@
}
}}
on:pointerdown|stopPropagation
{disabled}
>
<slot />
</button>