@aphrody/koharu-ui 0.0.0-stage → 0.1.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 (123) hide show
  1. package/README.md +37 -2
  2. package/package.json +70 -4
  3. package/src/assets/NotoSansCJK-VF.otf +0 -0
  4. package/src/assets/OFL.txt +92 -0
  5. package/src/components/ClientOnly.tsx +21 -0
  6. package/src/components/ShenronExportPanel.tsx +213 -0
  7. package/src/components/app/AboutDialog.tsx +64 -0
  8. package/src/components/app/KoharuApp.tsx +58 -0
  9. package/src/components/app/StartupView.tsx +67 -0
  10. package/src/components/app/TitleBar.tsx +322 -0
  11. package/src/components/app/Updater.tsx +143 -0
  12. package/src/components/app/WindowChrome.tsx +137 -0
  13. package/src/components/controls/ColorSampling.tsx +70 -0
  14. package/src/components/controls/ColorWell.tsx +139 -0
  15. package/src/components/controls/CommitTextarea.tsx +63 -0
  16. package/src/components/controls/FontPicker.tsx +543 -0
  17. package/src/components/controls/ModelPicker.tsx +178 -0
  18. package/src/components/controls/OutputPicker.tsx +170 -0
  19. package/src/components/editor/ActivityCenter.tsx +234 -0
  20. package/src/components/editor/AgentPanel.tsx +352 -0
  21. package/src/components/editor/CanvasCommandBar.tsx +38 -0
  22. package/src/components/editor/CanvasOverlay.tsx +194 -0
  23. package/src/components/editor/CanvasWorkspace.tsx +947 -0
  24. package/src/components/editor/Editor.tsx +56 -0
  25. package/src/components/editor/InferenceControl.tsx +457 -0
  26. package/src/components/editor/Inspector.tsx +1073 -0
  27. package/src/components/editor/PageRail.tsx +581 -0
  28. package/src/components/editor/ResourceMonitor.tsx +151 -0
  29. package/src/components/editor/RightSidebar.tsx +50 -0
  30. package/src/components/editor/SelectionControls.tsx +184 -0
  31. package/src/components/editor/StatusBar.tsx +41 -0
  32. package/src/components/editor/ToolBar.tsx +182 -0
  33. package/src/components/editor/useCanvas.ts +194 -0
  34. package/src/components/preferences/GenerationPreferences.tsx +118 -0
  35. package/src/components/preferences/KoharuSettings.tsx +229 -0
  36. package/src/components/preferences/PipelinePreferences.tsx +173 -0
  37. package/src/components/preferences/PreferenceFields.tsx +149 -0
  38. package/src/components/preferences/ProviderPreferences.tsx +173 -0
  39. package/src/components/preferences/SettingsPage.tsx +336 -0
  40. package/src/components/preferences/TranslationPreferences.tsx +187 -0
  41. package/src/components/preferences/TypesettingPreferences.tsx +142 -0
  42. package/src/components/preferences/models.ts +103 -0
  43. package/src/components/start/StartView.tsx +277 -0
  44. package/src/index.ts +59 -0
  45. package/src/internal/components/accordion.tsx +72 -0
  46. package/src/internal/components/alert-dialog.tsx +189 -0
  47. package/src/internal/components/alert.tsx +76 -0
  48. package/src/internal/components/aspect-ratio.tsx +22 -0
  49. package/src/internal/components/attachment.tsx +207 -0
  50. package/src/internal/components/avatar.tsx +109 -0
  51. package/src/internal/components/badge.tsx +52 -0
  52. package/src/internal/components/breadcrumb.tsx +125 -0
  53. package/src/internal/components/bubble.tsx +128 -0
  54. package/src/internal/components/button-group.tsx +87 -0
  55. package/src/internal/components/button.tsx +58 -0
  56. package/src/internal/components/card.tsx +103 -0
  57. package/src/internal/components/checkbox.tsx +29 -0
  58. package/src/internal/components/collapsible.tsx +21 -0
  59. package/src/internal/components/combobox.tsx +298 -0
  60. package/src/internal/components/context-menu.tsx +272 -0
  61. package/src/internal/components/dialog.tsx +162 -0
  62. package/src/internal/components/direction.tsx +6 -0
  63. package/src/internal/components/drawer.tsx +230 -0
  64. package/src/internal/components/dropdown-menu.tsx +278 -0
  65. package/src/internal/components/empty.tsx +104 -0
  66. package/src/internal/components/field.tsx +238 -0
  67. package/src/internal/components/hover-card.tsx +52 -0
  68. package/src/internal/components/input-group.tsx +158 -0
  69. package/src/internal/components/input.tsx +20 -0
  70. package/src/internal/components/item.tsx +201 -0
  71. package/src/internal/components/kbd.tsx +26 -0
  72. package/src/internal/components/label.tsx +20 -0
  73. package/src/internal/components/marker.tsx +71 -0
  74. package/src/internal/components/menubar.tsx +280 -0
  75. package/src/internal/components/message.tsx +92 -0
  76. package/src/internal/components/native-select.tsx +61 -0
  77. package/src/internal/components/navigation-menu.tsx +168 -0
  78. package/src/internal/components/number-field.tsx +68 -0
  79. package/src/internal/components/pagination.tsx +130 -0
  80. package/src/internal/components/popover.tsx +91 -0
  81. package/src/internal/components/progress.tsx +83 -0
  82. package/src/internal/components/radio-group.tsx +38 -0
  83. package/src/internal/components/resizable.tsx +50 -0
  84. package/src/internal/components/scroll-area.tsx +88 -0
  85. package/src/internal/components/select.tsx +191 -0
  86. package/src/internal/components/separator.tsx +25 -0
  87. package/src/internal/components/sheet.tsx +140 -0
  88. package/src/internal/components/sidebar.tsx +723 -0
  89. package/src/internal/components/skeleton.tsx +13 -0
  90. package/src/internal/components/slider.tsx +56 -0
  91. package/src/internal/components/spinner.tsx +10 -0
  92. package/src/internal/components/switch.tsx +32 -0
  93. package/src/internal/components/table.tsx +116 -0
  94. package/src/internal/components/tabs.tsx +82 -0
  95. package/src/internal/components/textarea.tsx +18 -0
  96. package/src/internal/components/toast.tsx +235 -0
  97. package/src/internal/components/toggle-group.tsx +89 -0
  98. package/src/internal/components/toggle.tsx +45 -0
  99. package/src/internal/components/tooltip.tsx +67 -0
  100. package/src/internal/hooks/use-mobile.ts +19 -0
  101. package/src/internal/lib/utils.ts +6 -0
  102. package/src/internal/styles/globals.css +73 -0
  103. package/src/lib/backend.ts +85 -0
  104. package/src/lib/document.ts +46 -0
  105. package/src/lib/geometry.ts +272 -0
  106. package/src/lib/i18n.ts +54 -0
  107. package/src/lib/queries.ts +110 -0
  108. package/src/lib/store.ts +191 -0
  109. package/src/lib/translation.ts +35 -0
  110. package/src/locales/en-US/translation.json +536 -0
  111. package/src/locales/es-ES/translation.json +536 -0
  112. package/src/locales/ja-JP/translation.json +536 -0
  113. package/src/locales/ko-KR/translation.json +536 -0
  114. package/src/locales/pt-BR/translation.json +536 -0
  115. package/src/locales/ru-RU/translation.json +536 -0
  116. package/src/locales/tr-TR/translation.json +536 -0
  117. package/src/locales/zh-CN/translation.json +536 -0
  118. package/src/locales/zh-TW/translation.json +536 -0
  119. package/src/navigation.ts +28 -0
  120. package/src/providers.tsx +132 -0
  121. package/src/shenron-pipeline-env.d.ts +14 -0
  122. package/src/styles.css +246 -0
  123. package/tsconfig.json +21 -0
