From f2c6d525bc7e2358aa56ca5a38b1befa4e6334ce Mon Sep 17 00:00:00 2001 From: kev1n77 Date: Tue, 15 Sep 2026 00:09:43 +0800 Subject: [PATCH 1/6] refactor(ui): adopt Input in installer and standalone markets --- pnpm-lock.yaml | 6 ++ src/apps/miniapp-market-server/Dockerfile | 4 ++ .../Dockerfile.dockerignore | 3 + src/apps/skin-market-server/Dockerfile | 4 ++ .../Dockerfile.dockerignore | 3 + src/miniapp-market-web/package.json | 3 +- src/miniapp-market-web/src/App.test.tsx | 58 +++++++++++++++++++ src/miniapp-market-web/src/App.tsx | 23 ++++---- src/miniapp-market-web/src/main.tsx | 6 +- src/miniapp-market-web/src/styles.css | 31 +++++++--- src/skin-market-web/package.json | 3 +- src/skin-market-web/src/CatalogPage.tsx | 3 +- src/skin-market-web/src/main.tsx | 6 +- src/skin-market-web/src/styles.css | 15 +++++ 14 files changed, 145 insertions(+), 23 deletions(-) create mode 100644 src/miniapp-market-web/src/App.test.tsx diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8c4ca0fff2..bedb83e385 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -222,6 +222,9 @@ importers: '@openbitfun/theme-openbitfun': specifier: workspace:^ version: link:../../design-system/packages/theme-openbitfun + '@openbitfun/ui': + specifier: workspace:^ + version: link:../../design-system/packages/ui '@phosphor-icons/react': specifier: ^2.1.10 version: 2.1.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -335,6 +338,9 @@ importers: '@openbitfun/theme-openbitfun': specifier: workspace:^ version: link:../../design-system/packages/theme-openbitfun + '@openbitfun/ui': + specifier: workspace:^ + version: link:../../design-system/packages/ui '@phosphor-icons/react': specifier: ^2.1.10 version: 2.1.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1) diff --git a/src/apps/miniapp-market-server/Dockerfile b/src/apps/miniapp-market-server/Dockerfile index a3f7d936bb..22e6625132 100644 --- a/src/apps/miniapp-market-server/Dockerfile +++ b/src/apps/miniapp-market-server/Dockerfile @@ -8,6 +8,8 @@ RUN corepack enable && corepack prepare pnpm@10.15.0 --activate COPY package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc ./ COPY patches/ patches/ COPY design-system/LICENSE design-system/LICENSE +COPY design-system/tsconfig.base.json design-system/tsconfig.base.json +COPY design-system/packages/ui/package.json design-system/packages/ui/package.json COPY design-system/tooling/token-engine/package.json design-system/tooling/token-engine/package.json COPY design-system/packages/design-tokens/package.json design-system/packages/design-tokens/package.json COPY design-system/packages/theme-openbitfun/package.json design-system/packages/theme-openbitfun/package.json @@ -15,12 +17,14 @@ COPY src/miniapp-market-web/package.json src/miniapp-market-web/package.json RUN --mount=type=cache,id=openbitfun-market-pnpm,target=/root/.local/share/pnpm/store,sharing=locked \ pnpm install --frozen-lockfile --ignore-scripts --filter openbitfun-miniapp-market-web... +COPY design-system/packages/ui/ design-system/packages/ui/ COPY design-system/tooling/token-engine/ design-system/tooling/token-engine/ COPY design-system/packages/design-tokens/ design-system/packages/design-tokens/ COPY design-system/packages/theme-openbitfun/ design-system/packages/theme-openbitfun/ COPY src/miniapp-market-web/ src/miniapp-market-web/ RUN pnpm --dir design-system/packages/design-tokens build \ && pnpm --dir design-system/packages/theme-openbitfun build \ + && pnpm --dir design-system/packages/ui build \ && pnpm --dir src/miniapp-market-web build FROM rust:1.96-bookworm AS rust-builder diff --git a/src/apps/miniapp-market-server/Dockerfile.dockerignore b/src/apps/miniapp-market-server/Dockerfile.dockerignore index 9d77f42167..bfe9f881de 100644 --- a/src/apps/miniapp-market-server/Dockerfile.dockerignore +++ b/src/apps/miniapp-market-server/Dockerfile.dockerignore @@ -11,6 +11,9 @@ !design-system/ !design-system/LICENSE +!design-system/tsconfig.base.json +!design-system/packages/ui/ +!design-system/packages/ui/** !design-system/packages/ !design-system/packages/design-tokens/ !design-system/packages/design-tokens/package.json diff --git a/src/apps/skin-market-server/Dockerfile b/src/apps/skin-market-server/Dockerfile index 108a00b790..50f91b23e3 100644 --- a/src/apps/skin-market-server/Dockerfile +++ b/src/apps/skin-market-server/Dockerfile @@ -8,6 +8,8 @@ RUN corepack enable && corepack prepare pnpm@10.15.0 --activate COPY package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc ./ COPY patches/ patches/ COPY design-system/LICENSE design-system/LICENSE +COPY design-system/tsconfig.base.json design-system/tsconfig.base.json +COPY design-system/packages/ui/package.json design-system/packages/ui/package.json COPY design-system/tooling/token-engine/package.json design-system/tooling/token-engine/package.json COPY design-system/packages/design-tokens/package.json design-system/packages/design-tokens/package.json COPY design-system/packages/theme-openbitfun/package.json design-system/packages/theme-openbitfun/package.json @@ -15,6 +17,7 @@ COPY src/skin-market-web/package.json src/skin-market-web/package.json RUN --mount=type=cache,id=openbitfun-skin-market-pnpm,target=/root/.local/share/pnpm/store,sharing=locked \ pnpm install --frozen-lockfile --ignore-scripts --filter openbitfun-skin-market-web... +COPY design-system/packages/ui/ design-system/packages/ui/ COPY design-system/tooling/token-engine/ design-system/tooling/token-engine/ COPY design-system/packages/design-tokens/ design-system/packages/design-tokens/ COPY design-system/packages/theme-openbitfun/ design-system/packages/theme-openbitfun/ @@ -22,6 +25,7 @@ COPY src/skin-market-web/ src/skin-market-web/ COPY src/shared/appearance-market-contract-fixtures/ src/shared/appearance-market-contract-fixtures/ RUN pnpm --dir design-system/packages/design-tokens build \ && pnpm --dir design-system/packages/theme-openbitfun build \ + && pnpm --dir design-system/packages/ui build \ && pnpm --dir src/skin-market-web build FROM rust:1.96-bookworm AS rust-builder diff --git a/src/apps/skin-market-server/Dockerfile.dockerignore b/src/apps/skin-market-server/Dockerfile.dockerignore index 3e642b697d..97b27b0b3b 100644 --- a/src/apps/skin-market-server/Dockerfile.dockerignore +++ b/src/apps/skin-market-server/Dockerfile.dockerignore @@ -11,6 +11,9 @@ !design-system/ !design-system/LICENSE +!design-system/tsconfig.base.json +!design-system/packages/ui/ +!design-system/packages/ui/** !design-system/packages/ !design-system/packages/design-tokens/ !design-system/packages/design-tokens/package.json diff --git a/src/miniapp-market-web/package.json b/src/miniapp-market-web/package.json index 9175dfda20..0a6f2f5972 100644 --- a/src/miniapp-market-web/package.json +++ b/src/miniapp-market-web/package.json @@ -15,7 +15,8 @@ "@phosphor-icons/react": "^2.1.10", "lucide-react": "^0.541.0", "react": "^18.3.1", - "react-dom": "^18.3.1" + "react-dom": "^18.3.1", + "@openbitfun/ui": "workspace:^" }, "devDependencies": { "@types/react": "^18.3.0", diff --git a/src/miniapp-market-web/src/App.test.tsx b/src/miniapp-market-web/src/App.test.tsx new file mode 100644 index 0000000000..43c1bf2569 --- /dev/null +++ b/src/miniapp-market-web/src/App.test.tsx @@ -0,0 +1,58 @@ +// @vitest-environment jsdom +import React, { act } from 'react'; +import { createRoot } from 'react-dom/client'; +import { afterEach, beforeEach, expect, it, vi } from 'vitest'; +import App from './App'; + +const mocks = vi.hoisted(() => ({ config: vi.fn(), me: vi.fn() })); +vi.mock('./api', async (original) => ({ + ...await original(), + marketApi: mocks, +})); + +let container: HTMLDivElement; +let root: ReturnType; +beforeEach(() => { + (globalThis as typeof globalThis & { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true; + vi.stubGlobal('matchMedia', vi.fn(() => ({ matches: false, addEventListener: vi.fn(), removeEventListener: vi.fn() }))); + window.history.replaceState({}, '', '/miniapp/submit?listingId=listing-1&slug=my-app&release=2'); + mocks.config.mockResolvedValue({ webSubmissionsEnabled: true, githubAuthConfigured: true }); + mocks.me.mockResolvedValue({ user: { login: 'publisher', avatarUrl: '' }, isAdmin: false }); + container = document.createElement('div'); + document.body.append(container); + root = createRoot(container); +}); +afterEach(() => { + act(() => root.unmount()); + container.remove(); + vi.unstubAllGlobals(); +}); + +it('preserves native submission fields and update constraints on the actual submit route', async () => { + await act(async () => root.render()); + const form = container.querySelector('form'); + expect(form).not.toBeNull(); + const data = new FormData(form!); + expect(data.get('slug')).toBe('my-app'); + expect(data.get('releaseNumber')).toBe('2'); + expect(data.get('icon')).toBe('✦'); + expect(data.get('licenseValue')).toBe('MIT'); + const slug = form!.elements.namedItem('slug') as HTMLInputElement; + const release = form!.elements.namedItem('releaseNumber') as HTMLInputElement; + expect(slug.readOnly).toBe(true); + expect(slug.pattern).toBe('[a-z0-9][a-z0-9-]{2,62}'); + expect(release.readOnly).toBe(true); + expect(release.min).toBe('1'); + expect(slug.closest('[data-openbitfun-component="input"]')).not.toBeNull(); + expect(form!.querySelectorAll('input[type="file"]')).toHaveLength(2); + expect((form!.elements.namedItem('screenshots') as HTMLInputElement).multiple).toBe(true); + expect(form!.querySelector('.submit-button')!.type).toBe('submit'); + expect(form!.checkValidity()).toBe(false); +}); + +it('keeps web submissions unavailable when the server disables them', async () => { + mocks.config.mockResolvedValue({ webSubmissionsEnabled: false }); + await act(async () => root.render()); + expect(container.querySelector('form')).toBeNull(); + expect(container.querySelector('input[type="file"]')).toBeNull(); +}); diff --git a/src/miniapp-market-web/src/App.tsx b/src/miniapp-market-web/src/App.tsx index 84ebd40400..b135e204a1 100644 --- a/src/miniapp-market-web/src/App.tsx +++ b/src/miniapp-market-web/src/App.tsx @@ -1,3 +1,4 @@ +import { Input } from '@openbitfun/ui'; import { FormEvent, useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { CubeFocus as MarketLogo, GithubLogo, IconContext } from '@phosphor-icons/react'; import { @@ -516,7 +517,7 @@ function CatalogPage({