wired ui: add source selector support

This commit is contained in:
Lorenzune
2026-03-15 19:02:34 +01:00
parent bdae069003
commit ba0208c654
37 changed files with 1095 additions and 104 deletions
@@ -3,6 +3,7 @@ import { LocalizeText, WiredFurniType } from '../../../../api';
import { Text } from '../../../../common';
import { useWired } from '../../../../hooks';
import { WiredConditionBaseView } from './WiredConditionBaseView';
import { WiredSourcesSelector } from '../WiredSourcesSelector';
const ALLOWED_HAND_ITEM_IDS: number[] = [ 2, 5, 7, 8, 9, 10, 27 ];
@@ -10,16 +11,26 @@ export const WiredConditionActorHasHandItemView: FC<{}> = props =>
{
const [ handItemId, setHandItemId ] = useState(-1);
const { trigger = null, setIntParams = null } = useWired();
const [ userSource, setUserSource ] = useState<number>(() =>
{
if(trigger?.intData?.length > 1) return trigger.intData[1];
return 0;
});
const save = () => setIntParams([ handItemId ]);
const save = () => setIntParams([ handItemId, userSource ]);
useEffect(() =>
{
setHandItemId((trigger.intData.length > 0) ? trigger.intData[0] : 0);
setUserSource((trigger.intData.length > 1) ? trigger.intData[1] : 0);
}, [ trigger ]);
return (
<WiredConditionBaseView hasSpecialInput={ true } requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_NONE } save={ save }>
<WiredConditionBaseView
hasSpecialInput={ true }
requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_NONE }
save={ save }
footer={ <WiredSourcesSelector showUsers={ true } userSource={ userSource } onChangeUsers={ setUserSource } /> }>
<div className="flex flex-col gap-1">
<Text bold>{ LocalizeText('wiredfurni.params.handitem') }</Text>
<select className="form-select form-select-sm" value={ handItemId } onChange={ event => setHandItemId(parseInt(event.target.value)) }>
@@ -1,8 +1,32 @@
import { FC } from 'react';
import { FC, useEffect, useState } from 'react';
import { WiredFurniType } from '../../../../api';
import { useWired } from '../../../../hooks';
import { WiredConditionBaseView } from './WiredConditionBaseView';
import { WiredSourcesSelector } from '../WiredSourcesSelector';
export const WiredConditionActorIsGroupMemberView: FC<{}> = props =>
{
return <WiredConditionBaseView hasSpecialInput={ false } requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_NONE } save={ null } />;
const { trigger = null, setIntParams = null } = useWired();
const [ userSource, setUserSource ] = useState<number>(() =>
{
if(trigger?.intData?.length >= 1) return trigger.intData[0];
return 0;
});
useEffect(() =>
{
if(!trigger) return;
if(trigger.intData.length >= 1) setUserSource(trigger.intData[0]);
else setUserSource(0);
}, [ trigger ]);
const save = () => setIntParams([ userSource ]);
return (
<WiredConditionBaseView
hasSpecialInput={ true }
requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_NONE }
save={ save }
footer={ <WiredSourcesSelector showUsers={ true } userSource={ userSource } onChangeUsers={ setUserSource } /> } />
);
};
@@ -1,8 +1,67 @@
import { FC } from 'react';
import { WiredFurniType } from '../../../../api';
import { FC, useEffect, useState } from 'react';
import { WiredFurniType, WiredSelectionVisualizer } from '../../../../api';
import { useWired } from '../../../../hooks';
import { WiredConditionBaseView } from './WiredConditionBaseView';
import { WiredSourcesSelector } from '../WiredSourcesSelector';
export const WiredConditionActorIsOnFurniView: FC<{}> = props =>
{
return <WiredConditionBaseView hasSpecialInput={ false } requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_BY_ID } save={ null } />;
const { trigger = null, furniIds = [], setFurniIds = null, setIntParams = null } = useWired();
const [ furniSource, setFurniSource ] = useState<number>(() =>
{
if(trigger?.intData?.length > 0) return trigger.intData[0];
return (trigger?.selectedItems?.length ?? 0) > 0 ? 100 : 0;
});
const [ userSource, setUserSource ] = useState<number>(() =>
{
if(trigger?.intData?.length > 1) return trigger.intData[1];
return 0;
});
useEffect(() =>
{
if(!trigger) return;
if(trigger.intData.length > 0) setFurniSource(trigger.intData[0]);
else setFurniSource((trigger.selectedItems?.length ?? 0) > 0 ? 100 : 0);
if(trigger.intData.length > 1) setUserSource(trigger.intData[1]);
else setUserSource(0);
}, [ trigger ]);
const onChangeFurniSource = (next: number) =>
{
if(furniIds.length && setFurniIds)
{
setFurniIds(prev =>
{
if(prev && prev.length) WiredSelectionVisualizer.clearSelectionShaderFromFurni(prev);
return [];
});
}
setFurniSource(next);
};
const save = () => setIntParams([ furniSource, userSource ]);
const requiresFurni = (furniSource === 100)
? WiredFurniType.STUFF_SELECTION_OPTION_BY_ID
: WiredFurniType.STUFF_SELECTION_OPTION_NONE;
return (
<WiredConditionBaseView
hasSpecialInput={ true }
requiresFurni={ requiresFurni }
save={ save }
footer={ (
<WiredSourcesSelector
showFurni={ true }
showUsers={ true }
furniSource={ furniSource }
userSource={ userSource }
onChangeFurni={ onChangeFurniSource }
onChangeUsers={ setUserSource } />
) } />
);
};
@@ -3,6 +3,7 @@ import { LocalizeText, WiredFurniType } from '../../../../api';
import { Text } from '../../../../common';
import { useWired } from '../../../../hooks';
import { WiredConditionBaseView } from './WiredConditionBaseView';
import { WiredSourcesSelector } from '../WiredSourcesSelector';
const teamIds: number[] = [ 1, 2, 3, 4 ];
@@ -10,16 +11,26 @@ export const WiredConditionActorIsTeamMemberView: FC<{}> = props =>
{
const [ selectedTeam, setSelectedTeam ] = useState(-1);
const { trigger = null, setIntParams = null } = useWired();
const [ userSource, setUserSource ] = useState<number>(() =>
{
if(trigger?.intData?.length > 1) return trigger.intData[1];
return 0;
});
const save = () => setIntParams([ selectedTeam ]);
const save = () => setIntParams([ selectedTeam, userSource ]);
useEffect(() =>
{
setSelectedTeam((trigger.intData.length > 0) ? trigger.intData[0] : 0);
setUserSource((trigger.intData.length > 1) ? trigger.intData[1] : 0);
}, [ trigger ]);
return (
<WiredConditionBaseView hasSpecialInput={ true } requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_NONE } save={ save }>
<WiredConditionBaseView
hasSpecialInput={ true }
requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_NONE }
save={ save }
footer={ <WiredSourcesSelector showUsers={ true } userSource={ userSource } onChangeUsers={ setUserSource } /> }>
<div className="flex flex-col gap-1">
<Text bold>{ LocalizeText('wiredfurni.params.team') }</Text>
{ teamIds.map(value =>
@@ -4,21 +4,37 @@ import { Text } from '../../../../common';
import { useWired } from '../../../../hooks';
import { NitroInput } from '../../../../layout';
import { WiredConditionBaseView } from './WiredConditionBaseView';
import { WiredSourcesSelector } from '../WiredSourcesSelector';
export const WiredConditionActorIsWearingBadgeView: FC<{}> = props =>
{
const [ badge, setBadge ] = useState('');
const { trigger = null, setStringParam = null } = useWired();
const { trigger = null, setStringParam = null, setIntParams = null } = useWired();
const [ userSource, setUserSource ] = useState<number>(() =>
{
if(trigger?.intData?.length >= 1) return trigger.intData[0];
return 0;
});
const save = () => setStringParam(badge);
const save = () =>
{
setStringParam(badge);
setIntParams([ userSource ]);
};
useEffect(() =>
{
setBadge(trigger.stringData);
if(trigger.intData.length >= 1) setUserSource(trigger.intData[0]);
else setUserSource(0);
}, [ trigger ]);
return (
<WiredConditionBaseView hasSpecialInput={ true } requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_NONE } save={ save }>
<WiredConditionBaseView
hasSpecialInput={ true }
requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_NONE }
save={ save }
footer={ <WiredSourcesSelector showUsers={ true } userSource={ userSource } onChangeUsers={ setUserSource } /> }>
<div className="flex flex-col gap-1">
<Text bold>{ LocalizeText('wiredfurni.params.badgecode') }</Text>
<NitroInput type="text" value={ badge } onChange={ event => setBadge(event.target.value) } />
@@ -4,21 +4,33 @@ import { Text } from '../../../../common';
import { useWired } from '../../../../hooks';
import { NitroInput } from '../../../../layout';
import { WiredConditionBaseView } from './WiredConditionBaseView';
import { WiredSourcesSelector } from '../WiredSourcesSelector';
export const WiredConditionActorIsWearingEffectView: FC<{}> = props =>
{
const [ effect, setEffect ] = useState(-1);
const { trigger = null, setIntParams = null } = useWired();
const [ userSource, setUserSource ] = useState<number>(() =>
{
if(trigger?.intData?.length > 1) return trigger.intData[1];
return 0;
});
const save = () => setIntParams([ effect ]);
const save = () => setIntParams([ effect, userSource ]);
useEffect(() =>
{
setEffect(trigger?.intData[0] ?? 0);
if(trigger?.intData?.length > 1) setUserSource(trigger.intData[1]);
else setUserSource(0);
}, [ trigger ]);
return (
<WiredConditionBaseView hasSpecialInput={ true } requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_NONE } save={ save }>
<WiredConditionBaseView
hasSpecialInput={ true }
requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_NONE }
save={ save }
footer={ <WiredSourcesSelector showUsers={ true } userSource={ userSource } onChangeUsers={ setUserSource } /> }>
<div className="flex flex-col gap-1">
<Text bold>{ LocalizeText('wiredfurni.tooltip.effectid') }</Text>
<NitroInput type="number" value={ effect } onChange={ event => setEffect(parseInt(event.target.value)) } />
@@ -1,4 +1,4 @@
import { FC, PropsWithChildren } from 'react';
import { FC, PropsWithChildren, ReactNode } from 'react';
import { WiredFurniType } from '../../../../api';
import { WiredBaseView } from '../WiredBaseView';
@@ -7,16 +7,17 @@ export interface WiredConditionBaseViewProps
hasSpecialInput: boolean;
requiresFurni: number;
save: () => void;
footer?: ReactNode;
}
export const WiredConditionBaseView: FC<PropsWithChildren<WiredConditionBaseViewProps>> = props =>
{
const { requiresFurni = WiredFurniType.STUFF_SELECTION_OPTION_NONE, save = null, hasSpecialInput = false, children = null } = props;
const { requiresFurni = WiredFurniType.STUFF_SELECTION_OPTION_NONE, save = null, hasSpecialInput = false, children = null, footer = null } = props;
const onSave = () => (save && save());
return (
<WiredBaseView hasSpecialInput={ hasSpecialInput } requiresFurni={ requiresFurni } save={ onSave } wiredType="condition">
<WiredBaseView hasSpecialInput={ hasSpecialInput } requiresFurni={ requiresFurni } save={ onSave } wiredType="condition" footer={ footer }>
{ children }
</WiredBaseView>
);
@@ -1,8 +1,50 @@
import { FC } from 'react';
import { WiredFurniType } from '../../../../api';
import { FC, useEffect, useState } from 'react';
import { WiredFurniType, WiredSelectionVisualizer } from '../../../../api';
import { useWired } from '../../../../hooks';
import { WiredConditionBaseView } from './WiredConditionBaseView';
import { WiredSourcesSelector } from '../WiredSourcesSelector';
export const WiredConditionFurniHasAvatarOnView: FC<{}> = props =>
{
return <WiredConditionBaseView hasSpecialInput={ false } requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_BY_ID } save={ null } />;
const { trigger = null, furniIds = [], setFurniIds = null, setIntParams = null } = useWired();
const [ furniSource, setFurniSource ] = useState<number>(() =>
{
if(trigger?.intData?.length >= 1) return trigger.intData[0];
return (trigger?.selectedItems?.length ?? 0) > 0 ? 100 : 0;
});
useEffect(() =>
{
if(!trigger) return;
if(trigger.intData.length >= 1) setFurniSource(trigger.intData[0]);
else setFurniSource((trigger.selectedItems?.length ?? 0) > 0 ? 100 : 0);
}, [ trigger ]);
const onChangeFurniSource = (next: number) =>
{
if(furniIds.length && setFurniIds)
{
setFurniIds(prev =>
{
if(prev && prev.length) WiredSelectionVisualizer.clearSelectionShaderFromFurni(prev);
return [];
});
}
setFurniSource(next);
};
const save = () => setIntParams([ furniSource ]);
const requiresFurni = (furniSource === 100)
? WiredFurniType.STUFF_SELECTION_OPTION_BY_ID
: WiredFurniType.STUFF_SELECTION_OPTION_NONE;
return (
<WiredConditionBaseView
hasSpecialInput={ true }
requiresFurni={ requiresFurni }
save={ save }
footer={ <WiredSourcesSelector showFurni={ true } furniSource={ furniSource } onChangeFurni={ onChangeFurniSource } /> } />
);
};
@@ -1,23 +1,53 @@
import { FC, useEffect, useState } from 'react';
import { LocalizeText, WiredFurniType } from '../../../../api';
import { LocalizeText, WiredFurniType, WiredSelectionVisualizer } from '../../../../api';
import { Text } from '../../../../common';
import { useWired } from '../../../../hooks';
import { WiredConditionBaseView } from './WiredConditionBaseView';
import { WiredSourcesSelector } from '../WiredSourcesSelector';
export const WiredConditionFurniHasFurniOnView: FC<{}> = props =>
{
const [ requireAll, setRequireAll ] = useState(-1);
const { trigger = null, setIntParams = null } = useWired();
const { trigger = null, furniIds = [], setFurniIds = null, setIntParams = null } = useWired();
const [ furniSource, setFurniSource ] = useState<number>(() =>
{
if(trigger?.intData?.length > 1) return trigger.intData[1];
return (trigger?.selectedItems?.length ?? 0) > 0 ? 100 : 0;
});
const save = () => setIntParams([ requireAll ]);
const save = () => setIntParams([ requireAll, furniSource ]);
useEffect(() =>
{
setRequireAll((trigger.intData.length > 0) ? trigger.intData[0] : 0);
if(trigger.intData.length > 1) setFurniSource(trigger.intData[1]);
else setFurniSource((trigger.selectedItems?.length ?? 0) > 0 ? 100 : 0);
}, [ trigger ]);
const onChangeFurniSource = (next: number) =>
{
if(furniIds.length && setFurniIds)
{
setFurniIds(prev =>
{
if(prev && prev.length) WiredSelectionVisualizer.clearSelectionShaderFromFurni(prev);
return [];
});
}
setFurniSource(next);
};
const requiresFurni = (furniSource === 100)
? WiredFurniType.STUFF_SELECTION_OPTION_BY_ID
: WiredFurniType.STUFF_SELECTION_OPTION_NONE;
return (
<WiredConditionBaseView hasSpecialInput={ true } requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_BY_ID } save={ save }>
<WiredConditionBaseView
hasSpecialInput={ true }
requiresFurni={ requiresFurni }
save={ save }
footer={ <WiredSourcesSelector showFurni={ true } furniSource={ furniSource } onChangeFurni={ onChangeFurniSource } /> }>
<div className="flex flex-col gap-1">
<Text bold>{ LocalizeText('wiredfurni.params.requireall') }</Text>
{ [ 0, 1 ].map(value =>
@@ -1,23 +1,53 @@
import { FC, useEffect, useState } from 'react';
import { LocalizeText, WiredFurniType } from '../../../../api';
import { LocalizeText, WiredFurniType, WiredSelectionVisualizer } from '../../../../api';
import { Text } from '../../../../common';
import { useWired } from '../../../../hooks';
import { WiredConditionBaseView } from './WiredConditionBaseView';
import { WiredSourcesSelector } from '../WiredSourcesSelector';
export const WiredConditionFurniHasNotFurniOnView: FC<{}> = props =>
{
const [ requireAll, setRequireAll ] = useState(-1);
const { trigger = null, setIntParams = null } = useWired();
const { trigger = null, furniIds = [], setFurniIds = null, setIntParams = null } = useWired();
const [ furniSource, setFurniSource ] = useState<number>(() =>
{
if(trigger?.intData?.length > 1) return trigger.intData[1];
return (trigger?.selectedItems?.length ?? 0) > 0 ? 100 : 0;
});
const save = () => setIntParams([ requireAll ]);
const save = () => setIntParams([ requireAll, furniSource ]);
useEffect(() =>
{
setRequireAll((trigger.intData.length > 0) ? trigger.intData[0] : 0);
if(trigger.intData.length > 1) setFurniSource(trigger.intData[1]);
else setFurniSource((trigger.selectedItems?.length ?? 0) > 0 ? 100 : 0);
}, [ trigger ]);
const onChangeFurniSource = (next: number) =>
{
if(furniIds.length && setFurniIds)
{
setFurniIds(prev =>
{
if(prev && prev.length) WiredSelectionVisualizer.clearSelectionShaderFromFurni(prev);
return [];
});
}
setFurniSource(next);
};
const requiresFurni = (furniSource === 100)
? WiredFurniType.STUFF_SELECTION_OPTION_BY_ID
: WiredFurniType.STUFF_SELECTION_OPTION_NONE;
return (
<WiredConditionBaseView hasSpecialInput={ true } requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_BY_ID } save={ save }>
<WiredConditionBaseView
hasSpecialInput={ true }
requiresFurni={ requiresFurni }
save={ save }
footer={ <WiredSourcesSelector showFurni={ true } furniSource={ furniSource } onChangeFurni={ onChangeFurniSource } /> }>
<div className="flex flex-col gap-1">
<Text bold>{ LocalizeText('wiredfurni.params.not_requireall') }</Text>
{ [ 0, 1 ].map(value =>
@@ -1,8 +1,50 @@
import { FC } from 'react';
import { WiredFurniType } from '../../../../api';
import { FC, useEffect, useState } from 'react';
import { WiredFurniType, WiredSelectionVisualizer } from '../../../../api';
import { useWired } from '../../../../hooks';
import { WiredConditionBaseView } from './WiredConditionBaseView';
import { WiredSourcesSelector } from '../WiredSourcesSelector';
export const WiredConditionFurniIsOfTypeView: FC<{}> = props =>
{
return <WiredConditionBaseView hasSpecialInput={ false } requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_BY_ID_OR_BY_TYPE } save={ null } />;
const { trigger = null, furniIds = [], setFurniIds = null, setIntParams = null } = useWired();
const [ furniSource, setFurniSource ] = useState<number>(() =>
{
if(trigger?.intData?.length >= 1) return trigger.intData[0];
return (trigger?.selectedItems?.length ?? 0) > 0 ? 100 : 0;
});
useEffect(() =>
{
if(!trigger) return;
if(trigger.intData.length >= 1) setFurniSource(trigger.intData[0]);
else setFurniSource((trigger.selectedItems?.length ?? 0) > 0 ? 100 : 0);
}, [ trigger ]);
const onChangeFurniSource = (next: number) =>
{
if(furniIds.length && setFurniIds)
{
setFurniIds(prev =>
{
if(prev && prev.length) WiredSelectionVisualizer.clearSelectionShaderFromFurni(prev);
return [];
});
}
setFurniSource(next);
};
const save = () => setIntParams([ furniSource ]);
const requiresFurni = (furniSource === 100)
? WiredFurniType.STUFF_SELECTION_OPTION_BY_ID_OR_BY_TYPE
: WiredFurniType.STUFF_SELECTION_OPTION_NONE;
return (
<WiredConditionBaseView
hasSpecialInput={ true }
requiresFurni={ requiresFurni }
save={ save }
footer={ <WiredSourcesSelector showFurni={ true } furniSource={ furniSource } onChangeFurni={ onChangeFurniSource } /> } />
);
};
@@ -1,27 +1,57 @@
import { FC, useEffect, useState } from 'react';
import { LocalizeText, WiredFurniType } from '../../../../api';
import { LocalizeText, WiredFurniType, WiredSelectionVisualizer } from '../../../../api';
import { Text } from '../../../../common';
import { useWired } from '../../../../hooks';
import { WiredConditionBaseView } from './WiredConditionBaseView';
import { WiredSourcesSelector } from '../WiredSourcesSelector';
export const WiredConditionFurniMatchesSnapshotView: FC<{}> = props =>
{
const [ stateFlag, setStateFlag ] = useState(0);
const [ directionFlag, setDirectionFlag ] = useState(0);
const [ positionFlag, setPositionFlag ] = useState(0);
const { trigger = null, setIntParams = null } = useWired();
const { trigger = null, furniIds = [], setFurniIds = null, setIntParams = null } = useWired();
const [ furniSource, setFurniSource ] = useState<number>(() =>
{
if(trigger?.intData?.length > 3) return trigger.intData[3];
return (trigger?.selectedItems?.length ?? 0) > 0 ? 100 : 0;
});
const save = () => setIntParams([ stateFlag, directionFlag, positionFlag ]);
const save = () => setIntParams([ stateFlag, directionFlag, positionFlag, furniSource ]);
useEffect(() =>
{
setStateFlag(trigger.getBoolean(0) ? 1 : 0);
setDirectionFlag(trigger.getBoolean(1) ? 1 : 0);
setPositionFlag(trigger.getBoolean(2) ? 1 : 0);
if(trigger.intData.length > 3) setFurniSource(trigger.intData[3]);
else setFurniSource((trigger.selectedItems?.length ?? 0) > 0 ? 100 : 0);
}, [ trigger ]);
const onChangeFurniSource = (next: number) =>
{
if(furniIds.length && setFurniIds)
{
setFurniIds(prev =>
{
if(prev && prev.length) WiredSelectionVisualizer.clearSelectionShaderFromFurni(prev);
return [];
});
}
setFurniSource(next);
};
const requiresFurni = (furniSource === 100)
? WiredFurniType.STUFF_SELECTION_OPTION_BY_ID
: WiredFurniType.STUFF_SELECTION_OPTION_NONE;
return (
<WiredConditionBaseView hasSpecialInput={ true } requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_BY_ID } save={ save }>
<WiredConditionBaseView
hasSpecialInput={ true }
requiresFurni={ requiresFurni }
save={ save }
footer={ <WiredSourcesSelector showFurni={ true } furniSource={ furniSource } onChangeFurni={ onChangeFurniSource } /> }>
<div className="flex flex-col gap-1">
<Text bold>{ LocalizeText('wiredfurni.params.conditions') }</Text>
<div className="flex items-center gap-1">
@@ -3,14 +3,20 @@ import { LocalizeText, WiredFurniType } from '../../../../api';
import { Slider, Text } from '../../../../common';
import { useWired } from '../../../../hooks';
import { WiredConditionBaseView } from './WiredConditionBaseView';
import { WiredSourcesSelector } from '../WiredSourcesSelector';
export const WiredConditionUserCountInRoomView: FC<{}> = props =>
{
const [ min, setMin ] = useState(1);
const [ max, setMax ] = useState(0);
const { trigger = null, setIntParams = null } = useWired();
const [ userSource, setUserSource ] = useState<number>(() =>
{
if(trigger?.intData?.length > 2) return trigger.intData[2];
return 0;
});
const save = () => setIntParams([ min, max ]);
const save = () => setIntParams([ min, max, userSource ]);
useEffect(() =>
{
@@ -24,10 +30,16 @@ export const WiredConditionUserCountInRoomView: FC<{}> = props =>
setMin(1);
setMax(0);
}
if(trigger.intData.length > 2) setUserSource(trigger.intData[2]);
else setUserSource(0);
}, [ trigger ]);
return (
<WiredConditionBaseView hasSpecialInput={ true } requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_NONE } save={ save }>
<WiredConditionBaseView
hasSpecialInput={ true }
requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_NONE }
save={ save }
footer={ <WiredSourcesSelector showUsers={ true } userSource={ userSource } onChangeUsers={ setUserSource } /> }>
<div className="flex flex-col gap-1">
<Text bold>{ LocalizeText('wiredfurni.params.usercountmin', [ 'value' ], [ min.toString() ]) }</Text>
<Slider