From 6ac363d0abe7aab8ac46f89c980443f6cb268554 Mon Sep 17 00:00:00 2001 From: Danilo Arioli Date: Fri, 19 Dec 2025 15:45:42 +0100 Subject: [PATCH 1/9] feat: make IconDefinition strongly typed --- dev/schema.ts | 12 ++++++++++++ src/lib/types.ts | 38 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 dev/schema.ts diff --git a/dev/schema.ts b/dev/schema.ts new file mode 100644 index 0000000..9950080 --- /dev/null +++ b/dev/schema.ts @@ -0,0 +1,12 @@ +import { defineField } from 'sanity'; + +export const test = defineField({ + name: 'test', + type: 'icon', + hidden: ({ value }) => value.name === 'test', + validation: (Rule) => + Rule.custom((value) => { + const test = value?.name; + return test === 'yihaa' ? true : 'error'; + }), +}); diff --git a/src/lib/types.ts b/src/lib/types.ts index 17d5bd9..97008bd 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -1,5 +1,13 @@ import type { IconifyInfo } from '@iconify/types'; -import type { BaseSchemaDefinition } from 'sanity'; +import type { + BaseSchemaDefinition, + ConditionalPropertyCallbackContext, + FieldGroupDefinition, + FieldsetDefinition, + PreviewConfig, + RuleDef, + ValidationBuilder, +} from 'sanity'; // If this line errors, the type definitions have not been generated. import type { IconPrefix } from './icon-types.gen'; @@ -23,11 +31,37 @@ export interface IconifySearchResult { collections: Record; } +export interface IconValue { + name?: string; +} + // Extend the Sanity schema types to include our custom type declare module 'sanity' { - interface IconDefinition extends BaseSchemaDefinition { + //eslint-disable-next-line + export interface IconRule extends RuleDef {} + + export type IconConditionalPropertyCallbackContext = Omit< + ConditionalPropertyCallbackContext, + 'value' + > & { + value: IconValue; + }; + + export type IconConditionalPropertyCallback = ( + context: IconConditionalPropertyCallbackContext, + ) => boolean; + + export type IconConditionalProperty = boolean | IconConditionalPropertyCallback | undefined; + + interface IconDefinition extends Omit { type: 'icon'; + groups?: FieldGroupDefinition[]; + fieldsets?: FieldsetDefinition[]; + preview?: PreviewConfig; options?: IconOptions; + hidden?: IconConditionalProperty; + readOnly?: IconConditionalProperty; + validation?: ValidationBuilder; } export interface IntrinsicDefinitions { From 0146533ded7aee14b14d3755bc4f09eb402a1fec Mon Sep 17 00:00:00 2001 From: Danilo Arioli Date: Fri, 19 Dec 2025 16:34:59 +0100 Subject: [PATCH 2/9] feat: add tests --- dev/schema.ts | 4 +- package.json | 7 +- pnpm-lock.yaml | 292 ++++++++++++++++++++++++++++++++++++++++++ src/lib/types.test.ts | 82 ++++++++++++ vitest.config.ts | 9 ++ 5 files changed, 391 insertions(+), 3 deletions(-) create mode 100644 src/lib/types.test.ts create mode 100644 vitest.config.ts diff --git a/dev/schema.ts b/dev/schema.ts index 9950080..c0718bb 100644 --- a/dev/schema.ts +++ b/dev/schema.ts @@ -6,7 +6,7 @@ export const test = defineField({ hidden: ({ value }) => value.name === 'test', validation: (Rule) => Rule.custom((value) => { - const test = value?.name; - return test === 'yihaa' ? true : 'error'; + const name = value?.name; + return name === 'lucide:home' ? true : 'error'; }), }); diff --git a/package.json b/package.json index d8f23d1..817ca03 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,9 @@ "generate-types": "node src/lib/generate-types", "lint": "eslint .", "release": "release-it", + "test": "vitest run", + "test:ui": "vitest --ui", + "test:watch": "vitest", "watch": "pkg-utils watch --strict" }, "browserslist": "extends @sanity/browserslist-config", @@ -74,6 +77,7 @@ "@tanstack/react-query-devtools": "^5.89.0", "@types/react": "^19.1.13", "@types/styled-components": "^5.1.34", + "@vitest/ui": "^4.0.16", "@waspeer/config": "^2.4.5", "eslint": "^9.35.0", "lefthook": "^1.13.1", @@ -87,7 +91,8 @@ "sanity": "^4.9.0", "tsx": "^4.20.5", "typescript": "^5.9.2", - "vite": "^7.1.6" + "vite": "^7.1.6", + "vitest": "^4.0.16" }, "peerDependencies": { "react": "^18 || ^19", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 17bba85..6247b47 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -81,6 +81,9 @@ importers: '@types/styled-components': specifier: ^5.1.34 version: 5.1.34 + '@vitest/ui': + specifier: ^4.0.16 + version: 4.0.16(vitest@4.0.16) '@waspeer/config': specifier: ^2.4.5 version: 2.4.5(eslint@9.25.1(jiti@2.5.1))(postcss@8.5.6)(prettier@3.6.2)(ts-api-utils@2.1.0(typescript@5.9.2))(typescript@5.9.2) @@ -123,6 +126,9 @@ importers: vite: specifier: ^7.1.6 version: 7.1.6(@types/node@22.15.3)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.39.0)(tsx@4.20.5)(yaml@2.7.1) + vitest: + specifier: ^4.0.16 + version: 4.0.16(@types/node@22.15.3)(@vitest/ui@4.0.16)(jiti@2.5.1)(jsdom@23.2.0)(lightningcss@1.30.1)(terser@5.39.0)(tsx@4.20.5)(yaml@2.7.1) packages: @@ -2066,6 +2072,9 @@ packages: resolution: {integrity: sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw==} engines: {node: '>=12'} + '@polka/url@1.0.0-next.29': + resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} + '@portabletext/block-tools@3.5.6': resolution: {integrity: sha512-/jBxOkzkQVareAyB+F/NetjQnwt/eodTsQ/rnPbPSXEIBhKV2EkWnWsAqJMbGhs+DPYsKKT3tyfvHGHlIeEcFQ==} peerDependencies: @@ -2843,6 +2852,9 @@ packages: resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==} engines: {node: '>=18'} + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + '@tanstack/eslint-plugin-query@5.89.0': resolution: {integrity: sha512-vz8TEuw9GO0xXIdreMpcofvOY17T3cjgob9bSFln8yQsKsbsUvtpvV3F8pVC3tZEDq0IwO++3/e0/+7YKEarNA==} peerDependencies: @@ -2909,9 +2921,15 @@ packages: '@types/babel__traverse@7.20.7': resolution: {integrity: sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==} + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + '@types/conventional-commits-parser@5.0.1': resolution: {integrity: sha512-7uz5EHdzz2TqoMfV7ee61Egf5y6NkcO4FB/1iCCQnbeiI1F3xzv3vK5dBCXUCLQgGYS+mUeigK1iKQzvED+QnQ==} + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + '@types/eslint@9.6.1': resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==} @@ -3200,6 +3218,40 @@ packages: peerDependencies: vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 + '@vitest/expect@4.0.16': + resolution: {integrity: sha512-eshqULT2It7McaJkQGLkPjPjNph+uevROGuIMJdG3V+0BSR2w9u6J9Lwu+E8cK5TETlfou8GRijhafIMhXsimA==} + + '@vitest/mocker@4.0.16': + resolution: {integrity: sha512-yb6k4AZxJTB+q9ycAvsoxGn+j/po0UaPgajllBgt1PzoMAAmJGYFdDk0uCcRcxb3BrME34I6u8gHZTQlkqSZpg==} + peerDependencies: + msw: ^2.4.9 + vite: ^6.0.0 || ^7.0.0-0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@4.0.16': + resolution: {integrity: sha512-eNCYNsSty9xJKi/UdVD8Ou16alu7AYiS2fCPRs0b1OdhJiV89buAXQLpTbe+X8V9L6qrs9CqyvU7OaAopJYPsA==} + + '@vitest/runner@4.0.16': + resolution: {integrity: sha512-VWEDm5Wv9xEo80ctjORcTQRJ539EGPB3Pb9ApvVRAY1U/WkHXmmYISqU5E79uCwcW7xYUV38gwZD+RV755fu3Q==} + + '@vitest/snapshot@4.0.16': + resolution: {integrity: sha512-sf6NcrYhYBsSYefxnry+DR8n3UV4xWZwWxYbCJUt2YdvtqzSPR7VfGrY0zsv090DAbjFZsi7ZaMi1KnSRyK1XA==} + + '@vitest/spy@4.0.16': + resolution: {integrity: sha512-4jIOWjKP0ZUaEmJm00E0cOBLU+5WE0BpeNr3XN6TEF05ltro6NJqHWxXD0kA8/Zc8Nh23AT8WQxwNG+WeROupw==} + + '@vitest/ui@4.0.16': + resolution: {integrity: sha512-rkoPH+RqWopVxDnCBE/ysIdfQ2A7j1eDmW8tCxxrR9nnFBa9jKf86VgsSAzxBd1x+ny0GC4JgiD3SNfRHv3pOg==} + peerDependencies: + vitest: 4.0.16 + + '@vitest/utils@4.0.16': + resolution: {integrity: sha512-h8z9yYhV3e1LEfaQ3zdypIrnAg/9hguReGZoS7Gl0aBG5xgA410zBqECqmaF/+RkTggRsfnzc1XaAHA6bmUufA==} + '@waspeer/config@2.4.5': resolution: {integrity: sha512-RnkOEfh2WEgy2s0m2b2AlM2ZsPdZ2pOYsgt1V5o4BIjIN5CJZqqGRi5CKUteVMdeKkEvCaATLpC02d/jQ7eFSQ==} peerDependencies: @@ -3381,6 +3433,10 @@ packages: resolution: {integrity: sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==} engines: {node: '>=8'} + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + ast-kit@2.1.2: resolution: {integrity: sha512-cl76xfBQM6pztbrFWRnxbrDm9EOqDr1BF6+qQnnDZG2Co2LjyUktkN9GTJfBAfdae+DbT2nJf2nCGAdDDN7W2g==} engines: {node: '>=20.18.0'} @@ -3597,6 +3653,10 @@ packages: peerDependencies: react: '>=17.0.0' + chai@6.2.1: + resolution: {integrity: sha512-p4Z49OGG5W/WBCPSS/dH3jQ73kD6tiMmUM+bckNK6Jr5JHMG3k9bg/BvKR8lKmtVBKmOiuVaV2ws8s9oSbwysg==} + engines: {node: '>=18'} + chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} @@ -4473,6 +4533,9 @@ packages: estree-walker@2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} @@ -4523,6 +4586,10 @@ packages: exif-component@1.0.1: resolution: {integrity: sha512-FXnmK9yJYTa3V3G7DE9BRjUJ0pwXMICAxfbsAuKPTuSlFzMZhQbcvvwx0I8ofNJHxz3tfjze+whxcGpfklAWOQ==} + expect-type@1.3.0: + resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} + engines: {node: '>=12.0.0'} + exsolve@1.0.7: resolution: {integrity: sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==} @@ -4579,6 +4646,9 @@ packages: picomatch: optional: true + fflate@0.8.2: + resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} + figures@3.2.0: resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} engines: {node: '>=8'} @@ -5872,6 +5942,9 @@ packages: magic-string@0.30.19: resolution: {integrity: sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==} + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + make-dir@2.1.0: resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} engines: {node: '>=6'} @@ -6055,6 +6128,10 @@ packages: motion-utils@12.23.6: resolution: {integrity: sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==} + mrmime@2.0.1: + resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} + engines: {node: '>=10'} + ms@2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} @@ -6218,6 +6295,9 @@ packages: peerDependencies: rxjs: ^6.5 || ^7 + obug@2.1.1: + resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} + ohash@2.0.11: resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==} @@ -7162,6 +7242,9 @@ packages: resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} engines: {node: '>= 0.4'} + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} @@ -7176,6 +7259,10 @@ packages: simple-wcswidth@1.0.1: resolution: {integrity: sha512-xMO/8eNREtaROt7tJvWJqHBDTMFN4eiQ5I4JRMuilwfnFcV5W9u7RUkueNkdw0jPqGMX36iCywelS5yilTuOxg==} + sirv@3.0.2: + resolution: {integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==} + engines: {node: '>=18'} + sisteransi@1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} @@ -7274,6 +7361,12 @@ packages: stable-hash@0.0.5: resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==} + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + std-env@3.10.0: + resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} + stdin-discarder@0.2.2: resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==} engines: {node: '>=18'} @@ -7464,12 +7557,19 @@ packages: tiny-warning@1.0.3: resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==} + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + tinyexec@0.3.2: resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} tinyexec@1.0.1: resolution: {integrity: sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==} + tinyexec@1.0.2: + resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==} + engines: {node: '>=18'} + tinyglobby@0.2.13: resolution: {integrity: sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==} engines: {node: '>=12.0.0'} @@ -7478,6 +7578,10 @@ packages: resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} + tinyrainbow@3.0.3: + resolution: {integrity: sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==} + engines: {node: '>=14.0.0'} + tldts-core@7.0.14: resolution: {integrity: sha512-viZGNK6+NdluOJWwTO9olaugx0bkKhscIdriQQ+lNNhwitIKvb+SvhbYgnCz6j9p7dX3cJntt4agQAKMXLjJ5g==} @@ -7493,6 +7597,10 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + totalist@3.0.1: + resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} + engines: {node: '>=6'} + touch@3.1.1: resolution: {integrity: sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==} hasBin: true @@ -7889,6 +7997,40 @@ packages: yaml: optional: true + vitest@4.0.16: + resolution: {integrity: sha512-E4t7DJ9pESL6E3I8nFjPa4xGUd3PmiWDLsDztS2qXSJWfHtbQnwAWylaBvSNY48I3vr8PTqIZlyK8TE3V3CA4Q==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@opentelemetry/api': ^1.9.0 + '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 4.0.16 + '@vitest/browser-preview': 4.0.16 + '@vitest/browser-webdriverio': 4.0.16 + '@vitest/ui': 4.0.16 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@opentelemetry/api': + optional: true + '@types/node': + optional: true + '@vitest/browser-playwright': + optional: true + '@vitest/browser-preview': + optional: true + '@vitest/browser-webdriverio': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + void-elements@3.1.0: resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==} engines: {node: '>=0.10.0'} @@ -7954,6 +8096,11 @@ packages: engines: {node: ^18.17.0 || >=20.5.0} hasBin: true + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + widest-line@3.1.0: resolution: {integrity: sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==} engines: {node: '>=8'} @@ -10364,6 +10511,8 @@ snapshots: '@pnpm/network.ca-file': 1.0.2 config-chain: 1.1.13 + '@polka/url@1.0.0-next.29': {} + '@portabletext/block-tools@3.5.6(@sanity/schema@4.9.0(@types/react@19.1.13)(debug@4.4.3))(@sanity/types@4.9.0(@types/react@19.1.13)(debug@4.4.3))(@types/react@19.1.13)': dependencies: '@portabletext/sanity-bridge': 1.1.10(@sanity/schema@4.9.0(@types/react@19.1.13)(debug@4.4.3))(@sanity/types@4.9.0(@types/react@19.1.13)(debug@4.4.3)) @@ -11461,6 +11610,8 @@ snapshots: '@sindresorhus/merge-streams@2.3.0': {} + '@standard-schema/spec@1.1.0': {} + '@tanstack/eslint-plugin-query@5.89.0(eslint@9.25.1(jiti@2.5.1))(typescript@5.9.2)': dependencies: '@typescript-eslint/utils': 8.44.0(eslint@9.25.1(jiti@2.5.1))(typescript@5.9.2) @@ -11535,10 +11686,17 @@ snapshots: dependencies: '@babel/types': 7.27.1 + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + '@types/conventional-commits-parser@5.0.1': dependencies: '@types/node': 22.15.3 + '@types/deep-eql@4.0.2': {} + '@types/eslint@9.6.1': dependencies: '@types/estree': 1.0.7 @@ -11874,6 +12032,56 @@ snapshots: transitivePeerDependencies: - supports-color + '@vitest/expect@4.0.16': + dependencies: + '@standard-schema/spec': 1.1.0 + '@types/chai': 5.2.3 + '@vitest/spy': 4.0.16 + '@vitest/utils': 4.0.16 + chai: 6.2.1 + tinyrainbow: 3.0.3 + + '@vitest/mocker@4.0.16(vite@7.1.6(@types/node@22.15.3)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.39.0)(tsx@4.20.5)(yaml@2.7.1))': + dependencies: + '@vitest/spy': 4.0.16 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 7.1.6(@types/node@22.15.3)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.39.0)(tsx@4.20.5)(yaml@2.7.1) + + '@vitest/pretty-format@4.0.16': + dependencies: + tinyrainbow: 3.0.3 + + '@vitest/runner@4.0.16': + dependencies: + '@vitest/utils': 4.0.16 + pathe: 2.0.3 + + '@vitest/snapshot@4.0.16': + dependencies: + '@vitest/pretty-format': 4.0.16 + magic-string: 0.30.21 + pathe: 2.0.3 + + '@vitest/spy@4.0.16': {} + + '@vitest/ui@4.0.16(vitest@4.0.16)': + dependencies: + '@vitest/utils': 4.0.16 + fflate: 0.8.2 + flatted: 3.3.3 + pathe: 2.0.3 + sirv: 3.0.2 + tinyglobby: 0.2.15 + tinyrainbow: 3.0.3 + vitest: 4.0.16(@types/node@22.15.3)(@vitest/ui@4.0.16)(jiti@2.5.1)(jsdom@23.2.0)(lightningcss@1.30.1)(terser@5.39.0)(tsx@4.20.5)(yaml@2.7.1) + + '@vitest/utils@4.0.16': + dependencies: + '@vitest/pretty-format': 4.0.16 + tinyrainbow: 3.0.3 + '@waspeer/config@2.4.5(eslint@9.25.1(jiti@2.5.1))(postcss@8.5.6)(prettier@3.6.2)(ts-api-utils@2.1.0(typescript@5.9.2))(typescript@5.9.2)': dependencies: '@eslint-react/eslint-plugin': 1.48.5(eslint@9.25.1(jiti@2.5.1))(ts-api-utils@2.1.0(typescript@5.9.2))(typescript@5.9.2) @@ -12087,6 +12295,8 @@ snapshots: arrify@2.0.1: {} + assertion-error@2.0.1: {} + ast-kit@2.1.2: dependencies: '@babel/parser': 7.28.4 @@ -12324,6 +12534,8 @@ snapshots: dependencies: react: 19.1.1 + chai@6.2.1: {} + chalk@2.4.2: dependencies: ansi-styles: 3.2.1 @@ -13414,6 +13626,10 @@ snapshots: estree-walker@2.0.2: {} + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.8 + esutils@2.0.3: {} eta@4.0.1: {} @@ -13475,6 +13691,8 @@ snapshots: exif-component@1.0.1: {} + expect-type@1.3.0: {} + exsolve@1.0.7: {} extend-shallow@2.0.1: @@ -13521,6 +13739,8 @@ snapshots: optionalDependencies: picomatch: 4.0.3 + fflate@0.8.2: {} + figures@3.2.0: dependencies: escape-string-regexp: 1.0.5 @@ -14829,6 +15049,10 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + make-dir@2.1.0: dependencies: pify: 4.0.1 @@ -15005,6 +15229,8 @@ snapshots: motion-utils@12.23.6: {} + mrmime@2.0.1: {} + ms@2.0.0: {} ms@2.1.3: {} @@ -15170,6 +15396,8 @@ snapshots: dependencies: rxjs: 7.8.2 + obug@2.1.1: {} + ohash@2.0.11: {} once@1.4.0: @@ -16439,6 +16667,8 @@ snapshots: side-channel-map: 1.0.1 side-channel-weakmap: 1.0.2 + siginfo@2.0.0: {} + signal-exit@3.0.7: {} signal-exit@4.1.0: {} @@ -16449,6 +16679,12 @@ snapshots: simple-wcswidth@1.0.1: {} + sirv@3.0.2: + dependencies: + '@polka/url': 1.0.0-next.29 + mrmime: 2.0.1 + totalist: 3.0.1 + sisteransi@1.0.5: {} slash@3.0.0: {} @@ -16553,6 +16789,10 @@ snapshots: stable-hash@0.0.5: {} + stackback@0.0.2: {} + + std-env@3.10.0: {} + stdin-discarder@0.2.2: {} stream-each@1.2.3: @@ -16778,10 +17018,14 @@ snapshots: tiny-warning@1.0.3: {} + tinybench@2.9.0: {} + tinyexec@0.3.2: {} tinyexec@1.0.1: {} + tinyexec@1.0.2: {} + tinyglobby@0.2.13: dependencies: fdir: 6.4.4(picomatch@4.0.2) @@ -16792,6 +17036,8 @@ snapshots: fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 + tinyrainbow@3.0.3: {} + tldts-core@7.0.14: {} tldts@7.0.14: @@ -16806,6 +17052,8 @@ snapshots: dependencies: is-number: 7.0.0 + totalist@3.0.1: {} + touch@3.1.1: {} tough-cookie@4.1.4: @@ -17158,6 +17406,45 @@ snapshots: tsx: 4.20.5 yaml: 2.7.1 + vitest@4.0.16(@types/node@22.15.3)(@vitest/ui@4.0.16)(jiti@2.5.1)(jsdom@23.2.0)(lightningcss@1.30.1)(terser@5.39.0)(tsx@4.20.5)(yaml@2.7.1): + dependencies: + '@vitest/expect': 4.0.16 + '@vitest/mocker': 4.0.16(vite@7.1.6(@types/node@22.15.3)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.39.0)(tsx@4.20.5)(yaml@2.7.1)) + '@vitest/pretty-format': 4.0.16 + '@vitest/runner': 4.0.16 + '@vitest/snapshot': 4.0.16 + '@vitest/spy': 4.0.16 + '@vitest/utils': 4.0.16 + es-module-lexer: 1.7.0 + expect-type: 1.3.0 + magic-string: 0.30.21 + obug: 2.1.1 + pathe: 2.0.3 + picomatch: 4.0.3 + std-env: 3.10.0 + tinybench: 2.9.0 + tinyexec: 1.0.2 + tinyglobby: 0.2.15 + tinyrainbow: 3.0.3 + vite: 7.1.6(@types/node@22.15.3)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.39.0)(tsx@4.20.5)(yaml@2.7.1) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 22.15.3 + '@vitest/ui': 4.0.16(vitest@4.0.16) + jsdom: 23.2.0 + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - terser + - tsx + - yaml + void-elements@3.1.0: {} w3c-xmlserializer@5.0.0: @@ -17241,6 +17528,11 @@ snapshots: dependencies: isexe: 3.1.1 + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + widest-line@3.1.0: dependencies: string-width: 4.2.3 diff --git a/src/lib/types.test.ts b/src/lib/types.test.ts new file mode 100644 index 0000000..c580cd5 --- /dev/null +++ b/src/lib/types.test.ts @@ -0,0 +1,82 @@ +import { defineField } from 'sanity'; +import { describe, it, expectTypeOf } from 'vitest'; +import type { IconValue } from './types'; + +describe('IconDefinition - Type Safety', () => { + it('should strongly type value as IconValue in validation callbacks', () => { + defineField({ + name: 'icon', + type: 'icon', + validation: (Rule) => + Rule.custom((value) => { + // value should be typed as IconValue | undefined + expectTypeOf(value).toExtend(); + expectTypeOf(value?.name).toExtend(); + + // Should support real-world validation logic + if (!value?.name) { + return 'Icon is required'; + } + + if (!value.name.startsWith('mdi:')) { + return 'Only Material Design Icons are allowed'; + } + + return true; + }), + }); + }); + + it('should strongly type value as IconValue in hidden callbacks', () => { + defineField({ + name: 'icon', + type: 'icon', + hidden: ({ value, document }) => { + // value should be typed as IconValue (not undefined) + expectTypeOf(value).toExtend(); + expectTypeOf(value.name).toExtend(); + + // Should support real-world conditional logic + return value.name === 'hidden-icon' || document?._type === 'simple'; + }, + }); + }); + + it('should strongly type value as IconValue in readOnly callbacks', () => { + defineField({ + name: 'icon', + type: 'icon', + readOnly: ({ value, document }) => { + // value should be typed as IconValue (not undefined) + expectTypeOf(value).toExtend(); + expectTypeOf(value.name).toExtend(); + + // Should support real-world conditional logic + const isPublished = document?.published === true; + const isSystemIcon = value.name?.startsWith('system:') ?? false; + + return isPublished && isSystemIcon; + }, + }); + }); + + it('should maintain IconValue type across all callbacks when combined', () => { + defineField({ + name: 'icon', + type: 'icon', + hidden: ({ value }) => { + expectTypeOf(value).toExtend(); + return value.name === 'test'; + }, + readOnly: ({ value }) => { + expectTypeOf(value).toExtend(); + return value.name === 'locked'; + }, + validation: (Rule) => + Rule.custom((value) => { + expectTypeOf(value).toExtend(); + return value?.name === 'yihaa' ? true : 'error'; + }), + }); + }); +}); diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000..8abc388 --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + environment: 'node', + include: ['**/*.test.ts', '**/*.test.tsx'], + }, +}); From c85dbc4bdf83610b39d98c2421175efa8b44d0b3 Mon Sep 17 00:00:00 2001 From: Danilo Arioli Date: Fri, 19 Dec 2025 16:49:22 +0100 Subject: [PATCH 3/9] fix: export icon definitions directly from the plugin instead of sanity module declaration --- dev/schema.ts | 12 ----------- src/lib/types.test.ts | 2 +- src/lib/types.ts | 48 +++++++++++++++++++++---------------------- 3 files changed, 25 insertions(+), 37 deletions(-) delete mode 100644 dev/schema.ts diff --git a/dev/schema.ts b/dev/schema.ts deleted file mode 100644 index c0718bb..0000000 --- a/dev/schema.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { defineField } from 'sanity'; - -export const test = defineField({ - name: 'test', - type: 'icon', - hidden: ({ value }) => value.name === 'test', - validation: (Rule) => - Rule.custom((value) => { - const name = value?.name; - return name === 'lucide:home' ? true : 'error'; - }), -}); diff --git a/src/lib/types.test.ts b/src/lib/types.test.ts index c580cd5..a18b05a 100644 --- a/src/lib/types.test.ts +++ b/src/lib/types.test.ts @@ -75,7 +75,7 @@ describe('IconDefinition - Type Safety', () => { validation: (Rule) => Rule.custom((value) => { expectTypeOf(value).toExtend(); - return value?.name === 'yihaa' ? true : 'error'; + return value?.name === 'lucide:home' ? true : 'error'; }), }); }); diff --git a/src/lib/types.ts b/src/lib/types.ts index 97008bd..d43bfcd 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -31,39 +31,39 @@ export interface IconifySearchResult { collections: Record; } +// Extend the Sanity schema types to include our custom type export interface IconValue { name?: string; } -// Extend the Sanity schema types to include our custom type -declare module 'sanity' { - //eslint-disable-next-line - export interface IconRule extends RuleDef {} +//eslint-disable-next-line +export interface IconRule extends RuleDef {} - export type IconConditionalPropertyCallbackContext = Omit< - ConditionalPropertyCallbackContext, - 'value' - > & { - value: IconValue; - }; +export type IconConditionalPropertyCallbackContext = Omit< + ConditionalPropertyCallbackContext, + 'value' +> & { + value: IconValue; +}; - export type IconConditionalPropertyCallback = ( - context: IconConditionalPropertyCallbackContext, - ) => boolean; +export type IconConditionalPropertyCallback = ( + context: IconConditionalPropertyCallbackContext, +) => boolean; - export type IconConditionalProperty = boolean | IconConditionalPropertyCallback | undefined; +export type IconConditionalProperty = boolean | IconConditionalPropertyCallback | undefined; - interface IconDefinition extends Omit { - type: 'icon'; - groups?: FieldGroupDefinition[]; - fieldsets?: FieldsetDefinition[]; - preview?: PreviewConfig; - options?: IconOptions; - hidden?: IconConditionalProperty; - readOnly?: IconConditionalProperty; - validation?: ValidationBuilder; - } +export interface IconDefinition extends Omit { + type: 'icon'; + groups?: FieldGroupDefinition[]; + fieldsets?: FieldsetDefinition[]; + preview?: PreviewConfig; + options?: IconOptions; + hidden?: IconConditionalProperty; + readOnly?: IconConditionalProperty; + validation?: ValidationBuilder; +} +declare module 'sanity' { export interface IntrinsicDefinitions { icon: IconDefinition; } From cc599692df8ee71e799b3400569a6872ee492d28 Mon Sep 17 00:00:00 2001 From: Danilo Arioli Date: Fri, 19 Dec 2025 17:12:23 +0100 Subject: [PATCH 4/9] fix: remove preview in IconDefinition and add necessary types to bundle --- src/lib/types.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/lib/types.ts b/src/lib/types.ts index d43bfcd..b428506 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -4,7 +4,6 @@ import type { ConditionalPropertyCallbackContext, FieldGroupDefinition, FieldsetDefinition, - PreviewConfig, RuleDef, ValidationBuilder, } from 'sanity'; @@ -13,7 +12,14 @@ import type { import type { IconPrefix } from './icon-types.gen'; // Export types that need to be bundled with the plugin -export type { BaseSchemaDefinition } from 'sanity'; +export type { + BaseSchemaDefinition, + ConditionalPropertyCallbackContext, + RuleDef, + FieldGroupDefinition, + FieldsetDefinition, +} from 'sanity'; + export type { IconPrefix }; export interface IconOptions { @@ -56,7 +62,6 @@ export interface IconDefinition extends Omit Date: Fri, 19 Dec 2025 17:25:34 +0100 Subject: [PATCH 5/9] feat: add collapsed and collapsible properties to IconDefinition options --- src/lib/types.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib/types.ts b/src/lib/types.ts index b428506..24972fd 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -4,6 +4,7 @@ import type { ConditionalPropertyCallbackContext, FieldGroupDefinition, FieldsetDefinition, + ObjectOptions, RuleDef, ValidationBuilder, } from 'sanity'; @@ -62,7 +63,7 @@ export interface IconDefinition extends Omit; hidden?: IconConditionalProperty; readOnly?: IconConditionalProperty; validation?: ValidationBuilder; From 39a42e7c844c1fc9867ca57db9da731d923d76b3 Mon Sep 17 00:00:00 2001 From: Danilo Arioli Date: Fri, 19 Dec 2025 17:44:19 +0100 Subject: [PATCH 6/9] fix: move collapsed and collapsible properties to IconOptions --- src/lib/types.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/types.ts b/src/lib/types.ts index 24972fd..252b487 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -23,10 +23,10 @@ export type { export type { IconPrefix }; -export interface IconOptions { +export type IconOptions = { collections?: IconPrefix[]; showName?: boolean; -} +} & Pick; export interface IconifyPluginConfig { collections?: IconPrefix[]; @@ -63,7 +63,7 @@ export interface IconDefinition extends Omit; + options?: IconOptions; hidden?: IconConditionalProperty; readOnly?: IconConditionalProperty; validation?: ValidationBuilder; From 0745cb7ba4c2b08ae7b7884f7644a4b6d02e7dbb Mon Sep 17 00:00:00 2001 From: Danilo Arioli Date: Fri, 19 Dec 2025 17:54:42 +0100 Subject: [PATCH 7/9] fix: consider that icon value can also be undefined --- src/lib/types.test.ts | 12 ++++++------ src/lib/types.ts | 8 +++++--- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/lib/types.test.ts b/src/lib/types.test.ts index a18b05a..46dfbf2 100644 --- a/src/lib/types.test.ts +++ b/src/lib/types.test.ts @@ -34,10 +34,10 @@ describe('IconDefinition - Type Safety', () => { hidden: ({ value, document }) => { // value should be typed as IconValue (not undefined) expectTypeOf(value).toExtend(); - expectTypeOf(value.name).toExtend(); + expectTypeOf(value?.name).toExtend(); // Should support real-world conditional logic - return value.name === 'hidden-icon' || document?._type === 'simple'; + return value?.name === 'hidden-icon' || document?._type === 'simple'; }, }); }); @@ -49,11 +49,11 @@ describe('IconDefinition - Type Safety', () => { readOnly: ({ value, document }) => { // value should be typed as IconValue (not undefined) expectTypeOf(value).toExtend(); - expectTypeOf(value.name).toExtend(); + expectTypeOf(value?.name).toExtend(); // Should support real-world conditional logic const isPublished = document?.published === true; - const isSystemIcon = value.name?.startsWith('system:') ?? false; + const isSystemIcon = value?.name?.startsWith('system:') ?? false; return isPublished && isSystemIcon; }, @@ -66,11 +66,11 @@ describe('IconDefinition - Type Safety', () => { type: 'icon', hidden: ({ value }) => { expectTypeOf(value).toExtend(); - return value.name === 'test'; + return value?.name === 'test'; }, readOnly: ({ value }) => { expectTypeOf(value).toExtend(); - return value.name === 'locked'; + return value?.name === 'locked'; }, validation: (Rule) => Rule.custom((value) => { diff --git a/src/lib/types.ts b/src/lib/types.ts index 252b487..f23dd91 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -39,9 +39,11 @@ export interface IconifySearchResult { } // Extend the Sanity schema types to include our custom type -export interface IconValue { - name?: string; -} +export type IconValue = + | { + name?: string; + } + | undefined; //eslint-disable-next-line export interface IconRule extends RuleDef {} From ed6b478fda5a3a6fa481d1a7f42674f0fcc4a050 Mon Sep 17 00:00:00 2001 From: Danilo Arioli Date: Fri, 19 Dec 2025 18:01:46 +0100 Subject: [PATCH 8/9] test: expect value to extend IconValue, which can also be undefined --- src/lib/types.test.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/lib/types.test.ts b/src/lib/types.test.ts index 46dfbf2..7654348 100644 --- a/src/lib/types.test.ts +++ b/src/lib/types.test.ts @@ -9,8 +9,8 @@ describe('IconDefinition - Type Safety', () => { type: 'icon', validation: (Rule) => Rule.custom((value) => { - // value should be typed as IconValue | undefined - expectTypeOf(value).toExtend(); + // value should be typed as IconValue + expectTypeOf(value).toExtend(); expectTypeOf(value?.name).toExtend(); // Should support real-world validation logic @@ -32,7 +32,7 @@ describe('IconDefinition - Type Safety', () => { name: 'icon', type: 'icon', hidden: ({ value, document }) => { - // value should be typed as IconValue (not undefined) + // value should be typed as IconValue expectTypeOf(value).toExtend(); expectTypeOf(value?.name).toExtend(); @@ -47,7 +47,7 @@ describe('IconDefinition - Type Safety', () => { name: 'icon', type: 'icon', readOnly: ({ value, document }) => { - // value should be typed as IconValue (not undefined) + // value should be typed as IconValue expectTypeOf(value).toExtend(); expectTypeOf(value?.name).toExtend(); @@ -74,7 +74,7 @@ describe('IconDefinition - Type Safety', () => { }, validation: (Rule) => Rule.custom((value) => { - expectTypeOf(value).toExtend(); + expectTypeOf(value).toExtend(); return value?.name === 'lucide:home' ? true : 'error'; }), }); From c4b7fff98e855560dd9c35047bfbdd9dd1858e00 Mon Sep 17 00:00:00 2001 From: Danilo Arioli Date: Sun, 21 Dec 2025 18:22:37 +0100 Subject: [PATCH 9/9] feat: add initialValue type in IconDefinition --- src/lib/types.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lib/types.ts b/src/lib/types.ts index f23dd91..058e5ec 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -4,6 +4,7 @@ import type { ConditionalPropertyCallbackContext, FieldGroupDefinition, FieldsetDefinition, + InitialValueProperty, ObjectOptions, RuleDef, ValidationBuilder, @@ -19,6 +20,7 @@ export type { RuleDef, FieldGroupDefinition, FieldsetDefinition, + InitialValueProperty, } from 'sanity'; export type { IconPrefix }; @@ -69,6 +71,7 @@ export interface IconDefinition extends Omit; + initialValue?: InitialValueProperty; } declare module 'sanity' {