generated from chiffre-io/template-library
-
-
Notifications
You must be signed in to change notification settings - Fork 227
feat: Shadcn Registry Package #1188
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
I-3B
wants to merge
14
commits into
47ng:next
Choose a base branch
from
I-3B:feat/registry
base: next
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+656
−29
Open
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
2d96275
feat: parseAsTuple (#1036)
I-3B 1fea0c1
feat: add registry package with parseAsTuple item
I-3B 0743e8c
feat: remove parseAsTuple from parsers.test.ts
I-3B 0818109
doc: add README to registry
I-3B 53c8d99
doc(registry): add usage example for parseAsTuple parser
I-3B ab20790
test(registry): update shadcn to 3.4.2, add vitest for testing, and i…
I-3B 09a0eee
feat(registry): move safe-parse util to registry package, restructur…
I-3B 0bb04a2
chore(registry): reorder dependencies and devDependencies in package.…
I-3B f76b99d
feat(registry): use nuqs/lib export
I-3B 93640c8
Merge branch 'next' into feat/registry
I-3B f35ba1b
feat(registry): update docs to use registry package
I-3B 88dad2b
test: add safeParse function export to API test
I-3B fc7d16f
doc: update parse-as-tuple example to use correct import path
I-3B 0cd611d
Merge branch 'next' into feat/registry
I-3B File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| The `parseAsTuple` parser allows you to parse fixed-length tuples with **any type** for each position. | ||
|
|
||
| ```ts | ||
| import { parseAsTuple } from '@/lib/parsers/parse-as-tuple' | ||
| import { parseAsInteger } from 'nuqs' | ||
|
|
||
| // Coordinates tuple (x, y) | ||
| parseAsTuple([parseAsInteger, parseAsInteger]) | ||
|
|
||
| // Optionally, customise the separator | ||
| parseAsTuple([parseAsInteger, parseAsInteger], ';') | ||
| ``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export * from './safe-parse' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| public/r/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| # registry | ||
|
|
||
| A shadcn/ui compatible registry for community parsers and utilities for the [nuqs](https://nuqs.dev) library. | ||
|
|
||
| ## Development | ||
|
|
||
| ```bash | ||
| # Install dependencies | ||
| pnpm install | ||
|
|
||
| # Build the registry | ||
| cd ../docs && pnpm build:registry | ||
| # Run the docs server | ||
| cd ../docs && pnpm dev | ||
|
|
||
| ``` | ||
|
|
||
| Usage example in any npm package: | ||
|
|
||
| ```bash | ||
| pnpm dlx shadcn@latest add http://localhost:3000/r/parse-as-tuple.json | ||
| ``` | ||
|
|
||
| ## Learn More | ||
|
|
||
| To learn more about nuqs and shadcn/ui registries, take a look at the following resources: | ||
|
|
||
| - [nuqs Documentation](https://nuqs.dev) - learn about nuqs features and API | ||
| - [shadcn/ui Registry Documentation](https://ui.shadcn.com/docs/registry) - learn about shadcn/ui registries | ||
| - [nuqs GitHub Repository](https://github.com/47ng/nuqs) - source code and issues |
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. note: This one would be difficult to test without having a proper Next.js setup to typegen route definitions from, which we do have in the docs and could test against there. |
File renamed without changes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| { | ||
| "name": "registry", | ||
| "description": "Shadcn CLI registry for community parsers & utilities", | ||
| "scripts": { | ||
| "test": "pnpm run --stream '/^test:/'", | ||
| "test:unit": "vitest run --typecheck" | ||
| }, | ||
| "dependencies": { | ||
| "next": "15.5.0", | ||
| "nuqs": "workspace:*", | ||
| "shadcn": "^3.4.2" | ||
| }, | ||
| "devDependencies": { | ||
| "typescript": "^5.9.2", | ||
| "vitest": "^3.2.4" | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| import { parseAsBoolean, parseAsInteger, parseAsString } from 'nuqs' | ||
| import { | ||
| isParserBijective, | ||
| testParseThenSerialize, | ||
| testSerializeThenParse | ||
| } from 'nuqs/testing' | ||
| import { describe, expect, it } from 'vitest' | ||
| import { parseAsTuple } from './parse-as-tuple' | ||
|
|
||
| describe('parseAsTuple', () => { | ||
| it('parses and serializes tuples correctly', () => { | ||
| const parser = parseAsTuple([parseAsInteger, parseAsString, parseAsBoolean]) | ||
| expect(parser.parse('1,a,false,will-ignore')).toStrictEqual([1, 'a', false]) | ||
| expect(parser.parse('not-a-number,a,true')).toBeNull() | ||
| expect(parser.parse('1,a')).toBeNull() | ||
| // @ts-expect-error - Tuple length is less than 2 | ||
| expect(() => parseAsTuple([parseAsInteger])).toThrow() | ||
| expect(parser.serialize([1, 'a', true])).toBe('1,a,true') | ||
| // @ts-expect-error - Tuple length mismatch | ||
| expect(() => parser.serialize([1, 'a'])).toThrow() | ||
| expect(testParseThenSerialize(parser, '1,a,true')).toBe(true) | ||
| expect(testSerializeThenParse(parser, [1, 'a', true] as const)).toBe(true) | ||
| expect(isParserBijective(parser, '1,a,true', [1, 'a', true] as const)).toBe( | ||
| true | ||
| ) | ||
| expect(() => | ||
| isParserBijective(parser, 'not-a-tuple', [1, 'a', true] as const) | ||
| ).toThrow() | ||
| }) | ||
|
|
||
| it('equality comparison works correctly', () => { | ||
| const eq = parseAsTuple([parseAsInteger, parseAsBoolean]).eq! | ||
| expect(eq([1, true], [1, true])).toBe(true) | ||
| expect(eq([1, true], [1, false])).toBe(false) | ||
| expect(eq([1, true], [2, true])).toBe(false) | ||
| // @ts-expect-error - Tuple length mismatch | ||
| expect(eq([1, true], [1])).toBe(false) | ||
| // @ts-expect-error - Tuple length mismatch | ||
| expect(eq([1], [1])).toBe(false) | ||
| }) | ||
| }) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,74 @@ | ||
| import { createParser, type SingleParserBuilder } from 'nuqs' | ||
| import { safeParse } from 'nuqs/lib' | ||
|
|
||
| type ParserTuple<T extends readonly unknown[]> = { | ||
| [K in keyof T]: SingleParserBuilder<T[K]> | ||
| } & { length: 2 | 3 | 4 | 5 | 6 | 7 | 8 } | ||
|
|
||
| /** | ||
| * Parse a comma-separated tuple with type-safe positions. | ||
| * Items are URI-encoded for safety, so they may not look nice in the URL. | ||
| * allowed tuple length is 2-8. | ||
| * | ||
| * @param itemParsers Tuple of parsers for each position in the tuple | ||
| * @param separator The character to use to separate items (default ',') | ||
| */ | ||
| export function parseAsTuple<T extends any[]>( | ||
| itemParsers: ParserTuple<T>, | ||
| separator = ',' | ||
| ): SingleParserBuilder<T> { | ||
| const encodedSeparator = encodeURIComponent(separator) | ||
| if (itemParsers.length < 2 || itemParsers.length > 8) { | ||
| throw new Error( | ||
| `Tuple length must be between 2 and 8, got ${itemParsers.length}` | ||
| ) | ||
| } | ||
| return createParser<T>({ | ||
| parse: query => { | ||
| if (query === '') { | ||
| return null | ||
| } | ||
| const parts = query.split(separator) | ||
| if (parts.length < itemParsers.length) { | ||
| return null | ||
| } | ||
| // iterating by parsers instead of parts, any additional parts are ignored. | ||
| const result = itemParsers.map( | ||
| (parser, index) => | ||
| safeParse( | ||
| parser.parse, | ||
| parts[index]!.replaceAll(encodedSeparator, separator), | ||
| `[${index}]` | ||
| ) as T[number] | null | ||
| ) | ||
| return result.some(x => x === null) ? null : (result as T) | ||
| }, | ||
| serialize: (values: T) => { | ||
| if (values.length !== itemParsers.length) { | ||
| throw new Error( | ||
| `Tuple length mismatch: expected ${itemParsers.length}, got ${values.length}` | ||
| ) | ||
| } | ||
| return values | ||
| .map((value, index) => { | ||
| const parser = itemParsers[index]! | ||
| const str = parser.serialize ? parser.serialize(value) : String(value) | ||
| return str.replaceAll(separator, encodedSeparator) | ||
| }) | ||
| .join(separator) | ||
| }, | ||
| eq(a: T, b: T) { | ||
| if (a === b) { | ||
| return true | ||
| } | ||
| if (a.length !== b.length || a.length !== itemParsers.length) { | ||
| return false | ||
| } | ||
| return a.every((value, index) => { | ||
| const parser = itemParsers[index]! | ||
| const itemEq = parser.eq ?? ((x, y) => x === y) | ||
| return itemEq(value, b[index]) | ||
| }) | ||
| } | ||
| }) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| { | ||
| "$schema": "https://json.schemastore.org/tsconfig", | ||
| "compilerOptions": { | ||
| "jsx": "react", | ||
| // Type checking | ||
| "strict": true, | ||
| "noUncheckedIndexedAccess": true, | ||
| "alwaysStrict": false, // Don't emit "use strict" to avoid conflicts with "use client" | ||
| // Modules | ||
| "module": "ESNext", | ||
| "moduleResolution": "Bundler", | ||
| "resolveJsonModule": true, | ||
| // Language & Environment | ||
| "target": "ESNext", | ||
| "lib": ["DOM", "DOM.Iterable", "ESNext"], | ||
| // Emit | ||
| "noEmit": true, | ||
| "declaration": true, | ||
| "declarationMap": true, | ||
| "verbatimModuleSyntax": true, | ||
| "moduleDetection": "force", | ||
|
|
||
| "downlevelIteration": true, | ||
| // Interop | ||
| "isolatedModules": true, | ||
| "esModuleInterop": true, | ||
| "forceConsistentCasingInFileNames": true, | ||
| // Misc | ||
| "skipLibCheck": true, | ||
| "skipDefaultLibCheck": true, | ||
| "incremental": true, | ||
| "tsBuildInfoFile": ".tsbuildinfo" | ||
| }, | ||
| "include": ["**/*.ts", "**/*.tsx"], | ||
| "exclude": ["node_modules", "dist"] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| import { defineConfig, type ViteUserConfig } from 'vitest/config' | ||
|
|
||
| const config: ViteUserConfig = defineConfig({ | ||
| test: { | ||
| typecheck: { | ||
| tsconfig: './tsconfig.json' | ||
| } | ||
| } | ||
| }) | ||
|
|
||
| export default config |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: usage files should remain next to their source files.