🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@isoftdata/svelte-user-configuration

Package Overview
Dependencies
Maintainers
11
Versions
62
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@isoftdata/svelte-user-configuration - npm Package Compare versions

Comparing version
1.3.3
to
2.0.0
+32
-20
dist/DeactivateUserModal.svelte

@@ -1,19 +0,31 @@

<script>import { getContext, tick } from "svelte";
import { klona } from "klona";
import { translate as defaultTranslate } from "@isoftdata/utility-string";
import Modal from "@isoftdata/svelte-modal";
import TextArea from "@isoftdata/svelte-textarea";
let show = false;
let userAccount;
let lockNotes;
let textarea;
export let deactivateUser = void 0;
export async function open(userAccountCtx) {
userAccount = klona(userAccountCtx);
lockNotes = userAccount.lockNotes;
show = true;
await tick();
textarea?.select();
}
const { t: translate } = getContext("i18next") || { t: defaultTranslate };
<script lang="ts">
import type { UserAccount } from './'
import type { i18n } from 'i18next'
import { getContext, tick } from 'svelte'
import { klona } from 'klona'
import { translate as defaultTranslate } from '@isoftdata/utility-string'
import Modal from '@isoftdata/svelte-modal'
import TextArea from '@isoftdata/svelte-textarea'
let show: boolean = $state(false)
let userAccount: UserAccount | undefined = $state()
let lockNotes: UserAccount['lockNotes'] = $state(null)
let textarea: HTMLTextAreaElement | undefined = $state()
interface Props {
deactivateUser?: ((user: { id: UserAccount['id']; lockNotes: UserAccount['lockNotes'] }) => void | Promise<void>) | undefined;
}
let { deactivateUser = undefined }: Props = $props();
export async function open(userAccountCtx: UserAccount) {
userAccount = klona(userAccountCtx)
lockNotes = userAccount.lockNotes
show = true
await tick()
textarea?.select()
}
const { t: translate } = getContext<i18n>('i18next') || { t: defaultTranslate }
</script>

@@ -28,3 +40,3 @@

confirmButtonFormId="deactivateUserModalForm"
on:close={() => (show = false)}
close={() => (show = false)}
bind:show

@@ -34,3 +46,3 @@ >

