style: formatting

This commit is contained in:
ByteAtATime 2025-06-11 14:58:11 -07:00
parent 85c9595d15
commit fc7c835c66
38 changed files with 4202 additions and 2343 deletions

View file

@ -1 +1,8 @@
sidecar/plugin-host.js
sidecar/dist
src-tauri
package-lock.json
pnpm-lock.yaml
yarn.lock
bun.lock
bun.lockb

View file

@ -1,7 +1,3 @@
{
"recommendations": [
"svelte.svelte-vscode",
"tauri-apps.tauri-vscode",
"rust-lang.rust-analyzer"
]
"recommendations": ["svelte.svelte-vscode", "tauri-apps.tauri-vscode", "rust-lang.rust-analyzer"]
}

3116
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

938
sidecar/pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
declare module "*.txt" {
declare module '*.txt' {
const content: string;
export default content;
}

View file

@ -1,4 +1,4 @@
import type { HostConfig } from "react-reconciler";
import type { HostConfig } from 'react-reconciler';
import type {
ComponentType,
ComponentProps,
@ -7,18 +7,18 @@ import type {
TextInstance,
UpdatePayload,
ParentInstance,
AnyInstance,
} from "./types";
AnyInstance
} from './types';
import {
instances,
getNextInstanceId,
commitBuffer,
addToCommitBuffer,
clearCommitBuffer,
} from "./state";
import { writeOutput } from "./io";
import { serializeProps, optimizeCommitBuffer } from "./utils";
import React from "react";
clearCommitBuffer
} from './state';
import { writeOutput } from './io';
import { serializeProps, optimizeCommitBuffer } from './utils';
import React from 'react';
const appendChildToParent = (parent: ParentInstance, child: AnyInstance) => {
const existingIndex = parent.children.findIndex(({ id }) => id === child.id);
@ -27,8 +27,8 @@ const appendChildToParent = (parent: ParentInstance, child: AnyInstance) => {
}
parent.children.push(child);
addToCommitBuffer({
type: "APPEND_CHILD",
payload: { parentId: parent.id, childId: child.id },
type: 'APPEND_CHILD',
payload: { parentId: parent.id, childId: child.id }
});
};
@ -42,18 +42,16 @@ const insertChildBefore = (
parent.children.splice(existingIndex, 1);
}
const beforeIndex = parent.children.findIndex(
({ id }) => id === beforeChild.id
);
const beforeIndex = parent.children.findIndex(({ id }) => id === beforeChild.id);
if (beforeIndex !== -1) {
parent.children.splice(beforeIndex, 0, child);
addToCommitBuffer({
type: "INSERT_BEFORE",
type: 'INSERT_BEFORE',
payload: {
parentId: parent.id,
childId: child.id,
beforeId: beforeChild.id,
},
beforeId: beforeChild.id
}
});
} else {
appendChildToParent(parent, child);
@ -63,8 +61,8 @@ const insertChildBefore = (
const removeChildFromParent = (parent: ParentInstance, child: AnyInstance) => {
parent.children = parent.children.filter(({ id }) => id !== child.id);
addToCommitBuffer({
type: "REMOVE_CHILD",
payload: { parentId: parent.id, childId: child.id },
type: 'REMOVE_CHILD',
payload: { parentId: parent.id, childId: child.id }
});
};
@ -99,8 +97,8 @@ export const hostConfig: HostConfig<
if (commitBuffer.length > 0) {
const optimizedPayload = optimizeCommitBuffer(commitBuffer);
writeOutput({
type: "BATCH_UPDATE",
payload: optimizedPayload,
type: 'BATCH_UPDATE',
payload: optimizedPayload
});
clearCommitBuffer();
}
@ -108,32 +106,30 @@ export const hostConfig: HostConfig<
createInstance(type, props, root, hostContext, internalInstanceHandle) {
const componentType =
typeof type === "string"
? type
: type.displayName || type.name || "Anonymous";
typeof type === 'string' ? type : type.displayName || type.name || 'Anonymous';
const id = getNextInstanceId();
const instance: RaycastInstance = {
id,
type: componentType,
children: [],
props: serializeProps(props),
_internalFiber: internalInstanceHandle,
_internalFiber: internalInstanceHandle
};
(internalInstanceHandle as any).stateNode = instance;
instances.set(id, instance);
addToCommitBuffer({
type: "CREATE_INSTANCE",
payload: { id, type: componentType, props: instance.props },
type: 'CREATE_INSTANCE',
payload: { id, type: componentType, props: instance.props }
});
return instance;
},
createTextInstance(text) {
const id = getNextInstanceId();
const instance: TextInstance = { id, type: "TEXT", text };
const instance: TextInstance = { id, type: 'TEXT', text };
instances.set(id, instance);
addToCommitBuffer({ type: "CREATE_TEXT_INSTANCE", payload: instance });
addToCommitBuffer({ type: 'CREATE_TEXT_INSTANCE', payload: instance });
return instance;
},
@ -148,16 +144,16 @@ export const hostConfig: HostConfig<
commitUpdate(instance, type, oldProps, newProps, internalHandle) {
instance.props = serializeProps(newProps);
addToCommitBuffer({
type: "UPDATE_PROPS",
payload: { id: instance.id, props: instance.props },
type: 'UPDATE_PROPS',
payload: { id: instance.id, props: instance.props }
});
},
commitTextUpdate(textInstance, oldText, newText) {
textInstance.text = newText;
addToCommitBuffer({
type: "UPDATE_TEXT",
payload: { id: textInstance.id, text: newText },
type: 'UPDATE_TEXT',
payload: { id: textInstance.id, text: newText }
});
},
@ -167,8 +163,8 @@ export const hostConfig: HostConfig<
clearContainer: (container) => {
container.children = [];
addToCommitBuffer({
type: "CLEAR_CONTAINER",
payload: { containerId: container.id },
type: 'CLEAR_CONTAINER',
payload: { containerId: container.id }
});
},
@ -202,33 +198,33 @@ export const hostConfig: HostConfig<
HostTransitionContext: React.createContext(0),
resetFormInstance: function (): void {
throw new Error("Function not implemented.");
throw new Error('Function not implemented.');
},
requestPostPaintCallback: function (): void {
throw new Error("Function not implemented.");
throw new Error('Function not implemented.');
},
shouldAttemptEagerTransition: function (): boolean {
throw new Error("Function not implemented.");
throw new Error('Function not implemented.');
},
trackSchedulerEvent: function (): void {
throw new Error("Function not implemented.");
throw new Error('Function not implemented.');
},
resolveEventType: function (): null | string {
throw new Error("Function not implemented.");
throw new Error('Function not implemented.');
},
resolveEventTimeStamp: function (): number {
throw new Error("Function not implemented.");
throw new Error('Function not implemented.');
},
preloadInstance: function (): boolean {
throw new Error("Function not implemented.");
throw new Error('Function not implemented.');
},
startSuspendingCommit: function (): void {
throw new Error("Function not implemented.");
throw new Error('Function not implemented.');
},
suspendInstance: function (): void {
throw new Error("Function not implemented.");
throw new Error('Function not implemented.');
},
waitForCommitToBeReady: function () {
throw new Error("Function not implemented.");
},
throw new Error('Function not implemented.');
}
};

