github-issue-tower-defence-management 1.86.0 → 1.88.0

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.
Files changed (64) hide show
  1. package/.eslintrc.cjs +5 -1
  2. package/.github/workflows/console-ui.yml +47 -0
  3. package/.prettierignore +3 -0
  4. package/CHANGELOG.md +15 -0
  5. package/README.md +42 -0
  6. package/bin/adapter/entry-points/console/ui-dist/assets/index-DFxrSRH4.css +1 -0
  7. package/bin/adapter/entry-points/console/ui-dist/assets/index-DcOZ02ON.js +49 -0
  8. package/bin/adapter/entry-points/console/ui-dist/index.html +13 -0
  9. package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js +54 -12
  10. package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js.map +1 -1
  11. package/bin/adapter/entry-points/handlers/inTmuxByHumanDataWriter.js +67 -0
  12. package/bin/adapter/entry-points/handlers/inTmuxByHumanDataWriter.js.map +1 -0
  13. package/bin/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.js +306 -0
  14. package/bin/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.js.map +1 -1
  15. package/bin/domain/usecases/intmux/GenerateInTmuxByHumanDataUseCase.js +91 -0
  16. package/bin/domain/usecases/intmux/GenerateInTmuxByHumanDataUseCase.js.map +1 -0
  17. package/package.json +22 -2
  18. package/scripts/copyConsoleUiDist.mjs +35 -0
  19. package/src/adapter/entry-points/console/ui/.storybook/main.ts +12 -0
  20. package/src/adapter/entry-points/console/ui/.storybook/preview.ts +15 -0
  21. package/src/adapter/entry-points/console/ui/biome.json +47 -0
  22. package/src/adapter/entry-points/console/ui/components.json +20 -0
  23. package/src/adapter/entry-points/console/ui/index.html +12 -0
  24. package/src/adapter/entry-points/console/ui/src/components/ui/badge.stories.tsx +35 -0
  25. package/src/adapter/entry-points/console/ui/src/components/ui/badge.tsx +28 -0
  26. package/src/adapter/entry-points/console/ui/src/components/ui/button.stories.tsx +34 -0
  27. package/src/adapter/entry-points/console/ui/src/components/ui/button.tsx +50 -0
  28. package/src/adapter/entry-points/console/ui/src/features/console/components/ConsoleListView.stories.tsx +44 -0
  29. package/src/adapter/entry-points/console/ui/src/features/console/components/ConsoleListView.tsx +58 -0
  30. package/src/adapter/entry-points/console/ui/src/features/console/components/ConsoleTabBar.stories.tsx +34 -0
  31. package/src/adapter/entry-points/console/ui/src/features/console/components/ConsoleTabBar.tsx +32 -0
  32. package/src/adapter/entry-points/console/ui/src/features/console/fixtures.ts +47 -0
  33. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleList.ts +65 -0
  34. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleToken.ts +64 -0
  35. package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsolePage.tsx +19 -0
  36. package/src/adapter/entry-points/console/ui/src/features/console/types.ts +69 -0
  37. package/src/adapter/entry-points/console/ui/src/index.css +31 -0
  38. package/src/adapter/entry-points/console/ui/src/lib/utils.ts +4 -0
  39. package/src/adapter/entry-points/console/ui/src/main.tsx +15 -0
  40. package/src/adapter/entry-points/console/ui/src/vite-env.d.ts +1 -0
  41. package/src/adapter/entry-points/console/ui/tsconfig.json +24 -0
  42. package/src/adapter/entry-points/console/ui/vite.config.ts +19 -0
  43. package/src/adapter/entry-points/console/ui-dist/assets/index-DFxrSRH4.css +1 -0
  44. package/src/adapter/entry-points/console/ui-dist/assets/index-DcOZ02ON.js +49 -0
  45. package/src/adapter/entry-points/console/ui-dist/index.html +13 -0
  46. package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts +26 -0
  47. package/src/adapter/entry-points/handlers/inTmuxByHumanDataWriter.test.ts +266 -0
  48. package/src/adapter/entry-points/handlers/inTmuxByHumanDataWriter.ts +103 -0
  49. package/src/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.test.ts +630 -0
  50. package/src/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.ts +492 -0
  51. package/src/domain/usecases/adapter-interfaces/IssueRepository.ts +51 -0
  52. package/src/domain/usecases/intmux/GenerateInTmuxByHumanDataUseCase.test.ts +285 -0
  53. package/src/domain/usecases/intmux/GenerateInTmuxByHumanDataUseCase.ts +182 -0
  54. package/tsconfig.build.json +7 -1
  55. package/tsconfig.json +6 -1
  56. package/types/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.d.ts.map +1 -1
  57. package/types/adapter/entry-points/handlers/inTmuxByHumanDataWriter.d.ts +16 -0
  58. package/types/adapter/entry-points/handlers/inTmuxByHumanDataWriter.d.ts.map +1 -0
  59. package/types/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.d.ts +18 -1
  60. package/types/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.d.ts.map +1 -1
  61. package/types/domain/usecases/adapter-interfaces/IssueRepository.d.ts +47 -0
  62. package/types/domain/usecases/adapter-interfaces/IssueRepository.d.ts.map +1 -1
  63. package/types/domain/usecases/intmux/GenerateInTmuxByHumanDataUseCase.d.ts +57 -0
  64. package/types/domain/usecases/intmux/GenerateInTmuxByHumanDataUseCase.d.ts.map +1 -0