id="deactivateUserModalForm"
on:submit={async e => {
onsubmit={async e => {
e.preventDefault()

@@ -37,0 +49,0 @@ userAccount ? await deactivateUser?.({ id: userAccount.id, lockNotes }) : undefined

@@ -1,24 +0,12 @@

import { SvelteComponent } from "svelte";
import type { UserAccount } from './';
declare const __propDef: {
props: {
deactivateUser?: ((user: {
id: UserAccount["id"];
lockNotes: UserAccount["lockNotes"];
}) => void | Promise<void>) | undefined;
open?: (userAccountCtx: UserAccount) => Promise<void>;
};
events: {
[evt: string]: CustomEvent<any>;
};
slots: {};
exports?: {} | undefined;
bindings?: string | undefined;
};
export type DeactivateUserModalProps = typeof __propDef.props;
export type DeactivateUserModalEvents = typeof __propDef.events;
export type DeactivateUserModalSlots = typeof __propDef.slots;
export default class DeactivateUserModal extends SvelteComponent<DeactivateUserModalProps, DeactivateUserModalEvents, DeactivateUserModalSlots> {
get open(): (userAccountCtx: UserAccount) => Promise<void>;
interface Props {
deactivateUser?: ((user: {
id: UserAccount['id'];
lockNotes: UserAccount['lockNotes'];
}) => void | Promise<void>) | undefined;
}
export {};
declare const DeactivateUserModal: import("svelte").Component<Props, {
open: (userAccountCtx: UserAccount) => Promise<void>;
}, "">;
type DeactivateUserModal = ReturnType<typeof DeactivateUserModal>;
export default DeactivateUserModal;

@@ -1,16 +0,26 @@

<script>import { getContext } from "svelte";
import Modal from "@isoftdata/svelte-modal";
import Input from "@isoftdata/svelte-input";
import { translate as defaultTranslate } from "@isoftdata/utility-string";
const { t: translate } = getContext("i18next") || { t: defaultTranslate };
export let sendPasswordRecoveryToken = void 0;
export let doSendPasswordRecoveryToken;
let resetDate = void 0;
let email = null;
let show = false;
export function open(passwordRecoveryEmail, lastResetDate) {
email = passwordRecoveryEmail;
resetDate = lastResetDate;
show = true;
}
<script lang="ts">
import type { i18n } from 'i18next'
import { getContext } from 'svelte'
import Modal from '@isoftdata/svelte-modal'
import Input from '@isoftdata/svelte-input'
import { translate as defaultTranslate } from '@isoftdata/utility-string'
const { t: translate } = getContext<i18n>('i18next') || { t: defaultTranslate }
interface Props {
sendPasswordRecoveryToken?: ((email: string | null) => void | Promise<void>) | undefined
doSendPasswordRecoveryToken: boolean
}
let { sendPasswordRecoveryToken = undefined, doSendPasswordRecoveryToken = $bindable() }: Props = $props()
let resetDate: Date | null | undefined = $state(undefined)
let email: string | null = $state(null)
let show: boolean = $state(false)
export function open(passwordRecoveryEmail: typeof email, lastResetDate: Date | null | undefined) {
email = passwordRecoveryEmail
resetDate = lastResetDate
show = true
}
</script>

@@ -21,6 +31,9 @@

title={translate('configuration.user.accountInfo.passwordRecovery.header', 'Password Recovery')}
confirmButtonText={translate('configuration.user.accountInfo.passwordManagementModal.requestResetToken', 'Request Reset Token')}
confirmButtonText={translate(
'configuration.user.accountInfo.passwordManagementModal.requestResetToken',
'Request Reset Token',
)}
confirmButtonIcon="check"
confirmButtonDisabled={!email}
on:close={() => (show = false)}
close={() => (show = false)}
confirmButtonType="submit"

@@ -31,3 +44,3 @@ confirmButtonFormId="passwordRecoveryForm"

id="passwordRecoveryForm"
on:submit={async event => {
onsubmit={async event => {
event.preventDefault()

@@ -43,5 +56,8 @@ try {

>
<div class="form-row">
<div class="row">
<Input
label={translate('configuration.user.accountInfo.passwordManagementModal.lastPasswordSetDate', 'Last Password Set Date')}
label={translate(
'configuration.user.accountInfo.passwordManagementModal.lastPasswordSetDate',
'Last Password Set Date',
)}
value={resetDate?.toLocaleString() ?? ''}

@@ -52,3 +68,6 @@ labelParentClass="col-12 col-md-6 form-group mb-0"

<Input
label={translate('configuration.user.accountInfo.passwordRecoveryModal.passwordRecoveryEmail', 'Password Recovery Email')}
label={translate(
'configuration.user.accountInfo.passwordRecoveryModal.passwordRecoveryEmail',
'Password Recovery Email',
)}
value={email ?? ''}

@@ -60,3 +79,6 @@ labelParentClass="col-12 col-md-6 form-group mb-0"

<div class="alert alert-danger mt-3 mb-0">
{translate('configuration.user.accountInfo.passwordRecovery.noRecoveryEmail', 'No recovery email has been set for this user.')}
{translate(
'configuration.user.accountInfo.passwordRecovery.noRecoveryEmail',
'No recovery email has been set for this user.',
)}
</div>

@@ -63,0 +85,0 @@ {/if}

@@ -1,21 +0,9 @@

import { SvelteComponent } from "svelte";
declare const __propDef: {
props: {
sendPasswordRecoveryToken?: ((email: string | null) => void | Promise<void>) | undefined;
doSendPasswordRecoveryToken: boolean;
open?: (passwordRecoveryEmail: string | null, lastResetDate: Date | null | undefined) => void;
};
events: {
[evt: string]: CustomEvent<any>;
};
slots: {};
exports?: {} | undefined;
bindings?: string | undefined;
};
export type PasswordRecoveryModalProps = typeof __propDef.props;
export type PasswordRecoveryModalEvents = typeof __propDef.events;
export type PasswordRecoveryModalSlots = typeof __propDef.slots;
export default class PasswordRecoveryModal extends SvelteComponent<PasswordRecoveryModalProps, PasswordRecoveryModalEvents, PasswordRecoveryModalSlots> {
get open(): (passwordRecoveryEmail: string | null, lastResetDate: Date | null | undefined) => void;
interface Props {
sendPasswordRecoveryToken?: ((email: string | null) => void | Promise<void>) | undefined;
doSendPasswordRecoveryToken: boolean;
}
export {};
declare const PasswordRecoveryModal: import("svelte").Component<Props, {
open: (passwordRecoveryEmail: string | null, lastResetDate: Date | null | undefined) => void;
}, "doSendPasswordRecoveryToken">;
type PasswordRecoveryModal = ReturnType<typeof PasswordRecoveryModal>;
export default PasswordRecoveryModal;

@@ -1,37 +0,57 @@

<script>import { klona } from "klona";
import { tick, getContext } from "svelte";
import Input from "@isoftdata/svelte-input";
import Modal from "@isoftdata/svelte-modal";
import PasswordFields from "@isoftdata/svelte-password-fields";
import { translate as defaultTranslate } from "@isoftdata/utility-string";
let show = false;
let currentPassword = "";
let newPassword = "";
let confirmPassword = "";
let passwordMismatch = false;
let lastResetDate = void 0;
let currentPasswordInput = void 0;
let newPasswordInput = void 0;
let passwordRecoveryEmail = void 0;
let passwordIsValid = false;
export let validationRules = void 0;
export let changePasswordMode = false;
export let confirmPasswordSet;
export async function open(userAccount) {
currentPassword = "";
newPassword = "";
confirmPassword = "";
lastResetDate = klona(userAccount?.lastPasswordResetDate);
passwordRecoveryEmail = userAccount?.recoveryEmail;
show = true;
await tick();
if (changePasswordMode) {
currentPasswordInput?.focus();
} else {
newPasswordInput?.focus();
}
}
const { t: translate } = getContext("i18next") || { t: defaultTranslate };
$: passwordMismatch = !(newPassword && confirmPassword && newPassword === confirmPassword);
$: disablePasswordChange = changePasswordMode && !currentPassword || passwordMismatch || !newPassword || !confirmPassword || !passwordIsValid;
<script lang="ts">
import type { i18n } from 'i18next'
import type { UserAccount, PasswordValidationRules } from './'
import { klona } from 'klona'
import { tick, getContext } from 'svelte'
import Input from '@isoftdata/svelte-input'
import Modal from '@isoftdata/svelte-modal'
import PasswordFields from '@isoftdata/svelte-password-fields'
import { translate as defaultTranslate } from '@isoftdata/utility-string'
let show: boolean = $state(false)
let currentPassword: string = $state('')
let newPassword: string = $state('')
let confirmPassword: string = $state('')
let lastResetDate: Date | null | undefined = $state(undefined)
let currentPasswordInput: HTMLInputElement | undefined = $state(undefined)
let newPasswordInput: HTMLInputElement | undefined = $state(undefined)
let passwordRecoveryEmail: string | null | undefined = $state(undefined)
let passwordIsValid: boolean = $state(false)
interface Props {
validationRules?: PasswordValidationRules | undefined
changePasswordMode?: boolean
confirmPasswordSet: (ctx: { currentPassword: string; newPassword: string }) => void | Promise<void>
}
let { validationRules = undefined, changePasswordMode = false, confirmPasswordSet }: Props = $props()
export async function open(userAccount?: UserAccount) {
currentPassword = ''
newPassword = ''
confirmPassword = ''
lastResetDate = klona(userAccount?.lastPasswordResetDate) // Don't mutate the given Date obj
passwordRecoveryEmail = userAccount?.recoveryEmail
show = true
await tick()
if (changePasswordMode) {
currentPasswordInput?.focus()
} else {
newPasswordInput?.focus()
}
}
const { t: translate } = getContext<i18n>('i18next') || { t: defaultTranslate }
// The passwordMismatch prop from the PasswordFields component only updates on:change,
// but we want the component consumer to be able to update their save button disabled state in real time
let passwordMismatch: boolean = $derived(!(newPassword && confirmPassword && newPassword === confirmPassword))
let disablePasswordChange: boolean = $derived(
(changePasswordMode && !currentPassword) ||
passwordMismatch ||
!newPassword ||
!confirmPassword ||
!passwordIsValid,
)
</script>

@@ -41,7 +61,11 @@

bind:show
title={changePasswordMode ? translate('configuration.user.changePassword', 'Change Password') : translate('configuration.user.setPassword', 'Set Password')}
confirmButtonText={changePasswordMode ? translate('configuration.user.changePassword', 'Change Password') : translate('configuration.user.setPassword', 'Set Password')}
title={changePasswordMode
? translate('configuration.user.changePassword', 'Change Password')
: translate('configuration.user.setPassword', 'Set Password')}
confirmButtonText={changePasswordMode
? translate('configuration.user.changePassword', 'Change Password')
: translate('configuration.user.setPassword', 'Set Password')}
confirmButtonIcon="check"
confirmButtonDisabled={disablePasswordChange}
on:close={() => (show = false)}
close={() => (show = false)}
confirmButtonType="submit"

@@ -52,3 +76,3 @@ confirmButtonFormId="setPasswordForm"

id="setPasswordForm"
on:submit={async e => {
onsubmit={async e => {
e.preventDefault()

@@ -62,3 +86,6 @@ if (!disablePasswordChange) {

<Input
label={translate('configuration.user.accountInfo.passwordManagementModal.lastPasswordSetDate', 'Last Password Set Date')}
label={translate(
'configuration.user.accountInfo.passwordManagementModal.lastPasswordSetDate',
'Last Password Set Date',
)}
tabindex={-1}

@@ -89,7 +116,13 @@ value={lastResetDate ? lastResetDate.toLocaleString() : ''}

passwordLabel={translate('configuration.user.accountInfo.passwordManagementModal.newPassword', 'New Password')}
confirmPasswordLabel={translate('configuration.user.accountInfo.passwordManagementModal.confirmNewPassword', 'Confirm New Password')}
confirmPasswordLabel={translate(
'configuration.user.accountInfo.passwordManagementModal.confirmNewPassword',
'Confirm New Password',
)}
/>
{#if !passwordRecoveryEmail}
<div class="alert alert-danger mt-3 mb-0">
{translate('configuration.user.accountInfo.passwordRecovery.noRecoveryEmail', 'No recovery email has been set for this user.')}
{translate(
'configuration.user.accountInfo.passwordRecovery.noRecoveryEmail',
'No recovery email has been set for this user.',
)}
</div>

@@ -96,0 +129,0 @@ {/if}

@@ -1,26 +0,14 @@

import { SvelteComponent } from "svelte";
import type { UserAccount, PasswordValidationRules } from './';
declare const __propDef: {
props: {
validationRules?: PasswordValidationRules | undefined;
changePasswordMode?: boolean;
confirmPasswordSet: (ctx: {
currentPassword: string;
newPassword: string;
}) => void | Promise<void>;
open?: (userAccount?: UserAccount) => Promise<void>;
};
events: {
[evt: string]: CustomEvent<any>;
};
slots: {};
exports?: {} | undefined;
bindings?: string | undefined;
};
export type PasswordSetModalProps = typeof __propDef.props;
export type PasswordSetModalEvents = typeof __propDef.events;
export type PasswordSetModalSlots = typeof __propDef.slots;
export default class PasswordSetModal extends SvelteComponent<PasswordSetModalProps, PasswordSetModalEvents, PasswordSetModalSlots> {
get open(): (userAccount?: UserAccount) => Promise<void>;
interface Props {
validationRules?: PasswordValidationRules | undefined;
changePasswordMode?: boolean;
confirmPasswordSet: (ctx: {
currentPassword: string;
newPassword: string;
}) => void | Promise<void>;
}
export {};
declare const PasswordSetModal: import("svelte").Component<Props, {
open: (userAccount?: UserAccount) => Promise<void>;
}, "">;
type PasswordSetModal = ReturnType<typeof PasswordSetModal>;
export default PasswordSetModal;

@@ -1,86 +0,169 @@

<script>import { getContext } from "svelte";
import camelCase from "just-camel-case";
import Icon from "@isoftdata/svelte-icon";
import Button from "@isoftdata/svelte-button";
import Select from "@isoftdata/svelte-select";
import { getEventValue } from "@isoftdata/browser-event";
import { Table, Td } from "@isoftdata/svelte-table";
import { translate as defaultTranslate } from "@isoftdata/utility-string";
const { t: translate } = getContext("i18next") || { t: defaultTranslate };
export let permissions;
export let siteLabel = "Site";
export let permissionValueChange = void 0;
export let icon = "user-lock";
export let cardHeaderTitle = translate("common:permissions", "Permissions");
export let permissionValueMap = /* @__PURE__ */ new Map();
export let groupPermissionValueMap = void 0;
let computedPermissions = [];
let selectedPermissionIds = /* @__PURE__ */ new Set();
let selectedPermissionValue = null;
const permissionColumns = getColumns(groupPermissionValueMap);
const permissionValueList = {
NONE: { label: translate("common:permissionLevel.none", "None"), value: "NONE", color: "danger" },
SITE: { label: translate(`common:permissionLevel.${siteLabel.toLowerCase()}`, siteLabel), value: "SITE", color: "primary" },
GLOBAL: { label: translate("common:permissionLevel.global", "Global"), value: "GLOBAL", color: "success" }
};
function getColumns(groupPermissionValueMap2) {
let columns = [
{ property: "value", name: groupPermissionValueMap2 ? translate("common:user", "User") : translate("common:permission", "Permission"), width: "1rem" },
{ property: "category", name: translate("common:category", "Category") },
{ property: "displayName", name: translate("common:name", "Name") }
];
if (groupPermissionValueMap2) {
columns.splice(
1,
0,
{ property: "groupValue", name: translate("common:group", "Group"), align: "center", width: "1rem", minWidth: "25%" },
{ property: "computedValue", name: translate("common:access", "Access"), align: "center", width: "1rem", minWidth: "25%" }
);
}
return columns;
}
function selectPermissions(permissionId) {
selectedPermissionIds.has(permissionId) ? selectedPermissionIds.delete(permissionId) : selectedPermissionIds.add(permissionId);
selectedPermissionIds = selectedPermissionIds;
}
function selectAndDeselectAllPermissions() {
if (selectedPermissionIds.size === computedPermissions.length) {
selectedPermissionIds.clear();
selectedPermissionValue = null;
} else {
selectedPermissionIds = new Set(permissions.map((permission) => permission.id));
}
selectedPermissionIds = selectedPermissionIds;
}
const getButtonColor = (optionValue, permissionValue) => optionValue === permissionValue ? permissionValueList[optionValue].color : "outline-secondary";
const isValidPermissionValue = (value) => Object.keys(permissionValueList).includes(value);
async function updatePermissionValues(event, permissionIds) {
const newValue = getEventValue(event);
if (isValidPermissionValue(newValue)) {
const permissionIdsArray = Array.from(permissionIds);
for (const id of permissionIdsArray) {
permissionValueMap.set(id, newValue);
}
permissionValueMap = permissionValueMap;
await permissionValueChange?.({
value: newValue,
permissionIds: permissionIdsArray
});
}
}
function getComputedPermissions(permissions2, permissionValueMap2, groupPermissionValueMap2) {
return permissions2.map((permission) => {
const value = permissionValueMap2.get(permission.id) ?? "NONE";
const groupValue = groupPermissionValueMap2?.get(permission.id);
return {
...permission,
displayName: translate(`permissions:${camelCase(permission.codeName)}.displayName`, permission.displayName),
category: translate(`permissions:categories.${camelCase(permission.category)}`, permission.category),
value,
groupValue,
computedValue: value === "NONE" && groupValue || value === "SITE" && groupValue === "GLOBAL" ? groupValue : value
};
});
}
$: computedPermissions = getComputedPermissions(permissions, permissionValueMap, groupPermissionValueMap);
<script lang="ts">
import type { i18n } from 'i18next'
import type { Merge } from 'type-fest'
import type { IconName, SiteLabel, HTMLDivAttributes } from './'
import type { Snippet } from 'svelte'
import { getContext } from 'svelte'
import camelCase from 'just-camel-case'
import Icon from '@isoftdata/svelte-icon'
import Button from '@isoftdata/svelte-button'
import Select from '@isoftdata/svelte-select'
import { getEventValue } from '@isoftdata/browser-event'
import { Table, Td, type Column } from '@isoftdata/svelte-table'
import { translate as defaultTranslate } from '@isoftdata/utility-string'
import { SvelteSet, SvelteMap } from 'svelte/reactivity'
const { t: translate } = getContext<i18n>('i18next') || { t: defaultTranslate }
type Permission = {
id: number
displayName: string
category: string
codeName: string
}
type ComputedPermission = Merge<
Permission,
{ value: PermissionValue; groupValue?: PermissionValue | undefined; computedValue?: PermissionValue }
>
type ComputedPermissionColumns = Array<Column<ComputedPermission>>
type PermissionValue = keyof typeof permissionValueList
type PermissionValueMap = Map<number, PermissionValue>
interface Props extends HTMLDivAttributes {
permissions: Array<Permission>
siteLabel?: SiteLabel
permissionValueChange?:
| ((change: { value: PermissionValue; permissionIds: Array<number> }) => void | Promise<void>)
| undefined
icon?: IconName
cardHeaderTitle?: string
permissionValueMap: PermissionValueMap
groupPermissionValueMap?: PermissionValueMap | undefined
children?: Snippet
}
let {
permissions,
siteLabel = 'Site',
permissionValueChange = undefined,
icon = 'user-lock',
cardHeaderTitle = translate('common:permissions', 'Permissions'),
permissionValueMap = $bindable(new SvelteMap()),
groupPermissionValueMap = undefined,
children,
...rest
}: Props = $props()
let selectedPermissionIds: SvelteSet<number> = $state(new SvelteSet())
let selectedPermissionValue: string | null = $state(null)
const permissionColumns: ComputedPermissionColumns = getColumns(groupPermissionValueMap)
const permissionValueList = {
NONE: { label: translate('common:permissionLevel.none', 'None'), value: 'NONE', color: 'danger' },
SITE: {
label: translate(`common:permissionLevel.${siteLabel.toLowerCase()}`, siteLabel),
value: 'SITE',
color: 'primary',
},
GLOBAL: { label: translate('common:permissionLevel.global', 'Global'), value: 'GLOBAL', color: 'success' },
}
function getColumns(groupPermissionValueMap: PermissionValueMap | undefined): ComputedPermissionColumns {
let columns: ComputedPermissionColumns = [
{
property: 'value',
name: groupPermissionValueMap ? translate('common:user', 'User') : translate('common:permission', 'Permission'),
width: '1rem',
},
{ property: 'category', name: translate('common:category', 'Category') },
{ property: 'displayName', name: translate('common:name', 'Name') },
]
if (groupPermissionValueMap) {
columns.splice(
1,
0,
{
property: 'groupValue',
name: translate('common:group', 'Group'),
align: 'center',
width: '1rem',
minWidth: '25%',
},
{
property: 'computedValue',
name: translate('common:access', 'Access'),
align: 'center',
width: '1rem',
minWidth: '25%',
},
)
}
return columns
}
function selectPermissions(permissionId: number) {
selectedPermissionIds.has(permissionId)
? selectedPermissionIds.delete(permissionId)
: selectedPermissionIds.add(permissionId)
}
function selectAndDeselectAllPermissions() {
if (selectedPermissionIds.size === computedPermissions.length) {
selectedPermissionIds.clear()
selectedPermissionValue = null
} else {
selectedPermissionIds = new SvelteSet(permissions.map(permission => permission.id))
}
}
const getButtonColor = (optionValue: string, permissionValue: PermissionValue) =>
optionValue === permissionValue ? permissionValueList[optionValue].color : 'outline-secondary'
const isValidPermissionValue = (value: string): value is PermissionValue =>
Object.keys(permissionValueList).includes(value)
async function updatePermissionValues(event: Event, permissionIds: SvelteSet<number>) {
const newValue = getEventValue(event)
if (isValidPermissionValue(newValue)) {
const permissionIdsArray = Array.from(permissionIds)
for (const id of permissionIdsArray) {
permissionValueMap.set(id, newValue)
}
permissionValueMap = permissionValueMap
await permissionValueChange?.({
value: newValue,
permissionIds: permissionIdsArray,
})
}
}
function getComputedPermissions(
permissions: Array<Permission>,
permissionValueMap: PermissionValueMap,
groupPermissionValueMap: PermissionValueMap | undefined,
): Array<ComputedPermission> {
return permissions.map(permission => {
const value = permissionValueMap.get(permission.id) ?? 'NONE'
const groupValue = groupPermissionValueMap?.get(permission.id)
return {
...permission,
displayName: translate(`permissions:${camelCase(permission.codeName)}.displayName`, permission.displayName),
category: translate(`permissions:categories.${camelCase(permission.category)}`, permission.category),
value,
groupValue,
computedValue:
(value === 'NONE' && groupValue) || (value === 'SITE' && groupValue === 'GLOBAL') ? groupValue : value,
}
})
}
let computedPermissions = $derived.by(() =>
getComputedPermissions(permissions, permissionValueMap, groupPermissionValueMap),
)
$inspect(computedPermissions)
</script>

@@ -90,3 +173,3 @@

class="card"
{...$$restProps}
{...rest}
>

@@ -97,3 +180,3 @@ <div class="card-header">

{icon}
class="mr-1"
class="mr-1 me-1"
/>

@@ -113,47 +196,53 @@ {cardHeaderTitle}

filterEnabled
let:row={permission}
>
<tr
on:click={() => selectPermissions(permission.id)}
class:table-primary={selectedPermissionIds.has(permission.id)}
class="cursor-pointer"
>
<Td property="value">
<div
class="btn-group btn-group-toggle"
data-toggle="buttons"
>
{#each Object.values(permissionValueList) as permissionValue}
<label class="btn btn-sm btn-{getButtonColor(permissionValue.value, permission.value)} cursor-pointer">
<input
type="radio"
autocomplete="off"
name={permission.value}
value={permissionValue.value}
on:change={e => updatePermissionValues(e, new Set([permission.id]))}
/>
{permissionValue.label}
</label>
{/each}
</div>
</Td>
{#if groupPermissionValueMap}
<Td
property="groupValue"
class="px-4"
>
<span class="badge badge-pill badge-{permissionValueList[permission.groupValue ?? 'NONE'].color}">{permissionValueList[permission.groupValue ?? 'NONE'].label}</span>
{#snippet children({ row: permission })}
<tr
onclick={() => selectPermissions(permission.id)}
class:table-primary={selectedPermissionIds.has(permission.id)}
class="cursor-pointer"
>
<Td property="value">
<div
class="btn-group btn-group-toggle"
data-toggle="buttons"
>
{#each Object.values(permissionValueList) as permissionValue}
<label class="btn btn-sm btn-{getButtonColor(permissionValue.value, permission.value)} cursor-pointer">
<input
class="btn-check"
type="radio"
autocomplete="off"
name={permission.value}
value={permissionValue.value}
onchange={e => updatePermissionValues(e, new SvelteSet([permission.id]))}
/>
{permissionValue.label}
</label>
{/each}
</div>
</Td>
<Td
property="computedValue"
class="px-4"
>
<span class="badge badge-pill badge-{permissionValueList[permission.computedValue ?? 'NONE'].color}">{permissionValueList[permission.computedValue ?? 'NONE'].label}</span>
</Td>
{/if}
<Td property="category">{permission.category}</Td>
<Td property="displayName">{permission.displayName}</Td>
</tr>
{#if groupPermissionValueMap}
<Td
property="groupValue"
class="px-4"
>
<span class="badge badge-pill bg-{permissionValueList[permission.groupValue ?? 'NONE'].color}"
>{permissionValueList[permission.groupValue ?? 'NONE'].label}</span
>
</Td>
<Td
property="computedValue"
class="px-4"
>
<span class="badge badge-pill bg-{permissionValueList[permission.computedValue ?? 'NONE'].color}"
>{permissionValueList[permission.computedValue ?? 'NONE'].label}</span
>
</Td>
{/if}
<Td property="category">{permission.category}</Td>
<Td property="displayName">{permission.displayName}</Td>
</tr>
{/snippet}
</Table>
<slot></slot>
{@render children?.()}
</div>

@@ -168,8 +257,8 @@ <div class="card-footer">

emptyText={translate('common:selectValue', 'Select a Value')}
labelParentClass="form-inline mr-2"
labelClass="mr-2 p-0"
labelParentClass="form-inline mr-2 me-2"
labelClass="mr-2 me-2 p-0"
disabled={selectedPermissionIds.size === 0}
on:change={e => {
onchange={e => {
updatePermissionValues(e, selectedPermissionIds)
selectedPermissionIds = new Set() //clear the Set and trigger reactivity
selectedPermissionIds.clear()
selectedPermissionValue = null

@@ -187,6 +276,10 @@ }}

iconClass="check-double"
on:click={selectAndDeselectAllPermissions}
onclick={selectAndDeselectAllPermissions}
>
<span class:d-none={selectedPermissionIds.size !== computedPermissions.length}>{translate('common:deselectAll', 'Deselect All')}</span>
<span class:d-none={selectedPermissionIds.size === computedPermissions.length}>{translate('common:selectAll', 'Select All')}</span>
<span class:d-none={selectedPermissionIds.size !== computedPermissions.length}
>{translate('common:deselectAll', 'Deselect All')}</span
>
<span class:d-none={selectedPermissionIds.size === computedPermissions.length}
>{translate('common:selectAll', 'Select All')}</span
>
</Button>

@@ -193,0 +286,0 @@ </div>

@@ -1,35 +0,22 @@

import { SvelteComponent } from "svelte";
import type { IconName, SiteLabel, HTMLDivAttributes } from './';
declare const __propDef: {
props: HTMLDivAttributes & {
permissions: Array<{
id: number;
displayName: string;
category: string;
codeName: string;
}>;
siteLabel?: SiteLabel;
permissionValueChange?: ((change: {
value: "NONE" | "SITE" | "GLOBAL";
permissionIds: Array<number>;
}) => void | Promise<void>) | undefined;
icon?: IconName;
cardHeaderTitle?: string;
permissionValueMap: Map<number, "NONE" | "SITE" | "GLOBAL">;
groupPermissionValueMap?: Map<number, "NONE" | "SITE" | "GLOBAL"> | undefined;
};
events: {
[evt: string]: CustomEvent<any>;
};
slots: {
default: {};
};
exports?: {} | undefined;
bindings?: string | undefined;
};
export type PermissionListProps = typeof __propDef.props;
export type PermissionListEvents = typeof __propDef.events;
export type PermissionListSlots = typeof __propDef.slots;
export default class PermissionList extends SvelteComponent<PermissionListProps, PermissionListEvents, PermissionListSlots> {
}
export {};
import type { Snippet } from 'svelte';
declare const PermissionList: import("svelte").Component<HTMLDivAttributes & {
permissions: Array<{
id: number;
displayName: string;
category: string;
codeName: string;
}>;
siteLabel?: SiteLabel;
permissionValueChange?: ((change: {
value: "NONE" | "SITE" | "GLOBAL";
permissionIds: Array<number>;
}) => void | Promise<void>) | undefined;
icon?: IconName;
cardHeaderTitle?: string;
permissionValueMap: Map<number, "NONE" | "SITE" | "GLOBAL">;
groupPermissionValueMap?: Map<number, "NONE" | "SITE" | "GLOBAL"> | undefined;
children?: Snippet;
}, {}, "permissionValueMap">;
type PermissionList = ReturnType<typeof PermissionList>;
export default PermissionList;

@@ -1,79 +0,154 @@

<script>import { getContext } from "svelte";
import Icon from "@isoftdata/svelte-icon";
import Input from "@isoftdata/svelte-input";
import Button from "@isoftdata/svelte-button";
import TextArea from "@isoftdata/svelte-textarea";
import PasswordSetModal from "./PasswordSetModal.svelte";
import DeactivateUserModal from "./DeactivateUserModal.svelte";
import PasswordRecoveryModal from "./PasswordRecoveryModal.svelte";
import { translate as defaultTranslate } from "@isoftdata/utility-string";
const { t: translate } = getContext("i18next") || { t: defaultTranslate };
export let userAccount;
export let icon = "user";
export let canToggleActive = true;
export let canEditAccountInfo = true;
export let deactivateUser = void 0;
export let hasPermissionToChangePassword = false;
export let confirmPasswordSet = void 0;
export let accountInfoChanged = void 0;
export let error = void 0;
export let success = void 0;
export let sendPasswordRecoveryToken = void 0;
export let doSendPasswordRecoveryToken = false;
export let generateNewActivationPIN = () => Promise.resolve();
export let usernameInput = void 0;
export let cardHeight = 0;
export let myAccountMode = false;
export let passwordValidationRules = void 0;
export let cardTitle = translate("configuration.user.accountInfoHeader", "Account");
export let recoveryEmailIsValid = true;
export let workEmailIsValid = true;
let isLoading = false;
let passwordSetModal;
let deactivateUserModal;
let passwordRecoveryModal;
let activationPINInput;
async function getNewActivationPIN(sendEmail = false) {
let confirmationMessage = sendEmail ? translate("configuration.user.permissions.sendNewActivationPINMessage", "Are you sure you want to send a new activation PIN? The user will receive an email with the new activation PIN.") : translate("configuration.user.permissions.generateNewActivationPINMessage", "Are you sure you want to generate a new activation PIN?");
if (confirm(confirmationMessage)) {
try {
isLoading = true;
await generateNewActivationPIN(userAccount.name, !!userAccount.workEmail);
let successMessage = sendEmail ? translate("configuration.user.permissions.activationPINSent", "Email with new activation PIN has been sent successfully.") : translate("configuration.user.permissions.activationPINGenerated", "Activation PIN generated successfully.");
let successHeading = sendEmail ? translate("configuration.messageHeading.activationPINSent", "New Activation PIN Sent!") : translate("configuration.messageHeading.activationPINGenerated", "New Activation PIN Generated!");
await success?.({ heading: successHeading, message: successMessage });
isLoading = false;
await accountInfoChanged?.();
} catch (err) {
console.log(err);
if (err instanceof Error) {
await error?.({ heading: translate("configuration.messageHeading.failedToGenerateNewPIN", "Failed To Generate New PIN"), message: err.message });
}
}
}
}
async function copyTextToClipboard() {
if (activationPINInput) {
navigator.clipboard.writeText(activationPINInput.value);
await success?.({
heading: translate("configuration.messageHeading.activationPINCopied", "Activation PIN Copied!"),
message: translate("configuration.user.permissions.activationPINCopied", "Activation PIN copied to clipboard successfully.")
});
}
}
async function reactivateUserAccount() {
if (confirm(translate("configuration.user.permissions.reactivateUserConfirmation", "Are you sure you want to reactivate this user?"))) {
userAccount.status = "ACTIVE";
userAccount.lockNotes = null;
await accountInfoChanged?.();
}
}
const emailAddressRegex = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
const emailIsValid = (emailAddress) => emailAddressRegex.test(emailAddress);
$: workEmail = userAccount.workEmail;
$: status = userAccount.status;
$: activationPIN = userAccount.userActivationData?.activationPIN;
$: isCreatingNewUser = userAccount.id === null;
$: recoveryEmailIsValid = myAccountMode && userAccount.recoveryEmail ? emailIsValid(userAccount.recoveryEmail) : true;
$: workEmailIsValid = !myAccountMode && userAccount.workEmail ? emailIsValid(userAccount.workEmail) : true;
<script lang="ts">
import type { i18n } from 'i18next'
import type { HTMLDivAttributes } from './'
import type { ComponentProps, Snippet } from 'svelte'
import type { UserAccount, ConfirmPasswordSetFn, DeactivateUserFn, IconName, PasswordValidationRules } from './'
import { getContext } from 'svelte'
import Icon from '@isoftdata/svelte-icon'
import Input from '@isoftdata/svelte-input'
import Button from '@isoftdata/svelte-button'
import TextArea from '@isoftdata/svelte-textarea'
import PasswordSetModal from './PasswordSetModal.svelte'
import DeactivateUserModal from './DeactivateUserModal.svelte'
import PasswordRecoveryModal from './PasswordRecoveryModal.svelte'
import { translate as defaultTranslate } from '@isoftdata/utility-string'
const { t: translate } = getContext<i18n>('i18next') || { t: defaultTranslate }
interface Props extends HTMLDivAttributes {
userAccount: UserAccount
canEditAccountInfo?: boolean
canToggleActive?: boolean
hasPermissionToChangePassword?: boolean
generateNewActivationPIN?: (userName: string, hasWorkEmail: boolean) => Promise<void>
confirmPasswordSet?: ConfirmPasswordSetFn
deactivateUser?: DeactivateUserFn
success?: ((info: { heading: string; message: string }) => void | Promise<void>) | undefined
error?: ((info: { heading: string; message: string }) => void | Promise<void>) | undefined
accountInfoChanged?: (() => void | Promise<void>) | undefined
sendPasswordRecoveryToken?: ComponentProps<typeof PasswordRecoveryModal>['sendPasswordRecoveryToken']
doSendPasswordRecoveryToken?: boolean
icon?: IconName
usernameInput?: HTMLInputElement | undefined
cardHeight?: number
myAccountMode?: boolean
passwordValidationRules?: PasswordValidationRules | undefined
cardTitle?: string
recoveryEmailIsValid?: boolean
workEmailIsValid?: boolean
formFields?: Snippet
children?: Snippet
}
let {
userAccount = $bindable(),
canEditAccountInfo = true,
canToggleActive = true,
hasPermissionToChangePassword = false,
generateNewActivationPIN = () => Promise.resolve(),
confirmPasswordSet = undefined,
deactivateUser = undefined,
success = undefined,
error = undefined,
accountInfoChanged = undefined,
sendPasswordRecoveryToken = undefined,
doSendPasswordRecoveryToken = $bindable(false),
icon = 'user',
usernameInput = $bindable(undefined),
cardHeight = $bindable(),
myAccountMode = false,
passwordValidationRules = undefined,
cardTitle = translate('configuration.user.accountInfoHeader', 'Account'),
recoveryEmailIsValid = $bindable(true),
workEmailIsValid = $bindable(true),
formFields,
children,
...rest
}: Props = $props()
let isLoading = $state(false)
let passwordSetModal: PasswordSetModal | undefined = $state()
let passwordRecoveryModal: PasswordRecoveryModal | undefined = $state()
let deactivateUserModal: DeactivateUserModal | undefined = $state()
let activationPINInput: HTMLInputElement | undefined = $state()
async function getNewActivationPIN(sendEmail: boolean = false) {
let confirmationMessage: string = sendEmail
? translate(
'configuration.user.permissions.sendNewActivationPINMessage',
'Are you sure you want to send a new activation PIN? The user will receive an email with the new activation PIN.',
)
: translate(
'configuration.user.permissions.generateNewActivationPINMessage',
'Are you sure you want to generate a new activation PIN?',
)
if (confirm(confirmationMessage)) {
try {
isLoading = true
await generateNewActivationPIN(userAccount.name, !!userAccount.workEmail)
let successMessage: string = sendEmail
? translate(
'configuration.user.permissions.activationPINSent',
'Email with new activation PIN has been sent successfully.',
)
: translate('configuration.user.permissions.activationPINGenerated', 'Activation PIN generated successfully.')
let successHeading: string = sendEmail
? translate('configuration.messageHeading.activationPINSent', 'New Activation PIN Sent!')
: translate('configuration.messageHeading.activationPINGenerated', 'New Activation PIN Generated!')
await success?.({ heading: successHeading, message: successMessage })
isLoading = false
await accountInfoChanged?.()
} catch (err) {
console.log(err)
if (err instanceof Error) {
await error?.({
heading: translate('configuration.messageHeading.failedToGenerateNewPIN', 'Failed To Generate New PIN'),
message: err.message,
})
}
}
}
}
async function copyTextToClipboard() {
if (activationPINInput) {
navigator.clipboard.writeText(activationPINInput.value)
await success?.({
heading: translate('configuration.messageHeading.activationPINCopied', 'Activation PIN Copied!'),
message: translate(
'configuration.user.permissions.activationPINCopied',
'Activation PIN copied to clipboard successfully.',
),
})
}
}
async function reactivateUserAccount() {
if (
confirm(
translate(
'configuration.user.permissions.reactivateUserConfirmation',
'Are you sure you want to reactivate this user?',
),
)
) {
userAccount.status = 'ACTIVE'
userAccount.lockNotes = null
await accountInfoChanged?.()
}
}
const emailAddressRegex =
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
const emailIsValid = (emailAddress: string): boolean => emailAddressRegex.test(emailAddress)
let workEmail = $derived(userAccount.workEmail)
let status = $derived(userAccount.status)
let activationPIN = $derived(userAccount.userActivationData?.activationPIN)
let isCreatingNewUser = $derived(userAccount.id === null)
</script>

@@ -84,3 +159,3 @@

bind:offsetHeight={cardHeight}
{...$$restProps}
{...rest}
>

@@ -93,3 +168,3 @@ <fieldset disabled={!canEditAccountInfo}>

{icon}
class="mr-1"
class="mr-1 me-1"
/>

@@ -104,3 +179,3 @@ {isCreatingNewUser ? translate('configuration.user.creatingNewAccountInfoHeader', 'New Account') : cardTitle}

iconClass="xmark"
on:click={() => deactivateUserModal.open(userAccount)}
onclick={() => deactivateUserModal?.open(userAccount)}
disabled={!canEditAccountInfo || !canToggleActive}

@@ -116,3 +191,3 @@ >

iconClass="check"
on:click={() => reactivateUserAccount()}
onclick={() => reactivateUserAccount()}
disabled={!canEditAccountInfo || !canToggleActive}

@@ -126,3 +201,3 @@ >

<div class="card-body">
<div class="form-row">
<div class="row">
{#if !isCreatingNewUser && status === 'PENDING_ACTIVATION'}

@@ -132,3 +207,7 @@ <div class="col-12">

<div class="alert alert-info mb-0">
{translate('configuration.user.accountInfo.activationPINSent', 'An activation PIN has been sent to {{email}}.', { email: workEmail })}
{translate(
'configuration.user.accountInfo.activationPINSent',
'An activation PIN has been sent to {{email}}.',
{ email: workEmail },
)}
</div>

@@ -154,3 +233,3 @@ {:else}

iconClass="refresh"
on:click={() => getNewActivationPIN()}
onclick={() => getNewActivationPIN()}
title={translate('configuration.user.generateNewActivationPIN', 'Generate New PIN')}

@@ -162,3 +241,3 @@ />

iconClass="copy"
on:click={() => copyTextToClipboard()}
onclick={() => copyTextToClipboard()}
disabled={!activationPIN}

@@ -215,2 +294,5 @@ title={translate('configuration.user.copyActivationPIN', 'Copy Activation PIN')}

bind:value={userAccount.workEmail}
onchange={() => {
workEmailIsValid = !myAccountMode && userAccount.workEmail ? emailIsValid(userAccount.workEmail) : true
}}
autocomplete="email"

@@ -229,3 +311,3 @@ type="email"

class="p-0 mb-2"
on:click={() => getNewActivationPIN(true)}
onclick={() => getNewActivationPIN(true)}
>

@@ -238,4 +320,11 @@ {translate('configuration.user.sendNewActivationPIN', 'Send New Activation PIN')}...

<Input
label={translate('configuration.user.accountInfo.passwordRecoveryModal.passwordRecoveryEmail', 'Password Recovery Email')}
label={translate(
'configuration.user.accountInfo.passwordRecoveryModal.passwordRecoveryEmail',
'Password Recovery Email',
)}
bind:value={userAccount.recoveryEmail}
onchange={() => {
recoveryEmailIsValid =
myAccountMode && userAccount.recoveryEmail ? emailIsValid(userAccount.recoveryEmail) : true
}}
autocomplete="email"

@@ -261,5 +350,5 @@ type="email"

{/if}
<slot name="formFields"></slot>
{@render formFields?.()}
</div>
<slot></slot>
{@render children?.()}
</div>

@@ -273,4 +362,4 @@ <div class="card-footer">

disabled={!canEditAccountInfo}
on:click={() => {
passwordRecoveryModal.open(userAccount.workEmail, userAccount.lastPasswordResetDate)
onclick={() => {
passwordRecoveryModal?.open(userAccount.workEmail, userAccount.lastPasswordResetDate)
}}

@@ -287,3 +376,3 @@ >

disabled={!myAccountMode && !canEditAccountInfo}
on:click={() => passwordSetModal.open(userAccount)}
onclick={() => passwordSetModal?.open(userAccount)}
>

@@ -300,3 +389,3 @@ {#if myAccountMode}

color="danger"
on:click={() => {
onclick={() => {
userAccount.currentPassword = ''

@@ -330,3 +419,6 @@ userAccount.newPassword = ''

if (err instanceof Error) {
await error?.({ heading: translate('configuration.user.messageHeading.failedToDeactivateUser', 'Failed To Deactivate User'), message: err.message })
await error?.({
heading: translate('configuration.user.messageHeading.failedToDeactivateUser', 'Failed To Deactivate User'),
message: err.message,
})
}

@@ -352,3 +444,4 @@ }

heading: translate('configuration.user.passwordChangeErrorHeading', 'Failed To Change Password'),
message: err instanceof Error ? err.message : translate('workOrder.unknownError', 'An unknown error occurred'),
message:
err instanceof Error ? err.message : translate('workOrder.unknownError', 'An unknown error occurred'),
})

@@ -355,0 +448,0 @@ console.error(err)

@@ -1,49 +0,37 @@

import { SvelteComponent } from "svelte";
import type { ComponentProps } from 'svelte';
import type { UserAccount, ConfirmPasswordSetFn, DeactivateUserFn, HTMLDivAttributes, IconName, PasswordValidationRules } from './';
import type { HTMLDivAttributes } from './';
import type { ComponentProps, Snippet } from 'svelte';
import type { UserAccount, ConfirmPasswordSetFn, DeactivateUserFn, IconName, PasswordValidationRules } from './';
import PasswordRecoveryModal from './PasswordRecoveryModal.svelte';
declare const __propDef: {
props: HTMLDivAttributes & {
userAccount: UserAccount;
canEditAccountInfo?: boolean;
canToggleActive?: boolean;
hasPermissionToChangePassword?: boolean;
generateNewActivationPIN?: (userName: string, hasWorkEmail: boolean) => Promise<void>;
confirmPasswordSet?: ConfirmPasswordSetFn;
deactivateUser?: DeactivateUserFn;
success?: ((info: {
heading: string;
message: string;
}) => void | Promise<void>) | undefined;
error?: ((info: {
heading: string;
message: string;
}) => void | Promise<void>) | undefined;
accountInfoChanged?: (() => void | Promise<void>) | undefined;
sendPasswordRecoveryToken?: ComponentProps<PasswordRecoveryModal>["sendPasswordRecoveryToken"];
doSendPasswordRecoveryToken?: boolean;
icon?: IconName;
usernameInput?: HTMLInputElement | undefined;
cardHeight?: number;
myAccountMode?: boolean;
passwordValidationRules?: PasswordValidationRules | undefined;
cardTitle?: string;
recoveryEmailIsValid?: boolean;
workEmailIsValid?: boolean;
};
events: {
[evt: string]: CustomEvent<any>;
};
slots: {
formFields: {};
default: {};
};
exports?: {} | undefined;
bindings?: string | undefined;
};
export type UserAccountInfoProps = typeof __propDef.props;
export type UserAccountInfoEvents = typeof __propDef.events;
export type UserAccountInfoSlots = typeof __propDef.slots;
export default class UserAccountInfo extends SvelteComponent<UserAccountInfoProps, UserAccountInfoEvents, UserAccountInfoSlots> {
interface Props extends HTMLDivAttributes {
userAccount: UserAccount;
canEditAccountInfo?: boolean;
canToggleActive?: boolean;
hasPermissionToChangePassword?: boolean;
generateNewActivationPIN?: (userName: string, hasWorkEmail: boolean) => Promise<void>;
confirmPasswordSet?: ConfirmPasswordSetFn;
deactivateUser?: DeactivateUserFn;
success?: ((info: {
heading: string;
message: string;
}) => void | Promise<void>) | undefined;
error?: ((info: {
heading: string;
message: string;
}) => void | Promise<void>) | undefined;
accountInfoChanged?: (() => void | Promise<void>) | undefined;
sendPasswordRecoveryToken?: ComponentProps<typeof PasswordRecoveryModal>['sendPasswordRecoveryToken'];
doSendPasswordRecoveryToken?: boolean;
icon?: IconName;
usernameInput?: HTMLInputElement | undefined;
cardHeight?: number;
myAccountMode?: boolean;
passwordValidationRules?: PasswordValidationRules | undefined;
cardTitle?: string;
recoveryEmailIsValid?: boolean;
workEmailIsValid?: boolean;
formFields?: Snippet;
children?: Snippet;
}
export {};
declare const UserAccountInfo: import("svelte").Component<Props, {}, "doSendPasswordRecoveryToken" | "userAccount" | "usernameInput" | "cardHeight" | "recoveryEmailIsValid" | "workEmailIsValid">;
type UserAccountInfo = ReturnType<typeof UserAccountInfo>;
export default UserAccountInfo;

@@ -1,39 +0,114 @@

<script>import UserSiteAccess from "./UserSiteAccess.svelte";
import PermissionList from "./PermissionList.svelte";
import UserAccountInfo from "./UserAccountInfo.svelte";
import UserGroupMembership from "./UserGroupMembership.svelte";
export let siteLabel = "Site";
export let userAccountInfoIcon = "user";
export let groupMembershipIcon = "users";
export let permissionListIcon = "user-lock";
export let userSiteAccessIcon = "industry-windows";
export let permissionListCardHeaderTitle = "Permissions";
export let usernameInput = void 0;
export let userAccount;
export let canToggleActive = true;
export let canEditAccountInfo = true;
export let doSendPasswordRecoveryToken = false;
export let hasPermissionToChangePassword = false;
export let passwordValidationRules = void 0;
export let error = void 0;
export let success = void 0;
export let deactivateUser = void 0;
export let confirmPasswordSet = void 0;
export let accountInfoChanged = void 0;
export let sendPasswordRecoveryToken = void 0;
export let generateNewActivationPIN = () => Promise.resolve();
export let userSites;
export let canEditSiteAccess = true;
export let siteAccessChange = void 0;
export let groupMembership;
export let canEditGroupMembership = true;
export let groupMembershipChange = void 0;
export let permissions;
export let permissionValueMap = /* @__PURE__ */ new Map();
export let groupPermissionValueMap = void 0;
export let permissionValueChange = void 0;
let cardHeight;
<script lang="ts">
import type {
ErrorFn,
IconName,
UserSites,
SuccessFn,
SiteLabel,
UserAccount,
Permissions,
GroupMembership,
CanToggleActive,
DeactivateUserFn,
CanEditSiteAccess,
SiteAccessChangeFn,
PermissionValueMap,
CanEditAccountInfo,
ConfirmPasswordSetFn,
AccountInfoChangedFn,
CanEditGroupMembership,
PasswordValidationRules,
GroupMembershipChangeFn,
PermissionValueChangeFn,
GroupPermissionValueMap,
GenerateNewActivationPINFn,
DoSendPasswordRecoveryToken,
SendPasswordRecoveryTokenFn,
HasPermissionToChangePassword,
PermissionListCardHeaderTitle,
} from './util'
import UserSiteAccess from './UserSiteAccess.svelte'
import PermissionList from './PermissionList.svelte'
import UserAccountInfo from './UserAccountInfo.svelte'
import UserGroupMembership from './UserGroupMembership.svelte'
interface Props {
siteLabel?: SiteLabel
userAccountInfoIcon?: IconName
groupMembershipIcon?: IconName
permissionListIcon?: IconName
userSiteAccessIcon?: IconName
permissionListCardHeaderTitle?: PermissionListCardHeaderTitle
usernameInput?: HTMLInputElement | undefined
userAccount: UserAccount
canToggleActive?: CanToggleActive
canEditAccountInfo?: CanEditAccountInfo
doSendPasswordRecoveryToken?: DoSendPasswordRecoveryToken
hasPermissionToChangePassword?: HasPermissionToChangePassword
passwordValidationRules?: PasswordValidationRules | undefined
error?: ErrorFn
success?: SuccessFn
deactivateUser?: DeactivateUserFn
confirmPasswordSet?: ConfirmPasswordSetFn | undefined
accountInfoChanged?: AccountInfoChangedFn
sendPasswordRecoveryToken?: SendPasswordRecoveryTokenFn
generateNewActivationPIN?: GenerateNewActivationPINFn
userSites: UserSites
canEditSiteAccess?: CanEditSiteAccess
siteAccessChange?: SiteAccessChangeFn
groupMembership: GroupMembership
canEditGroupMembership?: CanEditGroupMembership
groupMembershipChange?: GroupMembershipChangeFn
permissions: Permissions
permissionValueMap?: PermissionValueMap
groupPermissionValueMap?: GroupPermissionValueMap
permissionValueChange?: PermissionValueChangeFn
userAccountInfo?: import('svelte').Snippet
siteAccess?: import('svelte').Snippet
userGroupMembership?: import('svelte').Snippet
permissionList?: import('svelte').Snippet
}
let {
siteLabel = 'Site',
userAccountInfoIcon = 'user',
groupMembershipIcon = 'users',
permissionListIcon = 'user-lock',
userSiteAccessIcon = 'industry-windows',
permissionListCardHeaderTitle = 'Permissions',
usernameInput = $bindable(undefined),
userAccount = $bindable(),
canToggleActive = true,
canEditAccountInfo = true,
doSendPasswordRecoveryToken = $bindable(false),
hasPermissionToChangePassword = false,
passwordValidationRules = undefined,
error = undefined,
success = undefined,
deactivateUser = undefined,
confirmPasswordSet = undefined,
accountInfoChanged = undefined,
sendPasswordRecoveryToken = undefined,
generateNewActivationPIN = () => Promise.resolve(),
userSites,
canEditSiteAccess = true,
siteAccessChange = undefined,
groupMembership,
canEditGroupMembership = true,
groupMembershipChange = undefined,
permissions,
permissionValueMap = new Map(),
groupPermissionValueMap = undefined,
permissionValueChange = undefined,
userAccountInfo,
siteAccess,
userGroupMembership,
permissionList,
}: Props = $props()
let cardHeight: number | undefined = $state()
</script>
<div class="form-row">
<div class="row">
<div class="col-12 col-lg-4 mb-2">

@@ -58,3 +133,3 @@ <UserAccountInfo

>
<slot name="userAccountInfo"></slot>
{@render userAccountInfo?.()}
</UserAccountInfo>

@@ -71,3 +146,3 @@ </div>

>
<slot name="siteAccess"></slot>
{@render siteAccess?.()}
</UserSiteAccess>

@@ -83,7 +158,7 @@ </div>

>
<slot name="userGroupMembership"></slot>
{@render userGroupMembership?.()}
</UserGroupMembership>
</div>
</div>
<div class="form-row">
<div class="row">
<div class="col-12">

@@ -99,5 +174,5 @@ <PermissionList

>
<slot name="permissionList"></slot>
{@render permissionList?.()}
</PermissionList>
</div>
</div>

@@ -1,53 +0,40 @@

import { SvelteComponent } from "svelte";
import type { ErrorFn, IconName, UserSites, SuccessFn, SiteLabel, UserAccount, Permissions, GroupMembership, CanToggleActive, DeactivateUserFn, CanEditSiteAccess, SiteAccessChangeFn, PermissionValueMap, CanEditAccountInfo, ConfirmPasswordSetFn, AccountInfoChangedFn, CanEditGroupMembership, PasswordValidationRules, GroupMembershipChangeFn, PermissionValueChangeFn, GroupPermissionValueMap, GenerateNewActivationPINFn, DoSendPasswordRecoveryToken, SendPasswordRecoveryTokenFn, HasPermissionToChangePassword, PermissionListCardHeaderTitle } from './util';
declare const __propDef: {
props: {
siteLabel?: SiteLabel;
userAccountInfoIcon?: IconName;
groupMembershipIcon?: IconName;
permissionListIcon?: IconName;
userSiteAccessIcon?: IconName;
permissionListCardHeaderTitle?: PermissionListCardHeaderTitle;
usernameInput?: HTMLInputElement | undefined;
userAccount: UserAccount;
canToggleActive?: CanToggleActive;
canEditAccountInfo?: CanEditAccountInfo;
doSendPasswordRecoveryToken?: DoSendPasswordRecoveryToken;
hasPermissionToChangePassword?: HasPermissionToChangePassword;
passwordValidationRules?: PasswordValidationRules | undefined;
error?: ErrorFn;
success?: SuccessFn;
deactivateUser?: DeactivateUserFn;
confirmPasswordSet?: ConfirmPasswordSetFn | undefined;
accountInfoChanged?: AccountInfoChangedFn;
sendPasswordRecoveryToken?: SendPasswordRecoveryTokenFn;
generateNewActivationPIN?: GenerateNewActivationPINFn;
userSites: UserSites;
canEditSiteAccess?: CanEditSiteAccess;
siteAccessChange?: SiteAccessChangeFn;
groupMembership: GroupMembership;
canEditGroupMembership?: CanEditGroupMembership;
groupMembershipChange?: GroupMembershipChangeFn;
permissions: Permissions;
permissionValueMap?: PermissionValueMap;
groupPermissionValueMap?: GroupPermissionValueMap;
permissionValueChange?: PermissionValueChangeFn;
};
events: {
[evt: string]: CustomEvent<any>;
};
slots: {
userAccountInfo: {};
siteAccess: {};
userGroupMembership: {};
permissionList: {};
};
exports?: {} | undefined;
bindings?: string | undefined;
};
export type UserConfigurationProps = typeof __propDef.props;
export type UserConfigurationEvents = typeof __propDef.events;
export type UserConfigurationSlots = typeof __propDef.slots;
export default class UserConfiguration extends SvelteComponent<UserConfigurationProps, UserConfigurationEvents, UserConfigurationSlots> {
interface Props {
siteLabel?: SiteLabel;
userAccountInfoIcon?: IconName;
groupMembershipIcon?: IconName;
permissionListIcon?: IconName;
userSiteAccessIcon?: IconName;
permissionListCardHeaderTitle?: PermissionListCardHeaderTitle;
usernameInput?: HTMLInputElement | undefined;
userAccount: UserAccount;
canToggleActive?: CanToggleActive;
canEditAccountInfo?: CanEditAccountInfo;
doSendPasswordRecoveryToken?: DoSendPasswordRecoveryToken;
hasPermissionToChangePassword?: HasPermissionToChangePassword;
passwordValidationRules?: PasswordValidationRules | undefined;
error?: ErrorFn;
success?: SuccessFn;
deactivateUser?: DeactivateUserFn;
confirmPasswordSet?: ConfirmPasswordSetFn | undefined;
accountInfoChanged?: AccountInfoChangedFn;
sendPasswordRecoveryToken?: SendPasswordRecoveryTokenFn;
generateNewActivationPIN?: GenerateNewActivationPINFn;
userSites: UserSites;
canEditSiteAccess?: CanEditSiteAccess;
siteAccessChange?: SiteAccessChangeFn;
groupMembership: GroupMembership;
canEditGroupMembership?: CanEditGroupMembership;
groupMembershipChange?: GroupMembershipChangeFn;
permissions: Permissions;
permissionValueMap?: PermissionValueMap;
groupPermissionValueMap?: GroupPermissionValueMap;
permissionValueChange?: PermissionValueChangeFn;
userAccountInfo?: import('svelte').Snippet;
siteAccess?: import('svelte').Snippet;
userGroupMembership?: import('svelte').Snippet;
permissionList?: import('svelte').Snippet;
}
export {};
declare const UserConfiguration: import("svelte").Component<Props, {}, "doSendPasswordRecoveryToken" | "userAccount" | "usernameInput">;
type UserConfiguration = ReturnType<typeof UserConfiguration>;
export default UserConfiguration;

@@ -1,10 +0,34 @@

<script>import { getContext } from "svelte";
import Icon from "@isoftdata/svelte-icon";
import Checkbox from "@isoftdata/svelte-checkbox";
import { translate as defaultTranslate } from "@isoftdata/utility-string";
const { t: translate } = getContext("i18next") || { t: defaultTranslate };
export let groupMembership;
export let canEditGroupMembership = true;
export let groupMembershipChange = void 0;
export let icon = "users";
<script lang="ts">
import type { i18n } from 'i18next'
import type { IconName, HTMLDivAttributes } from './'
import { getContext } from 'svelte'
import Icon from '@isoftdata/svelte-icon'
import Checkbox from '@isoftdata/svelte-checkbox'
import { translate as defaultTranslate } from '@isoftdata/utility-string'
const { t: translate } = getContext<i18n>('i18next') || { t: defaultTranslate }
interface GroupMembership {
id: number
name: string
isMember: boolean
}
interface Props extends HTMLDivAttributes {
groupMembership: Array<GroupMembership>
canEditGroupMembership?: boolean
groupMembershipChange?: ((groupMembership: GroupMembership) => void | Promise<void>) | undefined
icon?: IconName
children?: import('svelte').Snippet
}
let {
groupMembership,
canEditGroupMembership = true,
groupMembershipChange = undefined,
icon = 'users',
children,
...rest
}: Props = $props()
</script>

@@ -14,3 +38,3 @@

class="card"
{...$$restProps}
{...rest}
>

@@ -27,9 +51,9 @@ <div class="card-header">

>
{#each groupMembership as { id, name, isMember } (id)}
{#each groupMembership as { id, name, isMember }, index (id)}
<li class="list-group-item">
<Checkbox
label={name}
bind:checked={isMember}
bind:checked={groupMembership[index].isMember}
disabled={!canEditGroupMembership}
on:change={async () => {
onchange={async () => {
await groupMembershipChange?.({ id, name, isMember })

@@ -41,3 +65,3 @@ }}

</ul>
<slot></slot>
{@render children?.()}
</div>

@@ -1,32 +0,16 @@

import { SvelteComponent } from "svelte";
import type { IconName, HTMLDivAttributes } from './';
declare const __propDef: {
props: HTMLDivAttributes & {
groupMembership: Array<{
id: number;
name: string;
isMember: boolean;
}>;
canEditGroupMembership?: boolean;
groupMembershipChange?: ((groupMembership: {
id: number;
name: string;
isMember: boolean;
}) => void | Promise<void>) | undefined;
icon?: IconName;
};
events: {
[evt: string]: CustomEvent<any>;
};
slots: {
default: {};
};
exports?: {} | undefined;
bindings?: string | undefined;
};
export type UserGroupMembershipProps = typeof __propDef.props;
export type UserGroupMembershipEvents = typeof __propDef.events;
export type UserGroupMembershipSlots = typeof __propDef.slots;
export default class UserGroupMembership extends SvelteComponent<UserGroupMembershipProps, UserGroupMembershipEvents, UserGroupMembershipSlots> {
interface GroupMembership {
id: number;
name: string;
isMember: boolean;
}
export {};
interface Props extends HTMLDivAttributes {
groupMembership: Array<GroupMembership>;
canEditGroupMembership?: boolean;
groupMembershipChange?: ((groupMembership: GroupMembership) => void | Promise<void>) | undefined;
icon?: IconName;
children?: import('svelte').Snippet;
}
declare const UserGroupMembership: import("svelte").Component<Props, {}, "">;
type UserGroupMembership = ReturnType<typeof UserGroupMembership>;
export default UserGroupMembership;

@@ -1,11 +0,38 @@

<script>import { getContext } from "svelte";
import Icon from "@isoftdata/svelte-icon";
import Checkbox from "@isoftdata/svelte-checkbox";
import { translate as defaultTranslate } from "@isoftdata/utility-string";
const { t: translate } = getContext("i18next") || { t: defaultTranslate };
export let userSites;
export let siteLabel = "Site";
export let canEditSiteAccess = true;
export let siteAccessChange = void 0;
export let icon = "industry-windows";
<script lang="ts">
import type { Snippet } from 'svelte'
import type { i18n } from 'i18next'
import type { IconName, HTMLDivAttributes, SiteLabel } from './'
import { getContext } from 'svelte'
import Icon from '@isoftdata/svelte-icon'
import Checkbox from '@isoftdata/svelte-checkbox'
import { translate as defaultTranslate } from '@isoftdata/utility-string'
const { t: translate } = getContext<i18n>('i18next') || { t: defaultTranslate }
interface SiteAccess {
id: number
code: string
name: string
isAuthorized: boolean
}
interface Props extends HTMLDivAttributes {
userSites: Array<SiteAccess>
siteLabel?: SiteLabel
canEditSiteAccess?: boolean
siteAccessChange?: ((siteAccess: SiteAccess) => void | Promise<void>) | undefined
icon?: IconName
children?: Snippet
}
let {
userSites = $bindable(),
siteLabel = 'Site',
canEditSiteAccess = true,
siteAccessChange = undefined,
icon = 'industry-windows',
children,
...rest
}: Props = $props()
</script>

@@ -15,3 +42,3 @@

class="card"
{...$$restProps}
{...rest}
>

@@ -31,3 +58,3 @@ <div class="card-header">

disabled={!canEditSiteAccess}
on:change={async () => {
onchange={async () => {
await siteAccessChange?.(userSites[i])

@@ -39,3 +66,3 @@ }}

</ul>
<slot></slot>
{@render children?.()}
</div>

@@ -1,35 +0,19 @@

import { SvelteComponent } from "svelte";
import type { Snippet } from 'svelte';
import type { IconName, HTMLDivAttributes, SiteLabel } from './';
declare const __propDef: {
props: HTMLDivAttributes & {
userSites: Array<{
id: number;
code: string;
name: string;
isAuthorized: boolean;
}>;
siteLabel?: SiteLabel;
canEditSiteAccess?: boolean;
siteAccessChange?: ((siteAccess: {
id: number;
code: string;
name: string;
isAuthorized: boolean;
}) => void | Promise<void>) | undefined;
icon?: IconName;
};
events: {
[evt: string]: CustomEvent<any>;
};
slots: {
default: {};
};
exports?: {} | undefined;
bindings?: string | undefined;
};
export type UserSiteAccessProps = typeof __propDef.props;
export type UserSiteAccessEvents = typeof __propDef.events;
export type UserSiteAccessSlots = typeof __propDef.slots;
export default class UserSiteAccess extends SvelteComponent<UserSiteAccessProps, UserSiteAccessEvents, UserSiteAccessSlots> {
interface SiteAccess {
id: number;
code: string;
name: string;
isAuthorized: boolean;
}
export {};
interface Props extends HTMLDivAttributes {
userSites: Array<SiteAccess>;
siteLabel?: SiteLabel;
canEditSiteAccess?: boolean;
siteAccessChange?: ((siteAccess: SiteAccess) => void | Promise<void>) | undefined;
icon?: IconName;
children?: Snippet;
}
declare const UserSiteAccess: import("svelte").Component<Props, {}, "userSites">;
type UserSiteAccess = ReturnType<typeof UserSiteAccess>;
export default UserSiteAccess;

@@ -33,24 +33,24 @@ import type { ComponentProps } from 'svelte';

export declare const valueRank: Record<PermissionValue, number>;
export type GenerateNewActivationPINFn = ComponentProps<UserAccountInfo>['generateNewActivationPIN'];
export type SuccessFn = ComponentProps<UserAccountInfo>['success'];
export type ErrorFn = ComponentProps<UserAccountInfo>['error'];
export type AccountInfoChangedFn = ComponentProps<UserAccountInfo>['accountInfoChanged'];
export type CanEditAccountInfo = ComponentProps<UserAccountInfo>['canEditAccountInfo'];
export type CanToggleActive = ComponentProps<UserAccountInfo>['canToggleActive'];
export type HasPermissionToChangePassword = ComponentProps<UserAccountInfo>['hasPermissionToChangePassword'];
export type ConfirmPasswordSetFn = ComponentProps<PasswordSetModal>['confirmPasswordSet'];
export type DeactivateUserFn = ComponentProps<DeactivateUserModal>['deactivateUser'];
export type DoSendPasswordRecoveryToken = ComponentProps<PasswordRecoveryModal>['doSendPasswordRecoveryToken'];
export type SendPasswordRecoveryTokenFn = ComponentProps<PasswordRecoveryModal>['sendPasswordRecoveryToken'];
export type UserSites = ComponentProps<UserSiteAccess>['userSites'];
export type CanEditSiteAccess = ComponentProps<UserSiteAccess>['canEditSiteAccess'];
export type SiteAccessChangeFn = ComponentProps<UserSiteAccess>['siteAccessChange'];
export type GroupMembership = ComponentProps<UserGroupMembership>['groupMembership'];
export type GroupMembershipChangeFn = ComponentProps<UserGroupMembership>['groupMembershipChange'];
export type CanEditGroupMembership = ComponentProps<UserGroupMembership>['canEditGroupMembership'];
export type Permissions = ComponentProps<PermissionList>['permissions'];
export type PermissionValueMap = ComponentProps<PermissionList>['permissionValueMap'];
export type GroupPermissionValueMap = ComponentProps<PermissionList>['groupPermissionValueMap'];
export type PermissionValueChangeFn = ComponentProps<PermissionList>['permissionValueChange'];
export type PermissionListCardHeaderTitle = ComponentProps<PermissionList>['cardHeaderTitle'];
export type GenerateNewActivationPINFn = ComponentProps<typeof UserAccountInfo>['generateNewActivationPIN'];
export type SuccessFn = ComponentProps<typeof UserAccountInfo>['success'];
export type ErrorFn = ComponentProps<typeof UserAccountInfo>['error'];
export type AccountInfoChangedFn = ComponentProps<typeof UserAccountInfo>['accountInfoChanged'];
export type CanEditAccountInfo = ComponentProps<typeof UserAccountInfo>['canEditAccountInfo'];
export type CanToggleActive = ComponentProps<typeof UserAccountInfo>['canToggleActive'];
export type HasPermissionToChangePassword = ComponentProps<typeof UserAccountInfo>['hasPermissionToChangePassword'];
export type ConfirmPasswordSetFn = ComponentProps<typeof PasswordSetModal>['confirmPasswordSet'];
export type DeactivateUserFn = ComponentProps<typeof DeactivateUserModal>['deactivateUser'];
export type DoSendPasswordRecoveryToken = ComponentProps<typeof PasswordRecoveryModal>['doSendPasswordRecoveryToken'];
export type SendPasswordRecoveryTokenFn = ComponentProps<typeof PasswordRecoveryModal>['sendPasswordRecoveryToken'];
export type UserSites = ComponentProps<typeof UserSiteAccess>['userSites'];
export type CanEditSiteAccess = ComponentProps<typeof UserSiteAccess>['canEditSiteAccess'];
export type SiteAccessChangeFn = ComponentProps<typeof UserSiteAccess>['siteAccessChange'];
export type GroupMembership = ComponentProps<typeof UserGroupMembership>['groupMembership'];
export type GroupMembershipChangeFn = ComponentProps<typeof UserGroupMembership>['groupMembershipChange'];
export type CanEditGroupMembership = ComponentProps<typeof UserGroupMembership>['canEditGroupMembership'];
export type Permissions = ComponentProps<typeof PermissionList>['permissions'];
export type PermissionValueMap = ComponentProps<typeof PermissionList>['permissionValueMap'];
export type GroupPermissionValueMap = ComponentProps<typeof PermissionList>['groupPermissionValueMap'];
export type PermissionValueChangeFn = ComponentProps<typeof PermissionList>['permissionValueChange'];
export type PermissionListCardHeaderTitle = ComponentProps<typeof PermissionList>['cardHeaderTitle'];
/** Returns a Map where the key is the `permissioniId` and the value is the highest permission level for the given group membership

@@ -57,0 +57,0 @@ *

{
"name": "@isoftdata/svelte-user-configuration",
"version": "1.3.3",
"scripts": {
"dev": "vite dev",
"build": "vite build && npm run package",
"preview": "vite preview",
"package": "svelte-kit sync && svelte-package && publint",
"prepublishOnly": "npm run package",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"lint": "prettier --check . && eslint .",
"format": "prettier --write ."
},
"exports": {
".": {
"types": "./dist/index.d.ts",
"svelte": "./dist/index.js"
}
},
"sideEffects": [
"**/*.css"
],
"files": [
"dist",
"!dist/**/*.test.*",
"!dist/**/*.spec.*"
],
"peerDependencies": {
"svelte": "^4.0.0 || ^5.16.3"
},
"devDependencies": {
"@fortawesome/fontawesome-common-types": "^6.7.2",
"@isoftdata/prettier-config": "^1.0.3",
"@isoftdata/svelte-bootstrap-version-switcher": "^1.0.2",
"@sveltejs/adapter-auto": "^3.0.0",
"@sveltejs/kit": "^2.0.0",
"@sveltejs/package": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^3.0.0",
"@types/eslint": "^9.6.0",
"eslint": "^9.0.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-svelte": "^2.36.0",
"globals": "^15.0.0",
"i18next": "^24.2.1",
"prettier": "^3.1.1",
"prettier-plugin-svelte": "^3.1.2",
"publint": "^0.2.0",
"svelte": "^4.2.7",
"svelte-check": "^4.0.0",
"type-fest": "^4.33.0",
"typescript": "^5.0.0",
"typescript-eslint": "^8.0.0",
"vite": "^5.0.11"
},
"svelte": "./dist/index.js",
"types": "./dist/index.d.ts",
"type": "module",
"prettier": "@isoftdata/prettier-config",
"dependencies": {
"@isoftdata/browser-event": "^2.3.2",
"@isoftdata/svelte-button": "^1.4.1",
"@isoftdata/svelte-checkbox": "^1.5.1",
"@isoftdata/svelte-icon": "^1.4.0",
"@isoftdata/svelte-input": "^1.6.0",
"@isoftdata/svelte-modal": "^1.3.1",
"@isoftdata/svelte-password-fields": "^1.4.1",
"@isoftdata/svelte-select": "^1.5.0",
"@isoftdata/svelte-table": "^1.16.0",
"@isoftdata/svelte-textarea": "^1.2.0",
"@isoftdata/utility-string": "^2.1.0",
"just-camel-case": "^6.2.0",
"klona": "^2.0.6"
}
"name": "@isoftdata/svelte-user-configuration",
"version": "2.0.0",
"scripts": {
"dev": "vite dev",
"build": "vite build && npm run package",
"preview": "vite preview",
"package": "svelte-kit sync && svelte-package && publint",
"prepublishOnly": "npm run package",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"lint": "prettier --check . && eslint .",
"format": "prettier --write ."
},
"exports": {
".": {
"types": "./dist/index.d.ts",
"svelte": "./dist/index.js"
}
},
"sideEffects": [
"**/*.css"
],
"files": [
"dist",
"!dist/**/*.test.*",
"!dist/**/*.spec.*"
],
"peerDependencies": {
"svelte": "^5.23.2"
},
"devDependencies": {
"@fortawesome/fontawesome-common-types": "^6.7.2",
"@isoftdata/prettier-config": "^2.0.4",
"@isoftdata/svelte-bootstrap-version-switcher": "^1.1.0",
"@sveltejs/adapter-auto": "^6.0.0",
"@sveltejs/kit": "^2.5.27",
"@sveltejs/package": "^2.3.7",
"@sveltejs/vite-plugin-svelte": "^5.0.3",
"@types/eslint": "^9.6.0",
"eslint": "^9.0.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-svelte": "^2.45.1",
"globals": "^15.0.0",
"i18next": "^24.2.1",
"prettier": "^3.1.1",
"prettier-plugin-svelte": "^3.2.6",
"publint": "^0.2.0",
"svelte": "^5.0.0",
"svelte-check": "^4.0.0",
"type-fest": "^4.33.0",
"typescript": "^5.5.0",
"typescript-eslint": "^8.0.0",
"vite": "^6.2.5"
},
"svelte": "./dist/index.js",
"types": "./dist/index.d.ts",
"type": "module",
"prettier": "@isoftdata/prettier-config",
"dependencies": {
"@isoftdata/browser-event": "^2.3.2",
"@isoftdata/svelte-button": "^2.1.0",
"@isoftdata/svelte-checkbox": "^2.0.1",
"@isoftdata/svelte-icon": "^2.0.0",
"@isoftdata/svelte-input": "^2.0.1",
"@isoftdata/svelte-modal": "^2.0.4",
"@isoftdata/svelte-password-fields": "^1.5.0",
"@isoftdata/svelte-select": "^2.0.1",
"@isoftdata/svelte-table": "^2.1.1",
"@isoftdata/svelte-textarea": "^2.0.0",
"@isoftdata/utility-string": "^2.1.0",
"just-camel-case": "^6.2.0",
"klona": "^2.0.6",
"svelte": "^5.23.2"
}
}

@@ -11,2 +11,9 @@ # Svelte UserConfiguration

## Breaking changes
### 2.0.0
- Require Svelte 5
- Slots -> Snippets
- Events -> Callbacks
## Props

@@ -46,3 +53,3 @@

| `permissions` | `Permissions` | ✅ | - | The list of permissions for the user. |
| `permissionValueMap` | `PermissionValueMap` | ✅ | `new Map()` | A mapping of permissions to their values. |
| `permissionValueMap` | `PermissionValueMap` | ✅ | `new SvelteMap()` | A mapping of permissions to their values. **Note this *must* be a `SvelteMap`** or reactivity will not work. |
| `groupPermissionValueMap` | `GroupPermissionValueMap` | ❌ | `undefined` | A mapping of group-based permissions. |

@@ -150,5 +157,5 @@

}
permissionValueMap = new Map(permissionValueMap)
permissionValueMap = new SvelteMap(permissionValueMap)
}}
/>
```