(null);
const treeRef = useRef(null);
const filterRef = useRef(null);
@@ -227,7 +230,7 @@ function Sidebar({ className }: { className?: string }) {
);
const clearFilterText = useCallback(() => {
- jotaiStore.set(sidebarFilterAtom, { text: "", key: `${Math.random()}` });
+ setSidebarFilterText("");
requestAnimationFrame(() => {
filterRef.current?.focus();
});
@@ -252,6 +255,13 @@ function Sidebar({ className }: { className?: string }) {
[],
);
+ const applyFilterExample = useCallback((text: string) => {
+ setSidebarFilterText(text);
+ requestAnimationFrame(() => {
+ filterRef.current?.focus();
+ });
+ }, []);
+
const treeHasFocus = useCallback(() => treeRef.current?.hasFocus() ?? false, []);
const getSelectedTreeModels = useCallback(
@@ -654,8 +664,43 @@ function Sidebar({ className }: { className?: string }) {
)}
{allHidden ? (
-
- No results for
{filterText.text}
+
+ {(emptyFilterSuggestions?.length ?? 0) > 0 ? (
+
+
+ No results, but found matches for{" "}
+ {emptyFilterSuggestions?.map((suggestion, i) => (
+
+ {i > 0 && " or "}
+
+
+ ))}
+
+
+ ) : (
+
+
+ No results for{" "}
+
+ {filterText.text}
+
+
+
+ )}
) : (
({
key: "",
});
-const sidebarTreeAtom = atom<[TreeNode, FieldDef[]] | null>((get) => {
+type SidebarFilterSuggestion = {
+ field: string;
+ filterText: string;
+};
+
+function setSidebarFilterText(text: string) {
+ jotaiStore.set(sidebarFilterAtom, { text, key: `${Math.random()}` });
+}
+
+function getSidebarSuggestionValue(ast: Ast | null) {
+ if (ast == null) return null;
+
+ if (ast.type === "Term" || ast.type === "Phrase") {
+ const value = ast.value.trim();
+ return value.length > 0 ? value : null;
+ }
+
+ if (ast.type === "Field") {
+ const value = ast.value.trim();
+ return value.length > 0 ? value : null;
+ }
+
+ return null;
+}
+
+function sidebarFieldMatchesValue(fieldValue: string, filterValue: string) {
+ return fieldValue.toLowerCase().includes(filterValue.toLowerCase());
+}
+
+const sidebarSuggestionFieldOrder = [
+ "url",
+ "folder",
+ "method",
+ "type",
+ "grpc_service",
+ "grpc_method",
+ "name",
+];
+
+const sidebarTreeAtom = atom<
+ [TreeNode, FieldDef[], SidebarFilterSuggestion[]] | null
+>((get) => {
const allModels = get(memoAllPotentialChildrenAtom);
const activeWorkspace = get(activeWorkspaceAtom);
const filter = get(sidebarFilterAtom);
@@ -807,9 +893,11 @@ const sidebarTreeAtom = atom<[TreeNode, FieldDef[]] | null>((get)
}
const queryAst = parseQuery(filter.text);
+ const suggestionValue = getSidebarSuggestionValue(queryAst);
// returns true if this node OR any child matches the filter
const allFields: Record> = {};
+ const suggestionFields = new Set();
const build = (node: TreeNode, depth: number): boolean => {
const childItems = childrenMap[node.item.id] ?? [];
let matchesSelf = true;
@@ -821,6 +909,13 @@ const sidebarTreeAtom = atom<[TreeNode, FieldDef[]] | null>((get)
if (!value) continue;
allFields[field] = allFields[field] ?? new Set();
allFields[field].add(value);
+ if (
+ isLeafNode &&
+ suggestionValue != null &&
+ sidebarFieldMatchesValue(value, suggestionValue)
+ ) {
+ suggestionFields.add(field);
+ }
}
if (queryAst != null) {
@@ -874,7 +969,18 @@ const sidebarTreeAtom = atom<[TreeNode, FieldDef[]] | null>((get)
values: Array.from(values).filter((v) => v.length < 20),
});
}
- return [root, fields] as const;
+ const suggestions = Array.from(suggestionFields)
+ .sort((a, b) => {
+ const aIndex = sidebarSuggestionFieldOrder.indexOf(a);
+ const bIndex = sidebarSuggestionFieldOrder.indexOf(b);
+ if (aIndex === -1 && bIndex === -1) return a.localeCompare(b);
+ return (aIndex === -1 ? Infinity : aIndex) - (bIndex === -1 ? Infinity : bIndex);
+ })
+ .map((field) => ({
+ field,
+ filterText: formatFieldFilter(field, suggestionValue ?? ""),
+ }));
+ return [root, fields, suggestions] as const;
});
const sidebarGitStatusByModelIdAtom = atom>((get) => {
diff --git a/apps/yaak-client/components/core/Editor/filter/extension.ts b/apps/yaak-client/components/core/Editor/filter/extension.ts
index 88f6c4bb..722c442a 100644
--- a/apps/yaak-client/components/core/Editor/filter/extension.ts
+++ b/apps/yaak-client/components/core/Editor/filter/extension.ts
@@ -15,8 +15,9 @@ export interface FilterOptions {
fields: FieldDef[] | null; // e.g., ['method','status','path'] or [{name:'tag', values:()=>cachedTags}]
}
-const IDENT = /[A-Za-z0-9_/]+$/;
-const IDENT_ONLY = /^[A-Za-z0-9_/]+$/;
+const FIELD_IDENT = /[A-Za-z0-9_/]+$/;
+const VALUE_IDENT = /[A-Za-z0-9_\-./]+$/;
+const VALUE_IDENT_ONLY = /^[A-Za-z0-9_\-./]+$/;
function normalizeFields(fields: FieldDef[]): {
fieldNames: string[];
@@ -31,14 +32,37 @@ function normalizeFields(fields: FieldDef[]): {
return { fieldNames, fieldMap };
}
-function wordBefore(doc: string, pos: number): { from: number; to: number; text: string } | null {
+function wordBefore(
+ doc: string,
+ pos: number,
+ pattern: RegExp,
+): { from: number; to: number; text: string } | null {
const upto = doc.slice(0, pos);
- const m = upto.match(IDENT);
+ const m = upto.match(pattern);
if (!m) return null;
const from = pos - m[0].length;
return { from, to: pos, text: m[0] };
}
+function fieldCompletionFrom(doc: string, pos: number): { from: number; includeAt: boolean } | null {
+ const w = wordBefore(doc, pos, FIELD_IDENT);
+ const from = w?.from ?? pos;
+ const beforeToken = doc[from - 1];
+
+ if (from === 0 || (beforeToken != null && /\s/.test(beforeToken))) {
+ return { from, includeAt: true };
+ }
+
+ if (beforeToken === "@") {
+ const beforeAt = doc[from - 2];
+ if (from === 1 || (beforeAt != null && /\s/.test(beforeAt))) {
+ return { from, includeAt: false };
+ }
+ }
+
+ return null;
+}
+
function inPhrase(ctx: CompletionContext): boolean {
// Lezer node names from your grammar: Phrase is the quoted token
let n: SyntaxNode | null = syntaxTree(ctx.state).resolveInner(ctx.pos, -1);
@@ -81,7 +105,7 @@ function contextInfo(stateDoc: string, pos: number) {
if (inValue) {
// word before the colon = field name
const beforeColon = stateDoc.slice(0, lastColon);
- const m = beforeColon.match(IDENT);
+ const m = beforeColon.match(FIELD_IDENT);
fieldName = m ? m[0] : null;
// nothing (or only spaces) typed after the colon?
@@ -93,15 +117,16 @@ function contextInfo(stateDoc: string, pos: number) {
}
/** Build a completion list for field names */
-function fieldNameCompletions(fieldNames: string[]): Completion[] {
+function fieldNameCompletions(fieldNames: string[], includeAt: boolean): Completion[] {
return fieldNames.map((name) => ({
label: name,
type: "property",
apply: (view, _completion, from, to) => {
- // Insert "name:" (leave cursor right after colon)
+ // Leave cursor right after the field filter colon.
+ const insert = `${includeAt ? "@" : ""}${name}:`;
view.dispatch({
- changes: { from, to, insert: `${name}:` },
- selection: { anchor: from + name.length + 1 },
+ changes: { from, to, insert },
+ selection: { anchor: from + insert.length },
});
startCompletion(view);
},
@@ -115,7 +140,7 @@ function fieldValueCompletions(
if (!def || !def.values) return null;
const vals = Array.isArray(def.values) ? def.values : def.values();
return vals.map((v) => ({
- label: v.match(IDENT_ONLY) ? v : `"${v}"`,
+ label: v.match(VALUE_IDENT_ONLY) ? v : `"${v}"`,
displayLabel: v,
type: "constant",
}));
@@ -132,14 +157,13 @@ function makeCompletionSource(opts: FilterOptions) {
return null;
}
- const w = wordBefore(doc, pos);
- const from = w?.from ?? pos;
- const to = pos;
-
const { inValue, fieldName, emptyAfterColon } = contextInfo(doc, pos);
// In field value position
if (inValue && fieldName) {
+ const w = wordBefore(doc, pos, VALUE_IDENT);
+ const from = w?.from ?? pos;
+ const to = pos;
const valDefs = fieldMap[fieldName];
const vals = fieldValueCompletions(valDefs);
@@ -162,7 +186,11 @@ function makeCompletionSource(opts: FilterOptions) {
}
// Not in a value: suggest field names (and maybe boolean ops)
- const options: Completion[] = fieldNameCompletions(fieldNames);
+ const completion = fieldCompletionFrom(doc, pos);
+ if (completion == null) return null;
+ const { from, includeAt } = completion;
+ const to = pos;
+ const options: Completion[] = fieldNameCompletions(fieldNames, includeAt);
return { from, to, options, filter: true };
};
diff --git a/apps/yaak-client/components/core/Editor/filter/filter.grammar b/apps/yaak-client/components/core/Editor/filter/filter.grammar
index 0d857e72..077ab945 100644
--- a/apps/yaak-client/components/core/Editor/filter/filter.grammar
+++ b/apps/yaak-client/components/core/Editor/filter/filter.grammar
@@ -6,6 +6,7 @@
LParen { "(" }
RParen { ")" }
+ At { "@" }
Colon { ":" }
Not { "-" | "NOT" }
@@ -60,7 +61,7 @@ Field {
}
FieldName {
- Word
+ At? Word
}
FieldValue {
diff --git a/apps/yaak-client/components/core/Editor/filter/filter.ts b/apps/yaak-client/components/core/Editor/filter/filter.ts
index f7a1dae3..65767606 100644
--- a/apps/yaak-client/components/core/Editor/filter/filter.ts
+++ b/apps/yaak-client/components/core/Editor/filter/filter.ts
@@ -1,27 +1,22 @@
-/* oxlint-disable */
// This file was generated by lezer-generator. You probably shouldn't edit it.
-import { LRParser } from "@lezer/lr";
-import { highlight } from "./highlight";
+import {LRParser} from "@lezer/lr"
+import {highlight} from "./highlight"
export const parser = LRParser.deserialize({
version: 14,
- states:
- "%QOVQPOOPeOPOOOVQPO'#CfOjQPO'#ChO!XQPO'#CgOOQO'#Cc'#CcOVQPO'#CaOOQO'#Ca'#CaO!oQPO'#C`O!|QPO'#C_OOQO'#C^'#C^QOQPOOPOOO'#Cp'#CpP#XOPO)C>jO#`QPO,59QO#eQPO,59ROOQO,58{,58{OVQPO'#CqOOQO'#Cq'#CqO#mQPO,58zOVQPO'#CrO#zQPO,58yPOOO-E6n-E6nOOQO1G.l1G.lOOQO'#Cm'#CmOOQO'#Ck'#CkOOQO1G.m1G.mOOQO,59],59]OOQO-E6o-E6oOOQO,59^,59^OOQO-E6p-E6p",
- stateData:
- "$]~OiPQ~OUUOXQO]RO`TO~Oi[O~OUaXXaX]aX^[X`aXbaXcaXgaXWaX~O^_O~OUUOXQO]RO`TObaO~OcSXgSXWSX~P!^OcdOgRXWRX~Oi[O~Qh]WgO~O]hO`iO~OcSagSaWSa~P!^OcdOgRaWRa~OUbc]c~",
- goto: "#hgPPhnryP!YPP!c!c!lPP!uP!xPP#U#[#bQZOR^QTYOQSXOQRmdUWOQdQ`USbWcRka_VOQUWacd_TOQUWacd_SOQUWacdRj_^TOQUWacdRi_Q]PRf]QcWRlcQeXRne",
- nodeNames:
- "⚠ Query Expr OrExpr AndExpr Unary Not Primary RParen LParen Group Field FieldName Word Colon FieldValue Phrase Term And Or",
- maxTerm: 25,
+ states: "%^OVQPOOPhOPOOOVQPO'#CfOmQPO'#ChO!_QPO'#ChO!dQPO'#CgOOQO'#Cc'#CcOVQPO'#CaOOQO'#Ca'#CaO!iQPO'#C`O!yQPO'#C_OOQO'#C^'#C^QOQPOOPOOO'#Cq'#CqP#UOPO)C>kO#]QPO,59QOOQO,59S,59SO#bQPO,59ROOQO,58{,58{OVQPO'#CrOOQO'#Cr'#CrO#jQPO,58zOVQPO'#CsO#zQPO,58yPOOO-E6o-E6oOOQO1G.l1G.lOOQO'#Cn'#CnOOQO'#Cl'#ClOOQO1G.m1G.mOOQO,59^,59^OOQO-E6p-E6pOOQO,59_,59_OOQO-E6q-E6q",
+ stateData: "$]~OjPQ~OUVOXQO]SO^ROaUO~Oj]O~OUbXXbX]bX^bX_[XabXcbXdbXhbXWbX~O^`O~O_aO~OccOdSXhSXWSX~PVOdfOhRXWRX~Oj]O~Qi]WiO~O^jOakO~OccOdSahSaWSa~PVOdfOhRaWRa~OUcd^d~",
+ goto: "#ihPPioszP!ZPP!d!d!mPPP!vP!yPP#V#]#cQ[OR_QTZOQSYOQRofUXOQfQbVSdXeRmc_WOQVXcef_UOQVXcef_TOQVXcefRla^UOQVXcefRkaQ^PRh^QeXRneQgYRpg",
+ nodeNames: "⚠ Query Expr OrExpr AndExpr Unary Not Primary RParen LParen Group Field FieldName At Word Colon FieldValue Phrase Term And Or",
+ maxTerm: 26,
nodeProps: [
- ["openedBy", 8, "LParen"],
- ["closedBy", 9, "RParen"],
+ ["openedBy", 8,"LParen"],
+ ["closedBy", 9,"RParen"]
],
propSources: [highlight],
- skippedNodes: [0, 20],
+ skippedNodes: [0,21],
repeatNodeCount: 3,
- tokenData:
- ")f~RgX^!jpq!jrs#_xy${yz%Q}!O%V!Q![%[![!]%m!c!d%r!d!p%[!p!q'V!q!r(j!r!}%[#R#S%[#T#o%[#y#z!j$f$g!j#BY#BZ!j$IS$I_!j$I|$JO!j$JT$JU!j$KV$KW!j&FU&FV!j~!oYi~X^!jpq!j#y#z!j$f$g!j#BY#BZ!j$IS$I_!j$I|$JO!j$JT$JU!j$KV$KW!j&FU&FV!j~#bVOr#_rs#ws#O#_#O#P#|#P;'S#_;'S;=`$u<%lO#_~#|O`~~$PRO;'S#_;'S;=`$Y;=`O#_~$]WOr#_rs#ws#O#_#O#P#|#P;'S#_;'S;=`$u;=`<%l#_<%lO#_~$xP;=`<%l#_~%QOX~~%VOW~~%[OU~~%aS]~!Q![%[!c!}%[#R#S%[#T#o%[~%rO^~~%wU]~!Q![%[!c!p%[!p!q&Z!q!}%[#R#S%[#T#o%[~&`U]~!Q![%[!c!f%[!f!g&r!g!}%[#R#S%[#T#o%[~&ySb~]~!Q![%[!c!}%[#R#S%[#T#o%[~'[U]~!Q![%[!c!q%[!q!r'n!r!}%[#R#S%[#T#o%[~'sU]~!Q![%[!c!v%[!v!w(V!w!}%[#R#S%[#T#o%[~(^SU~]~!Q![%[!c!}%[#R#S%[#T#o%[~(oU]~!Q![%[!c!t%[!t!u)R!u!}%[#R#S%[#T#o%[~)YSc~]~!Q![%[!c!}%[#R#S%[#T#o%[",
+ tokenData: ")n~RhX^!mpq!mrs#bxy%Oyz%T}!O%Y!Q![%_![!]%p!b!c%u!c!d%z!d!p%_!p!q'_!q!r(r!r!}%_#R#S%_#T#o%_#y#z!m$f$g!m#BY#BZ!m$IS$I_!m$I|$JO!m$JT$JU!m$KV$KW!m&FU&FV!m~!rYj~X^!mpq!m#y#z!m$f$g!m#BY#BZ!m$IS$I_!m$I|$JO!m$JT$JU!m$KV$KW!m&FU&FV!m~#eVOr#brs#zs#O#b#O#P$P#P;'S#b;'S;=`$x<%lO#b~$POa~~$SRO;'S#b;'S;=`$];=`O#b~$`WOr#brs#zs#O#b#O#P$P#P;'S#b;'S;=`$x;=`<%l#b<%lO#b~${P;=`<%l#b~%TOX~~%YOW~~%_OU~~%dS^~!Q![%_!c!}%_#R#S%_#T#o%_~%uO_~~%zO]~~&PU^~!Q![%_!c!p%_!p!q&c!q!}%_#R#S%_#T#o%_~&hU^~!Q![%_!c!f%_!f!g&z!g!}%_#R#S%_#T#o%_~'RSc~^~!Q![%_!c!}%_#R#S%_#T#o%_~'dU^~!Q![%_!c!q%_!q!r'v!r!}%_#R#S%_#T#o%_~'{U^~!Q![%_!c!v%_!v!w(_!w!}%_#R#S%_#T#o%_~(fSU~^~!Q![%_!c!}%_#R#S%_#T#o%_~(wU^~!Q![%_!c!t%_!t!u)Z!u!}%_#R#S%_#T#o%_~)bSd~^~!Q![%_!c!}%_#R#S%_#T#o%_",
tokenizers: [0],
- topRules: { Query: [0, 1] },
- tokenPrec: 145,
-});
+ topRules: {"Query":[0,1]},
+ tokenPrec: 145
+})
diff --git a/apps/yaak-client/components/core/Editor/filter/format.test.ts b/apps/yaak-client/components/core/Editor/filter/format.test.ts
new file mode 100644
index 00000000..c7f90a5c
--- /dev/null
+++ b/apps/yaak-client/components/core/Editor/filter/format.test.ts
@@ -0,0 +1,33 @@
+import { describe, expect, test } from "vite-plus/test";
+import { formatFieldFilter } from "./format";
+import { evaluate, parseQuery } from "./query";
+
+function matchesFormattedUrl(value: string) {
+ return evaluate(parseQuery(formatFieldFilter("url", value)), {
+ fields: { url: value },
+ });
+}
+
+describe("formatFieldFilter", () => {
+ test("keeps URL-like values bare", () => {
+ expect(formatFieldFilter("url", "yaak.app/foo-bar")).toBe("@url:yaak.app/foo-bar");
+ expect(matchesFormattedUrl("yaak.app/foo-bar")).toBe(true);
+ });
+
+ test("quotes values that start with an operator token", () => {
+ expect(formatFieldFilter("url", "-foo")).toBe('@url:"-foo"');
+ expect(matchesFormattedUrl("-foo")).toBe(true);
+ });
+
+ test("quotes boolean operator words", () => {
+ expect(formatFieldFilter("url", "AND")).toBe('@url:"AND"');
+ expect(formatFieldFilter("url", "or")).toBe('@url:"or"');
+ expect(formatFieldFilter("url", "Not")).toBe('@url:"Not"');
+ expect(matchesFormattedUrl("AND")).toBe(true);
+ });
+
+ test("escapes quoted values", () => {
+ expect(formatFieldFilter("url", 'say "hi"')).toBe('@url:"say \\"hi\\""');
+ expect(matchesFormattedUrl('say "hi"')).toBe(true);
+ });
+});
diff --git a/apps/yaak-client/components/core/Editor/filter/format.ts b/apps/yaak-client/components/core/Editor/filter/format.ts
new file mode 100644
index 00000000..96173353
--- /dev/null
+++ b/apps/yaak-client/components/core/Editor/filter/format.ts
@@ -0,0 +1,9 @@
+const bareFieldValue = /^[A-Za-z0-9_./][A-Za-z0-9_\-./]*$/;
+const operatorWord = /^(?:AND|OR|NOT)$/i;
+
+export function formatFieldFilter(field: string, value: string) {
+ const escapedValue = value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
+ const filterValue =
+ bareFieldValue.test(value) && !operatorWord.test(value) ? value : `"${escapedValue}"`;
+ return `@${field}:${filterValue}`;
+}
diff --git a/apps/yaak-client/components/core/Editor/filter/highlight.ts b/apps/yaak-client/components/core/Editor/filter/highlight.ts
index 0491e5bb..c6092819 100644
--- a/apps/yaak-client/components/core/Editor/filter/highlight.ts
+++ b/apps/yaak-client/components/core/Editor/filter/highlight.ts
@@ -16,6 +16,7 @@ export const highlight = styleTags({
Phrase: t.string, // "quoted string"
// Fields
+ "FieldName/At": t.attributeName,
"FieldName/Word": t.attributeName,
"FieldValue/Term/Word": t.attributeValue,
});
diff --git a/package.json b/package.json
index 8f2265b4..439d8b10 100644
--- a/package.json
+++ b/package.json
@@ -75,6 +75,7 @@
"start": "npm run client:dev",
"client:build": "node scripts/run-build.mjs client",
"client:dev": "node scripts/run-dev.mjs client",
+ "client:bundle": "node scripts/run-build.mjs client --config crates-tauri/yaak-app-client/tauri.release.conf.json --no-sign",
"proxy:build": "node scripts/run-build.mjs proxy",
"proxy:dev": "node scripts/run-dev.mjs proxy",
"migration": "node scripts/create-migration.cjs",
diff --git a/packages/plugin-runtime-types/src/bindings/gen_events.ts b/packages/plugin-runtime-types/src/bindings/gen_events.ts
index df3a1378..abd4fac3 100644
--- a/packages/plugin-runtime-types/src/bindings/gen_events.ts
+++ b/packages/plugin-runtime-types/src/bindings/gen_events.ts
@@ -18,12 +18,12 @@ export type CallHttpAuthenticationActionRequest = { index: number, pluginRefId:
export type CallHttpAuthenticationRequest = { contextId: string, values: { [key in string]?: JsonPrimitive }, method: string, url: string, headers: Array, };
-export type CallHttpAuthenticationResponse = {
+export type CallHttpAuthenticationResponse = {
/**
* HTTP headers to add to the request. Existing headers will be replaced, while
* new headers will be added.
*/
-setHeaders?: Array,
+setHeaders?: Array,
/**
* Query parameters to add to the request. Existing params will be replaced, while
* new params will be added.
@@ -78,7 +78,7 @@ export type ExportHttpRequestRequest = { httpRequest: HttpRequest, };
export type ExportHttpRequestResponse = { content: string, };
-export type FileFilter = { name: string,
+export type FileFilter = { name: string,
/**
* File extensions to require
*/
@@ -100,149 +100,149 @@ export type FormInputAccordion = { label: string, inputs?: Array, hid
export type FormInputBanner = { inputs?: Array, hidden?: boolean, color?: Color, };
-export type FormInputBase = {
+export type FormInputBase = {
/**
* The name of the input. The value will be stored at this object attribute in the resulting data
*/
-name: string,
+name: string,
/**
* Whether this input is visible for the given configuration. Use this to
* make branching forms.
*/
-hidden?: boolean,
+hidden?: boolean,
/**
* Whether the user must fill in the argument
*/
-optional?: boolean,
+optional?: boolean,
/**
* The label of the input
*/
-label?: string,
+label?: string,
/**
* Visually hide the label of the input
*/
-hideLabel?: boolean,
+hideLabel?: boolean,
/**
* The default value
*/
-defaultValue?: string, disabled?: boolean,
+defaultValue?: string, disabled?: boolean,
/**
* Longer description of the input, likely shown in a tooltip
*/
description?: string, };
-export type FormInputCheckbox = {
+export type FormInputCheckbox = {
/**
* The name of the input. The value will be stored at this object attribute in the resulting data
*/
-name: string,
+name: string,
/**
* Whether this input is visible for the given configuration. Use this to
* make branching forms.
*/
-hidden?: boolean,
+hidden?: boolean,
/**
* Whether the user must fill in the argument
*/
-optional?: boolean,
+optional?: boolean,
/**
* The label of the input
*/
-label?: string,
+label?: string,
/**
* Visually hide the label of the input
*/
-hideLabel?: boolean,
+hideLabel?: boolean,
/**
* The default value
*/
-defaultValue?: string, disabled?: boolean,
+defaultValue?: string, disabled?: boolean,
/**
* Longer description of the input, likely shown in a tooltip
*/
description?: string, };
-export type FormInputEditor = {
+export type FormInputEditor = {
/**
* Placeholder for the text input
*/
-placeholder?: string | null,
+placeholder?: string | null,
/**
* Don't show the editor gutter (line numbers, folds, etc.)
*/
-hideGutter?: boolean,
+hideGutter?: boolean,
/**
* Language for syntax highlighting
*/
-language?: EditorLanguage, readOnly?: boolean,
+language?: EditorLanguage, readOnly?: boolean,
/**
* Fixed number of visible rows
*/
-rows?: number, completionOptions?: Array,
+rows?: number, completionOptions?: Array,
/**
* The name of the input. The value will be stored at this object attribute in the resulting data
*/
-name: string,
+name: string,
/**
* Whether this input is visible for the given configuration. Use this to
* make branching forms.
*/
-hidden?: boolean,
+hidden?: boolean,
/**
* Whether the user must fill in the argument
*/
-optional?: boolean,
+optional?: boolean,
/**
* The label of the input
*/
-label?: string,
+label?: string,
/**
* Visually hide the label of the input
*/
-hideLabel?: boolean,
+hideLabel?: boolean,
/**
* The default value
*/
-defaultValue?: string, disabled?: boolean,
+defaultValue?: string, disabled?: boolean,
/**
* Longer description of the input, likely shown in a tooltip
*/
description?: string, };
-export type FormInputFile = {
+export type FormInputFile = {
/**
* The title of the file selection window
*/
-title: string,
+title: string,
/**
* Allow selecting multiple files
*/
-multiple?: boolean, directory?: boolean, defaultPath?: string, filters?: Array,
+multiple?: boolean, directory?: boolean, defaultPath?: string, filters?: Array,
/**
* The name of the input. The value will be stored at this object attribute in the resulting data
*/
-name: string,
+name: string,
/**
* Whether this input is visible for the given configuration. Use this to
* make branching forms.
*/
-hidden?: boolean,
+hidden?: boolean,
/**
* Whether the user must fill in the argument
*/
-optional?: boolean,
+optional?: boolean,
/**
* The label of the input
*/
-label?: string,
+label?: string,
/**
* Visually hide the label of the input
*/
-hideLabel?: boolean,
+hideLabel?: boolean,
/**
* The default value
*/
-defaultValue?: string, disabled?: boolean,
+defaultValue?: string, disabled?: boolean,
/**
* Longer description of the input, likely shown in a tooltip
*/
@@ -250,63 +250,63 @@ description?: string, };
export type FormInputHStack = { inputs?: Array, hidden?: boolean, };
-export type FormInputHttpRequest = {
+export type FormInputHttpRequest = {
/**
* The name of the input. The value will be stored at this object attribute in the resulting data
*/
-name: string,
+name: string,
/**
* Whether this input is visible for the given configuration. Use this to
* make branching forms.
*/
-hidden?: boolean,
+hidden?: boolean,
/**
* Whether the user must fill in the argument
*/
-optional?: boolean,
+optional?: boolean,
/**
* The label of the input
*/
-label?: string,
+label?: string,
/**
* Visually hide the label of the input
*/
-hideLabel?: boolean,
+hideLabel?: boolean,
/**
* The default value
*/
-defaultValue?: string, disabled?: boolean,
+defaultValue?: string, disabled?: boolean,
/**
* Longer description of the input, likely shown in a tooltip
*/
description?: string, };
-export type FormInputKeyValue = {
+export type FormInputKeyValue = {
/**
* The name of the input. The value will be stored at this object attribute in the resulting data
*/
-name: string,
+name: string,
/**
* Whether this input is visible for the given configuration. Use this to
* make branching forms.
*/
-hidden?: boolean,
+hidden?: boolean,
/**
* Whether the user must fill in the argument
*/
-optional?: boolean,
+optional?: boolean,
/**
* The label of the input
*/
-label?: string,
+label?: string,
/**
* Visually hide the label of the input
*/
-hideLabel?: boolean,
+hideLabel?: boolean,
/**
* The default value
*/
-defaultValue?: string, disabled?: boolean,
+defaultValue?: string, disabled?: boolean,
/**
* Longer description of the input, likely shown in a tooltip
*/
@@ -314,36 +314,36 @@ description?: string, };
export type FormInputMarkdown = { content: string, hidden?: boolean, };
-export type FormInputSelect = {
+export type FormInputSelect = {
/**
* The options that will be available in the select input
*/
-options: Array,
+options: Array,
/**
* The name of the input. The value will be stored at this object attribute in the resulting data
*/
-name: string,
+name: string,
/**
* Whether this input is visible for the given configuration. Use this to
* make branching forms.
*/
-hidden?: boolean,
+hidden?: boolean,
/**
* Whether the user must fill in the argument
*/
-optional?: boolean,
+optional?: boolean,
/**
* The label of the input
*/
-label?: string,
+label?: string,
/**
* Visually hide the label of the input
*/
-hideLabel?: boolean,
+hideLabel?: boolean,
/**
* The default value
*/
-defaultValue?: string, disabled?: boolean,
+defaultValue?: string, disabled?: boolean,
/**
* Longer description of the input, likely shown in a tooltip
*/
@@ -351,44 +351,44 @@ description?: string, };
export type FormInputSelectOption = { label: string, value: string, };
-export type FormInputText = {
+export type FormInputText = {
/**
* Placeholder for the text input
*/
-placeholder?: string | null,
+placeholder?: string | null,
/**
* Placeholder for the text input
*/
-password?: boolean,
+password?: boolean,
/**
* Whether to allow newlines in the input, like a
*/
-multiLine?: boolean, completionOptions?: Array,
+multiLine?: boolean, completionOptions?: Array,
/**
* The name of the input. The value will be stored at this object attribute in the resulting data
*/
-name: string,
+name: string,
/**
* Whether this input is visible for the given configuration. Use this to
* make branching forms.
*/
-hidden?: boolean,
+hidden?: boolean,
/**
* Whether the user must fill in the argument
*/
-optional?: boolean,
+optional?: boolean,
/**
* The label of the input
*/
-label?: string,
+label?: string,
/**
* Visually hide the label of the input
*/
-hideLabel?: boolean,
+hideLabel?: boolean,
/**
* The default value
*/
-defaultValue?: string, disabled?: boolean,
+defaultValue?: string, disabled?: boolean,
/**
* Longer description of the input, likely shown in a tooltip
*/
@@ -474,7 +474,7 @@ export type ListOpenWorkspacesResponse = { workspaces: Array, };
export type OpenExternalUrlRequest = { url: string, };
-export type OpenWindowRequest = { url: string,
+export type OpenWindowRequest = { url: string,
/**
* Label for the window. If not provided, a random one will be generated.
*/
@@ -486,15 +486,15 @@ export type PromptFormRequest = { id: string, title: string, description?: strin
export type PromptFormResponse = { values: { [key in string]?: JsonPrimitive } | null, done?: boolean, };
-export type PromptTextRequest = { id: string, title: string, label: string, description?: string, defaultValue?: string, placeholder?: string,
+export type PromptTextRequest = { id: string, title: string, label: string, description?: string, defaultValue?: string, placeholder?: string,
/**
* Text to add to the confirmation button
*/
-confirmText?: string, password?: boolean,
+confirmText?: string, password?: boolean,
/**
* Text to add to the cancel button
*/
-cancelText?: string,
+cancelText?: string,
/**
* Require the user to enter a non-empty value
*/
@@ -524,12 +524,12 @@ export type SetKeyValueResponse = {};
export type ShowToastRequest = { message: string, color?: Color, icon?: Icon, timeout?: number, };
-export type TemplateFunction = { name: string, previewType?: TemplateFunctionPreviewType, description?: string,
+export type TemplateFunction = { name: string, previewType?: TemplateFunctionPreviewType, description?: string,
/**
* Also support alternative names. This is useful for not breaking existing
* tags when changing the `name` property
*/
-aliases?: Array, args: Array,
+aliases?: Array, args: Array,
/**
* A list of arg names to show in the inline preview. If not provided, none will be shown (for privacy reasons).
*/
@@ -546,23 +546,23 @@ export type TemplateRenderRequest = { data: JsonValue, purpose: RenderPurpose, }
export type TemplateRenderResponse = { data: JsonValue, };
-export type Theme = {
+export type Theme = {
/**
* How the theme is identified. This should never be changed
*/
-id: string,
+id: string,
/**
* The friendly name of the theme to be displayed to the user
*/
-label: string,
+label: string,
/**
* Whether the theme will be used for dark or light appearance
*/
-dark: boolean,
+dark: boolean,
/**
* The default top-level colors for the theme
*/
-base: ThemeComponentColors,
+base: ThemeComponentColors,
/**
* Optionally override theme for individual UI components for more control
*/
diff --git a/packages/theme/src/defaultThemes.ts b/packages/theme/src/defaultThemes.ts
index 439871be..5b944dbf 100644
--- a/packages/theme/src/defaultThemes.ts
+++ b/packages/theme/src/defaultThemes.ts
@@ -53,7 +53,7 @@ export const defaultLightTheme: Theme = {
dark: false,
base: {
surface: "hsl(0,0%,100%)",
- surfaceHighlight: "hsl(218,24%,87%)",
+ surfaceHighlight: "hsl(218,24%,92%)",
text: "hsl(217,24%,10%)",
textSubtle: "hsl(217,24%,40%)",
textSubtlest: "hsl(217,24%,58%)",
@@ -70,7 +70,7 @@ export const defaultLightTheme: Theme = {
sidebar: {
surface: "hsl(220,20%,98%)",
border: "hsl(217,22%,88%)",
- surfaceHighlight: "hsl(217,25%,90%)",
+ surfaceHighlight: "hsl(217,25%,94%)",
},
},
};