@@ -0,0 +1,58 @@
1
+ import { Badge } from '@/components/ui/badge';
2
+ import type { ConsoleListItem } from '../types';
3
+
4
+ export type ConsoleListViewProps = {
5
+ items: ConsoleListItem[];
6
+ isLoading: boolean;
7
+ error: string | null;
8
+ };
9
+
10
+ export const ConsoleListView = ({
11
+ items,
12
+ isLoading,
13
+ error,
14
+ }: ConsoleListViewProps) => {
15
+ if (error !== null) {
16
+ return (
17
+ <p role="alert" className="p-4 text-sm text-destructive">
18
+ Failed to load list: {error}
19
+ </p>
20
+ );
21
+ }
22
+
23
+ if (isLoading) {
24
+ return <p className="p-4 text-sm text-muted-foreground">Loading list...</p>;
25
+ }
26
+
27
+ if (items.length === 0) {
28
+ return <p className="p-4 text-sm text-muted-foreground">No items.</p>;
29
+ }
30
+
31
+ return (
32
+ <ul className="divide-y divide-border">
33
+ {items.map((item) => (
34
+ <li key={item.itemId} className="flex flex-col gap-1 p-3">
35
+ <div className="flex items-center gap-2">
36
+ <Badge variant={item.isPr ? 'default' : 'secondary'}>
37
+ {item.isPr ? 'PR' : 'Issue'}
38
+ </Badge>
39
+ <a
40
+ href={item.url}
41
+ className="font-medium underline-offset-2 hover:underline"
42
+ >
43
+ {item.title}
44
+ </a>
45
+ <span className="text-sm text-muted-foreground">
46
+ #{item.number}
47
+ </span>
48
+ </div>
49
+ <div className="flex flex-wrap items-center gap-2 text-xs text-muted-foreground">
50
+ <span>{item.repo}</span>
51
+ {item.story !== '' && <span>story: {item.story}</span>}
52
+ <span>{new Date(item.createdAt).toISOString()}</span>
53
+ </div>
54
+ </li>
55
+ ))}
56
+ </ul>
57
+ );
58
+ };
@@ -0,0 +1,34 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { useState } from 'react';
3
+ import type { ConsoleTabName } from '../types';
4
+ import { ConsoleTabBar } from './ConsoleTabBar';
5
+
6
+ const meta: Meta<typeof ConsoleTabBar> = {
7
+ title: 'Console/ConsoleTabBar',
8
+ component: ConsoleTabBar,
9
+ };
10
+
11
+ export default meta;
12
+
13
+ type Story = StoryObj<typeof ConsoleTabBar>;
14
+
15
+ export const PrsActive: Story = {
16
+ args: {
17
+ activeTab: 'prs',
18
+ onSelectTab: () => undefined,
19
+ },
20
+ };
21
+
22
+ export const TriageActive: Story = {
23
+ args: {
24
+ activeTab: 'triage',
25
+ onSelectTab: () => undefined,
26
+ },
27
+ };
28
+
29
+ export const Interactive: Story = {
30
+ render: () => {
31
+ const [activeTab, setActiveTab] = useState<ConsoleTabName>('prs');
32
+ return <ConsoleTabBar activeTab={activeTab} onSelectTab={setActiveTab} />;
33
+ },
34
+ };
@@ -0,0 +1,32 @@
1
+ import { Button } from '@/components/ui/button';
2
+ import { cn } from '@/lib/utils';
3
+ import { CONSOLE_TABS, type ConsoleTabName } from '../types';
4
+
5
+ export type ConsoleTabBarProps = {
6
+ activeTab: ConsoleTabName;
7
+ onSelectTab: (tab: ConsoleTabName) => void;
8
+ };
9
+
10
+ export const ConsoleTabBar = ({
11
+ activeTab,
12
+ onSelectTab,
13
+ }: ConsoleTabBarProps) => (
14
+ <nav
15
+ aria-label="Console tabs"
16
+ className="flex flex-wrap gap-1 border-b border-border p-2"
17
+ >
18
+ {CONSOLE_TABS.map((tab) => (
19
+ <Button
20
+ key={tab.name}
21
+ type="button"
22
+ size="sm"
23
+ variant={tab.name === activeTab ? 'default' : 'ghost'}
24
+ aria-current={tab.name === activeTab ? 'page' : undefined}
25
+ className={cn(tab.name === activeTab && 'font-semibold')}
26
+ onClick={() => onSelectTab(tab.name)}
27
+ >
28
+ {tab.label}
29
+ </Button>
30
+ ))}
31
+ </nav>
32
+ );
@@ -0,0 +1,47 @@
1
+ import type { ConsoleListItem } from './types';
2
+
3
+ export const consoleListItemsFixture: ConsoleListItem[] = [
4
+ {
5
+ number: 844,
6
+ title: 'Add serveConsole server skeleton under entry-points',
7
+ url: 'https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/pull/851',
8
+ repo: 'HiromiShikata/npm-cli-github-issue-tower-defence-management',
9
+ nameWithOwner:
10
+ 'HiromiShikata/npm-cli-github-issue-tower-defence-management',
11
+ projectItemId: 'PVTI_lADOABCD1234zgABCD01',
12
+ itemId: 'PVTI_lADOABCD1234zgABCD01',
13
+ isPr: true,
14
+ story: 'TDPM Console port',
15
+ labels: ['claude'],
16
+ createdAt: '2026-06-17T02:14:33.000Z',
17
+ },
18
+ {
19
+ number: 845,
20
+ title:
21
+ 'Scaffold React console UI under entry-points with build bundling and minimal tab view',
22
+ url: 'https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/issues/845',
23
+ repo: 'HiromiShikata/npm-cli-github-issue-tower-defence-management',
24
+ nameWithOwner:
25
+ 'HiromiShikata/npm-cli-github-issue-tower-defence-management',
26
+ projectItemId: 'PVTI_lADOABCD1234zgABCD02',
27
+ itemId: 'PVTI_lADOABCD1234zgABCD02',
28
+ isPr: false,
29
+ story: 'TDPM Console port',
30
+ labels: ['claude'],
31
+ createdAt: '2026-06-17T05:48:09.000Z',
32
+ },
33
+ {
34
+ number: 778,
35
+ title: 'Add Sonnet to Opus weekly-limit fallback routing per token',
36
+ url: 'https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/issues/778',
37
+ repo: 'HiromiShikata/npm-cli-github-issue-tower-defence-management',
38
+ nameWithOwner:
39
+ 'HiromiShikata/npm-cli-github-issue-tower-defence-management',
40
+ projectItemId: 'PVTI_lADOABCD1234zgABCD03',
41
+ itemId: 'PVTI_lADOABCD1234zgABCD03',
42
+ isPr: false,
43
+ story: 'regular / workflow improvement',
44
+ labels: [],
45
+ createdAt: '2026-06-12T23:01:55.000Z',
46
+ },
47
+ ];
@@ -0,0 +1,65 @@
1
+ import { useEffect, useState } from 'react';
2
+ import type { ConsoleListItem, ConsoleTabName } from '../types';
3
+ import { useConsoleToken } from './useConsoleToken';
4
+
5
+ const buildListUrl = (tab: ConsoleTabName): string => `./${tab}/list.json`;
6
+
7
+ const extractItems = (payload: unknown): ConsoleListItem[] => {
8
+ if (
9
+ payload !== null &&
10
+ typeof payload === 'object' &&
11
+ 'items' in payload &&
12
+ Array.isArray((payload as { items: unknown }).items)
13
+ ) {
14
+ return (payload as { items: ConsoleListItem[] }).items;
15
+ }
16
+ return [];
17
+ };
18
+
19
+ export type ConsoleListState = {
20
+ items: ConsoleListItem[];
21
+ isLoading: boolean;
22
+ error: string | null;
23
+ };
24
+
25
+ export const useConsoleList = (tab: ConsoleTabName): ConsoleListState => {
26
+ const { appendToken } = useConsoleToken();
27
+ const [items, setItems] = useState<ConsoleListItem[]>([]);
28
+ const [isLoading, setIsLoading] = useState<boolean>(true);
29
+ const [error, setError] = useState<string | null>(null);
30
+
31
+ useEffect(() => {
32
+ let cancelled = false;
33
+ setIsLoading(true);
34
+ setError(null);
35
+
36
+ const url = appendToken(buildListUrl(tab));
37
+ fetch(url)
38
+ .then(async (response) => {
39
+ if (!response.ok) {
40
+ throw new Error(`HTTP ${response.status}`);
41
+ }
42
+ return response.json();
43
+ })
44
+ .then((payload: unknown) => {
45
+ if (cancelled) {
46
+ return;
47
+ }
48
+ setItems(extractItems(payload));
49
+ setIsLoading(false);
50
+ })
51
+ .catch((cause: unknown) => {
52
+ if (cancelled) {
53
+ return;
54
+ }
55
+ setError(cause instanceof Error ? cause.message : String(cause));
56
+ setIsLoading(false);
57
+ });
58
+
59
+ return () => {
60
+ cancelled = true;
61
+ };
62
+ }, [tab, appendToken]);
63
+
64
+ return { items, isLoading, error };
65
+ };
@@ -0,0 +1,64 @@
1
+ import { useCallback, useEffect, useState } from 'react';
2
+
3
+ const CONSOLE_TOKEN_STORAGE_KEY = 'tdpm-console-token';
4
+
5
+ const readTokenFromLocation = (search: string): string | null => {
6
+ const params = new URLSearchParams(search);
7
+ const tokenFromQuery = params.get('k');
8
+ if (tokenFromQuery !== null && tokenFromQuery !== '') {
9
+ return tokenFromQuery;
10
+ }
11
+ return null;
12
+ };
13
+
14
+ const readPersistedToken = (): string | null => {
15
+ if (typeof localStorage === 'undefined') {
16
+ return null;
17
+ }
18
+ const persisted = localStorage.getItem(CONSOLE_TOKEN_STORAGE_KEY);
19
+ return persisted !== null && persisted !== '' ? persisted : null;
20
+ };
21
+
22
+ export type ConsoleTokenState = {
23
+ token: string | null;
24
+ appendToken: (dataUrl: string) => string;
25
+ };
26
+
27
+ export const useConsoleToken = (): ConsoleTokenState => {
28
+ const [token, setToken] = useState<string | null>(() => {
29
+ const search = typeof window === 'undefined' ? '' : window.location.search;
30
+ return readTokenFromLocation(search) ?? readPersistedToken();
31
+ });
32
+
33
+ useEffect(() => {
34
+ if (token === null) {
35
+ return;
36
+ }
37
+ if (typeof localStorage !== 'undefined') {
38
+ localStorage.setItem(CONSOLE_TOKEN_STORAGE_KEY, token);
39
+ }
40
+ }, [token]);
41
+
42
+ useEffect(() => {
43
+ if (typeof window === 'undefined') {
44
+ return;
45
+ }
46
+ const tokenFromQuery = readTokenFromLocation(window.location.search);
47
+ if (tokenFromQuery !== null) {
48
+ setToken(tokenFromQuery);
49
+ }
50
+ }, []);
51
+
52
+ const appendToken = useCallback(
53
+ (dataUrl: string): string => {
54
+ if (token === null) {
55
+ return dataUrl;
56
+ }
57
+ const separator = dataUrl.includes('?') ? '&' : '?';
58
+ return `${dataUrl}${separator}k=${encodeURIComponent(token)}`;
59
+ },
60
+ [token],
61
+ );
62
+
63
+ return { token, appendToken };
64
+ };
@@ -0,0 +1,19 @@
1
+ import { useState } from 'react';
2
+ import { ConsoleListView } from '../components/ConsoleListView';
3
+ import { ConsoleTabBar } from '../components/ConsoleTabBar';
4
+ import { useConsoleList } from '../hooks/useConsoleList';
5
+ import { CONSOLE_TABS, type ConsoleTabName } from '../types';
6
+
7
+ export const ConsolePage = () => {
8
+ const [activeTab, setActiveTab] = useState<ConsoleTabName>(
9
+ CONSOLE_TABS[0].name,
10
+ );
11
+ const { items, isLoading, error } = useConsoleList(activeTab);
12
+
13
+ return (
14
+ <main className="mx-auto flex max-w-3xl flex-col">
15
+ <ConsoleTabBar activeTab={activeTab} onSelectTab={setActiveTab} />
16
+ <ConsoleListView items={items} isLoading={isLoading} error={error} />
17
+ </main>
18
+ );
19
+ };
@@ -0,0 +1,69 @@
1
+ export type ConsoleColor =
2
+ | 'GRAY'
3
+ | 'BLUE'
4
+ | 'GREEN'
5
+ | 'YELLOW'
6
+ | 'ORANGE'
7
+ | 'RED'
8
+ | 'PINK'
9
+ | 'PURPLE';
10
+
11
+ export type ConsoleListItem = {
12
+ number: number;
13
+ title: string;
14
+ url: string;
15
+ repo: string;
16
+ nameWithOwner: string;
17
+ projectItemId: string;
18
+ itemId: string;
19
+ isPr: boolean;
20
+ story: string;
21
+ labels: string[];
22
+ createdAt: string;
23
+ };
24
+
25
+ export type ConsoleFieldOption = {
26
+ id: string;
27
+ name: string;
28
+ color: ConsoleColor;
29
+ };
30
+
31
+ export type ConsoleStatusTab = {
32
+ pjcode: string;
33
+ generatedAt: string;
34
+ statusOptions: ConsoleFieldOption[];
35
+ storyOrder: string[];
36
+ storyColors: Record<string, { color: ConsoleColor }>;
37
+ items: ConsoleListItem[];
38
+ };
39
+
40
+ export type ConsoleTriageTab = {
41
+ pjcode: string;
42
+ generatedAt: string;
43
+ storyOptions: ConsoleFieldOption[];
44
+ storyOrder: string[];
45
+ storyColors: Record<string, ConsoleColor>;
46
+ items: ConsoleListItem[];
47
+ };
48
+
49
+ export type ConsoleTabData = ConsoleStatusTab | ConsoleTriageTab;
50
+
51
+ export type ConsoleTabName =
52
+ | 'prs'
53
+ | 'triage'
54
+ | 'unread'
55
+ | 'failed-preparation'
56
+ | 'todo-by-human';
57
+
58
+ export type ConsoleTab = {
59
+ name: ConsoleTabName;
60
+ label: string;
61
+ };
62
+
63
+ export const CONSOLE_TABS: ConsoleTab[] = [
64
+ { name: 'prs', label: 'Awaiting Quality Check' },
65
+ { name: 'triage', label: 'Triage' },
66
+ { name: 'unread', label: 'Unread' },
67
+ { name: 'failed-preparation', label: 'Failed Preparation' },
68
+ { name: 'todo-by-human', label: 'Todo By Human' },
69
+ ];
@@ -0,0 +1,31 @@
1
+ @import "tailwindcss";
2
+
3
+ @theme {
4
+ --color-border: hsl(0 0% 89.8%);
5
+ --color-input: hsl(0 0% 89.8%);
6
+ --color-ring: hsl(0 0% 3.9%);
7
+ --color-background: hsl(0 0% 100%);
8
+ --color-foreground: hsl(0 0% 3.9%);
9
+ --color-primary: hsl(0 0% 9%);
10
+ --color-primary-foreground: hsl(0 0% 98%);
11
+ --color-secondary: hsl(0 0% 96.1%);
12
+ --color-secondary-foreground: hsl(0 0% 9%);
13
+ --color-muted: hsl(0 0% 96.1%);
14
+ --color-muted-foreground: hsl(0 0% 45.1%);
15
+ --color-accent: hsl(0 0% 96.1%);
16
+ --color-accent-foreground: hsl(0 0% 9%);
17
+ --color-destructive: hsl(0 84.2% 60.2%);
18
+ --color-destructive-foreground: hsl(0 0% 98%);
19
+ --color-card: hsl(0 0% 100%);
20
+ --color-card-foreground: hsl(0 0% 3.9%);
21
+ --radius: 0.5rem;
22
+ }
23
+
24
+ body {
25
+ margin: 0;
26
+ background-color: var(--color-background);
27
+ color: var(--color-foreground);
28
+ font-family:
29
+ ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
30
+ Roboto, Helvetica, Arial, sans-serif;
31
+ }
@@ -0,0 +1,4 @@
1
+ import { type ClassValue, clsx } from 'clsx';
2
+ import { twMerge } from 'tailwind-merge';
3
+
4
+ export const cn = (...inputs: ClassValue[]): string => twMerge(clsx(inputs));
@@ -0,0 +1,15 @@
1
+ import { StrictMode } from 'react';
2
+ import { createRoot } from 'react-dom/client';
3
+ import { ConsolePage } from '@/features/console/pages/ConsolePage';
4
+ import './index.css';
5
+
6
+ const container = document.getElementById('root');
7
+ if (container === null) {
8
+ throw new Error('Root container #root not found');
9
+ }
10
+
11
+ createRoot(container).render(
12
+ <StrictMode>
13
+ <ConsolePage />
14
+ </StrictMode>,
15
+ );
@@ -0,0 +1 @@
1
+ /// <reference types="vite/client" />
@@ -0,0 +1,24 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "useDefineForClassFields": true,
5
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
6
+ "module": "ESNext",
7
+ "skipLibCheck": true,
8
+ "moduleResolution": "Bundler",
9
+ "allowImportingTsExtensions": true,
10
+ "verbatimModuleSyntax": true,
11
+ "moduleDetection": "force",
12
+ "noEmit": true,
13
+ "jsx": "react-jsx",
14
+ "strict": true,
15
+ "noUnusedLocals": true,
16
+ "noUnusedParameters": true,
17
+ "noFallthroughCasesInSwitch": true,
18
+ "noUncheckedSideEffectImports": true,
19
+ "paths": {
20
+ "@/*": ["./src/*"]
21
+ }
22
+ },
23
+ "include": ["src", ".storybook"]
24
+ }
@@ -0,0 +1,19 @@
1
+ import path from 'node:path';
2
+ import tailwindcss from '@tailwindcss/vite';
3
+ import react from '@vitejs/plugin-react';
4
+ import { defineConfig } from 'vite';
5
+
6
+ export default defineConfig({
7
+ root: path.resolve(__dirname),
8
+ base: './',
9
+ plugins: [react(), tailwindcss()],
10
+ resolve: {
11
+ alias: {
12
+ '@': path.resolve(__dirname, 'src'),
13
+ },
14
+ },
15
+ build: {
16
+ outDir: path.resolve(__dirname, '../ui-dist'),
17
+ emptyOutDir: true,
18
+ },
19
+ });
@@ -0,0 +1 @@
1
+ /*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-divide-y-reverse:0;--tw-border-style:solid;--tw-font-weight:initial;--tw-outline-style:solid;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--spacing:.25rem;--container-3xl:48rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--font-weight-medium:500;--font-weight-semibold:600;--radius-md:.375rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-border:#e5e5e5;--color-input:#e5e5e5;--color-ring:#0a0a0a;--color-background:#fff;--color-foreground:#0a0a0a;--color-primary:#171717;--color-primary-foreground:#fafafa;--color-secondary:#f5f5f5;--color-secondary-foreground:#171717;--color-muted-foreground:#737373;--color-accent:#f5f5f5;--color-accent-foreground:#171717;--color-destructive:#ef4444}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.container{width:100%}@media(min-width:40rem){.container{max-width:40rem}}@media(min-width:48rem){.container{max-width:48rem}}@media(min-width:64rem){.container{max-width:64rem}}@media(min-width:80rem){.container{max-width:80rem}}@media(min-width:96rem){.container{max-width:96rem}}.mx-auto{margin-inline:auto}.flex{display:flex}.inline-flex{display:inline-flex}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-10{height:calc(var(--spacing) * 10)}.max-w-3xl{max-width:var(--container-3xl)}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-center{justify-content:center}.gap-1{gap:calc(var(--spacing) * 1)}.gap-2{gap:calc(var(--spacing) * 2)}:where(.divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px * var(--tw-divide-y-reverse));border-bottom-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)))}:where(.divide-border>:not(:last-child)){border-color:var(--color-border)}.rounded-md{border-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-border{border-color:var(--color-border)}.border-input{border-color:var(--color-input)}.border-transparent{border-color:#0000}.bg-background{background-color:var(--color-background)}.bg-primary{background-color:var(--color-primary)}.bg-secondary{background-color:var(--color-secondary)}.p-2{padding:calc(var(--spacing) * 2)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-8{padding-inline:calc(var(--spacing) * 8)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-2{padding-block:calc(var(--spacing) * 2)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.whitespace-nowrap{white-space:nowrap}.text-destructive{color:var(--color-destructive)}.text-foreground{color:var(--color-foreground)}.text-muted-foreground{color:var(--color-muted-foreground)}.text-primary-foreground{color:var(--color-primary-foreground)}.text-secondary-foreground{color:var(--color-secondary-foreground)}.underline-offset-2{text-underline-offset:2px}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}@media(hover:hover){.hover\:bg-accent:hover{background-color:var(--color-accent)}.hover\:bg-primary\/90:hover{background-color:#171717e6}@supports (color:color-mix(in lab,red,red)){.hover\:bg-primary\/90:hover{background-color:color-mix(in oklab,var(--color-primary) 90%,transparent)}}.hover\:bg-secondary\/80:hover{background-color:#f5f5f5cc}@supports (color:color-mix(in lab,red,red)){.hover\:bg-secondary\/80:hover{background-color:color-mix(in oklab,var(--color-secondary) 80%,transparent)}}.hover\:text-accent-foreground:hover{color:var(--color-accent-foreground)}.hover\:underline:hover{text-decoration-line:underline}}.focus-visible\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\:ring-ring:focus-visible{--tw-ring-color:var(--color-ring)}.focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:opacity-50:disabled{opacity:.5}}body{background-color:var(--color-background);color:var(--color-foreground);margin:0;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif}@property --tw-divide-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}