pocketbase/ui/src/components/collections/RuleField.svelte

192 lines
5.3 KiB
Svelte
Raw Normal View History

2022-10-30 16:28:14 +08:00
<script context="module">
let cachedRuleComponent;
</script>
<script>
import { tick } from "svelte";
2023-03-24 04:59:02 +08:00
import { scale } from "svelte/transition";
2022-10-30 16:28:14 +08:00
import Field from "@/components/base/Field.svelte";
export let collection = null;
export let rule = null;
export let label = "Rule";
export let formKey = "rule";
export let required = false;
2023-03-25 04:30:57 +08:00
export let placeholder = "Leave empty to grant everyone access...";
2022-10-30 16:28:14 +08:00
let editorRef = null;
let tempValue = null;
let ruleInputComponent = cachedRuleComponent;
let isRuleComponentLoading = false;
$: isAdminOnly = rule === null;
2023-01-08 04:25:56 +08:00
loadEditorComponent();
2022-10-30 16:28:14 +08:00
async function loadEditorComponent() {
if (ruleInputComponent || isRuleComponentLoading) {
return; // already loaded or in the process
}
isRuleComponentLoading = true;
ruleInputComponent = (await import("@/components/base/FilterAutocompleteInput.svelte")).default;
cachedRuleComponent = ruleInputComponent;
isRuleComponentLoading = false;
}
2023-01-08 04:25:56 +08:00
async function unlock() {
rule = tempValue || "";
await tick();
editorRef?.focus();
}
async function lock() {
tempValue = rule;
rule = null;
}
2022-10-30 16:28:14 +08:00
</script>
{#if isRuleComponentLoading}
<div class="txt-center">
<span class="loader" />
</div>
{:else}
2023-01-08 04:25:56 +08:00
<Field
2023-03-04 19:05:55 +08:00
class="form-field rule-field {required ? 'requied' : ''} {isAdminOnly ? 'disabled' : ''}"
2023-01-08 04:25:56 +08:00
name={formKey}
let:uniqueId
>
2023-03-24 04:59:02 +08:00
<div class="input-wrapper">
<label for={uniqueId}>
<slot name="beforeLabel" {isAdminOnly} />
2023-03-24 04:59:02 +08:00
<span class="txt" class:txt-hint={isAdminOnly}>
{label}
{isAdminOnly ? "- Admins only" : ""}
</span>
<slot name="afterLabel" {isAdminOnly} />
2023-03-24 04:59:02 +08:00
{#if !isAdminOnly}
<button
type="button"
class="btn btn-sm btn-transparent btn-hint lock-toggle"
2023-03-24 04:59:02 +08:00
on:click={lock}
>
<i class="ri-lock-line" />
<span class="txt">Set Admins only</span>
</button>
{/if}
</label>
<svelte:component
this={ruleInputComponent}
id={uniqueId}
bind:this={editorRef}
bind:value={rule}
baseCollection={collection}
disabled={isAdminOnly}
2023-03-25 04:30:57 +08:00
placeholder={!isAdminOnly ? placeholder : ""}
2023-03-24 04:59:02 +08:00
/>
2023-01-08 04:25:56 +08:00
{#if isAdminOnly}
2023-01-08 17:11:02 +08:00
<button
type="button"
2023-03-24 04:59:02 +08:00
class="unlock-overlay"
aria-label="Unlock and set custom rule"
2023-09-01 14:22:49 +08:00
transition:scale={{ duration: 150, start: 0.98 }}
2023-01-08 17:11:02 +08:00
on:click={unlock}
>
2023-03-28 12:59:37 +08:00
<small class="txt">Unlock and set custom rule</small>
2023-03-24 04:59:02 +08:00
<div class="icon">
<i class="ri-lock-unlock-line" />
</div>
2023-01-08 04:25:56 +08:00
</button>
{/if}
2023-03-24 04:59:02 +08:00
</div>
2023-01-08 04:25:56 +08:00
<div class="help-block">
2023-03-04 19:05:55 +08:00
<slot {isAdminOnly} />
2023-01-08 04:25:56 +08:00
</div>
</Field>
2022-10-30 16:28:14 +08:00
{/if}
2023-03-24 04:59:02 +08:00
<style lang="scss">
2023-01-08 04:25:56 +08:00
.lock-toggle {
2023-01-08 17:11:02 +08:00
position: absolute;
right: 0px;
top: 0px;
min-width: 135px;
2023-02-19 01:33:42 +08:00
padding: 10px;
2023-01-08 17:11:02 +08:00
border-top-left-radius: 0;
border-bottom-right-radius: 0;
2023-02-26 16:47:00 +08:00
background: rgba(53, 71, 104, 0.09);
2022-10-30 16:28:14 +08:00
}
2023-03-05 21:18:51 +08:00
:global(.rule-field .code-editor .cm-placeholder) {
font-family: var(--baseFontFamily);
}
2023-03-24 04:59:02 +08:00
.input-wrapper {
position: relative;
}
.unlock-overlay {
2023-03-28 12:59:37 +08:00
--hoverAnimationSpeed: 0.2s;
2023-03-24 04:59:02 +08:00
position: absolute;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
display: flex;
2023-03-28 12:59:37 +08:00
padding: 20px;
gap: 10px;
2023-03-24 04:59:02 +08:00
align-items: center;
2023-03-28 12:59:37 +08:00
justify-content: end;
2023-03-24 04:59:02 +08:00
text-align: center;
border-radius: var(--baseRadius);
2023-03-28 12:59:37 +08:00
background: rgba(255, 255, 255, 0.2);
2023-03-24 04:59:02 +08:00
outline: 0;
cursor: pointer;
text-decoration: none;
color: var(--successColor);
border: 2px solid var(--baseAlt1Color);
transition: border-color var(--baseAnimationSpeed);
i {
font-size: inherit;
}
.icon {
color: var(--successColor);
font-size: 1.15rem;
line-height: 1;
font-weight: normal;
2023-03-28 12:59:37 +08:00
transition: transform var(--hoverAnimationSpeed);
2023-03-24 04:59:02 +08:00
}
.txt {
opacity: 0;
font-size: var(--xsFontSize);
font-weight: 600;
line-height: var(--smLineHeight);
2023-03-28 12:59:37 +08:00
transform: translateX(5px);
transition: transform var(--hoverAnimationSpeed), opacity var(--hoverAnimationSpeed);
2023-03-24 04:59:02 +08:00
}
&:hover,
&:focus-visible,
&:active {
2023-03-28 12:59:37 +08:00
border-color: var(--baseAlt3Color);
2023-03-24 04:59:02 +08:00
.icon {
2023-03-28 12:59:37 +08:00
transform: scale(1.1);
2023-03-24 04:59:02 +08:00
}
.txt {
opacity: 1;
transform: scale(1);
}
}
&:active {
transition-duration: var(--activeAnimationSpeed);
border-color: var(--baseAlt3Color);
}
}
2022-10-30 16:28:14 +08:00
</style>