@c15t/svelte 3.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (274) hide show
  1. package/AGENTS.md +88 -0
  2. package/README.md +136 -0
  3. package/SKILL.md +14 -0
  4. package/dist/actions/focus-trap.d.ts +8 -0
  5. package/dist/actions/focus-trap.js +23 -0
  6. package/dist/actions/portal.d.ts +8 -0
  7. package/dist/actions/portal.js +39 -0
  8. package/dist/actions/scroll-lock.d.ts +8 -0
  9. package/dist/actions/scroll-lock.js +23 -0
  10. package/dist/components/action-button.svelte +119 -0
  11. package/dist/components/action-button.svelte.d.ts +18 -0
  12. package/dist/components/branding.svelte +139 -0
  13. package/dist/components/branding.svelte.d.ts +13 -0
  14. package/dist/components/consent-dev-tools.svelte +58 -0
  15. package/dist/components/consent-dev-tools.svelte.d.ts +4 -0
  16. package/dist/components/frame.svelte +95 -0
  17. package/dist/components/frame.svelte.d.ts +12 -0
  18. package/dist/components/iab-panel.svelte +542 -0
  19. package/dist/components/iab-panel.svelte.d.ts +16 -0
  20. package/dist/components/iab-prompt.svelte +304 -0
  21. package/dist/components/iab-prompt.svelte.d.ts +14 -0
  22. package/dist/components/iab-purpose-item.svelte +511 -0
  23. package/dist/components/iab-purpose-item.svelte.d.ts +26 -0
  24. package/dist/components/iab-stack-item.svelte +146 -0
  25. package/dist/components/iab-stack-item.svelte.d.ts +19 -0
  26. package/dist/components/iab-vendor-list.svelte +900 -0
  27. package/dist/components/iab-vendor-list.svelte.d.ts +19 -0
  28. package/dist/components/icons/c15-t-icon-only.svelte +27 -0
  29. package/dist/components/icons/c15-t-icon-only.svelte.d.ts +9 -0
  30. package/dist/components/icons/chevron-down-icon.svelte +30 -0
  31. package/dist/components/icons/chevron-down-icon.svelte.d.ts +10 -0
  32. package/dist/components/icons/chevron-right-icon.svelte +36 -0
  33. package/dist/components/icons/chevron-right-icon.svelte.d.ts +12 -0
  34. package/dist/components/icons/close-icon.svelte +40 -0
  35. package/dist/components/icons/close-icon.svelte.d.ts +10 -0
  36. package/dist/components/icons/consent-icon-only.svelte +36 -0
  37. package/dist/components/icons/consent-icon-only.svelte.d.ts +9 -0
  38. package/dist/components/icons/external-link-icon.svelte +30 -0
  39. package/dist/components/icons/external-link-icon.svelte.d.ts +8 -0
  40. package/dist/components/icons/globe-icon.svelte +39 -0
  41. package/dist/components/icons/globe-icon.svelte.d.ts +9 -0
  42. package/dist/components/icons/info-icon.svelte +42 -0
  43. package/dist/components/icons/info-icon.svelte.d.ts +9 -0
  44. package/dist/components/icons/inth-logo.svelte +38 -0
  45. package/dist/components/icons/inth-logo.svelte.d.ts +9 -0
  46. package/dist/components/icons/layers-icon.svelte +25 -0
  47. package/dist/components/icons/layers-icon.svelte.d.ts +8 -0
  48. package/dist/components/icons/legitimate-interest-icon.svelte +29 -0
  49. package/dist/components/icons/legitimate-interest-icon.svelte.d.ts +10 -0
  50. package/dist/components/icons/lock-icon.svelte +31 -0
  51. package/dist/components/icons/lock-icon.svelte.d.ts +8 -0
  52. package/dist/components/icons/search-icon.svelte +33 -0
  53. package/dist/components/icons/search-icon.svelte.d.ts +8 -0
  54. package/dist/components/inline-legal-links.svelte +95 -0
  55. package/dist/components/inline-legal-links.svelte.d.ts +10 -0
  56. package/dist/components/manager-provider.svelte +459 -0
  57. package/dist/components/manager-provider.svelte.d.ts +27 -0
  58. package/dist/components/overlay.svelte +79 -0
  59. package/dist/components/overlay.svelte.d.ts +7 -0
  60. package/dist/components/panel-link.svelte +33 -0
  61. package/dist/components/panel-link.svelte.d.ts +10 -0
  62. package/dist/components/panel-trigger.svelte +237 -0
  63. package/dist/components/panel-trigger.svelte.d.ts +16 -0
  64. package/dist/components/panel.svelte +258 -0
  65. package/dist/components/panel.svelte.d.ts +22 -0
  66. package/dist/components/policy-actions-renderer.svelte +79 -0
  67. package/dist/components/policy-actions-renderer.svelte.d.ts +19 -0
  68. package/dist/components/preferences.svelte +320 -0
  69. package/dist/components/preferences.svelte.d.ts +8 -0
  70. package/dist/components/prompt.svelte +514 -0
  71. package/dist/components/prompt.svelte.d.ts +43 -0
  72. package/dist/context.svelte.d.ts +125 -0
  73. package/dist/context.svelte.js +354 -0
  74. package/dist/devtools-options.d.ts +7 -0
  75. package/dist/devtools-options.js +1 -0
  76. package/dist/devtools.d.ts +9 -0
  77. package/dist/devtools.js +7 -0
  78. package/dist/headless.d.ts +10 -0
  79. package/dist/headless.js +7 -0
  80. package/dist/iab/styles.css +11 -0
  81. package/dist/iab-loader.d.ts +30 -0
  82. package/dist/iab-loader.js +33 -0
  83. package/dist/iab-translations.d.ts +84 -0
  84. package/dist/iab-translations.js +45 -0
  85. package/dist/iab-types.d.ts +62 -0
  86. package/dist/iab-types.js +43 -0
  87. package/dist/index.d.ts +28 -0
  88. package/dist/index.js +21 -0
  89. package/dist/kit/app.d.ts +35 -0
  90. package/dist/kit/handle.d.ts +34 -0
  91. package/dist/kit/handle.js +87 -0
  92. package/dist/kit/index.d.ts +30 -0
  93. package/dist/kit/index.js +5 -0
  94. package/dist/kit/load-consent.d.ts +57 -0
  95. package/dist/kit/load-consent.js +144 -0
  96. package/dist/kit/routes.d.ts +46 -0
  97. package/dist/kit/routes.js +203 -0
  98. package/dist/kit/types.d.ts +56 -0
  99. package/dist/kit/types.js +1 -0
  100. package/dist/primitives/accordion/accordion-item-content.svelte +35 -0
  101. package/dist/primitives/accordion/accordion-item-content.svelte.d.ts +9 -0
  102. package/dist/primitives/accordion/accordion-item-trigger.svelte +54 -0
  103. package/dist/primitives/accordion/accordion-item-trigger.svelte.d.ts +10 -0
  104. package/dist/primitives/accordion/accordion-item.svelte +61 -0
  105. package/dist/primitives/accordion/accordion-item.svelte.d.ts +11 -0
  106. package/dist/primitives/accordion/accordion-root.svelte +61 -0
  107. package/dist/primitives/accordion/accordion-root.svelte.d.ts +13 -0
  108. package/dist/primitives/accordion/context.d.ts +18 -0
  109. package/dist/primitives/accordion/context.js +23 -0
  110. package/dist/primitives/accordion/index.d.ts +29 -0
  111. package/dist/primitives/accordion/index.js +11 -0
  112. package/dist/primitives/collapsible/collapsible-content.svelte +36 -0
  113. package/dist/primitives/collapsible/collapsible-content.svelte.d.ts +9 -0
  114. package/dist/primitives/collapsible/collapsible-indicator.svelte +29 -0
  115. package/dist/primitives/collapsible/collapsible-indicator.svelte.d.ts +9 -0
  116. package/dist/primitives/collapsible/collapsible-root.svelte +70 -0
  117. package/dist/primitives/collapsible/collapsible-root.svelte.d.ts +11 -0
  118. package/dist/primitives/collapsible/collapsible-trigger.svelte +52 -0
  119. package/dist/primitives/collapsible/collapsible-trigger.svelte.d.ts +10 -0
  120. package/dist/primitives/collapsible/context.d.ts +10 -0
  121. package/dist/primitives/collapsible/context.js +12 -0
  122. package/dist/primitives/collapsible/index.d.ts +26 -0
  123. package/dist/primitives/collapsible/index.js +11 -0
  124. package/dist/primitives/dialog/context.d.ts +14 -0
  125. package/dist/primitives/dialog/context.js +12 -0
  126. package/dist/primitives/dialog/dialog-backdrop.svelte +39 -0
  127. package/dist/primitives/dialog/dialog-backdrop.svelte.d.ts +7 -0
  128. package/dist/primitives/dialog/dialog-close-trigger.svelte +48 -0
  129. package/dist/primitives/dialog/dialog-close-trigger.svelte.d.ts +11 -0
  130. package/dist/primitives/dialog/dialog-content.svelte +81 -0
  131. package/dist/primitives/dialog/dialog-content.svelte.d.ts +9 -0
  132. package/dist/primitives/dialog/dialog-description.svelte +28 -0
  133. package/dist/primitives/dialog/dialog-description.svelte.d.ts +9 -0
  134. package/dist/primitives/dialog/dialog-positioner.svelte +33 -0
  135. package/dist/primitives/dialog/dialog-positioner.svelte.d.ts +9 -0
  136. package/dist/primitives/dialog/dialog-root.svelte +117 -0
  137. package/dist/primitives/dialog/dialog-root.svelte.d.ts +14 -0
  138. package/dist/primitives/dialog/dialog-title.svelte +28 -0
  139. package/dist/primitives/dialog/dialog-title.svelte.d.ts +9 -0
  140. package/dist/primitives/dialog/index.d.ts +50 -0
  141. package/dist/primitives/dialog/index.js +19 -0
  142. package/dist/primitives/index.d.ts +7 -0
  143. package/dist/primitives/index.js +7 -0
  144. package/dist/primitives/portal/index.d.ts +4 -0
  145. package/dist/primitives/portal/index.js +2 -0
  146. package/dist/primitives/portal/portal.svelte +23 -0
  147. package/dist/primitives/portal/portal.svelte.d.ts +9 -0
  148. package/dist/primitives/preference-item/context.d.ts +11 -0
  149. package/dist/primitives/preference-item/context.js +12 -0
  150. package/dist/primitives/preference-item/index.d.ts +54 -0
  151. package/dist/primitives/preference-item/index.js +21 -0
  152. package/dist/primitives/preference-item/preference-item-auxiliary.svelte +33 -0
  153. package/dist/primitives/preference-item/preference-item-auxiliary.svelte.d.ts +9 -0
  154. package/dist/primitives/preference-item/preference-item-content.svelte +68 -0
  155. package/dist/primitives/preference-item/preference-item-content.svelte.d.ts +14 -0
  156. package/dist/primitives/preference-item/preference-item-control.svelte +33 -0
  157. package/dist/primitives/preference-item/preference-item-control.svelte.d.ts +9 -0
  158. package/dist/primitives/preference-item/preference-item-header.svelte +33 -0
  159. package/dist/primitives/preference-item/preference-item-header.svelte.d.ts +9 -0
  160. package/dist/primitives/preference-item/preference-item-leading.svelte +33 -0
  161. package/dist/primitives/preference-item/preference-item-leading.svelte.d.ts +9 -0
  162. package/dist/primitives/preference-item/preference-item-meta.svelte +33 -0
  163. package/dist/primitives/preference-item/preference-item-meta.svelte.d.ts +9 -0
  164. package/dist/primitives/preference-item/preference-item-root.svelte +82 -0
  165. package/dist/primitives/preference-item/preference-item-root.svelte.d.ts +12 -0
  166. package/dist/primitives/preference-item/preference-item-title.svelte +33 -0
  167. package/dist/primitives/preference-item/preference-item-title.svelte.d.ts +9 -0
  168. package/dist/primitives/preference-item/preference-item-trigger.svelte +62 -0
  169. package/dist/primitives/preference-item/preference-item-trigger.svelte.d.ts +10 -0
  170. package/dist/primitives/switch/context.d.ts +7 -0
  171. package/dist/primitives/switch/context.js +12 -0
  172. package/dist/primitives/switch/index.d.ts +25 -0
  173. package/dist/primitives/switch/index.js +11 -0
  174. package/dist/primitives/switch/switch-control.svelte +21 -0
  175. package/dist/primitives/switch/switch-control.svelte.d.ts +9 -0
  176. package/dist/primitives/switch/switch-hidden-input.svelte +31 -0
  177. package/dist/primitives/switch/switch-hidden-input.svelte.d.ts +8 -0
  178. package/dist/primitives/switch/switch-root.svelte +86 -0
  179. package/dist/primitives/switch/switch-root.svelte.d.ts +12 -0
  180. package/dist/primitives/switch/switch-thumb.svelte +14 -0
  181. package/dist/primitives/switch/switch-thumb.svelte.d.ts +7 -0
  182. package/dist/primitives/tabs/context.d.ts +11 -0
  183. package/dist/primitives/tabs/context.js +12 -0
  184. package/dist/primitives/tabs/index.d.ts +32 -0
  185. package/dist/primitives/tabs/index.js +11 -0
  186. package/dist/primitives/tabs/tabs-content.svelte +45 -0
  187. package/dist/primitives/tabs/tabs-content.svelte.d.ts +11 -0
  188. package/dist/primitives/tabs/tabs-list.svelte +38 -0
  189. package/dist/primitives/tabs/tabs-list.svelte.d.ts +10 -0
  190. package/dist/primitives/tabs/tabs-root.svelte +67 -0
  191. package/dist/primitives/tabs/tabs-root.svelte.d.ts +14 -0
  192. package/dist/primitives/tabs/tabs-trigger.svelte +108 -0
  193. package/dist/primitives/tabs/tabs-trigger.svelte.d.ts +11 -0
  194. package/dist/server/headers.d.ts +13 -0
  195. package/dist/server/headers.js +37 -0
  196. package/dist/server/index.d.ts +8 -0
  197. package/dist/server/index.js +116 -0
  198. package/dist/server/normalize-url.d.ts +23 -0
  199. package/dist/server/normalize-url.js +46 -0
  200. package/dist/server/types.d.ts +25 -0
  201. package/dist/server/types.js +1 -0
  202. package/dist/styles.css +10 -0
  203. package/dist/transports/offline.d.ts +14 -0
  204. package/dist/transports/offline.js +22 -0
  205. package/dist/types.d.ts +70 -0
  206. package/dist/types.js +1 -0
  207. package/dist/use-banner-visibility.svelte.d.ts +25 -0
  208. package/dist/use-banner-visibility.svelte.js +108 -0
  209. package/dist/utils.d.ts +25 -0
  210. package/dist/utils.js +32 -0
  211. package/dist/version.d.ts +1 -0
  212. package/dist/version.js +2 -0
  213. package/docs/README.md +88 -0
  214. package/docs/assets/v3/brand-bar.png +0 -0
  215. package/docs/assets/v3/brand-card.png +0 -0
  216. package/docs/assets/v3/choice-wall.png +0 -0
  217. package/docs/assets/v3/mobile-card.png +0 -0
  218. package/docs/assets/v3/preferences.png +0 -0
  219. package/docs/customization/overview.md +45 -0
  220. package/docs/customization/recipes.md +79 -0
  221. package/docs/customization/slots.md +55 -0
  222. package/docs/customization/tokens.md +76 -0
  223. package/docs/customization/translations.md +49 -0
  224. package/docs/frameworks/svelte/quickstart.md +133 -0
  225. package/docs/frameworks/sveltekit/quickstart.md +144 -0
  226. package/docs/guides/consent-state.md +60 -0
  227. package/docs/guides/data-fetching.md +163 -0
  228. package/docs/guides/deployment-modes.md +63 -0
  229. package/docs/guides/troubleshooting.md +68 -0
  230. package/docs/guides/verify-consent.md +62 -0
  231. package/docs/integrations/adobe-analytics.md +294 -0
  232. package/docs/integrations/ahrefs-analytics.md +291 -0
  233. package/docs/integrations/amplitude.md +292 -0
  234. package/docs/integrations/building-integrations.md +47 -0
  235. package/docs/integrations/clearbit.md +291 -0
  236. package/docs/integrations/cloudflare-web-analytics.md +292 -0
  237. package/docs/integrations/crisp.md +294 -0
  238. package/docs/integrations/databuddy.md +311 -0
  239. package/docs/integrations/fathom-analytics.md +293 -0
  240. package/docs/integrations/google-maps.md +384 -0
  241. package/docs/integrations/google-tag-manager.md +306 -0
  242. package/docs/integrations/google-tag.md +305 -0
  243. package/docs/integrations/heap.md +292 -0
  244. package/docs/integrations/hightouch.md +293 -0
  245. package/docs/integrations/hotjar.md +292 -0
  246. package/docs/integrations/intercom.md +285 -0
  247. package/docs/integrations/linkedin-insights.md +291 -0
  248. package/docs/integrations/logrocket.md +293 -0
  249. package/docs/integrations/matomo-analytics.md +316 -0
  250. package/docs/integrations/meta-pixel.md +285 -0
  251. package/docs/integrations/microsoft-clarity.md +292 -0
  252. package/docs/integrations/microsoft-uet.md +291 -0
  253. package/docs/integrations/mixpanel-analytics.md +295 -0
  254. package/docs/integrations/openai-pixel.md +441 -0
  255. package/docs/integrations/overview.md +111 -0
  256. package/docs/integrations/pirsch.md +295 -0
  257. package/docs/integrations/plausible-analytics.md +295 -0
  258. package/docs/integrations/posthog.md +397 -0
  259. package/docs/integrations/promptwatch.md +291 -0
  260. package/docs/integrations/reddit-pixel.md +294 -0
  261. package/docs/integrations/rudderstack.md +328 -0
  262. package/docs/integrations/rybbit-analytics.md +296 -0
  263. package/docs/integrations/segment.md +292 -0
  264. package/docs/integrations/snapchat-pixel.md +293 -0
  265. package/docs/integrations/tiktok-pixel.md +291 -0
  266. package/docs/integrations/umami-analytics.md +295 -0
  267. package/docs/integrations/vercel-analytics.md +293 -0
  268. package/docs/integrations/x-pixel.md +291 -0
  269. package/docs/integrations/youtube.md +405 -0
  270. package/docs/upgrade-v3.md +334 -0
  271. package/iab/styles.css +1 -0
  272. package/package.json +153 -0
  273. package/readme.json +36 -0
  274. package/styles.css +1 -0
