@engenty/wizards 0.8.0 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","names":["WIZARD_COMPONENT","wizardProps","z","WIZARD_DESCRIPTION","WizardSpec","defineComponent","addWizard","library","loadWizards","base","runtimeUrl","tokens","res","token","w","fieldLine","choices","f","o","wizardRules","wizards"],"sources":["../../src/openui/server.ts"],"sourcesContent":["import type { PublicField, PublicWizard } from \"@engenty-wizards/shared/run\";\nimport { defineComponent, type Library } from \"@openuidev/react-lang\";\nimport { z } from \"zod\";\n\n/**\n * The model's half of the Wizard component: its props, its description and the rules a system\n * prompt gets. Nothing here draws, so a chat server builds its prompt from this file alone.\n */\n\nexport const WIZARD_COMPONENT = \"Wizard\";\n\nexport const wizardProps = z.object({\n wizard: z.string().describe(\"The token of a wizard from the list of available wizards\"),\n note: z\n .string()\n .optional()\n .describe(\"One short sentence shown above the wizard: why it starts now\"),\n prefill: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\n \"Answers already known from the conversation, by field id; the person still checks them\",\n ),\n});\n\nexport type WizardProps = z.infer<typeof wizardProps>;\n\nexport const WIZARD_DESCRIPTION =\n \"Runs a predefined wizard inline: its pages, AI steps, review and result, exactly as its author defined them. Use it whenever a listed wizard fits the request; never rebuild a wizard's pages with Form components.\";\n\n/** The component as a prompt sees it: the same name and props, nothing to draw. */\nexport const WizardSpec = defineComponent({\n name: WIZARD_COMPONENT,\n description: WIZARD_DESCRIPTION,\n props: wizardProps,\n component: () => null,\n});\n\n/**\n * The library with the Wizard component among a Card's children. A server passes `WizardSpec`\n * for its prompt, the browser the drawing `Wizard`; both make the same prompt.\n */\nexport function addWizard<L extends Library>(\n library: L,\n component: typeof WizardSpec = WizardSpec,\n): Library {\n if (!library.extend) {\n throw new Error(\"This OpenUI library cannot be extended.\");\n }\n return library.extend({ components: { add: [{ component, slots: [\"Card\"] }] } });\n}\n\n/** A wizard as the chat server lists it to the model. */\nexport interface WizardInfo {\n token: string;\n title: string;\n description: string;\n fields: PublicField[];\n}\n\n/** Reads the published wizards behind these tokens from a runtime; ones it cannot read are left out. */\nexport async function loadWizards(runtimeUrl: string, tokens: string[]): Promise<WizardInfo[]> {\n const base = runtimeUrl.replace(/\\/+$/, \"\");\n const found = await Promise.all(\n tokens.map(async (token) => {\n try {\n const res = await fetch(`${base}/api/public/wizards/${encodeURIComponent(token)}`);\n if (!res.ok) {\n return null;\n }\n const w = (await res.json()) as PublicWizard;\n return w.available\n ? { token: w.token, title: w.title, description: w.description, fields: w.fields ?? [] }\n : null;\n } catch {\n return null;\n }\n }),\n );\n return found.filter((w): w is WizardInfo => w !== null);\n}\n\nfunction fieldLine(f: PublicField): string {\n const choices = f.options?.length\n ? ` one of ${f.options.map((o) => JSON.stringify(o)).join(\" | \")}`\n : \"\";\n return `${f.id} (${f.kind}${choices}${f.required ? \", required\" : \"\"}): ${f.label}`;\n}\n\n/** The rules a system prompt adds for the Wizard component: when to use it and which wizards exist. */\nexport function wizardRules(wizards: WizardInfo[]): string[] {\n if (!wizards.length) {\n return [];\n }\n const list = wizards\n .map(\n (w) =>\n `- \"${w.title}\" token: ${w.token} — ${w.description}\\n fields: ${w.fields.map(fieldLine).join(\"; \") || \"none\"}`,\n )\n .join(\"\\n\");\n return [\n `Wizards are fixed workflows with their own pages, AI steps and results. When the person asks for something a wizard below does, answer with a Card that holds one short TextContent and Wizard(\"<token>\", \"<note>\", {prefill}). Do not ask the wizard's questions yourself and do not build them as a Form: the wizard asks them.`,\n `Prefill only answers the person has actually given in this conversation, by field id; leave out anything you would have to guess. Dates are YYYY-MM-DD.`,\n `When a message says a wizard finished, its context holds the result: answer in plain words about it, and start a wizard again only when asked.`,\n `Available wizards:\\n${list}`,\n ];\n}\n"],"mappings":";;;AASA,IAAaA,IAAmB,UAEnBC,IAAcC,EAAE,OAAO;CAClC,QAAQA,EAAE,OAAO,CAAC,CAAC,SAAS,0DAA0D;CACtF,MAAMA,EACH,OAAO,CAAC,CACR,SAAS,CAAC,CACV,SAAS,8DAA8D;CAC1E,SAASA,EACN,OAAOA,EAAE,OAAO,GAAGA,EAAE,QAAQ,CAAC,CAAC,CAC/B,SAAS,CAAC,CACV,SACC,wFACF;AACJ,CAAC,GAIYC,IACX,uNAGWC,IAAaC,EAAgB;CACxC,MAAML;CACN,aAAaG;CACb,OAAOF;CACP,iBAAiB;AACnB,CAAC;AAMD,SAAgBK,EACd,GACA,IAA+BF,GACtB;CACT,IAAI,CAACG,EAAQ,QACX,MAAU,MAAM,yCAAyC;CAE3D,OAAOA,EAAQ,OAAO,EAAE,YAAY,EAAE,KAAK,CAAC;EAAE;EAAW,OAAO,CAAC,MAAM;CAAE,CAAC,EAAE,EAAE,CAAC;AACjF;AAWA,eAAsBC,EAAY,GAAoB,GAAyC;CAC7F,IAAMC,IAAOC,EAAW,QAAQ,QAAQ,EAAE;CAiB1C,QAAO,MAhBa,QAAQ,IAC1BC,EAAO,IAAI,OAAO,MAAU;EAC1B,IAAI;GACF,IAAMC,IAAM,MAAM,MAAM,GAAGH,EAAK,sBAAsB,mBAAmBI,CAAK,GAAG;GACjF,IAAI,CAACD,EAAI,IACP,OAAO;GAET,IAAME,IAAK,MAAMF,EAAI,KAAK;GAC1B,OAAOE,EAAE,YACL;IAAE,OAAOA,EAAE;IAAO,OAAOA,EAAE;IAAO,aAAaA,EAAE;IAAa,QAAQA,EAAE,UAAU,CAAC;GAAE,IACrF;EACN,QAAQ;GACN,OAAO;EACT;CACF,CAAC,CACH,EAAA,CACa,QAAQ,MAAuBA,MAAM,IAAI;AACxD;AAEA,SAASC,EAAU,GAAwB;CACzC,IAAMC,IAAUC,EAAE,SAAS,SACvB,WAAWA,EAAE,QAAQ,KAAK,MAAM,KAAK,UAAUC,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK,MAC7D;CACJ,OAAO,GAAGD,EAAE,GAAG,IAAIA,EAAE,OAAOD,IAAUC,EAAE,WAAW,eAAe,GAAG,KAAKA,EAAE;AAC9E;AAGA,SAAgBE,EAAY,GAAiC;CAU3D,OATKC,EAAQ,SASN;EACL;EACA;EACA;EACA,uBAVWA,EACV,KACE,MACC,MAAMN,EAAE,MAAM,WAAWA,EAAE,MAAM,KAAKA,EAAE,YAAY,cAAcA,EAAE,OAAO,IAAIC,CAAS,CAAC,CAAC,KAAK,IAAI,KAAK,QAC5G,CAAC,CACA,KAAK,IAKiB;CACzB,IAbS,CAAC;AAcZ"}
1
+ {"version":3,"file":"server.js","names":["WIZARD_COMPONENT","wizardProps","z","WIZARD_DESCRIPTION","WizardSpec","defineComponent","addWizard","library","loadWizards","base","runtimeUrl","tokens","res","token","w","fieldLine","choices","f","o","wizardRules","wizards"],"sources":["../../src/openui/server.ts"],"sourcesContent":["import type { PublicField, PublicWizard } from \"@engenty/wizards-shared/run\";\nimport { defineComponent, type Library } from \"@openuidev/react-lang\";\nimport { z } from \"zod\";\n\n/**\n * The model's half of the Wizard component: its props, its description and the rules a system\n * prompt gets. Nothing here draws, so a chat server builds its prompt from this file alone.\n */\n\nexport const WIZARD_COMPONENT = \"Wizard\";\n\nexport const wizardProps = z.object({\n wizard: z.string().describe(\"The token of a wizard from the list of available wizards\"),\n note: z\n .string()\n .optional()\n .describe(\"One short sentence shown above the wizard: why it starts now\"),\n prefill: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\n \"Answers already known from the conversation, by field id; the person still checks them\",\n ),\n});\n\nexport type WizardProps = z.infer<typeof wizardProps>;\n\nexport const WIZARD_DESCRIPTION =\n \"Runs a predefined wizard inline: its pages, AI steps, review and result, exactly as its author defined them. Use it whenever a listed wizard fits the request; never rebuild a wizard's pages with Form components.\";\n\n/** The component as a prompt sees it: the same name and props, nothing to draw. */\nexport const WizardSpec = defineComponent({\n name: WIZARD_COMPONENT,\n description: WIZARD_DESCRIPTION,\n props: wizardProps,\n component: () => null,\n});\n\n/**\n * The library with the Wizard component among a Card's children. A server passes `WizardSpec`\n * for its prompt, the browser the drawing `Wizard`; both make the same prompt.\n */\nexport function addWizard<L extends Library>(\n library: L,\n component: typeof WizardSpec = WizardSpec,\n): Library {\n if (!library.extend) {\n throw new Error(\"This OpenUI library cannot be extended.\");\n }\n return library.extend({ components: { add: [{ component, slots: [\"Card\"] }] } });\n}\n\n/** A wizard as the chat server lists it to the model. */\nexport interface WizardInfo {\n token: string;\n title: string;\n description: string;\n fields: PublicField[];\n}\n\n/** Reads the published wizards behind these tokens from a runtime; ones it cannot read are left out. */\nexport async function loadWizards(runtimeUrl: string, tokens: string[]): Promise<WizardInfo[]> {\n const base = runtimeUrl.replace(/\\/+$/, \"\");\n const found = await Promise.all(\n tokens.map(async (token) => {\n try {\n const res = await fetch(`${base}/api/public/wizards/${encodeURIComponent(token)}`);\n if (!res.ok) {\n return null;\n }\n const w = (await res.json()) as PublicWizard;\n return w.available\n ? { token: w.token, title: w.title, description: w.description, fields: w.fields ?? [] }\n : null;\n } catch {\n return null;\n }\n }),\n );\n return found.filter((w): w is WizardInfo => w !== null);\n}\n\nfunction fieldLine(f: PublicField): string {\n const choices = f.options?.length\n ? ` one of ${f.options.map((o) => JSON.stringify(o)).join(\" | \")}`\n : \"\";\n return `${f.id} (${f.kind}${choices}${f.required ? \", required\" : \"\"}): ${f.label}`;\n}\n\n/** The rules a system prompt adds for the Wizard component: when to use it and which wizards exist. */\nexport function wizardRules(wizards: WizardInfo[]): string[] {\n if (!wizards.length) {\n return [];\n }\n const list = wizards\n .map(\n (w) =>\n `- \"${w.title}\" token: ${w.token} — ${w.description}\\n fields: ${w.fields.map(fieldLine).join(\"; \") || \"none\"}`,\n )\n .join(\"\\n\");\n return [\n `Wizards are fixed workflows with their own pages, AI steps and results. When the person asks for something a wizard below does, answer with a Card that holds one short TextContent and Wizard(\"<token>\", \"<note>\", {prefill}). Do not ask the wizard's questions yourself and do not build them as a Form: the wizard asks them.`,\n `Prefill only answers the person has actually given in this conversation, by field id; leave out anything you would have to guess. Dates are YYYY-MM-DD.`,\n `When a message says a wizard finished, its context holds the result: answer in plain words about it, and start a wizard again only when asked.`,\n `Available wizards:\\n${list}`,\n ];\n}\n"],"mappings":";;;AASA,IAAaA,IAAmB,UAEnBC,IAAcC,EAAE,OAAO;CAClC,QAAQA,EAAE,OAAO,CAAC,CAAC,SAAS,0DAA0D;CACtF,MAAMA,EACH,OAAO,CAAC,CACR,SAAS,CAAC,CACV,SAAS,8DAA8D;CAC1E,SAASA,EACN,OAAOA,EAAE,OAAO,GAAGA,EAAE,QAAQ,CAAC,CAAC,CAC/B,SAAS,CAAC,CACV,SACC,wFACF;AACJ,CAAC,GAIYC,IACX,uNAGWC,IAAaC,EAAgB;CACxC,MAAML;CACN,aAAaG;CACb,OAAOF;CACP,iBAAiB;AACnB,CAAC;AAMD,SAAgBK,EACd,GACA,IAA+BF,GACtB;CACT,IAAI,CAACG,EAAQ,QACX,MAAU,MAAM,yCAAyC;CAE3D,OAAOA,EAAQ,OAAO,EAAE,YAAY,EAAE,KAAK,CAAC;EAAE;EAAW,OAAO,CAAC,MAAM;CAAE,CAAC,EAAE,EAAE,CAAC;AACjF;AAWA,eAAsBC,EAAY,GAAoB,GAAyC;CAC7F,IAAMC,IAAOC,EAAW,QAAQ,QAAQ,EAAE;CAiB1C,QAAO,MAhBa,QAAQ,IAC1BC,EAAO,IAAI,OAAO,MAAU;EAC1B,IAAI;GACF,IAAMC,IAAM,MAAM,MAAM,GAAGH,EAAK,sBAAsB,mBAAmBI,CAAK,GAAG;GACjF,IAAI,CAACD,EAAI,IACP,OAAO;GAET,IAAME,IAAK,MAAMF,EAAI,KAAK;GAC1B,OAAOE,EAAE,YACL;IAAE,OAAOA,EAAE;IAAO,OAAOA,EAAE;IAAO,aAAaA,EAAE;IAAa,QAAQA,EAAE,UAAU,CAAC;GAAE,IACrF;EACN,QAAQ;GACN,OAAO;EACT;CACF,CAAC,CACH,EAAA,CACa,QAAQ,MAAuBA,MAAM,IAAI;AACxD;AAEA,SAASC,EAAU,GAAwB;CACzC,IAAMC,IAAUC,EAAE,SAAS,SACvB,WAAWA,EAAE,QAAQ,KAAK,MAAM,KAAK,UAAUC,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK,MAC7D;CACJ,OAAO,GAAGD,EAAE,GAAG,IAAIA,EAAE,OAAOD,IAAUC,EAAE,WAAW,eAAe,GAAG,KAAKA,EAAE;AAC9E;AAGA,SAAgBE,EAAY,GAAiC;CAU3D,OATKC,EAAQ,SASN;EACL;EACA;EACA;EACA,uBAVWA,EACV,KACE,MACC,MAAMN,EAAE,MAAM,WAAWA,EAAE,MAAM,KAAKA,EAAE,YAAY,cAAcA,EAAE,OAAO,IAAIC,CAAS,CAAC,CAAC,KAAK,IAAI,KAAK,QAC5G,CAAC,CACA,KAAK,IAKiB;CACzB,IAbS,CAAC;AAcZ"}
@@ -1865,20 +1865,45 @@
1865
1865
  }
