@stacksjs/composables 0.74.40 → 0.74.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -1
- package/dist/useCookieConsent.d.ts +56 -0
- package/dist/useCookieConsent.js +1 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ Stacks is a rapid development framework, where the goal is to _help you_ create
|
|
|
22
22
|
</picture>
|
|
23
23
|
</a>
|
|
24
24
|
|
|
25
|
-
_[Open the interactive diagram](https://stacksjs.com/docs/diagrams/stacks-runtime) for a theme toggle and SVG, PNG, JPEG, and
|
|
25
|
+
_[Open the interactive diagram](https://stacksjs.com/docs/diagrams/stacks-runtime) for a theme toggle, node search, route tracing, presentation mode, and SVG, PNG, JPEG, WebP and share-card exports._
|
|
26
26
|
|
|
27
27
|
- Web & Desktop Applications _(including system tray apps)_
|
|
28
28
|
- Serverless & Traditional APIs
|
|
@@ -58,6 +58,16 @@ redefine those behaviors.
|
|
|
58
58
|
|
|
59
59
|
## Get Started
|
|
60
60
|
|
|
61
|
+
### In the browser
|
|
62
|
+
|
|
63
|
+
[](https://codespaces.new/stacksjs/stacks)
|
|
64
|
+
|
|
65
|
+
A Codespace provisions Pantry, installs dependencies, runs `buddy setup` and
|
|
66
|
+
forwards the dev ports, so `./buddy dev` works on first open. Nothing to
|
|
67
|
+
install locally.
|
|
68
|
+
|
|
69
|
+
### On your machine
|
|
70
|
+
|
|
61
71
|
The fastest path after Pantry is installed:
|
|
62
72
|
|
|
63
73
|
```bash
|
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export type {
|
|
|
7
7
|
UseQueryOptions,
|
|
8
8
|
UseQueryResult,
|
|
9
9
|
} from './useQuery';
|
|
10
|
+
export type { ConsentCategory, ConsentDecision, UseCookieConsentOptions, UseCookieConsentResult } from './useCookieConsent';
|
|
10
11
|
export type {
|
|
11
12
|
FormFieldAccessor,
|
|
12
13
|
FormValidator,
|
|
@@ -38,6 +39,7 @@ export { createFetch } from './createFetch';
|
|
|
38
39
|
// Query / Mutation (stacksjs/stacks#1939)
|
|
39
40
|
export { createQueryClient, queryClient, useMutation, useQuery } from './useQuery';
|
|
40
41
|
// Form primitive (stacksjs/stacks#1940)
|
|
42
|
+
export { emptyCategories, OPTIONAL_CATEGORIES, parseDecision, useCookieConsent } from './useCookieConsent';
|
|
41
43
|
export { useForm } from './useForm';
|
|
42
44
|
// Date / Time
|
|
43
45
|
export { useDateFormat } from './useDateFormat';
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export{defaultDocument,defaultNavigator,defaultWindow,isRef,noop,toValue,unref}from"./_shared";export{getSSRHandler,setSSRHandler,customStorageEventName}from"./ssrHandlers";export{useStorage}from"./useStorage";export{useLocalStorage}from"./useLocalStorage";export{useSessionStorage}from"./useSessionStorage";export{useDark,usePreferredDark}from"./useDark";export{useColorMode}from"./useColorMode";export{usePreferredColorScheme}from"./usePreferredColorScheme";export{usePreferredContrast}from"./usePreferredContrast";export{usePreferredReducedMotion}from"./usePreferredReducedMotion";export{useOnline}from"./useOnline";export{useNetwork}from"./useNetwork";export{useToggle}from"./useToggle";export{useFetch}from"./useFetch";export{createFetch}from"./createFetch";export{createQueryClient,queryClient,useMutation,useQuery}from"./useQuery";export{useForm}from"./useForm";export{useDateFormat}from"./useDateFormat";export{useNow}from"./useNow";export{useTimestamp}from"./useTimestamp";export{useTimeAgo}from"./useTimeAgo";export{useEventListener}from"./useEventListener";export{useEventBus}from"./useEventBus";export{createEventHook}from"./createEventHook";export{useDebounceFn}from"./useDebounceFn";export{useThrottleFn}from"./useThrottleFn";export{useDebouncedRef}from"./useDebouncedRef";export{useThrottledRef}from"./useThrottledRef";export{useDebounce}from"./useDebounce";export{useThrottle}from"./useThrottle";export{useInterval}from"./useInterval";export{useIntervalFn}from"./useIntervalFn";export{useTimeout}from"./useTimeout";export{useTimeoutFn}from"./useTimeoutFn";export{useTimeoutPoll}from"./useTimeoutPoll";export{useRafFn}from"./useRafFn";export{useFps}from"./useFps";export{useClipboard}from"./useClipboard";export{useClipboardItems}from"./useClipboardItems";export{useMediaQuery}from"./useMediaQuery";export{breakpointsAntDesign,breakpointsBootstrap,breakpointsBootstrapV5,breakpointsMasterCss,breakpointsQuasar,breakpointsSematic,breakpointsTailwind,breakpointsMaterialDesign,useBreakpoints}from"./useBreakpoints";export{useTitle}from"./useTitle";export{useFavicon}from"./useFavicon";export{useDocumentVisibility}from"./useDocumentVisibility";export{useTextDirection}from"./useTextDirection";export{useTextSelection}from"./useTextSelection";export{useUrlSearchParams}from"./useUrlSearchParams";export{useBrowserLocation}from"./useBrowserLocation";export{useWindowSize}from"./useWindowSize";export{useWindowFocus}from"./useWindowFocus";export{useWindowScroll}from"./useWindowScroll";export{useScroll}from"./useScroll";export{useScrollLock}from"./useScrollLock";export{useInfiniteScroll}from"./useInfiniteScroll";export{useFullscreen}from"./useFullscreen";export{onClickOutside}from"./onClickOutside";export{onKeyStroke,onKeyDown,onKeyUp}from"./onKeyStroke";export{onLongPress}from"./onLongPress";export{onStartTyping}from"./onStartTyping";export{useKeyModifier}from"./useKeyModifier";export{useMagicKeys}from"./useMagicKeys";export{and,logicNot,logicOr,or,useAbs,useAverage,useCeil,useClamp,useFloor,useMax,useMin,usePrecision,useRound,useSum,useTrunc}from"./useMath";export{useCounter}from"./useCounter";export{usePrevious}from"./usePrevious";export{useLastChanged}from"./useLastChanged";export{useStepper}from"./useStepper";export{useCycleList}from"./useCycleList";export{useSorted}from"./useSorted";export{useCloned}from"./useCloned";export{useManualRefHistory}from"./useManualRefHistory";export{useRefHistory}from"./useRefHistory";export{useDebouncedRefHistory}from"./useDebouncedRefHistory";export{useThrottledRefHistory}from"./useThrottledRefHistory";export{useAsyncState}from"./useAsyncState";export{useAsyncQueue}from"./useAsyncQueue";export{whenever}from"./whenever";export{watchOnce}from"./watchOnce";export{watchDebounced}from"./watchDebounced";export{watchThrottled}from"./watchThrottled";export{watchPausable,pausableWatch}from"./watchPausable";export{watchIgnorable,ignorableWatch}from"./watchIgnorable";export{watchArray}from"./watchArray";export{watchAtMost}from"./watchAtMost";export{watchDeep}from"./watchDeep";export{watchImmediate}from"./watchImmediate";export{watchTriggerable}from"./watchTriggerable";export{watchWithFilter}from"./watchWithFilter";export{useWebSocket}from"./useWebSocket";export{useEventSource}from"./useEventSource";export{useBroadcastChannel}from"./useBroadcastChannel";export{computedAsync}from"./computedAsync";export{computedEager}from"./computedEager";export{useIntersectionObserver}from"./useIntersectionObserver";export{useResizeObserver}from"./useResizeObserver";export{useMutationObserver}from"./useMutationObserver";export{useElementSize}from"./useElementSize";export{useElementBounding}from"./useElementBounding";export{useElementVisibility}from"./useElementVisibility";export{useElementHover}from"./useElementHover";export{useElementByPoint}from"./useElementByPoint";export{useCssVar}from"./useCssVar";export{unrefElement}from"./unrefElement";export{useMouse}from"./useMouse";export{useMouseInElement}from"./useMouseInElement";export{useMousePressed}from"./useMousePressed";export{usePointer}from"./usePointer";export{useSwipe}from"./useSwipe";export{usePointerSwipe}from"./usePointerSwipe";export{usePointerLock}from"./usePointerLock";export{useParallax}from"./useParallax";export{useGeolocation}from"./useGeolocation";export{useDeviceMotion}from"./useDeviceMotion";export{useDeviceOrientation}from"./useDeviceOrientation";export{useDevicePixelRatio}from"./useDevicePixelRatio";export{useBattery}from"./useBattery";export{useFocus}from"./useFocus";export{useFocusWithin}from"./useFocusWithin";export{useActiveElement}from"./useActiveElement";export{useIdle}from"./useIdle";export{usePageLeave}from"./usePageLeave";export{useMounted}from"./useMounted";export{useDraggable}from"./useDraggable";export{useDropZone}from"./useDropZone";export{useNavigatorLanguage}from"./useNavigatorLanguage";export{usePreferredLanguages}from"./usePreferredLanguages";export{useScreenOrientation}from"./useScreenOrientation";export{useScreenSafeArea}from"./useScreenSafeArea";export{useParentElement}from"./useParentElement";export{usePermission}from"./usePermission";export{useShare}from"./useShare";export{useObjectUrl}from"./useObjectUrl";export{useImage}from"./useImage";export{useBase64}from"./useBase64";export{useAnimate}from"./useAnimate";export{useTransition,executeTransition,TransitionPresets}from"./useTransition";export{useScriptTag}from"./useScriptTag";export{useStyleTag}from"./useStyleTag";export{useConfirmDialog}from"./useConfirmDialog";export{useFileDialog}from"./useFileDialog";export{useEyeDropper}from"./useEyeDropper";export{useTextareaAutosize}from"./useTextareaAutosize";export{useWebNotification}from"./useWebNotification";export{useVibrate}from"./useVibrate";export{useWakeLock}from"./useWakeLock";export{useWebWorker,useWebWorkerFn}from"./useWebWorker";export{useVirtualList}from"./useVirtualList";export{useOffsetPagination}from"./useOffsetPagination";export{isDefined}from"./isDefined";export{useSupported}from"./useSupported";export{useToNumber}from"./useToNumber";export{useToString}from"./useToString";export{refDefault}from"./refDefault";export{refAutoReset,autoResetRef}from"./refAutoReset";export{cloneFnJSON}from"./cloneFnJSON";export{formatTimeAgo}from"./formatTimeAgo";export{until}from"./until";export{resolveRef}from"./resolveRef";export{extendRef}from"./extendRef";export{useMemoize}from"./useMemoize";export{makeDestructurable}from"./makeDestructurable";export{syncRef,syncRefs}from"./syncRef";export{createGlobalState}from"./createGlobalState";export{createSharedComposable}from"./createSharedComposable";export{tryOnMounted,tryOnBeforeMount,tryOnUnmounted,tryOnBeforeUnmount,tryOnScopeDispose}from"./tryOnMounted";export{useArrayDifference,useArrayEvery,useArrayFilter,useArrayFind,useArrayFindIndex,useArrayIncludes,useArrayMap,useArrayReduce,useArraySome,useArrayUnique}from"./useArrayUtils";export{computedAsync as asyncComputed}from"./computedAsync";export{computedEager as eagerComputed}from"./computedEager";export{useDebouncedRef as debouncedRef}from"./useDebouncedRef";export{useDebouncedRef as refDebounced}from"./useDebouncedRef";export{useThrottledRef as throttledRef}from"./useThrottledRef";export{useThrottledRef as refThrottled}from"./useThrottledRef";export{watchDebounced as debouncedWatch}from"./watchDebounced";export{watchThrottled as throttledWatch}from"./watchThrottled";export{buildSessionHandoffUrl,decodeSessionHandoff,encodeSessionHandoff,readSessionHandoff,SESSION_HANDOFF_KEY,stripSessionHandoff}from"./session-handoff";
|
|
1
|
+
export{defaultDocument,defaultNavigator,defaultWindow,isRef,noop,toValue,unref}from"./_shared";export{getSSRHandler,setSSRHandler,customStorageEventName}from"./ssrHandlers";export{useStorage}from"./useStorage";export{useLocalStorage}from"./useLocalStorage";export{useSessionStorage}from"./useSessionStorage";export{useDark,usePreferredDark}from"./useDark";export{useColorMode}from"./useColorMode";export{usePreferredColorScheme}from"./usePreferredColorScheme";export{usePreferredContrast}from"./usePreferredContrast";export{usePreferredReducedMotion}from"./usePreferredReducedMotion";export{useOnline}from"./useOnline";export{useNetwork}from"./useNetwork";export{useToggle}from"./useToggle";export{useFetch}from"./useFetch";export{createFetch}from"./createFetch";export{createQueryClient,queryClient,useMutation,useQuery}from"./useQuery";export{emptyCategories,OPTIONAL_CATEGORIES,parseDecision,useCookieConsent}from"./useCookieConsent";export{useForm}from"./useForm";export{useDateFormat}from"./useDateFormat";export{useNow}from"./useNow";export{useTimestamp}from"./useTimestamp";export{useTimeAgo}from"./useTimeAgo";export{useEventListener}from"./useEventListener";export{useEventBus}from"./useEventBus";export{createEventHook}from"./createEventHook";export{useDebounceFn}from"./useDebounceFn";export{useThrottleFn}from"./useThrottleFn";export{useDebouncedRef}from"./useDebouncedRef";export{useThrottledRef}from"./useThrottledRef";export{useDebounce}from"./useDebounce";export{useThrottle}from"./useThrottle";export{useInterval}from"./useInterval";export{useIntervalFn}from"./useIntervalFn";export{useTimeout}from"./useTimeout";export{useTimeoutFn}from"./useTimeoutFn";export{useTimeoutPoll}from"./useTimeoutPoll";export{useRafFn}from"./useRafFn";export{useFps}from"./useFps";export{useClipboard}from"./useClipboard";export{useClipboardItems}from"./useClipboardItems";export{useMediaQuery}from"./useMediaQuery";export{breakpointsAntDesign,breakpointsBootstrap,breakpointsBootstrapV5,breakpointsMasterCss,breakpointsQuasar,breakpointsSematic,breakpointsTailwind,breakpointsMaterialDesign,useBreakpoints}from"./useBreakpoints";export{useTitle}from"./useTitle";export{useFavicon}from"./useFavicon";export{useDocumentVisibility}from"./useDocumentVisibility";export{useTextDirection}from"./useTextDirection";export{useTextSelection}from"./useTextSelection";export{useUrlSearchParams}from"./useUrlSearchParams";export{useBrowserLocation}from"./useBrowserLocation";export{useWindowSize}from"./useWindowSize";export{useWindowFocus}from"./useWindowFocus";export{useWindowScroll}from"./useWindowScroll";export{useScroll}from"./useScroll";export{useScrollLock}from"./useScrollLock";export{useInfiniteScroll}from"./useInfiniteScroll";export{useFullscreen}from"./useFullscreen";export{onClickOutside}from"./onClickOutside";export{onKeyStroke,onKeyDown,onKeyUp}from"./onKeyStroke";export{onLongPress}from"./onLongPress";export{onStartTyping}from"./onStartTyping";export{useKeyModifier}from"./useKeyModifier";export{useMagicKeys}from"./useMagicKeys";export{and,logicNot,logicOr,or,useAbs,useAverage,useCeil,useClamp,useFloor,useMax,useMin,usePrecision,useRound,useSum,useTrunc}from"./useMath";export{useCounter}from"./useCounter";export{usePrevious}from"./usePrevious";export{useLastChanged}from"./useLastChanged";export{useStepper}from"./useStepper";export{useCycleList}from"./useCycleList";export{useSorted}from"./useSorted";export{useCloned}from"./useCloned";export{useManualRefHistory}from"./useManualRefHistory";export{useRefHistory}from"./useRefHistory";export{useDebouncedRefHistory}from"./useDebouncedRefHistory";export{useThrottledRefHistory}from"./useThrottledRefHistory";export{useAsyncState}from"./useAsyncState";export{useAsyncQueue}from"./useAsyncQueue";export{whenever}from"./whenever";export{watchOnce}from"./watchOnce";export{watchDebounced}from"./watchDebounced";export{watchThrottled}from"./watchThrottled";export{watchPausable,pausableWatch}from"./watchPausable";export{watchIgnorable,ignorableWatch}from"./watchIgnorable";export{watchArray}from"./watchArray";export{watchAtMost}from"./watchAtMost";export{watchDeep}from"./watchDeep";export{watchImmediate}from"./watchImmediate";export{watchTriggerable}from"./watchTriggerable";export{watchWithFilter}from"./watchWithFilter";export{useWebSocket}from"./useWebSocket";export{useEventSource}from"./useEventSource";export{useBroadcastChannel}from"./useBroadcastChannel";export{computedAsync}from"./computedAsync";export{computedEager}from"./computedEager";export{useIntersectionObserver}from"./useIntersectionObserver";export{useResizeObserver}from"./useResizeObserver";export{useMutationObserver}from"./useMutationObserver";export{useElementSize}from"./useElementSize";export{useElementBounding}from"./useElementBounding";export{useElementVisibility}from"./useElementVisibility";export{useElementHover}from"./useElementHover";export{useElementByPoint}from"./useElementByPoint";export{useCssVar}from"./useCssVar";export{unrefElement}from"./unrefElement";export{useMouse}from"./useMouse";export{useMouseInElement}from"./useMouseInElement";export{useMousePressed}from"./useMousePressed";export{usePointer}from"./usePointer";export{useSwipe}from"./useSwipe";export{usePointerSwipe}from"./usePointerSwipe";export{usePointerLock}from"./usePointerLock";export{useParallax}from"./useParallax";export{useGeolocation}from"./useGeolocation";export{useDeviceMotion}from"./useDeviceMotion";export{useDeviceOrientation}from"./useDeviceOrientation";export{useDevicePixelRatio}from"./useDevicePixelRatio";export{useBattery}from"./useBattery";export{useFocus}from"./useFocus";export{useFocusWithin}from"./useFocusWithin";export{useActiveElement}from"./useActiveElement";export{useIdle}from"./useIdle";export{usePageLeave}from"./usePageLeave";export{useMounted}from"./useMounted";export{useDraggable}from"./useDraggable";export{useDropZone}from"./useDropZone";export{useNavigatorLanguage}from"./useNavigatorLanguage";export{usePreferredLanguages}from"./usePreferredLanguages";export{useScreenOrientation}from"./useScreenOrientation";export{useScreenSafeArea}from"./useScreenSafeArea";export{useParentElement}from"./useParentElement";export{usePermission}from"./usePermission";export{useShare}from"./useShare";export{useObjectUrl}from"./useObjectUrl";export{useImage}from"./useImage";export{useBase64}from"./useBase64";export{useAnimate}from"./useAnimate";export{useTransition,executeTransition,TransitionPresets}from"./useTransition";export{useScriptTag}from"./useScriptTag";export{useStyleTag}from"./useStyleTag";export{useConfirmDialog}from"./useConfirmDialog";export{useFileDialog}from"./useFileDialog";export{useEyeDropper}from"./useEyeDropper";export{useTextareaAutosize}from"./useTextareaAutosize";export{useWebNotification}from"./useWebNotification";export{useVibrate}from"./useVibrate";export{useWakeLock}from"./useWakeLock";export{useWebWorker,useWebWorkerFn}from"./useWebWorker";export{useVirtualList}from"./useVirtualList";export{useOffsetPagination}from"./useOffsetPagination";export{isDefined}from"./isDefined";export{useSupported}from"./useSupported";export{useToNumber}from"./useToNumber";export{useToString}from"./useToString";export{refDefault}from"./refDefault";export{refAutoReset,autoResetRef}from"./refAutoReset";export{cloneFnJSON}from"./cloneFnJSON";export{formatTimeAgo}from"./formatTimeAgo";export{until}from"./until";export{resolveRef}from"./resolveRef";export{extendRef}from"./extendRef";export{useMemoize}from"./useMemoize";export{makeDestructurable}from"./makeDestructurable";export{syncRef,syncRefs}from"./syncRef";export{createGlobalState}from"./createGlobalState";export{createSharedComposable}from"./createSharedComposable";export{tryOnMounted,tryOnBeforeMount,tryOnUnmounted,tryOnBeforeUnmount,tryOnScopeDispose}from"./tryOnMounted";export{useArrayDifference,useArrayEvery,useArrayFilter,useArrayFind,useArrayFindIndex,useArrayIncludes,useArrayMap,useArrayReduce,useArraySome,useArrayUnique}from"./useArrayUtils";export{computedAsync as asyncComputed}from"./computedAsync";export{computedEager as eagerComputed}from"./computedEager";export{useDebouncedRef as debouncedRef}from"./useDebouncedRef";export{useDebouncedRef as refDebounced}from"./useDebouncedRef";export{useThrottledRef as throttledRef}from"./useThrottledRef";export{useThrottledRef as refThrottled}from"./useThrottledRef";export{watchDebounced as debouncedWatch}from"./watchDebounced";export{watchThrottled as throttledWatch}from"./watchThrottled";export{buildSessionHandoffUrl,decodeSessionHandoff,encodeSessionHandoff,readSessionHandoff,SESSION_HANDOFF_KEY,stripSessionHandoff}from"./session-handoff";
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { Ref } from '@stacksjs/stx';
|
|
2
|
+
/** Nothing consented. The starting point, and the answer whenever in doubt. */
|
|
3
|
+
export declare function emptyCategories(): Record<ConsentCategory, boolean>;
|
|
4
|
+
/**
|
|
5
|
+
* Parse a stored decision, or `null` if it is unusable.
|
|
6
|
+
*
|
|
7
|
+
* Anything unrecognised - a truncated write, a value from an older shape, a
|
|
8
|
+
* different policy version - resolves to "no decision" rather than to a
|
|
9
|
+
* partially-trusted one. The cost is asking again; the cost of the other
|
|
10
|
+
* choice is running a tracker the visitor did not agree to.
|
|
11
|
+
*/
|
|
12
|
+
export declare function parseDecision(raw: string | null, policyVersion: string): ConsentDecision | null;
|
|
13
|
+
export declare function useCookieConsent(options?: UseCookieConsentOptions): UseCookieConsentResult;
|
|
14
|
+
/** Every category except the one that cannot be declined. */
|
|
15
|
+
export declare const OPTIONAL_CATEGORIES: readonly ConsentCategory[];
|
|
16
|
+
export declare interface ConsentDecision {
|
|
17
|
+
categories: Record<ConsentCategory, boolean>
|
|
18
|
+
policyVersion: string
|
|
19
|
+
decidedAt: string
|
|
20
|
+
}
|
|
21
|
+
export declare interface UseCookieConsentOptions {
|
|
22
|
+
policyVersion?: string
|
|
23
|
+
storageKey?: string
|
|
24
|
+
onChange?: (decision: ConsentDecision | null) => void
|
|
25
|
+
}
|
|
26
|
+
export declare interface UseCookieConsentResult {
|
|
27
|
+
decision: Ref<ConsentDecision | null>
|
|
28
|
+
needsDecision: Ref<boolean>
|
|
29
|
+
allows: (category: ConsentCategory) => boolean
|
|
30
|
+
accept: (categories?: readonly ConsentCategory[]) => ConsentDecision
|
|
31
|
+
acceptAll: () => ConsentDecision
|
|
32
|
+
declineAll: () => ConsentDecision
|
|
33
|
+
withdraw: () => void
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Cookie consent, the GDPR-correct way round (stacksjs/stacks#365).
|
|
37
|
+
*
|
|
38
|
+
* The rule this exists to enforce is that **non-essential cookies are declined
|
|
39
|
+
* until the visitor says otherwise**. Every category except `necessary`
|
|
40
|
+
* defaults to false, and there is deliberately no way to ask for a permissive
|
|
41
|
+
* default: a banner whose "accept" is preselected is the single most common
|
|
42
|
+
* way a consent implementation fails an audit, and making it impossible here
|
|
43
|
+
* is cheaper than reviewing every app that uses it.
|
|
44
|
+
*
|
|
45
|
+
* The stored decision is versioned by the policy it was given under. Changing
|
|
46
|
+
* `policyVersion` invalidates every stored choice and re-asks, because consent
|
|
47
|
+
* to a previous policy is not consent to this one.
|
|
48
|
+
*
|
|
49
|
+
* Storage is `localStorage`, per browser. That is the right scope - consent is
|
|
50
|
+
* a property of a device and a person, not of a session - and it means the
|
|
51
|
+
* decision survives a reload without a server round trip. A visitor who blocks
|
|
52
|
+
* storage gets the safe answer on every page: nothing is consented, and the
|
|
53
|
+
* banner asks again.
|
|
54
|
+
*/
|
|
55
|
+
/** The categories a visitor decides about. */
|
|
56
|
+
export type ConsentCategory = 'necessary' | 'preferences' | 'analytics' | 'marketing';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{ref}from"@stacksjs/stx";export const OPTIONAL_CATEGORIES=["preferences","analytics","marketing"];const DEFAULT_KEY="stacks:cookie-consent:v1";export function emptyCategories(){return{necessary:!0,preferences:!1,analytics:!1,marketing:!1}}export function parseDecision(raw,policyVersion){if(!raw)return null;let parsed;try{parsed=JSON.parse(raw)}catch{return null}if(!parsed||typeof parsed!=="object")return null;const candidate=parsed;if(candidate.policyVersion!==policyVersion)return null;if(!candidate.categories||typeof candidate.categories!=="object")return null;if(typeof candidate.decidedAt!=="string")return null;const categories=emptyCategories();for(const category of OPTIONAL_CATEGORIES)categories[category]=candidate.categories[category]===!0;return{categories,policyVersion,decidedAt:candidate.decidedAt}}function readStored(key){try{return globalThis.localStorage?.getItem(key)??null}catch{return null}}function writeStored(key,value){try{if(value===null)globalThis.localStorage?.removeItem(key);else globalThis.localStorage?.setItem(key,value)}catch{}}export function useCookieConsent(options={}){const policyVersion=options.policyVersion??"1.0",storageKey=options.storageKey??DEFAULT_KEY,decision=ref(parseDecision(readStored(storageKey),policyVersion)),needsDecision=ref(decision.value===null);if(decision.value)options.onChange?.(decision.value);function commit(categories){const next={categories:{...categories,necessary:!0},policyVersion,decidedAt:new Date().toISOString()};decision.value=next;needsDecision.value=!1;writeStored(storageKey,JSON.stringify(next));options.onChange?.(next);return next}return{decision,needsDecision,allows(category){if(category==="necessary")return!0;return decision.value?.categories[category]===!0},accept(categories=OPTIONAL_CATEGORIES){const next=emptyCategories();for(const category of categories)if(category!=="necessary")next[category]=!0;return commit(next)},acceptAll(){const next=emptyCategories();for(const category of OPTIONAL_CATEGORIES)next[category]=!0;return commit(next)},declineAll(){return commit(emptyCategories())},withdraw(){decision.value=null;needsDecision.value=!0;writeStored(storageKey,null);options.onChange?.(null)}}}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@stacksjs/composables",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"sideEffects": false,
|
|
5
|
-
"version": "0.74.
|
|
5
|
+
"version": "0.74.42",
|
|
6
6
|
"description": "Stacks composables powered by stx reactivity.",
|
|
7
7
|
"author": "Chris Breuer",
|
|
8
8
|
"contributors": [
|
|
@@ -51,8 +51,8 @@
|
|
|
51
51
|
"prepublishOnly": "bun run build"
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"@stacksjs/stx": "^0.2.
|
|
55
|
-
"@stacksjs/datetime": "0.74.
|
|
54
|
+
"@stacksjs/stx": "^0.2.285",
|
|
55
|
+
"@stacksjs/datetime": "0.74.42"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
58
|
"better-dx": "^0.2.24"
|