mirror of
https://github.com/logto-io/logto.git
synced 2024-12-16 20:26:19 -05:00
refactor: reorg elements project (#6708)
This commit is contained in:
parent
95c7d8b5be
commit
98bd9bb4e0
62 changed files with 143 additions and 2413 deletions
|
@ -1,3 +0,0 @@
|
|||
# Logto account elements
|
||||
|
||||
TBD
|
|
@ -1,17 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Logto elements dev page</title>
|
||||
<script type="module" src="./src/index.ts"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<logto-account-provider>
|
||||
Logto Account Provider
|
||||
</logto-account-provider>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,83 +0,0 @@
|
|||
{
|
||||
"name": "@logto/elements",
|
||||
"version": "0.0.1",
|
||||
"description": "Logto account elements.",
|
||||
"author": "Silverhand Inc. <contact@silverhand.io>",
|
||||
"homepage": "https://github.com/logto-io/logto#readme",
|
||||
"license": "MPL-2.0",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.js",
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
},
|
||||
"./react": {
|
||||
"import": "./dist/react.js",
|
||||
"types": "./dist/react.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/logto-io/logto.git"
|
||||
},
|
||||
"scripts": {
|
||||
"precommit": "lint-staged",
|
||||
"build": "tsup",
|
||||
"start": "web-dev-server",
|
||||
"dev": "tsup --watch --no-splitting",
|
||||
"lint": "eslint --ext .ts src",
|
||||
"lint:report": "pnpm lint --format json --output-file report.json",
|
||||
"test": "echo \"No tests yet.\"",
|
||||
"test:ci": "pnpm run test --silent --coverage"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.9.0"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/logto-io/logto/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"@lit/context": "^1.1.2",
|
||||
"@lit/react": "^1.0.5",
|
||||
"@silverhand/essentials": "^2.9.1",
|
||||
"ky": "^1.2.3",
|
||||
"lit": "^3.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@logto/schemas": "workspace:^1.20.0",
|
||||
"@silverhand/eslint-config": "6.0.1",
|
||||
"@silverhand/ts-config": "6.0.0",
|
||||
"@types/node": "^20.9.5",
|
||||
"@web/dev-server": "^0.4.6",
|
||||
"@web/dev-server-esbuild": "^1.0.2",
|
||||
"eslint": "^8.56.0",
|
||||
"lint-staged": "^15.0.0",
|
||||
"prettier": "^3.0.0",
|
||||
"tsup": "^8.1.0"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "@silverhand",
|
||||
"ignorePatterns": [
|
||||
"src/generated/"
|
||||
],
|
||||
"rules": {
|
||||
"no-console": "error",
|
||||
"unicorn/prevent-abbreviations": [
|
||||
"error",
|
||||
{
|
||||
"replacements": {
|
||||
"var": false,
|
||||
"vars": false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"prettier": "@silverhand/eslint-config/.prettierrc"
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
import { type UserProfileResponse } from '@logto/schemas';
|
||||
import ky, { type KyInstance } from 'ky';
|
||||
|
||||
export type AccessTokenFetcher = () => Promise<string>;
|
||||
|
||||
/**
|
||||
* The API client for the Logto account elements
|
||||
*
|
||||
* Used internally to interact with Account-related backend APIs, including the Profile API.
|
||||
*/
|
||||
export class LogtoAccountApi {
|
||||
private readonly ky: KyInstance;
|
||||
|
||||
constructor(
|
||||
/**
|
||||
* The endpoint of the Logto instance.
|
||||
*/
|
||||
logtoEndpoint: string,
|
||||
/**
|
||||
* The function to fetch the account access token.
|
||||
*/
|
||||
accessTokenFetcher: AccessTokenFetcher
|
||||
) {
|
||||
this.ky = ky.create({
|
||||
prefixUrl: logtoEndpoint,
|
||||
hooks: {
|
||||
beforeRequest: [
|
||||
async (request) => {
|
||||
request.headers.set('Authorization', `Bearer ${await accessTokenFetcher()}`);
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async fetchUserProfile() {
|
||||
return this.ky.get('api/profile').json<UserProfileResponse>();
|
||||
}
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
export type { AccessTokenFetcher } from './api/index.js';
|
||||
|
||||
export * from './providers/logto-account-provider.js';
|
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
"extends": "@silverhand/ts-config/tsconfig.base",
|
||||
"compilerOptions": {
|
||||
"experimentalDecorators": true,
|
||||
"useDefineForClassFields": false,
|
||||
"noEmit": true
|
||||
},
|
||||
"include": [
|
||||
"src",
|
||||
"*.config.ts"
|
||||
]
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
import fs from 'node:fs/promises';
|
||||
|
||||
import { defineConfig } from 'tsup';
|
||||
|
||||
export default defineConfig({
|
||||
entry: ['src/index.ts', 'src/react.ts'],
|
||||
format: 'esm',
|
||||
dts: true,
|
||||
clean: true,
|
||||
esbuildPlugins: [
|
||||
{
|
||||
name: 'transform-svg',
|
||||
setup: (build) => {
|
||||
build.onLoad({ filter: /\.svg$/ }, async (arguments_) => {
|
||||
const text = await fs.readFile(arguments_.path, 'utf8');
|
||||
return {
|
||||
contents: `import { html } from 'lit';\nexport default html\`${text}\`;`,
|
||||
};
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
|
@ -1,33 +0,0 @@
|
|||
// eslint-disable-next-line unicorn/prevent-abbreviations
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
import { esbuildPlugin } from '@web/dev-server-esbuild';
|
||||
|
||||
const config = {
|
||||
open: true,
|
||||
watch: true,
|
||||
appIndex: 'index.html',
|
||||
nodeResolve: {
|
||||
exportConditions: ['development'],
|
||||
},
|
||||
plugins: [
|
||||
esbuildPlugin({
|
||||
ts: true,
|
||||
tsconfig: fileURLToPath(new URL('tsconfig.json', import.meta.url)),
|
||||
}),
|
||||
// Transform SVG files into Lit templates
|
||||
{
|
||||
name: 'transform-svg',
|
||||
transform(context) {
|
||||
if (context.path.endsWith('.svg')) {
|
||||
return {
|
||||
body: `import { html } from 'lit';\nexport default html\`${context.body}\`;`,
|
||||
headers: { 'content-type': 'application/javascript' },
|
||||
};
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default config;
|
|
@ -30,7 +30,6 @@
|
|||
"@logto/cloud": "0.2.5-5e334eb",
|
||||
"@logto/connector-kit": "workspace:^4.0.0",
|
||||
"@logto/core-kit": "workspace:^2.5.0",
|
||||
"@logto/elements": "workspace:^0.0.1",
|
||||
"@logto/language-kit": "workspace:^1.1.0",
|
||||
"@logto/phrases": "workspace:^1.14.0",
|
||||
"@logto/phrases-experience": "workspace:^1.8.0",
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { createReactComponents, initLocalization } from '@logto/elements/react';
|
||||
import type { ConnectorResponse } from '@logto/schemas';
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import { useCallback, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useRoutes } from 'react-router-dom';
|
||||
import useSWRImmutable from 'swr/immutable';
|
||||
|
@ -9,7 +8,7 @@ import FormCard from '@/components/FormCard';
|
|||
import PageMeta from '@/components/PageMeta';
|
||||
import Topbar from '@/components/Topbar';
|
||||
import { adminTenantEndpoint, meApi } from '@/consts';
|
||||
import { isCloud, isDevFeaturesEnabled } from '@/consts/env';
|
||||
import { isCloud } from '@/consts/env';
|
||||
import AppBoundary from '@/containers/AppBoundary';
|
||||
import Button from '@/ds-components/Button';
|
||||
import CardTitle from '@/ds-components/CardTitle';
|
||||
|
@ -32,12 +31,6 @@ import Skeleton from './components/Skeleton';
|
|||
import DeleteAccountModal from './containers/DeleteAccountModal';
|
||||
import styles from './index.module.scss';
|
||||
|
||||
if (isDevFeaturesEnabled) {
|
||||
initLocalization();
|
||||
}
|
||||
|
||||
const { LogtoProfileCard, LogtoThemeProvider, LogtoUserProvider } = createReactComponents(React);
|
||||
|
||||
function Profile() {
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||
const { navigate } = useTenantPathname();
|
||||
|
@ -69,64 +62,59 @@ function Profile() {
|
|||
|
||||
return (
|
||||
<AppBoundary>
|
||||
<LogtoThemeProvider theme="dark">
|
||||
<LogtoUserProvider api={api}>
|
||||
<div className={styles.pageContainer}>
|
||||
<Topbar hideTenantSelector hideTitle />
|
||||
<OverlayScrollbar className={styles.scrollable}>
|
||||
<div className={styles.wrapper}>
|
||||
<PageMeta titleKey="profile.page_title" />
|
||||
<div className={pageLayout.headline}>
|
||||
<CardTitle title="profile.title" subtitle="profile.description" />
|
||||
</div>
|
||||
{showLoadingSkeleton && <Skeleton />}
|
||||
{isDevFeaturesEnabled && <LogtoProfileCard />}
|
||||
{user && !showLoadingSkeleton && (
|
||||
<div className={styles.content}>
|
||||
<BasicUserInfoSection user={user} onUpdate={reload} />
|
||||
{isCloud && (
|
||||
<LinkAccountSection user={user} connectors={connectors} onUpdate={reload} />
|
||||
)}
|
||||
<FormCard title="profile.password.title">
|
||||
<CardContent
|
||||
title="profile.password.password_setting"
|
||||
data={[
|
||||
{
|
||||
key: 'password',
|
||||
label: 'profile.password.password',
|
||||
value: user.hasPassword,
|
||||
renderer: (value) => (value ? <span>********</span> : <NotSet />),
|
||||
action: {
|
||||
name: 'profile.change',
|
||||
handler: () => {
|
||||
navigate(user.hasPassword ? 'verify-password' : 'change-password', {
|
||||
state: { email: user.primaryEmail, action: 'changePassword' },
|
||||
});
|
||||
},
|
||||
},
|
||||
<div className={styles.pageContainer}>
|
||||
<Topbar hideTenantSelector hideTitle />
|
||||
<OverlayScrollbar className={styles.scrollable}>
|
||||
<div className={styles.wrapper}>
|
||||
<PageMeta titleKey="profile.page_title" />
|
||||
<div className={pageLayout.headline}>
|
||||
<CardTitle title="profile.title" subtitle="profile.description" />
|
||||
</div>
|
||||
{showLoadingSkeleton && <Skeleton />}
|
||||
{user && !showLoadingSkeleton && (
|
||||
<div className={styles.content}>
|
||||
<BasicUserInfoSection user={user} onUpdate={reload} />
|
||||
{isCloud && (
|
||||
<LinkAccountSection user={user} connectors={connectors} onUpdate={reload} />
|
||||
)}
|
||||
<FormCard title="profile.password.title">
|
||||
<CardContent
|
||||
title="profile.password.password_setting"
|
||||
data={[
|
||||
{
|
||||
key: 'password',
|
||||
label: 'profile.password.password',
|
||||
value: user.hasPassword,
|
||||
renderer: (value) => (value ? <span>********</span> : <NotSet />),
|
||||
action: {
|
||||
name: 'profile.change',
|
||||
handler: () => {
|
||||
navigate(user.hasPassword ? 'verify-password' : 'change-password', {
|
||||
state: { email: user.primaryEmail, action: 'changePassword' },
|
||||
});
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</FormCard>
|
||||
{isCloud && (
|
||||
<FormCard title="profile.delete_account.title">
|
||||
<div className={styles.deleteAccount}>
|
||||
<div className={styles.description}>
|
||||
{t('profile.delete_account.description')}
|
||||
</div>
|
||||
<Button title="profile.delete_account.button" onClick={show} />
|
||||
</div>
|
||||
<DeleteAccountModal isOpen={showDeleteAccountModal} onClose={hide} />
|
||||
</FormCard>
|
||||
)}
|
||||
</div>
|
||||
},
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</FormCard>
|
||||
{isCloud && (
|
||||
<FormCard title="profile.delete_account.title">
|
||||
<div className={styles.deleteAccount}>
|
||||
<div className={styles.description}>
|
||||
{t('profile.delete_account.description')}
|
||||
</div>
|
||||
<Button title="profile.delete_account.button" onClick={show} />
|
||||
</div>
|
||||
<DeleteAccountModal isOpen={showDeleteAccountModal} onClose={hide} />
|
||||
</FormCard>
|
||||
)}
|
||||
</div>
|
||||
</OverlayScrollbar>
|
||||
{childrenRoutes}
|
||||
)}
|
||||
</div>
|
||||
</LogtoUserProvider>
|
||||
</LogtoThemeProvider>
|
||||
</OverlayScrollbar>
|
||||
{childrenRoutes}
|
||||
</div>
|
||||
</AppBoundary>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
# @logto/elements
|
||||
|
||||
## 0.0.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- fae8725a4: improve RTL language support
|
|
@ -5,15 +5,13 @@
|
|||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Logto elements dev page</title>
|
||||
<script type="module" src="./src/index.ts"></script>
|
||||
<script type="module" src="./src/account/index.ts"></script>
|
||||
</head>
|
||||
|
||||
<body style="background: #111;">
|
||||
<logto-theme-provider theme="dark">
|
||||
<logto-user-provider>
|
||||
<logto-profile-card></logto-profile-card>
|
||||
</logto-user-provider>
|
||||
</logto-theme-provider>
|
||||
<body style="background: #ecebf5;">
|
||||
<logto-account-provider>
|
||||
Logto Account Provider
|
||||
</logto-account-provider>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
{
|
||||
"$schema": "https://raw.githubusercontent.com/lit/lit/main/packages/localize-tools/config.schema.json",
|
||||
"sourceLocale": "en",
|
||||
"targetLocales": [
|
||||
"ar-AR",
|
||||
"de",
|
||||
"es",
|
||||
"fr",
|
||||
"it",
|
||||
"ja",
|
||||
"ko",
|
||||
"pl-PL",
|
||||
"pt-BR",
|
||||
"pt-PT",
|
||||
"ru",
|
||||
"tr-TR",
|
||||
"zh-CN",
|
||||
"zh-HK",
|
||||
"zh-TW"
|
||||
],
|
||||
"tsConfig": "./tsconfig.json",
|
||||
"output": {
|
||||
"mode": "runtime",
|
||||
"outputDir": "./src/generated/locales",
|
||||
"localeCodesModule": "./src/generated/locale-codes.ts"
|
||||
},
|
||||
"interchange": {
|
||||
"format": "xliff",
|
||||
"xliffDir": "./xliff/"
|
||||
}
|
||||
}
|
|
@ -10,13 +10,13 @@
|
|||
"main": "dist/index.js",
|
||||
"module": "dist/index.js",
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
"./account": {
|
||||
"import": "./dist/account/index.js",
|
||||
"types": "./dist/account/index.d.ts"
|
||||
},
|
||||
"./react": {
|
||||
"import": "./dist/react.js",
|
||||
"types": "./dist/react.d.ts"
|
||||
"./account/react": {
|
||||
"import": "./dist/account/react.js",
|
||||
"types": "./dist/account/react.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
|
@ -28,17 +28,14 @@
|
|||
},
|
||||
"scripts": {
|
||||
"precommit": "lint-staged",
|
||||
"build:only": "lit-localize build && tsup",
|
||||
"build": "pnpm check && pnpm build:only",
|
||||
"prepack": "pnpm build",
|
||||
"build": "tsup",
|
||||
"start": "web-dev-server",
|
||||
"dev": "lit-localize build && tsup --watch --no-splitting",
|
||||
"dev": "tsup --watch --no-splitting",
|
||||
"lint": "eslint --ext .ts src",
|
||||
"lint:report": "pnpm lint --format json --output-file report.json",
|
||||
"test": "echo \"No tests yet.\"",
|
||||
"test:ci": "pnpm run test --silent --coverage",
|
||||
"prepack": "pnpm build:only",
|
||||
"localize": "lit-localize",
|
||||
"check": "if command -v git &> /dev/null; then lit-localize extract && git add . -N && git diff --exit-code; fi"
|
||||
"test:ci": "pnpm run test --silent --coverage"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.9.0"
|
||||
|
|
49
packages/elements/src/account/api/index.ts
Normal file
49
packages/elements/src/account/api/index.ts
Normal file
|
@ -0,0 +1,49 @@
|
|||
import ky, { type KyInstance } from 'ky';
|
||||
|
||||
import { type UserProfile } from '../types.js';
|
||||
|
||||
export type GetAccessToken = () => Promise<string>;
|
||||
|
||||
/**
|
||||
* The API client for the Logto account elements
|
||||
*
|
||||
* Used to interact with Account-related backend APIs, including the Profile API.
|
||||
*/
|
||||
export class LogtoAccountApi {
|
||||
private readonly ky: KyInstance;
|
||||
|
||||
constructor(
|
||||
/**
|
||||
* The endpoint URL of the Logto service.
|
||||
*
|
||||
* Example: 'https://your-tenant-id.logto.app'
|
||||
*/
|
||||
logtoEndpoint: string,
|
||||
/**
|
||||
* Obtains the access token for Account-related API interactions.
|
||||
*
|
||||
* Called every time the account elements make a request to the backend API.
|
||||
*
|
||||
* Should handle access token expiration and request a new token when needed.
|
||||
*
|
||||
* Note: If using the `getAccessToken` method provided by the Logto SDK,
|
||||
* it already ensures a valid access token is obtained.
|
||||
*/
|
||||
getAccessToken: GetAccessToken
|
||||
) {
|
||||
this.ky = ky.create({
|
||||
prefixUrl: logtoEndpoint,
|
||||
hooks: {
|
||||
beforeRequest: [
|
||||
async (request) => {
|
||||
request.headers.set('Authorization', `Bearer ${await getAccessToken()}`);
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async fetchUserProfile() {
|
||||
return this.ky.get('api/profile').json<UserProfile>();
|
||||
}
|
||||
}
|
3
packages/elements/src/account/index.ts
Normal file
3
packages/elements/src/account/index.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
export * from './api/index.js';
|
||||
|
||||
export * from './providers/logto-account-provider.js';
|
|
@ -2,7 +2,7 @@ import { html, LitElement } from 'lit';
|
|||
import { customElement } from 'lit/decorators.js';
|
||||
|
||||
const tagName = 'logto-account-provider';
|
||||
@customElement('logto-account-provider')
|
||||
@customElement(tagName)
|
||||
export class LogtoAccountProvider extends LitElement {
|
||||
static tagName = tagName;
|
||||
|
|
@ -2,7 +2,7 @@ import { createComponent } from '@lit/react';
|
|||
|
||||
import { LogtoAccountProvider } from './index.js';
|
||||
|
||||
export type { AccessTokenFetcher } from './api/index.js';
|
||||
export * from './api/index.js';
|
||||
|
||||
export const createReactComponents = (react: Parameters<typeof createComponent>[0]['react']) => {
|
||||
return {
|
3
packages/elements/src/account/types.ts
Normal file
3
packages/elements/src/account/types.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
import { type UserProfileResponse } from '@logto/schemas';
|
||||
|
||||
export type UserProfile = Partial<UserProfileResponse>;
|
|
@ -1,53 +0,0 @@
|
|||
import { msg } from '@lit/localize';
|
||||
import { LitElement, css } from 'lit';
|
||||
import { customElement, property } from 'lit/decorators.js';
|
||||
|
||||
import { unit } from '../utils/css.js';
|
||||
|
||||
const tagName = 'logto-avatar';
|
||||
|
||||
const sizes = Object.freeze({
|
||||
medium: unit(8),
|
||||
large: unit(10),
|
||||
});
|
||||
|
||||
@customElement(tagName)
|
||||
export class LogtoAvatar extends LitElement {
|
||||
static tagName = tagName;
|
||||
static styles = css`
|
||||
:host {
|
||||
display: block;
|
||||
border-radius: ${unit(2)};
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
`;
|
||||
|
||||
@property({ reflect: true })
|
||||
size: 'medium' | 'large' = 'medium';
|
||||
|
||||
@property({ reflect: true })
|
||||
src = '';
|
||||
|
||||
@property({ reflect: true })
|
||||
alt = msg('Avatar', {
|
||||
id: 'account.profile.personal-info.avatar',
|
||||
desc: 'The avatar of the user.',
|
||||
});
|
||||
|
||||
connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
this.style.setProperty('width', sizes[this.size].cssText);
|
||||
this.style.setProperty('height', sizes[this.size].cssText);
|
||||
|
||||
if (this.src) {
|
||||
// Show the image holder with the provided image.
|
||||
this.style.setProperty('background-color', '#adaab422');
|
||||
this.style.setProperty('background-image', `url(${this.src})`);
|
||||
} else {
|
||||
// A temporary default fallback color. Need to implement the relevant logic in `<UserAvatar />` later.
|
||||
this.style.setProperty('background-color', '#e74c3c');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,106 +0,0 @@
|
|||
import { css } from 'lit';
|
||||
|
||||
import { unit } from '../utils/css.js';
|
||||
import { vars } from '../utils/theme.js';
|
||||
|
||||
export const buttonSizes = css`
|
||||
:host([size='small']) {
|
||||
height: 30px;
|
||||
padding: ${unit(0, 3)};
|
||||
}
|
||||
|
||||
:host([size='small'][type='text']) {
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
:host([size='medium']) {
|
||||
height: 36px;
|
||||
padding: ${unit(0, 4)};
|
||||
}
|
||||
|
||||
:host([size='medium'][type='text']) {
|
||||
height: 28px;
|
||||
font: ${vars.fontLabel1};
|
||||
}
|
||||
|
||||
:host([size='large']) {
|
||||
height: 44px;
|
||||
padding: ${unit(0, 6)};
|
||||
}
|
||||
|
||||
:host([size='large'][type='text']) {
|
||||
height: 28px;
|
||||
font: ${vars.fontLabel1};
|
||||
}
|
||||
`;
|
||||
|
||||
export const textButton = css`
|
||||
:host([type='text']) {
|
||||
background: none;
|
||||
border-color: transparent;
|
||||
font: ${vars.fontLabel2};
|
||||
color: ${vars.colorTextLink};
|
||||
padding: ${unit(0.5, 1)};
|
||||
border-radius: ${unit(1)};
|
||||
}
|
||||
|
||||
:host([type='text']:disabled) {
|
||||
color: ${vars.colorDisabled};
|
||||
}
|
||||
|
||||
:host([type='text']:focus-visible) {
|
||||
outline: 2px solid ${vars.colorFocusedVariant};
|
||||
}
|
||||
|
||||
:host([type='text']:not(:disabled):not(:active):hover) {
|
||||
background: ${vars.colorHoverVariant};
|
||||
}
|
||||
`;
|
||||
|
||||
export const defaultButton = css`
|
||||
:host([type='default']) {
|
||||
background: ${vars.colorLayer1};
|
||||
color: ${vars.colorTextPrimary};
|
||||
border: 1px solid ${vars.colorBorder};
|
||||
}
|
||||
|
||||
:host([type='default']:disabled) {
|
||||
color: ${vars.colorPlaceholder};
|
||||
}
|
||||
|
||||
:host([type='default']:focus-visible) {
|
||||
outline: 3px solid ${vars.colorFocused};
|
||||
}
|
||||
|
||||
:host([type='default']:active) {
|
||||
background: ${vars.colorPressed};
|
||||
}
|
||||
|
||||
:host([type='default']:not(:disabled):not(:active):hover) {
|
||||
background: ${vars.colorHover};
|
||||
}
|
||||
`;
|
||||
|
||||
export const primaryButton = css`
|
||||
:host([type='primary']) {
|
||||
background: ${vars.colorPrimary};
|
||||
color: ${vars.colorOnPrimary};
|
||||
}
|
||||
|
||||
:host([type='primary']:disabled) {
|
||||
background: ${vars.colorDisabledBackground};
|
||||
color: ${vars.colorPlaceholder};
|
||||
}
|
||||
|
||||
:host([type='primary']:focus-visible) {
|
||||
outline: 3px solid ${vars.colorFocusedVariant};
|
||||
}
|
||||
|
||||
:host([type='primary']:active) {
|
||||
background: ${vars.colorPrimaryPressed};
|
||||
}
|
||||
|
||||
:host([type='primary']:not(:disabled):not(:active):hover) {
|
||||
background: ${vars.colorPrimaryHover};
|
||||
}
|
||||
`;
|
|
@ -1,58 +0,0 @@
|
|||
import { LitElement, css, html } from 'lit';
|
||||
import { customElement, property } from 'lit/decorators.js';
|
||||
|
||||
import { unit } from '../utils/css.js';
|
||||
import { vars } from '../utils/theme.js';
|
||||
|
||||
import { buttonSizes, defaultButton, primaryButton, textButton } from './logto-button.styles.js';
|
||||
|
||||
const tagName = 'logto-button';
|
||||
|
||||
@customElement(tagName)
|
||||
export class LogtoButton extends LitElement {
|
||||
static tagName = tagName;
|
||||
static styles = [
|
||||
css`
|
||||
:host {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: none;
|
||||
outline: none;
|
||||
font: ${vars.fontLabel2};
|
||||
transition: background-color 0.2s ease-in-out;
|
||||
white-space: nowrap;
|
||||
user-select: none;
|
||||
position: relative;
|
||||
text-decoration: none;
|
||||
gap: ${unit(2)};
|
||||
border-radius: ${unit(2)};
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
:host(:disabled) {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
`,
|
||||
buttonSizes,
|
||||
textButton,
|
||||
defaultButton,
|
||||
primaryButton,
|
||||
];
|
||||
|
||||
@property({ reflect: true })
|
||||
type: 'default' | 'text' | 'primary' = 'default';
|
||||
|
||||
@property({ reflect: true })
|
||||
size: 'small' | 'medium' | 'large' = 'medium';
|
||||
|
||||
connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
this.role = 'button';
|
||||
this.tabIndex = 0;
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`<slot></slot>`;
|
||||
}
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
import { localized } from '@lit/localize';
|
||||
import { LitElement, css, html } from 'lit';
|
||||
import { customElement, property } from 'lit/decorators.js';
|
||||
|
||||
import { notSet } from '../phrases/index.js';
|
||||
import { unit } from '../utils/css.js';
|
||||
import { vars } from '../utils/theme.js';
|
||||
|
||||
const tagName = 'logto-card-section';
|
||||
|
||||
/** A section in a form card with a heading. It is used to group related content. */
|
||||
@customElement(tagName)
|
||||
@localized()
|
||||
export class LogtoCardSection extends LitElement {
|
||||
static tagName = tagName;
|
||||
static styles = css`
|
||||
header {
|
||||
font: ${vars.fontLabel2};
|
||||
color: ${vars.colorTextPrimary};
|
||||
margin-bottom: ${unit(1)};
|
||||
}
|
||||
`;
|
||||
|
||||
@property()
|
||||
heading = notSet;
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<header>${this.heading}</header>
|
||||
<slot></slot>
|
||||
`;
|
||||
}
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
import { LitElement, css, html } from 'lit';
|
||||
import { customElement } from 'lit/decorators.js';
|
||||
|
||||
import { unit } from '../utils/css.js';
|
||||
import { vars } from '../utils/theme.js';
|
||||
|
||||
const tagName = 'logto-card';
|
||||
|
||||
/**
|
||||
* A card with background, padding, and border radius.
|
||||
*
|
||||
* @example
|
||||
* ```html
|
||||
* <logto-card>
|
||||
* <!-- Content goes here -->
|
||||
* </logto-card>
|
||||
* ```
|
||||
*/
|
||||
@customElement(tagName)
|
||||
export class LogtoCard extends LitElement {
|
||||
static tagName = tagName;
|
||||
static styles = css`
|
||||
:host {
|
||||
background: ${vars.colorLayer1};
|
||||
border-radius: ${unit(4)};
|
||||
padding: ${unit(6)};
|
||||
}
|
||||
`;
|
||||
|
||||
render() {
|
||||
return html`<slot></slot>`;
|
||||
}
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
import { localized } from '@lit/localize';
|
||||
import { cond } from '@silverhand/essentials';
|
||||
import { LitElement, css, html } from 'lit';
|
||||
import { customElement, property } from 'lit/decorators.js';
|
||||
|
||||
import { notSet } from '../phrases/index.js';
|
||||
import { unit } from '../utils/css.js';
|
||||
import { vars } from '../utils/theme.js';
|
||||
|
||||
const tagName = 'logto-form-card';
|
||||
|
||||
/**
|
||||
* A card that contains a form or form-like content. A heading and an optional description can be
|
||||
* provided to describe the purpose of the content.
|
||||
*
|
||||
* To group related content in a form card, use the `logto-card-section` element.
|
||||
*
|
||||
* @example
|
||||
* ```tsx
|
||||
* html`
|
||||
* <logto-form-card heading=${msg('Account', ...)}>
|
||||
* <logto-card-section heading=${msg('Personal information', ...)}>
|
||||
* <!-- Content goes here -->
|
||||
* </logto-card-section>
|
||||
* <logto-card-section heading=${msg('Account settings', ...)}>
|
||||
* <!-- Content goes here -->
|
||||
* </logto-card-section>
|
||||
* </logto-form-card>
|
||||
* `
|
||||
* ```
|
||||
*/
|
||||
@customElement(tagName)
|
||||
@localized()
|
||||
export class LogtoFormCard extends LitElement {
|
||||
static tagName = tagName;
|
||||
static styles = css`
|
||||
logto-card {
|
||||
display: flex;
|
||||
padding: ${unit(6, 8)};
|
||||
}
|
||||
|
||||
header {
|
||||
flex: 7;
|
||||
font: ${vars.fontSectionHeading1};
|
||||
color: ${vars.colorCardTitle};
|
||||
letter-spacing: 0.1em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
div.spacer {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
slot {
|
||||
display: block;
|
||||
flex: 16;
|
||||
}
|
||||
`;
|
||||
|
||||
@property()
|
||||
heading = notSet;
|
||||
|
||||
@property()
|
||||
description = '';
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<logto-card>
|
||||
<header>
|
||||
<div role="heading">${this.heading}</div>
|
||||
${cond(this.description && html`<p>${this.description}</p>`)}
|
||||
</header>
|
||||
<div class="spacer"></div>
|
||||
<slot></slot>
|
||||
</logto-card>
|
||||
`;
|
||||
}
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
import { LitElement, html, css } from 'lit';
|
||||
import { customElement } from 'lit/decorators.js';
|
||||
|
||||
import { unit } from '../utils/css.js';
|
||||
import { vars } from '../utils/theme.js';
|
||||
|
||||
const tagName = 'logto-icon-button';
|
||||
|
||||
@customElement(tagName)
|
||||
export class LogtoIconButton extends LitElement {
|
||||
static tagName = tagName;
|
||||
|
||||
static styles = css`
|
||||
:host {
|
||||
all: unset;
|
||||
border-radius: ${unit(1.5)};
|
||||
transition: background 0.2s ease-in-out;
|
||||
padding: ${unit(1)};
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
:host(:disabled) {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
:host(:focus-visible) {
|
||||
background: ${vars.colorFocused};
|
||||
}
|
||||
|
||||
:host(:not(:disabled):hover) {
|
||||
background: ${vars.colorHover};
|
||||
}
|
||||
|
||||
::slotted(svg) {
|
||||
color: ${vars.colorTextSecondary};
|
||||
}
|
||||
`;
|
||||
|
||||
connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
this.role = 'button';
|
||||
this.tabIndex = 0;
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`<slot></slot>`;
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
import { localized, msg } from '@lit/localize';
|
||||
import { LitElement, css, html } from 'lit';
|
||||
import { customElement } from 'lit/decorators.js';
|
||||
|
||||
import { notSet } from '../phrases/index.js';
|
||||
import { unit } from '../utils/css.js';
|
||||
import { vars } from '../utils/theme.js';
|
||||
|
||||
const tagName = 'logto-list-row';
|
||||
|
||||
@customElement(tagName)
|
||||
@localized()
|
||||
export class LogtoListRow extends LitElement {
|
||||
static tagName = tagName;
|
||||
static styles = css`
|
||||
:host {
|
||||
box-sizing: border-box;
|
||||
display: grid;
|
||||
height: ${unit(16)};
|
||||
padding: ${unit(2, 6)};
|
||||
grid-template-columns: 1fr 2fr 1fr;
|
||||
align-items: center;
|
||||
color: ${vars.colorTextPrimary};
|
||||
font: ${vars.fontBody2};
|
||||
}
|
||||
|
||||
:host(:not(:last-child)) {
|
||||
border-bottom: 1px solid ${vars.colorLineDivider};
|
||||
}
|
||||
|
||||
slot {
|
||||
display: block;
|
||||
}
|
||||
|
||||
slot[name='title'] {
|
||||
font: ${vars.fontLabel2};
|
||||
}
|
||||
|
||||
slot[name='actions'] {
|
||||
text-align: end;
|
||||
}
|
||||
|
||||
span.not-set {
|
||||
color: ${vars.colorTextSecondary};
|
||||
}
|
||||
`;
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<slot name="title">${msg('Title', { id: 'general.title' })}</slot>
|
||||
<slot name="content"><span class="not-set">${notSet}</span></slot>
|
||||
<slot name="actions">${msg('Actions', { id: 'general.actions' })}</slot>
|
||||
`;
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
import { LitElement, css, html } from 'lit';
|
||||
import { customElement } from 'lit/decorators.js';
|
||||
|
||||
import { unit } from '../utils/css.js';
|
||||
import { vars } from '../utils/theme.js';
|
||||
|
||||
const tagName = 'logto-list';
|
||||
|
||||
@customElement(tagName)
|
||||
export class LogtoList extends LitElement {
|
||||
static tagName = tagName;
|
||||
static styles = css`
|
||||
:host {
|
||||
display: block;
|
||||
border-radius: ${unit(2)};
|
||||
border: 1px solid ${vars.colorLineDivider};
|
||||
}
|
||||
`;
|
||||
|
||||
render() {
|
||||
return html`<slot></slot>`;
|
||||
}
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
import { consume } from '@lit/context';
|
||||
import { localized, msg } from '@lit/localize';
|
||||
import { cond, noop } from '@silverhand/essentials';
|
||||
import { LitElement, html, css } from 'lit';
|
||||
import { customElement, property } from 'lit/decorators.js';
|
||||
|
||||
import closeIcon from '../icons/close.svg';
|
||||
import { unit } from '../utils/css.js';
|
||||
import { vars } from '../utils/theme.js';
|
||||
|
||||
import { ModalContext, type ModalContextType } from './logto-modal.context.js';
|
||||
|
||||
const tagName = 'logto-modal-layout';
|
||||
|
||||
/**
|
||||
* A typical layout for a modal. It includes a header, a footer, and a slot for the content.
|
||||
*
|
||||
* Note: A consumable modal context ({@link ModalContext}) is required to use this component.
|
||||
*/
|
||||
@customElement(tagName)
|
||||
@localized()
|
||||
export class LogtoModalLayout extends LitElement {
|
||||
static tagName = tagName;
|
||||
|
||||
static styles = css`
|
||||
header {
|
||||
font: ${vars.fontTitle1};
|
||||
color: ${vars.colorTextPrimary};
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
margin-bottom: ${unit(6)};
|
||||
}
|
||||
|
||||
h1 {
|
||||
all: unset;
|
||||
}
|
||||
|
||||
footer:not(:empty) {
|
||||
margin-top: ${unit(6)};
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: ${unit(4)};
|
||||
align-items: center;
|
||||
}
|
||||
`;
|
||||
|
||||
@property({ reflect: true })
|
||||
heading = msg('Not set', {
|
||||
id: 'general.fallback-title',
|
||||
desc: 'A fallback title when the title or heading of a component is not provided.',
|
||||
});
|
||||
|
||||
@consume({ context: ModalContext })
|
||||
context?: ModalContextType;
|
||||
|
||||
render() {
|
||||
const { onClose } = this.context ?? {};
|
||||
|
||||
return html`
|
||||
<header>
|
||||
<h1>${this.heading}</h1>
|
||||
${cond(
|
||||
onClose &&
|
||||
onClose !== noop &&
|
||||
html`<logto-icon-button @click=${onClose}>${closeIcon}</logto-icon-button>`
|
||||
)}
|
||||
</header>
|
||||
<slot></slot>
|
||||
<footer>
|
||||
<slot name="footer"></slot>
|
||||
</footer>
|
||||
`;
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
import { createContext } from '@lit/context';
|
||||
import { noop } from '@silverhand/essentials';
|
||||
|
||||
/** @see {@link ModalContext} */
|
||||
export type ModalContextType = { onClose: () => void };
|
||||
|
||||
/**
|
||||
* Context for the modal component. It's useful for operating the modal from deep in the component
|
||||
* tree. For example, closing the modal from a child component.
|
||||
*/
|
||||
export const ModalContext = createContext<ModalContextType>('modal-context');
|
||||
|
||||
/** The default value for the modal context. */
|
||||
export const modalContext: ModalContextType = {
|
||||
onClose: noop,
|
||||
};
|
|
@ -1,88 +0,0 @@
|
|||
import { provide } from '@lit/context';
|
||||
import { noop } from '@silverhand/essentials';
|
||||
import { LitElement, html, css, type PropertyValues } from 'lit';
|
||||
import { customElement, property } from 'lit/decorators.js';
|
||||
import { type Ref, createRef, ref } from 'lit/directives/ref.js';
|
||||
|
||||
import { unit } from '../utils/css.js';
|
||||
import { vars } from '../utils/theme.js';
|
||||
|
||||
import { ModalContext, modalContext } from './logto-modal.context.js';
|
||||
|
||||
const tagName = 'logto-modal';
|
||||
|
||||
@customElement(tagName)
|
||||
export class LogtoModal extends LitElement {
|
||||
static tagName = tagName;
|
||||
|
||||
static styles = css`
|
||||
dialog {
|
||||
padding: 0;
|
||||
border: none;
|
||||
color: ${vars.colorTextPrimary};
|
||||
background: ${vars.colorLayer1};
|
||||
border-radius: ${unit(4)};
|
||||
padding: ${unit(6)};
|
||||
width: 95%;
|
||||
max-width: 600px;
|
||||
min-width: 300px;
|
||||
}
|
||||
|
||||
dialog::backdrop {
|
||||
background-color: ${vars.colorOverlay};
|
||||
}
|
||||
`;
|
||||
|
||||
@property({ type: Boolean, reflect: true })
|
||||
open = false;
|
||||
|
||||
@property()
|
||||
onClose = noop;
|
||||
|
||||
@provide({ context: ModalContext })
|
||||
context = modalContext;
|
||||
|
||||
protected dialogRef: Ref<HTMLDialogElement> = createRef();
|
||||
|
||||
render() {
|
||||
return html`<dialog
|
||||
${ref(this.dialogRef)}
|
||||
@keydown=${(event: KeyboardEvent) => {
|
||||
// The "right" way should be to use the `@cancel` event, but it doesn't always work and the
|
||||
// browser support is unknown. See: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/cancel_event#browser_compatibility
|
||||
if (event.key === 'Escape') {
|
||||
event.preventDefault();
|
||||
this.onClose();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<slot></slot>
|
||||
</dialog> `;
|
||||
}
|
||||
|
||||
protected toggleDialog() {
|
||||
if (this.open) {
|
||||
this.dialogRef.value?.showModal();
|
||||
} else {
|
||||
this.dialogRef.value?.close();
|
||||
}
|
||||
}
|
||||
|
||||
protected handlePropertiesChange(changedProperties: PropertyValues) {
|
||||
if (changedProperties.has('open')) {
|
||||
this.toggleDialog();
|
||||
}
|
||||
|
||||
if (changedProperties.has('onClose')) {
|
||||
this.context.onClose = this.onClose;
|
||||
}
|
||||
}
|
||||
|
||||
protected firstUpdated(changedProperties: PropertyValues): void {
|
||||
this.handlePropertiesChange(changedProperties);
|
||||
}
|
||||
|
||||
protected updated(changedProperties: PropertyValues): void {
|
||||
this.handlePropertiesChange(changedProperties);
|
||||
}
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
import { LitElement, css, html } from 'lit';
|
||||
import { customElement, property, queryAssignedElements } from 'lit/decorators.js';
|
||||
|
||||
import { unit } from '../utils/css.js';
|
||||
import { vars } from '../utils/theme.js';
|
||||
|
||||
const tagName = 'logto-text-input';
|
||||
|
||||
@customElement(tagName)
|
||||
export class LogtoTextInput extends LitElement {
|
||||
static tagName = tagName;
|
||||
static styles = css`
|
||||
:host {
|
||||
display: flex;
|
||||
position: relative;
|
||||
border-radius: ${unit(1.5)};
|
||||
border: 1px solid ${vars.colorBorder};
|
||||
outline: 3px solid transparent;
|
||||
transition-property: outline, border;
|
||||
transition-timing-function: ease-in-out;
|
||||
transition-duration: 0.2s;
|
||||
height: 36px;
|
||||
background: ${vars.colorLayer1};
|
||||
font: ${vars.fontBody2};
|
||||
padding: 0 ${unit(3)};
|
||||
}
|
||||
|
||||
:host(:focus-within) {
|
||||
border-color: ${vars.colorPrimary};
|
||||
outline-color: ${vars.colorFocusedVariant};
|
||||
}
|
||||
|
||||
:host([disabled]) {
|
||||
background: ${vars.colorDisabledBackground};
|
||||
color: ${vars.colorTextSecondary};
|
||||
border-color: ${vars.colorBorder};
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
:host([readonly]) {
|
||||
background: ${vars.colorLayer2};
|
||||
}
|
||||
|
||||
:host([readonly]:focus-within) {
|
||||
border-color: ${vars.colorBorder};
|
||||
outline-color: transparent;
|
||||
}
|
||||
|
||||
::slotted(input) {
|
||||
all: unset;
|
||||
flex: 1;
|
||||
color: ${vars.colorTextPrimary};
|
||||
}
|
||||
|
||||
::slotted(input::placeholder) {
|
||||
color: ${vars.colorPlaceholder};
|
||||
}
|
||||
|
||||
::slotted(input:webkit-autofill) {
|
||||
box-shadow: 0 0 0 ${unit(6)} ${vars.colorLayer1} inset;
|
||||
-webkit-text-fill-color: ${vars.colorTextPrimary};
|
||||
caret-color: ${vars.colorTextPrimary};
|
||||
}
|
||||
`;
|
||||
|
||||
@property({ type: Boolean, reflect: true })
|
||||
disabled = false;
|
||||
|
||||
@property({ type: Boolean, reflect: true })
|
||||
readonly = false;
|
||||
|
||||
@queryAssignedElements({ selector: 'input' })
|
||||
slotInputs!: HTMLInputElement[];
|
||||
|
||||
render() {
|
||||
return html`<slot @slotchange=${this.handleSlotChange}></slot>`;
|
||||
}
|
||||
|
||||
protected handleSlotChange() {
|
||||
if (this.slotInputs[0] && this.slotInputs.length === 1) {
|
||||
this.disabled = this.slotInputs[0].disabled;
|
||||
this.readonly = this.slotInputs[0].readOnly;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,129 +0,0 @@
|
|||
import { consume } from '@lit/context';
|
||||
import { localized, msg } from '@lit/localize';
|
||||
import { cond } from '@silverhand/essentials';
|
||||
import { LitElement, css, html } from 'lit';
|
||||
import { customElement, state } from 'lit/decorators.js';
|
||||
|
||||
import { UserContext, type UserContextType } from '../providers/logto-user-provider.js';
|
||||
import { vars } from '../utils/theme.js';
|
||||
|
||||
const tagName = 'logto-profile-card';
|
||||
|
||||
@customElement(tagName)
|
||||
@localized()
|
||||
export class LogtoProfileCard extends LitElement {
|
||||
static tagName = tagName;
|
||||
static styles = css`
|
||||
p.dev {
|
||||
color: ${vars.colorTextSecondary};
|
||||
}
|
||||
`;
|
||||
|
||||
@consume({ context: UserContext, subscribe: true })
|
||||
userContext?: UserContextType;
|
||||
|
||||
@state()
|
||||
updateNameOpened = false;
|
||||
|
||||
@state()
|
||||
name = '';
|
||||
|
||||
render() {
|
||||
const user = this.userContext?.user;
|
||||
|
||||
if (!user) {
|
||||
return html`<logto-form-card heading=${msg('Profile', { id: 'account.profile.title' })}>
|
||||
<p class="dev">⚠️ ${msg('No user provided.', { id: 'account.profile.no-user' })}</p>
|
||||
</logto-form-card>`;
|
||||
}
|
||||
|
||||
return html`
|
||||
<logto-form-card heading=${msg('Profile', { id: 'account.profile.title' })}>
|
||||
<p class="dev">🚧 This section is a dev feature that is still working in progress.</p>
|
||||
<logto-card-section
|
||||
heading=${msg('Personal information', { id: 'account.profile.personal-info.title' })}
|
||||
>
|
||||
<logto-list>
|
||||
<logto-list-row>
|
||||
<div slot="title">
|
||||
${msg('Avatar', {
|
||||
id: 'account.profile.personal-info.avatar',
|
||||
desc: 'The avatar of the user.',
|
||||
})}
|
||||
</div>
|
||||
${cond(
|
||||
user.avatar &&
|
||||
html`<div slot="content">
|
||||
<logto-avatar size="large" src=${user.avatar}></logto-avatar>
|
||||
</div>`
|
||||
)}
|
||||
<div slot="actions">
|
||||
<logto-button type="text" size="small">
|
||||
${msg('Change', { id: 'general.change' })}
|
||||
</logto-button>
|
||||
</div>
|
||||
</logto-list-row>
|
||||
<logto-list-row>
|
||||
<div slot="title">
|
||||
${msg('Name', {
|
||||
id: 'account.profile.personal-info.name',
|
||||
desc: 'The name of the user.',
|
||||
})}
|
||||
</div>
|
||||
${cond(user.name && html`<div slot="content">${user.name}</div>`)}
|
||||
<div slot="actions">
|
||||
<logto-button
|
||||
type="text"
|
||||
size="small"
|
||||
@click=${() => {
|
||||
this.updateNameOpened = true;
|
||||
this.name = user.name ?? '';
|
||||
}}
|
||||
>
|
||||
${msg('Update', { id: 'general.update' })}
|
||||
</logto-button>
|
||||
</div>
|
||||
</logto-list-row>
|
||||
</logto-list>
|
||||
</logto-card-section>
|
||||
</logto-form-card>
|
||||
<logto-modal
|
||||
?open=${this.updateNameOpened}
|
||||
.onClose=${() => {
|
||||
this.updateNameOpened = false;
|
||||
}}
|
||||
>
|
||||
<logto-modal-layout
|
||||
heading=${msg('Update name', {
|
||||
id: 'account.profile.personal-info.update-name',
|
||||
})}
|
||||
>
|
||||
<logto-text-input>
|
||||
<input
|
||||
placeholder=${msg('Person Doe', {
|
||||
id: 'account.profile.personal-info.name-placeholder',
|
||||
desc: 'The placeholder for the name input field.',
|
||||
})}
|
||||
.value=${this.name}
|
||||
@input=${(event: InputEvent) => {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
this.name = (event.target as HTMLInputElement).value;
|
||||
}}
|
||||
/>
|
||||
</logto-text-input>
|
||||
<logto-button
|
||||
slot="footer"
|
||||
size="large"
|
||||
type="primary"
|
||||
@click=${async () => {
|
||||
await this.userContext?.updateUser({ name: this.name });
|
||||
this.updateNameOpened = false;
|
||||
}}
|
||||
>
|
||||
${msg('Save', { id: 'general.save' })}
|
||||
</logto-button>
|
||||
</logto-modal-layout>
|
||||
</logto-modal>
|
||||
`;
|
||||
}
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M13.4099 12.0002L19.7099 5.71019C19.8982 5.52188 20.004 5.26649 20.004 5.00019C20.004 4.73388 19.8982 4.47849 19.7099 4.29019C19.5216 4.10188 19.2662 3.99609 18.9999 3.99609C18.7336 3.99609 18.4782 4.10188 18.2899 4.29019L11.9999 10.5902L5.70994 4.29019C5.52164 4.10188 5.26624 3.99609 4.99994 3.99609C4.73364 3.99609 4.47824 4.10188 4.28994 4.29019C4.10164 4.47849 3.99585 4.73388 3.99585 5.00019C3.99585 5.26649 4.10164 5.52188 4.28994 5.71019L10.5899 12.0002L4.28994 18.2902C4.19621 18.3831 4.12182 18.4937 4.07105 18.6156C4.02028 18.7375 3.99414 18.8682 3.99414 19.0002C3.99414 19.1322 4.02028 19.2629 4.07105 19.3848C4.12182 19.5066 4.19621 19.6172 4.28994 19.7102C4.3829 19.8039 4.4935 19.8783 4.61536 19.9291C4.73722 19.9798 4.86793 20.006 4.99994 20.006C5.13195 20.006 5.26266 19.9798 5.38452 19.9291C5.50638 19.8783 5.61698 19.8039 5.70994 19.7102L11.9999 13.4102L18.2899 19.7102C18.3829 19.8039 18.4935 19.8783 18.6154 19.9291C18.7372 19.9798 18.8679 20.006 18.9999 20.006C19.132 20.006 19.2627 19.9798 19.3845 19.9291C19.5064 19.8783 19.617 19.8039 19.7099 19.7102C19.8037 19.6172 19.8781 19.5066 19.9288 19.3848C19.9796 19.2629 20.0057 19.1322 20.0057 19.0002C20.0057 18.8682 19.9796 18.7375 19.9288 18.6156C19.8781 18.4937 19.8037 18.3831 19.7099 18.2902L13.4099 12.0002Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
Before Width: | Height: | Size: 1.4 KiB |
4
packages/elements/src/icons/index.d.ts
vendored
4
packages/elements/src/icons/index.d.ts
vendored
|
@ -1,4 +0,0 @@
|
|||
declare module '*.svg' {
|
||||
const value: string;
|
||||
export default value;
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
export * from './components/logto-avatar.js';
|
||||
export * from './components/logto-button.js';
|
||||
export * from './components/logto-card-section.js';
|
||||
export * from './components/logto-card.js';
|
||||
export * from './components/logto-form-card.js';
|
||||
export * from './components/logto-icon-button.js';
|
||||
export * from './components/logto-list-row.js';
|
||||
export * from './components/logto-list.js';
|
||||
export * from './components/logto-modal-layout.js';
|
||||
export * from './components/logto-modal.js';
|
||||
export * from './components/logto-text-input.js';
|
||||
export * from './elements/logto-profile-card.js';
|
||||
|
||||
export * from './providers/logto-theme-provider.js';
|
||||
export * from './providers/logto-user-provider.js';
|
||||
|
||||
export * from './utils/api.js';
|
||||
export * from './utils/locale.js';
|
|
@ -1,6 +0,0 @@
|
|||
import { msg } from '@lit/localize';
|
||||
|
||||
export const notSet = msg('Not set', {
|
||||
id: 'general.fallback-title',
|
||||
desc: 'A fallback title when the title or heading of a component is not provided.',
|
||||
});
|
|
@ -1,22 +0,0 @@
|
|||
import { LitElement, css, html } from 'lit';
|
||||
import { customElement, property } from 'lit/decorators.js';
|
||||
|
||||
import { defaultTheme, darkTheme, toLitCss } from '../utils/theme.js';
|
||||
|
||||
const tagName = 'logto-theme-provider';
|
||||
|
||||
@customElement(tagName)
|
||||
export class LogtoThemeProvider extends LitElement {
|
||||
static tagName = tagName;
|
||||
static styles = css`
|
||||
${toLitCss(defaultTheme)}
|
||||
${toLitCss(darkTheme, 'dark')}
|
||||
`;
|
||||
|
||||
@property({ reflect: true })
|
||||
theme: 'default' | 'dark' = 'default';
|
||||
|
||||
render() {
|
||||
return html`<slot></slot>`;
|
||||
}
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
import { createContext, provide } from '@lit/context';
|
||||
import { type UserInfo } from '@logto/schemas';
|
||||
import { noop } from '@silverhand/essentials';
|
||||
import { LitElement, type PropertyValues, html } from 'lit';
|
||||
import { customElement, property } from 'lit/decorators.js';
|
||||
|
||||
import { LogtoAccountApi } from '../utils/api.js';
|
||||
|
||||
/** @see {@link UserContext} */
|
||||
export type UserContextType = Readonly<{
|
||||
user?: UserInfo;
|
||||
updateUser: (user: Partial<UserInfo>) => void | Promise<void>;
|
||||
}>;
|
||||
|
||||
/**
|
||||
* Context for the current user. It's a fundamental context for the account-related elements.
|
||||
*/
|
||||
export const UserContext = createContext<UserContextType>('user-context');
|
||||
|
||||
/** The default value for the user context. */
|
||||
export const userContext: UserContextType = Object.freeze({
|
||||
updateUser: noop,
|
||||
});
|
||||
|
||||
const tagName = 'logto-user-provider';
|
||||
|
||||
@customElement(tagName)
|
||||
export class LogtoUserProvider extends LitElement {
|
||||
static tagName = tagName;
|
||||
|
||||
@provide({ context: UserContext })
|
||||
context = userContext;
|
||||
|
||||
@property({ type: Object })
|
||||
api!: LogtoAccountApi | ConstructorParameters<typeof LogtoAccountApi>[0];
|
||||
|
||||
render() {
|
||||
return html`<slot></slot>`;
|
||||
}
|
||||
|
||||
protected updateContext(context: Partial<UserContextType>) {
|
||||
this.context = Object.freeze({ ...this.context, ...context });
|
||||
}
|
||||
|
||||
protected async handlePropertiesChange(changedProperties: PropertyValues) {
|
||||
if (changedProperties.has('api')) {
|
||||
const api = this.api instanceof LogtoAccountApi ? this.api : new LogtoAccountApi(this.api);
|
||||
this.updateContext({
|
||||
updateUser: async (user) => {
|
||||
const updated = await api.updateUser(user);
|
||||
this.updateContext({ user: updated });
|
||||
},
|
||||
user: await api.getUser(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected firstUpdated(changedProperties: PropertyValues): void {
|
||||
void this.handlePropertiesChange(changedProperties);
|
||||
}
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
import { createComponent } from '@lit/react';
|
||||
|
||||
import {
|
||||
LogtoThemeProvider,
|
||||
LogtoCard,
|
||||
LogtoFormCard,
|
||||
LogtoProfileCard,
|
||||
LogtoList,
|
||||
LogtoUserProvider,
|
||||
} from './index.js';
|
||||
|
||||
export * from './utils/locale.js';
|
||||
export * from './utils/api.js';
|
||||
|
||||
export const createReactComponents = (react: Parameters<typeof createComponent>[0]['react']) => {
|
||||
return {
|
||||
LogtoFormCard: createComponent({
|
||||
tagName: LogtoFormCard.tagName,
|
||||
elementClass: LogtoFormCard,
|
||||
react,
|
||||
}),
|
||||
LogtoList: createComponent({
|
||||
tagName: LogtoList.tagName,
|
||||
elementClass: LogtoList,
|
||||
react,
|
||||
}),
|
||||
LogtoProfileCard: createComponent({
|
||||
tagName: LogtoProfileCard.tagName,
|
||||
elementClass: LogtoProfileCard,
|
||||
react,
|
||||
}),
|
||||
LogtoCard: createComponent({
|
||||
tagName: LogtoCard.tagName,
|
||||
elementClass: LogtoCard,
|
||||
react,
|
||||
}),
|
||||
LogtoThemeProvider: createComponent({
|
||||
tagName: LogtoThemeProvider.tagName,
|
||||
elementClass: LogtoThemeProvider,
|
||||
react,
|
||||
}),
|
||||
LogtoUserProvider: createComponent({
|
||||
tagName: LogtoUserProvider.tagName,
|
||||
elementClass: LogtoUserProvider,
|
||||
react,
|
||||
}),
|
||||
};
|
||||
};
|
|
@ -1,22 +0,0 @@
|
|||
import { type UserInfo } from '@logto/schemas';
|
||||
import originalKy, { type Options, type KyInstance } from 'ky';
|
||||
|
||||
/**
|
||||
* CAUTION: The current implementation is based on the admin tenant's `/me` API which is interim.
|
||||
* The final implementation should be based on the Account API.
|
||||
*/
|
||||
export class LogtoAccountApi {
|
||||
protected ky: KyInstance;
|
||||
|
||||
constructor(init: KyInstance | Options) {
|
||||
this.ky = 'create' in init ? init : originalKy.create(init);
|
||||
}
|
||||
|
||||
async getUser() {
|
||||
return this.ky('me').json<UserInfo>();
|
||||
}
|
||||
|
||||
async updateUser(user: Partial<UserInfo>) {
|
||||
return this.ky.patch('me', { json: user }).json<UserInfo>();
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
import { type CSSResult, unsafeCSS } from 'lit';
|
||||
|
||||
type Unit = {
|
||||
/**
|
||||
* @example unit(1) // '4px'
|
||||
*/
|
||||
(value: number): CSSResult;
|
||||
/**
|
||||
* @example unit(1, 2) // '4px 8px'
|
||||
*/
|
||||
(value1: number, value2: number): CSSResult;
|
||||
/**
|
||||
* @example unit(1, 2, 3) // '4px 8px 12px'
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/unified-signatures -- for better readability
|
||||
(value1: number, value2: number, value3: number): CSSResult;
|
||||
/**
|
||||
* @example unit(1, 2, 3, 4) // '4px 8px 12px 16px'
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/unified-signatures -- for better readability
|
||||
(value1: number, value2: number, value3: number, value4: number): CSSResult;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a `CSSResult` that represents the given values in pixels. The values are multiplied by 4.
|
||||
*/
|
||||
export const unit: Unit = (...values: number[]) => {
|
||||
if (values.length === 0 || values.length > 4) {
|
||||
throw new Error('unit() accepts 1 to 4 arguments');
|
||||
}
|
||||
|
||||
if (values.some((value) => typeof value !== 'number')) {
|
||||
throw new Error('unit() accepts only numbers');
|
||||
}
|
||||
|
||||
return unsafeCSS(values.map((value) => `${value * 4}px`).join(' '));
|
||||
};
|
|
@ -1,11 +0,0 @@
|
|||
import { configureLocalization } from '@lit/localize';
|
||||
|
||||
// Generated via output.localeCodesModule
|
||||
import { sourceLocale, targetLocales } from '../generated/locale-codes.js';
|
||||
|
||||
export const initLocalization = () =>
|
||||
configureLocalization({
|
||||
sourceLocale,
|
||||
targetLocales,
|
||||
loadLocale: async (locale) => import(`/locales/${locale}.js`),
|
||||
});
|
|
@ -1,19 +0,0 @@
|
|||
export type KebabCase<T extends string> = T extends `${infer L}${infer M}${infer R}`
|
||||
? L extends Lowercase<L>
|
||||
? M extends Lowercase<M>
|
||||
? `${L}${KebabCase<`${M}${R}`>}`
|
||||
: `${L}-${KebabCase<`${M}${R}`>}`
|
||||
: M extends Lowercase<M>
|
||||
? `${Lowercase<L>}${KebabCase<`${M}${R}`>}`
|
||||
: R extends Uncapitalize<R>
|
||||
? `${Lowercase<L>}-${Lowercase<M>}${KebabCase<R>}`
|
||||
: `${Lowercase<L>}${KebabCase<`${M}${R}`>}`
|
||||
: T;
|
||||
|
||||
export const kebabCase = <T extends string>(value: T): KebabCase<T> => {
|
||||
// eslint-disable-next-line no-restricted-syntax -- `as` assertion is needed to make TS happy
|
||||
return value
|
||||
.replaceAll(/([^A-Z])([A-Z])/g, '$1-$2')
|
||||
.replaceAll(/([A-Z])([A-Z][^A-Z])/g, '$1-$2')
|
||||
.toLowerCase() as KebabCase<T>;
|
||||
};
|
|
@ -1,174 +0,0 @@
|
|||
import { type CSSResult, unsafeCSS } from 'lit';
|
||||
|
||||
import { type KebabCase, kebabCase } from './string.js';
|
||||
|
||||
/** All the colors to be used in the Logto components and elements. */
|
||||
export type Color = {
|
||||
colorPrimary: string;
|
||||
colorOnPrimary: string;
|
||||
colorPrimaryPressed: string;
|
||||
colorPrimaryHover: string;
|
||||
colorTextPrimary: string;
|
||||
colorTextLink: string;
|
||||
colorTextSecondary: string;
|
||||
colorBorder: string;
|
||||
colorCardTitle: string;
|
||||
colorLayer1: string;
|
||||
colorLayer2: string;
|
||||
colorLineDivider: string;
|
||||
colorDisabled: string;
|
||||
colorDisabledBackground: string;
|
||||
colorHover: string;
|
||||
colorHoverVariant: string;
|
||||
colorPressed: string;
|
||||
colorFocused: string;
|
||||
colorFocusedVariant: string;
|
||||
colorOverlay: string;
|
||||
colorPlaceholder: string;
|
||||
};
|
||||
|
||||
/** All the fonts to be used in the Logto components and elements. */
|
||||
export type Font = {
|
||||
fontTitle1: string;
|
||||
fontTitle2: string;
|
||||
fontTitle3: string;
|
||||
fontLabel1: string;
|
||||
fontLabel2: string;
|
||||
fontLabel3: string;
|
||||
fontBody1: string;
|
||||
fontBody2: string;
|
||||
fontBody3: string;
|
||||
fontSectionHeading1: string;
|
||||
fontSectionHeading2: string;
|
||||
};
|
||||
|
||||
/** The complete styling properties to be used in the Logto components and elements. */
|
||||
export type Theme = Color & Font;
|
||||
|
||||
export const defaultFontFamily =
|
||||
'-apple-system, system-ui, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Helvetica, Arial, sans-serif, Apple Color Emoji';
|
||||
|
||||
export const defaultFont: Readonly<Font> = Object.freeze({
|
||||
fontTitle1: `600 20px / 28px ${defaultFontFamily}`,
|
||||
fontTitle2: `600 16px / 24px ${defaultFontFamily}`,
|
||||
fontTitle3: `600 14px / 20px ${defaultFontFamily}`,
|
||||
fontLabel1: `500 16px / 24px ${defaultFontFamily}`,
|
||||
fontLabel2: `500 14px / 20px ${defaultFontFamily}`,
|
||||
fontLabel3: `500 12px / 16px ${defaultFontFamily}`,
|
||||
fontBody1: `400 16px / 24px ${defaultFontFamily}`,
|
||||
fontBody2: `400 14px / 20px ${defaultFontFamily}`,
|
||||
fontBody3: `400 12px / 16px ${defaultFontFamily}`,
|
||||
fontSectionHeading1: `700 12px / 16px ${defaultFontFamily}`,
|
||||
fontSectionHeading2: `700 10px / 16px ${defaultFontFamily}`,
|
||||
});
|
||||
|
||||
export const defaultTheme: Readonly<Theme> = Object.freeze({
|
||||
...defaultFont,
|
||||
colorPrimary: '#5d34f2',
|
||||
colorOnPrimary: '#000',
|
||||
colorPrimaryPressed: '#e6deff',
|
||||
colorPrimaryHover: '#af9eff',
|
||||
colorTextPrimary: '#191c1d',
|
||||
colorTextLink: '#5d34f2',
|
||||
colorTextSecondary: '#747778',
|
||||
colorBorder: '#c4c7c7',
|
||||
colorCardTitle: '#928f9a',
|
||||
colorLayer1: '#000',
|
||||
colorLayer2: '#2d3132',
|
||||
colorLineDivider: '#191c1d1f',
|
||||
colorDisabled: '#5c5f60',
|
||||
colorDisabledBackground: '#2d3132',
|
||||
colorHover: '#191c1d14',
|
||||
colorHoverVariant: '#5d34f214',
|
||||
colorPressed: 'rgba(25, 28, 29, 12%)',
|
||||
colorFocused: 'rgba(25, 28, 29, 16%)',
|
||||
colorFocusedVariant: '#5d34f229',
|
||||
colorOverlay: '#000000b3',
|
||||
colorPlaceholder: '#747778',
|
||||
});
|
||||
|
||||
export const darkTheme: Readonly<Theme> = Object.freeze({
|
||||
...defaultFont,
|
||||
colorPrimary: '#7958ff',
|
||||
colorOnPrimary: '#fff',
|
||||
colorPrimaryPressed: '#5d34f2',
|
||||
colorPrimaryHover: '#947dff',
|
||||
colorTextPrimary: '#f7f8f8',
|
||||
colorTextLink: '#cabeff',
|
||||
colorTextSecondary: '#a9acac',
|
||||
colorBorder: '#5c5f60',
|
||||
colorCardTitle: '#928f9a',
|
||||
colorLayer1: '#2a2c32',
|
||||
colorLayer2: '#34353f',
|
||||
colorLineDivider: '#f7f8f824',
|
||||
colorDisabled: '#5c5f60',
|
||||
colorDisabledBackground: '#2d3132',
|
||||
colorHover: '#f7f8f814',
|
||||
colorHoverVariant: '#cabeff14',
|
||||
colorPressed: 'rgba(247, 248, 248, 12%)',
|
||||
colorFocused: 'rgba(247, 248, 248, 16%)',
|
||||
colorFocusedVariant: '#cabeff29',
|
||||
colorOverlay: '#0000003c',
|
||||
colorPlaceholder: '#747778',
|
||||
});
|
||||
|
||||
/**
|
||||
* Converts the theme object to a list of CSS custom properties entries. Each key is prefixed
|
||||
* with `--logto-`.
|
||||
*
|
||||
* @example
|
||||
* toLogtoCssEntries(defaultTheme) // [['--logto-color-primary', '#5d34f2'], ...]
|
||||
*/
|
||||
export const toLogtoCssEntries = (theme: Theme) =>
|
||||
Object.entries(theme).map(([key, value]) =>
|
||||
Object.freeze([`--logto-${kebabCase(key)}`, value] as const)
|
||||
);
|
||||
|
||||
export type ToLogtoCssProperties<T extends Record<string, unknown>> = {
|
||||
[K in keyof T as K extends string ? `--logto-${KebabCase<K>}` : never]: T[K];
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts the theme object to a map of CSS custom properties. Each key is prefixed with
|
||||
* `--logto-`.
|
||||
*
|
||||
* @example
|
||||
* toLogtoCssProperties(defaultTheme) // { '--logto-color-primary': '#5d34f2', ... }
|
||||
*/
|
||||
export const toLogtoCssProperties = (theme: Theme): ToLogtoCssProperties<Theme> => {
|
||||
// eslint-disable-next-line no-restricted-syntax -- `Object.fromEntries` will lose the type
|
||||
return Object.fromEntries(toLogtoCssEntries(theme)) as ToLogtoCssProperties<Theme>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts the given value to a logto CSS custom property prefixed with `--logto-`.
|
||||
*
|
||||
* @example
|
||||
* toVar('colorPrimary') // '--logto-color-primary' in `CSSResult`
|
||||
*/
|
||||
export const toVar = (value: string) => unsafeCSS(`var(--logto-${kebabCase(value)})`);
|
||||
|
||||
/**
|
||||
* The CSS custom properties in `CSSResult` format for a theme object. You can use this object
|
||||
* to apply a custom property from the theme.
|
||||
*
|
||||
* @example
|
||||
* css`
|
||||
* p {
|
||||
* color: ${vars.colorPrimary};
|
||||
* }
|
||||
* `
|
||||
*/
|
||||
// eslint-disable-next-line no-restricted-syntax -- `Object.fromEntries` will lose the type
|
||||
export const vars: Record<keyof Theme, CSSResult> = Object.freeze(
|
||||
Object.fromEntries(Object.keys(defaultTheme).map((key) => [key, toVar(key)]))
|
||||
) as Record<keyof Theme, CSSResult>;
|
||||
|
||||
export const toLitCss = (theme: Theme, name?: string) =>
|
||||
unsafeCSS(
|
||||
`:host${typeof name === 'string' ? `([theme=${name}])` : ''} {\n` +
|
||||
toLogtoCssEntries(theme)
|
||||
.map(([key, value]) => `${key}: ${value};`)
|
||||
.join('\n') +
|
||||
'\n}'
|
||||
);
|
|
@ -3,7 +3,10 @@ import fs from 'node:fs/promises';
|
|||
import { defineConfig } from 'tsup';
|
||||
|
||||
export default defineConfig({
|
||||
entry: ['src/index.ts', 'src/react.ts'],
|
||||
entry: {
|
||||
'account/index': 'src/account/index.ts',
|
||||
'account/react': 'src/account/react.ts',
|
||||
},
|
||||
format: 'esm',
|
||||
dts: true,
|
||||
clean: true,
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<file target-language="ar-AR" source-language="en" original="lit-localize-inputs" datatype="plaintext">
|
||||
<body>
|
||||
<trans-unit id="general.title">
|
||||
<source>Title</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.actions">
|
||||
<source>Actions</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.title">
|
||||
<source>Profile</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.no-user">
|
||||
<source>No user provided.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.title">
|
||||
<source>Personal information</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.change">
|
||||
<source>Change</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.update">
|
||||
<source>Update</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.update-name">
|
||||
<source>Update name</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.save">
|
||||
<source>Save</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.fallback-title">
|
||||
<source>Not set</source>
|
||||
<note from="lit-localize">A fallback title when the title or heading of a component is not provided.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.avatar">
|
||||
<source>Avatar</source>
|
||||
<note from="lit-localize">The avatar of the user.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.name">
|
||||
<source>Name</source>
|
||||
<note from="lit-localize">The name of the user.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.name-placeholder">
|
||||
<source>Person Doe</source>
|
||||
<note from="lit-localize">The placeholder for the name input field.</note>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
|
@ -1,50 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<file target-language="de" source-language="en" original="lit-localize-inputs" datatype="plaintext">
|
||||
<body>
|
||||
<trans-unit id="general.title">
|
||||
<source>Title</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.actions">
|
||||
<source>Actions</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.title">
|
||||
<source>Profile</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.title">
|
||||
<source>Personal information</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.change">
|
||||
<source>Change</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.update">
|
||||
<source>Update</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.update-name">
|
||||
<source>Update name</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.fallback-title">
|
||||
<source>Not set</source>
|
||||
<note from="lit-localize">A fallback title when the title or heading of a component is not provided.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.avatar">
|
||||
<source>Avatar</source>
|
||||
<note from="lit-localize">The avatar of the user.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.name">
|
||||
<source>Name</source>
|
||||
<note from="lit-localize">The name of the user.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.name-placeholder">
|
||||
<source>Person Doe</source>
|
||||
<note from="lit-localize">The placeholder for the name input field.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.no-user">
|
||||
<source>No user provided.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.save">
|
||||
<source>Save</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
|
@ -1,50 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<file target-language="es" source-language="en" original="lit-localize-inputs" datatype="plaintext">
|
||||
<body>
|
||||
<trans-unit id="general.title">
|
||||
<source>Title</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.actions">
|
||||
<source>Actions</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.title">
|
||||
<source>Profile</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.title">
|
||||
<source>Personal information</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.change">
|
||||
<source>Change</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.update">
|
||||
<source>Update</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.update-name">
|
||||
<source>Update name</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.fallback-title">
|
||||
<source>Not set</source>
|
||||
<note from="lit-localize">A fallback title when the title or heading of a component is not provided.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.avatar">
|
||||
<source>Avatar</source>
|
||||
<note from="lit-localize">The avatar of the user.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.name">
|
||||
<source>Name</source>
|
||||
<note from="lit-localize">The name of the user.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.name-placeholder">
|
||||
<source>Person Doe</source>
|
||||
<note from="lit-localize">The placeholder for the name input field.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.no-user">
|
||||
<source>No user provided.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.save">
|
||||
<source>Save</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
|
@ -1,50 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<file target-language="fr" source-language="en" original="lit-localize-inputs" datatype="plaintext">
|
||||
<body>
|
||||
<trans-unit id="general.title">
|
||||
<source>Title</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.actions">
|
||||
<source>Actions</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.title">
|
||||
<source>Profile</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.title">
|
||||
<source>Personal information</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.change">
|
||||
<source>Change</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.update">
|
||||
<source>Update</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.update-name">
|
||||
<source>Update name</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.fallback-title">
|
||||
<source>Not set</source>
|
||||
<note from="lit-localize">A fallback title when the title or heading of a component is not provided.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.avatar">
|
||||
<source>Avatar</source>
|
||||
<note from="lit-localize">The avatar of the user.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.name">
|
||||
<source>Name</source>
|
||||
<note from="lit-localize">The name of the user.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.name-placeholder">
|
||||
<source>Person Doe</source>
|
||||
<note from="lit-localize">The placeholder for the name input field.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.no-user">
|
||||
<source>No user provided.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.save">
|
||||
<source>Save</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
|
@ -1,50 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<file target-language="it" source-language="en" original="lit-localize-inputs" datatype="plaintext">
|
||||
<body>
|
||||
<trans-unit id="general.title">
|
||||
<source>Title</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.actions">
|
||||
<source>Actions</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.title">
|
||||
<source>Profile</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.title">
|
||||
<source>Personal information</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.change">
|
||||
<source>Change</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.update">
|
||||
<source>Update</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.update-name">
|
||||
<source>Update name</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.fallback-title">
|
||||
<source>Not set</source>
|
||||
<note from="lit-localize">A fallback title when the title or heading of a component is not provided.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.avatar">
|
||||
<source>Avatar</source>
|
||||
<note from="lit-localize">The avatar of the user.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.name">
|
||||
<source>Name</source>
|
||||
<note from="lit-localize">The name of the user.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.name-placeholder">
|
||||
<source>Person Doe</source>
|
||||
<note from="lit-localize">The placeholder for the name input field.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.no-user">
|
||||
<source>No user provided.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.save">
|
||||
<source>Save</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
|
@ -1,50 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<file target-language="ja" source-language="en" original="lit-localize-inputs" datatype="plaintext">
|
||||
<body>
|
||||
<trans-unit id="general.title">
|
||||
<source>Title</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.actions">
|
||||
<source>Actions</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.title">
|
||||
<source>Profile</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.title">
|
||||
<source>Personal information</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.change">
|
||||
<source>Change</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.update">
|
||||
<source>Update</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.update-name">
|
||||
<source>Update name</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.fallback-title">
|
||||
<source>Not set</source>
|
||||
<note from="lit-localize">A fallback title when the title or heading of a component is not provided.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.avatar">
|
||||
<source>Avatar</source>
|
||||
<note from="lit-localize">The avatar of the user.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.name">
|
||||
<source>Name</source>
|
||||
<note from="lit-localize">The name of the user.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.name-placeholder">
|
||||
<source>Person Doe</source>
|
||||
<note from="lit-localize">The placeholder for the name input field.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.no-user">
|
||||
<source>No user provided.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.save">
|
||||
<source>Save</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
|
@ -1,50 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<file target-language="ko" source-language="en" original="lit-localize-inputs" datatype="plaintext">
|
||||
<body>
|
||||
<trans-unit id="general.title">
|
||||
<source>Title</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.actions">
|
||||
<source>Actions</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.title">
|
||||
<source>Profile</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.title">
|
||||
<source>Personal information</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.change">
|
||||
<source>Change</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.update">
|
||||
<source>Update</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.update-name">
|
||||
<source>Update name</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.fallback-title">
|
||||
<source>Not set</source>
|
||||
<note from="lit-localize">A fallback title when the title or heading of a component is not provided.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.avatar">
|
||||
<source>Avatar</source>
|
||||
<note from="lit-localize">The avatar of the user.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.name">
|
||||
<source>Name</source>
|
||||
<note from="lit-localize">The name of the user.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.name-placeholder">
|
||||
<source>Person Doe</source>
|
||||
<note from="lit-localize">The placeholder for the name input field.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.no-user">
|
||||
<source>No user provided.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.save">
|
||||
<source>Save</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
|
@ -1,50 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<file target-language="pl-PL" source-language="en" original="lit-localize-inputs" datatype="plaintext">
|
||||
<body>
|
||||
<trans-unit id="general.title">
|
||||
<source>Title</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.actions">
|
||||
<source>Actions</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.title">
|
||||
<source>Profile</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.title">
|
||||
<source>Personal information</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.change">
|
||||
<source>Change</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.update">
|
||||
<source>Update</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.update-name">
|
||||
<source>Update name</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.fallback-title">
|
||||
<source>Not set</source>
|
||||
<note from="lit-localize">A fallback title when the title or heading of a component is not provided.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.avatar">
|
||||
<source>Avatar</source>
|
||||
<note from="lit-localize">The avatar of the user.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.name">
|
||||
<source>Name</source>
|
||||
<note from="lit-localize">The name of the user.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.name-placeholder">
|
||||
<source>Person Doe</source>
|
||||
<note from="lit-localize">The placeholder for the name input field.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.no-user">
|
||||
<source>No user provided.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.save">
|
||||
<source>Save</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
|
@ -1,50 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<file target-language="pt-BR" source-language="en" original="lit-localize-inputs" datatype="plaintext">
|
||||
<body>
|
||||
<trans-unit id="general.title">
|
||||
<source>Title</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.actions">
|
||||
<source>Actions</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.title">
|
||||
<source>Profile</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.title">
|
||||
<source>Personal information</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.change">
|
||||
<source>Change</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.update">
|
||||
<source>Update</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.update-name">
|
||||
<source>Update name</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.fallback-title">
|
||||
<source>Not set</source>
|
||||
<note from="lit-localize">A fallback title when the title or heading of a component is not provided.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.avatar">
|
||||
<source>Avatar</source>
|
||||
<note from="lit-localize">The avatar of the user.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.name">
|
||||
<source>Name</source>
|
||||
<note from="lit-localize">The name of the user.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.name-placeholder">
|
||||
<source>Person Doe</source>
|
||||
<note from="lit-localize">The placeholder for the name input field.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.no-user">
|
||||
<source>No user provided.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.save">
|
||||
<source>Save</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
|
@ -1,50 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<file target-language="pt-PT" source-language="en" original="lit-localize-inputs" datatype="plaintext">
|
||||
<body>
|
||||
<trans-unit id="general.title">
|
||||
<source>Title</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.actions">
|
||||
<source>Actions</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.title">
|
||||
<source>Profile</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.title">
|
||||
<source>Personal information</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.change">
|
||||
<source>Change</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.update">
|
||||
<source>Update</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.update-name">
|
||||
<source>Update name</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.fallback-title">
|
||||
<source>Not set</source>
|
||||
<note from="lit-localize">A fallback title when the title or heading of a component is not provided.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.avatar">
|
||||
<source>Avatar</source>
|
||||
<note from="lit-localize">The avatar of the user.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.name">
|
||||
<source>Name</source>
|
||||
<note from="lit-localize">The name of the user.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.name-placeholder">
|
||||
<source>Person Doe</source>
|
||||
<note from="lit-localize">The placeholder for the name input field.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.no-user">
|
||||
<source>No user provided.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.save">
|
||||
<source>Save</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
|
@ -1,50 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<file target-language="ru" source-language="en" original="lit-localize-inputs" datatype="plaintext">
|
||||
<body>
|
||||
<trans-unit id="general.title">
|
||||
<source>Title</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.actions">
|
||||
<source>Actions</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.title">
|
||||
<source>Profile</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.title">
|
||||
<source>Personal information</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.change">
|
||||
<source>Change</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.update">
|
||||
<source>Update</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.update-name">
|
||||
<source>Update name</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.fallback-title">
|
||||
<source>Not set</source>
|
||||
<note from="lit-localize">A fallback title when the title or heading of a component is not provided.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.avatar">
|
||||
<source>Avatar</source>
|
||||
<note from="lit-localize">The avatar of the user.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.name">
|
||||
<source>Name</source>
|
||||
<note from="lit-localize">The name of the user.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.name-placeholder">
|
||||
<source>Person Doe</source>
|
||||
<note from="lit-localize">The placeholder for the name input field.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.no-user">
|
||||
<source>No user provided.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.save">
|
||||
<source>Save</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
|
@ -1,50 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<file target-language="tr-TR" source-language="en" original="lit-localize-inputs" datatype="plaintext">
|
||||
<body>
|
||||
<trans-unit id="general.title">
|
||||
<source>Title</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.actions">
|
||||
<source>Actions</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.title">
|
||||
<source>Profile</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.title">
|
||||
<source>Personal information</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.change">
|
||||
<source>Change</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.update">
|
||||
<source>Update</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.update-name">
|
||||
<source>Update name</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.fallback-title">
|
||||
<source>Not set</source>
|
||||
<note from="lit-localize">A fallback title when the title or heading of a component is not provided.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.avatar">
|
||||
<source>Avatar</source>
|
||||
<note from="lit-localize">The avatar of the user.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.name">
|
||||
<source>Name</source>
|
||||
<note from="lit-localize">The name of the user.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.name-placeholder">
|
||||
<source>Person Doe</source>
|
||||
<note from="lit-localize">The placeholder for the name input field.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.no-user">
|
||||
<source>No user provided.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.save">
|
||||
<source>Save</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
|
@ -1,50 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<file target-language="zh-CN" source-language="en" original="lit-localize-inputs" datatype="plaintext">
|
||||
<body>
|
||||
<trans-unit id="general.title">
|
||||
<source>Title</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.actions">
|
||||
<source>Actions</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.title">
|
||||
<source>Profile</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.title">
|
||||
<source>Personal information</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.change">
|
||||
<source>Change</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.update">
|
||||
<source>Update</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.update-name">
|
||||
<source>Update name</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.fallback-title">
|
||||
<source>Not set</source>
|
||||
<note from="lit-localize">A fallback title when the title or heading of a component is not provided.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.avatar">
|
||||
<source>Avatar</source>
|
||||
<note from="lit-localize">The avatar of the user.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.name">
|
||||
<source>Name</source>
|
||||
<note from="lit-localize">The name of the user.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.name-placeholder">
|
||||
<source>Person Doe</source>
|
||||
<note from="lit-localize">The placeholder for the name input field.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.no-user">
|
||||
<source>No user provided.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.save">
|
||||
<source>Save</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
|
@ -1,50 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<file target-language="zh-HK" source-language="en" original="lit-localize-inputs" datatype="plaintext">
|
||||
<body>
|
||||
<trans-unit id="general.title">
|
||||
<source>Title</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.actions">
|
||||
<source>Actions</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.title">
|
||||
<source>Profile</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.title">
|
||||
<source>Personal information</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.change">
|
||||
<source>Change</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.update">
|
||||
<source>Update</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.update-name">
|
||||
<source>Update name</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.fallback-title">
|
||||
<source>Not set</source>
|
||||
<note from="lit-localize">A fallback title when the title or heading of a component is not provided.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.avatar">
|
||||
<source>Avatar</source>
|
||||
<note from="lit-localize">The avatar of the user.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.name">
|
||||
<source>Name</source>
|
||||
<note from="lit-localize">The name of the user.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.name-placeholder">
|
||||
<source>Person Doe</source>
|
||||
<note from="lit-localize">The placeholder for the name input field.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.no-user">
|
||||
<source>No user provided.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.save">
|
||||
<source>Save</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
|
@ -1,50 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<file target-language="zh-TW" source-language="en" original="lit-localize-inputs" datatype="plaintext">
|
||||
<body>
|
||||
<trans-unit id="general.title">
|
||||
<source>Title</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.actions">
|
||||
<source>Actions</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.title">
|
||||
<source>Profile</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.title">
|
||||
<source>Personal information</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.change">
|
||||
<source>Change</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.update">
|
||||
<source>Update</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.update-name">
|
||||
<source>Update name</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.fallback-title">
|
||||
<source>Not set</source>
|
||||
<note from="lit-localize">A fallback title when the title or heading of a component is not provided.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.avatar">
|
||||
<source>Avatar</source>
|
||||
<note from="lit-localize">The avatar of the user.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.name">
|
||||
<source>Name</source>
|
||||
<note from="lit-localize">The name of the user.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.personal-info.name-placeholder">
|
||||
<source>Person Doe</source>
|
||||
<note from="lit-localize">The placeholder for the name input field.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="account.profile.no-user">
|
||||
<source>No user provided.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="general.save">
|
||||
<source>Save</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
|
@ -2738,9 +2738,6 @@ importers:
|
|||
'@logto/core-kit':
|
||||
specifier: workspace:^2.5.0
|
||||
version: link:../toolkit/core-kit
|
||||
'@logto/elements':
|
||||
specifier: workspace:^0.0.1
|
||||
version: link:../elements
|
||||
'@logto/language-kit':
|
||||
specifier: workspace:^1.1.0
|
||||
version: link:../toolkit/language-kit
|
||||
|
@ -16064,10 +16061,10 @@ snapshots:
|
|||
eslint-config-prettier: 9.1.0(eslint@8.57.0)
|
||||
eslint-config-xo: 0.44.0(eslint@8.57.0)
|
||||
eslint-config-xo-typescript: 4.0.0(@typescript-eslint/eslint-plugin@7.7.0(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3))(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3)
|
||||
eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0)
|
||||
eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0))(eslint@8.57.0)
|
||||
eslint-plugin-consistent-default-export-name: 0.0.15
|
||||
eslint-plugin-eslint-comments: 3.2.0(eslint@8.57.0)
|
||||
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
|
||||
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0)
|
||||
eslint-plugin-n: 17.2.1(eslint@8.57.0)
|
||||
eslint-plugin-no-use-extend-native: 0.5.0
|
||||
eslint-plugin-prettier: 5.1.3(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.0.0)
|
||||
|
@ -18556,6 +18553,10 @@ snapshots:
|
|||
|
||||
debounce@1.2.1: {}
|
||||
|
||||
debug@3.2.7:
|
||||
dependencies:
|
||||
ms: 2.1.3
|
||||
|
||||
debug@3.2.7(supports-color@5.5.0):
|
||||
dependencies:
|
||||
ms: 2.1.3
|
||||
|
@ -19029,19 +19030,19 @@ snapshots:
|
|||
|
||||
eslint-import-resolver-node@0.3.9:
|
||||
dependencies:
|
||||
debug: 3.2.7(supports-color@5.5.0)
|
||||
debug: 3.2.7
|
||||
is-core-module: 2.13.1
|
||||
resolve: 1.22.8
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0):
|
||||
eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0))(eslint@8.57.0):
|
||||
dependencies:
|
||||
debug: 4.3.5
|
||||
enhanced-resolve: 5.16.0
|
||||
eslint: 8.57.0
|
||||
eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
|
||||
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
|
||||
eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0)
|
||||
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0)
|
||||
fast-glob: 3.3.2
|
||||
get-tsconfig: 4.7.3
|
||||
is-core-module: 2.13.1
|
||||
|
@ -19052,14 +19053,14 @@ snapshots:
|
|||
- eslint-import-resolver-webpack
|
||||
- supports-color
|
||||
|
||||
eslint-module-utils@2.8.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0):
|
||||
eslint-module-utils@2.8.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0):
|
||||
dependencies:
|
||||
debug: 3.2.7(supports-color@5.5.0)
|
||||
debug: 3.2.7
|
||||
optionalDependencies:
|
||||
'@typescript-eslint/parser': 7.7.0(eslint@8.57.0)(typescript@5.5.3)
|
||||
eslint: 8.57.0
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0)
|
||||
eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0))(eslint@8.57.0)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
|
@ -19081,17 +19082,17 @@ snapshots:
|
|||
eslint: 8.57.0
|
||||
ignore: 5.3.1
|
||||
|
||||
eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0):
|
||||
eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0):
|
||||
dependencies:
|
||||
array-includes: 3.1.8
|
||||
array.prototype.findlastindex: 1.2.5
|
||||
array.prototype.flat: 1.3.2
|
||||
array.prototype.flatmap: 1.3.2
|
||||
debug: 3.2.7(supports-color@5.5.0)
|
||||
debug: 3.2.7
|
||||
doctrine: 2.1.0
|
||||
eslint: 8.57.0
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
|
||||
eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0)
|
||||
hasown: 2.0.2
|
||||
is-core-module: 2.13.1
|
||||
is-glob: 4.0.3
|
||||
|
|
Loading…
Reference in a new issue