@celestia-island/hikari 0.4.4

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 (187) hide show
  1. package/README.md +54 -0
  2. package/package.json +63 -0
  3. package/src/DemoApp.vue +400 -0
  4. package/src/components/HkActionBar.tsx +15 -0
  5. package/src/components/HkAlert.scss +121 -0
  6. package/src/components/HkAlert.tsx +85 -0
  7. package/src/components/HkAvatar.tsx +29 -0
  8. package/src/components/HkBadge.scss +117 -0
  9. package/src/components/HkBadge.tsx +50 -0
  10. package/src/components/HkBreadcrumb.tsx +39 -0
  11. package/src/components/HkButton.scss +128 -0
  12. package/src/components/HkButton.tsx +74 -0
  13. package/src/components/HkCard.scss +49 -0
  14. package/src/components/HkCard.tsx +38 -0
  15. package/src/components/HkCheckbox.scss +102 -0
  16. package/src/components/HkCheckbox.tsx +85 -0
  17. package/src/components/HkCollapse.tsx +48 -0
  18. package/src/components/HkColorPicker.scss +148 -0
  19. package/src/components/HkColorPicker.tsx +204 -0
  20. package/src/components/HkConfirmDialog.scss +12 -0
  21. package/src/components/HkConfirmDialog.tsx +75 -0
  22. package/src/components/HkDateTimePicker.scss +361 -0
  23. package/src/components/HkDateTimePicker.tsx +424 -0
  24. package/src/components/HkDivider.scss +85 -0
  25. package/src/components/HkDivider.tsx +51 -0
  26. package/src/components/HkDraggableGrid.scss +132 -0
  27. package/src/components/HkDraggableGrid.tsx +291 -0
  28. package/src/components/HkDraggableList.scss +110 -0
  29. package/src/components/HkDraggableList.tsx +238 -0
  30. package/src/components/HkDrawer.scss +175 -0
  31. package/src/components/HkDrawer.tsx +171 -0
  32. package/src/components/HkEmptyState.scss +42 -0
  33. package/src/components/HkEmptyState.tsx +41 -0
  34. package/src/components/HkErrorBoundary.scss +64 -0
  35. package/src/components/HkErrorBoundary.tsx +82 -0
  36. package/src/components/HkGaugeRing.scss +4 -0
  37. package/src/components/HkGaugeRing.tsx +130 -0
  38. package/src/components/HkHoverRevealAction.scss +66 -0
  39. package/src/components/HkHoverRevealAction.tsx +77 -0
  40. package/src/components/HkIcon.tsx +43 -0
  41. package/src/components/HkIconButton.tsx +42 -0
  42. package/src/components/HkImageViewer.scss +33 -0
  43. package/src/components/HkImageViewer.tsx +250 -0
  44. package/src/components/HkInput.scss +172 -0
  45. package/src/components/HkInput.tsx +175 -0
  46. package/src/components/HkKbd.tsx +26 -0
  47. package/src/components/HkKeywordSearchModal.scss +148 -0
  48. package/src/components/HkKeywordSearchModal.tsx +308 -0
  49. package/src/components/HkListTransition.scss +131 -0
  50. package/src/components/HkListTransition.tsx +29 -0
  51. package/src/components/HkLocalePickerPopup.tsx +42 -0
  52. package/src/components/HkLogo.scss +36 -0
  53. package/src/components/HkLogo.tsx +93 -0
  54. package/src/components/HkMarkdownRenderer.scss +141 -0
  55. package/src/components/HkMarkdownRenderer.tsx +123 -0
  56. package/src/components/HkMediaControlBar.scss +65 -0
  57. package/src/components/HkMediaControlBar.tsx +115 -0
  58. package/src/components/HkMediaPlayer.scss +29 -0
  59. package/src/components/HkMediaPlayer.tsx +210 -0
  60. package/src/components/HkMediaSlider.scss +54 -0
  61. package/src/components/HkMediaSlider.tsx +81 -0
  62. package/src/components/HkMediaVisualizer.scss +7 -0
  63. package/src/components/HkMediaVisualizer.tsx +119 -0
  64. package/src/components/HkMinimap.scss +76 -0
  65. package/src/components/HkMinimap.tsx +255 -0
  66. package/src/components/HkModal.scss +318 -0
  67. package/src/components/HkModal.tsx +481 -0
  68. package/src/components/HkModalBreadcrumb.scss +55 -0
  69. package/src/components/HkModalBreadcrumb.tsx +113 -0
  70. package/src/components/HkMorphingTabs.scss +141 -0
  71. package/src/components/HkMorphingTabs.tsx +113 -0
  72. package/src/components/HkNavItem.scss +81 -0
  73. package/src/components/HkNavItem.tsx +157 -0
  74. package/src/components/HkNumberInput.scss +154 -0
  75. package/src/components/HkNumberInput.tsx +161 -0
  76. package/src/components/HkPasswordInput.scss +289 -0
  77. package/src/components/HkPasswordInput.tsx +533 -0
  78. package/src/components/HkPhaseTransition.scss +25 -0
  79. package/src/components/HkPhaseTransition.tsx +40 -0
  80. package/src/components/HkPopover.scss +82 -0
  81. package/src/components/HkPopover.tsx +410 -0
  82. package/src/components/HkPopupSelect.scss +136 -0
  83. package/src/components/HkPopupSelect.tsx +199 -0
  84. package/src/components/HkProgressBar.scss +106 -0
  85. package/src/components/HkProgressBar.tsx +61 -0
  86. package/src/components/HkProgressDialog.tsx +67 -0
  87. package/src/components/HkProgressRing.scss +56 -0
  88. package/src/components/HkProgressRing.tsx +82 -0
  89. package/src/components/HkRadio.scss +119 -0
  90. package/src/components/HkRadio.tsx +75 -0
  91. package/src/components/HkRollingNumber.scss +37 -0
  92. package/src/components/HkRollingNumber.tsx +97 -0
  93. package/src/components/HkScrollContainer.scss +101 -0
  94. package/src/components/HkScrollContainer.tsx +362 -0
  95. package/src/components/HkSearchInput.scss +132 -0
  96. package/src/components/HkSearchInput.tsx +117 -0
  97. package/src/components/HkSelect.scss +143 -0
  98. package/src/components/HkSelect.tsx +230 -0
  99. package/src/components/HkSelectionGrid.scss +177 -0
  100. package/src/components/HkSelectionGrid.tsx +99 -0
  101. package/src/components/HkSelectionWaterfall.scss +93 -0
  102. package/src/components/HkSelectionWaterfall.tsx +90 -0
  103. package/src/components/HkSidebar.scss +81 -0
  104. package/src/components/HkSidebar.tsx +45 -0
  105. package/src/components/HkSkeleton.scss +44 -0
  106. package/src/components/HkSkeleton.tsx +30 -0
  107. package/src/components/HkSkeletonList.tsx +35 -0
  108. package/src/components/HkSpinner.scss +67 -0
  109. package/src/components/HkSpinner.tsx +41 -0
  110. package/src/components/HkSplash.scss +60 -0
  111. package/src/components/HkSplash.tsx +40 -0
  112. package/src/components/HkSwitch.scss +157 -0
  113. package/src/components/HkSwitch.tsx +72 -0
  114. package/src/components/HkTable.scss +198 -0
  115. package/src/components/HkTable.tsx +246 -0
  116. package/src/components/HkTabs.scss +109 -0
  117. package/src/components/HkTabs.tsx +111 -0
  118. package/src/components/HkTag.scss +88 -0
  119. package/src/components/HkTag.tsx +44 -0
  120. package/src/components/HkTextarea.scss +72 -0
  121. package/src/components/HkTextarea.tsx +104 -0
  122. package/src/components/HkTimeline.scss +139 -0
  123. package/src/components/HkTimeline.tsx +95 -0
  124. package/src/components/HkToast.scss +168 -0
  125. package/src/components/HkToast.tsx +175 -0
  126. package/src/components/HkTooltip.scss +47 -0
  127. package/src/components/HkTooltip.tsx +108 -0
  128. package/src/components/HkTree.scss +188 -0
  129. package/src/components/HkTree.tsx +217 -0
  130. package/src/components/HkTrendChart.tsx +180 -0
  131. package/src/components/HkWindowedItem.scss +17 -0
  132. package/src/components/HkWindowedItem.tsx +107 -0
  133. package/src/components/HkZoomToolbar.scss +35 -0
  134. package/src/components/HkZoomToolbar.tsx +69 -0
  135. package/src/composables/useBreakpoint.ts +41 -0
  136. package/src/composables/useClipboard.ts +37 -0
  137. package/src/composables/useConfirm.ts +35 -0
  138. package/src/composables/useProgressDialog.ts +52 -0
  139. package/src/composables/useReportedTransition.ts +69 -0
  140. package/src/composables/useScrollWindow.ts +21 -0
  141. package/src/composables/useToast.ts +2 -0
  142. package/src/demo.scss +24 -0
  143. package/src/demo.ts +22 -0
  144. package/src/env.d.ts +6 -0
  145. package/src/i18n/context.ts +89 -0
  146. package/src/i18n/locales/ar/components.json +43 -0
  147. package/src/i18n/locales/ar/components.toml +40 -0
  148. package/src/i18n/locales/de/components.json +43 -0
  149. package/src/i18n/locales/de/components.toml +40 -0
  150. package/src/i18n/locales/en/components.json +43 -0
  151. package/src/i18n/locales/en/components.toml +40 -0
  152. package/src/i18n/locales/es/components.json +43 -0
  153. package/src/i18n/locales/es/components.toml +40 -0
  154. package/src/i18n/locales/fr/components.json +43 -0
  155. package/src/i18n/locales/fr/components.toml +40 -0
  156. package/src/i18n/locales/ja/components.json +43 -0
  157. package/src/i18n/locales/ja/components.toml +40 -0
  158. package/src/i18n/locales/ko/components.json +43 -0
  159. package/src/i18n/locales/ko/components.toml +40 -0
  160. package/src/i18n/locales/pt/components.json +43 -0
  161. package/src/i18n/locales/pt/components.toml +40 -0
  162. package/src/i18n/locales/ru/components.json +43 -0
  163. package/src/i18n/locales/ru/components.toml +40 -0
  164. package/src/i18n/locales/zh-Hans/components.json +43 -0
  165. package/src/i18n/locales/zh-Hans/components.toml +40 -0
  166. package/src/i18n/locales/zh-Hant/components.json +43 -0
  167. package/src/i18n/locales/zh-Hant/components.toml +40 -0
  168. package/src/index.ts +137 -0
  169. package/src/render.ts +18 -0
  170. package/src/runtime/animationBus.ts +278 -0
  171. package/src/runtime/cronBus.ts +25 -0
  172. package/src/runtime/index.ts +12 -0
  173. package/src/runtime/useAsyncData.ts +30 -0
  174. package/src/runtime/useBreakpoint.ts +62 -0
  175. package/src/runtime/useClipboard.ts +37 -0
  176. package/src/runtime/useConfirm.ts +35 -0
  177. package/src/runtime/useOverlay.ts +82 -0
  178. package/src/runtime/usePopupManager.ts +89 -0
  179. package/src/runtime/useToast.ts +140 -0
  180. package/src/styles/index.scss +10 -0
  181. package/src/theme/index.ts +5 -0
  182. package/src/theme/presets.ts +307 -0
  183. package/src/theme/theme.scss +17 -0
  184. package/src/theme/useBackgroundLuminance.ts +145 -0
  185. package/src/theme/useSolarTime.ts +101 -0
  186. package/src/theme/useTheme.ts +141 -0
  187. package/src/tokens.scss +26 -0
package/README.md ADDED
@@ -0,0 +1,54 @@
1
+ # @celestia-island/hikari
2
+
3
+ Vue 3 component library sharing SCSS styles with the hikari Rust/WASM renderer.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @celestia-island/hikari
9
+ pnpm add @celestia-island/hikari
10
+ ```
11
+
12
+ ## Usage
13
+
14
+ Import styles once in your app entry point:
15
+
16
+ ```ts
17
+ // main.ts
18
+ import "@celestia-island/hikari/styles";
19
+ import { createApp } from "vue";
20
+ import App from "./App.vue";
21
+
22
+ createApp(App).mount("#app");
23
+ ```
24
+
25
+ Use components in your templates:
26
+
27
+ ```vue
28
+ <script setup lang="ts">
29
+ import { HkButton, HkCard, HkInput } from "@celestia-island/hikari";
30
+ </script>
31
+
32
+ <template>
33
+ <HkCard>
34
+ <HkInput v-model="text" placeholder="Type..." />
35
+ <HkButton variant="primary">Submit</HkButton>
36
+ </HkCard>
37
+ </template>
38
+ ```
39
+
40
+ ## Components
41
+
42
+ - **HkButton** — primary/secondary/danger/ghost variants
43
+ - **HkCard** — hoverable card container
44
+ - **HkInput** — text input with v-model
45
+ - **HkModal** — teleported dialog
46
+ - **HkSidebar** — collapsible sidebar
47
+ - **HkTabs** — tab navigation
48
+ - **HkToast** — toast notifications
49
+ - **HkAvatar** — image/fallback avatar
50
+ - And more...
51
+
52
+ ## License
53
+
54
+ BUSL-1.1
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@celestia-island/hikari",
3
+ "version": "0.4.4",
4
+ "private": false,
5
+ "type": "module",
6
+ "description": "Hikari Vue 3 component library — production-grade UI components based on shittim-chest design system",
7
+ "license": "SySL-1.0",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/celestia-island/hikari"
11
+ },
12
+ "homepage": "https://github.com/celestia-island/hikari",
13
+ "keywords": [
14
+ "vue3",
15
+ "ui-components",
16
+ "design-system",
17
+ "hikari",
18
+ "celestia-island"
19
+ ],
20
+ "main": "./src/index.ts",
21
+ "types": "./src/index.ts",
22
+ "exports": {
23
+ ".": {
24
+ "import": "./src/index.ts",
25
+ "types": "./src/index.ts"
26
+ },
27
+ "./styles": {
28
+ "import": "./src/styles/index.scss"
29
+ }
30
+ },
31
+ "files": [
32
+ "src/",
33
+ "package.json"
34
+ ],
35
+ "scripts": {
36
+ "dev": "vite",
37
+ "build": "vue-tsc --noEmit",
38
+ "build:docs": "vite build",
39
+ "lint": "echo ok",
40
+ "prepublishOnly": "vue-tsc --noEmit"
41
+ },
42
+ "peerDependencies": {
43
+ "vue": "^*"
44
+ },
45
+ "dependencies": {
46
+ "dompurify": "^*",
47
+ "echarts": "^*",
48
+ "lucide-vue-next": "^*",
49
+ "marked": "^*"
50
+ },
51
+ "devDependencies": {
52
+ "@vitejs/plugin-vue": "^*",
53
+ "@vitejs/plugin-vue-jsx": "^*",
54
+ "@vue/server-renderer": "^*",
55
+ "sass": "^*",
56
+ "typescript": "~6.0",
57
+ "vite": "^*",
58
+ "vue-tsc": "^*"
59
+ },
60
+ "overrides": {
61
+ "typescript": "~6.0"
62
+ }
63
+ }
@@ -0,0 +1,400 @@
1
+ <template>
2
+ <div class="demo">
3
+ <header class="demo-header">
4
+ <h1>Hikari</h1>
5
+ <p class="subtitle">Vue 3 Component Library — {{ totalComponents }} components</p>
6
+ </header>
7
+
8
+ <section>
9
+ <h2>HButton</h2>
10
+ <div class="row">
11
+ <HButton variant="primary" size="sm">Primary</HButton>
12
+ <HButton variant="secondary" size="sm">Secondary</HButton>
13
+ <HButton variant="outline" size="sm">Outline</HButton>
14
+ <HButton variant="ghost" size="sm">Ghost</HButton>
15
+ <HButton variant="danger" size="sm">Danger</HButton>
16
+ </div>
17
+ <div class="row">
18
+ <HButton variant="primary" size="sm">Sm</HButton>
19
+ <HButton variant="primary" size="md">Md</HButton>
20
+ <HButton variant="primary" size="lg">Lg</HButton>
21
+ </div>
22
+ <div class="row">
23
+ <HButton variant="primary" loading>Loading</HButton>
24
+ <HButton variant="primary" disabled>Disabled</HButton>
25
+ <HButton variant="primary" shortcut="⌘K">Shortcut</HButton>
26
+ </div>
27
+ </section>
28
+
29
+ <section>
30
+ <h2>HIconButton</h2>
31
+ <div class="row">
32
+ <HIconButton icon="search" variant="ghost" :size="16" />
33
+ <HIconButton icon="settings" variant="secondary" :size="24" />
34
+ <HIconButton icon="heart" variant="primary" :size="40" />
35
+ </div>
36
+ </section>
37
+
38
+ <section>
39
+ <h2>HTooltip</h2>
40
+ <div class="row">
41
+ <HTooltip text="Top placement" placement="top"><HButton variant="outline" size="sm">Top</HButton></HTooltip>
42
+ <HTooltip text="Bottom placement" placement="bottom"><HButton variant="outline" size="sm">Bottom</HButton></HTooltip>
43
+ <HTooltip text="Left placement" placement="left"><HButton variant="outline" size="sm">Left</HButton></HTooltip>
44
+ <HTooltip text="Right placement" placement="right"><HButton variant="outline" size="sm">Right</HButton></HTooltip>
45
+ </div>
46
+ </section>
47
+
48
+ <section>
49
+ <h2>HBadge</h2>
50
+ <div class="row">
51
+ <HBadge>Default</HBadge>
52
+ <HBadge variant="success">Success</HBadge>
53
+ <HBadge variant="warning">Warning</HBadge>
54
+ <HBadge variant="error">Error</HBadge>
55
+ </div>
56
+ </section>
57
+
58
+ <section>
59
+ <h2>HTag</h2>
60
+ <div class="row">
61
+ <HTag>Default</HTag>
62
+ <HTag variant="success">Success</HTag>
63
+ <HTag variant="warning">Warning</HTag>
64
+ <HTag variant="danger">Danger</HTag>
65
+ <HTag closable @close="() => {}">Closable</HTag>
66
+ </div>
67
+ </section>
68
+
69
+ <section>
70
+ <h2>HIcons</h2>
71
+ <div class="row icons">
72
+ <span class="icon-grid" v-for="i in icons" :key="i"><HIcon :name="i" :size="24" /><small>{{ i }}</small></span>
73
+ </div>
74
+ </section>
75
+
76
+ <section>
77
+ <h2>HSpinner</h2>
78
+ <div class="row"><HSpinner size="xs" /><HSpinner size="sm" /><HSpinner size="md" /><HSpinner size="lg" /><HSpinner size="xl" /></div>
79
+ </section>
80
+
81
+ <section>
82
+ <h2>HProgressBar / HProgressRing / HGaugeRing</h2>
83
+ <div class="row"><HProgressBar :value="65" style="width:200px" /></div>
84
+ <div class="row"><HProgressRing :value="75" :size="80" /><HGaugeRing :rings="gaugeRings" :size="80" center-label="CPU" /></div>
85
+ </section>
86
+
87
+ <section>
88
+ <h2>HInput / HSearchInput / HNumberInput / HPasswordInput / HTextarea</h2>
89
+ <div class="form-grid">
90
+ <HInput v-model="form.text" placeholder="Text input" />
91
+ <HInput v-model="form.text" placeholder="Disabled" disabled />
92
+ <HSearchInput v-model="form.search" placeholder="Search..." />
93
+ <HNumberInput v-model="form.number" placeholder="Number" />
94
+ <HPasswordInput v-model="form.password" placeholder="Password" />
95
+ <HTextarea v-model="form.textarea" placeholder="Textarea" :rows="3" />
96
+ </div>
97
+ <p class="result" v-if="anyForm">Form: {{ anyForm }}</p>
98
+ </section>
99
+
100
+ <section>
101
+ <h2>HCheckbox / HSwitch / HRadio</h2>
102
+ <div class="row">
103
+ <HCheckbox v-model="flags.a">Option A</HCheckbox>
104
+ <HCheckbox v-model="flags.b">Option B</HCheckbox>
105
+ <HSwitch v-model="flags.on" label="Toggle" />
106
+ <HRadio v-model="flags.radio" :options="radioOpts" />
107
+ </div>
108
+ </section>
109
+
110
+ <section>
111
+ <h2>HSelect</h2>
112
+ <div class="row"><HSelect v-model="select.val" :options="select.opts" placeholder="Choose..." style="width:200px" /></div>
113
+ </section>
114
+
115
+ <section>
116
+ <h2>HSkeleton / HSkeletonList</h2>
117
+ <div class="row">
118
+ <HSkeleton width="100px" height="24px" />
119
+ <HSkeletonList :count="3" style="width:300px" />
120
+ </div>
121
+ </section>
122
+
123
+ <section>
124
+ <h2>HAvatar</h2>
125
+ <div class="row">
126
+ <HAvatar name="John Doe" size="sm" />
127
+ <HAvatar name="Jane Smith" size="md" />
128
+ <HAvatar name="Admin" size="lg" />
129
+ </div>
130
+ </section>
131
+
132
+ <section>
133
+ <h2>HKbd</h2>
134
+ <div class="row"><HKbd keys="⌘" /><HKbd keys="⌥" /><HKbd keys="⇧" /><HKbd keys="⌃" /><HKbd keys="K" /><span> = open command palette</span></div>
135
+ </section>
136
+
137
+ <section>
138
+ <h2>HDivider</h2>
139
+ <HDivider />
140
+ <p style="opacity:0.5;text-align:center;padding:8px 0">Section above divider</p>
141
+ <HDivider />
142
+ <p style="opacity:0.5;text-align:center;padding:8px 0">Section below divider</p>
143
+ </section>
144
+
145
+ <section>
146
+ <h2>HAlert</h2>
147
+ <div class="col"><HAlert message="Default info alert" /><HAlert variant="success" message="Success alert" /><HAlert variant="warning" message="Warning alert" /><HAlert variant="error" message="Error alert" /></div>
148
+ </section>
149
+
150
+ <section>
151
+ <h2>HEmptyState</h2>
152
+ <HEmptyState title="No items" description="Nothing to show here yet.">
153
+ <template #icon><HIcon name="inbox" :size="48" /></template>
154
+ </HEmptyState>
155
+ </section>
156
+
157
+ <section>
158
+ <h2>HCollapse</h2>
159
+ <HCollapse title="Click to expand section">
160
+ <p style="padding:12px">This content is collapsible. It can contain any children.</p>
161
+ </HCollapse>
162
+ </section>
163
+
164
+ <section>
165
+ <h2>HTabs / HMorphingTabs</h2>
166
+ <HTabs v-model="tabs.active" :tabs="tabs.items" />
167
+ <p class="result" style="margin-top:8px">Active tab: {{ tabs.active }}</p>
168
+ <div style="margin-top:12px" />
169
+ <HMorphingTabs v-model="morphTabs.active" :tabs="morphTabs.items" />
170
+ </section>
171
+
172
+ <section>
173
+ <h2>HCard</h2>
174
+ <div class="row">
175
+ <HCard style="padding:20px;flex:1">
176
+ <h4>Card title</h4>
177
+ <p style="font-size:0.75rem;opacity:0.7">Card body content goes here.</p>
178
+ </HCard>
179
+ <HCard style="padding:20px;flex:1" hover>
180
+ <h4>Hoverable card</h4>
181
+ <p style="font-size:0.75rem;opacity:0.7">Hover me for effect.</p>
182
+ </HCard>
183
+ </div>
184
+ </section>
185
+
186
+ <section>
187
+ <h2>HTable</h2>
188
+ <HTable :columns="tableCols" :rows="tableRows" style="max-height:200px" />
189
+ </section>
190
+
191
+ <section>
192
+ <h2>HTimeline</h2>
193
+ <HTimeline :steps="timelineSteps" current-key="v2" />
194
+ </section>
195
+
196
+ <section>
197
+ <h2>HMediaSlider</h2>
198
+ <div class="row" style="width:min(420px,100%)">
199
+ <HMediaSlider v-model:ratio="mediaSliderRatio" :buffered="0.85" />
200
+ <span style="font-size:0.7rem;opacity:0.6">{{ Math.round(mediaSliderRatio * 100) }}%</span>
201
+ </div>
202
+ </section>
203
+
204
+ <section>
205
+ <h2>HMediaPlayer (audio)</h2>
206
+ <HMediaPlayer type="audio" :src="demoAudioSrc" style="max-width:560px" />
207
+ </section>
208
+
209
+ <section>
210
+ <h2>HImageViewer</h2>
211
+ <HImageViewer :src="demoImageSrc" alt="Hikari demo image" />
212
+ </section>
213
+
214
+ <section>
215
+ <h2>HZoomToolbar / HMinimap</h2>
216
+ <div style="position:relative;height:200px;border-radius:8px;overflow:hidden;background:rgba(0,0,0,0.35)">
217
+ <div style="position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:0.75rem;opacity:0.5">
218
+ Host surface — zoom {{ zoomState.zoom.toFixed(2) }}x, pan ({{ Math.round(zoomState.panX) }}, {{ Math.round(zoomState.panY) }})
219
+ </div>
220
+ <HZoomToolbar
221
+ :zoom="zoomState.zoom"
222
+ :can-zoom-in="zoomState.canIn"
223
+ :can-zoom-out="zoomState.canOut"
224
+ :is-zoomed="zoomState.zoomed"
225
+ @zoom-in="zoomIn"
226
+ @zoom-out="zoomOut"
227
+ @reset="zoomReset"
228
+ />
229
+ <HMinimap
230
+ :boxes="zoomBoxes"
231
+ :hub-pos="zoomHub"
232
+ :zoom="zoomState.zoom"
233
+ :pan-x="zoomState.panX"
234
+ :pan-y="zoomState.panY"
235
+ :viewport-width="800"
236
+ :viewport-height="200"
237
+ :content-bounds="zoomContent"
238
+ :zoom-percent="Math.round(zoomState.zoom * 100)"
239
+ :can-zoom-in="zoomState.canIn"
240
+ :can-zoom-out="zoomState.canOut"
241
+ show-reset
242
+ @pan-delta="panBy"
243
+ />
244
+ </div>
245
+ </section>
246
+
247
+ <section>
248
+ <h2>HTrendChart</h2>
249
+ <HTrendChart :pens="trendPens" height="260px" style="max-width:760px" />
250
+ </section>
251
+
252
+ <section class="demo-footer">
253
+ <p>Hikari v0.4.4 — Powered by celestia-island</p>
254
+ </section>
255
+ </div>
256
+ </template>
257
+
258
+ <script setup lang="ts">
259
+ import { ref, computed } from 'vue'
260
+ import {
261
+ HButton, HIconButton, HTooltip, HBadge, HTag, HIcon, HSpinner,
262
+ HProgressBar, HProgressRing, HGaugeRing,
263
+ HInput, HSearchInput, HNumberInput, HPasswordInput, HTextarea,
264
+ HCheckbox, HSwitch, HRadio, HSelect,
265
+ HSkeleton, HSkeletonList, HAvatar, HKbd, HDivider,
266
+ HAlert, HEmptyState, HCollapse,
267
+ HTabs, HMorphingTabs, HCard, HTable, HTimeline,
268
+ HMediaSlider, HMediaPlayer, HImageViewer,
269
+ HZoomToolbar, HMinimap, HTrendChart,
270
+ type TrendPen, type MinimapBox,
271
+ } from '@celestia-island/hikari'
272
+
273
+ const totalComponents = 64
274
+
275
+ const icons = ['home', 'settings', 'user', 'search', 'bell', 'heart', 'star', 'mail', 'download', 'upload', 'trash', 'edit', 'plus', 'check', 'x']
276
+
277
+ const form = ref({ text: '', search: '', number: 0, password: '', textarea: '' })
278
+ const anyForm = computed(() => Object.values(form.value).filter(v => v !== '' && v !== 0).join(', ') || null)
279
+ const flags = ref({ a: true, b: false, on: false, radio: 'x' })
280
+ const radioOpts = [{ value: 'x', label: 'X' }, { value: 'y', label: 'Y' }]
281
+ const gaugeRings = [{ pct: 45, color: 'rgb(var(--color-primary, 122 162 247))', trackColor: 'rgba(122, 162, 247, 0.15)' }]
282
+ const select = ref({ val: '', opts: [{ value: 'a', label: 'Alpha' }, { value: 'b', label: 'Beta' }, { value: 'c', label: 'Gamma' }] })
283
+ const tabs = ref({ active: 'tab1', items: [{ key: 'tab1', label: 'Overview' }, { key: 'tab2', label: 'Details' }, { key: 'tab3', label: 'Settings' }] })
284
+ const morphTabs = ref({ active: 'm1', items: [{ key: 'm1', label: 'Read' }, { key: 'm2', label: 'Write' }, { key: 'm3', label: 'Preview' }] })
285
+
286
+ const tableCols = [{ key: 'name', title: 'Name' }, { key: 'role', title: 'Role' }]
287
+ const tableRows = [{ name: 'Alice', role: 'Admin' }, { name: 'Bob', role: 'Editor' }, { name: 'Charlie', role: 'Viewer' }]
288
+ const timelineSteps = [
289
+ { key: 'v1', label: 'v1.0 Released' },
290
+ { key: 'v11', label: 'v1.1' },
291
+ { key: 'v2', label: 'v2.0' },
292
+ ]
293
+
294
+ const mediaSliderRatio = ref(0.42)
295
+
296
+ function makeSilentWav(seconds = 2, sampleRate = 8000): string {
297
+ const frames = seconds * sampleRate
298
+ const bytes = 44 + frames
299
+ const buf = new Uint8Array(bytes)
300
+ const v = new DataView(buf.buffer)
301
+ v.setUint32(0, 0x52494646, false) // "RIFF"
302
+ v.setUint32(4, bytes - 8, true)
303
+ v.setUint32(8, 0x57415645, false) // "WAVE"
304
+ v.setUint32(12, 0x666d7420, false) // "fmt "
305
+ v.setUint32(16, 16, true)
306
+ v.setUint16(20, 1, true)
307
+ v.setUint16(22, 1, true)
308
+ v.setUint32(24, sampleRate, true)
309
+ v.setUint32(28, sampleRate, true)
310
+ v.setUint16(32, 1, true)
311
+ v.setUint16(34, 8, true)
312
+ v.setUint32(36, 0x64617461, false) // "data"
313
+ v.setUint32(40, frames, true)
314
+ return 'data:audio/wav;base64,' + btoa(String.fromCharCode(...buf))
315
+ }
316
+ const demoAudioSrc = makeSilentWav()
317
+
318
+ const demoImageSrc =
319
+ 'data:image/svg+xml;base64,' +
320
+ btoa(`<svg xmlns="http://www.w3.org/2000/svg" width="1600" height="900">
321
+ <rect width="1600" height="900" fill="#1b2333"/>
322
+ <g stroke="#2c3a55" stroke-width="1">
323
+ ${Array.from({ length: 15 }, (_, i) => `<line x1="${i * 110}" y1="0" x2="${i * 110}" y2="900"/>`).join('')}
324
+ ${Array.from({ length: 9 }, (_, i) => `<line x1="0" y1="${i * 110}" x2="1600" y2="${i * 110}"/>`).join('')}
325
+ </g>
326
+ <circle cx="800" cy="450" r="180" fill="rgba(122,162,247,0.35)" stroke="#7aa2f7" stroke-width="3"/>
327
+ <circle cx="800" cy="450" r="90" fill="rgba(122,162,247,0.2)" stroke="#7aa2f7" stroke-width="2" stroke-dasharray="6 4"/>
328
+ <circle cx="800" cy="450" r="12" fill="#f7768e"/>
329
+ <text x="800" y="700" fill="#9aa5ce" font-family="monospace" font-size="28" text-anchor="middle">Hikari — zoom / pan demo</text>
330
+ </svg>`)
331
+
332
+ const zoomState = ref({ zoom: 1.6, panX: -40, panY: -18, canIn: true, canOut: true, zoomed: true })
333
+ const zoomBoxes: MinimapBox[] = [
334
+ { id: 'a', bounds: { x: 60, y: 40, w: 200, h: 90 }, color: 'rgb(var(--color-info, 59 130 246))' },
335
+ { id: 'b', bounds: { x: 340, y: 40, w: 200, h: 90 }, color: 'rgb(var(--color-success, 34 197 94))' },
336
+ { id: 'c', bounds: { x: 200, y: 160, w: 200, h: 90 }, color: 'rgb(var(--color-warning, 245 158 11))' },
337
+ ]
338
+ const zoomHub = { x: 300, y: 210 }
339
+ const zoomContent = { x: 0, y: 0, w: 600, h: 300 }
340
+ function zoomIn() {
341
+ zoomState.value.zoom = Math.min(8, zoomState.value.zoom * 1.2)
342
+ syncZoom()
343
+ }
344
+ function zoomOut() {
345
+ zoomState.value.zoom = Math.max(1, zoomState.value.zoom / 1.2)
346
+ syncZoom()
347
+ }
348
+ function zoomReset() {
349
+ zoomState.value.zoom = 1
350
+ zoomState.value.panX = 0
351
+ zoomState.value.panY = 0
352
+ syncZoom()
353
+ }
354
+ function panBy(dx: number, dy: number) {
355
+ zoomState.value.panX += dx
356
+ zoomState.value.panY += dy
357
+ syncZoom()
358
+ }
359
+ function syncZoom() {
360
+ const z = zoomState.value
361
+ z.zoomed = z.zoom > 1
362
+ z.canIn = z.zoom < 8
363
+ z.canOut = z.zoom > 1
364
+ }
365
+
366
+ const now = Date.now()
367
+ const trendPens: TrendPen[] = [
368
+ {
369
+ label: 'CPU',
370
+ thresholds: { h: 70, l: 15 },
371
+ data: Array.from({ length: 40 }, (_, i) => ({
372
+ time: now - (40 - i) * 15_000,
373
+ value: 30 + Math.sin(i / 3) * 18 + (i % 7) * 2,
374
+ })),
375
+ },
376
+ {
377
+ label: 'Memory',
378
+ thresholds: { hh: 90 },
379
+ data: Array.from({ length: 40 }, (_, i) => ({
380
+ time: now - (40 - i) * 15_000,
381
+ value: 48 + Math.cos(i / 4) * 10,
382
+ })),
383
+ },
384
+ ]
385
+ </script>
386
+
387
+ <style lang="scss" scoped>
388
+ .demo-header { text-align: center; margin-bottom: 3rem; }
389
+ .demo-header h1 { font-size: 2.5rem; margin-bottom: 0.25rem; }
390
+ .subtitle { font-size: 0.875rem; opacity: 0.5; }
391
+ h2 { font-size: 1.1rem; margin: 2.5rem 0 0.75rem; padding-bottom: 0.5rem; border-bottom: 1px solid var(--border-faint, rgba(255,255,255,0.1)); }
392
+ .row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
393
+ .col { display: flex; flex-direction: column; gap: 8px; }
394
+ .icons { gap: 20px; }
395
+ .icon-grid { display: inline-flex; flex-direction: column; align-items: center; gap: 2px; }
396
+ .icon-grid small { font-size: 0.6rem; opacity: 0.4; }
397
+ .form-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; max-width: 600px; }
398
+ .result { font-size: 0.75rem; opacity: 0.6; margin-top: 8px; }
399
+ .demo-footer { text-align: center; margin-top: 4rem; padding: 2rem 0; font-size: 0.75rem; opacity: 0.35; }
400
+ </style>
@@ -0,0 +1,15 @@
1
+ import { defineComponent, type PropType } from "vue";
2
+
3
+ export default defineComponent({
4
+ name: "HkActionBar",
5
+ props: {
6
+ gap: { type: String, default: "0.5rem" },
7
+ },
8
+ setup(props, { slots }) {
9
+ return () => (
10
+ <div class="hk-action-bar" style={{ gap: props.gap }}>
11
+ {slots.default?.()}
12
+ </div>
13
+ );
14
+ },
15
+ });
@@ -0,0 +1,121 @@
1
+ .hk-alert {
2
+ display: flex;
3
+ align-items: flex-start;
4
+ gap: var(--hi-space-12, 12px);
5
+ padding: var(--hi-space-12, 12px) var(--hi-space-16, 16px);
6
+ border-radius: var(--hi-radius-md, 8px);
7
+ border: 1px solid transparent;
8
+ border-left-width: 4px;
9
+ color: var(--hi-color-text-primary);
10
+ }
11
+
12
+ .hk-alert-banner {
13
+ border-radius: 0;
14
+ }
15
+
16
+ .hk-alert-no-title {
17
+ align-items: center;
18
+ }
19
+
20
+ /* ── Sizes ─────────────────────────────────────── */
21
+
22
+ .hk-alert-sm {
23
+ padding: var(--hi-space-8, 8px) var(--hi-space-12, 12px);
24
+ font-size: var(--hi-text-xs, 0.75rem);
25
+ }
26
+
27
+ .hk-alert-md {
28
+ padding: var(--hi-space-12, 12px) var(--hi-space-16, 16px);
29
+ font-size: var(--hi-text-sm, 0.875rem);
30
+ }
31
+
32
+ .hk-alert-lg {
33
+ padding: var(--hi-space-16, 16px) var(--hi-space-24, 24px);
34
+ font-size: var(--hi-text-base, 1rem);
35
+ }
36
+
37
+ /* ── Variants ──────────────────────────────────── */
38
+
39
+ .hk-alert-error {
40
+ background: color-mix(in srgb, var(--hi-color-danger) 8%, transparent);
41
+ border-color: color-mix(in srgb, var(--hi-color-danger) 15%, transparent);
42
+ border-left-color: var(--hi-color-danger);
43
+
44
+ .hk-alert-icon { color: var(--hi-color-danger); }
45
+ }
46
+
47
+ .hk-alert-warning {
48
+ background: color-mix(in srgb, var(--hi-color-warning) 8%, transparent);
49
+ border-color: color-mix(in srgb, var(--hi-color-warning) 15%, transparent);
50
+ border-left-color: var(--hi-color-warning);
51
+
52
+ .hk-alert-icon { color: var(--hi-color-warning); }
53
+ }
54
+
55
+ .hk-alert-info {
56
+ background: color-mix(in srgb, var(--hi-color-primary) 8%, transparent);
57
+ border-color: color-mix(in srgb, var(--hi-color-primary) 15%, transparent);
58
+ border-left-color: var(--hi-color-primary);
59
+
60
+ .hk-alert-icon { color: var(--hi-color-primary); }
61
+ }
62
+
63
+ .hk-alert-success {
64
+ background: color-mix(in srgb, var(--hi-color-success) 8%, transparent);
65
+ border-color: color-mix(in srgb, var(--hi-color-success) 15%, transparent);
66
+ border-left-color: var(--hi-color-success);
67
+
68
+ .hk-alert-icon { color: var(--hi-color-success); }
69
+ }
70
+
71
+ /* ── Icon ──────────────────────────────────────── */
72
+
73
+ .hk-alert-icon {
74
+ display: flex;
75
+ align-items: center;
76
+ flex-shrink: 0;
77
+ padding-top: 1px;
78
+ }
79
+
80
+ /* ── Body ──────────────────────────────────────── */
81
+
82
+ .hk-alert-body {
83
+ flex: 1;
84
+ min-width: 0;
85
+ }
86
+
87
+ .hk-alert-title {
88
+ margin: 0 0 2px;
89
+ font-weight: 600;
90
+ font-size: inherit;
91
+ line-height: 1.4;
92
+ }
93
+
94
+ .hk-alert-text {
95
+ margin: 0;
96
+ line-height: 1.5;
97
+ color: color-mix(in srgb, var(--hi-color-text-secondary) 85%, transparent);
98
+ }
99
+
100
+ /* ── Close button ──────────────────────────────── */
101
+
102
+ .hk-alert-close {
103
+ display: flex;
104
+ align-items: center;
105
+ justify-content: center;
106
+ flex-shrink: 0;
107
+ width: 22px;
108
+ height: 22px;
109
+ border: 0;
110
+ background: transparent;
111
+ border-radius: var(--hi-radius-sm, 4px);
112
+ color: var(--hi-color-muted);
113
+ cursor: pointer;
114
+ padding: 0;
115
+ transition: background var(--hi-duration-fast, 0.15s) ease, color var(--hi-duration-fast, 0.15s) ease;
116
+
117
+ &:hover {
118
+ background: var(--hi-color-surface);
119
+ color: var(--hi-color-text-primary);
120
+ }
121
+ }