Compare commits
No commits in common. "d0c1ee2adb312512632f8908752fa8da2b6af0b9" and "d2a854490fb5b417f3bff5dce45a4bede0973623" have entirely different histories.
d0c1ee2adb
...
d2a854490f
|
@ -467,9 +467,6 @@
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: calc(var(--spacing) * 2);
|
gap: calc(var(--spacing) * 2);
|
||||||
border-bottom: 1px solid var(--color-on-surface-variant);
|
|
||||||
border-top-left-radius: calc(var(--border-radius) * 2);
|
|
||||||
border-top-right-radius: calc(var(--border-radius) * 2);
|
|
||||||
background-color: var(--color-surface-container-highest);
|
background-color: var(--color-surface-container-highest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { invoke } from '@tauri-apps/api/core';
|
import { invoke } from '@tauri-apps/api/core';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { atom } from 'jotai';
|
import { atom } from 'jotai';
|
||||||
import { atomFamily, atomWithRefresh } from 'jotai/utils';
|
import { atomFamily } from 'jotai/utils';
|
||||||
import { get, reduce } from 'lodash-es';
|
import { get, reduce } from 'lodash-es';
|
||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ export function totalDuration(pattern: Pattern): number {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PatternsAtom = atomFamily((keyword: string) =>
|
export const PatternsAtom = atomFamily((keyword: string) =>
|
||||||
atomWithRefresh(async () => {
|
atom(async () => {
|
||||||
try {
|
try {
|
||||||
const patterns = await invoke<Pattern[]>('list_patterns', { keyword });
|
const patterns = await invoke<Pattern[]>('list_patterns', { keyword });
|
||||||
return patterns;
|
return patterns;
|
||||||
|
|
|
@ -3,4 +3,3 @@
|
||||||
@import 'sanitize.css/forms.css' layer(base);
|
@import 'sanitize.css/forms.css' layer(base);
|
||||||
@import './theme.css';
|
@import './theme.css';
|
||||||
@import './components.css';
|
@import './components.css';
|
||||||
@import './utilities.css';
|
|
||||||
|
|
|
@ -41,5 +41,11 @@
|
||||||
background-color: color-mix(in oklch, var(--color-on-surface) 8%, transparent);
|
background-color: color-mix(in oklch, var(--color-on-surface) 8%, transparent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.empty_prompt {
|
||||||
|
padding-block: calc(var(--spacing) * 1);
|
||||||
|
text-align: center;
|
||||||
|
font-size: calc(var(--font-size) * 0.8);
|
||||||
|
color: var(--color-on-surface-variant);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ const AvailableDevices: FC = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.devices_list}>
|
<div className={styles.devices_list}>
|
||||||
{devices.length === 0 && <div className="empty_prompt">No available devices.</div>}
|
{devices.length === 0 && <div className={styles.empty_prompt}>No available devices.</div>}
|
||||||
{devices.map((device, index) => (
|
{devices.map((device, index) => (
|
||||||
<div key={index} className={styles.device_card}>
|
<div key={index} className={styles.device_card}>
|
||||||
<div className={styles.device_name}>{device.represent}</div>
|
<div className={styles.device_name}>{device.represent}</div>
|
||||||
|
|
|
@ -1,27 +1,10 @@
|
||||||
@layer pages {
|
@layer pages {
|
||||||
.patterns {
|
.pattern_list {
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
border-radius: calc(var(--border-radius) * 2);
|
border-radius: calc(var(--border-radius) * 2);
|
||||||
background-color: var(--color-surface-container);
|
background-color: var(--color-surface-container);
|
||||||
padding: calc(var(--spacing) * 2);
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: stretch;
|
|
||||||
gap: calc(var(--spacing) * 2);
|
|
||||||
.search_row {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
gap: calc(var(--spacing));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.pattern_list {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: stretch;
|
|
||||||
gap: calc(var(--spacing) * 2);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,51 +1,11 @@
|
||||||
import { Icon } from '@iconify/react/dist/iconify.js';
|
import { FC } from 'react';
|
||||||
import cx from 'clsx';
|
|
||||||
import { useAtomValue } from 'jotai';
|
|
||||||
import { FC, useState } from 'react';
|
|
||||||
import { useDebounce } from 'react-use';
|
|
||||||
import { ScrollArea } from '../../components/ScrollArea';
|
import { ScrollArea } from '../../components/ScrollArea';
|
||||||
import { PatternsAtom } from '../../context/Patterns';
|
|
||||||
import styles from './Patterns.module.css';
|
import styles from './Patterns.module.css';
|
||||||
|
|
||||||
const Patterns: FC = () => {
|
const Patterns: FC = () => {
|
||||||
const [rawKeyword, setRawKeyword] = useState<string>('');
|
|
||||||
const [keyword, setKeyword] = useState<string | null>(null);
|
|
||||||
const patterns = useAtomValue(PatternsAtom(keyword));
|
|
||||||
|
|
||||||
useDebounce(
|
|
||||||
() => {
|
|
||||||
if (rawKeyword.trim().length > 0) {
|
|
||||||
setKeyword(rawKeyword.trim());
|
|
||||||
} else {
|
|
||||||
setKeyword(null);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
1500,
|
|
||||||
[rawKeyword],
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.patterns}>
|
<div className={styles.pattern_list}>
|
||||||
<div className={styles.search_row}>
|
<ScrollArea enableY></ScrollArea>
|
||||||
<div className={cx('input_wrapper', 'extendable')}>
|
|
||||||
<Icon icon="material-symbols-light:search" />
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
placeholder="Search patterns..."
|
|
||||||
value={rawKeyword}
|
|
||||||
onChange={(evt) => setRawKeyword(evt.currentTarget.value)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<button className="tonal secondary">
|
|
||||||
<Icon icon="material-symbols-light:add" />
|
|
||||||
New Pattern
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<ScrollArea enableY>
|
|
||||||
<div className={styles.pattern_list}>
|
|
||||||
{patterns.length === 0 && <div className="empty_prompt">No pattern found.</div>}
|
|
||||||
</div>
|
|
||||||
</ScrollArea>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
@layer utilities {
|
|
||||||
.extendable {
|
|
||||||
flex: 1 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grow {
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.shrink {
|
|
||||||
flex-shrink: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.empty_prompt {
|
|
||||||
padding-block: calc(var(--spacing) * 1);
|
|
||||||
text-align: center;
|
|
||||||
font-size: calc(var(--font-size) * 0.8);
|
|
||||||
color: var(--color-on-surface-variant);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user