View file

@ -1,30 +1,27 @@
import { createInterface } from "readline";
import { writeLog, writeOutput } from "./io";
import { runPlugin } from "./plugin";
import { instances } from "./state";
import { batchedUpdates } from "./reconciler";
import { createInterface } from 'readline';
import { writeLog, writeOutput } from './io';
import { runPlugin } from './plugin';
import { instances } from './state';
import { batchedUpdates } from './reconciler';
process.on("unhandledRejection", (reason: unknown) => {
process.on('unhandledRejection', (reason: unknown) => {
writeLog(`--- UNHANDLED PROMISE REJECTION ---`);
const stack =
reason && typeof reason === "object" && "stack" in reason
? reason.stack
: reason;
const stack = reason && typeof reason === 'object' && 'stack' in reason ? reason.stack : reason;
writeLog(stack);
});
const rl = createInterface({ input: process.stdin });
rl.on("line", (line) => {
rl.on('line', (line) => {
batchedUpdates(() => {
try {
const command: { action: string; payload: unknown } = JSON.parse(line);
switch (command.action) {
case "run-plugin":
case 'run-plugin':
runPlugin();
break;
case "dispatch-event": {
case 'dispatch-event': {
const { instanceId, handlerName, args } = command.payload as {
instanceId: number;
handlerName: string;
@ -39,12 +36,10 @@ rl.on("line", (line) => {
const handler = instance._internalFiber?.memoizedProps?.[handlerName];
if (typeof handler === "function") {
if (typeof handler === 'function') {
handler(...args);
} else {
writeLog(
`Handler ${handlerName} not found on instance ${instanceId}`
);
writeLog(`Handler ${handlerName} not found on instance ${instanceId}`);
}
break;
}
@ -56,10 +51,10 @@ rl.on("line", (line) => {
err instanceof Error
? { message: err.message, stack: err.stack }
: { message: String(err) };
writeLog(`ERROR: ${error.message} \n ${error.stack ?? ""}`);
writeOutput({ type: "error", payload: error.message });
writeLog(`ERROR: ${error.message} \n ${error.stack ?? ''}`);
writeOutput({ type: 'error', payload: error.message });
}
});
});
writeLog("Node.js Sidecar started successfully with React Reconciler.");
writeLog('Node.js Sidecar started successfully with React Reconciler.');

View file

@ -1,4 +1,4 @@
import { Packr } from "msgpackr";
import { Packr } from 'msgpackr';
const packr = new Packr();
@ -12,7 +12,7 @@ export const writeOutput = (data: object): void => {
process.stdout.write(payload);
} catch (e: unknown) {
const errorString = e instanceof Error ? e.toString() : String(e);
const errorPayload = packr.pack({ type: "log", payload: errorString });
const errorPayload = packr.pack({ type: 'log', payload: errorString });
const errorHeader = Buffer.alloc(4);
errorHeader.writeUInt32BE(errorPayload.length);
process.stdout.write(errorHeader);
@ -21,5 +21,5 @@ export const writeOutput = (data: object): void => {
};
export const writeLog = (message: unknown): void => {
writeOutput({ type: "log", payload: message });
writeOutput({ type: 'log', payload: message });
};

View file

@ -1,23 +1,23 @@
import React from "react";
import { jsx } from "react/jsx-runtime";
import plugin from "../dist/plugin/emoji.txt";
import { updateContainer } from "./reconciler";
import { writeLog } from "./io";
import React from 'react';
import { jsx } from 'react/jsx-runtime';
import plugin from '../dist/plugin/emoji.txt';
import { updateContainer } from './reconciler';
import { writeLog } from './io';
const createPluginRequire =
() =>
(moduleName: string): unknown => {
if (moduleName === "react") {
if (moduleName === 'react') {
return React;
}
if (moduleName.startsWith("@raycast/api")) {
if (moduleName.startsWith('@raycast/api')) {
const storage = new Map<string, string>();
const LocalStorage = {
getItem: async (key: string) => storage.get(key),
setItem: async (key: string, value: string) => storage.set(key, value),
removeItem: async (key: string) => storage.delete(key),
clear: async () => storage.clear(),
clear: async () => storage.clear()
};
const createWrapperComponent =
@ -25,33 +25,31 @@ const createPluginRequire =
({ children, ...rest }: { children?: React.ReactNode }) =>
jsx(name, { ...rest, children });
const ListComponent = createWrapperComponent("List");
const ListSectionComponent = createWrapperComponent("ListSection");
const ListDropdownComponent = createWrapperComponent("ListDropdown");
const ActionPanelComponent = createWrapperComponent("ActionPanel");
const ActionPanelSectionComponent =
createWrapperComponent("ActionPanelSection");
const ListComponent = createWrapperComponent('List');
const ListSectionComponent = createWrapperComponent('ListSection');
const ListDropdownComponent = createWrapperComponent('ListDropdown');
const ActionPanelComponent = createWrapperComponent('ActionPanel');
const ActionPanelSectionComponent = createWrapperComponent('ActionPanelSection');
Object.assign(ListComponent, {
Item: "ListItem",
Item: 'ListItem',
Section: ListSectionComponent,
Dropdown: ListDropdownComponent,
Dropdown: ListDropdownComponent
});
Object.assign(ListDropdownComponent, { Item: "ListDropdownItem" });
Object.assign(ListDropdownComponent, { Item: 'ListDropdownItem' });
Object.assign(ActionPanelComponent, {
Section: ActionPanelSectionComponent,
Section: ActionPanelSectionComponent
});
return {
LocalStorage,
environment: {
assetsPath:
"/home/byte/code/raycast-linux/sidecar/dist/plugin/assets/",
assetsPath: '/home/byte/code/raycast-linux/sidecar/dist/plugin/assets/'
},
getPreferenceValues: () => ({
primaryAction: "paste",
unicodeVersion: "14.0",
shortCodes: true,
primaryAction: 'paste',
unicodeVersion: '14.0',
shortCodes: true
}),
usePersistentState: <T>(
key: string,
@ -63,10 +61,10 @@ const createPluginRequire =
List: ListComponent,
ActionPanel: ActionPanelComponent,
Action: {
Paste: "Action.Paste",
CopyToClipboard: "Action.CopyToClipboard",
OpenInBrowser: "Action.OpenInBrowser",
},
Paste: 'Action.Paste',
CopyToClipboard: 'Action.CopyToClipboard',
OpenInBrowser: 'Action.OpenInBrowser'
}
};
}
@ -76,32 +74,21 @@ const createPluginRequire =
export const runPlugin = (): void => {
const scriptText = plugin;
const pluginModule = {
exports: {} as { default: React.ComponentType | null },
exports: {} as { default: React.ComponentType | null }
};
const scriptFunction = new Function(
"require",
"module",
"exports",
"React",
scriptText
);
const scriptFunction = new Function('require', 'module', 'exports', 'React', scriptText);
scriptFunction(
createPluginRequire(),
pluginModule,
pluginModule.exports,
React
);
scriptFunction(createPluginRequire(), pluginModule, pluginModule.exports, React);
const PluginRootComponent = pluginModule.exports.default;
if (!PluginRootComponent) {
throw new Error("Plugin did not export a default component.");
throw new Error('Plugin did not export a default component.');
}
writeLog("Plugin loaded. Initializing React render...");
writeLog('Plugin loaded. Initializing React render...');
const AppElement = React.createElement(PluginRootComponent);
updateContainer(AppElement, () => {
writeLog("Initial render complete");
writeLog('Initial render complete');
});
};

View file

@ -1,8 +1,8 @@
import Reconciler, { type RootTag } from "react-reconciler";
import type React from "react";
import { root } from "./state";
import { hostConfig } from "./hostConfig";
import { writeLog } from "./io";
import Reconciler, { type RootTag } from 'react-reconciler';
import type React from 'react';
import { root } from './state';
import { hostConfig } from './hostConfig';
import { writeLog } from './io';
const reconciler = Reconciler(hostConfig);
@ -17,15 +17,12 @@ export const container = reconciler.createContainer(
null,
false,
null,
"",
'',
onRecoverableError,
null
);
export const updateContainer = (
element: React.ReactElement,
callback?: () => void
) => {
export const updateContainer = (element: React.ReactElement, callback?: () => void) => {
reconciler.updateContainer(element, container, null, callback);
};

View file

@ -1,7 +1,7 @@
import type { AnyInstance, Commit, Container } from "./types";
import type { AnyInstance, Commit, Container } from './types';
export const instances = new Map<number, AnyInstance>();
export const root: Container = { id: "root", children: [] };
export const root: Container = { id: 'root', children: [] };
let instanceCounter = 0;
export const getNextInstanceId = (): number => ++instanceCounter;

View file

@ -1,5 +1,5 @@
import type React from "react";
import type Reconciler from "react-reconciler";
import type React from 'react';
import type Reconciler from 'react-reconciler';
export type ComponentType = string | React.ComponentType<any>;
export type ComponentProps = Record<string, unknown>;
@ -16,12 +16,12 @@ export interface RaycastInstance extends BaseInstance {
}
export interface TextInstance extends BaseInstance {
type: "TEXT";
type: 'TEXT';
text: string;
}
export interface Container {
id: "root";
id: 'root';
children: (RaycastInstance | TextInstance)[];
}
@ -35,7 +35,7 @@ export interface Commit {
}
export interface SerializedReactElement {
$$typeof: "react.element.serialized";
$$typeof: 'react.element.serialized';
type: string;
props: Record<string, unknown>;
}

View file

@ -1,41 +1,29 @@
import React from "react";
import type {
ComponentType,
Commit,
SerializedReactElement,
ParentInstance,
} from "./types";
import { root, instances } from "./state";
import React from 'react';
import type { ComponentType, Commit, SerializedReactElement, ParentInstance } from './types';
import { root, instances } from './state';
export const getComponentDisplayName = (type: ComponentType): string => {
if (typeof type === "string") {
if (typeof type === 'string') {
return type;
}
return type.displayName ?? type.name ?? "Anonymous";
return type.displayName ?? type.name ?? 'Anonymous';
};
const isSerializableReactElement = (
value: unknown
): value is React.ReactElement => React.isValidElement(value);
const isSerializableReactElement = (value: unknown): value is React.ReactElement =>
React.isValidElement(value);
function serializeReactElement(
element: React.ReactElement
): SerializedReactElement {
function serializeReactElement(element: React.ReactElement): SerializedReactElement {
return {
$$typeof: "react.element.serialized",
$$typeof: 'react.element.serialized',
type: getComponentDisplayName(element.type as ComponentType),
props: serializeProps(element.props as Record<string, unknown>),
props: serializeProps(element.props as Record<string, unknown>)
};
}
export function serializeProps(
props: Record<string, unknown>
): Record<string, unknown> {
export function serializeProps(props: Record<string, unknown>): Record<string, unknown> {
return Object.fromEntries(
Object.entries(props)
.filter(
([key, value]) => key !== "children" && typeof value !== "function"
)
.filter(([key, value]) => key !== 'children' && typeof value !== 'function')
.map(([key, value]) => {
if (isSerializableReactElement(value)) {
return [key, serializeReactElement(value)];
@ -44,10 +32,8 @@ export function serializeProps(
return [
key,
value.map((item) =>
isSerializableReactElement(item)
? serializeReactElement(item)
: item
),
isSerializableReactElement(item) ? serializeReactElement(item) : item
)
];
}
return [key, value];
@ -57,23 +43,18 @@ export function serializeProps(
export function optimizeCommitBuffer(buffer: Commit[]): Commit[] {
const OPTIMIZATION_THRESHOLD = 10;
const childOpsByParent = new Map<ParentInstance["id"], Commit[]>();
const childOpsByParent = new Map<ParentInstance['id'], Commit[]>();
const otherOps: Commit[] = [];
for (const op of buffer) {
const { type, payload } = op;
const parentId = (payload as { parentId?: ParentInstance["id"] })?.parentId;
const parentId = (payload as { parentId?: ParentInstance['id'] })?.parentId;
const isChildOp =
type === "APPEND_CHILD" ||
type === "REMOVE_CHILD" ||
type === "INSERT_BEFORE";
type === 'APPEND_CHILD' || type === 'REMOVE_CHILD' || type === 'INSERT_BEFORE';
if (isChildOp && parentId) {
childOpsByParent.set(
parentId,
(childOpsByParent.get(parentId) ?? []).concat(op)
);
childOpsByParent.set(parentId, (childOpsByParent.get(parentId) ?? []).concat(op));
} else {
otherOps.push(op);
}
@ -91,14 +72,13 @@ export function optimizeCommitBuffer(buffer: Commit[]): Commit[] {
continue;
}
const parentInstance =
parentId === "root" ? root : instances.get(parentId as number);
const parentInstance = parentId === 'root' ? root : instances.get(parentId as number);
if (parentInstance && "children" in parentInstance) {
if (parentInstance && 'children' in parentInstance) {
const childrenIds = parentInstance.children.map(({ id }) => id);
finalOps.push({
type: "REPLACE_CHILDREN",
payload: { parentId, childrenIds },
type: 'REPLACE_CHILDREN',
payload: { parentId, childrenIds }
});
} else {
finalOps.push(...ops);

View file

@ -1,22 +1,18 @@
import { setResults } from "../results.svelte";
import type * as api from "@raycast/api";
import { Toast } from "./toast";
import {
writeText,
writeHtml,
writeImage,
} from "@tauri-apps/plugin-clipboard-manager";
import { setResults } from '../results.svelte';
import type * as api from '@raycast/api';
import { Toast } from './toast';
import { writeText, writeHtml, writeImage } from '@tauri-apps/plugin-clipboard-manager';
export const mockRaycastApi = {
updateCommandMetadata: async (metadata: { subtitle?: string | null }) => {
setResults([{ subtitle: metadata.subtitle }]);
},
environment: {
launchType: "userInitiated",
launchType: 'userInitiated'
},
LaunchType: {
UserInitiated: "userInitiated",
Background: "background",
UserInitiated: 'userInitiated',
Background: 'background'
},
Toast: Toast as typeof api.Toast,
Clipboard: {
@ -24,17 +20,17 @@ export const mockRaycastApi = {
content: string | number | api.Clipboard.Content,
options?: api.Clipboard.CopyOptions
) => {
if (typeof content === "string" || typeof content === "number") {
if (typeof content === 'string' || typeof content === 'number') {
await writeText(content.toString());
} else {
if ("html" in content) {
if ('html' in content) {
await writeHtml(content.html);
} else if ("file" in content) {
} else if ('file' in content) {
await writeImage(content.file);
} else {
await writeText(content.text);
}
}
},
},
}
}
} satisfies typeof api;

View file

@ -1,21 +1,21 @@
import { setToast } from "$lib/results.svelte";
import type * as api from "@raycast/api";
import { setToast } from '$lib/results.svelte';
import type * as api from '@raycast/api';
export class Toast {
public static readonly Style = {
Success: "SUCCESS",
Failure: "FAILURE",
Animated: "ANIMATED",
Success: 'SUCCESS',
Failure: 'FAILURE',
Animated: 'ANIMATED'
};
public style: "SUCCESS" | "FAILURE" | "ANIMATED";
public style: 'SUCCESS' | 'FAILURE' | 'ANIMATED';
public title: string;
public message: string | undefined;
public primaryAction: api.Toast.ActionOptions | undefined;
public secondaryAction: api.Toast.ActionOptions | undefined;
constructor(props: api.Toast.Options) {
this.style = props.style ?? "SUCCESS"; // TODO: is this default value correct?
this.style = props.style ?? 'SUCCESS'; // TODO: is this default value correct?
this.title = props.title;
this.message = props.message;
this.primaryAction = props.primaryAction;

View file

@ -1,6 +1,6 @@
<!-- src/ResultsList.svelte -->
<script lang="ts">
import { getResults } from "$lib/results.svelte";
import { getResults } from '$lib/results.svelte';
const pluginResults = $derived(getResults());
</script>
@ -8,10 +8,8 @@
<div class="flex-grow overflow-y-auto">
<ul>
{#each pluginResults as result}
<li
class="flex items-center p-2 rounded-lg hover:bg-blue-500/20 cursor-pointer"
>
<div class="flex flex-col ml-2">
<li class="flex cursor-pointer items-center rounded-lg p-2 hover:bg-blue-500/20">
<div class="ml-2 flex flex-col">
<span class="text-xs text-gray-400">{result.subtitle}</span>
</div>
</li>

View file

@ -1,22 +1,22 @@
<script lang="ts">
import { Separator } from "./ui/separator";
import { getToast } from "../results.svelte";
import { Toast } from "$lib/api/toast";
import { Button } from "./ui/button";
import type * as api from "@raycast/api";
import { Kbd } from "./ui/kbd";
import { shortcutToText } from "$lib/renderKey";
import { Separator } from './ui/separator';
import { getToast } from '../results.svelte';
import { Toast } from '$lib/api/toast';
import { Button } from './ui/button';
import type * as api from '@raycast/api';
import { Kbd } from './ui/kbd';
import { shortcutToText } from '$lib/renderKey';
const toast = getToast();
const styles = $derived.by(() => {
switch (toast?.style) {
case Toast.Style.Success:
return "bg-green-500/20";
return 'bg-green-500/20';
case Toast.Style.Failure:
return "bg-red-500/20";
return 'bg-red-500/20';
default:
return "bg-gray-500/20";
return 'bg-gray-500/20';
}
});
</script>
@ -26,13 +26,13 @@
{#if toast}
{@const actualToast = toast as Toast}
<div class="py-2 px-4 flex items-center gap-4 {styles}">
{#if actualToast.style === "SUCCESS"}
<div class="w-2.5 h-2.5 bg-green-500 rounded-full"></div>
{:else if actualToast.style === "FAILURE"}
<div class="w-2.5 h-2.5 bg-red-500 rounded-full"></div>
{:else if actualToast.style === "ANIMATED"}
<div class="w-2.5 h-2.5 bg-gray-500 rounded-full"></div>
<div class="flex items-center gap-4 px-4 py-2 {styles}">
{#if actualToast.style === 'SUCCESS'}
<div class="h-2.5 w-2.5 rounded-full bg-green-500"></div>
{:else if actualToast.style === 'FAILURE'}
<div class="h-2.5 w-2.5 rounded-full bg-red-500"></div>
{:else if actualToast.style === 'ANIMATED'}
<div class="h-2.5 w-2.5 rounded-full bg-gray-500"></div>
{/if}
{actualToast.title}
@ -42,8 +42,7 @@
{#if actualToast.primaryAction}
<Button
variant="ghost"
onclick={() =>
actualToast.primaryAction!.onAction(actualToast as api.Toast)}
onclick={() => actualToast.primaryAction!.onAction(actualToast as api.Toast)}
>
{actualToast.primaryAction.title}

View file

@ -1,36 +1,36 @@
<script lang="ts" module>
import { cn, type WithElementRef } from "$lib/utils.js";
import type { HTMLAnchorAttributes, HTMLButtonAttributes } from "svelte/elements";
import { type VariantProps, tv } from "tailwind-variants";
import { cn, type WithElementRef } from '$lib/utils.js';
import type { HTMLAnchorAttributes, HTMLButtonAttributes } from 'svelte/elements';
import { type VariantProps, tv } from 'tailwind-variants';
export const buttonVariants = tv({
base: "focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive inline-flex shrink-0 items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium outline-none transition-all focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
variants: {
variant: {
default: "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
default: 'bg-primary text-primary-foreground shadow-xs hover:bg-primary/90',
destructive:
"bg-destructive shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60 text-white",
'bg-destructive shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60 text-white',
outline:
"bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 border",
secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
link: "text-primary underline-offset-4 hover:underline",
'bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 border',
secondary: 'bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80',
ghost: 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',
link: 'text-primary underline-offset-4 hover:underline'
},
size: {
default: "h-9 px-4 py-2 has-[>svg]:px-3",
sm: "h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5",
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
icon: "size-9",
},
default: 'h-9 px-4 py-2 has-[>svg]:px-3',
sm: 'h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5',
lg: 'h-10 rounded-md px-6 has-[>svg]:px-4',
icon: 'size-9'
}
},
defaultVariants: {
variant: "default",
size: "default",
},
variant: 'default',
size: 'default'
}
});
export type ButtonVariant = VariantProps<typeof buttonVariants>["variant"];
export type ButtonSize = VariantProps<typeof buttonVariants>["size"];
export type ButtonVariant = VariantProps<typeof buttonVariants>['variant'];
export type ButtonSize = VariantProps<typeof buttonVariants>['size'];
export type ButtonProps = WithElementRef<HTMLButtonAttributes> &
WithElementRef<HTMLAnchorAttributes> & {
@ -42,11 +42,11 @@
<script lang="ts">
let {
class: className,
variant = "default",
size = "default",
variant = 'default',
size = 'default',
ref = $bindable(null),
href = undefined,
type = "button",
type = 'button',
disabled,
children,
...restProps
@ -60,7 +60,7 @@
class={cn(buttonVariants({ variant, size }), className)}
href={disabled ? undefined : href}
aria-disabled={disabled}
role={disabled ? "link" : undefined}
role={disabled ? 'link' : undefined}
tabindex={disabled ? -1 : undefined}
{...restProps}
>

View file

@ -2,8 +2,8 @@ import Root, {
type ButtonProps,
type ButtonSize,
type ButtonVariant,
buttonVariants,
} from "./button.svelte";
buttonVariants
} from './button.svelte';
export {
Root,
@ -13,5 +13,5 @@ export {
buttonVariants,
type ButtonProps,
type ButtonSize,
type ButtonVariant,
type ButtonVariant
};

View file

@ -1,7 +1,7 @@
import Root from "./input.svelte";
import Root from './input.svelte';
export {
Root,
//
Root as Input,
Root as Input
};

View file

@ -1,18 +1,12 @@
<script lang="ts">
import type {
HTMLInputAttributes,
HTMLInputTypeAttribute,
} from "svelte/elements";
import { cn, type WithElementRef } from "$lib/utils.js";
import type { HTMLInputAttributes, HTMLInputTypeAttribute } from 'svelte/elements';
import { cn, type WithElementRef } from '$lib/utils.js';
type InputType = Exclude<HTMLInputTypeAttribute, "file">;
type InputType = Exclude<HTMLInputTypeAttribute, 'file'>;
type Props = WithElementRef<
Omit<HTMLInputAttributes, "type"> &
(
| { type: "file"; files?: FileList }
| { type?: InputType; files?: undefined }
)
Omit<HTMLInputAttributes, 'type'> &
({ type: 'file'; files?: FileList } | { type?: InputType; files?: undefined })
>;
let {
@ -25,14 +19,14 @@
}: Props = $props();
</script>
{#if type === "file"}
{#if type === 'file'}
<input
bind:this={ref}
data-slot="input"
class={cn(
"selection:bg-primary dark:bg-input/30 selection:text-primary-foreground border-input ring-offset-background placeholder:text-muted-foreground shadow-xs flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 pt-1.5 text-sm font-medium outline-none transition-[color,box-shadow] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
'selection:bg-primary dark:bg-input/30 selection:text-primary-foreground border-input ring-offset-background placeholder:text-muted-foreground flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 pt-1.5 text-sm font-medium shadow-xs transition-[color,box-shadow] outline-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
'focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]',
'aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive',
className
)}
type="file"
@ -45,8 +39,8 @@
bind:this={ref}
data-slot="input"
class={cn(
"border-input bg-background selection:bg-primary dark:bg-input/30 selection:text-primary-foreground ring-offset-background placeholder:text-muted-foreground shadow-xs flex h-9 w-full min-w-0 rounded-md border px-3 py-1 text-base outline-none transition-[color,box-shadow] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
'border-input bg-background selection:bg-primary dark:bg-input/30 selection:text-primary-foreground ring-offset-background placeholder:text-muted-foreground flex h-9 w-full min-w-0 rounded-md border px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
'aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive',
className
)}
{type}

View file

@ -1,3 +1,3 @@
import Kbd from "./kbd.svelte";
import Kbd from './kbd.svelte';
export { Kbd };

View file

@ -1,25 +1,25 @@
<script lang="ts" module>
import { tv, type VariantProps } from "tailwind-variants";
import type { WithChildren } from "bits-ui";
import { tv, type VariantProps } from 'tailwind-variants';
import type { WithChildren } from 'bits-ui';
const style = tv({
base: "inline-flex place-items-center justify-center gap-1 rounded-md p-0.5",
base: 'inline-flex place-items-center justify-center gap-1 rounded-md p-0.5',
variants: {
variant: {
outline: "border-border bg-background text-muted-foreground border",
secondary: "bg-secondary text-muted-foreground",
primary: "bg-primary text-primary-foreground",
outline: 'border-border bg-background text-muted-foreground border',
secondary: 'bg-secondary text-muted-foreground',
primary: 'bg-primary text-primary-foreground'
},
size: {
sm: "min-w-6 gap-1.5 p-0.5 px-1 text-sm",
default: "min-w-8 gap-1.5 p-1 px-2",
lg: "min-w-9 gap-2 p-1 px-3 text-lg",
},
},
sm: 'min-w-6 gap-1.5 p-0.5 px-1 text-sm',
default: 'min-w-8 gap-1.5 p-1 px-2',
lg: 'min-w-9 gap-2 p-1 px-3 text-lg'
}
}
});
type Size = VariantProps<typeof style>["size"];
type Variant = VariantProps<typeof style>["variant"];
type Size = VariantProps<typeof style>['size'];
type Variant = VariantProps<typeof style>['variant'];
export type KbdPropsWithoutHTML = WithChildren<{
ref?: HTMLElement | null;
@ -32,14 +32,14 @@
</script>
<script lang="ts">
import { cn } from "$lib/utils";
import { cn } from '$lib/utils';
let {
ref = $bindable(null),
class: className,
size = "default",
variant = "outline",
children,
size = 'default',
variant = 'outline',
children
}: KbdProps = $props();
</script>

View file

@ -1,7 +1,7 @@
import Root from "./separator.svelte";
import Root from './separator.svelte';
export {
Root,
//
Root as Separator,
Root as Separator
};

View file

@ -1,6 +1,6 @@
<script lang="ts">
import { Separator as SeparatorPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js";
import { Separator as SeparatorPrimitive } from 'bits-ui';
import { cn } from '$lib/utils.js';
let {
ref = $bindable(null),
@ -13,7 +13,7 @@
bind:ref
data-slot="separator"
class={cn(
"bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=vertical]:h-full data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-px",
'bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px',
className
)}
{...restProps}

View file

@ -1,5 +1,5 @@
import { mockRaycastApi } from "./api";
import plugin from "./plugin.js?raw";
import { mockRaycastApi } from './api';
import plugin from './plugin.js?raw';
declare global {
interface Window {
@ -10,42 +10,36 @@ declare global {
window.require = function (moduleName) {
console.log(`Plugin is requesting module: ${moduleName}`);
if (moduleName === "@raycast/api") {
if (moduleName === '@raycast/api') {
return mockRaycastApi;
}
throw new Error(
`Module not found: ${moduleName}. Our fake 'require' is very limited!`
);
throw new Error(`Module not found: ${moduleName}. Our fake 'require' is very limited!`);
};
window.module = {
exports: {},
exports: {}
};
export async function runPlugin() {
console.log("Requesting plugin script from Rust backend...");
console.log('Requesting plugin script from Rust backend...');
const scriptText = plugin;
console.log("Executing plugin script in a try/catch block...");
console.log('Executing plugin script in a try/catch block...');
try {
// TOOD: don't use eval
eval(scriptText);
} catch (e) {
console.error("Error evaluating plugin script:", e);
console.error('Error evaluating plugin script:', e);
return;
}
const pluginMainFunction = window.module.exports.default;
if (pluginMainFunction && typeof pluginMainFunction === "function") {
console.log(
"Plugin script loaded successfully. Running its main command..."
);
if (pluginMainFunction && typeof pluginMainFunction === 'function') {
console.log('Plugin script loaded successfully. Running its main command...');
await pluginMainFunction();
console.log("Plugin main command finished.");
console.log('Plugin main command finished.');
} else {
console.error(
"Could not find a default export function in the plugin script."
);
console.error('Could not find a default export function in the plugin script.');
}
}

View file

@ -1,65 +1,61 @@
"use strict";
'use strict';
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
for (var name in all) __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if ((from && typeof from === "object") || typeof from === "function") {
if ((from && typeof from === 'object') || typeof from === 'function') {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, {
get: () => from[key],
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable,
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
});
}
return to;
};
var __toCommonJS = (mod) =>
__copyProps(__defProp({}, "__esModule", { value: true }), mod);
var __toCommonJS = (mod) => __copyProps(__defProp({}, '__esModule', { value: true }), mod);
// src/index.ts
var src_exports = {};
__export(src_exports, {
default: () => src_default,
default: () => src_default
});
module.exports = __toCommonJS(src_exports);
var import_api = require("@raycast/api");
var import_api = require('@raycast/api');
var command = async () => {
const now = new Date();
const london = now.toLocaleString(void 0, {
timeZone: "Europe/London",
timeStyle: "short",
timeZone: 'Europe/London',
timeStyle: 'short'
});
const berlin = now.toLocaleString(void 0, {
timeZone: "Europe/Berlin",
timeStyle: "short",
timeZone: 'Europe/Berlin',
timeStyle: 'short'
});
const moscow = now.toLocaleString(void 0, {
timeZone: "Europe/Moscow",
timeStyle: "short",
timeZone: 'Europe/Moscow',
timeStyle: 'short'
});
const india = now.toLocaleString(void 0, {
timeZone: "Asia/Kolkata",
timeStyle: "short",
timeZone: 'Asia/Kolkata',
timeStyle: 'short'
});
const subtitle = `\u{1F1EC}\u{1F1E7} ${london} \u{1F1F3}\u{1F1F1}\u{1F1E9}\u{1F1EA}\u{1F1F3}\u{1F1F4}\u{1F1E9}\u{1F1F0}\u{1F1F5}\u{1F1F1} ${berlin} \u{1F1F7}\u{1F1FA} ${moscow} \u{1F1EE}\u{1F1F3} ${india}`;
await (0, import_api.updateCommandMetadata)({ subtitle });
if (
import_api.environment.launchType === import_api.LaunchType.UserInitiated
) {
if (import_api.environment.launchType === import_api.LaunchType.UserInitiated) {
const toast = new import_api.Toast({
style: import_api.Toast.Style.Success,
title: "Refreshed!",
message: subtitle,
title: 'Refreshed!',
message: subtitle
});
toast.primaryAction = {
title: "Copy to Clipboard",
shortcut: { modifiers: ["cmd", "shift"], key: "c" },
onAction: () => import_api.Clipboard.copy(subtitle),
title: 'Copy to Clipboard',
shortcut: { modifiers: ['cmd', 'shift'], key: 'c' },
onAction: () => import_api.Clipboard.copy(subtitle)
};
await toast.show();
}

View file

@ -1,4 +1,4 @@
import type { Keyboard } from "@raycast/api";
import type { Keyboard } from '@raycast/api';
type ShortcutParts = {
modifiers: Keyboard.KeyModifier[];
@ -8,32 +8,32 @@ type ShortcutParts = {
function formatShortcutParts(parts: ShortcutParts, isMac: boolean): string {
const modifierMap = {
mac: {
cmd: "⌘",
ctrl: "⌃",
opt: "⌥",
shift: "⇧",
cmd: '⌘',
ctrl: '⌃',
opt: '⌥',
shift: '⇧'
},
other: {
cmd: "Win",
ctrl: "Ctrl",
opt: "Alt",
shift: "Shift",
},
cmd: 'Win',
ctrl: 'Ctrl',
opt: 'Alt',
shift: 'Shift'
}
};
const keyMap: Partial<Record<Keyboard.KeyEquivalent, string>> = {
return: "⏎",
enter: "⏎",
delete: "⌫",
backspace: "⌫",
deleteForward: "⌦",
arrowUp: "↑",
arrowDown: "↓",
arrowLeft: "←",
arrowRight: "→",
tab: "⇥",
escape: "⎋",
space: "␣",
return: '⏎',
enter: '⏎',
delete: '⌫',
backspace: '⌫',
deleteForward: '⌦',
arrowUp: '↑',
arrowDown: '↓',
arrowLeft: '←',
arrowRight: '→',
tab: '⇥',
escape: '⎋',
space: '␣'
};
const currentModifiers = isMac ? modifierMap.mac : modifierMap.other;
@ -44,18 +44,15 @@ function formatShortcutParts(parts: ShortcutParts, isMac: boolean): string {
const allParts = [...modifierStrings, keyString];
return allParts.join(" + ");
return allParts.join(' + ');
}
export function shortcutToText(
shortcut: Keyboard.Shortcut,
forceOS?: "macOS" | "windows"
): string {
export function shortcutToText(shortcut: Keyboard.Shortcut, forceOS?: 'macOS' | 'windows'): string {
const isMac = forceOS
? forceOS === "macOS"
: typeof navigator !== "undefined" && /Mac/i.test(navigator.platform);
? forceOS === 'macOS'
: typeof navigator !== 'undefined' && /Mac/i.test(navigator.platform);
if ("modifiers" in shortcut) {
if ('modifiers' in shortcut) {
return formatShortcutParts(shortcut, isMac);
} else {
if (isMac) {

View file

@ -1,4 +1,4 @@
import type { Toast } from "./api/toast";
import type { Toast } from './api/toast';
type Result = {
subtitle?: string | null;

View file

@ -1,13 +1,13 @@
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
import { clsx, type ClassValue } from 'clsx';
import { twMerge } from 'tailwind-merge';
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type WithoutChild<T> = T extends { child?: any } ? Omit<T, "child"> : T;
export type WithoutChild<T> = T extends { child?: any } ? Omit<T, 'child'> : T;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type WithoutChildren<T> = T extends { children?: any } ? Omit<T, "children"> : T;
export type WithoutChildren<T> = T extends { children?: any } ? Omit<T, 'children'> : T;
export type WithoutChildrenOrChild<T> = WithoutChildren<WithoutChild<T>>;
export type WithElementRef<T, U extends HTMLElement = HTMLElement> = T & { ref?: U | null };

View file

@ -1,9 +1,9 @@
<script lang="ts">
import { Command, type Child } from "@tauri-apps/plugin-shell";
import { SvelteMap } from "svelte/reactivity";
import { Unpackr } from "msgpackr";
import { tick } from "svelte";
import { VList } from "virtua/svelte";
import { Command, type Child } from '@tauri-apps/plugin-shell';
import { SvelteMap } from 'svelte/reactivity';
import { Unpackr } from 'msgpackr';
import { tick } from 'svelte';
import { VList } from 'virtua/svelte';
interface UINode {
id: number;
@ -21,7 +21,7 @@
type ListItem = {
id: number;
type: "header" | "item";
type: 'header' | 'item';
props: Record<string, any>;
height: number;
};
@ -41,21 +41,21 @@
for (const childId of root.children) {
const sectionNode = uiTree.get(childId);
if (sectionNode && sectionNode.type === "ListSection") {
if (sectionNode && sectionNode.type === 'ListSection') {
newFlatList.push({
id: sectionNode.id,
type: "header",
type: 'header',
props: sectionNode.props,
height: HEADER_HEIGHT,
height: HEADER_HEIGHT
});
for (const itemId of sectionNode.children) {
const itemNode = uiTree.get(itemId);
if (itemNode) {
newFlatList.push({
id: itemNode.id,
type: "item",
type: 'item',
props: itemNode.props,
height: ITEM_HEIGHT,
height: ITEM_HEIGHT
});
}
}
@ -80,7 +80,7 @@
const message = unpackr.unpack(messagePayload);
handleSidecarMessage(message);
} catch (e) {
console.error("Failed to unpack sidecar message:", e);
console.error('Failed to unpack sidecar message:', e);
}
} else {
break;
@ -89,39 +89,36 @@
}
async function connectAndRun() {
const command = Command.sidecar("binaries/app", undefined, {
encoding: "raw",
const command = Command.sidecar('binaries/app', undefined, {
encoding: 'raw'
});
command.stdout.on("data", (chunk) => {
command.stdout.on('data', (chunk) => {
try {
receiveBuffer = Buffer.concat([receiveBuffer, Buffer.from(chunk)]);
processReceiveBuffer();
} catch (e) {
console.error("Failed to parse sidecar message:", chunk, e);
console.error('Failed to parse sidecar message:', chunk, e);
}
});
command.stderr.on("data", (line) => {
command.stderr.on('data', (line) => {
sidecarLogs = [...sidecarLogs, `STDERR: ${line}`];
});
sidecarChild = await command.spawn();
sidecarLogs = [
...sidecarLogs,
`Sidecar spawned with PID: ${sidecarChild.pid}`,
];
sidecarLogs = [...sidecarLogs, `Sidecar spawned with PID: ${sidecarChild.pid}`];
if (sidecarChild) {
sidecarChild.write(JSON.stringify({ action: "run-plugin" }) + "\n");
sidecarChild.write(JSON.stringify({ action: 'run-plugin' }) + '\n');
}
}
connectAndRun();
return () => {
console.log("Component unmounting, killing sidecar...");
console.log('Component unmounting, killing sidecar...');
sidecarChild?.kill();
};
});
function sendToSidecar(message: object) {
if (sidecarChild) {
sidecarChild.write(JSON.stringify(message) + "\n");
sidecarChild.write(JSON.stringify(message) + '\n');
}
}
@ -132,7 +129,7 @@
getMutableNode: (id: number) => UINode | undefined
) {
switch (command.type) {
case "REPLACE_CHILDREN": {
case 'REPLACE_CHILDREN': {
const { parentId, childrenIds } = command.payload;
const parentNode = getMutableNode(parentId);
if (parentNode) {
@ -140,17 +137,17 @@
}
break;
}
case "log":
console.log("SIDECAR:", command.payload);
case 'log':
console.log('SIDECAR:', command.payload);
sidecarLogs = [...sidecarLogs, command.payload];
break;
case "CREATE_TEXT_INSTANCE":
case "CREATE_INSTANCE": {
case 'CREATE_TEXT_INSTANCE':
case 'CREATE_INSTANCE': {
const { id, type, props } = command.payload;
tempTree.set(id, { id, type, props, children: [] });
break;
}
case "UPDATE_PROPS": {
case 'UPDATE_PROPS': {
const { id, props } = command.payload;
const node = getMutableNode(id);
if (node) {
@ -158,9 +155,9 @@
}
break;
}
case "APPEND_CHILD": {
case 'APPEND_CHILD': {
const { parentId, childId } = command.payload;
if (parentId === "root") {
if (parentId === 'root') {
tempState.rootNodeId = childId;
} else {
const parentNode = getMutableNode(parentId);
@ -172,7 +169,7 @@
}
break;
}
case "REMOVE_CHILD": {
case 'REMOVE_CHILD': {
const { parentId, childId } = command.payload;
const parentNode = getMutableNode(parentId);
if (parentNode) {
@ -181,7 +178,7 @@
}
break;
}
case "INSERT_BEFORE": {
case 'INSERT_BEFORE': {
const { parentId, childId, beforeId } = command.payload;
const parentNode = getMutableNode(parentId);
if (parentNode) {
@ -200,8 +197,7 @@
}
function handleSidecarMessage(message: any) {
const commands =
message.type === "BATCH_UPDATE" ? message.payload : [message];
const commands = message.type === 'BATCH_UPDATE' ? message.payload : [message];
if (commands.length === 0) {
updateCounter++;
return;
@ -216,7 +212,7 @@
const clonedNode = {
...originalNode,
props: { ...originalNode.props },
children: [...originalNode.children],
children: [...originalNode.children]
};
tempTree.set(id, clonedNode);
mutatedIds.add(id);
@ -236,41 +232,34 @@
}
function dispatchEvent(instanceId: number, handlerName: string, args: any[]) {
console.log(
`[EVENT] Dispatching '${handlerName}' to instance ${instanceId}`
);
console.log(`[EVENT] Dispatching '${handlerName}' to instance ${instanceId}`);
sendToSidecar({
action: "dispatch-event",
payload: { instanceId, handlerName, args },
action: 'dispatch-event',
payload: { instanceId, handlerName, args }
});
}
</script>
<main class="flex grow flex-col h-screen">
<main class="flex h-screen grow flex-col">
{#if rootNodeId}
{@const rootNode = uiTree.get(rootNodeId)}
{#if rootNode?.type === "List"}
{#if rootNode?.type === 'List'}
<div class="flex h-full flex-col">
<input
type="text"
class="w-full border-b border-gray-300 px-4 py-3 text-lg focus:border-blue-500 focus:outline-none"
placeholder="Search Emojis..."
oninput={(e) =>
dispatchEvent(rootNode.id, "onSearchTextChange", [
e.currentTarget.value,
])}
oninput={(e) => dispatchEvent(rootNode.id, 'onSearchTextChange', [e.currentTarget.value])}
/>
<div class="flex-grow">
<VList data={flatList} getKey={(item) => item.id} class="h-full">
{#snippet children(item)}
{#if item.type === "header"}
<h3
class="px-4 pb-1 pt-2.5 text-xs font-semibold uppercase text-gray-500"
>
{#if item.type === 'header'}
<h3 class="px-4 pt-2.5 pb-1 text-xs font-semibold text-gray-500 uppercase">
{item.props.title}
</h3>
{:else if item.type === "item"}
{:else if item.type === 'item'}
<div class="flex items-center gap-3 px-4 py-2">
<span class="text-lg">{item.props.icon}</span>
<span>{item.props.title}</span>

View file

@ -1,15 +1,15 @@
// Tauri doesn't have a Node.js server to do proper SSR
// so we will use adapter-static to prerender the app (SSG)
// See: https://v2.tauri.app/start/frontend/sveltekit/ for more info
import adapter from "@sveltejs/adapter-static";
import { vitePreprocess } from "@sveltejs/vite-plugin-svelte";
import adapter from '@sveltejs/adapter-static';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
/** @type {import('@sveltejs/kit').Config} */
const config = {
preprocess: vitePreprocess(),
kit: {
adapter: adapter(),
},
adapter: adapter()
}
};
export default config;

View file

@ -1,7 +1,7 @@
import { defineConfig } from "vite";
import tailwindcss from "@tailwindcss/vite";
import { sveltekit } from "@sveltejs/kit/vite";
import { nodePolyfills } from "vite-plugin-node-polyfills";
import { defineConfig } from 'vite';
import tailwindcss from '@tailwindcss/vite';
import { sveltekit } from '@sveltejs/kit/vite';
import { nodePolyfills } from 'vite-plugin-node-polyfills';
const host = process.env.TAURI_DEV_HOST;
@ -20,14 +20,14 @@ export default defineConfig(async () => ({
host: host || false,
hmr: host
? {
protocol: "ws",
protocol: 'ws',
host,
port: 1421,
port: 1421
}
: undefined,
watch: {
// 3. tell vite to ignore watching `src-tauri`
ignored: ["**/src-tauri/**"],
},
},
ignored: ['**/src-tauri/**']
}
}
}));