From e1750b16c4db19198162df19c373d800ea62e69d Mon Sep 17 00:00:00 2001 From: Ironsp <1522278303@qq.com> Date: Thu, 17 Sep 2026 08:52:53 +0800 Subject: [PATCH] feat .calude --- .claude/skills/pinia/GENERATION.md | 5 + .claude/skills/pinia/LICENSE.md | 21 + .claude/skills/pinia/SKILL.md | 59 + .claude/skills/pinia/SYNC.md | 5 + .../skills/pinia/references/advanced-hmr.md | 61 + .../skills/pinia/references/advanced-nuxt.md | 119 ++ .../skills/pinia/references/advanced-ssr.md | 121 ++ .../best-practices-outside-component.md | 115 ++ .../references/best-practices-testing.md | 212 +++ .../skills/pinia/references/core-stores.md | 389 ++++++ .../pinia/references/features-composables.md | 114 ++ .../references/features-composing-stores.md | 134 ++ .../pinia/references/features-plugins.md | 203 +++ .claude/skills/project-structure/SKILL.md | 436 +++++++ .claude/skills/uni-app/GENERATION.md | 54 + .claude/skills/uni-app/SKILL.md | 113 ++ .../uni-app/references/config-manifest.md | 370 ++++++ .../skills/uni-app/references/config-pages.md | 270 ++++ .../references/core-form-components.md | 250 ++++ .../uni-app/references/core-framework.md | 133 ++ .../references/core-view-components.md | 202 +++ .../references/feature-file-operations.md | 391 ++++++ .../uni-app/references/feature-lifecycle.md | 423 ++++++ .../uni-app/references/feature-location.md | 417 ++++++ .../references/feature-media-components.md | 314 +++++ .../uni-app/references/feature-navigation.md | 257 ++++ .../uni-app/references/feature-network.md | 345 +++++ .../uni-app/references/feature-storage.md | 279 ++++ .../uni-app/references/feature-system-info.md | 300 +++++ .../uni-app/references/feature-ui-feedback.md | 382 ++++++ .claude/skills/uni-helper/GENERATION.md | 5 + .claude/skills/uni-helper/SKILL.md | 88 ++ .../uni-helper/references/lib-uni-network.md | 221 ++++ .../uni-helper/references/lib-uni-promises.md | 197 +++ .../uni-helper/references/lib-uni-typed.md | 200 +++ .../uni-helper/references/lib-uni-use.md | 185 +++ .../references/plugin-components.md | 93 ++ .../uni-helper/references/plugin-layouts.md | 143 +++ .../uni-helper/references/plugin-manifest.md | 103 ++ .../references/plugin-middleware.md | 181 +++ .../uni-helper/references/plugin-pages.md | 186 +++ .../references/plugin-platform-modifier.md | 119 ++ .../uni-helper/references/plugin-platform.md | 105 ++ .../references/starter-create-uni.md | 153 +++ .../uni-helper/references/starter-vitesse.md | 263 ++++ .../uni-helper/references/util-uni-env.md | 155 +++ .../references/util-unocss-preset.md | 175 +++ .claude/skills/unocss/GENERATION.md | 5 + .claude/skills/unocss/LICENSE.md | 21 + .claude/skills/unocss/SKILL.md | 64 + .claude/skills/unocss/SYNC.md | 5 + .../skills/unocss/references/core-config.md | 187 +++ .../unocss/references/core-extracting.md | 137 ++ .../skills/unocss/references/core-layers.md | 104 ++ .../skills/unocss/references/core-rules.md | 166 +++ .../skills/unocss/references/core-safelist.md | 105 ++ .../unocss/references/core-shortcuts.md | 89 ++ .../skills/unocss/references/core-theme.md | 172 +++ .../skills/unocss/references/core-variants.md | 175 +++ .../unocss/references/integrations-nuxt.md | 199 +++ .../unocss/references/integrations-vite.md | 283 ++++ .../unocss/references/preset-attributify.md | 142 ++ .../skills/unocss/references/preset-icons.md | 184 +++ .../skills/unocss/references/preset-mini.md | 158 +++ .../unocss/references/preset-rem-to-px.md | 97 ++ .../skills/unocss/references/preset-tagify.md | 134 ++ .../unocss/references/preset-typography.md | 95 ++ .../unocss/references/preset-web-fonts.md | 91 ++ .../skills/unocss/references/preset-wind3.md | 194 +++ .../skills/unocss/references/preset-wind4.md | 247 ++++ .../references/transformer-attributify-jsx.md | 156 +++ .../references/transformer-compile-class.md | 128 ++ .../references/transformer-directives.md | 157 +++ .../references/transformer-variant-group.md | 97 ++ .claude/skills/vue/GENERATION.md | 5 + .claude/skills/vue/LICENSE.md | 21 + .claude/skills/vue/SKILL.md | 63 + .claude/skills/vue/SYNC.md | 5 + .../vue/references/advanced-async-suspense.md | 246 ++++ .../vue/references/advanced-provide-inject.md | 174 +++ .../skills/vue/references/components-emits.md | 139 ++ .../vue/references/components-lifecycle.md | 192 +++ .../skills/vue/references/components-props.md | 211 +++ .../skills/vue/references/components-slots.md | 201 +++ .../vue/references/components-v-model.md | 183 +++ .../skills/vue/references/core-reactivity.md | 289 +++++ .../vue/references/features-composables.md | 262 ++++ .../vue/references/features-directives.md | 224 ++++ .../vue/references/features-script-setup.md | 247 ++++ .../vue/references/features-template-refs.md | 212 +++ .../vue/references/features-typescript.md | 274 ++++ .claude/skills/vueuse-functions/LICENSE.md | 21 + .claude/skills/vueuse-functions/SKILL.md | 418 ++++++ .claude/skills/vueuse-functions/SYNC.md | 5 + .../references/computedAsync.md | 159 +++ .../references/computedEager.md | 62 + .../references/computedInject.md | 86 ++ .../references/computedWithControl.md | 100 ++ .../references/createEventHook.md | 86 ++ .../references/createGenericProjection.md | 25 + .../references/createGlobalState.md | 95 ++ .../references/createInjectionState.md | 215 ++++ .../references/createProjection.md | 31 + .../vueuse-functions/references/createRef.md | 54 + .../references/createReusableTemplate.md | 357 ++++++ .../references/createSharedComposable.md | 42 + .../references/createTemplatePromise.md | 259 ++++ .../references/createUnrefFn.md | 51 + .../vueuse-functions/references/extendRef.md | 76 ++ .../vueuse-functions/references/from.md | 48 + .../skills/vueuse-functions/references/get.md | 30 + .../references/injectLocal.md | 35 + .../vueuse-functions/references/isDefined.md | 31 + .../vueuse-functions/references/logicAnd.md | 40 + .../vueuse-functions/references/logicNot.md | 36 + .../vueuse-functions/references/logicOr.md | 40 + .../references/makeDestructurable.md | 41 + .../references/onClickOutside.md | 187 +++ .../references/onElementRemoval.md | 64 + .../references/onKeyStroke.md | 176 +++ .../references/onLongPress.md | 170 +++ .../references/onStartTyping.md | 43 + .../references/provideLocal.md | 37 + .../vueuse-functions/references/reactify.md | 144 +++ .../references/reactifyObject.md | 61 + .../references/reactiveComputed.md | 34 + .../references/reactiveOmit.md | 86 ++ .../references/reactivePick.md | 106 ++ .../references/refAutoReset.md | 44 + .../references/refDebounced.md | 81 ++ .../vueuse-functions/references/refDefault.md | 36 + .../references/refManualReset.md | 44 + .../references/refThrottled.md | 99 ++ .../references/refWithControl.md | 146 +++ .../skills/vueuse-functions/references/set.md | 30 + .../vueuse-functions/references/syncRef.md | 195 +++ .../vueuse-functions/references/syncRefs.md | 128 ++ .../references/templateRef.md | 86 ++ .../vueuse-functions/references/toObserver.md | 38 + .../vueuse-functions/references/toReactive.md | 41 + .../vueuse-functions/references/toRef.md | 75 ++ .../vueuse-functions/references/toRefs.md | 81 ++ .../references/tryOnBeforeMount.md | 34 + .../references/tryOnBeforeUnmount.md | 32 + .../references/tryOnMounted.md | 34 + .../references/tryOnScopeDispose.md | 31 + .../references/tryOnUnmounted.md | 32 + .../references/unrefElement.md | 54 + .../vueuse-functions/references/until.md | 165 +++ .../vueuse-functions/references/useAbs.md | 31 + .../references/useActiveElement.md | 65 + .../vueuse-functions/references/useAnimate.md | 140 ++ .../references/useArrayDifference.md | 84 ++ .../references/useArrayEvery.md | 59 + .../references/useArrayFilter.md | 63 + .../references/useArrayFind.md | 50 + .../references/useArrayFindIndex.md | 59 + .../references/useArrayFindLast.md | 52 + .../references/useArrayIncludes.md | 63 + .../references/useArrayJoin.md | 74 ++ .../references/useArrayMap.md | 59 + .../references/useArrayReduce.md | 81 ++ .../references/useArraySome.md | 59 + .../references/useArrayUnique.md | 76 ++ .../references/useAsyncQueue.md | 87 ++ .../references/useAsyncState.md | 140 ++ .../references/useAsyncValidator.md | 70 + .../vueuse-functions/references/useAuth.md | 114 ++ .../vueuse-functions/references/useAverage.md | 36 + .../vueuse-functions/references/useAxios.md | 292 +++++ .../vueuse-functions/references/useBase64.md | 88 ++ .../vueuse-functions/references/useBattery.md | 67 + .../references/useBluetooth.md | 161 +++ .../references/useBreakpoints.md | 128 ++ .../references/useBroadcastChannel.md | 74 ++ .../references/useBrowserLocation.md | 83 ++ .../vueuse-functions/references/useCached.md | 53 + .../vueuse-functions/references/useCeil.md | 31 + .../references/useChangeCase.md | 79 ++ .../vueuse-functions/references/useClamp.md | 51 + .../references/useClipboard.md | 99 ++ .../references/useClipboardItems.md | 93 ++ .../vueuse-functions/references/useCloned.md | 91 ++ .../references/useColorMode.md | 171 +++ .../references/useConfirmDialog.md | 159 +++ .../vueuse-functions/references/useCookies.md | 162 +++ .../references/useCountdown.md | 102 ++ .../vueuse-functions/references/useCounter.md | 86 ++ .../vueuse-functions/references/useCssVar.md | 50 + .../references/useCurrentElement.md | 61 + .../references/useCycleList.md | 75 ++ .../vueuse-functions/references/useDark.md | 142 ++ .../references/useDateFormat.md | 145 +++ .../references/useDebounceFn.md | 100 ++ .../references/useDebouncedRefHistory.md | 40 + .../references/useDeviceMotion.md | 87 ++ .../references/useDeviceOrientation.md | 62 + .../references/useDevicePixelRatio.md | 44 + .../references/useDevicesList.md | 90 ++ .../references/useDisplayMedia.md | 71 + .../references/useDocumentVisibility.md | 45 + .../references/useDraggable.md | 210 +++ .../vueuse-functions/references/useDrauu.md | 65 + .../references/useDropZone.md | 83 ++ .../references/useElementBounding.md | 131 ++ .../references/useElementByPoint.md | 45 + .../references/useElementHover.md | 79 ++ .../references/useElementSize.md | 78 ++ .../references/useElementVisibility.md | 126 ++ .../references/useEventBus.md | 101 ++ .../references/useEventListener.md | 184 +++ .../references/useEventSource.md | 204 +++ .../references/useExtractedObservable.md | 185 +++ .../references/useEyeDropper.md | 71 + .../vueuse-functions/references/useFavicon.md | 67 + .../vueuse-functions/references/useFetch.md | 546 ++++++++ .../references/useFileDialog.md | 91 ++ .../references/useFileSystemAccess.md | 162 +++ .../references/useFirestore.md | 104 ++ .../vueuse-functions/references/useFloor.md | 31 + .../vueuse-functions/references/useFocus.md | 99 ++ .../references/useFocusTrap.md | 245 ++++ .../references/useFocusWithin.md | 57 + .../vueuse-functions/references/useFps.md | 28 + .../references/useFullscreen.md | 75 ++ .../vueuse-functions/references/useFuse.md | 107 ++ .../vueuse-functions/references/useGamepad.md | 223 ++++ .../references/useGeolocation.md | 86 ++ .../references/useIDBKeyval.md | 93 ++ .../vueuse-functions/references/useIdle.md | 89 ++ .../vueuse-functions/references/useImage.md | 86 ++ .../references/useInfiniteScroll.md | 157 +++ .../references/useIntersectionObserver.md | 118 ++ .../references/useInterval.md | 69 + .../references/useIntervalFn.md | 50 + .../references/useIpcRenderer.md | 118 ++ .../references/useIpcRendererInvoke.md | 58 + .../references/useIpcRendererOn.md | 52 + .../vueuse-functions/references/useJwt.md | 57 + .../references/useKeyModifier.md | 87 ++ .../references/useLastChanged.md | 63 + .../references/useLocalStorage.md | 41 + .../references/useMagicKeys.md | 217 ++++ .../references/useManualRefHistory.md | 204 +++ .../vueuse-functions/references/useMath.md | 47 + .../vueuse-functions/references/useMax.md | 36 + .../references/useMediaControls.md | 571 +++++++++ .../references/useMediaQuery.md | 53 + .../vueuse-functions/references/useMemoize.md | 175 +++ .../vueuse-functions/references/useMemory.md | 56 + .../vueuse-functions/references/useMin.md | 36 + .../vueuse-functions/references/useMounted.md | 38 + .../vueuse-functions/references/useMouse.md | 114 ++ .../references/useMouseInElement.md | 123 ++ .../references/useMousePressed.md | 112 ++ .../references/useMutationObserver.md | 62 + .../references/useNProgress.md | 78 ++ .../references/useNavigatorLanguage.md | 57 + .../vueuse-functions/references/useNetwork.md | 106 ++ .../vueuse-functions/references/useNow.md | 75 ++ .../references/useObjectUrl.md | 55 + .../references/useObservable.md | 67 + .../references/useOffsetPagination.md | 199 +++ .../vueuse-functions/references/useOnline.md | 41 + .../references/usePageLeave.md | 42 + .../references/useParallax.md | 58 + .../references/useParentElement.md | 54 + .../references/usePerformanceObserver.md | 48 + .../references/usePermission.md | 78 ++ .../vueuse-functions/references/usePointer.md | 89 ++ .../references/usePointerLock.md | 60 + .../references/usePointerSwipe.md | 80 ++ .../references/usePrecision.md | 49 + .../references/usePreferredColorScheme.md | 42 + .../references/usePreferredContrast.md | 42 + .../references/usePreferredDark.md | 41 + .../references/usePreferredLanguages.md | 41 + .../references/usePreferredReducedMotion.md | 42 + .../usePreferredReducedTransparency.md | 42 + .../references/usePrevious.md | 40 + .../references/useProjection.md | 38 + .../vueuse-functions/references/useQRCode.md | 53 + .../vueuse-functions/references/useRTDB.md | 70 + .../vueuse-functions/references/useRafFn.md | 68 + .../references/useRefHistory.md | 292 +++++ .../references/useResizeObserver.md | 110 ++ .../vueuse-functions/references/useRound.md | 31 + .../references/useRouteHash.md | 27 + .../references/useRouteParams.md | 38 + .../references/useRouteQuery.md | 38 + .../references/useSSRWidth.md | 47 + .../references/useScreenOrientation.md | 96 ++ .../references/useScreenSafeArea.md | 60 + .../references/useScriptTag.md | 116 ++ .../vueuse-functions/references/useScroll.md | 238 ++++ .../references/useScrollLock.md | 66 + .../references/useSessionStorage.md | 41 + .../vueuse-functions/references/useShare.md | 68 + .../references/useSortable.md | 177 +++ .../vueuse-functions/references/useSorted.md | 90 ++ .../references/useSpeechRecognition.md | 94 ++ .../references/useSpeechSynthesis.md | 105 ++ .../vueuse-functions/references/useStepper.md | 137 ++ .../vueuse-functions/references/useStorage.md | 219 ++++ .../references/useStorageAsync.md | 134 ++ .../references/useStyleTag.md | 131 ++ .../vueuse-functions/references/useSubject.md | 52 + .../references/useSubscription.md | 33 + .../vueuse-functions/references/useSum.md | 36 + .../references/useSupported.md | 29 + .../vueuse-functions/references/useSwipe.md | 75 ++ .../references/useTemplateRefsList.md | 37 + .../references/useTextDirection.md | 75 ++ .../references/useTextSelection.md | 40 + .../references/useTextareaAutosize.md | 97 ++ .../references/useThrottleFn.md | 57 + .../references/useThrottledRefHistory.md | 47 + .../vueuse-functions/references/useTimeAgo.md | 152 +++ .../references/useTimeAgoIntl.md | 116 ++ .../vueuse-functions/references/useTimeout.md | 75 ++ .../references/useTimeoutFn.md | 51 + .../references/useTimeoutPoll.md | 47 + .../references/useTimestamp.md | 85 ++ .../vueuse-functions/references/useTitle.md | 113 ++ .../references/useToNumber.md | 54 + .../references/useToString.md | 34 + .../vueuse-functions/references/useToggle.md | 56 + .../references/useTransition.md | 265 ++++ .../vueuse-functions/references/useTrunc.md | 33 + .../references/useUrlSearchParams.md | 121 ++ .../references/useUserMedia.md | 1138 +++++++++++++++++ .../vueuse-functions/references/useVModel.md | 116 ++ .../vueuse-functions/references/useVModels.md | 67 + .../vueuse-functions/references/useVibrate.md | 83 ++ .../references/useVirtualList.md | 184 +++ .../references/useWakeLock.md | 50 + .../references/useWebNotification.md | 177 +++ .../references/useWebSocket.md | 268 ++++ .../references/useWebWorker.md | 60 + .../references/useWebWorkerFn.md | 102 ++ .../references/useWindowFocus.md | 46 + .../references/useWindowScroll.md | 62 + .../references/useWindowSize.md | 76 ++ .../references/useZoomFactor.md | 53 + .../references/useZoomLevel.md | 53 + .../vueuse-functions/references/watchArray.md | 53 + .../references/watchAtMost.md | 54 + .../references/watchDebounced.md | 72 ++ .../vueuse-functions/references/watchDeep.md | 54 + .../references/watchExtractedObservable.md | 167 +++ .../references/watchIgnorable.md | 120 ++ .../references/watchImmediate.md | 44 + .../vueuse-functions/references/watchOnce.md | 41 + .../references/watchPausable.md | 86 ++ .../references/watchThrottled.md | 73 ++ .../references/watchTriggerable.md | 97 ++ .../references/watchWithFilter.md | 55 + .../vueuse-functions/references/whenever.md | 100 ++ .claude/skills/wot-ui/SKILL.md | 46 + .claude/skills/wot-ui/references/overview.md | 85 ++ .eslintignore | 3 + .gitignore | 2 - eslint.config.js | 3 + 363 files changed, 41250 insertions(+), 2 deletions(-) create mode 100644 .claude/skills/pinia/GENERATION.md create mode 100644 .claude/skills/pinia/LICENSE.md create mode 100644 .claude/skills/pinia/SKILL.md create mode 100644 .claude/skills/pinia/SYNC.md create mode 100644 .claude/skills/pinia/references/advanced-hmr.md create mode 100644 .claude/skills/pinia/references/advanced-nuxt.md create mode 100644 .claude/skills/pinia/references/advanced-ssr.md create mode 100644 .claude/skills/pinia/references/best-practices-outside-component.md create mode 100644 .claude/skills/pinia/references/best-practices-testing.md create mode 100644 .claude/skills/pinia/references/core-stores.md create mode 100644 .claude/skills/pinia/references/features-composables.md create mode 100644 .claude/skills/pinia/references/features-composing-stores.md create mode 100644 .claude/skills/pinia/references/features-plugins.md create mode 100644 .claude/skills/project-structure/SKILL.md create mode 100644 .claude/skills/uni-app/GENERATION.md create mode 100644 .claude/skills/uni-app/SKILL.md create mode 100644 .claude/skills/uni-app/references/config-manifest.md create mode 100644 .claude/skills/uni-app/references/config-pages.md create mode 100644 .claude/skills/uni-app/references/core-form-components.md create mode 100644 .claude/skills/uni-app/references/core-framework.md create mode 100644 .claude/skills/uni-app/references/core-view-components.md create mode 100644 .claude/skills/uni-app/references/feature-file-operations.md create mode 100644 .claude/skills/uni-app/references/feature-lifecycle.md create mode 100644 .claude/skills/uni-app/references/feature-location.md create mode 100644 .claude/skills/uni-app/references/feature-media-components.md create mode 100644 .claude/skills/uni-app/references/feature-navigation.md create mode 100644 .claude/skills/uni-app/references/feature-network.md create mode 100644 .claude/skills/uni-app/references/feature-storage.md create mode 100644 .claude/skills/uni-app/references/feature-system-info.md create mode 100644 .claude/skills/uni-app/references/feature-ui-feedback.md create mode 100644 .claude/skills/uni-helper/GENERATION.md create mode 100644 .claude/skills/uni-helper/SKILL.md create mode 100644 .claude/skills/uni-helper/references/lib-uni-network.md create mode 100644 .claude/skills/uni-helper/references/lib-uni-promises.md create mode 100644 .claude/skills/uni-helper/references/lib-uni-typed.md create mode 100644 .claude/skills/uni-helper/references/lib-uni-use.md create mode 100644 .claude/skills/uni-helper/references/plugin-components.md create mode 100644 .claude/skills/uni-helper/references/plugin-layouts.md create mode 100644 .claude/skills/uni-helper/references/plugin-manifest.md create mode 100644 .claude/skills/uni-helper/references/plugin-middleware.md create mode 100644 .claude/skills/uni-helper/references/plugin-pages.md create mode 100644 .claude/skills/uni-helper/references/plugin-platform-modifier.md create mode 100644 .claude/skills/uni-helper/references/plugin-platform.md create mode 100644 .claude/skills/uni-helper/references/starter-create-uni.md create mode 100644 .claude/skills/uni-helper/references/starter-vitesse.md create mode 100644 .claude/skills/uni-helper/references/util-uni-env.md create mode 100644 .claude/skills/uni-helper/references/util-unocss-preset.md create mode 100644 .claude/skills/unocss/GENERATION.md create mode 100644 .claude/skills/unocss/LICENSE.md create mode 100644 .claude/skills/unocss/SKILL.md create mode 100644 .claude/skills/unocss/SYNC.md create mode 100644 .claude/skills/unocss/references/core-config.md create mode 100644 .claude/skills/unocss/references/core-extracting.md create mode 100644 .claude/skills/unocss/references/core-layers.md create mode 100644 .claude/skills/unocss/references/core-rules.md create mode 100644 .claude/skills/unocss/references/core-safelist.md create mode 100644 .claude/skills/unocss/references/core-shortcuts.md create mode 100644 .claude/skills/unocss/references/core-theme.md create mode 100644 .claude/skills/unocss/references/core-variants.md create mode 100644 .claude/skills/unocss/references/integrations-nuxt.md create mode 100644 .claude/skills/unocss/references/integrations-vite.md create mode 100644 .claude/skills/unocss/references/preset-attributify.md create mode 100644 .claude/skills/unocss/references/preset-icons.md create mode 100644 .claude/skills/unocss/references/preset-mini.md create mode 100644 .claude/skills/unocss/references/preset-rem-to-px.md create mode 100644 .claude/skills/unocss/references/preset-tagify.md create mode 100644 .claude/skills/unocss/references/preset-typography.md create mode 100644 .claude/skills/unocss/references/preset-web-fonts.md create mode 100644 .claude/skills/unocss/references/preset-wind3.md create mode 100644 .claude/skills/unocss/references/preset-wind4.md create mode 100644 .claude/skills/unocss/references/transformer-attributify-jsx.md create mode 100644 .claude/skills/unocss/references/transformer-compile-class.md create mode 100644 .claude/skills/unocss/references/transformer-directives.md create mode 100644 .claude/skills/unocss/references/transformer-variant-group.md create mode 100644 .claude/skills/vue/GENERATION.md create mode 100644 .claude/skills/vue/LICENSE.md create mode 100644 .claude/skills/vue/SKILL.md create mode 100644 .claude/skills/vue/SYNC.md create mode 100644 .claude/skills/vue/references/advanced-async-suspense.md create mode 100644 .claude/skills/vue/references/advanced-provide-inject.md create mode 100644 .claude/skills/vue/references/components-emits.md create mode 100644 .claude/skills/vue/references/components-lifecycle.md create mode 100644 .claude/skills/vue/references/components-props.md create mode 100644 .claude/skills/vue/references/components-slots.md create mode 100644 .claude/skills/vue/references/components-v-model.md create mode 100644 .claude/skills/vue/references/core-reactivity.md create mode 100644 .claude/skills/vue/references/features-composables.md create mode 100644 .claude/skills/vue/references/features-directives.md create mode 100644 .claude/skills/vue/references/features-script-setup.md create mode 100644 .claude/skills/vue/references/features-template-refs.md create mode 100644 .claude/skills/vue/references/features-typescript.md create mode 100644 .claude/skills/vueuse-functions/LICENSE.md create mode 100644 .claude/skills/vueuse-functions/SKILL.md create mode 100644 .claude/skills/vueuse-functions/SYNC.md create mode 100644 .claude/skills/vueuse-functions/references/computedAsync.md create mode 100644 .claude/skills/vueuse-functions/references/computedEager.md create mode 100644 .claude/skills/vueuse-functions/references/computedInject.md create mode 100644 .claude/skills/vueuse-functions/references/computedWithControl.md create mode 100644 .claude/skills/vueuse-functions/references/createEventHook.md create mode 100644 .claude/skills/vueuse-functions/references/createGenericProjection.md create mode 100644 .claude/skills/vueuse-functions/references/createGlobalState.md create mode 100644 .claude/skills/vueuse-functions/references/createInjectionState.md create mode 100644 .claude/skills/vueuse-functions/references/createProjection.md create mode 100644 .claude/skills/vueuse-functions/references/createRef.md create mode 100644 .claude/skills/vueuse-functions/references/createReusableTemplate.md create mode 100644 .claude/skills/vueuse-functions/references/createSharedComposable.md create mode 100644 .claude/skills/vueuse-functions/references/createTemplatePromise.md create mode 100644 .claude/skills/vueuse-functions/references/createUnrefFn.md create mode 100644 .claude/skills/vueuse-functions/references/extendRef.md create mode 100644 .claude/skills/vueuse-functions/references/from.md create mode 100644 .claude/skills/vueuse-functions/references/get.md create mode 100644 .claude/skills/vueuse-functions/references/injectLocal.md create mode 100644 .claude/skills/vueuse-functions/references/isDefined.md create mode 100644 .claude/skills/vueuse-functions/references/logicAnd.md create mode 100644 .claude/skills/vueuse-functions/references/logicNot.md create mode 100644 .claude/skills/vueuse-functions/references/logicOr.md create mode 100644 .claude/skills/vueuse-functions/references/makeDestructurable.md create mode 100644 .claude/skills/vueuse-functions/references/onClickOutside.md create mode 100644 .claude/skills/vueuse-functions/references/onElementRemoval.md create mode 100644 .claude/skills/vueuse-functions/references/onKeyStroke.md create mode 100644 .claude/skills/vueuse-functions/references/onLongPress.md create mode 100644 .claude/skills/vueuse-functions/references/onStartTyping.md create mode 100644 .claude/skills/vueuse-functions/references/provideLocal.md create mode 100644 .claude/skills/vueuse-functions/references/reactify.md create mode 100644 .claude/skills/vueuse-functions/references/reactifyObject.md create mode 100644 .claude/skills/vueuse-functions/references/reactiveComputed.md create mode 100644 .claude/skills/vueuse-functions/references/reactiveOmit.md create mode 100644 .claude/skills/vueuse-functions/references/reactivePick.md create mode 100644 .claude/skills/vueuse-functions/references/refAutoReset.md create mode 100644 .claude/skills/vueuse-functions/references/refDebounced.md create mode 100644 .claude/skills/vueuse-functions/references/refDefault.md create mode 100644 .claude/skills/vueuse-functions/references/refManualReset.md create mode 100644 .claude/skills/vueuse-functions/references/refThrottled.md create mode 100644 .claude/skills/vueuse-functions/references/refWithControl.md create mode 100644 .claude/skills/vueuse-functions/references/set.md create mode 100644 .claude/skills/vueuse-functions/references/syncRef.md create mode 100644 .claude/skills/vueuse-functions/references/syncRefs.md create mode 100644 .claude/skills/vueuse-functions/references/templateRef.md create mode 100644 .claude/skills/vueuse-functions/references/toObserver.md create mode 100644 .claude/skills/vueuse-functions/references/toReactive.md create mode 100644 .claude/skills/vueuse-functions/references/toRef.md create mode 100644 .claude/skills/vueuse-functions/references/toRefs.md create mode 100644 .claude/skills/vueuse-functions/references/tryOnBeforeMount.md create mode 100644 .claude/skills/vueuse-functions/references/tryOnBeforeUnmount.md create mode 100644 .claude/skills/vueuse-functions/references/tryOnMounted.md create mode 100644 .claude/skills/vueuse-functions/references/tryOnScopeDispose.md create mode 100644 .claude/skills/vueuse-functions/references/tryOnUnmounted.md create mode 100644 .claude/skills/vueuse-functions/references/unrefElement.md create mode 100644 .claude/skills/vueuse-functions/references/until.md create mode 100644 .claude/skills/vueuse-functions/references/useAbs.md create mode 100644 .claude/skills/vueuse-functions/references/useActiveElement.md create mode 100644 .claude/skills/vueuse-functions/references/useAnimate.md create mode 100644 .claude/skills/vueuse-functions/references/useArrayDifference.md create mode 100644 .claude/skills/vueuse-functions/references/useArrayEvery.md create mode 100644 .claude/skills/vueuse-functions/references/useArrayFilter.md create mode 100644 .claude/skills/vueuse-functions/references/useArrayFind.md create mode 100644 .claude/skills/vueuse-functions/references/useArrayFindIndex.md create mode 100644 .claude/skills/vueuse-functions/references/useArrayFindLast.md create mode 100644 .claude/skills/vueuse-functions/references/useArrayIncludes.md create mode 100644 .claude/skills/vueuse-functions/references/useArrayJoin.md create mode 100644 .claude/skills/vueuse-functions/references/useArrayMap.md create mode 100644 .claude/skills/vueuse-functions/references/useArrayReduce.md create mode 100644 .claude/skills/vueuse-functions/references/useArraySome.md create mode 100644 .claude/skills/vueuse-functions/references/useArrayUnique.md create mode 100644 .claude/skills/vueuse-functions/references/useAsyncQueue.md create mode 100644 .claude/skills/vueuse-functions/references/useAsyncState.md create mode 100644 .claude/skills/vueuse-functions/references/useAsyncValidator.md create mode 100644 .claude/skills/vueuse-functions/references/useAuth.md create mode 100644 .claude/skills/vueuse-functions/references/useAverage.md create mode 100644 .claude/skills/vueuse-functions/references/useAxios.md create mode 100644 .claude/skills/vueuse-functions/references/useBase64.md create mode 100644 .claude/skills/vueuse-functions/references/useBattery.md create mode 100644 .claude/skills/vueuse-functions/references/useBluetooth.md create mode 100644 .claude/skills/vueuse-functions/references/useBreakpoints.md create mode 100644 .claude/skills/vueuse-functions/references/useBroadcastChannel.md create mode 100644 .claude/skills/vueuse-functions/references/useBrowserLocation.md create mode 100644 .claude/skills/vueuse-functions/references/useCached.md create mode 100644 .claude/skills/vueuse-functions/references/useCeil.md create mode 100644 .claude/skills/vueuse-functions/references/useChangeCase.md create mode 100644 .claude/skills/vueuse-functions/references/useClamp.md create mode 100644 .claude/skills/vueuse-functions/references/useClipboard.md create mode 100644 .claude/skills/vueuse-functions/references/useClipboardItems.md create mode 100644 .claude/skills/vueuse-functions/references/useCloned.md create mode 100644 .claude/skills/vueuse-functions/references/useColorMode.md create mode 100644 .claude/skills/vueuse-functions/references/useConfirmDialog.md create mode 100644 .claude/skills/vueuse-functions/references/useCookies.md create mode 100644 .claude/skills/vueuse-functions/references/useCountdown.md create mode 100644 .claude/skills/vueuse-functions/references/useCounter.md create mode 100644 .claude/skills/vueuse-functions/references/useCssVar.md create mode 100644 .claude/skills/vueuse-functions/references/useCurrentElement.md create mode 100644 .claude/skills/vueuse-functions/references/useCycleList.md create mode 100644 .claude/skills/vueuse-functions/references/useDark.md create mode 100644 .claude/skills/vueuse-functions/references/useDateFormat.md create mode 100644 .claude/skills/vueuse-functions/references/useDebounceFn.md create mode 100644 .claude/skills/vueuse-functions/references/useDebouncedRefHistory.md create mode 100644 .claude/skills/vueuse-functions/references/useDeviceMotion.md create mode 100644 .claude/skills/vueuse-functions/references/useDeviceOrientation.md create mode 100644 .claude/skills/vueuse-functions/references/useDevicePixelRatio.md create mode 100644 .claude/skills/vueuse-functions/references/useDevicesList.md create mode 100644 .claude/skills/vueuse-functions/references/useDisplayMedia.md create mode 100644 .claude/skills/vueuse-functions/references/useDocumentVisibility.md create mode 100644 .claude/skills/vueuse-functions/references/useDraggable.md create mode 100644 .claude/skills/vueuse-functions/references/useDrauu.md create mode 100644 .claude/skills/vueuse-functions/references/useDropZone.md create mode 100644 .claude/skills/vueuse-functions/references/useElementBounding.md create mode 100644 .claude/skills/vueuse-functions/references/useElementByPoint.md create mode 100644 .claude/skills/vueuse-functions/references/useElementHover.md create mode 100644 .claude/skills/vueuse-functions/references/useElementSize.md create mode 100644 .claude/skills/vueuse-functions/references/useElementVisibility.md create mode 100644 .claude/skills/vueuse-functions/references/useEventBus.md create mode 100644 .claude/skills/vueuse-functions/references/useEventListener.md create mode 100644 .claude/skills/vueuse-functions/references/useEventSource.md create mode 100644 .claude/skills/vueuse-functions/references/useExtractedObservable.md create mode 100644 .claude/skills/vueuse-functions/references/useEyeDropper.md create mode 100644 .claude/skills/vueuse-functions/references/useFavicon.md create mode 100644 .claude/skills/vueuse-functions/references/useFetch.md create mode 100644 .claude/skills/vueuse-functions/references/useFileDialog.md create mode 100644 .claude/skills/vueuse-functions/references/useFileSystemAccess.md create mode 100644 .claude/skills/vueuse-functions/references/useFirestore.md create mode 100644 .claude/skills/vueuse-functions/references/useFloor.md create mode 100644 .claude/skills/vueuse-functions/references/useFocus.md create mode 100644 .claude/skills/vueuse-functions/references/useFocusTrap.md create mode 100644 .claude/skills/vueuse-functions/references/useFocusWithin.md create mode 100644 .claude/skills/vueuse-functions/references/useFps.md create mode 100644 .claude/skills/vueuse-functions/references/useFullscreen.md create mode 100644 .claude/skills/vueuse-functions/references/useFuse.md create mode 100644 .claude/skills/vueuse-functions/references/useGamepad.md create mode 100644 .claude/skills/vueuse-functions/references/useGeolocation.md create mode 100644 .claude/skills/vueuse-functions/references/useIDBKeyval.md create mode 100644 .claude/skills/vueuse-functions/references/useIdle.md create mode 100644 .claude/skills/vueuse-functions/references/useImage.md create mode 100644 .claude/skills/vueuse-functions/references/useInfiniteScroll.md create mode 100644 .claude/skills/vueuse-functions/references/useIntersectionObserver.md create mode 100644 .claude/skills/vueuse-functions/references/useInterval.md create mode 100644 .claude/skills/vueuse-functions/references/useIntervalFn.md create mode 100644 .claude/skills/vueuse-functions/references/useIpcRenderer.md create mode 100644 .claude/skills/vueuse-functions/references/useIpcRendererInvoke.md create mode 100644 .claude/skills/vueuse-functions/references/useIpcRendererOn.md create mode 100644 .claude/skills/vueuse-functions/references/useJwt.md create mode 100644 .claude/skills/vueuse-functions/references/useKeyModifier.md create mode 100644 .claude/skills/vueuse-functions/references/useLastChanged.md create mode 100644 .claude/skills/vueuse-functions/references/useLocalStorage.md create mode 100644 .claude/skills/vueuse-functions/references/useMagicKeys.md create mode 100644 .claude/skills/vueuse-functions/references/useManualRefHistory.md create mode 100644 .claude/skills/vueuse-functions/references/useMath.md create mode 100644 .claude/skills/vueuse-functions/references/useMax.md create mode 100644 .claude/skills/vueuse-functions/references/useMediaControls.md create mode 100644 .claude/skills/vueuse-functions/references/useMediaQuery.md create mode 100644 .claude/skills/vueuse-functions/references/useMemoize.md create mode 100644 .claude/skills/vueuse-functions/references/useMemory.md create mode 100644 .claude/skills/vueuse-functions/references/useMin.md create mode 100644 .claude/skills/vueuse-functions/references/useMounted.md create mode 100644 .claude/skills/vueuse-functions/references/useMouse.md create mode 100644 .claude/skills/vueuse-functions/references/useMouseInElement.md create mode 100644 .claude/skills/vueuse-functions/references/useMousePressed.md create mode 100644 .claude/skills/vueuse-functions/references/useMutationObserver.md create mode 100644 .claude/skills/vueuse-functions/references/useNProgress.md create mode 100644 .claude/skills/vueuse-functions/references/useNavigatorLanguage.md create mode 100644 .claude/skills/vueuse-functions/references/useNetwork.md create mode 100644 .claude/skills/vueuse-functions/references/useNow.md create mode 100644 .claude/skills/vueuse-functions/references/useObjectUrl.md create mode 100644 .claude/skills/vueuse-functions/references/useObservable.md create mode 100644 .claude/skills/vueuse-functions/references/useOffsetPagination.md create mode 100644 .claude/skills/vueuse-functions/references/useOnline.md create mode 100644 .claude/skills/vueuse-functions/references/usePageLeave.md create mode 100644 .claude/skills/vueuse-functions/references/useParallax.md create mode 100644 .claude/skills/vueuse-functions/references/useParentElement.md create mode 100644 .claude/skills/vueuse-functions/references/usePerformanceObserver.md create mode 100644 .claude/skills/vueuse-functions/references/usePermission.md create mode 100644 .claude/skills/vueuse-functions/references/usePointer.md create mode 100644 .claude/skills/vueuse-functions/references/usePointerLock.md create mode 100644 .claude/skills/vueuse-functions/references/usePointerSwipe.md create mode 100644 .claude/skills/vueuse-functions/references/usePrecision.md create mode 100644 .claude/skills/vueuse-functions/references/usePreferredColorScheme.md create mode 100644 .claude/skills/vueuse-functions/references/usePreferredContrast.md create mode 100644 .claude/skills/vueuse-functions/references/usePreferredDark.md create mode 100644 .claude/skills/vueuse-functions/references/usePreferredLanguages.md create mode 100644 .claude/skills/vueuse-functions/references/usePreferredReducedMotion.md create mode 100644 .claude/skills/vueuse-functions/references/usePreferredReducedTransparency.md create mode 100644 .claude/skills/vueuse-functions/references/usePrevious.md create mode 100644 .claude/skills/vueuse-functions/references/useProjection.md create mode 100644 .claude/skills/vueuse-functions/references/useQRCode.md create mode 100644 .claude/skills/vueuse-functions/references/useRTDB.md create mode 100644 .claude/skills/vueuse-functions/references/useRafFn.md create mode 100644 .claude/skills/vueuse-functions/references/useRefHistory.md create mode 100644 .claude/skills/vueuse-functions/references/useResizeObserver.md create mode 100644 .claude/skills/vueuse-functions/references/useRound.md create mode 100644 .claude/skills/vueuse-functions/references/useRouteHash.md create mode 100644 .claude/skills/vueuse-functions/references/useRouteParams.md create mode 100644 .claude/skills/vueuse-functions/references/useRouteQuery.md create mode 100644 .claude/skills/vueuse-functions/references/useSSRWidth.md create mode 100644 .claude/skills/vueuse-functions/references/useScreenOrientation.md create mode 100644 .claude/skills/vueuse-functions/references/useScreenSafeArea.md create mode 100644 .claude/skills/vueuse-functions/references/useScriptTag.md create mode 100644 .claude/skills/vueuse-functions/references/useScroll.md create mode 100644 .claude/skills/vueuse-functions/references/useScrollLock.md create mode 100644 .claude/skills/vueuse-functions/references/useSessionStorage.md create mode 100644 .claude/skills/vueuse-functions/references/useShare.md create mode 100644 .claude/skills/vueuse-functions/references/useSortable.md create mode 100644 .claude/skills/vueuse-functions/references/useSorted.md create mode 100644 .claude/skills/vueuse-functions/references/useSpeechRecognition.md create mode 100644 .claude/skills/vueuse-functions/references/useSpeechSynthesis.md create mode 100644 .claude/skills/vueuse-functions/references/useStepper.md create mode 100644 .claude/skills/vueuse-functions/references/useStorage.md create mode 100644 .claude/skills/vueuse-functions/references/useStorageAsync.md create mode 100644 .claude/skills/vueuse-functions/references/useStyleTag.md create mode 100644 .claude/skills/vueuse-functions/references/useSubject.md create mode 100644 .claude/skills/vueuse-functions/references/useSubscription.md create mode 100644 .claude/skills/vueuse-functions/references/useSum.md create mode 100644 .claude/skills/vueuse-functions/references/useSupported.md create mode 100644 .claude/skills/vueuse-functions/references/useSwipe.md create mode 100644 .claude/skills/vueuse-functions/references/useTemplateRefsList.md create mode 100644 .claude/skills/vueuse-functions/references/useTextDirection.md create mode 100644 .claude/skills/vueuse-functions/references/useTextSelection.md create mode 100644 .claude/skills/vueuse-functions/references/useTextareaAutosize.md create mode 100644 .claude/skills/vueuse-functions/references/useThrottleFn.md create mode 100644 .claude/skills/vueuse-functions/references/useThrottledRefHistory.md create mode 100644 .claude/skills/vueuse-functions/references/useTimeAgo.md create mode 100644 .claude/skills/vueuse-functions/references/useTimeAgoIntl.md create mode 100644 .claude/skills/vueuse-functions/references/useTimeout.md create mode 100644 .claude/skills/vueuse-functions/references/useTimeoutFn.md create mode 100644 .claude/skills/vueuse-functions/references/useTimeoutPoll.md create mode 100644 .claude/skills/vueuse-functions/references/useTimestamp.md create mode 100644 .claude/skills/vueuse-functions/references/useTitle.md create mode 100644 .claude/skills/vueuse-functions/references/useToNumber.md create mode 100644 .claude/skills/vueuse-functions/references/useToString.md create mode 100644 .claude/skills/vueuse-functions/references/useToggle.md create mode 100644 .claude/skills/vueuse-functions/references/useTransition.md create mode 100644 .claude/skills/vueuse-functions/references/useTrunc.md create mode 100644 .claude/skills/vueuse-functions/references/useUrlSearchParams.md create mode 100644 .claude/skills/vueuse-functions/references/useUserMedia.md create mode 100644 .claude/skills/vueuse-functions/references/useVModel.md create mode 100644 .claude/skills/vueuse-functions/references/useVModels.md create mode 100644 .claude/skills/vueuse-functions/references/useVibrate.md create mode 100644 .claude/skills/vueuse-functions/references/useVirtualList.md create mode 100644 .claude/skills/vueuse-functions/references/useWakeLock.md create mode 100644 .claude/skills/vueuse-functions/references/useWebNotification.md create mode 100644 .claude/skills/vueuse-functions/references/useWebSocket.md create mode 100644 .claude/skills/vueuse-functions/references/useWebWorker.md create mode 100644 .claude/skills/vueuse-functions/references/useWebWorkerFn.md create mode 100644 .claude/skills/vueuse-functions/references/useWindowFocus.md create mode 100644 .claude/skills/vueuse-functions/references/useWindowScroll.md create mode 100644 .claude/skills/vueuse-functions/references/useWindowSize.md create mode 100644 .claude/skills/vueuse-functions/references/useZoomFactor.md create mode 100644 .claude/skills/vueuse-functions/references/useZoomLevel.md create mode 100644 .claude/skills/vueuse-functions/references/watchArray.md create mode 100644 .claude/skills/vueuse-functions/references/watchAtMost.md create mode 100644 .claude/skills/vueuse-functions/references/watchDebounced.md create mode 100644 .claude/skills/vueuse-functions/references/watchDeep.md create mode 100644 .claude/skills/vueuse-functions/references/watchExtractedObservable.md create mode 100644 .claude/skills/vueuse-functions/references/watchIgnorable.md create mode 100644 .claude/skills/vueuse-functions/references/watchImmediate.md create mode 100644 .claude/skills/vueuse-functions/references/watchOnce.md create mode 100644 .claude/skills/vueuse-functions/references/watchPausable.md create mode 100644 .claude/skills/vueuse-functions/references/watchThrottled.md create mode 100644 .claude/skills/vueuse-functions/references/watchTriggerable.md create mode 100644 .claude/skills/vueuse-functions/references/watchWithFilter.md create mode 100644 .claude/skills/vueuse-functions/references/whenever.md create mode 100644 .claude/skills/wot-ui/SKILL.md create mode 100644 .claude/skills/wot-ui/references/overview.md create mode 100644 .eslintignore diff --git a/.claude/skills/pinia/GENERATION.md b/.claude/skills/pinia/GENERATION.md new file mode 100644 index 0000000..a2c0f71 --- /dev/null +++ b/.claude/skills/pinia/GENERATION.md @@ -0,0 +1,5 @@ +# Generation Info + +- **Source:** `sources/pinia` +- **Git SHA:** `55dbfc5c20d4461748996aa74d8c0913e89fb98e` +- **Generated:** 2026-01-28 diff --git a/.claude/skills/pinia/LICENSE.md b/.claude/skills/pinia/LICENSE.md new file mode 100644 index 0000000..29f64e0 --- /dev/null +++ b/.claude/skills/pinia/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025-PRESENT Anthony Fu + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/.claude/skills/pinia/SKILL.md b/.claude/skills/pinia/SKILL.md new file mode 100644 index 0000000..89cfa7d --- /dev/null +++ b/.claude/skills/pinia/SKILL.md @@ -0,0 +1,59 @@ +--- +name: pinia +description: Pinia official Vue state management library, type-safe and extensible. Use when defining stores, working with state/getters/actions, or implementing store patterns in Vue apps. +metadata: + author: Anthony Fu + version: "2026.1.28" + source: Generated from https://github.com/vuejs/pinia, scripts located at https://github.com/antfu/skills +--- + +# Pinia + +Pinia is the official state management library for Vue, designed to be intuitive and type-safe. It supports both Options API and Composition API styles, with first-class TypeScript support and devtools integration. + +> The skill is based on Pinia v3.0.4, generated at 2026-01-28. + +## Core References + +| Topic | Description | Reference | +|-------|-------------|-----------| +| Stores | Defining stores, state, getters, actions, storeToRefs, subscriptions | [core-stores](references/core-stores.md) | + +## Features + +### Extensibility + +| Topic | Description | Reference | +|-------|-------------|-----------| +| Plugins | Extend stores with custom properties, state, and behavior | [features-plugins](references/features-plugins.md) | + +### Composability + +| Topic | Description | Reference | +|-------|-------------|-----------| +| Composables | Using Vue composables within stores (VueUse, etc.) | [features-composables](references/features-composables.md) | +| Composing Stores | Store-to-store communication, avoiding circular dependencies | [features-composing-stores](references/features-composing-stores.md) | + +## Best Practices + +| Topic | Description | Reference | +|-------|-------------|-----------| +| Testing | Unit testing with @pinia/testing, mocking, stubbing | [best-practices-testing](references/best-practices-testing.md) | +| Outside Components | Using stores in navigation guards, plugins, middlewares | [best-practices-outside-component](references/best-practices-outside-component.md) | + +## Advanced + +| Topic | Description | Reference | +|-------|-------------|-----------| +| SSR | Server-side rendering, state hydration | [advanced-ssr](references/advanced-ssr.md) | +| Nuxt | Nuxt integration, auto-imports, SSR best practices | [advanced-nuxt](references/advanced-nuxt.md) | +| HMR | Hot module replacement for development | [advanced-hmr](references/advanced-hmr.md) | + +## Key Recommendations + +- **Prefer Setup Stores** for complex logic, composables, and watchers +- **Use `storeToRefs()`** when destructuring state/getters to preserve reactivity +- **Actions can be destructured directly** - they're bound to the store +- **Call stores inside functions** not at module scope, especially for SSR +- **Add HMR support** to each store for better development experience +- **Use `@pinia/testing`** for component tests with mocked stores diff --git a/.claude/skills/pinia/SYNC.md b/.claude/skills/pinia/SYNC.md new file mode 100644 index 0000000..622ef75 --- /dev/null +++ b/.claude/skills/pinia/SYNC.md @@ -0,0 +1,5 @@ +# Sync Info + +- **Source:** `vendor/antfu/skills/pinia` +- **Git SHA:** `4086f59fa12d308fb05592ca8ce1704fbb940aa3` +- **Synced:** 2026-01-30 diff --git a/.claude/skills/pinia/references/advanced-hmr.md b/.claude/skills/pinia/references/advanced-hmr.md new file mode 100644 index 0000000..3eef5c7 --- /dev/null +++ b/.claude/skills/pinia/references/advanced-hmr.md @@ -0,0 +1,61 @@ +--- +name: hot-module-replacement +description: Enable HMR to preserve store state during development +--- + +# Hot Module Replacement (HMR) + +Pinia supports HMR to edit stores without page reload, preserving existing state. + +## Setup + +Add this snippet after each store definition: + +```ts +import { defineStore, acceptHMRUpdate } from 'pinia' + +export const useAuth = defineStore('auth', { + // store options... +}) + +if (import.meta.hot) { + import.meta.hot.accept(acceptHMRUpdate(useAuth, import.meta.hot)) +} +``` + +## Setup Store Example + +```ts +import { defineStore, acceptHMRUpdate } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const increment = () => count.value++ + return { count, increment } +}) + +if (import.meta.hot) { + import.meta.hot.accept(acceptHMRUpdate(useCounterStore, import.meta.hot)) +} +``` + +## Bundler Support + +- **Vite:** Officially supported via `import.meta.hot` +- **Webpack:** Uses `import.meta.webpackHot` +- Any bundler implementing the `import.meta.hot` spec should work + +## Nuxt + +With `@pinia/nuxt`, `acceptHMRUpdate` is auto-imported but you still need to add the HMR snippet manually. + +## Benefits + +- Edit store logic without losing state +- Add/remove state, actions, and getters on the fly +- Faster development iteration + + diff --git a/.claude/skills/pinia/references/advanced-nuxt.md b/.claude/skills/pinia/references/advanced-nuxt.md new file mode 100644 index 0000000..569da63 --- /dev/null +++ b/.claude/skills/pinia/references/advanced-nuxt.md @@ -0,0 +1,119 @@ +--- +name: nuxt-integration +description: Using Pinia with Nuxt - auto-imports, SSR, and best practices +--- + +# Nuxt Integration + +Pinia works seamlessly with Nuxt 3/4, handling SSR, serialization, and XSS protection automatically. + +## Installation + +```bash +npx nuxi@latest module add pinia +``` + +This installs both `@pinia/nuxt` and `pinia`. If `pinia` isn't installed, add it manually. + +> **npm users:** If you get `ERESOLVE unable to resolve dependency tree`, add to `package.json`: +> ```json +> "overrides": { "vue": "latest" } +> ``` + +## Configuration + +```ts +// nuxt.config.ts +export default defineNuxtConfig({ + modules: ['@pinia/nuxt'], +}) +``` + +## Auto Imports + +These are automatically available: +- `usePinia()` - get pinia instance +- `defineStore()` - define stores +- `storeToRefs()` - extract reactive refs +- `acceptHMRUpdate()` - HMR support + +**All stores in `app/stores/` (Nuxt 4) or `stores/` are auto-imported.** + +### Custom Store Directories + +```ts +// nuxt.config.ts +export default defineNuxtConfig({ + modules: ['@pinia/nuxt'], + pinia: { + storesDirs: ['./stores/**', './custom-folder/stores/**'], + }, +}) +``` + +## Fetching Data in Pages + +Use `callOnce()` for SSR-friendly data fetching: + +```vue + +``` + +### Refetch on Navigation + +```vue + +``` + +## Using Stores Outside Components + +In navigation guards, middlewares, or other stores, pass the `pinia` instance: + +```ts +// middleware/auth.ts +export default defineNuxtRouteMiddleware((to) => { + const nuxtApp = useNuxtApp() + const store = useStore(nuxtApp.$pinia) + + if (to.meta.requiresAuth && !store.isLoggedIn) { + return navigateTo('/login') + } +}) +``` + +Most of the time, you don't need this - just use stores in components or other injection-aware contexts. + +## Pinia Plugins with Nuxt + +Create a Nuxt plugin: + +```ts +// plugins/myPiniaPlugin.ts +import { PiniaPluginContext } from 'pinia' + +function MyPiniaPlugin({ store }: PiniaPluginContext) { + store.$subscribe((mutation) => { + console.log(`[🍍 ${mutation.storeId}]: ${mutation.type}`) + }) + return { creationTime: new Date() } +} + +export default defineNuxtPlugin(({ $pinia }) => { + $pinia.use(MyPiniaPlugin) +}) +``` + + diff --git a/.claude/skills/pinia/references/advanced-ssr.md b/.claude/skills/pinia/references/advanced-ssr.md new file mode 100644 index 0000000..2972f3a --- /dev/null +++ b/.claude/skills/pinia/references/advanced-ssr.md @@ -0,0 +1,121 @@ +--- +name: server-side-rendering +description: SSR setup, state hydration, and avoiding cross-request state pollution +--- + +# Server Side Rendering (SSR) + +Pinia works with SSR when stores are called at the top of `setup`, getters, or actions. + +> **Using Nuxt?** See the [Nuxt integration](advanced-nuxt.md) instead. + +## Basic Usage + +```vue + +``` + +## Using Store Outside setup() + +Pass the `pinia` instance explicitly: + +```ts +const pinia = createPinia() +const app = createApp(App) +app.use(router) +app.use(pinia) + +router.beforeEach((to) => { + // ✅ Pass pinia for correct SSR context + const main = useMainStore(pinia) + + if (to.meta.requiresAuth && !main.isLoggedIn) { + return '/login' + } +}) +``` + +## serverPrefetch() + +Access pinia via `this.$pinia`: + +```ts +export default { + serverPrefetch() { + const store = useStore(this.$pinia) + return store.fetchData() + }, +} +``` + +## onServerPrefetch() + +Works normally: + +```vue + +``` + +## State Hydration + +Serialize state on server and hydrate on client. + +### Server Side + +Use [devalue](https://github.com/Rich-Harris/devalue) for XSS-safe serialization: + +```ts +import devalue from 'devalue' +import { createPinia } from 'pinia' + +const pinia = createPinia() +const app = createApp(App) +app.use(router) +app.use(pinia) + +// After rendering, state is available +const serializedState = devalue(pinia.state.value) +// Inject into HTML as global variable +``` + +### Client Side + +Hydrate before any `useStore()` call: + +```ts +const pinia = createPinia() +const app = createApp(App) +app.use(pinia) + +// Hydrate from serialized state (e.g., from window.__pinia) +if (typeof window !== 'undefined') { + pinia.state.value = JSON.parse(window.__pinia) +} +``` + +## SSR Examples + +- [Vitesse template](https://github.com/antfu/vitesse/blob/main/src/modules/pinia.ts) +- [vite-plugin-ssr](https://vite-plugin-ssr.com/pinia) + +## Key Points + +1. Call stores inside functions, not at module scope +2. Pass `pinia` instance when using stores outside components in SSR +3. Hydrate state before calling any `useStore()` +4. Use `devalue` or similar for safe serialization +5. Avoid cross-request state pollution by creating fresh pinia per request + + diff --git a/.claude/skills/pinia/references/best-practices-outside-component.md b/.claude/skills/pinia/references/best-practices-outside-component.md new file mode 100644 index 0000000..126f7a6 --- /dev/null +++ b/.claude/skills/pinia/references/best-practices-outside-component.md @@ -0,0 +1,115 @@ +--- +name: using-stores-outside-components +description: Correctly using stores in navigation guards, plugins, and other non-component contexts +--- + +# Using Stores Outside Components + +Stores need the `pinia` instance, which is automatically injected in components. Outside components, you may need to provide it manually. + +## Single Page Applications + +Call stores **after** pinia is installed: + +```ts +import { useUserStore } from '@/stores/user' +import { createPinia } from 'pinia' +import { createApp } from 'vue' +import App from './App.vue' + +// ❌ Fails - pinia not created yet +const userStore = useUserStore() + +const pinia = createPinia() +const app = createApp(App) +app.use(pinia) + +// ✅ Works - pinia is active +const userStore = useUserStore() +``` + +## Navigation Guards + +**Wrong:** Call at module level + +```ts +import { createRouter } from 'vue-router' +const router = createRouter({ /* ... */ }) + +// ❌ May fail depending on import order +const store = useUserStore() + +router.beforeEach((to) => { + if (store.isLoggedIn) { /* ... */ } +}) +``` + +**Correct:** Call inside the guard + +```ts +router.beforeEach((to) => { + // ✅ Called after pinia is installed + const store = useUserStore() + + if (to.meta.requiresAuth && !store.isLoggedIn) { + return '/login' + } +}) +``` + +## SSR Applications + +Always pass the `pinia` instance to `useStore()`: + +```ts +const pinia = createPinia() +const app = createApp(App) +app.use(router) +app.use(pinia) + +router.beforeEach((to) => { + // ✅ Pass pinia instance + const main = useMainStore(pinia) + + if (to.meta.requiresAuth && !main.isLoggedIn) { + return '/login' + } +}) +``` + +## serverPrefetch() + +Access pinia via `this.$pinia`: + +```ts +export default { + serverPrefetch() { + const store = useStore(this.$pinia) + return store.fetchData() + }, +} +``` + +## onServerPrefetch() + +Works normally in ` +``` + +## Key Takeaway + +Defer `useStore()` calls to functions that run after pinia is installed, rather than calling at module scope. + + diff --git a/.claude/skills/pinia/references/best-practices-testing.md b/.claude/skills/pinia/references/best-practices-testing.md new file mode 100644 index 0000000..7227cd4 --- /dev/null +++ b/.claude/skills/pinia/references/best-practices-testing.md @@ -0,0 +1,212 @@ +--- +name: testing +description: Unit testing stores and components with @pinia/testing +--- + +# Testing Stores + +## Unit Testing Stores + +Create a fresh pinia instance for each test: + +```ts +import { setActivePinia, createPinia } from 'pinia' +import { useCounterStore } from '../src/stores/counter' + +describe('Counter Store', () => { + beforeEach(() => { + setActivePinia(createPinia()) + }) + + it('increments', () => { + const counter = useCounterStore() + expect(counter.n).toBe(0) + counter.increment() + expect(counter.n).toBe(1) + }) +}) +``` + +### With Plugins + +```ts +import { setActivePinia, createPinia } from 'pinia' +import { createApp } from 'vue' +import { somePlugin } from '../src/stores/plugin' + +const app = createApp({}) + +beforeEach(() => { + const pinia = createPinia().use(somePlugin) + app.use(pinia) + setActivePinia(pinia) +}) +``` + +## Testing Components + +Install `@pinia/testing`: + +```bash +npm i -D @pinia/testing +``` + +Use `createTestingPinia()`: + +```ts +import { mount } from '@vue/test-utils' +import { createTestingPinia } from '@pinia/testing' +import { useSomeStore } from '@/stores/myStore' + +const wrapper = mount(Counter, { + global: { + plugins: [createTestingPinia()], + }, +}) + +const store = useSomeStore() + +// Manipulate state directly +store.name = 'new name' +store.$patch({ name: 'new name' }) + +// Actions are stubbed by default +store.someAction() +expect(store.someAction).toHaveBeenCalledTimes(1) +``` + +## Initial State + +Set initial state for tests: + +```ts +const wrapper = mount(Counter, { + global: { + plugins: [ + createTestingPinia({ + initialState: { + counter: { n: 20 }, // Store name → initial state + }, + }), + ], + }, +}) +``` + +## Action Stubbing + +### Execute Real Actions + +```ts +createTestingPinia({ stubActions: false }) +``` + +### Selective Stubbing + +```ts +// Only stub specific actions +createTestingPinia({ + stubActions: ['increment', 'reset'], +}) + +// Or use a function +createTestingPinia({ + stubActions: (actionName, store) => { + if (actionName.startsWith('set')) return true + return false + }, +}) +``` + +### Mock Action Return Values + +```ts +import type { Mock } from 'vitest' + +// After getting store +store.someAction.mockResolvedValue('mocked value') +``` + +## Mocking Getters + +Getters are writable in tests: + +```ts +const pinia = createTestingPinia() +const counter = useCounterStore(pinia) + +counter.double = 3 // Override computed value + +// Reset to default behavior +counter.double = undefined +counter.double // Now computed normally +``` + +## Custom Spy Function + +If not using Jest/Vitest with globals: + +```ts +import { vi } from 'vitest' + +createTestingPinia({ + createSpy: vi.fn, +}) +``` + +With Sinon: + +```ts +import sinon from 'sinon' + +createTestingPinia({ + createSpy: sinon.spy, +}) +``` + +## Pinia Plugins in Tests + +Pass plugins to `createTestingPinia()`: + +```ts +import { somePlugin } from '../src/stores/plugin' + +createTestingPinia({ + stubActions: false, + plugins: [somePlugin], +}) +``` + +**Don't use** `testingPinia.use(MyPlugin)` - pass plugins in options. + +## Type-Safe Mocked Store + +```ts +import type { Mock } from 'vitest' +import type { Store, StoreDefinition } from 'pinia' + +function mockedStore unknown>( + useStore: TStoreDef +): TStoreDef extends StoreDefinition + ? Store, { + [K in keyof Actions]: Actions[K] extends (...args: any[]) => any + ? Mock + : Actions[K] + }> + : ReturnType { + return useStore() as any +} + +// Usage +const store = mockedStore(useSomeStore) +store.someAction.mockResolvedValue('value') // Typed! +``` + +## E2E Tests + +No special handling needed - Pinia works normally. + + diff --git a/.claude/skills/pinia/references/core-stores.md b/.claude/skills/pinia/references/core-stores.md new file mode 100644 index 0000000..ea6a72b --- /dev/null +++ b/.claude/skills/pinia/references/core-stores.md @@ -0,0 +1,389 @@ +--- +name: stores +description: Defining stores, state, getters, and actions in Pinia +--- + +# Pinia Stores + +Stores are defined using `defineStore()` with a unique name. Each store has three core concepts: **state**, **getters**, and **actions**. + +## Defining Stores + +### Option Stores + +Similar to Vue's Options API: + +```ts +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', { + state: () => ({ + count: 0, + name: 'Eduardo', + }), + getters: { + doubleCount: (state) => state.count * 2, + }, + actions: { + increment() { + this.count++ + }, + }, +}) +``` + +Think of `state` as `data`, `getters` as `computed`, and `actions` as `methods`. + +### Setup Stores (Recommended) + +Uses Composition API syntax - more flexible and powerful: + +```ts +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const name = ref('Eduardo') + const doubleCount = computed(() => count.value * 2) + + function increment() { + count.value++ + } + + return { count, name, doubleCount, increment } +}) +``` + +In Setup Stores: `ref()` → state, `computed()` → getters, `function()` → actions. + +**Important:** You must return all state properties for Pinia to track them. + +### Using Stores + +```vue + +``` + +### Destructuring with storeToRefs + +```vue + +``` + +--- + +## State + +State is defined as a function returning the initial state. + +### TypeScript + +Type inference works automatically. For complex types: + +```ts +interface UserInfo { + name: string + age: number +} + +export const useUserStore = defineStore('user', { + state: () => ({ + userList: [] as UserInfo[], + user: null as UserInfo | null, + }), +}) +``` + +Or use an interface for the return type: + +```ts +interface State { + userList: UserInfo[] + user: UserInfo | null +} + +export const useUserStore = defineStore('user', { + state: (): State => ({ + userList: [], + user: null, + }), +}) +``` + +### Accessing and Modifying + +```ts +const store = useStore() +store.count++ +``` + +```vue + +``` + +### Mutating with $patch + +Apply multiple changes at once: + +```ts +// Object syntax +store.$patch({ + count: store.count + 1, + name: 'DIO', +}) + +// Function syntax (for complex mutations) +store.$patch((state) => { + state.items.push({ name: 'shoes', quantity: 1 }) + state.hasChanged = true +}) +``` + +### Resetting State + +Option Stores have built-in `$reset()`. For Setup Stores, implement your own: + +```ts +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + + function $reset() { + count.value = 0 + } + + return { count, $reset } +}) +``` + +### Subscribing to State Changes + +```ts +cartStore.$subscribe((mutation, state) => { + mutation.type // 'direct' | 'patch object' | 'patch function' + mutation.storeId // 'cart' + mutation.payload // patch object (only for 'patch object') + + localStorage.setItem('cart', JSON.stringify(state)) +}) + +// Options +cartStore.$subscribe(callback, { flush: 'sync' }) // Immediate +cartStore.$subscribe(callback, { detached: true }) // Keep after unmount +``` + +--- + +## Getters + +Getters are computed values, equivalent to Vue's `computed()`. + +### Basic Getters + +```ts +getters: { + doubleCount: (state) => state.count * 2, +} +``` + +### Accessing Other Getters + +Use `this` with explicit return type: + +```ts +getters: { + doubleCount: (state) => state.count * 2, + doublePlusOne(): number { + return this.doubleCount + 1 + }, +}, +``` + +### Getters with Arguments + +Return a function (note: loses caching): + +```ts +getters: { + getUserById: (state) => { + return (userId: string) => state.users.find((user) => user.id === userId) + }, +}, +``` + +Cache within parameterized getters: + +```ts +getters: { + getActiveUserById(state) { + const activeUsers = state.users.filter((user) => user.active) + return (userId: string) => activeUsers.find((user) => user.id === userId) + }, +}, +``` + +### Accessing Other Stores in Getters + +```ts +import { useOtherStore } from './other-store' + +getters: { + combined(state) { + const otherStore = useOtherStore() + return state.localData + otherStore.data + }, +}, +``` + +--- + +## Actions + +Actions are methods for business logic. Unlike getters, they can be asynchronous. + +### Defining Actions + +```ts +actions: { + increment() { + this.count++ + }, + randomizeCounter() { + this.count = Math.round(100 * Math.random()) + }, +}, +``` + +### Async Actions + +```ts +actions: { + async registerUser(login: string, password: string) { + try { + this.userData = await api.post({ login, password }) + } catch (error) { + return error + } + }, +}, +``` + +### Accessing Other Stores in Actions + +```ts +import { useAuthStore } from './auth-store' + +actions: { + async fetchUserPreferences() { + const auth = useAuthStore() + if (auth.isAuthenticated) { + this.preferences = await fetchPreferences() + } + }, +}, +``` + +**SSR:** Call all `useStore()` before any `await`: + +```ts +async orderCart() { + // ✅ Call stores before await + const user = useUserStore() + + await apiOrderCart(user.token, this.items) + // ❌ Don't call useStore() after await in SSR +} +``` + +### Subscribing to Actions + +```ts +const unsubscribe = someStore.$onAction( + ({ name, store, args, after, onError }) => { + const startTime = Date.now() + console.log(`Start "${name}" with params [${args.join(', ')}]`) + + after((result) => { + console.log(`Finished "${name}" after ${Date.now() - startTime}ms`) + }) + + onError((error) => { + console.warn(`Failed "${name}": ${error}`) + }) + } +) + +unsubscribe() // Cleanup +``` + +Keep subscription after component unmount: + +```ts +someStore.$onAction(callback, true) +``` + +--- + +## Options API Helpers + +```ts +import { mapState, mapWritableState, mapActions } from 'pinia' +import { useCounterStore } from '../stores/counter' + +export default { + computed: { + // Readonly state/getters + ...mapState(useCounterStore, ['count', 'doubleCount']), + // Writable state + ...mapWritableState(useCounterStore, ['count']), + }, + methods: { + ...mapActions(useCounterStore, ['increment']), + }, +} +``` + +--- + +## Accessing Global Providers in Setup Stores + +```ts +import { inject } from 'vue' +import { useRoute } from 'vue-router' +import { defineStore } from 'pinia' + +export const useSearchFilters = defineStore('search-filters', () => { + const route = useRoute() + const appProvided = inject('appProvided') + + // Don't return these - access them directly in components + return { /* ... */ } +}) +``` + + diff --git a/.claude/skills/pinia/references/features-composables.md b/.claude/skills/pinia/references/features-composables.md new file mode 100644 index 0000000..79f7d94 --- /dev/null +++ b/.claude/skills/pinia/references/features-composables.md @@ -0,0 +1,114 @@ +--- +name: composables-in-stores +description: Using Vue composables within Pinia stores +--- + +# Composables in Stores + +Pinia stores can leverage Vue composables for reusable stateful logic. + +## Option Stores + +Call composables inside the `state` property, but only those returning writable refs: + +```ts +import { defineStore } from 'pinia' +import { useLocalStorage } from '@vueuse/core' + +export const useAuthStore = defineStore('auth', { + state: () => ({ + user: useLocalStorage('pinia/auth/login', 'bob'), + }), +}) +``` + +**Works:** Composables returning `ref()`: +- `useLocalStorage` +- `useAsyncState` + +**Doesn't work in Option Stores:** +- Composables exposing functions +- Composables exposing readonly data + +## Setup Stores + +More flexible - can use almost any composable: + +```ts +import { defineStore } from 'pinia' +import { useMediaControls } from '@vueuse/core' +import { ref } from 'vue' + +export const useVideoPlayer = defineStore('video', () => { + const videoElement = ref() + const src = ref('/data/video.mp4') + const { playing, volume, currentTime, togglePictureInPicture } = + useMediaControls(videoElement, { src }) + + function loadVideo(element: HTMLVideoElement, newSrc: string) { + videoElement.value = element + src.value = newSrc + } + + return { + src, + playing, + volume, + currentTime, + loadVideo, + togglePictureInPicture, + } +}) +``` + +**Note:** Don't return non-serializable DOM refs like `videoElement` - they're internal implementation details. + +## SSR Considerations + +### Option Stores with hydrate() + +Define a `hydrate()` function to handle client-side hydration: + +```ts +import { defineStore } from 'pinia' +import { useLocalStorage } from '@vueuse/core' + +export const useAuthStore = defineStore('auth', { + state: () => ({ + user: useLocalStorage('pinia/auth/login', 'bob'), + }), + + hydrate(state, initialState) { + // Ignore server state, read from browser + state.user = useLocalStorage('pinia/auth/login', 'bob') + }, +}) +``` + +### Setup Stores with skipHydrate() + +Mark state that shouldn't hydrate from server: + +```ts +import { defineStore, skipHydrate } from 'pinia' +import { useEyeDropper, useLocalStorage } from '@vueuse/core' + +export const useColorStore = defineStore('colors', () => { + const { isSupported, open, sRGBHex } = useEyeDropper() + const lastColor = useLocalStorage('lastColor', sRGBHex) + + return { + // Skip hydration for client-only state + lastColor: skipHydrate(lastColor), + open, // Function - no hydration needed + isSupported, // Boolean - not reactive + } +}) +``` + +`skipHydrate()` only applies to state properties (refs), not functions or non-reactive values. + + diff --git a/.claude/skills/pinia/references/features-composing-stores.md b/.claude/skills/pinia/references/features-composing-stores.md new file mode 100644 index 0000000..948f8b5 --- /dev/null +++ b/.claude/skills/pinia/references/features-composing-stores.md @@ -0,0 +1,134 @@ +--- +name: composing-stores +description: Store-to-store communication and avoiding circular dependencies +--- + +# Composing Stores + +Stores can use each other for shared state and logic. + +## Rule: Avoid Circular Dependencies + +Two stores cannot directly read each other's state during setup: + +```ts +// ❌ Infinite loop +const useX = defineStore('x', () => { + const y = useY() + y.name // Don't read here! + return { name: ref('X') } +}) + +const useY = defineStore('y', () => { + const x = useX() + x.name // Don't read here! + return { name: ref('Y') } +}) +``` + +**Solution:** Read in getters, computed, or actions: + +```ts +const useX = defineStore('x', () => { + const y = useY() + + // ✅ Read in computed/actions + function doSomething() { + const yName = y.name + } + + return { name: ref('X'), doSomething } +}) +``` + +## Setup Stores: Use Store at Top + +```ts +import { defineStore } from 'pinia' +import { useUserStore } from './user' + +export const useCartStore = defineStore('cart', () => { + const user = useUserStore() + const list = ref([]) + + const summary = computed(() => { + return `Hi ${user.name}, you have ${list.value.length} items` + }) + + function purchase() { + return apiPurchase(user.id, list.value) + } + + return { list, summary, purchase } +}) +``` + +## Shared Getters + +Call `useStore()` inside a getter: + +```ts +import { useUserStore } from './user' + +export const useCartStore = defineStore('cart', { + getters: { + summary(state) { + const user = useUserStore() + return `Hi ${user.name}, you have ${state.list.length} items` + }, + }, +}) +``` + +## Shared Actions + +Call `useStore()` inside an action: + +```ts +import { useUserStore } from './user' +import { apiOrderCart } from './api' + +export const useCartStore = defineStore('cart', { + actions: { + async orderCart() { + const user = useUserStore() + + try { + await apiOrderCart(user.token, this.items) + this.emptyCart() + } catch (err) { + displayError(err) + } + }, + }, +}) +``` + +## SSR: Call Stores Before Await + +In async actions, call all stores before any `await`: + +```ts +actions: { + async orderCart() { + // ✅ All useStore() calls before await + const user = useUserStore() + const analytics = useAnalyticsStore() + + try { + await apiOrderCart(user.token, this.items) + // ❌ Don't call useStore() after await (SSR issue) + // const otherStore = useOtherStore() + } catch (err) { + displayError(err) + } + }, +} +``` + +This ensures the correct Pinia instance is used during SSR. + + diff --git a/.claude/skills/pinia/references/features-plugins.md b/.claude/skills/pinia/references/features-plugins.md new file mode 100644 index 0000000..c4355ac --- /dev/null +++ b/.claude/skills/pinia/references/features-plugins.md @@ -0,0 +1,203 @@ +--- +name: plugins +description: Extend stores with custom properties, methods, and behavior +--- + +# Plugins + +Plugins extend all stores with custom properties, methods, or behavior. + +## Basic Plugin + +```ts +import { createPinia } from 'pinia' + +function SecretPiniaPlugin() { + return { secret: 'the cake is a lie' } +} + +const pinia = createPinia() +pinia.use(SecretPiniaPlugin) + +// In any store +const store = useStore() +store.secret // 'the cake is a lie' +``` + +## Plugin Context + +Plugins receive a context object: + +```ts +import { PiniaPluginContext } from 'pinia' + +export function myPiniaPlugin(context: PiniaPluginContext) { + context.pinia // pinia instance + context.app // Vue app instance + context.store // store being augmented + context.options // store definition options +} +``` + +## Adding Properties + +Return an object to add properties (tracked in devtools): + +```ts +pinia.use(() => ({ hello: 'world' })) +``` + +Or set directly on store: + +```ts +pinia.use(({ store }) => { + store.hello = 'world' + // For devtools visibility in dev mode + if (process.env.NODE_ENV === 'development') { + store._customProperties.add('hello') + } +}) +``` + +## Adding State + +Add to both `store` and `store.$state` for SSR/devtools: + +```ts +import { toRef, ref } from 'vue' + +pinia.use(({ store }) => { + if (!store.$state.hasOwnProperty('hasError')) { + const hasError = ref(false) + store.$state.hasError = hasError + } + store.hasError = toRef(store.$state, 'hasError') +}) +``` + +## Adding External Properties + +Wrap non-reactive objects with `markRaw()`: + +```ts +import { markRaw } from 'vue' +import { router } from './router' + +pinia.use(({ store }) => { + store.router = markRaw(router) +}) +``` + +## Custom Store Options + +Define custom options consumed by plugins: + +```ts +// Store definition +defineStore('search', { + actions: { + searchContacts() { /* ... */ }, + }, + debounce: { + searchContacts: 300, + }, +}) + +// Plugin reads custom option +import debounce from 'lodash/debounce' + +pinia.use(({ options, store }) => { + if (options.debounce) { + return Object.keys(options.debounce).reduce((acc, action) => { + acc[action] = debounce(store[action], options.debounce[action]) + return acc + }, {}) + } +}) +``` + +For Setup Stores, pass options as third argument: + +```ts +defineStore( + 'search', + () => { /* ... */ }, + { + debounce: { searchContacts: 300 }, + } +) +``` + +## TypeScript Augmentation + +### Custom Properties + +```ts +import 'pinia' +import type { Router } from 'vue-router' + +declare module 'pinia' { + export interface PiniaCustomProperties { + router: Router + hello: string + } +} +``` + +### Custom State + +```ts +declare module 'pinia' { + export interface PiniaCustomStateProperties { + hasError: boolean + } +} +``` + +### Custom Options + +```ts +declare module 'pinia' { + export interface DefineStoreOptionsBase { + debounce?: Partial, number>> + } +} +``` + +## Subscribe in Plugins + +```ts +pinia.use(({ store }) => { + store.$subscribe(() => { + // React to state changes + }) + store.$onAction(() => { + // React to actions + }) +}) +``` + +## Nuxt Plugin + +Create a Nuxt plugin to add Pinia plugins: + +```ts +// plugins/myPiniaPlugin.ts +import { PiniaPluginContext } from 'pinia' + +function MyPiniaPlugin({ store }: PiniaPluginContext) { + store.$subscribe((mutation) => { + console.log(`[🍍 ${mutation.storeId}]: ${mutation.type}`) + }) + return { creationTime: new Date() } +} + +export default defineNuxtPlugin(({ $pinia }) => { + $pinia.use(MyPiniaPlugin) +}) +``` + + diff --git a/.claude/skills/project-structure/SKILL.md b/.claude/skills/project-structure/SKILL.md new file mode 100644 index 0000000..6f8fc2b --- /dev/null +++ b/.claude/skills/project-structure/SKILL.md @@ -0,0 +1,436 @@ +# Project Structure Skill + +本 skill 定义项目的分层架构和文件组织规范,用于指导 Agent 在创建新页面、组件时遵循统一的目录结构。 + +## 核心原则 + +1. **页面放在 `pages/`** - 每个页面一个目录,包含 `index.vue` +2. **组件放在 `components/`** - 公共组件直接放目录下,页面专属组件按页面名分子目录 +3. **页面专属组件与页面同名** - 如 `home` 页面的组件放在 `components/home/` +4. **使用 easycom 自动加载** - 无需手动 import,组件通过文件路径自动生成标签名 + +## 组件放置规则(重要) + +### 公共组件(跨页面复用) +当用户要求创建**公共组件**时,直接放在 `components/` 根目录下: + +``` +components/ +├── backNav.vue # 通用返回导航栏 +├── tabBar.vue # 通用底部栏 +├── modal.vue # 通用弹窗 +└── ... +``` + +标签名:``、``、`` + +### 页面专属组件(仅特定页面使用) +当组件只在某个页面内使用时,放在 `components/{pageName}/` 子目录下: + +``` +components/ +├── home/ # 首页专属组件 +│ ├── status.vue +│ └── overview.vue +├── message/ # 消息页专属组件 +│ └── list.vue +└── bluetooth/ # 蓝牙页专属组件 + └── device.vue +``` + +标签名:``、``、`` + +### 判断依据 + +| 需求描述 | 放置位置 | 示例 | +|----------|----------|------| +| "做一个通用的返回导航" | `components/backNav.vue` | `` | +| "做一个通用的弹窗组件" | `components/modal.vue` | `` | +| "首页的项目列表组件" | `components/home/projectList.vue` | `` | +| "消息页的消息列表" | `components/message/list.vue` | `` | +| "蓝牙页的设备卡片" | `components/bluetooth/device.vue` | `` | + +## 目录结构 + +``` +src/ +├── pages/ # 页面目录 +│ ├── home/ # 首页 +│ │ └── index.vue +│ ├── report/ # 报告页 +│ │ └── index.vue +│ ├── message/ # 消息页 +│ │ └── index.vue +│ ├── bluetooth/ # 蓝牙页 +│ │ └── index.vue +│ └── work/ # 工作页 +│ └── index.vue +│ +├── components/ # 组件目录 +│ ├── backNav.vue # 公共组件:通用返回导航栏 +│ │ +│ ├── home/ # 首页专属组件 +│ │ ├── homeNav.vue # 首页导航栏 +│ │ ├── overview.vue # 今日作业概览 +│ │ ├── status.vue # 实时作业状态 +│ │ ├── projectList.vue # 项目列表容器 +│ │ ├── list.vue # 项目列表项 +│ │ ├── progress.vue # 项目作业进度 +│ │ ├── construction.vue # 当前施工段 +│ │ ├── warning.vue # 异常警告容器 +│ │ └── warning_list.vue # 异常警告项 +│ │ +│ ├── message/ # 消息页专属组件 +│ │ └── list.vue # 消息列表项 +│ │ +│ └── bluetooth/ # 蓝牙页专属组件 +│ └── device.vue # 蓝牙设备卡片 +│ +├── composables/ # 组合式函数 +├── store/ # Pinia 状态管理 +├── api/ # 接口请求 +├── utils/ # 工具函数 +├── static/ # 静态资源 +└── layouts/ # 布局组件 +``` + +## 命名规范 + +### 文件命名 +- **页面**: `index.vue`(固定) +- **组件**: `camelCase.vue`(如 `projectList.vue`) +- **组合式函数**: `useXxx.ts`(如 `useCount.ts`) + +### 组件标签名(easycom 规则) +- **公共组件**: `backNav.vue` → `` +- **页面专属组件**: `home/status.vue` → `` +- **嵌套组件**: `home/list.vue` → `` + +### easycom 自动扫描规则 +```json +{ + "easycom": { + "autoscan": true, + "custom": { + "^wd-(.*)": "@wot-ui/ui/components/wd-$1/wd-$1.vue", + "^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue" + } + } +} +``` + +### easycom 自动生成标签名规则 +| 文件路径 | 自动生成标签名 | +|----------|----------------| +| `components/backNav.vue` | `` | +| `components/modal.vue` | `` | +| `components/home/status.vue` | `` | +| `components/message/list.vue` | `` | +| `components/bluetooth/device.vue` | `` | + +## 组件拆分原则 + +### 何时拆分组件 +1. **模板超过 100 行** - 拆分为子组件 +2. **重复使用的 UI 块** - 提取为独立组件 +3. **逻辑独立的功能块** - 拆分便于维护 + +### 拆分模式 +``` +页面容器组件(如 projectList.vue) + └── 列表项组件(如 projectList_list.vue) + +页面容器组件(如 warning.vue) + └── 列表项组件(如 warning_list.vue) +``` + +### 示例:项目列表 +``` +components/home/ +├── projectList.vue # 容器:卡片标题 + card-body +└── projectList_list.vue # 内容:项目信息 + 参数 + 操作按钮 +``` + +使用方式: +```vue + + + +``` + +## 创建新页面步骤 + +1. **创建页面目录** + ``` + src/pages/{pageName}/index.vue + ``` + +2. **创建页面专属组件目录**(如需要) + ``` + src/components/{pageName}/ + ``` + +3. **配置路由**(如需要) + ```json + // src/pages.json + { + "path": "pages/{pageName}/index", + "type": "page", + "style": { + "navigationBarTitleText": "页面标题" + } + } + ``` + +4. **使用组件** + ```vue + + ``` + +## 页面专属组件 vs 公共组件 + +| 类型 | 位置 | 标签名 | 示例 | +|------|------|--------|------| +| 公共组件 | `components/` 根目录 | `{name}` | `` | +| 页面专属组件 | `components/{pageName}/` | `{pageName}-{name}` | `` | + +## 页面样式规范 + +### 内容区域样式 +所有使用自定义导航栏(``)的页面,`.content` 容器必须使用以下样式: + +```css +.content { + padding: 16px; + padding-top: 72px; +} +``` + +- `padding-top: 72px` 为导航栏预留空间,避免内容被遮挡 +- `padding: 16px` 保持左右边距一致 + +### 卡片样式规范(重要) +每个组件自身就是一个卡片,**页面不要用额外的 `.card` 容器包裹组件**,否则多个组件会合并成一个卡片。 + +**卡片间距规则**: +- 卡片之间间距统一为 **12px** +- 页面通过 `gap: 12px` 设置间距,**组件内部不要添加 margin** +- 组件只负责自身样式(背景、圆角、内边距),不负责与其他组件的间距 + +**正确做法** - 页面用 gap 设置间距: +```vue + + + + + + + + + +``` + +**错误做法** - 组件添加 margin 影响间距: +```css +/* 错误:组件添加 margin */ +.card { + margin-bottom: 16px; /* 不要用 margin */ +} +``` + +**组件卡片统一样式:** +```css +.card { + background: #fff; + border-radius: 12px; + padding: 16px; + margin-bottom: 16px; +} +``` + +**例外情况** - 多个子组件需要合并展示时: +当明确要求将多个组件放在同一个卡片内时,由最外层容器组件统一设置卡片样式,子组件背景透明: +```css +/* 容器组件 */ +.container { + background: #fff; + border-radius: 12px; + padding: 16px; +} + +/* 子组件 */ +.child { + background: transparent; + padding: 0; +} +``` + +### 页面模板示例 +```vue + + + +``` + +### 字体规范 +项目使用三级字体体系: + +| 级别 | 字号 | 用途 | 示例 | +|------|------|------|------| +| 一级 | 22px | 最大标题 | 页面标题、卡片大标题 | +| 二级 | 18px | 次级正常字体 | 正文、列表项、表单标签 | +| 三级 | 14px | 最小描述字体 | 辅助说明、placeholder、元信息 | + +**CSS 变量:** +```css +/* 一级标题 */ +--font-size-title: 22px; + +/* 二级正文 */ +--font-size-body: 18px; + +/* 三级描述 */ +--font-size-caption: 14px; +``` + +**使用示例:** +```vue + + + +``` + +## 注意事项 + +1. **不要在页面中直接写大段模板** - 超过 100 行考虑拆分 +2. **组件样式使用 scoped** - 避免样式污染 +3. **组件 props 要有默认值** - 提高组件易用性 +4. **事件命名使用 kebab-case** - 如 `@handle-click` +5. **插槽优先于 props 传内容** - 灵活性更高 +6. **禁止使用 git 提交** - 代码的改动必须经过手动提交 + +## UI 组件库使用规范(重要) + +项目使用两套 UI 组件库,按场景分工: + +### uni-ui(表单/表格场景) +**仅用于**表单、表格相关的组件: +- 下拉选择:`` +- 单选框:`` / `` +- 多选框:`` / `` +- 日期选择:`` +- 输入框:`` +- 数据选择器:`` +- 图标:`` + +官网:https://uniapp.dcloud.net.cn/component/uniui/uni-data-select.html + +### wot-ui(其他所有场景) +**除表单表格外**,其他所有 UI 组件统一使用 wot-ui: +- 按钮:`` +- 图标:`` +- 弹窗:`` +- 导航栏:`` +- 标签:`` +- 步骤条:`` +- 加载:`` +- 等等 + +### 快速判断 + +| 场景 | 使用库 | 组件示例 | +|------|--------|----------| +| 输入框 | uni-ui | `` | +| 下拉选择 | uni-ui | `` | +| 单选/多选 | uni-ui | `` / `` | +| 日期时间选择 | uni-ui | `` | +| 按钮 | wot-ui | `` | +| 图标 | wot-ui | `` | +| 弹窗/通知 | wot-ui | `` / `` | +| 导航栏 | wot-ui | `` | +| 标签/徽标 | wot-ui | `` / `` | +| 表格展示 | uni-ui | `` | diff --git a/.claude/skills/uni-app/GENERATION.md b/.claude/skills/uni-app/GENERATION.md new file mode 100644 index 0000000..be7a721 --- /dev/null +++ b/.claude/skills/uni-app/GENERATION.md @@ -0,0 +1,54 @@ +# Generation Info + +- **Source:** `sources/uniapp` +- **Git SHA:** `91423a240a5b0714fc5e7e13bd3f93a79b8cc8d7` +- **Generated:** 2026-01-30 + +## Generated Skills + +| Category | File | Description | +|----------|------|-------------| +| Core | core-framework.md | Framework basics, platform support, condition compilation | +| Core | core-view-components.md | Container components: view, scroll-view, swiper, movable-area | +| Core | core-form-components.md | Form controls: input, textarea, picker, checkbox, radio | +| Features | feature-media-components.md | Media: image, video, camera, map, live-player | +| Features | feature-navigation.md | Navigation: navigator, routing APIs | +| Features | feature-network.md | Network: request, upload, download, WebSocket | +| Features | feature-storage.md | Storage: localStorage, file system | +| Features | feature-system-info.md | System: device info, network, screen, vibration | +| Features | feature-file-operations.md | Files: image/video selection, file operations | +| Features | feature-location.md | Location: geolocation, map component | +| Features | feature-ui-feedback.md | UI: toast, modal, loading, action sheet | +| Features | feature-lifecycle.md | Lifecycle: app and page hooks | +| Config | config-pages.md | pages.json configuration | +| Config | config-manifest.md | manifest.json configuration | + +## Source Documentation Structure + +``` +sources/uniapp/docs/ +├── README.md # Framework overview +├── api/ # API documentation +│ ├── README.md # API overview +│ ├── request/ # Network APIs +│ ├── storage/ # Storage APIs +│ ├── media/ # Media APIs +│ ├── file/ # File APIs +│ ├── location/ # Location APIs +│ ├── ui/ # UI APIs +│ └── system/ # System APIs +├── component/ # Component documentation +├── collocation/ # Configuration +│ ├── pages.md # pages.json +│ ├── manifest.md # manifest.json +│ └── manifest-app.md # App-specific manifest +├── tutorial/ # Tutorials +└── quickstart.md # Getting started +``` + +## Notes + +- Skills focus on practical usage patterns and code examples +- Platform-specific differences are highlighted where relevant +- Configuration files include common use cases for each platform +- API skills include both callback and Promise usage patterns diff --git a/.claude/skills/uni-app/SKILL.md b/.claude/skills/uni-app/SKILL.md new file mode 100644 index 0000000..f2bae87 --- /dev/null +++ b/.claude/skills/uni-app/SKILL.md @@ -0,0 +1,113 @@ +--- +name: uni-app +description: Comprehensive skill reference for uni-app cross-platform development framework +metadata: + author: FlippeDround + version: "2026.1.30" + source: Generated from https://gitcode.com/dcloud/unidocs-zh, skills located at https://github.com/antfu/skills +--- + +> The skill is based on uni-app documentation, generated at 2026-01-30. + +uni-app is a Vue.js-based cross-platform framework for developing applications that run on iOS, Android, HarmonyOS, Web (responsive), and various mini-program platforms (WeChat/Alipay/Baidu/Douyin/Feishu/QQ/Kuaishou/DingTalk/Taobao/Jingdong/Xiaohongshu). + +## Core + +| Topic | Description | Reference | +|-------|-------------|-----------| +| Core Framework | Project structure, platform support, condition compilation | [core-framework](references/core-framework.md) | +| View Components | view, scroll-view, swiper, movable-area, cover-view | [core-view-components](references/core-view-components.md) | +| Form Components | input, textarea, picker, checkbox, radio, switch, slider | [core-form-components](references/core-form-components.md) | + +## Features + +### UI Components + +| Topic | Description | Reference | +|-------|-------------|-----------| +| Media Components | image, video, camera, live-player, map | [feature-media-components](references/feature-media-components.md) | +| Navigation | navigator, routing, page navigation | [feature-navigation](references/feature-navigation.md) | +| UI Feedback | toast, modal, loading, action sheet, pull refresh | [feature-ui-feedback](references/feature-ui-feedback.md) | + +### APIs + +| Topic | Description | Reference | +|-------|-------------|-----------| +| Network | HTTP requests, file upload/download, WebSocket | [feature-network](references/feature-network.md) | +| Storage | Local storage, file system, caching | [feature-storage](references/feature-storage.md) | +| System Info | Device info, network status, screen, vibration | [feature-system-info](references/feature-system-info.md) | +| File Operations | Image/video selection, file system operations | [feature-file-operations](references/feature-file-operations.md) | +| Location | Geolocation, map component, address selection | [feature-location](references/feature-location.md) | +| Lifecycle | App and page lifecycle hooks | [feature-lifecycle](references/feature-lifecycle.md) | + +## Configuration + +| Topic | Description | Reference | +|-------|-------------|-----------| +| pages.json | Page routing, tab bar, global styles, sub-packages | [config-pages](references/config-pages.md) | +| manifest.json | App config, permissions, platform settings | [config-manifest](references/config-manifest.md) | + +## Platform Support + +| Platform | Support Level | +|----------|---------------| +| iOS App | Full support | +| Android App | Full support | +| HarmonyOS Next | Full support | +| H5/Web | Full support | +| WeChat Mini Program | Full support | +| Alipay Mini Program | Full support | +| Baidu Smart Program | Full support | +| Douyin Mini Program | Full support | +| QQ Mini Program | Full support | +| Kuaishou Mini Program | Full support | +| Feishu Mini Program | Full support | +| JD Mini Program | Full support | +| HarmonyOS Meta Service | Full support | + +## Key Concepts + +### Condition Compilation + +Use special comments to write platform-specific code: + +```vue + +App only + + + +WeChat only + +``` + +### API Promise Support + +Most uni-app APIs support Promise when no callback is provided: + +```javascript +const res = await uni.request({ url: 'https://api.example.com' }) +``` + +### Cross-Platform Best Practices + +1. Use uni-app components and APIs instead of platform-specific ones +2. Use condition compilation for platform-specific features +3. Test on all target platforms +4. Use rpx for responsive layouts +5. Handle platform differences in manifest.json +6. must use uni-helper tools + + +### MCP扩展 + +当需要查询 uni-app 官方文档时,优先调用 `search-docs-by-Uniapp-official` MCP 工具搜索相关 API 文档和使用示例。 + +**使用场景:** +- 用户询问特定 API 的详细用法 +- 需要官方文档中的代码示例 +- 查询组件的属性和事件 +- 了解 API 的平台兼容性 + +**工具安装:** +如果检测到该 MCP 工具不可用,引导用户访问 https://github.com/uni-helper/mcp 进行安装。 diff --git a/.claude/skills/uni-app/references/config-manifest.md b/.claude/skills/uni-app/references/config-manifest.md new file mode 100644 index 0000000..9a8c0cb --- /dev/null +++ b/.claude/skills/uni-app/references/config-manifest.md @@ -0,0 +1,370 @@ +--- +name: Manifest.json Configuration +description: App configuration, permissions, and platform-specific settings +--- + +# Manifest.json Configuration + +`manifest.json` is the application configuration file, defining app name, icon, permissions, and platform-specific settings. + +## Basic Configuration + +```json +{ + "name": "My App", + "appid": "__UNI__XXXXXXX", + "description": "App description", + "versionName": "1.0.0", + "versionCode": 100, + "locale": "auto", + "debug": false +} +``` + +### Basic Properties + +| Property | Type | Description | +|----------|------|-------------| +| name | String | App name | +| appid | String | DCloud app ID | +| description | String | App description | +| versionName | String | Version name (1.0.0) | +| versionCode | Number | Version code (integer) | +| locale | String | Default language | +| debug | Boolean | Debug mode | +| networkTimeout | Object | Network timeout settings | +| uniStatistics | Object | Statistics configuration | + +## Network Timeout + +```json +{ + "networkTimeout": { + "request": 60000, + "connectSocket": 60000, + "uploadFile": 60000, + "downloadFile": 60000 + } +} +``` + +## App Configuration (app-plus) + +```json +{ + "app-plus": { + "splashscreen": { + "alwaysShowBeforeRender": true, + "autoclose": true, + "waiting": true + }, + "screenOrientation": ["portrait-primary"], + "modules": { + "OAuth": {}, + "Payment": {}, + "Push": {} + }, + "distribute": { + "android": { + "permissions": [ + "" + ], + "minSdkVersion": 21, + "targetSdkVersion": 30 + }, + "ios": { + "capabilities": { + "entitlements": { + "com.apple.developer.push": true + } + } + }, + "sdkConfigs": { + "payment": { + "alipay": {}, + "weixin": {} + } + } + }, + "optimization": { + "subPackages": true + } + } +} +``` + +### Splash Screen + +| Property | Type | Description | +|----------|------|-------------| +| alwaysShowBeforeRender | Boolean | Show until first page renders | +| autoclose | Boolean | Auto close splash screen | +| waiting | Boolean | Show loading indicator | + +## Mini-Program Configuration + +### WeChat (mp-weixin) + +```json +{ + "mp-weixin": { + "appid": "wx1234567890", + "setting": { + "urlCheck": false, + "es6": true, + "postcss": true, + "minified": true + }, + "usingComponents": true, + "permission": { + "scope.userLocation": { + "desc": "Your location is needed" + } + }, + "requiredPrivateInfos": [ + "getLocation" + ] + } +} +``` + +### Alipay (mp-alipay) + +```json +{ + "mp-alipay": { + "appid": "2021...", + "allowsAlignRight": true, + "component2": true + } +} +``` + +### Baidu (mp-baidu) + +```json +{ + "mp-baidu": { + "appid": "12345678", + "navigationBarForceEnable": true + } +} +``` + +### Douyin (mp-toutiao) + +```json +{ + "mp-toutiao": { + "appid": "tt...", + "setting": { + "es6": true, + "minified": true + } + } +} +``` + +## H5 Configuration + +```json +{ + "h5": { + "title": "My App", + "template": "index.html", + "router": { + "mode": "hash", + "base": "./" + }, + "optimization": { + "treeShaking": { + "enable": true + } + }, + "publicPath": "./", + "devServer": { + "port": 8080, + "disableHostCheck": true + }, + "sdkConfigs": { + "maps": { + "qqmap": { + "key": "..." + } + } + } + } +} +``` + +## Vue Configuration + +### Vue 2 + +```json +{ + "vueVersion": "2", + "sassImplementationName": "dart-sass" +} +``` + +### Vue 3 + +```json +{ + "vueVersion": "3" +} +``` + +## Permission Configuration + +### Android Permissions + +```json +{ + "app-plus": { + "distribute": { + "android": { + "permissions": [ + "", + "", + "", + "", + "" + ] + } + } + } +} +``` + +### iOS Privacy Descriptions + +```json +{ + "app-plus": { + "distribute": { + "ios": { + "privacyDescription": { + "NSCameraUsageDescription": "Camera access is needed for scanning QR codes", + "NSPhotoLibraryUsageDescription": "Photo access is needed for uploading images", + "NSLocationWhenInUseUsageDescription": "Location is needed for finding nearby stores" + } + } + } + } +} +``` + +## Common Module Configuration + +### OAuth (Login) + +```json +{ + "app-plus": { + "modules": { + "OAuth": {} + }, + "distribute": { + "sdkConfigs": { + "oauth": { + "weixin": { + "appid": "wx...", + "appsecret": "...", + "UniversalLinks": "https://..." + } + } + } + } + } +} +``` + +### Payment + +```json +{ + "app-plus": { + "modules": { + "Payment": {} + }, + "distribute": { + "sdkConfigs": { + "payment": { + "alipay": {}, + "weixin": { + "appid": "wx..." + } + } + } + } + } +} +``` + +### Push Notifications + +```json +{ + "app-plus": { + "modules": { + "Push": {} + }, + "distribute": { + "sdkConfigs": { + "push": { + "unipush": {} + } + } + } + } +} +``` + +### Share + +```json +{ + "app-plus": { + "modules": { + "Share": {} + }, + "distribute": { + "sdkConfigs": { + "share": { + "weixin": { + "appid": "wx..." + } + } + } + } + } +} +``` + +## Statistics Configuration + +```json +{ + "uniStatistics": { + "enable": true + }, + "app-plus": { + "uniStatistics": { + "enable": true + } + }, + "mp-weixin": { + "uniStatistics": { + "enable": true + } + } +} +``` + + diff --git a/.claude/skills/uni-app/references/config-pages.md b/.claude/skills/uni-app/references/config-pages.md new file mode 100644 index 0000000..a117feb --- /dev/null +++ b/.claude/skills/uni-app/references/config-pages.md @@ -0,0 +1,270 @@ +--- +name: Pages.json Configuration +description: Page routing, tab bar, and global style configuration +--- + +# Pages.json Configuration + +`pages.json` is the global configuration file for uni-app, defining page routes, window styles, native navigation bar, and tab bar. + +## Basic Structure + +```json +{ + "pages": [ + { + "path": "pages/index/index", + "style": { + "navigationBarTitleText": "Home" + } + } + ], + "globalStyle": { + "navigationBarTextStyle": "black", + "navigationBarBackgroundColor": "#F8F8F8" + }, + "tabBar": { + "list": [ + { "pagePath": "pages/index/index", "text": "Home" } + ] + } +} +``` + +## Root Properties + +| Property | Type | Required | Description | +|----------|------|----------|-------------| +| pages | Array | Yes | Page routes | +| globalStyle | Object | No | Default window style | +| tabBar | Object | No | Tab bar configuration | +| condition | Object | No | Launch mode (dev only) | +| subPackages | Array | No | Sub-packages | +| preloadRule | Object | No | Preload rules (MP) | +| easycom | Object | No | Auto component import | +| leftWindow/topWindow/rightWindow | Object | No | Multi-window (H5) | + +## Pages Configuration + +```json +{ + "pages": [ + { + "path": "pages/index/index", + "style": { + "navigationBarTitleText": "Home", + "enablePullDownRefresh": true + } + }, + { + "path": "pages/detail/detail", + "style": { + "navigationBarTitleText": "Detail", + "navigationStyle": "custom" + } + } + ] +} +``` + +### Page Style Options + +| Property | Type | Description | +|----------|------|-------------| +| navigationBarTitleText | String | Navigation title | +| navigationBarTextStyle | String | Title color: black/white | +| navigationBarBackgroundColor | HexColor | Nav background | +| navigationStyle | String | default/custom | +| enablePullDownRefresh | Boolean | Enable pull refresh | +| backgroundColor | HexColor | Background color | +| backgroundTextStyle | String | dark/light | +| onReachBottomDistance | Number | Bottom distance (px) | +| disableScroll | Boolean | Disable scroll (MP) | +| usingComponents | Object | Using custom components | + +## Global Style + +Applied to all pages unless overridden. + +```json +{ + "globalStyle": { + "navigationBarTextStyle": "black", + "navigationBarTitleText": "My App", + "navigationBarBackgroundColor": "#F8F8F8", + "backgroundColor": "#F8F8F8", + "backgroundTextStyle": "dark", + "enablePullDownRefresh": false, + "onReachBottomDistance": 50, + "rpxCalcMaxDeviceWidth": 960, + "rpxCalcBaseDeviceWidth": 375, + "rpxCalcIncludeWidth": 750 + } +} +``` + +## Tab Bar Configuration + +```json +{ + "tabBar": { + "color": "#7A7E83", + "selectedColor": "#3cc51f", + "backgroundColor": "#ffffff", + "borderStyle": "black", + "list": [ + { + "pagePath": "pages/index/index", + "text": "Home", + "iconPath": "static/image/home.png", + "selectedIconPath": "static/image/home-active.png" + }, + { + "pagePath": "pages/category/category", + "text": "Category", + "iconPath": "static/image/cat.png", + "selectedIconPath": "static/image/cat-active.png" + }, + { + "pagePath": "pages/cart/cart", + "text": "Cart", + "iconPath": "static/image/cart.png", + "selectedIconPath": "static/image/cart-active.png" + }, + { + "pagePath": "pages/user/user", + "text": "User", + "iconPath": "static/image/user.png", + "selectedIconPath": "static/image/user-active.png" + } + ] + } +} +``` + +### Tab Bar Properties + +| Property | Type | Description | +|----------|------|-------------| +| color | HexColor | Unselected text color | +| selectedColor | HexColor | Selected text color | +| backgroundColor | HexColor | Background color | +| borderStyle | String | black/white | +| list | Array | Tab items (2-5 items) | +| position | String | bottom/top | + +### Tab Item Properties + +| Property | Type | Required | Description | +|----------|------|----------|-------------| +| pagePath | String | Yes | Page path | +| text | String | Yes | Tab text | +| iconPath | String | No | Icon path (81x81px) | +| selectedIconPath | String | No | Selected icon | + +### Custom Tab Bar (WeChat/QQ/Douyin) + +```json +{ + "tabBar": { + "custom": true, + "list": [ + { "pagePath": "pages/index/index", "text": "Home" } + ] + } +} +``` + +Create `custom-tab-bar/index` component in root. + +## Sub-packages + +Split app into smaller chunks for faster loading. + +```json +{ + "subPackages": [ + { + "root": "packageA", + "pages": [ + { "path": "pages/cat/cat" }, + { "path": "pages/dog/dog" } + ] + }, + { + "root": "packageB", + "pages": [ + { "path": "pages/apple/apple" }, + { "path": "pages/banana/banana" } + ] + } + ], + "preloadRule": { + "pages/index/index": { + "network": "all", + "packages": ["packageA"] + } + } +} +``` + +## EasyCom (Auto Component Import) + +```json +{ + "easycom": { + "autoscan": true, + "custom": { + "^u--(.*)": "uview-plus/components/u-$1/u-$1.vue", + "^up-(.*)": "uview-plus/components/u-$1/u-$1.vue", + "^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue" + } + } +} +``` + +With this config, components are auto-imported without registration. + +## Conditional Compilation in Config + +```json +{ + "pages": [ + { + "path": "pages/index/index", + "style": { + "navigationBarTitleText": "Home" + } + } + ], + "globalStyle": { + "navigationBarTextStyle": "black" + }, + "condition": { + "current": 0, + "list": [ + { + "name": "test", + "path": "pages/test/test", + "query": "id=1" + } + ] + }, + "mp-weixin": { + "appid": "wx...", + "setting": { + "urlCheck": false + } + }, + "app-plus": { + "splashscreen": { + "alwaysShowBeforeRender": true + } + } +} +``` + + diff --git a/.claude/skills/uni-app/references/core-form-components.md b/.claude/skills/uni-app/references/core-form-components.md new file mode 100644 index 0000000..6c51dca --- /dev/null +++ b/.claude/skills/uni-app/references/core-form-components.md @@ -0,0 +1,250 @@ +--- +name: Form Components +description: Input, selection, and form control components +--- + +# Form Components + +## input + +Single-line text input. + +```vue + +``` + +**Properties:** + +| Property | Type | Default | Description | +|----------|------|---------|-------------| +| value | String | | Input value | +| type | String | text | Input type: text/number/idcard/digit/tel | +| password | Boolean | false | Password input | +| placeholder | String | | Placeholder text | +| placeholder-style | String | | Placeholder inline styles | +| placeholder-class | String | | Placeholder CSS class | +| maxlength | Number | 140 | Max character length | +| cursor-spacing | Number | 0 | Cursor distance from keyboard bottom (px) | +| focus | Boolean | false | Auto focus | +| confirm-type | String | done | Return key type: send/search/next/go/done | +| confirm-hold | Boolean | false | Keep keyboard open after confirm | + +**Events:** +- `@input` - Input value change +- `@focus` - Input focused +- `@blur` - Input blurred +- `@confirm` - Confirm button clicked +- `@keyboardheightchange` - Keyboard height changed + +## textarea + +Multi-line text input. + +```vue +