1866
1866
  }
1867
1867
  .engenty-runner {
1868
- --raw-primary: #e0531b;
1869
- --paper: #f7f5f2;
1870
- --paper-2: #eae7e4;
1871
- --paper-3: #e0ddd9;
1872
- --card: #ffffff;
1868
+ --raw-primary: var(--wizard-accent, #e0531b);
1869
+ --raw-background: var(--wizard-background, #faf8f5);
1870
+ --paper: oklch(
1871
+ from var(--raw-background) calc(0.97 - (0.97 - l) * clamp(0, (0.5 - l) * 1000, 1)) c h
1872
+ );
1873
+ --paper-2: oklch(
1874
+ from var(--raw-background) calc(0.93 - (0.88 - l) * clamp(0, (0.5 - l) * 1000, 1)) calc(c * 1.2)
1875
+ h
1876
+ );
1877
+ --paper-3: oklch(
1878
+ from var(--raw-background) calc(0.9 - (0.81 - l) * clamp(0, (0.5 - l) * 1000, 1)) calc(c * 1.5)
1879
+ h
1880
+ );
1881
+ --card: oklch(
1882
+ from var(--raw-background) calc(1 - (0.96 - l) * clamp(0, (0.5 - l) * 1000, 1))
1883
+ calc(c * clamp(0, (0.5 - l) * 1000, 1)) h
1884
+ );
1873
1885
  --background: var(--paper);
1874
1886
  --foreground: var(--ink);
1875
- --ink: #282623;
1876
- --ink-2: #575552;
1877
- --ink-3: #81807e;
1878
- --ink-4: #afaeac;
1887
+ --ink: var(
1888
+ --wizard-text,
1889
+ oklch(
1890
+ from var(--raw-background) calc(0.27 + 0.67 * clamp(0, (0.5 - l) * 1000, 1))
1891
+ calc(c * (1.2 - 0.9 * clamp(0, (0.5 - l) * 1000, 1))) h
1892
+ )
1893
+ );
1894
+ --ink-2: oklch(from var(--raw-background) calc(0.45 + 0.35 * clamp(0, (0.5 - l) * 1000, 1)) c h);
1895
+ --ink-3: oklch(
1896
+ from var(--raw-background) calc(0.6 + 0.06 * clamp(0, (0.5 - l) * 1000, 1)) calc(c * 0.8) h
1897
+ );
1898
+ --ink-4: oklch(
1899
+ from var(--raw-background) calc(0.75 - 0.25 * clamp(0, (0.5 - l) * 1000, 1)) calc(c * 0.6) h
1900
+ );
1879
1901
  --ember: var(--raw-primary);
1880
- --ember-strong: #c43700;
1881
- --ember-tint: #ffeae0;
1902
+ --ember-strong: oklch(from var(--raw-primary) calc(l - 0.08) c h);
1903
+ --ember-tint: var(--ember);
1904
+ @supports (color: color-mix(in lab, red, red)) {
1905
+ --ember-tint: color-mix(in oklch, var(--ember) 14%, var(--card));
1906
+ }
1882
1907
  --ember-veil: var(--ember);
1883
1908
  @supports (color: color-mix(in lab, red, red)) {
1884
1909
  --ember-veil: color-mix(in oklch, var(--ember) 10%, transparent);
@@ -1894,17 +1919,29 @@
1894
1919
  );
1895
1920
  --secondary: var(--paper-2);
1896
1921
  --secondary-foreground: var(--ink);
1897
- --accent: #efece9;
1922
+ --accent: var(--ink);
1923
+ @supports (color: color-mix(in lab, red, red)) {
1924
+ --accent: color-mix(in oklch, var(--ink) 7.5%, var(--paper));
1925
+ }
1898
1926
  --accent-foreground: var(--ink);
1899
- --muted: #f0edea;
1927
+ --muted: var(--paper-3);
1928
+ @supports (color: color-mix(in lab, red, red)) {
1929
+ --muted: color-mix(in oklch, var(--paper-3) 32%, var(--card));
1930
+ }
1900
1931
  --muted-foreground: var(--ink-3);
1901
1932
  --destructive: var(--rose);
1902
- --border: #dbd9d6;
1933
+ --border: var(--ink);
1934
+ @supports (color: color-mix(in lab, red, red)) {
1935
+ --border: color-mix(in oklch, var(--ink) 12%, var(--paper));
1936
+ }
1903
1937
  --border-soft: var(--border);
1904
1938
  @supports (color: color-mix(in lab, red, red)) {
1905
1939
  --border-soft: color-mix(in oklch, var(--border) 50%, transparent);
1906
1940
  }
1907
- --input: #e0dedb;
1941
+ --input: var(--ink);
1942
+ @supports (color: color-mix(in lab, red, red)) {
1943
+ --input: color-mix(in oklch, var(--ink) 10%, var(--paper));
1944
+ }
1908
1945
  --ring: var(--ember);
1909
1946
  @supports (color: color-mix(in lab, red, red)) {
1910
1947
  --ring: color-mix(in oklch, var(--ember) 45%, transparent);
@@ -1917,19 +1954,31 @@
1917
1954
  --card-foreground: var(--ink);
1918
1955
  --popover: var(--card);
1919
1956
  --moss: #006527;
1920
- --moss-tint: #eafaec;
1957
+ --moss-tint: var(--moss);
1958
+ @supports (color: color-mix(in lab, red, red)) {
1959
+ --moss-tint: color-mix(in oklch, var(--moss) 10%, var(--card));
1960
+ }
1921
1961
  --second: var(--moss);
1922
1962
  --second-tint: var(--moss-tint);
1923
1963
  --cobalt: #2b5fd9;
1924
- --cobalt-tint: #ebf0fd;
1964
+ --cobalt-tint: var(--cobalt);
1965
+ @supports (color: color-mix(in lab, red, red)) {
1966
+ --cobalt-tint: color-mix(in oklch, var(--cobalt) 10%, var(--card));
1967
+ }
1925
1968
  --amber: #e2a324;
1926
- --amber-tint: #fff1d9;
1969
+ --amber-tint: var(--amber);
1970
+ @supports (color: color-mix(in lab, red, red)) {
1971
+ --amber-tint: color-mix(in oklch, var(--amber) 14%, var(--card));
1972
+ }
1927
1973
  --rose: #db373a;
1928
- --rose-tint: #ffeeeb;
1929
- --f-display: "Space Grotesk", ui-sans-serif, system-ui, sans-serif;
1930
- --f-ui: "Geist", ui-sans-serif, system-ui, sans-serif;
1974
+ --rose-tint: var(--rose);
1975
+ @supports (color: color-mix(in lab, red, red)) {
1976
+ --rose-tint: color-mix(in oklch, var(--rose) 10%, var(--card));
1977
+ }
1978
+ --f-display: var(--wizard-font-heading, "Space Grotesk", ui-sans-serif, system-ui, sans-serif);
1979
+ --f-ui: var(--wizard-font-text, "Geist", ui-sans-serif, system-ui, sans-serif);
1931
1980
  --f-mono: "Geist Mono", ui-monospace, monospace;
1932
- --radius: 0.5rem;
1981
+ --radius: var(--wizard-radius, 0.5rem);
1933
1982
  --shadow-ember-soft: 0 1px 2px rgba(40, 38, 35, 0.03), 0 3px 10px rgba(40, 38, 35, 0.05);
1934
1983
  --shadow-ember-elevated: 0 1px 2px rgba(40, 38, 35, 0.04), 0 6px 18px rgba(40, 38, 35, 0.06);
1935
1984
  --shadow-ember-overlay: 0 2px 4px rgba(40, 38, 35, 0.08), 0 10px 28px rgba(40, 38, 35, 0.16);
@@ -2203,6 +2252,64 @@
2203
2252
  overflow: hidden;
2204
2253
  }
2205
2254
  }
2255
+ .engenty-runner[data-cards="outline"] .wizard-card {
2256
+ background: transparent;
2257
+ box-shadow: none;
2258
+ border: 1px solid var(--ink);
2259
+ @supports (color: color-mix(in lab, red, red)) {
2260
+ border: 1px solid color-mix(in oklch, var(--ink) 25%, transparent);
2261
+ }
2262
+ }
2263
+ .engenty-runner[data-cards="glass"] .wizard-card {
2264
+ background: var(--card);
2265
+ @supports (color: color-mix(in lab, red, red)) {
2266
+ background: color-mix(in oklch, var(--card) 55%, transparent);
2267
+ }
2268
+ backdrop-filter: blur(14px);
2269
+ -webkit-backdrop-filter: blur(14px);
2270
+ }
2271
+ .engenty-runner[data-headings="uppercase"] :is(.wizard-title, .wizard-heading) {
2272
+ text-transform: uppercase;
2273
+ letter-spacing: 0.04em;
2274
+ }
2275
+ .engenty-runner[data-effects~="glow"] :is(h1, h2, .font-display) {
2276
+ text-shadow: 0 0 0.55em var(--primary),
2277
+ 0 0 0.12em var(--primary);
2278
+ @supports (color: color-mix(in lab, red, red)) {
2279
+ text-shadow: 0 0 0.55em color-mix(in oklch, var(--primary) 70%, transparent),
2280
+ 0 0 0.12em color-mix(in oklch, var(--primary) 45%, transparent);
2281
+ }
2282
+ }
2283
+ .engenty-runner[data-effects~="glow"] button[data-variant="primary"] {
2284
+ box-shadow: 0 0 1.4rem var(--primary),
2285
+ 0 0 0.35rem var(--primary);
2286
+ @supports (color: color-mix(in lab, red, red)) {
2287
+ box-shadow: 0 0 1.4rem color-mix(in oklch, var(--primary) 60%, transparent),
2288
+ 0 0 0.35rem color-mix(in oklch, var(--primary) 80%, transparent);
2289
+ }
2290
+ }
2291
+ .engenty-runner[data-effects~="pattern-dots"] {
2292
+ background-image: radial-gradient(
2293
+ var(--ink) 1px,
2294
+ transparent 1.5px
2295
+ );
2296
+ @supports (color: color-mix(in lab, red, red)) {
2297
+ background-image: radial-gradient(
2298
+ color-mix(in oklch, var(--ink) 12%, transparent) 1px,
2299
+ transparent 1.5px
2300
+ );
2301
+ }
2302
+ background-size: 22px 22px;
2303
+ }
2304
+ .engenty-runner[data-effects~="pattern-grid"] {
2305
+ background-image: linear-gradient(var(--ink) 1px, transparent 1px),
2306
+ linear-gradient(90deg, var(--ink) 1px, transparent 1px);
2307
+ @supports (color: color-mix(in lab, red, red)) {
2308
+ background-image: linear-gradient(color-mix(in oklch, var(--ink) 7%, transparent) 1px, transparent 1px),
2309
+ linear-gradient(90deg, color-mix(in oklch, var(--ink) 7%, transparent) 1px, transparent 1px);
2310
+ }
2311
+ background-size: 28px 28px;
2312
+ }
2206
2313
  @media (prefers-reduced-motion: reduce) {
2207
2314
  .engenty-runner .animate-rise,
2208
2315
  .engenty-runner .animate-breathe,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@engenty/wizards",
3
- "version": "0.8.0",
3
+ "version": "0.9.1",
4
4
  "description": "What your code imports from engenty wizards: plugins at /plugin, wizards in OpenUI chats at /openui.",
5
5
  "license": "FSL-1.1-MIT",
6
6
  "homepage": "https://engenty.ai",