@@ -0,0 +1,67 @@
1
+ <script lang="ts">
2
+ import type { TabsOrientation } from '@c15t/ui/primitives';
3
+ import { getDataDisabled } from '@c15t/ui/primitives';
4
+ import type { Snippet } from 'svelte';
5
+ import type { HTMLAttributes } from 'svelte/elements';
6
+
7
+ import { setTabsRootContext } from './context';
8
+
9
+ const componentId = $props.id();
10
+
11
+ let {
12
+ children,
13
+ class: className,
14
+ disabled = false,
15
+ loop = true,
16
+ orientation = 'horizontal',
17
+ value = $bindable<string | null>(null),
18
+ ...restProps
19
+ }: HTMLAttributes<HTMLDivElement> & {
20
+ children?: Snippet;
21
+ class?: string;
22
+ disabled?: boolean;
23
+ loop?: boolean;
24
+ orientation?: TabsOrientation;
25
+ value?: string | null;
26
+ } = $props();
27
+
28
+ const baseId = `c15t-tabs-${componentId}`;
29
+ const dataDisabled = $derived(getDataDisabled(disabled));
30
+
31
+ const setValue = function setValue(nextValue: string) {
32
+ if (disabled) {
33
+ return;
34
+ }
35
+
36
+ value = nextValue;
37
+ };
38
+
39
+ setTabsRootContext({
40
+ get baseId() {
41
+ return baseId;
42
+ },
43
+ get disabled() {
44
+ return disabled;
45
+ },
46
+ get loop() {
47
+ return loop;
48
+ },
49
+ get orientation() {
50
+ return orientation;
51
+ },
52
+ setValue,
53
+ get value() {
54
+ return value;
55
+ },
56
+ });
57
+ </script>
58
+
59
+ <div
60
+ class={className}
61
+ data-slot="tabs-root"
62
+ data-orientation={orientation}
63
+ data-disabled={dataDisabled}
64
+ {...restProps}
65
+ >
66
+ {@render children?.()}
67
+ </div>
@@ -0,0 +1,14 @@
1
+ import type { TabsOrientation } from '@c15t/ui/primitives';
2
+ import type { Snippet } from 'svelte';
3
+ import type { HTMLAttributes } from 'svelte/elements';
4
+ type $$ComponentProps = HTMLAttributes<HTMLDivElement> & {
5
+ children?: Snippet;
6
+ class?: string;
7
+ disabled?: boolean;
8
+ loop?: boolean;
9
+ orientation?: TabsOrientation;
10
+ value?: string | null;
11
+ };
12
+ declare const TabsRoot: import("svelte").Component<$$ComponentProps, {}, "value">;
13
+ type TabsRoot = ReturnType<typeof TabsRoot>;
14
+ export default TabsRoot;
@@ -0,0 +1,108 @@
1
+ <script lang="ts">
2
+ import {
3
+ getDataDisabled,
4
+ getNextTabValue,
5
+ getTabState,
6
+ } from '@c15t/ui/primitives';
7
+ import type { Snippet } from 'svelte';
8
+ import type { HTMLAttributes } from 'svelte/elements';
9
+
10
+ import { getTabsRootContext } from './context';
11
+
12
+ const root = getTabsRootContext();
13
+
14
+ let {
15
+ children,
16
+ class: className,
17
+ onclick,
18
+ onkeydown,
19
+ type = 'button',
20
+ value,
21
+ ...restProps
22
+ }: HTMLAttributes<HTMLButtonElement> & {
23
+ children?: Snippet;
24
+ class?: string;
25
+ type?: 'button' | 'submit' | 'reset';
26
+ value: string;
27
+ } = $props();
28
+
29
+ const baseId = $derived(root.baseId);
30
+ const disabled = $derived(root.disabled);
31
+ const selectedValue = $derived(root.value);
32
+ const isSelected = $derived(selectedValue === value);
33
+ const dataState = $derived(getTabState(isSelected));
34
+ const dataDisabled = $derived(getDataDisabled(disabled));
35
+ const triggerId = $derived(`${baseId}-trigger-${value}`);
36
+ const contentId = $derived(`${baseId}-content-${value}`);
37
+
38
+ const moveFocus = function moveFocus(nextValue: string) {
39
+ root.setValue(nextValue);
40
+
41
+ if (typeof document === 'undefined') {
42
+ return;
43
+ }
44
+
45
+ const nextButton = document.getElementById(
46
+ `${baseId}-trigger-${nextValue}`
47
+ );
48
+
49
+ if (nextButton instanceof HTMLButtonElement) {
50
+ nextButton.focus();
51
+ }
52
+ };
53
+
54
+ const handleKeyDown = function handleKeyDown(
55
+ event: KeyboardEvent & { currentTarget: EventTarget & HTMLButtonElement }
56
+ ) {
57
+ if (typeof document === 'undefined') {
58
+ onkeydown?.(event);
59
+ return;
60
+ }
61
+
62
+ const triggerValues = Array.from(
63
+ document.querySelectorAll<HTMLButtonElement>(
64
+ `[data-slot="tabs-trigger"][id^="${baseId}-trigger-"]`
65
+ )
66
+ ).map((button) => button.id.replace(`${baseId}-trigger-`, ''));
67
+
68
+ const nextValue = getNextTabValue({
69
+ currentValue: value,
70
+ key: event.key,
71
+ loop: root.loop,
72
+ orientation: root.orientation,
73
+ triggerValues,
74
+ });
75
+
76
+ if (nextValue !== value || event.key === 'Home' || event.key === 'End') {
77
+ event.preventDefault();
78
+ moveFocus(nextValue);
79
+ }
80
+ onkeydown?.(event);
81
+ };
82
+
83
+ const handleClick = function handleClick(
84
+ event: MouseEvent & { currentTarget: EventTarget & HTMLButtonElement }
85
+ ) {
86
+ root.setValue(value);
87
+ onclick?.(event);
88
+ };
89
+ </script>
90
+
91
+ <button
92
+ {type}
93
+ id={triggerId}
94
+ role="tab"
95
+ tabindex={isSelected ? 0 : -1}
96
+ aria-controls={contentId}
97
+ aria-selected={isSelected}
98
+ class={className}
99
+ data-slot="tabs-trigger"
100
+ data-state={dataState}
101
+ data-disabled={dataDisabled}
102
+ {disabled}
103
+ {...restProps}
104
+ onclick={handleClick}
105
+ onkeydown={handleKeyDown}
106
+ >
107
+ {@render children?.()}
108
+ </button>
@@ -0,0 +1,11 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ type $$ComponentProps = HTMLAttributes<HTMLButtonElement> & {
4
+ children?: Snippet;
5
+ class?: string;
6
+ type?: 'button' | 'submit' | 'reset';
7
+ value: string;
8
+ };
9
+ declare const TabsTrigger: import("svelte").Component<$$ComponentProps, {}, "">;
10
+ type TabsTrigger = ReturnType<typeof TabsTrigger>;
11
+ export default TabsTrigger;
@@ -0,0 +1,13 @@
1
+ declare const FORWARDED_HEADERS: readonly ["x-c15t-country", "cf-ipcountry", "x-vercel-ip-country", "x-amz-cf-ipcountry", "x-country-code", "x-country", "x-c15t-region", "cf-region-code", "x-vercel-ip-country-region", "x-region-code", "accept-language", "x-c15t-gpc", "sec-gpc", "user-agent", "x-forwarded-host", "x-forwarded-for", "purpose", "sec-purpose"];
2
+ type ForwardedHeader = (typeof FORWARDED_HEADERS)[number];
3
+ type RelevantHeaders = Partial<Record<ForwardedHeader, string>>;
4
+ /**
5
+ * Extracts relevant headers for consent management from the request headers.
6
+ *
7
+ * @param headersList - The Headers object from the incoming request
8
+ * @returns An object containing the relevant headers for consent management
9
+ *
10
+ * @public
11
+ */
12
+ export declare const extractRelevantHeaders: (headersList: Headers) => RelevantHeaders;
13
+ export {};
@@ -0,0 +1,37 @@
1
+ import { CONSENT_REQUEST_HEADER_NAMES, extractConsentRequestInputs, } from '@c15t/schema/types';
2
+ const SVELTE_EXTRA_HEADERS = [
3
+ 'user-agent',
4
+ 'x-forwarded-host',
5
+ 'x-forwarded-for',
6
+ 'purpose',
7
+ 'sec-purpose',
8
+ ];
9
+ const FORWARDED_HEADERS = [
10
+ ...CONSENT_REQUEST_HEADER_NAMES,
11
+ ...SVELTE_EXTRA_HEADERS,
12
+ ];
13
+ /**
14
+ * Extracts relevant headers for consent management from the request headers.
15
+ *
16
+ * @param headersList - The Headers object from the incoming request
17
+ * @returns An object containing the relevant headers for consent management
18
+ *
19
+ * @public
20
+ */
21
+ export const extractRelevantHeaders = function extractRelevantHeaders(headersList) {
22
+ const relevantHeaders = {};
23
+ for (const headerName of FORWARDED_HEADERS) {
24
+ const value = headersList.get(headerName);
25
+ if (value) {
26
+ relevantHeaders[headerName] = value;
27
+ }
28
+ }
29
+ const inputs = extractConsentRequestInputs(headersList);
30
+ if (inputs.country) {
31
+ relevantHeaders['x-c15t-country'] = inputs.country;
32
+ }
33
+ if (inputs.region) {
34
+ relevantHeaders['x-c15t-region'] = inputs.region;
35
+ }
36
+ return relevantHeaders;
37
+ };
@@ -0,0 +1,8 @@
1
+ import type { KernelConfig } from '@c15t/core';
2
+ import type { PrefetchInitialConsentOptions, ReadInitialConsentConfigOptions } from './types';
3
+ export declare const readInitialConsentConfig: (options: ReadInitialConsentConfigOptions) => Promise<KernelConfig>;
4
+ export declare const prefetchInitialConsent: (options: PrefetchInitialConsentOptions) => Promise<KernelConfig>;
5
+ export type { KernelConfig } from '@c15t/core';
6
+ export type { PrefetchInitialConsentOptions, ReadInitialConsentConfigOptions };
7
+ export { custom, hosted } from '@c15t/core';
8
+ export { offline } from '../transports/offline';
@@ -0,0 +1,116 @@
1
+ import { deferInitGvl, createHostedTransport, mergeInitResponseIntoKernelConfig, } from '@c15t/core';
2
+ import { readStoredRecordsFromCookieHeader } from '@c15t/core/modules/persistence';
3
+ import { consentInputsToOverrides, extractConsentRequestInputs, } from '@c15t/schema/types';
4
+ import { extractRelevantHeaders } from './headers';
5
+ import { normalizeBackendURL } from './normalize-url';
6
+ export const readInitialConsentConfig = function readInitialConsentConfig(options) {
7
+ const now = options.now ?? Date.now();
8
+ const cookieHeader = options.cookieHeader ?? options.headers.get('cookie') ?? undefined;
9
+ const initialRecords = readStoredRecordsFromCookieHeader(cookieHeader, options.cookieName ? { storageKey: options.cookieName } : undefined, now);
10
+ const inputs = extractConsentRequestInputs(options.headers, {
11
+ country: options.country,
12
+ language: options.language,
13
+ region: options.region,
14
+ });
15
+ const overrides = consentInputsToOverrides({
16
+ country: inputs.country,
17
+ language: inputs.language,
18
+ region: inputs.region,
19
+ });
20
+ const config = {
21
+ initialPrivacySignals: { gpc: options.headers.get('sec-gpc') === '1' },
22
+ initialRecords,
23
+ now,
24
+ };
25
+ if (Object.keys(overrides).length > 0) {
26
+ config.initialOverrides = overrides;
27
+ }
28
+ return Promise.resolve(config);
29
+ };
30
+ const createForwardHeaders = (options, overrides) => {
31
+ const forward = {
32
+ ...extractRelevantHeaders(options.headers),
33
+ };
34
+ const cookieHeader = options.cookieHeader ?? options.headers.get('cookie');
35
+ if (cookieHeader) {
36
+ forward.cookie = cookieHeader;
37
+ }
38
+ for (const key of options.forwardHeaders ?? []) {
39
+ const value = options.headers.get(key);
40
+ if (value) {
41
+ forward[key.toLowerCase()] = value;
42
+ }
43
+ }
44
+ if (overrides?.country) {
45
+ forward['x-c15t-country'] = overrides.country;
46
+ }
47
+ if (overrides?.region) {
48
+ forward['x-c15t-region'] = overrides.region;
49
+ }
50
+ if (options.language) {
51
+ forward['accept-language'] = options.language;
52
+ }
53
+ return forward;
54
+ };
55
+ export const prefetchInitialConsent = async function prefetchInitialConsent(options) {
56
+ const base = await readInitialConsentConfig(options);
57
+ const absoluteBackend = normalizeBackendURL(options.backendURL, options.headers);
58
+ if (!absoluteBackend) {
59
+ return base;
60
+ }
61
+ const forward = createForwardHeaders(options, base.initialOverrides);
62
+ try {
63
+ const fetchImpl = options.fetch ??
64
+ options.frameworkFetch ??
65
+ globalThis.fetch?.bind(globalThis);
66
+ if (!fetchImpl) {
67
+ return base;
68
+ }
69
+ const transport = createHostedTransport({
70
+ backendURL: absoluteBackend,
71
+ // Server-request forwarding is broader than the hosted client's
72
+ // header allowlist. Keep the transport's protocol headers authoritative.
73
+ fetch: (input, init) => {
74
+ const headers = new Headers(forward);
75
+ new Headers(init?.headers).forEach((value, key) => {
76
+ headers.set(key, value);
77
+ });
78
+ // Keep the caller's full language preference list. The normalized
79
+ // kernel language is for policy resolution, not HTTP forwarding.
80
+ if (forward['accept-language']) {
81
+ headers.set('accept-language', forward['accept-language']);
82
+ }
83
+ return fetchImpl(input, { ...init, headers });
84
+ },
85
+ });
86
+ const response = await transport.init?.({
87
+ overrides: base.initialOverrides ?? {},
88
+ user: base.initialUser ?? null,
89
+ });
90
+ if (!response) {
91
+ return base;
92
+ }
93
+ const merged = mergeInitResponseIntoKernelConfig(base, options.fetch ||
94
+ forward.cookie ||
95
+ (options.frameworkFetch && options.headers.has('authorization')) ||
96
+ options.forwardHeaders?.some((name) => options.headers.has(name))
97
+ ? response
98
+ : deferInitGvl(response, `${absoluteBackend}/init`, 'init', forward));
99
+ if (response.subjectId) {
100
+ merged.initialRecords = {
101
+ ...merged.initialRecords,
102
+ subject: {
103
+ ...merged.initialRecords?.subject,
104
+ subjectId: response.subjectId,
105
+ },
106
+ };
107
+ }
108
+ delete merged.initialDraft;
109
+ return merged;
110
+ }
111
+ catch {
112
+ return base;
113
+ }
114
+ };
115
+ export { custom, hosted } from '@c15t/core';
116
+ export { offline } from '../transports/offline';
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Validates and normalizes a backend URL.
3
+ *
4
+ * @param backendURL - The URL to validate (absolute or relative)
5
+ * @returns An object with isAbsolute flag and the normalized URL
6
+ * @throws {Error} If the URL format is invalid
7
+ *
8
+ * @public
9
+ */
10
+ export declare const validateBackendURL: (backendURL: string) => {
11
+ isAbsolute: boolean;
12
+ normalizedURL: string;
13
+ };
14
+ /**
15
+ * Normalizes a backend URL, resolving relative URLs using request headers.
16
+ *
17
+ * @param backendURL - The backend URL (absolute or relative)
18
+ * @param headersList - The Headers object from the incoming request
19
+ * @returns The normalized absolute URL, or null if it cannot be determined
20
+ *
21
+ * @public
22
+ */
23
+ export declare const normalizeBackendURL: (backendURL: string, headersList: Headers) => string | null;
@@ -0,0 +1,46 @@
1
+ import { resolveBackendURL } from '@c15t/schema/types';
2
+ const ABSOLUTE_URL_REGEX = /^https?:\/\//u;
3
+ const trimTrailingSlash = function trimTrailingSlash(url) {
4
+ if (url === '/') {
5
+ return url;
6
+ }
7
+ return url.endsWith('/') ? url.slice(0, -1) : url;
8
+ };
9
+ /**
10
+ * Validates and normalizes a backend URL.
11
+ *
12
+ * @param backendURL - The URL to validate (absolute or relative)
13
+ * @returns An object with isAbsolute flag and the normalized URL
14
+ * @throws {Error} If the URL format is invalid
15
+ *
16
+ * @public
17
+ */
18
+ export const validateBackendURL = function validateBackendURL(backendURL) {
19
+ const isAbsolute = ABSOLUTE_URL_REGEX.test(backendURL);
20
+ if (isAbsolute) {
21
+ String(new URL(backendURL));
22
+ return {
23
+ isAbsolute: true,
24
+ normalizedURL: trimTrailingSlash(backendURL),
25
+ };
26
+ }
27
+ if (backendURL.startsWith('/')) {
28
+ return {
29
+ isAbsolute: false,
30
+ normalizedURL: trimTrailingSlash(backendURL),
31
+ };
32
+ }
33
+ throw new Error(`Invalid URL format: ${backendURL}. URL must be absolute (https://...) or relative starting with (/)`);
34
+ };
35
+ /**
36
+ * Normalizes a backend URL, resolving relative URLs using request headers.
37
+ *
38
+ * @param backendURL - The backend URL (absolute or relative)
39
+ * @param headersList - The Headers object from the incoming request
40
+ * @returns The normalized absolute URL, or null if it cannot be determined
41
+ *
42
+ * @public
43
+ */
44
+ export const normalizeBackendURL = function normalizeBackendURL(backendURL, headersList) {
45
+ return resolveBackendURL(backendURL, headersList);
46
+ };
@@ -0,0 +1,25 @@
1
+ export interface ReadInitialConsentConfigOptions {
2
+ headers: Headers;
3
+ /** Request clock shared with the client seed. */
4
+ now?: number;
5
+ cookieHeader?: string | null;
6
+ /**
7
+ * Cookie name holding persisted consent. Defaults to `c15t` — the
8
+ * persistence module's storage key. Set this only if you customized
9
+ * `storageConfig.storageKey` client-side; it must match.
10
+ */
11
+ cookieName?: string;
12
+ country?: string;
13
+ region?: string;
14
+ language?: string;
15
+ }
16
+ export interface PrefetchInitialConsentOptions extends ReadInitialConsentConfigOptions {
17
+ backendURL: string;
18
+ fetch?: typeof globalThis.fetch;
19
+ /**
20
+ * Default request fetch supplied by the SvelteKit adapter.
21
+ * @internal
22
+ */
23
+ frameworkFetch?: typeof globalThis.fetch;
24
+ forwardHeaders?: string[];
25
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @c15t/svelte — Non-IAB prebuilt component styles.
3
+ *
4
+ * Import this stylesheet once from your app-level CSS entrypoint
5
+ * when using prebuilt (styled) consent components.
6
+ *
7
+ * Usage (src/app.css):
8
+ * @import "@c15t/svelte/styles.css";
9
+ */
10
+ @import '@c15t/ui/styles.css';
@@ -0,0 +1,14 @@
1
+ import type { ProviderTransportFactory } from '@c15t/core';
2
+ import type { PolicyRule } from '@c15t/schema/types';
3
+ /** Policy rules evaluated locally when initialization runs. */
4
+ export interface OfflineModeOptions {
5
+ policyRules?: PolicyRule[];
6
+ }
7
+ /**
8
+ * Resolve local rules outside render and hydration.
9
+ * @param options - Explicit policy rules; absence resolves the recommended
10
+ * pack: strict opt-in for Europe and unknown locations, opt-out for the US
11
+ * privacy states, and `none` where no consent law grants rights.
12
+ * @returns A provider transport with no network requests.
13
+ */
14
+ export declare const offline: (options?: OfflineModeOptions) => ProviderTransportFactory;
@@ -0,0 +1,22 @@
1
+ import { recommendedPolicyRules, resolvePolicyRules, writePolicyResolutionWire, } from '@c15t/schema/types';
2
+ /**
3
+ * Resolve local rules outside render and hydration.
4
+ * @param options - Explicit policy rules; absence resolves the recommended
5
+ * pack: strict opt-in for Europe and unknown locations, opt-out for the US
6
+ * privacy states, and `none` where no consent law grants rights.
7
+ * @returns A provider transport with no network requests.
8
+ */
9
+ export const offline = function offline(options = {}) {
10
+ return Object.assign((context) => ({
11
+ init: ({ overrides }) => Promise.resolve({
12
+ policyResolution: writePolicyResolutionWire(resolvePolicyRules({
13
+ countryCode: overrides.country ?? null,
14
+ iabEnabled: context.iabEnabled,
15
+ regionCode: overrides.region ?? null,
16
+ rules: options.policyRules ??
17
+ recommendedPolicyRules({ iab: context.iabEnabled }),
18
+ })),
19
+ translations: context.translations,
20
+ }),
21
+ }), { kind: 'offline' });
22
+ };
@@ -0,0 +1,70 @@
1
+ import type { IABConfig, LegalLinks, ProviderTransportFactory } from '@c15t/core';
2
+ import type { ConsentRuntimeOptions, RuntimeNetworkBlockerOptions, RuntimePersistenceOptions, RuntimeScriptLoaderOptions } from '@c15t/core/runtime';
3
+ import type { CreateIABOptions } from '@c15t/iab';
4
+ import type { Theme, UIOptions } from '@c15t/ui/theme';
5
+ /** IAB options a provider accepts, or `false` to leave IAB unmounted. */
6
+ export type ProviderIABOptions = (Partial<Omit<CreateIABOptions, 'kernel' | 'gvl'>> & Partial<Pick<IABConfig, 'enabled' | 'cmpId' | 'cmpVersion' | 'vendors'>> & Partial<Pick<CreateIABOptions, 'gvl'>>) | false;
7
+ /**
8
+ * Options for the script-loader module.
9
+ *
10
+ * The runtime's own contract, re-exported under this package's `use*`
11
+ * naming so the Svelte hooks and the runtime cannot drift apart.
12
+ *
13
+ * @see {@link https://c15t.com/docs/frameworks/svelte}
14
+ */
15
+ export type UseScriptLoaderOptions = RuntimeScriptLoaderOptions;
16
+ /**
17
+ * Options for the network-blocker module.
18
+ *
19
+ * The runtime's own contract, re-exported under this package's `use*`
20
+ * naming so the Svelte hooks and the runtime cannot drift apart.
21
+ */
22
+ export type UseNetworkBlockerOptions = RuntimeNetworkBlockerOptions;
23
+ /**
24
+ * Options for the persistence module.
25
+ *
26
+ * The runtime's own contract, re-exported under this package's `use*`
27
+ * naming so the Svelte hooks and the runtime cannot drift apart.
28
+ */
29
+ export type UsePersistenceOptions = RuntimePersistenceOptions;
30
+ /**
31
+ * Options accepted by `<ConsentManagerProvider>`.
32
+ *
33
+ * Everything except the fields below is the framework-agnostic
34
+ * {@link ConsentRuntimeOptions} contract, forwarded untouched to
35
+ * `createConsentRuntime()` from `@c15t/core/runtime`. `createIAB` is
36
+ * supplied by this package, and `pkg` is fixed to `'@c15t/svelte'`.
37
+ */
38
+ export interface ConsentManagerOptions extends Omit<ConsentRuntimeOptions, 'createIAB' | 'iab' | 'mode' | 'pkg'>, Pick<UIOptions, 'colorScheme' | 'disableAnimation' | 'noStyle' | 'scrollLock' | 'trapFocus'> {
39
+ /**
40
+ * Transport factory the provider builds its kernel with. Required.
41
+ *
42
+ * Pass `hosted()` to talk to a c15t backend, `offline()` to resolve
43
+ * policies locally with no network, or `custom()` to supply your own
44
+ * kernel transport or v2 endpoint handlers. This is an initial-only
45
+ * option: remount the provider to change it.
46
+ *
47
+ * @example
48
+ * ```svelte
49
+ * <script lang="ts">
50
+ * import { ConsentManagerProvider, hosted } from '@c15t/svelte';
51
+ *
52
+ * let { children } = $props();
53
+ * </script>
54
+ *
55
+ * <ConsentManagerProvider mode={hosted({ url: '/api/c15t' })}>
56
+ * {@render children()}
57
+ * </ConsentManagerProvider>
58
+ * ```
59
+ */
60
+ mode: ProviderTransportFactory;
61
+ /** IAB TCF configuration. Pass `false` to disable the TCF addon. */
62
+ iab?: ProviderIABOptions;
63
+ /** Links rendered in the banner and preference-center footers. */
64
+ legalLinks?: LegalLinks;
65
+ /** Design-token overrides applied as a `<style id="c15t-theme">` block. */
66
+ theme?: Theme;
67
+ }
68
+ export type SvelteUIOptions = UIOptions;
69
+ /** Public policy lifecycle callbacks. */
70
+ export type ConsentProviderCallbacks = NonNullable<ConsentRuntimeOptions['callbacks']>;
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Visibility / mount lifecycle for the consent banner.
3
+ *
4
+ * - On show: mounts the element with `.bannerHidden`, awaits Svelte commit,
5
+ * forces a reflow so the browser observes that initial style, then flips
6
+ * to `.bannerVisible`. The CSS transition fires automatically — no JS
7
+ * timing coordination.
8
+ * - On hide: flips to `.bannerHidden`, then unmounts after the duration
9
+ * declared by the `--consent-banner-animation-duration` CSS variable.
10
+ * - When animation is disabled (provider option or `prefers-reduced-motion`):
11
+ * toggles synchronously, skipping the show reflow and the hide timer.
12
+ * - Server render: when the very first evaluation already says "show" — which
13
+ * only happens once a `prefetch` has seeded a resolved policy, since
14
+ * without one the kernel's model is `null` and `activeUI` is `'none'` — the
15
+ * banner starts mounted and *visible*. That puts the shell in the first
16
+ * HTML and skips the entry animation on hydration, which would otherwise
17
+ * replay an animation the user has already seen painted. Client-triggered
18
+ * shows still take the animated path.
19
+ */
20
+ export declare const useBannerVisibility: (getShouldShow: () => boolean, getDisableAnimation: () => boolean) => {
21
+ bannerEl: HTMLElement | undefined;
22
+ readonly isMounted: boolean;
23
+ readonly isVisible: boolean;
24
+ readonly shouldRender: boolean;
25
+ };