mirror of
https://github.com/ByteAtATime/raycast-linux.git
synced 2025-08-30 18:57:25 +00:00
feat: add inset property to Grid components for customizable padding
This aligns the grid with Raycast's API, specifically allowing it to work with the Spotify Search command (among others, of course)
This commit is contained in:
parent
05fef6ef05
commit
afa6fc8235
5 changed files with 70 additions and 12 deletions
|
@ -28,10 +28,17 @@ const GridDropdown = createWrapperComponent('Grid.Dropdown');
|
|||
const GridDropdownItem = createWrapperComponent('Grid.Dropdown.Item');
|
||||
const GridDropdownSection = createWrapperComponent('Grid.Dropdown.Section');
|
||||
|
||||
const Inset = {
|
||||
Small: 'small',
|
||||
Medium: 'medium',
|
||||
Large: 'large'
|
||||
} as const;
|
||||
|
||||
Object.assign(Grid, {
|
||||
Section: GridSection,
|
||||
Item: GridItem,
|
||||
Dropdown: GridDropdown
|
||||
Dropdown: GridDropdown,
|
||||
Inset: Inset
|
||||
});
|
||||
Object.assign(GridDropdown, {
|
||||
Item: GridDropdownItem,
|
||||
|
|
|
@ -23,7 +23,8 @@
|
|||
columns: gridProps?.columns ?? 6,
|
||||
searchText,
|
||||
filtering: gridProps?.filtering,
|
||||
onSearchTextChange: !!gridProps?.onSearchTextChange
|
||||
onSearchTextChange: !!gridProps?.onSearchTextChange,
|
||||
inset: gridProps?.inset
|
||||
}));
|
||||
</script>
|
||||
|
||||
|
@ -44,6 +45,7 @@
|
|||
props={item.props as GridItemProps}
|
||||
selected={view.selectedItemIndex === index}
|
||||
onclick={() => view.setSelectedItemIndex(index)}
|
||||
inset={item.inset}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
|
|
|
@ -1,19 +1,38 @@
|
|||
<script lang="ts">
|
||||
import type { GridItemProps } from '$lib/props';
|
||||
import type { HTMLButtonAttributes } from 'svelte/elements';
|
||||
import { cn } from '$lib/utils';
|
||||
import type { GridInset } from '$lib/props/grid';
|
||||
|
||||
type Props = {
|
||||
props: GridItemProps;
|
||||
selected: boolean;
|
||||
inset?: GridInset;
|
||||
} & HTMLButtonAttributes;
|
||||
|
||||
let { props, selected, ...restProps }: Props = $props();
|
||||
let { props, selected, inset, ...restProps }: Props = $props();
|
||||
|
||||
const paddingClass = $derived(() => {
|
||||
switch (inset) {
|
||||
case 'small':
|
||||
return 'p-1';
|
||||
case 'medium':
|
||||
return 'p-2';
|
||||
case 'large':
|
||||
return 'p-4';
|
||||
default:
|
||||
return 'px-4 py-2';
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="hover:bg-accent/50 flex w-full flex-col items-center gap-3 px-4 py-2 text-left"
|
||||
class:bg-accent={selected}
|
||||
class={cn(
|
||||
'hover:bg-accent/50 flex w-full flex-col items-center gap-3 text-left',
|
||||
paddingClass,
|
||||
selected && 'bg-accent'
|
||||
)}
|
||||
{...restProps}
|
||||
>
|
||||
<img src={props.content} alt={props.title} />
|
||||
|
|
|
@ -1,18 +1,23 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { ImageLikeSchema } from './image';
|
||||
|
||||
export const GridInsetSchema = z.enum(['small', 'medium', 'large']);
|
||||
export type GridInset = z.infer<typeof GridInsetSchema>;
|
||||
|
||||
export const GridPropsSchema = z.object({
|
||||
filtering: z.boolean().optional(),
|
||||
throttle: z.boolean().default(false),
|
||||
columns: z.number().default(6), // TODO: is this the default?
|
||||
searchBarPlaceholder: z.string().optional(),
|
||||
onSearchTextChange: z.boolean().optional(),
|
||||
isLoading: z.boolean().default(false)
|
||||
isLoading: z.boolean().default(false),
|
||||
inset: GridInsetSchema.optional()
|
||||
});
|
||||
export type GridProps = z.infer<typeof GridPropsSchema>;
|
||||
|
||||
export const GridSectionPropsSchema = z.object({
|
||||
title: z.string().optional()
|
||||
title: z.string().optional(),
|
||||
inset: GridInsetSchema.optional()
|
||||
});
|
||||
export type GridSectionProps = z.infer<typeof GridSectionPropsSchema>;
|
||||
|
||||
|
|
|
@ -1,8 +1,33 @@
|
|||
import { _useBaseView, type BaseViewArgs } from './base.svelte';
|
||||
import type { GridInset, GridSectionProps } from '$lib/props';
|
||||
|
||||
export function useGridView(args: () => BaseViewArgs & { columns: number }) {
|
||||
export function useGridView(args: () => BaseViewArgs & { columns: number; inset?: GridInset }) {
|
||||
const base = _useBaseView(args, 'Grid.Item');
|
||||
const { columns } = $derived.by(args);
|
||||
const { columns, inset: gridInset } = $derived.by(args);
|
||||
|
||||
const processedFlatList = $derived.by(() => {
|
||||
const list = base.flatList;
|
||||
const newList: ((typeof list)[number] & { inset?: GridInset })[] = [];
|
||||
let currentSectionInset: GridInset | undefined;
|
||||
|
||||
for (const item of list) {
|
||||
if (item.type === 'header') {
|
||||
const sectionProps = item.props as GridSectionProps;
|
||||
if (item.id === -1) {
|
||||
// This is the synthetic section for top-level items, so it should inherit from the Grid.
|
||||
currentSectionInset = gridInset;
|
||||
} else {
|
||||
// This is a user-defined <Grid.Section>. It does not inherit.
|
||||
// If `sectionProps.inset` is undefined, it's treated as "none" by GridItem.
|
||||
currentSectionInset = sectionProps.inset;
|
||||
}
|
||||
newList.push(item);
|
||||
} else {
|
||||
newList.push({ ...item, inset: currentSectionInset });
|
||||
}
|
||||
}
|
||||
return newList;
|
||||
});
|
||||
|
||||
type GridMapItem = {
|
||||
flatListIndex: number;
|
||||
|
@ -15,7 +40,7 @@ export function useGridView(args: () => BaseViewArgs & { columns: number }) {
|
|||
let sectionIndex = -1,
|
||||
rowIndex = 0,
|
||||
colIndex = 0;
|
||||
base.flatList.forEach((item, index) => {
|
||||
processedFlatList.forEach((item, index) => {
|
||||
if (item.type === 'header') {
|
||||
sectionIndex++;
|
||||
rowIndex = 0;
|
||||
|
@ -31,7 +56,7 @@ export function useGridView(args: () => BaseViewArgs & { columns: number }) {
|
|||
|
||||
$effect(() => {
|
||||
if (base.selectedItemIndex < 0) return;
|
||||
const elementId = `item-${base.flatList[base.selectedItemIndex]?.id}`;
|
||||
const elementId = `item-${processedFlatList[base.selectedItemIndex]?.id}`;
|
||||
document.getElementById(elementId)?.scrollIntoView({ block: 'nearest' });
|
||||
});
|
||||
|
||||
|
@ -92,7 +117,7 @@ export function useGridView(args: () => BaseViewArgs & { columns: number }) {
|
|||
|
||||
return {
|
||||
get flatList() {
|
||||
return base.flatList;
|
||||
return processedFlatList;
|
||||
},
|
||||
get selectedItemIndex() {
|
||||
return base.selectedItemIndex;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue