@celestia-island/hikari 0.4.4 → 0.30.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.
- package/README.md +1 -1
- package/package.json +22 -7
- package/src/DemoApp.tsx +491 -0
- package/src/animation/registerAnimations.test.ts +94 -0
- package/src/animation/registerAnimations.ts +103 -0
- package/src/components/HkAboutModal.scss +95 -0
- package/src/components/HkAboutModal.tsx +114 -0
- package/src/components/HkAdaptiveDialog.scss +22 -0
- package/src/components/HkAdaptiveDialog.test.tsx +271 -0
- package/src/components/HkAdaptiveDialog.tsx +167 -0
- package/src/components/HkAdminHeader.test.tsx +185 -0
- package/src/components/HkAdminHeader.tsx +308 -0
- package/src/components/HkAdminShell.test.tsx +237 -0
- package/src/components/HkAdminShell.tsx +129 -0
- package/src/components/HkAdminTablePage.tsx +70 -0
- package/src/components/HkAdminWidgets.test.ts +89 -0
- package/src/components/HkAlert.tsx +1 -1
- package/src/components/HkAltSignIn.scss +55 -0
- package/src/components/HkAltSignIn.test.tsx +88 -0
- package/src/components/HkAltSignIn.tsx +92 -0
- package/src/components/HkAttachmentModal.scss +49 -0
- package/src/components/HkAttachmentModal.tsx +318 -0
- package/src/components/HkAuthCard.tsx +50 -0
- package/src/components/HkAuthSubmitButton.scss +12 -0
- package/src/components/HkAuthSubmitButton.tsx +94 -0
- package/src/components/HkAvatar.scss +93 -0
- package/src/components/HkAvatar.tsx +2 -2
- package/src/components/HkBlockingToast.scss +123 -0
- package/src/components/HkBlockingToast.test.tsx +221 -0
- package/src/components/HkBlockingToast.tsx +182 -0
- package/src/components/HkBreadcrumb.scss +624 -0
- package/src/components/HkBreadcrumb.tsx +2 -2
- package/src/components/HkButton.scss +16 -2
- package/src/components/HkCaptchaModal.scss +14 -0
- package/src/components/HkCaptchaModal.tsx +62 -0
- package/src/components/HkCaptchaWidget.scss +30 -0
- package/src/components/HkCaptchaWidget.tsx +181 -0
- package/src/components/HkCard.scss +1 -1
- package/src/components/HkChatTypes.ts +65 -0
- package/src/components/HkCheckbox.scss +4 -9
- package/src/components/HkCheckbox.tsx +18 -6
- package/src/components/HkColorPicker.scss +120 -3
- package/src/components/HkColorPicker.tsx +130 -19
- package/src/components/HkColorPickerTouch.test.tsx +145 -0
- package/src/components/HkColorSchemeDialog.scss +52 -0
- package/src/components/HkColorSchemeDialog.test.ts +201 -0
- package/src/components/HkColorSchemeDialog.tsx +96 -0
- package/src/components/HkColorSchemeEditor.test.ts +270 -0
- package/src/components/HkColorSchemeEditor.tsx +410 -0
- package/src/components/HkConfirmDialog.scss +43 -3
- package/src/components/HkConfirmDialog.tsx +7 -4
- package/src/components/HkConnectionInfo.ts +80 -0
- package/src/components/HkConnectionStatus.tsx +158 -0
- package/src/components/HkCookieConsent.scss +22 -0
- package/src/components/HkCookieConsent.test.tsx +70 -0
- package/src/components/HkCookieConsent.tsx +56 -0
- package/src/components/HkCountdownDigit.tsx +105 -0
- package/src/components/HkDatePicker.scss +361 -0
- package/src/components/HkDatePicker.test.ts +459 -0
- package/src/components/HkDatePicker.tsx +568 -0
- package/src/components/HkDateTimePicker.scss +65 -37
- package/src/components/HkDateTimePicker.test.ts +344 -0
- package/src/components/HkDateTimePicker.tsx +249 -82
- package/src/components/HkDraggableGrid.scss +4 -1
- package/src/components/HkDraggableList.scss +4 -1
- package/src/components/HkDrawer.scss +27 -13
- package/src/components/HkDrawer.test.tsx +73 -0
- package/src/components/HkDrawer.tsx +157 -10
- package/src/components/HkErrorBoundary.scss +5 -2
- package/src/components/HkErrorBoundary.tsx +7 -4
- package/src/components/HkExpansionPanel.scss +143 -0
- package/src/components/HkExpansionPanel.test.tsx +109 -0
- package/src/components/HkExpansionPanel.tsx +101 -0
- package/src/components/HkFab.scss +162 -0
- package/src/components/HkFab.test.tsx +217 -0
- package/src/components/HkFab.tsx +214 -0
- package/src/components/HkHoverRevealAction.scss +6 -0
- package/src/components/HkHoverRevealAction.test.ts +68 -0
- package/src/components/HkHoverRevealAction.tsx +84 -6
- package/src/components/HkIcon.scss +123 -0
- package/src/components/HkIcon.tsx +7 -23
- package/src/components/HkIconButton.scss +170 -0
- package/src/components/HkIconButton.test.tsx +75 -0
- package/src/components/HkIconButton.tsx +4 -3
- package/src/components/HkIconButtonVars.scss +180 -0
- package/src/components/HkInput.affix.test.ts +253 -0
- package/src/components/HkInput.enter.test.ts +88 -0
- package/src/components/HkInput.scss +127 -8
- package/src/components/HkInput.tsx +245 -13
- package/src/components/HkKeywordSearchModal.scss +13 -0
- package/src/components/HkKeywordSearchModal.tsx +46 -9
- package/src/components/HkLabel.scss +34 -0
- package/src/components/HkLabel.test.tsx +61 -0
- package/src/components/HkLabel.tsx +45 -0
- package/src/components/HkListTransition.scss +26 -0
- package/src/components/HkListTransition.tsx +57 -0
- package/src/components/HkLocalePicker.scss +37 -0
- package/src/components/HkLocalePicker.tsx +133 -0
- package/src/components/HkLocalePickerPopup.tsx +35 -19
- package/src/components/HkLocalizedInput.scss +277 -0
- package/src/components/HkLocalizedInput.test.tsx +693 -0
- package/src/components/HkLocalizedInput.tsx +495 -0
- package/src/components/HkLogWindow.scss +121 -0
- package/src/components/HkLogWindow.tsx +195 -0
- package/src/components/HkLogo.scss +1 -1
- package/src/components/HkLogo.tsx +1 -1
- package/src/components/HkMarkdownRenderer.scss +22 -2
- package/src/components/HkMarkdownRenderer.tsx +33 -3
- package/src/components/HkMediaControlBar.tsx +20 -13
- package/src/components/HkMenu.scss +200 -0
- package/src/components/HkMenu.test.ts +779 -0
- package/src/components/HkMenu.tsx +770 -0
- package/src/components/HkMenuActionItem.scss +58 -0
- package/src/components/HkMenuActionItem.tsx +41 -0
- package/src/components/HkMenuIdentityItem.scss +70 -0
- package/src/components/HkMenuIdentityItem.tsx +42 -0
- package/src/components/HkMenuPanel.scss +20 -0
- package/src/components/HkMenuPanel.test.tsx +118 -0
- package/src/components/HkMenuPanel.tsx +32 -0
- package/src/components/HkMinimap.tsx +16 -8
- package/src/components/HkModal.autofollow.test.ts +44 -0
- package/src/components/HkModal.scss +170 -53
- package/src/components/HkModal.sheetgap.test.ts +82 -0
- package/src/components/HkModal.test.tsx +334 -0
- package/src/components/HkModal.tsx +314 -68
- package/src/components/HkModalBreadcrumb.scss +4 -1
- package/src/components/HkModalBreadcrumb.test.tsx +111 -0
- package/src/components/HkModalBreadcrumb.tsx +34 -11
- package/src/components/HkModelCatalog.ts +98 -0
- package/src/components/HkModelTag.scss +130 -0
- package/src/components/HkModelTag.test.tsx +111 -0
- package/src/components/HkModelTag.tsx +190 -0
- package/src/components/HkNavItem.scss +13 -2
- package/src/components/HkNavItem.tsx +2 -1
- package/src/components/HkNavSidebar.tsx +99 -0
- package/src/components/HkNumberInput.scss +12 -0
- package/src/components/HkNumberInput.tsx +15 -8
- package/src/components/HkPageHeader.scss +79 -0
- package/src/components/HkPageHeader.test.ts +67 -0
- package/src/components/HkPageHeader.tsx +51 -0
- package/src/components/HkPasswordInput.scss +29 -17
- package/src/components/HkPasswordInput.test.ts +281 -0
- package/src/components/HkPasswordInput.tsx +337 -59
- package/src/components/HkPickerPane.scss +158 -0
- package/src/components/HkPlaceholderMarquee.scss +109 -0
- package/src/components/HkPlaceholderMarquee.test.ts +305 -0
- package/src/components/HkPlaceholderMarquee.tsx +170 -0
- package/src/components/HkPopover.scss +134 -10
- package/src/components/HkPopover.sheetdock.test.ts +34 -0
- package/src/components/HkPopover.surfacevars.test.ts +20 -0
- package/src/components/HkPopover.titleSuppress.test.tsx +265 -0
- package/src/components/HkPopover.tsx +225 -50
- package/src/components/HkPopoverSheet.test.tsx +130 -0
- package/src/components/HkPopupSelect.scss +30 -10
- package/src/components/HkPopupSelect.tsx +21 -1
- package/src/components/HkProgressDialog.scss +31 -0
- package/src/components/HkProgressDialog.tsx +37 -19
- package/src/components/HkProtocolModal.scss +26 -0
- package/src/components/HkProtocolModal.tsx +112 -0
- package/src/components/HkRadio.scss +1 -16
- package/src/components/HkRadio.tsx +5 -2
- package/src/components/HkRichInput.scss +162 -0
- package/src/components/HkRichInput.tsx +335 -0
- package/src/components/HkRollingNumber.test.ts +90 -0
- package/src/components/HkRollingNumber.tsx +39 -1
- package/src/components/HkScrollContainer.scss +71 -54
- package/src/components/HkScrollContainer.test.ts +160 -0
- package/src/components/HkScrollContainer.tsx +187 -160
- package/src/components/HkSearchInput.tsx +3 -3
- package/src/components/HkSecretRevealModal.scss +61 -0
- package/src/components/HkSecretRevealModal.tsx +91 -0
- package/src/components/HkSelect.scss +263 -12
- package/src/components/HkSelect.sheetdock.test.ts +30 -0
- package/src/components/HkSelect.test.tsx +88 -0
- package/src/components/HkSelect.tsx +59 -74
- package/src/components/HkSelectPanel.test.tsx +666 -0
- package/src/components/HkSelectPanel.tsx +595 -0
- package/src/components/HkSelectSheet.test.tsx +132 -0
- package/src/components/HkSelectionGrid.scss +1 -1
- package/src/components/HkSelectionGrid.tsx +2 -1
- package/src/components/HkSelectionWaterfall.scss +1 -1
- package/src/components/HkShareBar.scss +40 -0
- package/src/components/HkShareBar.tsx +50 -0
- package/src/components/HkSidebar.scss +15 -10
- package/src/components/HkSidebar.tsx +26 -2
- package/src/components/HkSignInCard.test.ts +154 -0
- package/src/components/HkSignInCard.tsx +155 -0
- package/src/components/HkSlider.scss +99 -0
- package/src/components/HkSlider.test.tsx +155 -0
- package/src/components/HkSlider.tsx +173 -0
- package/src/components/HkSpinner.scss +36 -1
- package/src/components/HkSpinner.test.tsx +63 -0
- package/src/components/HkSpinner.tsx +16 -1
- package/src/components/HkSplash.scss +1 -1
- package/src/components/HkSplash.tsx +3 -1
- package/src/components/HkStatCard.scss +73 -0
- package/src/components/HkStatCard.tsx +46 -0
- package/src/components/HkStatusBar.test.tsx +178 -0
- package/src/components/HkStatusBar.tsx +379 -0
- package/src/components/HkStatusPill.scss +73 -0
- package/src/components/HkStatusPill.tsx +41 -0
- package/src/components/HkStepFlow.scss +75 -0
- package/src/components/HkStepFlow.test.tsx +246 -0
- package/src/components/HkStepFlow.tsx +115 -0
- package/src/components/HkSwitch.scss +5 -17
- package/src/components/HkSwitch.tsx +6 -3
- package/src/components/HkTable.scss +20 -1
- package/src/components/HkTable.tsx +28 -3
- package/src/components/HkTabs.scss +222 -48
- package/src/components/HkTabs.test.ts +517 -0
- package/src/components/HkTabs.tsx +567 -56
- package/src/components/HkTag.tsx +2 -1
- package/src/components/HkTextarea.tsx +5 -0
- package/src/components/HkThemeToggle.scss +232 -0
- package/src/components/HkThemeToggle.test.ts +231 -0
- package/src/components/HkThemeToggle.tsx +289 -0
- package/src/components/HkTimeline.scss +134 -1
- package/src/components/HkTimeline.test.tsx +319 -0
- package/src/components/HkTimeline.tsx +303 -54
- package/src/components/HkToast.scss +34 -5
- package/src/components/HkToast.test.tsx +109 -0
- package/src/components/HkToast.tsx +57 -8
- package/src/components/HkTokenUsageBadge.scss +53 -0
- package/src/components/HkTokenUsageBadge.test.tsx +59 -0
- package/src/components/HkTokenUsageBadge.tsx +54 -0
- package/src/components/HkTokenUsagePanel.scss +95 -0
- package/src/components/HkTokenUsagePanel.tsx +140 -0
- package/src/components/HkToolBlock.scss +428 -0
- package/src/components/HkToolBlock.tsx +639 -0
- package/src/components/HkTooltip.scss +14 -2
- package/src/components/HkTooltip.tsx +25 -2
- package/src/components/HkTrendChart.tsx +27 -16
- package/src/components/HkVoiceInputPopup.scss +77 -0
- package/src/components/HkVoiceInputPopup.tsx +97 -0
- package/src/components/HkZoomToolbar.scss +4 -1
- package/src/components/HkZoomToolbar.tsx +7 -4
- package/src/components/_hikari-vars.scss +6 -0
- package/src/composables/highlightLanguages.ts +109 -0
- package/src/composables/iconRegistry.ts +127 -0
- package/src/composables/messaging/browserTransport.ts +96 -0
- package/src/composables/messaging/index.ts +204 -0
- package/src/composables/messaging/messaging.test.ts +256 -0
- package/src/composables/messaging/toastTransport.ts +26 -0
- package/src/composables/messaging/types.ts +115 -0
- package/src/composables/useActionBar.ts +66 -0
- package/src/composables/useAttachments.ts +154 -0
- package/src/composables/useConnectionProbe.ts +142 -0
- package/src/composables/useDeferredTransition.ts +16 -0
- package/src/composables/useEngineHealth.ts +69 -0
- package/src/composables/useHighlight.ts +124 -0
- package/src/composables/useMeasuredHighlight.ts +150 -0
- package/src/composables/useOverlayScrollbar.test.ts +221 -0
- package/src/composables/useOverlayScrollbar.ts +296 -0
- package/src/composables/usePageTitle.ts +37 -0
- package/src/composables/useReducedMotion.ts +34 -0
- package/src/composables/useResourceListModal.tsx +147 -0
- package/src/composables/useSafeArea.ts +137 -0
- package/src/composables/useSendShortcut.ts +35 -0
- package/src/composables/useSizeMorph.test.ts +156 -0
- package/src/composables/useSizeMorph.ts +149 -0
- package/src/composables/useSurfaceTransition.test.ts +96 -0
- package/src/composables/useSurfaceTransition.ts +71 -0
- package/src/composables/useZoomPan.ts +192 -0
- package/src/demo.scss +9 -1
- package/src/demo.ts +5 -1
- package/src/i18n/locales/ar/chat.json +38 -0
- package/src/i18n/locales/ar/components.json +141 -40
- package/src/i18n/locales/ar/components.toml +59 -0
- package/src/i18n/locales/ar/platform.json +65 -0
- package/src/i18n/locales/de/chat.json +38 -0
- package/src/i18n/locales/de/components.json +139 -38
- package/src/i18n/locales/de/components.toml +59 -0
- package/src/i18n/locales/de/platform.json +65 -0
- package/src/i18n/locales/en/chat.json +38 -0
- package/src/i18n/locales/en/components.json +104 -3
- package/src/i18n/locales/en/components.toml +59 -0
- package/src/i18n/locales/en/platform.json +65 -0
- package/src/i18n/locales/es/chat.json +38 -0
- package/src/i18n/locales/es/components.json +141 -40
- package/src/i18n/locales/es/components.toml +59 -0
- package/src/i18n/locales/es/platform.json +65 -0
- package/src/i18n/locales/fr/chat.json +38 -0
- package/src/i18n/locales/fr/components.json +137 -36
- package/src/i18n/locales/fr/components.toml +59 -0
- package/src/i18n/locales/fr/platform.json +65 -0
- package/src/i18n/locales/ja/chat.json +38 -0
- package/src/i18n/locales/ja/components.json +104 -3
- package/src/i18n/locales/ja/components.toml +59 -0
- package/src/i18n/locales/ja/platform.json +65 -0
- package/src/i18n/locales/ko/chat.json +38 -0
- package/src/i18n/locales/ko/components.json +104 -3
- package/src/i18n/locales/ko/components.toml +59 -0
- package/src/i18n/locales/ko/platform.json +65 -0
- package/src/i18n/locales/pt/chat.json +38 -0
- package/src/i18n/locales/pt/components.json +141 -40
- package/src/i18n/locales/pt/components.toml +59 -0
- package/src/i18n/locales/pt/platform.json +65 -0
- package/src/i18n/locales/ru/chat.json +38 -0
- package/src/i18n/locales/ru/components.json +141 -40
- package/src/i18n/locales/ru/components.toml +59 -0
- package/src/i18n/locales/ru/platform.json +65 -0
- package/src/i18n/locales/zh-Hans/chat.json +38 -0
- package/src/i18n/locales/zh-Hans/components.json +109 -4
- package/src/i18n/locales/zh-Hans/components.toml +59 -0
- package/src/i18n/locales/zh-Hans/platform.json +65 -0
- package/src/i18n/locales/zh-Hant/chat.json +38 -0
- package/src/i18n/locales/zh-Hant/components.json +109 -4
- package/src/i18n/locales/zh-Hant/components.toml +59 -0
- package/src/i18n/locales/zh-Hant/platform.json +65 -0
- package/src/index.ts +225 -6
- package/src/plugins/bootScriptsPlugin.ts +47 -0
- package/src/plugins/buildHashPlugin.ts +67 -0
- package/src/plugins/index.ts +2 -0
- package/src/render.ts +1 -1
- package/src/runtime/animationBus.test.ts +112 -0
- package/src/runtime/animationBus.ts +33 -2
- package/src/runtime/backStack.test.ts +334 -0
- package/src/runtime/backStack.ts +377 -0
- package/src/runtime/env.ts +4 -0
- package/src/runtime/index.ts +15 -3
- package/src/runtime/intervalBus.test.ts +118 -0
- package/src/runtime/intervalBus.ts +189 -0
- package/src/runtime/mobileViewport.test.ts +132 -0
- package/src/runtime/mobileViewport.ts +157 -0
- package/src/runtime/pageLifecycle.ts +91 -0
- package/src/runtime/useBlockingToast.ts +112 -0
- package/src/runtime/useClipboard.ts +28 -0
- package/src/runtime/useConfirm.ts +15 -7
- package/src/runtime/useMediaQuery.test.ts +67 -0
- package/src/runtime/useMediaQuery.ts +89 -0
- package/src/runtime/useOverlay.test.ts +160 -0
- package/src/runtime/useOverlay.ts +59 -12
- package/src/runtime/usePopupManager.test.ts +200 -0
- package/src/runtime/usePopupManager.ts +106 -10
- package/src/runtime/useToast.test.ts +90 -0
- package/src/runtime/useToast.ts +20 -2
- package/src/styles/admin-tokens.scss +744 -0
- package/src/styles/index.scss +5 -3
- package/src/styles/theme/_glass.scss +33 -0
- package/src/styles/theme/_layout.scss +123 -0
- package/src/styles/theme/_scrollbar.scss +73 -0
- package/src/styles/theme/_tokens.scss +69 -0
- package/src/styles/theme/base.scss +617 -0
- package/src/styles/theme/foundation.scss +219 -0
- package/src/styles/theme/mixins.scss +793 -0
- package/src/styles/theme/themes.scss +25 -0
- package/src/styles/theme/variables.scss +125 -0
- package/src/theme/_field.scss +116 -0
- package/src/theme/fontContext.test.ts +179 -0
- package/src/theme/fontContext.ts +169 -0
- package/src/theme/index.ts +19 -2
- package/src/theme/presets.ts +86 -18
- package/src/theme/theme.scss +61 -1
- package/src/theme/tokenGroups.test.ts +534 -0
- package/src/theme/tokenGroups.ts +552 -0
- package/src/theme/useSolarTime.test.ts +113 -0
- package/src/theme/useSolarTime.ts +95 -20
- package/src/theme/useTheme.test.ts +72 -0
- package/src/theme/useTheme.ts +144 -9
- package/src/tokens.scss +110 -0
- package/src/utils/base64.ts +31 -0
- package/src/utils/connectivity.ts +51 -0
- package/src/utils/dom.test.ts +131 -0
- package/src/utils/dom.ts +133 -0
- package/src/utils/download.ts +22 -0
- package/src/utils/fileType.ts +127 -0
- package/src/utils/format.ts +98 -0
- package/src/utils/fuzzy.ts +77 -0
- package/src/utils/fuzzySearch.test.ts +87 -0
- package/src/utils/healthProbe.ts +64 -0
- package/src/utils/objectPath.ts +59 -0
- package/src/utils/password.ts +53 -0
- package/src/utils/pow.test.ts +45 -0
- package/src/utils/pow.ts +226 -0
- package/src/utils/powNonce.ts +95 -0
- package/src/utils/validation.test.ts +78 -0
- package/src/DemoApp.vue +0 -400
- package/src/components/HkCollapse.tsx +0 -48
- package/src/components/HkMorphingTabs.scss +0 -141
- package/src/components/HkMorphingTabs.tsx +0 -113
- package/src/composables/useBreakpoint.ts +0 -41
- package/src/composables/useClipboard.ts +0 -37
- package/src/composables/useConfirm.ts +0 -35
- package/src/composables/useToast.ts +0 -2
- package/src/runtime/useAsyncData.ts +0 -30
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { defineComponent, type PropType } from "vue";
|
|
2
|
+
import { HModal } from "@celestia-island/hikari";
|
|
3
|
+
|
|
4
|
+
import { useI18n } from "../i18n/context";
|
|
5
|
+
|
|
6
|
+
import { HkCaptchaWidget, type HkCaptchaProvider } from "./HkCaptchaWidget";
|
|
7
|
+
import "./HkCaptchaModal.scss";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* HkCaptchaModal — modal host for HkCaptchaWidget.
|
|
11
|
+
* (Upstreamed from shittim-chest's plana-legacy layer.)
|
|
12
|
+
*
|
|
13
|
+
* Opens on demand (at submit time), renders the provider widget, and emits
|
|
14
|
+
* the verification token once the challenge succeeds. Closes itself when
|
|
15
|
+
* the provider reports an error so the caller can surface its own message.
|
|
16
|
+
*/
|
|
17
|
+
export const HkCaptchaModal = defineComponent({
|
|
18
|
+
name: "HkCaptchaModal",
|
|
19
|
+
props: {
|
|
20
|
+
modelValue: { type: Boolean, default: false },
|
|
21
|
+
siteKey: { type: String, required: true },
|
|
22
|
+
provider: { type: String as PropType<HkCaptchaProvider>, default: "turnstile" },
|
|
23
|
+
scriptUrl: { type: String, default: undefined },
|
|
24
|
+
attempt: { type: Number, default: 0 },
|
|
25
|
+
title: { type: String, default: undefined },
|
|
26
|
+
width: { type: String, default: "30rem" },
|
|
27
|
+
},
|
|
28
|
+
emits: {
|
|
29
|
+
"update:modelValue": (_v: boolean) => true,
|
|
30
|
+
verify: (_token: string) => true,
|
|
31
|
+
error: (_message: string) => true,
|
|
32
|
+
},
|
|
33
|
+
setup(props, { emit }) {
|
|
34
|
+
const { t } = useI18n();
|
|
35
|
+
|
|
36
|
+
return () => (
|
|
37
|
+
<HModal
|
|
38
|
+
modelValue={props.modelValue}
|
|
39
|
+
onUpdate:modelValue={(v: boolean) => emit("update:modelValue", v)}
|
|
40
|
+
title={props.title ?? t("hikari::captcha.title", "Security check")}
|
|
41
|
+
width={props.width}
|
|
42
|
+
>
|
|
43
|
+
<div class="s-captcha-modal">
|
|
44
|
+
<p class="s-captcha-modal-prompt">{t("hikari::captcha.prompt", "Complete the verification below to continue.")}</p>
|
|
45
|
+
{props.modelValue && (
|
|
46
|
+
<HkCaptchaWidget
|
|
47
|
+
siteKey={props.siteKey}
|
|
48
|
+
provider={props.provider}
|
|
49
|
+
scriptUrl={props.scriptUrl}
|
|
50
|
+
attempt={props.attempt}
|
|
51
|
+
onVerify={(token: string) => emit("verify", token)}
|
|
52
|
+
onError={(message: string) => {
|
|
53
|
+
emit("error", message);
|
|
54
|
+
emit("update:modelValue", false);
|
|
55
|
+
}}
|
|
56
|
+
/>
|
|
57
|
+
)}
|
|
58
|
+
</div>
|
|
59
|
+
</HModal>
|
|
60
|
+
);
|
|
61
|
+
},
|
|
62
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
.s-captcha-widget {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
align-items: center;
|
|
5
|
+
gap: var(--space-8, 0.5rem);
|
|
6
|
+
min-height: 4rem;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.s-captcha-widget-loading {
|
|
10
|
+
margin: 0;
|
|
11
|
+
font-size: var(--text-xs, 0.75rem);
|
|
12
|
+
color: rgb(var(--color-muted));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.s-captcha-widget-host {
|
|
16
|
+
display: flex;
|
|
17
|
+
justify-content: center;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.s-captcha-widget-placeholder {
|
|
21
|
+
justify-content: center;
|
|
22
|
+
min-height: 4rem;
|
|
23
|
+
padding: var(--space-16, 1rem);
|
|
24
|
+
border: 1px dashed var(--border-faint, rgb(var(--color-border) / 15%));
|
|
25
|
+
border-radius: var(--radius-md, 8px);
|
|
26
|
+
color: rgb(var(--color-muted));
|
|
27
|
+
font-size: var(--text-xs, 0.75rem);
|
|
28
|
+
text-align: center;
|
|
29
|
+
max-width: 22rem;
|
|
30
|
+
}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { computed, defineComponent, onBeforeUnmount, onMounted, ref, watch, type PropType } from "vue";
|
|
2
|
+
import { ShieldAlert } from "lucide-vue-next";
|
|
3
|
+
|
|
4
|
+
import { useI18n } from "../i18n/context";
|
|
5
|
+
|
|
6
|
+
import "./HkCaptchaWidget.scss";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* HkCaptchaWidget — provider-agnostic silent-captcha widget.
|
|
10
|
+
* (Upstreamed from shittim-chest's plana-legacy layer.)
|
|
11
|
+
*
|
|
12
|
+
* Renders a third-party captcha widget (Cloudflare Turnstile or Google
|
|
13
|
+
* reCAPTCHA protocol) and emits the verification token once the challenge
|
|
14
|
+
* succeeds. The provider CDN script is loaded lazily, only once per URL,
|
|
15
|
+
* and never bundled locally.
|
|
16
|
+
*
|
|
17
|
+
* Provider-agnostic contract:
|
|
18
|
+
* - `provider: "turnstile" | "recaptcha"` selects the render protocol.
|
|
19
|
+
* - `scriptUrl` overrides the official CDN URL (defaults per provider),
|
|
20
|
+
* so any platform compatible with one of those protocols — including a
|
|
21
|
+
* self-hosted one — works by pointing `scriptUrl` at it.
|
|
22
|
+
* - No-op placeholder mode: when `siteKey` is empty (or `disabled` is
|
|
23
|
+
* true) the widget renders a placeholder box and emits nothing. This
|
|
24
|
+
* lets deployments ship without a captcha provider; wire a real
|
|
25
|
+
* `siteKey`/`scriptUrl` per deployment to enable verification.
|
|
26
|
+
*
|
|
27
|
+
* Tokens are single-use; bump `attempt` (e.g. after a failed submit) to
|
|
28
|
+
* force a reset so a fresh token is produced.
|
|
29
|
+
*/
|
|
30
|
+
export type HkCaptchaProvider = "turnstile" | "recaptcha";
|
|
31
|
+
|
|
32
|
+
const DEFAULT_SCRIPT_URLS: Record<HkCaptchaProvider, string> = {
|
|
33
|
+
turnstile: "https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit",
|
|
34
|
+
recaptcha: "https://www.google.com/recaptcha/api.js?render=explicit",
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const SCRIPT_LOADERS: Record<string, Promise<unknown> | undefined> = {};
|
|
38
|
+
|
|
39
|
+
function loadScript(src: string): Promise<unknown> {
|
|
40
|
+
if (SCRIPT_LOADERS[src]) return SCRIPT_LOADERS[src];
|
|
41
|
+
SCRIPT_LOADERS[src] = new Promise((resolve, reject) => {
|
|
42
|
+
const el = document.createElement("script");
|
|
43
|
+
el.src = src;
|
|
44
|
+
el.async = true;
|
|
45
|
+
el.defer = true;
|
|
46
|
+
el.onload = () => resolve(undefined);
|
|
47
|
+
el.onerror = () => {
|
|
48
|
+
delete SCRIPT_LOADERS[src];
|
|
49
|
+
reject(new Error(`failed to load ${src}`));
|
|
50
|
+
};
|
|
51
|
+
document.head.appendChild(el);
|
|
52
|
+
});
|
|
53
|
+
return SCRIPT_LOADERS[src];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
type TurnstileApi = {
|
|
57
|
+
render: (el: HTMLElement, opts: Record<string, unknown>) => string;
|
|
58
|
+
reset: (id?: string) => void;
|
|
59
|
+
remove: (id: string) => void;
|
|
60
|
+
};
|
|
61
|
+
type GrecaptchaApi = {
|
|
62
|
+
ready: (cb: () => void) => void;
|
|
63
|
+
render: (el: HTMLElement, opts: Record<string, unknown>) => number;
|
|
64
|
+
reset: (id?: number) => void;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
function getGlobal(name: string): unknown {
|
|
68
|
+
return (window as unknown as Record<string, unknown>)[name];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export const HkCaptchaWidget = defineComponent({
|
|
72
|
+
name: "HkCaptchaWidget",
|
|
73
|
+
props: {
|
|
74
|
+
/** Site key issued by the provider (empty = placeholder/no-op mode). */
|
|
75
|
+
siteKey: { type: String, required: true },
|
|
76
|
+
/** Provider protocol: "turnstile" (default) or "recaptcha". */
|
|
77
|
+
provider: { type: String as PropType<HkCaptchaProvider>, default: "turnstile" },
|
|
78
|
+
/** CDN script URL override (defaults to the official provider URL). */
|
|
79
|
+
scriptUrl: { type: String, default: undefined },
|
|
80
|
+
/** Bump to force a token refresh (e.g. after a failed submit). */
|
|
81
|
+
attempt: { type: Number, default: 0 },
|
|
82
|
+
/** Disables rendering and enters no-op placeholder mode. */
|
|
83
|
+
disabled: { type: Boolean, default: false },
|
|
84
|
+
},
|
|
85
|
+
emits: {
|
|
86
|
+
verify: (_token: string) => true,
|
|
87
|
+
error: (_message: string) => true,
|
|
88
|
+
},
|
|
89
|
+
setup(props, { emit }) {
|
|
90
|
+
const { t } = useI18n();
|
|
91
|
+
const container = ref<HTMLElement>();
|
|
92
|
+
const loading = ref(false);
|
|
93
|
+
let widgetId: string | number | null = null;
|
|
94
|
+
|
|
95
|
+
const placeholder = computed(() => !props.siteKey || props.disabled);
|
|
96
|
+
|
|
97
|
+
function reset() {
|
|
98
|
+
if (widgetId == null) return;
|
|
99
|
+
if (props.provider === "turnstile") {
|
|
100
|
+
(getGlobal("turnstile") as TurnstileApi | undefined)?.reset(widgetId as string);
|
|
101
|
+
} else {
|
|
102
|
+
(getGlobal("grecaptcha") as GrecaptchaApi | undefined)?.reset(widgetId as number);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async function render() {
|
|
107
|
+
if (!container.value || placeholder.value) return;
|
|
108
|
+
const onToken = (token: string) => emit("verify", token);
|
|
109
|
+
|
|
110
|
+
loading.value = true;
|
|
111
|
+
try {
|
|
112
|
+
const src = props.scriptUrl || DEFAULT_SCRIPT_URLS[props.provider];
|
|
113
|
+
// An unknown provider string (config-driven value, typo) makes the
|
|
114
|
+
// lookup above return undefined — and `el.src = undefined` coerces
|
|
115
|
+
// to the literal "undefined", so the browser fetches
|
|
116
|
+
// `<origin>/undefined` and the widget reports a bogus load failure.
|
|
117
|
+
// Fail loudly with the provider name instead.
|
|
118
|
+
if (!src) {
|
|
119
|
+
throw new Error(
|
|
120
|
+
`no script URL for captcha provider "${props.provider}" (expected "${Object.keys(DEFAULT_SCRIPT_URLS).join('" | "')}")`,
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
if (props.provider === "turnstile") {
|
|
124
|
+
await loadScript(src);
|
|
125
|
+
const api = getGlobal("turnstile") as TurnstileApi | undefined;
|
|
126
|
+
if (!api) throw new Error("turnstile not available");
|
|
127
|
+
widgetId = api.render(container.value, {
|
|
128
|
+
sitekey: props.siteKey,
|
|
129
|
+
callback: onToken,
|
|
130
|
+
"error-callback": () => emit("error", "turnstile error"),
|
|
131
|
+
});
|
|
132
|
+
} else {
|
|
133
|
+
await loadScript(src);
|
|
134
|
+
const api = getGlobal("grecaptcha") as GrecaptchaApi | undefined;
|
|
135
|
+
if (!api) throw new Error("grecaptcha not available");
|
|
136
|
+
await new Promise<void>((resolve) => api.ready(() => resolve()));
|
|
137
|
+
widgetId = api.render(container.value, {
|
|
138
|
+
sitekey: props.siteKey,
|
|
139
|
+
callback: onToken,
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
} catch (e) {
|
|
143
|
+
emit("error", e instanceof Error ? e.message : String(e));
|
|
144
|
+
} finally {
|
|
145
|
+
loading.value = false;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
onMounted(render);
|
|
150
|
+
watch(
|
|
151
|
+
() => props.attempt,
|
|
152
|
+
() => {
|
|
153
|
+
if (widgetId != null) reset();
|
|
154
|
+
},
|
|
155
|
+
);
|
|
156
|
+
onBeforeUnmount(() => {
|
|
157
|
+
if (widgetId == null) return;
|
|
158
|
+
if (props.provider === "turnstile") {
|
|
159
|
+
(getGlobal("turnstile") as TurnstileApi | undefined)?.remove(widgetId as string);
|
|
160
|
+
}
|
|
161
|
+
widgetId = null;
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
return () => {
|
|
165
|
+
if (placeholder.value) {
|
|
166
|
+
return (
|
|
167
|
+
<div class="s-captcha-widget s-captcha-widget-placeholder">
|
|
168
|
+
<ShieldAlert size={16} />
|
|
169
|
+
<span>{t("hikari::captcha.placeholder", "Verification is not configured for this deployment (no site key provided).")}</span>
|
|
170
|
+
</div>
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
return (
|
|
174
|
+
<div class="s-captcha-widget">
|
|
175
|
+
{loading.value && <p class="s-captcha-widget-loading">{t("hikari::captcha.loading", "Loading verification widget…")}</p>}
|
|
176
|
+
<div ref={container} class="s-captcha-widget-host" />
|
|
177
|
+
</div>
|
|
178
|
+
);
|
|
179
|
+
};
|
|
180
|
+
},
|
|
181
|
+
});
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
.hk-card {
|
|
7
7
|
display: block;
|
|
8
8
|
overflow: hidden;
|
|
9
|
-
background: rgb(var(--color-surface)
|
|
9
|
+
background: color-mix(in srgb, rgb(var(--color-surface)) 70%, transparent);
|
|
10
10
|
backdrop-filter: blur(var(--blur-md));
|
|
11
11
|
border: 1px solid var(--border-subtle);
|
|
12
12
|
border-radius: var(--radius-md);
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared chat/LLM types for the hikari chat kit.
|
|
3
|
+
* (Upstreamed from shittim-chest's plana-legacy layer.)
|
|
4
|
+
*
|
|
5
|
+
* Deliberately dependency-light: plain data shapes only, so any service
|
|
6
|
+
* (arona, shittim-chest, …) can map its own store onto these props
|
|
7
|
+
* without importing provider internals.
|
|
8
|
+
*
|
|
9
|
+
* The attachment shapes already live on HkAttachmentModal (upstreamed in
|
|
10
|
+
* an earlier wave) and are re-exported here so this module mirrors the
|
|
11
|
+
* old PlanaChatTypes surface — import everything chat-related from here.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/** Message role — drives bubble alignment and tinting. */
|
|
15
|
+
export type HChatRole = "user" | "assistant";
|
|
16
|
+
|
|
17
|
+
/** Lifecycle of a tool call block. */
|
|
18
|
+
export type HToolCallStatus = "pending" | "running" | "done" | "error";
|
|
19
|
+
|
|
20
|
+
/** Tool call payload rendered by HkToolBlock (also nested in chat messages). */
|
|
21
|
+
export interface HToolCall {
|
|
22
|
+
id?: string;
|
|
23
|
+
toolName: string;
|
|
24
|
+
agentType?: string;
|
|
25
|
+
status: HToolCallStatus;
|
|
26
|
+
callText?: string;
|
|
27
|
+
resultText?: string;
|
|
28
|
+
durationMs?: number;
|
|
29
|
+
defaultExpanded?: boolean;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Voice popup phase — see HkVoiceInputPopup. */
|
|
33
|
+
export type HVoicePopupMode = "notConfigured" | "listening" | "transcribing";
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Voice state fed by the parent (e.g. from a voice-input composable).
|
|
37
|
+
* `open` + `mode` drive the anchored HkVoiceInputPopup; `transcribing`
|
|
38
|
+
* disables the mic button while recognition is running.
|
|
39
|
+
*/
|
|
40
|
+
export interface HVoiceState {
|
|
41
|
+
open: boolean;
|
|
42
|
+
mode: HVoicePopupMode;
|
|
43
|
+
transcribing?: boolean;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** One model row in the HkTokenUsagePanel per-model breakdown. */
|
|
47
|
+
export interface HModelUsageEntry {
|
|
48
|
+
model: string;
|
|
49
|
+
tokenCount: number;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Read-only cost inputs for HkTokenUsagePanel (USD amounts). */
|
|
53
|
+
export interface HModelCosts {
|
|
54
|
+
prompt: number;
|
|
55
|
+
completion: number;
|
|
56
|
+
cached?: number;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Attachment shapes (defined by HkAttachmentModal since the first
|
|
60
|
+
// chat-kit wave) — re-exported, not redefined.
|
|
61
|
+
export type {
|
|
62
|
+
HAttachmentDetail,
|
|
63
|
+
HAttachmentItem,
|
|
64
|
+
HAttachmentPreviewType,
|
|
65
|
+
} from "./HkAttachmentModal";
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
.hk-checkbox-box[data-checked] {
|
|
41
41
|
background: var(--hi-color-primary, #ff6b9d);
|
|
42
42
|
border-color: var(--hi-color-primary, #ff6b9d);
|
|
43
|
-
color: var(--
|
|
43
|
+
color: rgb(var(--color-on-solid-text, 255 255 255));
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
.hk-checkbox-box[data-indeterminate] {
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
.hk-checkbox-icon {
|
|
70
70
|
position: relative;
|
|
71
71
|
z-index: var(--hi-z-above, 1);
|
|
72
|
-
color: var(--
|
|
72
|
+
color: rgb(var(--color-on-solid-icon, 255 255 255));
|
|
73
73
|
width: 14px;
|
|
74
74
|
height: 14px;
|
|
75
75
|
}
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
width: 6px;
|
|
79
79
|
height: 6px;
|
|
80
80
|
border-radius: 50%;
|
|
81
|
-
background: var(--
|
|
81
|
+
background: rgb(var(--color-on-solid-icon, 255 255 255));
|
|
82
82
|
z-index: var(--hi-z-above, 1);
|
|
83
83
|
}
|
|
84
84
|
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
width: 8px;
|
|
87
87
|
height: 2px;
|
|
88
88
|
border-radius: 1px;
|
|
89
|
-
background: var(--
|
|
89
|
+
background: rgb(var(--color-on-solid-icon, 255 255 255));
|
|
90
90
|
z-index: var(--hi-z-above, 1);
|
|
91
91
|
}
|
|
92
92
|
|
|
@@ -95,8 +95,3 @@
|
|
|
95
95
|
.hk-checkbox[data-animating] .hk-checkbox-box {
|
|
96
96
|
will-change: border-color, background;
|
|
97
97
|
}
|
|
98
|
-
|
|
99
|
-
.hk-checkbox-label-text {
|
|
100
|
-
font-size: var(--hi-text-sm, 0.8125rem);
|
|
101
|
-
color: var(--hi-color-text-primary, #333);
|
|
102
|
-
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import { defineComponent, ref, type PropType } from "vue";
|
|
2
1
|
import { Check } from "lucide-vue-next";
|
|
2
|
+
import { defineComponent, onUnmounted, ref, type PropType } from "vue";
|
|
3
|
+
|
|
4
|
+
import { scheduleCronAfter, type CronHandle } from "../runtime/cronBus";
|
|
5
|
+
import HkLabel from "./HkLabel";
|
|
3
6
|
import "./HkCheckbox.scss";
|
|
4
7
|
|
|
5
8
|
export default defineComponent({
|
|
@@ -22,12 +25,16 @@ export default defineComponent({
|
|
|
22
25
|
},
|
|
23
26
|
setup(props, { emit, slots }) {
|
|
24
27
|
const animating = ref(false);
|
|
25
|
-
let animTimer:
|
|
28
|
+
let animTimer: CronHandle | null = null;
|
|
26
29
|
|
|
27
30
|
function markActive() {
|
|
28
31
|
animating.value = true;
|
|
29
|
-
|
|
30
|
-
|
|
32
|
+
// cronBus one-shot (not the rAF-driven animationBus one): the
|
|
33
|
+
// flag must always clear, even while the animation bus is parked
|
|
34
|
+
// under reduced motion.
|
|
35
|
+
animTimer?.disconnect();
|
|
36
|
+
animTimer = scheduleCronAfter(() => {
|
|
37
|
+
animTimer = null;
|
|
31
38
|
animating.value = false;
|
|
32
39
|
}, 300);
|
|
33
40
|
}
|
|
@@ -38,6 +45,11 @@ export default defineComponent({
|
|
|
38
45
|
markActive();
|
|
39
46
|
}
|
|
40
47
|
|
|
48
|
+
onUnmounted(() => {
|
|
49
|
+
animTimer?.disconnect();
|
|
50
|
+
animTimer = null;
|
|
51
|
+
});
|
|
52
|
+
|
|
41
53
|
return () => {
|
|
42
54
|
const inputType = props.type === "radio" ? "radio" : "checkbox";
|
|
43
55
|
const isChecked = props.modelValue === true || props.modelValue === null;
|
|
@@ -74,9 +86,9 @@ export default defineComponent({
|
|
|
74
86
|
) : null}
|
|
75
87
|
</span>
|
|
76
88
|
{props.label || slots.default ? (
|
|
77
|
-
<
|
|
89
|
+
<HkLabel size={props.size}>
|
|
78
90
|
{slots.default?.() ?? props.label}
|
|
79
|
-
</
|
|
91
|
+
</HkLabel>
|
|
80
92
|
) : null}
|
|
81
93
|
</label>
|
|
82
94
|
);
|
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
.hk-color-picker {
|
|
2
2
|
display: inline-flex;
|
|
3
|
+
min-width: 0;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
// Row layout — dense grids that must show full color names: swatch left,
|
|
7
|
+
// single-line label right, ellipsis when the name outgrows the cell.
|
|
8
|
+
// Grid/flex children sizing needs min-width: 0 on every ancestor to let
|
|
9
|
+
// text-overflow actually engage.
|
|
10
|
+
.hk-color-picker[data-layout="row"] {
|
|
11
|
+
.hk-color-picker-swatch-btn {
|
|
12
|
+
flex-direction: row;
|
|
13
|
+
align-items: center;
|
|
14
|
+
gap: var(--space-8);
|
|
15
|
+
width: 100%;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.hk-color-picker-swatch {
|
|
19
|
+
width: 18px;
|
|
20
|
+
height: 18px;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.hk-color-picker-label {
|
|
24
|
+
margin-bottom: 0;
|
|
25
|
+
min-width: 0;
|
|
26
|
+
max-width: 100%;
|
|
27
|
+
overflow: hidden;
|
|
28
|
+
text-overflow: ellipsis;
|
|
29
|
+
text-align: left;
|
|
30
|
+
}
|
|
3
31
|
}
|
|
4
32
|
|
|
5
33
|
.hk-color-picker-trigger {
|
|
@@ -33,9 +61,12 @@
|
|
|
33
61
|
}
|
|
34
62
|
|
|
35
63
|
.hk-color-picker-label {
|
|
64
|
+
display: block;
|
|
36
65
|
font-size: var(--text-xs);
|
|
37
|
-
font-weight:
|
|
38
|
-
|
|
66
|
+
font-weight: 600;
|
|
67
|
+
letter-spacing: 0.02em;
|
|
68
|
+
margin-bottom: var(--space-4);
|
|
69
|
+
color: rgb(var(--color-text) / var(--hk-field-label-alpha, 72%));
|
|
39
70
|
white-space: nowrap;
|
|
40
71
|
line-height: 1;
|
|
41
72
|
transition: color var(--duration-short);
|
|
@@ -106,9 +137,25 @@
|
|
|
106
137
|
display: block;
|
|
107
138
|
overflow: hidden;
|
|
108
139
|
box-shadow: inset 0 0 0 1px rgb(0 0 0 / 10%);
|
|
140
|
+
// Explicit on the hit targets too (not only the container): touch-action
|
|
141
|
+
// resolves against the touched element's ancestor chain, and spelling it
|
|
142
|
+
// out on track+thumb removes any hit-target ambiguity on mobile.
|
|
143
|
+
touch-action: none;
|
|
109
144
|
}
|
|
110
145
|
|
|
111
146
|
.hk-color-picker-slider-thumb {
|
|
147
|
+
// Absolute INSIDE the slider container (the track is the only in-flow
|
|
148
|
+
// flex child and spans the full width, so `left: N%` of the container
|
|
149
|
+
// is N% of the track). Without this the thumb was a static flex item:
|
|
150
|
+
// the inline `left` from HkColorPicker.tsx is ignored on static
|
|
151
|
+
// elements and the thumb sat parked after the flex:1 track at the
|
|
152
|
+
// right edge on every layout, never following the value.
|
|
153
|
+
position: absolute;
|
|
154
|
+
top: 50%;
|
|
155
|
+
left: 0;
|
|
156
|
+
// Center the thumb ON the value point; hover scale must extend (not
|
|
157
|
+
// replace) this transform or the thumb would jump back half its size.
|
|
158
|
+
transform: translate(-50%, -50%);
|
|
112
159
|
display: block;
|
|
113
160
|
width: 14px;
|
|
114
161
|
height: 14px;
|
|
@@ -119,8 +166,10 @@
|
|
|
119
166
|
cursor: grab;
|
|
120
167
|
outline: none;
|
|
121
168
|
transition: transform 0.1s;
|
|
169
|
+
touch-action: none;
|
|
170
|
+
-webkit-touch-callout: none;
|
|
122
171
|
|
|
123
|
-
&:hover { transform: scale(1.15); }
|
|
172
|
+
&:hover { transform: translate(-50%, -50%) scale(1.15); }
|
|
124
173
|
&:active { cursor: grabbing; }
|
|
125
174
|
}
|
|
126
175
|
|
|
@@ -138,6 +187,40 @@
|
|
|
138
187
|
width: 100%;
|
|
139
188
|
}
|
|
140
189
|
|
|
190
|
+
.hk-color-picker-band {
|
|
191
|
+
display: flex;
|
|
192
|
+
flex-direction: column;
|
|
193
|
+
gap: var(--space-4);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.hk-color-picker-hue-band {
|
|
197
|
+
position: relative;
|
|
198
|
+
height: 10px;
|
|
199
|
+
border-radius: var(--radius-full);
|
|
200
|
+
box-shadow: inset 0 0 0 1px rgb(0 0 0 / 10%);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.hk-color-picker-hue-band-thumb {
|
|
204
|
+
position: absolute;
|
|
205
|
+
top: 50%;
|
|
206
|
+
width: 12px;
|
|
207
|
+
height: 12px;
|
|
208
|
+
transform: translate(-50%, -50%);
|
|
209
|
+
border-radius: calc(var(--radius-xs) - 1px);
|
|
210
|
+
border: 2px solid rgb(255 255 255 / 90%);
|
|
211
|
+
box-shadow: 0 0 0 1px rgb(0 0 0 / 25%);
|
|
212
|
+
pointer-events: none;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.hk-color-picker-band-caption {
|
|
216
|
+
font-size: var(--text-2xs);
|
|
217
|
+
font-weight: 500;
|
|
218
|
+
color: rgb(var(--color-muted));
|
|
219
|
+
letter-spacing: 0.02em;
|
|
220
|
+
font-variant-numeric: tabular-nums;
|
|
221
|
+
text-align: center;
|
|
222
|
+
}
|
|
223
|
+
|
|
141
224
|
.hk-color-picker-hex-hash {
|
|
142
225
|
font-size: var(--text-xs);
|
|
143
226
|
font-weight: 600;
|
|
@@ -146,3 +229,37 @@
|
|
|
146
229
|
pointer-events: none;
|
|
147
230
|
line-height: 1;
|
|
148
231
|
}
|
|
232
|
+
|
|
233
|
+
// Mobile sheet form (via HPopover sheetOnMobile): the panel spans the full
|
|
234
|
+
// width and its controls get touch-sized spacing — the sliders are the
|
|
235
|
+
// whole point on phones, give them room to hit. The bottom padding stacks
|
|
236
|
+
// the home-bar safe-area inset ON TOP of the component's own gap (the
|
|
237
|
+
// shorthand here would otherwise silently override the base sheet rule's
|
|
238
|
+
// env() padding-bottom).
|
|
239
|
+
.hk-popover-panel.hk-is-sheet.hk-color-picker-panel {
|
|
240
|
+
padding: 0 var(--space-16)
|
|
241
|
+
calc(var(--space-20) + env(safe-area-inset-bottom, 0px));
|
|
242
|
+
|
|
243
|
+
.hk-color-picker-controls {
|
|
244
|
+
min-width: 0;
|
|
245
|
+
width: 100%;
|
|
246
|
+
gap: var(--space-16);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.hk-color-picker-slider-row {
|
|
250
|
+
gap: var(--space-10);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
.hk-color-picker-channel-slider {
|
|
254
|
+
height: 22px;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
.hk-color-picker-slider-track {
|
|
258
|
+
height: 14px;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
.hk-color-picker-slider-thumb {
|
|
262
|
+
width: 22px;
|
|
263
|
+
height: 22px;
|
|
264
|
+
}
|
|
265
|
+
}
|