@@ -0,0 +1,132 @@
1
+ 'use client'
2
+
3
+ import { QueryClientProvider } from '@tanstack/react-query'
4
+ import { Channel } from '@aphrody/api/core'
5
+ import { useEffect, useRef, type ReactNode } from 'react'
6
+ import { I18nextProvider } from 'react-i18next'
7
+
8
+ import { StartupView } from '@aphrody/koharu-ui/components/app/StartupView'
9
+ import ClientOnly from '@aphrody/koharu-ui/components/ClientOnly'
10
+ import { refreshTranslationModels } from '@aphrody/koharu-ui/lib/backend'
11
+ import i18n from '@aphrody/koharu-ui/lib/i18n'
12
+ import { pageKey, pagesKey, projectKey, queryClient, refresh } from '@aphrody/koharu-ui/lib/queries'
13
+ import {
14
+ receiveCanvas,
15
+ receiveDownload,
16
+ receiveStartupState,
17
+ receiveJob,
18
+ receiveResources,
19
+ useKoharuStore,
20
+ } from '@aphrody/koharu-ui/lib/store'
21
+ import {
22
+ commands,
23
+ type CanvasState,
24
+ type Download,
25
+ type Job,
26
+ type ModelResources,
27
+ type ProjectInfo,
28
+ } from '@aphrody/koharu-bridge/protocol'
29
+ import { Toaster } from '@aphrody/m3-primitives'
30
+ import { TooltipProvider } from '@aphrody/m3-primitives'
31
+
32
+ export function Providers({ children }: { children: ReactNode }) {
33
+ const runtime = useRef({ active: false, bound: false })
34
+
35
+ useEffect(() => {
36
+ const lifecycle = runtime.current
37
+ lifecycle.active = true
38
+ if (!lifecycle.bound) {
39
+ lifecycle.bound = true
40
+ const completed = new Map<string, number>()
41
+ const channel = <T,>(receive: (value: T) => void) =>
42
+ new Channel<T>((value) => {
43
+ if (lifecycle.active) receive(value)
44
+ })
45
+
46
+ void refreshTranslationModels().catch(() => undefined)
47
+
48
+ void commands
49
+ .subscribe(
50
+ channel<CanvasState>(receiveCanvas),
51
+ channel<Job>((job) => {
52
+ const previous = completed.get(job.id) ?? 0
53
+ completed.set(job.id, job.completed)
54
+ receiveJob(job)
55
+ if (job.completed > previous || job.state !== 'running') {
56
+ void refresh(projectKey, pagesKey, pageKey).catch(() => undefined)
57
+ }
58
+ }),
59
+ channel<Download>(receiveDownload),
60
+ channel<ModelResources>(receiveResources),
61
+ channel<ProjectInfo | null>((project) => {
62
+ const previous = queryClient.getQueryData<ProjectInfo | null>(projectKey)
63
+ queryClient.setQueryData(projectKey, project)
64
+ if (previous?.name !== project?.name) {
65
+ const store = useKoharuStore.getState()
66
+ store.selectPages(project?.active_page ? [project.active_page] : [])
67
+ store.selectLayers([])
68
+ }
69
+ if (project) {
70
+ void refresh(pagesKey, pageKey).catch(() => undefined)
71
+ } else {
72
+ queryClient.setQueryData(pagesKey, [])
73
+ queryClient.setQueryData(pageKey, null)
74
+ }
75
+ }),
76
+ )
77
+ .then((state) => {
78
+ if (lifecycle.active) receiveStartupState(state)
79
+ })
80
+ .catch(() => undefined)
81
+ }
82
+
83
+ return () => {
84
+ lifecycle.active = false
85
+ }
86
+ }, [])
87
+
88
+ useEffect(() => {
89
+ const setLanguage = (language: string) => {
90
+ document.documentElement.lang = language
91
+ }
92
+ setLanguage(i18n.language)
93
+ i18n.on('languageChanged', setLanguage)
94
+ return () => i18n.off('languageChanged', setLanguage)
95
+ }, [])
96
+
97
+ useEffect(() => {
98
+ // Prevent the host webview from applying browser zoom; keep Ctrl+wheel for app handlers.
99
+ const preventViewportScaling = (event: WheelEvent) => {
100
+ if (event.ctrlKey) event.preventDefault()
101
+ }
102
+
103
+ window.addEventListener('wheel', preventViewportScaling, { capture: true, passive: false })
104
+ return () => window.removeEventListener('wheel', preventViewportScaling, { capture: true })
105
+ }, [])
106
+
107
+ return (
108
+ <QueryClientProvider client={queryClient}>
109
+ <I18nextProvider i18n={i18n}>
110
+ <TooltipProvider delay={0}>
111
+ <ClientOnly>
112
+ <StartupBoundary>{children}</StartupBoundary>
113
+ <Toaster />
114
+ </ClientOnly>
115
+ </TooltipProvider>
116
+ </I18nextProvider>
117
+ </QueryClientProvider>
118
+ )
119
+ }
120
+
121
+ function StartupBoundary({ children }: { children: ReactNode }) {
122
+ const initialized = useKoharuStore((state) => state.initialized)
123
+ return initialized ? (
124
+ <>
125
+ {children}
126
+ </>
127
+ ) : (
128
+ <StartupView />
129
+ )
130
+ }
131
+
132
+ export default Providers
@@ -0,0 +1,14 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // @shenron/pipeline/koharu references Bun.CryptoHasher in one branch that the
3
+ // webview never reaches (ShenronExportPanel hashes the cleanup layer itself).
4
+ // koharu-ui does not load bun types, so declare only what that module names.
5
+
6
+
7
+ declare global {
8
+ var Bun: {
9
+ [member: string]: any;
10
+ CryptoHasher: new (algorithm: string) => {
11
+ update(data: Uint8Array): { digest(encoding: "hex"): string };
12
+ };
13
+ };
14
+ }
package/src/styles.css ADDED
@@ -0,0 +1,246 @@
1
+ /* SPDX-License-Identifier: Apache-2.0 */
2
+ @import './internal/styles/globals.css';
3
+
4
+ @font-face {
5
+ font-family: 'Koharu Noto Sans CJK';
6
+ src: url('./assets/NotoSansCJK-VF.otf') format('opentype');
7
+ font-style: normal;
8
+ font-weight: 100 900;
9
+ font-display: swap;
10
+ }
11
+
12
+ /* Koharu-specific surfaces are semantic aliases of the host's M3 scheme. */
13
+ [data-koharu-ui],
14
+ [data-koharu-ui-layer] {
15
+ --radius: var(--md-sys-shape-corner-medium);
16
+ --background: var(--md-sys-color-surface);
17
+ --foreground: var(--md-sys-color-on-surface);
18
+ --card: var(--md-sys-color-surface-container-low);
19
+ --card-foreground: var(--md-sys-color-on-surface);
20
+ --popover: var(--md-sys-color-surface-container-high);
21
+ --popover-foreground: var(--md-sys-color-on-surface);
22
+ --primary: var(--md-sys-color-primary);
23
+ --primary-foreground: var(--md-sys-color-on-primary);
24
+ --secondary: var(--md-sys-color-secondary-container);
25
+ --secondary-foreground: var(--md-sys-color-on-secondary-container);
26
+ --muted: var(--md-sys-color-surface-container-highest);
27
+ --muted-foreground: var(--md-sys-color-on-surface-variant);
28
+ --accent: var(--md-sys-color-tertiary-container);
29
+ --accent-foreground: var(--md-sys-color-on-tertiary-container);
30
+ --destructive: var(--md-sys-color-error);
31
+ --border: var(--md-sys-color-outline-variant);
32
+ --input: var(--md-sys-color-outline);
33
+ --ring: var(--md-sys-color-primary);
34
+ --canvas-selection: var(--md-sys-color-primary);
35
+ --canvas-region-contrast: var(--md-sys-color-inverse-on-surface);
36
+ --canvas-region-stroke: var(--md-sys-color-inverse-surface);
37
+ --surface-titlebar: var(--md-sys-color-surface-container-low);
38
+ --surface-toolbar: var(--md-sys-color-surface);
39
+ --surface-sidebar: var(--md-sys-color-surface-container);
40
+ --surface-panel: var(--md-sys-color-surface-container-low);
41
+ --surface-floating: var(--md-sys-color-surface-container-high);
42
+ --surface-well: var(--md-sys-color-surface-container-highest);
43
+ --surface-canvas: var(--md-sys-color-surface);
44
+ --shadow-titlebar: var(--md-sys-elevation-level1);
45
+ --shadow-panel: var(--md-sys-elevation-level2);
46
+ --shadow-content: var(--md-sys-elevation-level1);
47
+ --shadow-toolrail: var(--md-sys-elevation-level2);
48
+ --shadow-floating: var(--md-sys-elevation-level3);
49
+ }
50
+
51
+ @layer base {
52
+ [data-koharu-ui] {
53
+ min-height: 100%;
54
+ font-size: 18px;
55
+ line-height: 1.2;
56
+ font-family: var(--aphrody-font-brand, 'Koharu Noto Sans CJK', system-ui, sans-serif);
57
+ color: var(--md-sys-color-on-surface);
58
+ background-color: var(--md-sys-color-surface);
59
+ scrollbar-color: var(--md-sys-color-outline) var(--md-sys-color-surface-container);
60
+ scrollbar-width: auto;
61
+ }
62
+
63
+ [data-koharu-ui-layer] {
64
+ font-size: 18px;
65
+ line-height: 1.2;
66
+ font-family: var(--aphrody-font-brand, 'Koharu Noto Sans CJK', system-ui, sans-serif);
67
+ color: var(--md-sys-color-on-surface);
68
+ }
69
+
70
+ :is([data-koharu-ui], [data-koharu-ui-layer]) :focus-visible,
71
+ [data-koharu-ui-layer]:focus-visible {
72
+ outline: 3px solid var(--md-sys-color-primary);
73
+ outline-offset: 2px;
74
+ transition: none !important;
75
+ }
76
+
77
+ :is([data-koharu-ui], [data-koharu-ui-layer]) :is(button, [role='button'], input, select, textarea, [role='slider']) {
78
+ min-height: 48px;
79
+ }
80
+
81
+ :is([data-koharu-ui], [data-koharu-ui-layer]) :is(input, textarea) {
82
+ user-select: text;
83
+ }
84
+
85
+ [data-koharu-ui] [data-tauri-drag-region] {
86
+ app-region: drag;
87
+ }
88
+
89
+ [data-koharu-ui] [data-tauri-drag-region] :is(button, a, input, select, textarea, [role='button']) {
90
+ app-region: no-drag;
91
+ }
92
+
93
+ [data-koharu-ui] ::selection {
94
+ color: var(--md-sys-color-on-primary-container);
95
+ background: var(--md-sys-color-primary-container);
96
+ }
97
+ }
98
+
99
+ /* Keep dense legacy utility classes readable while preserving larger display text. */
100
+ @layer utilities {
101
+ :is([data-koharu-ui], [data-koharu-ui-layer]) :where(
102
+ .text-xs,
103
+ .text-sm,
104
+ .text-base,
105
+ [class~='text-[8px]'],
106
+ [class~='text-[9px]'],
107
+ [class~='text-[10px]'],
108
+ [class~='text-[11px]'],
109
+ [class~='text-[12px]'],
110
+ [class~='text-[13px]'],
111
+ [class~='text-[15px]']
112
+ ) {
113
+ font-size: 18px !important;
114
+ line-height: 1.2 !important;
115
+ }
116
+
117
+ [data-koharu-ui-layer]:where(
118
+ .text-xs,
119
+ .text-sm,
120
+ .text-base,
121
+ [class~='text-[8px]'],
122
+ [class~='text-[9px]'],
123
+ [class~='text-[10px]'],
124
+ [class~='text-[11px]'],
125
+ [class~='text-[12px]'],
126
+ [class~='text-[13px]'],
127
+ [class~='text-[15px]']
128
+ ) {
129
+ font-size: 18px !important;
130
+ line-height: 1.2 !important;
131
+ }
132
+ }
133
+
134
+ [data-koharu-ui] .workspace-corner-mask {
135
+ --workspace-corner-radius: var(--md-sys-shape-corner-extra-large);
136
+ overflow: visible !important;
137
+ }
138
+
139
+ [data-koharu-ui] .workspace-corner-mask::before {
140
+ position: absolute;
141
+ z-index: 50;
142
+ top: 0;
143
+ left: 0;
144
+ width: var(--workspace-corner-radius);
145
+ height: var(--workspace-corner-radius);
146
+ pointer-events: none;
147
+ content: '';
148
+ background: radial-gradient(
149
+ circle at bottom right,
150
+ transparent 0 calc(var(--workspace-corner-radius) - 1px),
151
+ var(--surface-sidebar) var(--workspace-corner-radius)
152
+ );
153
+ }
154
+
155
+ :is([data-koharu-ui], [data-koharu-ui-layer]) [data-slot='button']:not(.rounded-none),
156
+ :is([data-koharu-ui], [data-koharu-ui-layer]) [data-slot='input'],
157
+ :is([data-koharu-ui], [data-koharu-ui-layer]) [data-slot='textarea'],
158
+ :is([data-koharu-ui], [data-koharu-ui-layer]) [data-slot='select-trigger'],
159
+ [data-koharu-ui-layer][data-slot='button']:not(.rounded-none),
160
+ [data-koharu-ui-layer][data-slot='input'],
161
+ [data-koharu-ui-layer][data-slot='textarea'],
162
+ [data-koharu-ui-layer][data-slot='select-trigger'] {
163
+ border-radius: var(--md-sys-shape-corner-small);
164
+ box-shadow: none;
165
+ }
166
+
167
+ :is([data-koharu-ui], [data-koharu-ui-layer]) [data-slot='popover-content'],
168
+ :is([data-koharu-ui], [data-koharu-ui-layer]) [data-slot='dropdown-menu-content'],
169
+ :is([data-koharu-ui], [data-koharu-ui-layer]) [data-slot='select-content'],
170
+ :is([data-koharu-ui], [data-koharu-ui-layer]) [data-slot='dialog-content'],
171
+ :is([data-koharu-ui], [data-koharu-ui-layer]) [data-slot='alert-dialog-content'],
172
+ :is([data-koharu-ui], [data-koharu-ui-layer]) [data-slot='sheet-content'],
173
+ :is([data-koharu-ui], [data-koharu-ui-layer]) [data-slot='drawer-popup'],
174
+ :is([data-koharu-ui], [data-koharu-ui-layer]) [data-slot='toast'],
175
+ [data-koharu-ui-layer][data-slot='combobox-content'],
176
+ [data-koharu-ui-layer][data-slot='context-menu-content'],
177
+ [data-koharu-ui-layer][data-slot='popover-content'],
178
+ [data-koharu-ui-layer][data-slot='hover-card-content'],
179
+ [data-koharu-ui-layer][data-slot='dropdown-menu-content'],
180
+ [data-koharu-ui-layer][data-slot='navigation-menu-content'],
181
+ [data-koharu-ui-layer][data-slot='menubar-content'],
182
+ [data-koharu-ui-layer][data-slot='select-content'],
183
+ [data-koharu-ui-layer][data-slot='dialog-content'],
184
+ [data-koharu-ui-layer][data-slot='alert-dialog-content'],
185
+ [data-koharu-ui-layer][data-slot='sheet-content'],
186
+ [data-koharu-ui-layer][data-slot='drawer-popup'],
187
+ [data-koharu-ui-layer][data-slot='toast'] {
188
+ border: 1px solid var(--md-sys-color-outline-variant);
189
+ border-radius: var(--md-sys-shape-corner-large);
190
+ box-shadow: var(--md-sys-elevation-level3);
191
+ }
192
+
193
+ :is([data-koharu-ui], [data-koharu-ui-layer]) [data-slot='tabs-trigger'],
194
+ [data-koharu-ui-layer][data-slot='tabs-trigger'] {
195
+ min-height: 48px;
196
+ border-radius: var(--md-sys-shape-corner-small);
197
+ }
198
+
199
+ [data-koharu-ui] .react-colorful {
200
+ width: 100%;
201
+ min-height: 164px;
202
+ }
203
+
204
+ [data-koharu-ui] .react-colorful__saturation,
205
+ [data-koharu-ui] .react-colorful__last-control {
206
+ border-radius: var(--md-sys-shape-corner-small);
207
+ }
208
+
209
+ @media (prefers-contrast: more) {
210
+ :is([data-koharu-ui], [data-koharu-ui-layer]) :focus-visible,
211
+ [data-koharu-ui-layer]:focus-visible {
212
+ outline-color: var(--md-sys-color-on-surface);
213
+ outline-width: 4px;
214
+ }
215
+
216
+ :is([data-koharu-ui], [data-koharu-ui-layer]) :is(button, [role='button'], input, select, textarea, [role='slider']) {
217
+ border-color: var(--md-sys-color-outline);
218
+ }
219
+ }
220
+
221
+ @media (forced-colors: active) {
222
+ :is([data-koharu-ui], [data-koharu-ui-layer]) :focus-visible,
223
+ [data-koharu-ui-layer]:focus-visible {
224
+ outline-color: Highlight;
225
+ }
226
+
227
+ :is([data-koharu-ui], [data-koharu-ui-layer]) :is(button, [role='button'], input, select, textarea) {
228
+ border: 1px solid ButtonText;
229
+ }
230
+ }
231
+
232
+ @media (prefers-reduced-motion: reduce) {
233
+ [data-koharu-ui],
234
+ [data-koharu-ui-layer],
235
+ [data-koharu-ui] *,
236
+ [data-koharu-ui-layer] *,
237
+ [data-koharu-ui] *::before,
238
+ [data-koharu-ui] *::after,
239
+ [data-koharu-ui-layer] *::before,
240
+ [data-koharu-ui-layer] *::after {
241
+ scroll-behavior: auto !important;
242
+ animation-duration: 0.01ms !important;
243
+ animation-iteration-count: 1 !important;
244
+ transition-duration: 0.01ms !important;
245
+ }
246
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "lib": ["dom", "dom.iterable", "esnext"],
5
+ "strict": true,
6
+ "types": ["node"],
7
+ "noImplicitAny": false,
8
+ "noEmit": true,
9
+ "skipLibCheck": true,
10
+ "esModuleInterop": true,
11
+ "module": "esnext",
12
+ "moduleResolution": "bundler",
13
+ "resolveJsonModule": true,
14
+ "isolatedModules": true,
15
+ "jsx": "react-jsx",
16
+ "paths": {
17
+ "@aphrody/koharu-ui/*": ["./src/*"]
18
+ }
19
+ },
20
+ "include": ["src/**/*.ts", "src/**/*.tsx"]
21
+ }