@vskstudio/takt-astro 0.9.1 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # @vskstudio/takt-astro
2
2
 
3
3
 
4
- > 📚 **Documentation** — [taktlytics.com/docs/wrappers/astro](https://taktlytics.com/docs/wrappers/astro)
4
+ > 📚 **Documentation**: [taktlytics.com/docs/wrappers/astro](https://taktlytics.com/docs/wrappers/astro)
5
5
 
6
- Astro integration for [Takt](https://github.com/taktlytics/takt-core), privacy-friendly analytics. It injects a tiny browser runtime that boots Takt, fires the initial pageview, and tracks client-side navigations — including [Astro View Transitions](https://docs.astro.build/en/guides/view-transitions/).
6
+ Astro integration for [Takt](https://github.com/taktlytics/takt-core), privacy-friendly analytics. It injects a tiny browser runtime that boots Takt, fires the initial pageview, and tracks client-side navigations, including [Astro View Transitions](https://docs.astro.build/en/guides/view-transitions/).
7
7
 
8
8
  ## Install
9
9
 
@@ -11,11 +11,11 @@ Astro integration for [Takt](https://github.com/taktlytics/takt-core), privacy-f
11
11
  pnpm add @vskstudio/takt-astro @vskstudio/takt-core
12
12
  ```
13
13
 
14
- Both are peer dependencies: `astro` (`>=4`) and `@vskstudio/takt-core` (`>=0.10.0`).
14
+ Both are peer dependencies: `astro` (`>=4`) and `@vskstudio/takt-core` (`>=0.12.1`).
15
15
 
16
16
  ## Usage
17
17
 
18
- Pick **one** of the two paths below — not both. Both boot core's default instance, guarded by a shared `window.__takt` flag: installing both does not double-count (the second boot is skipped), but it ships the runtime twice for nothing.
18
+ Pick **one** of the two paths below, not both. Both boot core's default instance, guarded by a shared `window.__takt` flag: installing both does not double-count (the second boot is skipped), but it ships the runtime twice for nothing.
19
19
 
20
20
  ### Integration (recommended)
21
21
 
@@ -50,21 +50,23 @@ Both the integration and the component accept the same options, with one excepti
50
50
  | --- | --- | --- | --- |
51
51
  | `domain` | `string` | `location.hostname` | Site identifier sent with every event. |
52
52
  | `endpoint` | `string` | `https://taktlytics.com/api/event` | Ingestion endpoint. Pass `/api/event` for a same-origin first-party proxy. |
53
- | `scriptOrigin` | `string` | – | First-party origin to derive the endpoint from (`{origin}/api/event`) — your Takt domain or a custom domain to dodge ad-blockers (endpoint wins over it). |
53
+ | `scriptOrigin` | `string` | n/a | First-party origin to derive the endpoint from (`{origin}/api/event`): your Takt domain or a custom domain to dodge ad-blockers (endpoint wins over it). |
54
54
  | `outbound` | `boolean` | `false` | Auto-track outbound link clicks. |
55
- | `files` | `boolean` | `false` | Auto-track file downloads, using core's default extension list (this integration does not expose an extension override). |
55
+ | `files` | `boolean` | `false` | Auto-track file downloads. Narrow the extensions with `fileExtensions`. |
56
+ | `fileExtensions` | `string[]` | core's list | File extensions counted as downloads when `files` is on, e.g. `['pdf', 'zip']`. |
56
57
  | `track404` | `boolean` | `false` | Report a `404` event when the page is an error page (`[data-takt-404]` / `<meta name="takt:404">` marker, or a 404 HTTP status). |
57
58
  | `spa` | `boolean` | `true` | Track client-side navigations. |
58
59
  | `respectDnt` | `boolean` | `true` | Suppress events when Do Not Track is on. |
59
60
  | `excludeLocalhost` | `boolean` | `true` | Suppress events on localhost / private IPs. |
60
- | `enabled` | `boolean` | `true` | Master kill switch — set `false` to suppress every event. |
61
- | `sampleRate` | `number` | `1` | Fraction of visitors to track, `0`–`1`. |
61
+ | `enabled` | `boolean` | `true` | Master kill switch: set `false` to suppress every event. |
62
+ | `sampleRate` | `number` | `1` | Fraction of visitors to track, `0` to `1`. |
62
63
  | `trackQuery` | `boolean` | `false` | Keep the full query string and hash instead of stripping them. Wins over `queryParams`. |
63
- | `queryParams` | `string[]` | – | Allowlist of query params to keep, applied only when `trackQuery` is off. |
64
- | `exclude` | `string[]` | – | Path prefixes never tracked, e.g. `['/app', '/account']` (segment-bounded, checked at send time). |
64
+ | `queryParams` | `string[]` | n/a | Allowlist of query params to keep, applied only when `trackQuery` is off. |
65
+ | `exclude` | `string[]` | n/a | Path prefixes never tracked, e.g. `['/app', '/account']`. Segment-bounded, case-insensitive, blind to a trailing slash, and matched on the percent-decoded path (checked at send time). |
65
66
  | `redactRoutes` | `string[]` | none | Route patterns sent in place of the real path, e.g. `['/verify/[token]']` sends `/verify/[token]` instead of `/verify/abc123`. See [Route redaction](#route-redaction). |
67
+ | `redactUndecodablePaths` | `boolean` | `true` | When a route is configured, a path that cannot be decoded is sent as `/[redacted]`. Set `false` to decode it leniently and match it against the routes instead. |
66
68
  | `routeTemplates` | `boolean` | `false` | Send every page as its Astro route template (`/blog/[slug]`), read from `Astro.routePattern`. Needs Astro 5 and the route meta, see [Route redaction](#route-redaction). |
67
- | `scrubUrl` | `(url: string) => string` | – | **Integration only.** Rewrite each URL before it is sent (page, referrer, and the `url` prop of outbound-link and file-download events), e.g. to strip a fragment or PII. See the note below. |
69
+ | `scrubUrl` | `(url: string) => string` | n/a | **Integration only.** Rewrite each URL before it is sent (page, referrer, and the `url` prop of outbound-link and file-download events), e.g. to strip a fragment or PII. See the note below. |
68
70
  | `tagged` | `boolean` | `false` | Auto-track clicks on `[data-takt-event]` elements; `data-takt-prop-*` attributes become event props. |
69
71
  | `debug` | `boolean` | `false` | Log each payload to the browser console before sending. |
70
72
 
@@ -72,16 +74,38 @@ Both the integration and the component accept the same options, with one excepti
72
74
  > is supported **only via the integration**, not the `<Takt />` component. The
73
75
  > integration serializes config into a build-time runtime string, so `scrubUrl` is
74
76
  > stringified with `.toString()` and re-evaluated in the browser. It MUST be a
75
- > **self-contained** function — no closure variables or outer-scope references — and
77
+ > **self-contained** function. No closure variables or outer-scope references, and
76
78
  > must be **developer-controlled**: never build it from user input.
77
79
  >
78
80
  > The `<Takt />` component serializes its config as a JSON data island, which cannot
79
- > carry a function — so passing `scrubUrl` to `<Takt />` **throws at build time**
81
+ > carry a function. So passing `scrubUrl` to `<Takt />` **throws at build time**
80
82
  > rather than silently doing nothing. Use the integration if you need it.
81
83
 
84
+ ### Examples
85
+
86
+ Downloads of selected file types only, with `files` on and `fileExtensions` narrowing the default list:
87
+
88
+ ```js
89
+ takt({ files: true, fileExtensions: ['pdf', 'zip'] })
90
+ ```
91
+
92
+ Count 404 pages (the page must carry the `[data-takt-404]` marker or answer with a 404 status):
93
+
94
+ ```js
95
+ takt({ track404: true })
96
+ ```
97
+
98
+ Keep the real path for any route that does not decode, by setting `redactUndecodablePaths: false` (the default `true` sends it as `/[redacted]`):
99
+
100
+ ```js
101
+ takt({ redactRoutes: ['/verify/[token]'], redactUndecodablePaths: false })
102
+ ```
103
+
104
+ The same settings exist as attributes of the standalone `takt.auto.js` script: `redactRoutes` is `data-redact-routes`, `redactUndecodablePaths` is `data-redact-undecodable-paths`, `fileExtensions` is `data-downloads-ext`, and the opt-in features are listed in `data-auto` (`outbound`, `downloads` for `files`, `tagged`, `404` for `track404`).
105
+
82
106
  ## View Transitions
83
107
 
84
- Astro's client router runs several history operations per navigation (scroll-restoration `replaceState` plus `pushState`), so Takt does **not** rely on core's history patch here — it would over-count. Instead the runtime fires one explicit initial pageview and then one per Astro `astro:after-swap` event (including View Transitions DOM swaps and back/forward), so each navigation is counted exactly once. On a plain MPA (no client router) the script re-runs per page load, which fires the initial pageview each time. The runtime is SSR/prerender safe — it only runs in the browser.
108
+ Astro's client router runs several history operations per navigation (scroll-restoration `replaceState` plus `pushState`), so Takt does **not** rely on core's history patch here. It would over-count. Instead the runtime fires one explicit initial pageview and then one per Astro `astro:after-swap` event (including View Transitions DOM swaps and back/forward), so each navigation is counted exactly once. On a plain MPA (no client router) the script re-runs per page load, which fires the initial pageview each time. The runtime is SSR/prerender safe. It only runs in the browser.
85
109
 
86
110
  ## Route redaction
87
111
 
@@ -91,7 +115,9 @@ Query strings are stripped by default, but path segments are sent as they are, s
91
115
  takt({ redactRoutes: ['/verify/[token]', '/invoices/[id].pdf'] })
92
116
  ```
93
117
 
94
- The rule covers the page URL, same-origin referrers, outbound and download link destinations, and 404 paths. Patterns use Astro's syntax (`[param]`, `[...rest]`) and also accept `:param` and `*`.
118
+ The rule covers the page URL, same-origin referrers, outbound and download link destinations, and 404 paths. Patterns use Astro's syntax (`[param]`, `[[optional]]`, `[...rest]`), the Vue / React / Angular / Solid syntax (`:param`, `:param?`, `*`, `**`), and the Laravel / Symfony braces (`{param}`, `{param?}`, `{param<regex>}`). Matching is case-insensitive and runs on the decoded path.
119
+
120
+ A `{param<regex>}` constraint must follow a restricted grammar (printable ASCII, literals, `.`, `\d`, `\w`, `\s` and their negations, character classes, top-level alternation, bounded quantifiers). A route whose constraint falls outside it is never sent raw: every matching path is masked as `/[redacted]`. A path that cannot be decoded follows `redactUndecodablePaths` (see the options table).
95
121
 
96
122
  To send every page as its route template instead (`/blog/hello` becomes `/blog/[slug]`), turn on `routeTemplates`. Astro knows the template on the server (`Astro.routePattern`), so it travels in a `<meta name="takt:route">` tag that the runtime reads at each pageview, including after a ClientRouter navigation. With the integration, render that tag with `<TaktRoute />` in the `<head>` of your layout:
97
123
 
@@ -166,15 +192,15 @@ import Embed from '@vskstudio/takt-astro/Embed.astro'
166
192
  <Embed domain="example.com" theme="dark" />
167
193
  ```
168
194
 
169
- `Badge` renders an `<img>` (props: `domain` — required —, `variant` `a` | `b` | `d`, `glyph` `unplug` | `dash` | `off` | `eyeoff`, `lang` `fr` | `en`, `host`). Its `alt` defaults to `"takt"` and can be overridden; `loading="lazy"` and `decoding="async"` are applied after your attributes and cannot.
195
+ `Badge` renders an `<img>` (props: `domain` (required), `variant` `a` | `b` | `d`, `glyph` `unplug` | `dash` | `off` | `eyeoff`, `lang` `fr` | `en`, `host`). Its `alt` defaults to `"takt"` and can be overridden; `loading="lazy"` and `decoding="async"` are applied after your attributes and cannot.
170
196
 
171
- `Embed` renders an `<iframe>` (props: `domain` — required —, `theme` `light` | `dark` | `auto`, `lang`, `host`, plus `width` = `404`, `height` = `264`, `title` = `"takt"`); the iframe is sandboxed (`allow-scripts allow-same-origin`) and ships a fixed `referrerpolicy="strict-origin-when-cross-origin"`, a `loading="lazy"` and a zero border — all applied after your attributes, so a consumer cannot weaken them. Extra attributes pass through to the underlying element, but the built `src` is locked and cannot be overridden. The optional `host` must be an absolute `http(s)` URL — core validates it and throws on anything else (e.g. a `javascript:` URL), and reduces it to its origin (dropping path/query). Omitting `host` falls back to the hosted Takt origin (`https://taktlytics.com`), not to the current origin.
197
+ `Embed` renders an `<iframe>` (props: `domain` (required), `theme` `light` | `dark` | `auto`, `lang`, `host`, plus `width` = `404`, `height` = `264`, `title` = `"takt"`); the iframe is sandboxed (`allow-scripts allow-same-origin`) and ships a fixed `referrerpolicy="strict-origin-when-cross-origin"`, a `loading="lazy"` and a zero border: all applied after your attributes, so a consumer cannot weaken them. Extra attributes pass through to the underlying element, but the built `src` is locked and cannot be overridden. The optional `host` must be an absolute `http(s)` URL. Core validates it and throws on anything else (e.g. a `javascript:` URL), and reduces it to its origin (dropping path/query). Omitting `host` falls back to the hosted Takt origin (`https://taktlytics.com`), not to the current origin.
172
198
 
173
199
  ## Public stats
174
200
 
175
201
  `createStats` (re-exported from core) reads public analytics:
176
202
 
177
- Every method takes the domain first and the params second — the domain is optional once `createStats` is bound to one:
203
+ Every method takes the domain first and the params second: the domain is optional once `createStats` is bound to one:
178
204
 
179
205
  ```js
180
206
  import { createStats, PublicApiError } from '@vskstudio/takt-astro'
@@ -194,10 +220,10 @@ try {
194
220
 
195
221
  From `@vskstudio/takt-astro`:
196
222
 
197
- - `default` / `takt` — the integration factory (same function under both names)
198
- - `resolveOptions`, `assertNoScrubUrl`, `buildRuntime` — the internals the `.astro` components build on, exported so you can drive the runtime yourself
199
- - Re-exported from core: `track`, `pageview`, `optOut`, `optIn`, `isOptedOut`, `createStats`, `PublicApiError`, `badgeUrl`, `embedUrl`
200
- - Types: `TaktOptions`, plus `InitOptions`, `TrackOptions`, `BadgeOptions`, `EmbedOptions`, `BadgeVariant`, `BadgeGlyph`, `EmbedTheme`, `WidgetLang`, `StatsClient`, `StatsClientOptions`, `StatsParams`, `StatsPeriod`, `StatsDimension`, `StatsMetrics`, `StatsSummary`, `StatsPoint`, `StatsTimeseries`, `StatsBreakdownRow`, `StatsBreakdown`, `StatsRealtime` re-exported from core
223
+ - `default` / `takt`: the integration factory (same function under both names)
224
+ - `resolveOptions`, `assertNoScrubUrl`, `buildRuntime`: the internals the `.astro` components build on, exported so you can drive the runtime yourself
225
+ - Re-exported from core: `track`, `pageview`, `optOut`, `optIn`, `isOptedOut`, `createStats`, `PublicApiError`, `badgeUrl`, `embedUrl`, `normalizeHost`
226
+ - Types: `TaktOptions`, plus `InitOptions`, `TrackOptions`, `Payload`, `BadgeOptions`, `EmbedOptions`, `BadgeVariant`, `BadgeGlyph`, `EmbedTheme`, `WidgetLang`, `StatsClient`, `StatsClientOptions`, `StatsParams`, `StatsPeriod`, `StatsDimension`, `StatsMetrics`, `StatsSummary`, `StatsPoint`, `StatsTimeseries`, `StatsBreakdownRow`, `StatsBreakdown`, `StatsRealtime` re-exported from core
201
227
 
202
228
  Component subpaths: `@vskstudio/takt-astro/Takt.astro`, `/TaktRoute.astro`, `/Badge.astro`, `/Embed.astro`.
203
229
 
package/Takt.astro CHANGED
@@ -21,7 +21,7 @@ const config = JSON.stringify(resolveOptions(Astro.props))
21
21
  const route = Astro.props.routeTemplates ? Astro.routePattern : undefined
22
22
  ---
23
23
  {route && <meta name="takt:route" content={route} />}
24
- <!-- Pick ONE install path — this component OR the integration — not both. -->
24
+ <!-- Pick ONE install path: this component OR the integration, not both. -->
25
25
  <script type="application/json" data-takt-config set:html={config}></script>
26
26
  <!-- A bundled (non-inline) module so Astro resolves the bare core import; an
27
27
  is:inline module would leave it unresolved in the browser. -->
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { AstroIntegration } from 'astro';
2
2
  import { InitOptions } from '@vskstudio/takt-core';
3
- export { BadgeGlyph, BadgeOptions, BadgeVariant, EmbedOptions, EmbedTheme, InitOptions, PublicApiError, StatsBreakdown, StatsBreakdownRow, StatsClient, StatsClientOptions, StatsDimension, StatsMetrics, StatsParams, StatsPeriod, StatsPoint, StatsRealtime, StatsSummary, StatsTimeseries, TrackOptions, WidgetLang, badgeUrl, createStats, embedUrl, isOptedOut, optIn, optOut, pageview, track } from '@vskstudio/takt-core';
3
+ export { BadgeGlyph, BadgeOptions, BadgeVariant, EmbedOptions, EmbedTheme, InitOptions, Payload, PublicApiError, StatsBreakdown, StatsBreakdownRow, StatsClient, StatsClientOptions, StatsDimension, StatsMetrics, StatsParams, StatsPeriod, StatsPoint, StatsRealtime, StatsSummary, StatsTimeseries, TrackOptions, WidgetLang, badgeUrl, createStats, embedUrl, isOptedOut, normalizeHost, optIn, optOut, pageview, track } from '@vskstudio/takt-core';
4
4
 
5
5
  /**
6
6
  * Options for the Takt integration and `<Takt />` component. Mirrors core's
@@ -12,7 +12,7 @@ interface TaktOptions {
12
12
  /** Ingestion endpoint. Defaults to `https://taktlytics.com/api/event` (the hosted Takt origin); pass `/api/event` for a same-origin first-party proxy. */
13
13
  endpoint?: string;
14
14
  /**
15
- * First-party origin to derive the endpoint from (`{origin}/api/event`) — a
15
+ * First-party origin to derive the endpoint from (`{origin}/api/event`): a
16
16
  * custom domain you proxy through to dodge ad-blockers. `endpoint` wins over it.
17
17
  */
18
18
  scriptOrigin?: string;
@@ -20,6 +20,7 @@ interface TaktOptions {
20
20
  outbound?: boolean;
21
21
  /** Auto-track file downloads. */
22
22
  files?: boolean;
23
+ fileExtensions?: string[];
23
24
  /**
24
25
  * Report a `404` event when the page is an error page (`[data-takt-404]` /
25
26
  * `<meta name="takt:404">` marker, or a 404 HTTP status).
@@ -31,9 +32,9 @@ interface TaktOptions {
31
32
  respectDnt?: boolean;
32
33
  /** Suppress events on localhost and private IP ranges. Default `true`. */
33
34
  excludeLocalhost?: boolean;
34
- /** Master kill switch — when `false`, every event is suppressed. */
35
+ /** Master kill switch: when `false`, every event is suppressed. */
35
36
  enabled?: boolean;
36
- /** Fraction of visitors to track, `0`–`1`. Defaults to tracking everyone. */
37
+ /** Fraction of visitors to track, `0` to `1`. Defaults to tracking everyone. */
37
38
  sampleRate?: number;
38
39
  /** Send the full query string with pageviews instead of stripping it. */
39
40
  trackQuery?: boolean;
@@ -42,6 +43,7 @@ interface TaktOptions {
42
43
  /** Path prefixes never tracked, e.g. `['/app','/account']`. Segment-bounded: `'/app'` matches `'/app'` and `'/app/…'` but not `'/application'`. */
43
44
  exclude?: string[];
44
45
  redactRoutes?: string[];
46
+ redactUndecodablePaths?: boolean;
45
47
  routeTemplates?: boolean;
46
48
  /**
47
49
  * Rewrite each URL before it is sent (e.g. strip a fragment or PII).
@@ -51,7 +53,7 @@ interface TaktOptions {
51
53
  *
52
54
  * Integration-only: a function cannot survive the `<Takt />` component's
53
55
  * JSON data island, so it is supported solely via the `takt()` integration in
54
- * `astro.config`. Passing it to `<Takt />` throws — see {@link assertNoScrubUrl}.
56
+ * `astro.config`. Passing it to `<Takt />` throws: see {@link assertNoScrubUrl}.
55
57
  */
56
58
  scrubUrl?: (url: string) => string;
57
59
  /** Auto-track elements marked with `data-takt-event`. */
@@ -61,19 +63,19 @@ interface TaktOptions {
61
63
  /**
62
64
  * Guard the `<Takt />` component path against `scrubUrl`. The component
63
65
  * serializes its config as a JSON data island (`JSON.stringify` → `JSON.parse`),
64
- * which silently drops functions — so accepting `scrubUrl` there would be a
66
+ * which silently drops functions, so accepting `scrubUrl` there would be a
65
67
  * silent no-op. Fail fast at build time and point to the integration, which
66
68
  * embeds `scrubUrl` as build-time JS instead.
67
69
  */
68
70
  declare function assertNoScrubUrl(options?: TaktOptions): void;
69
71
  /**
70
72
  * Map user options to core's {@link InitOptions} for JSON serialization.
71
- * `scrubUrl` is intentionally absent here — it is a function and cannot survive
73
+ * `scrubUrl` is intentionally absent here. It is a function and cannot survive
72
74
  * `JSON.stringify`, so it is threaded separately to {@link buildRuntime}.
73
75
  */
74
76
  declare function resolveOptions(options?: TaktOptions): InitOptions;
75
77
 
76
- /** Pick ONE install path — this integration OR the `<Takt />` component — not both. */
78
+ /** Pick ONE install path: this integration OR the `<Takt />` component, not both. */
77
79
  declare function takt(options?: TaktOptions): AstroIntegration;
78
80
 
79
81
  /**
package/dist/index.js CHANGED
@@ -13,6 +13,7 @@ function resolveOptions(options = {}) {
13
13
  scriptOrigin: options.scriptOrigin,
14
14
  outbound: options.outbound ?? false,
15
15
  files: options.files ?? false,
16
+ fileExtensions: options.fileExtensions,
16
17
  notFound: options.track404 ?? false,
17
18
  respectDnt: options.respectDnt ?? true,
18
19
  excludeLocalhost: options.excludeLocalhost ?? true,
@@ -23,6 +24,7 @@ function resolveOptions(options = {}) {
23
24
  queryParams: options.queryParams,
24
25
  exclude: options.exclude,
25
26
  redactRoutes: options.redactRoutes,
27
+ redactUndecodablePaths: options.redactUndecodablePaths,
26
28
  routeTemplates: options.routeTemplates,
27
29
  tagged: options.tagged,
28
30
  debug: options.debug
@@ -74,7 +76,7 @@ function takt(options = {}) {
74
76
 
75
77
  // src/index.ts
76
78
  import { track, pageview, optOut, optIn, isOptedOut } from "@vskstudio/takt-core";
77
- import { createStats, PublicApiError, badgeUrl, embedUrl } from "@vskstudio/takt-core";
79
+ import { createStats, PublicApiError, badgeUrl, embedUrl, normalizeHost } from "@vskstudio/takt-core";
78
80
  export {
79
81
  PublicApiError,
80
82
  assertNoScrubUrl,
@@ -84,6 +86,7 @@ export {
84
86
  takt as default,
85
87
  embedUrl,
86
88
  isOptedOut,
89
+ normalizeHost,
87
90
  optIn,
88
91
  optOut,
89
92
  pageview,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vskstudio/takt-astro",
3
- "version": "0.9.1",
3
+ "version": "0.10.0",
4
4
  "description": "Astro integration for Takt privacy-friendly analytics",
5
5
  "license": "MIT",
6
6
  "author": "VSK Studio",
@@ -58,14 +58,14 @@
58
58
  "release": "pnpm build && changeset publish"
59
59
  },
60
60
  "peerDependencies": {
61
- "@vskstudio/takt-core": ">=0.11.0",
61
+ "@vskstudio/takt-core": ">=0.12.1",
62
62
  "astro": ">=4"
63
63
  },
64
64
  "devDependencies": {
65
65
  "@changesets/cli": "^2.31.0",
66
66
  "@playwright/test": "^1.50.0",
67
67
  "@size-limit/preset-small-lib": "^11.1.6",
68
- "@vskstudio/takt-core": "^0.11.0",
68
+ "@vskstudio/takt-core": "^0.12.1",
69
69
  "astro": "^5.0.0",
70
70
  "eslint": "^9.0.0",
71
71
  "size-limit": "^11.1.6",