diff --git a/src/lib/SearchableJson.svelte b/src/lib/SearchableJson.svelte index 708dc62b6..00bac0375 100644 --- a/src/lib/SearchableJson.svelte +++ b/src/lib/SearchableJson.svelte @@ -5,6 +5,7 @@ import { packageManager } from '$stores/packageManager'; import CategoryFilters from '$lib/CategoryFilters.svelte'; import { filterArray, sortArray } from '$utils/arrayUtils'; + import { tick } from 'svelte'; // eslint-disable-next-line @typescript-eslint/no-explicit-any export let data: any[]; @@ -18,6 +19,28 @@ let searchValue: string; let sort = sortableFields[0]; + packageManager.subscribe((newValues) => { + const grouped = newValues.reduce( + (carry, item) => { + if (['npm', 'pnpm', 'yarn'].includes(item)) { + carry['npm'].push(item); + } + if (['gem', 'bundler'].includes(item)) { + carry['gem'].push(item); + } + return carry; + }, + { npm: [], gem: [] } as { npm: Array; gem: Array } + ); + const corrected = [ + grouped['npm'][grouped['npm'].length - 1] ?? 'npm', + grouped['gem'][grouped['gem'].length - 1] ?? 'gem' + ]; + if (newValues.join() !== corrected.join()) { + tick().then(() => packageManager.set(corrected)); + } + }); + $: filteredData = filterArray(data, searchValue); $: sortedData = sortArray(filteredData, sort); @@ -48,12 +71,19 @@ isClearable={false} isSearchable={false} showIndicator - value={{ value: $packageManager }} - on:select={({ detail }) => ($packageManager = detail.value)} + handleClear={() => ({})} + value={$packageManager.map((value) => ({ value }))} + groupBy={(item) => item.group} + isMulti={true} + on:select={({ detail }) => { + $packageManager = (detail ?? []).map((i) => i.value); + }} items={[ - { label: 'NPM', value: 'npm' }, - { label: 'PNPM', value: 'pnpm' }, - { label: 'Yarn', value: 'yarn' } + { label: 'NPM', value: 'npm', group: 'NPM' }, + { label: 'PNPM', value: 'pnpm', group: 'NPM' }, + { label: 'Yarn', value: 'yarn', group: 'NPM' }, + { label: 'RubyGem', value: 'gem', group: 'Gem' }, + { label: 'Bundler', value: 'bundler', group: 'Gem' } ]} /> {/each} diff --git a/src/lib/components/ComponentIndex/Card.svelte b/src/lib/components/ComponentIndex/Card.svelte index 382a7f0c3..e7a0b1498 100644 --- a/src/lib/components/ComponentIndex/Card.svelte +++ b/src/lib/components/ComponentIndex/Card.svelte @@ -7,22 +7,35 @@ export let title: string; export let description: string; export let stars: string; - export let npm = ''; - export let repository = undefined; + export let npm: string | undefined = undefined; + export let gem: string | undefined = undefined; + export let repository: string | undefined = undefined; export let date = undefined; export let version = undefined; let clipboardCopy = false; const copy = () => { - copyToClipboard(`${packageManagers[$manager]} ${npm}`).then(() => (clipboardCopy = false)); + copyToClipboard(packageManagerAction($manager, npm, gem)).then(() => (clipboardCopy = false)); clipboardCopy = true; }; + const packageManagerAction = ($manager: Array, npm?: string, gem?: string): string => { + if (npm) { + return `${packageManagers[$manager.find((m) => ['npm', 'pnpm', 'yarn'].includes(m)) ?? 'npm']} ${npm}`; + } + if (gem) { + return `${packageManagers[$manager.find((m) => ['gem', 'bundler'].includes(m)) ?? 'gem']} ${gem}`; + } + return ''; + }; + const packageManagers = { npm: 'npm install', pnpm: 'pnpm add', - yarn: 'yarn add' + yarn: 'yarn add', + gem: 'gem install', + bundler: 'bundle add' }; @@ -34,7 +47,7 @@
- {#if repository.includes('github')} + {#if repository?.includes('github')} github logo - {:else if repository.includes('gitlab')} + {:else if repository?.includes('gitlab')} gitlab logo - + {:else if repository} + + 🌐 + {/if}
- {#if npm} + {#if npm || gem} copy()} variant="copy" - title={clipboardCopy ? 'copied!' : `${packageManagers[$manager]} ${npm}`} + title={clipboardCopy ? 'copied!' : packageManagerAction($manager, npm, gem)} /> {/if}

{description}

@@ -89,6 +110,9 @@ margin: -4px; background-color: rgba(0, 0, 0, 0); transition: background-color 200ms ease-out; + text-decoration: none; + font-size: 1rem; + line-height: 18px; } .repo:hover { background-color: rgba(0, 0, 0, 0.25); diff --git a/src/lib/components/Select.svelte b/src/lib/components/Select.svelte index feaa26473..c95442828 100644 --- a/src/lib/components/Select.svelte +++ b/src/lib/components/Select.svelte @@ -28,7 +28,7 @@ flex-direction: column; } - .themed :global(.select-container) { + .themed :global(.select-container.select-container) { border: 2px solid var(--dark-gray); cursor: pointer; flex: 1; @@ -39,17 +39,18 @@ } .themed :global(.multiSelectItem) { - font-size: 0.875rem; + font-size: 1rem; align-items: center; --multiItemBorderRadius: var(--s-1); - --multiItemHeight: 1.25rem; + /*--multiItemHeight: 1.25rem;*/ --multiItemMargin: 0; --multiItemPadding: 0.2rem 0.3rem; --multiClearBG: transparent; --multiClearFill: var(--secondary); --multiClearHoverBG: transparent; - /* --multiClearHoverFill: var(--white); */ - /* --multiLabelMargin: 1px 5px 0 0; */ + --multiClearHoverFill: var(--white); + --multiClearTop: 0px; + /*--multiLabelMargin: 1px 5px 0 0;*/ } .themed :global(input) { diff --git a/src/lib/schemas.js b/src/lib/schemas.js index 08b18feb9..c79b92d21 100644 --- a/src/lib/schemas.js +++ b/src/lib/schemas.js @@ -25,14 +25,24 @@ const PACKAGES_CATEGORIES = /** @type {const} */ ([ ]); export const packagesSchema = z.array( - z.object({ - title: z.string().max(50), - npm: z.string().regex(packageNameRegex), - url: z.string().url().optional(), - repository: z.string().url(), - description: z.string().max(250), - categories: z.array(z.enum(PACKAGES_CATEGORIES)).min(1).max(6) - }) + z.intersection( + z.object({ + title: z.string().max(50), + url: z.string().url().optional(), + repository: z.string().url(), + description: z.string().max(250), + categories: z.array(z.enum(PACKAGES_CATEGORIES)).min(1).max(6) + }), + z + .object({ + npm: z.string().regex(packageNameRegex) + }) + .or( + z.object({ + gem: z.string().regex(/^[a-z_-]+$/) + }) + ) + ) ); const TEMPLATES_CATEGORIES = /** @type {const} */ ([ diff --git a/src/lib/stores/packageManager.ts b/src/lib/stores/packageManager.ts index adeaecc58..eb5a0a5d3 100644 --- a/src/lib/stores/packageManager.ts +++ b/src/lib/stores/packageManager.ts @@ -2,8 +2,14 @@ import { createLocalStorage, persist } from '@macfja/svelte-persistent-store'; import type { PersistentStore } from '@macfja/svelte-persistent-store'; import { writable } from 'svelte/store'; -export const packageManager: PersistentStore = persist( - writable('npm'), +export const packageManager: PersistentStore> = persist( + writable(['npm', 'gem']), createLocalStorage(), 'packageManager' ); + +packageManager.subscribe((v) => { + if (typeof v === 'string') { + packageManager.set([v, 'gem']); + } +})();