@devslab/site-kit 0.14.1 → 0.16.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.ko.md +266 -3
- package/README.md +266 -3
- package/dist/chrome.d.ts +10 -0
- package/dist/chrome.d.ts.map +1 -1
- package/dist/consent.d.ts +36 -0
- package/dist/consent.d.ts.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/solid.js +336 -135
- package/dist/solid.js.map +1 -1
- package/dist/solid.server.js +282 -25
- package/dist/solid.server.js.map +1 -1
- package/fonts/geist/LICENSE.txt +93 -0
- package/fonts/geist/geist-cyrillic-ext-wght-normal.woff2 +0 -0
- package/fonts/geist/geist-cyrillic-wght-normal.woff2 +0 -0
- package/fonts/geist/geist-latin-ext-wght-normal.woff2 +0 -0
- package/fonts/geist/geist-latin-wght-normal.woff2 +0 -0
- package/fonts/geist/geist-vietnamese-wght-normal.woff2 +0 -0
- package/fonts/geist-mono/LICENSE.txt +93 -0
- package/fonts/geist-mono/geist-mono-cyrillic-ext-wght-normal.woff2 +0 -0
- package/fonts/geist-mono/geist-mono-cyrillic-wght-normal.woff2 +0 -0
- package/fonts/geist-mono/geist-mono-latin-ext-wght-normal.woff2 +0 -0
- package/fonts/geist-mono/geist-mono-latin-wght-normal.woff2 +0 -0
- package/fonts/geist-mono/geist-mono-symbols2-wght-normal.woff2 +0 -0
- package/fonts/geist-mono/geist-mono-vietnamese-wght-normal.woff2 +0 -0
- package/fonts/manifest.json +674 -0
- package/fonts/pretendard/LICENSE.txt +94 -0
- package/fonts/pretendard/PretendardVariable.subset.0.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.1.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.10.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.11.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.12.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.13.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.14.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.15.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.16.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.17.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.18.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.19.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.2.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.20.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.21.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.22.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.23.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.24.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.25.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.26.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.27.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.28.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.29.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.3.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.30.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.31.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.32.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.33.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.34.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.35.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.36.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.37.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.38.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.39.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.4.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.40.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.41.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.42.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.43.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.44.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.45.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.46.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.47.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.48.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.49.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.5.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.50.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.51.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.52.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.53.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.54.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.55.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.56.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.57.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.58.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.59.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.6.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.60.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.61.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.62.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.63.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.64.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.65.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.66.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.67.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.68.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.69.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.7.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.70.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.71.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.72.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.73.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.74.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.75.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.76.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.77.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.78.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.79.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.8.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.80.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.81.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.82.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.83.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.84.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.85.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.86.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.87.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.88.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.89.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.9.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.90.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.91.woff2 +0 -0
- package/fonts.css +937 -0
- package/package.json +10 -5
- package/src/core/consent.d.mts +160 -0
- package/src/core/consent.mjs +567 -0
- package/src/core/fonts.d.mts +5 -0
- package/src/core/fonts.mjs +39 -0
- package/src/core/index.d.mts +2 -0
- package/src/core/index.mjs +5 -0
- package/src/tanstack-start.d.mts +14 -2
- package/src/tanstack-start.mjs +39 -1
- package/styles.css +45 -2
package/src/tanstack-start.mjs
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import { brandIconLinks } from "./core/seo.mjs";
|
|
2
2
|
import { gtmHeadScript } from "./core/gtm.mjs";
|
|
3
|
+
import { fontPreloadLinks } from "./core/fonts.mjs";
|
|
4
|
+
import { consentCookieGrantsAnalytics, consentHeadScript } from "./core/consent.mjs";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Send these on every route that uses `consent` (TanStack Start: the route's
|
|
8
|
+
* `headers` option). The head differs per visitor's cookie, so the page must
|
|
9
|
+
* never sit in a shared cache.
|
|
10
|
+
*/
|
|
11
|
+
export { CONSENT_RESPONSE_HEADERS } from "./core/consent.mjs";
|
|
3
12
|
|
|
4
13
|
/**
|
|
5
14
|
* A route `head().scripts` entry that loads Google Tag Manager (D-031).
|
|
@@ -16,11 +25,35 @@ export function gtmHeadEntry(containerId) {
|
|
|
16
25
|
return { children: gtmHeadScript(containerId) };
|
|
17
26
|
}
|
|
18
27
|
|
|
28
|
+
/**
|
|
29
|
+
* The consent-gated head entry (D-034): one inline script. Without a current
|
|
30
|
+
* analytics grant in `cookie` it only pushes Consent Mode defaults (all
|
|
31
|
+
* denied) into the page's dataLayer — nothing contacts Google. With one, it
|
|
32
|
+
* also grants `analytics_storage` and runs Google's Tag Manager loader.
|
|
33
|
+
*
|
|
34
|
+
* `cookie` is the Cookie header on the server and `document.cookie` in the
|
|
35
|
+
* browser (TanStack Start: createIsomorphicFn), so both sides of hydration
|
|
36
|
+
* render the same script. Only the consent cookie is read from it; nothing
|
|
37
|
+
* from it is written into the page. Like gtmHeadEntry, no nonce: the router
|
|
38
|
+
* stamps `ssr.nonce`.
|
|
39
|
+
*/
|
|
40
|
+
export function consentHeadEntry(options) {
|
|
41
|
+
const granted = consentCookieGrantsAnalytics(options?.cookie, {
|
|
42
|
+
policyVersion: options?.policyVersion,
|
|
43
|
+
...(options.cookieName === undefined ? {} : { cookieName: options.cookieName }),
|
|
44
|
+
});
|
|
45
|
+
return { children: consentHeadScript({ granted, gtm: options.gtm }) };
|
|
46
|
+
}
|
|
47
|
+
|
|
19
48
|
// `icons` is opt-in: the adapter cannot know where (or whether) a product
|
|
20
49
|
// serves the linq-brand files, and a head that links icons the server 404s
|
|
21
50
|
// is worse than one that links none. `true` takes the /brand default.
|
|
22
51
|
// `gtm` is opt-in the same way, and per route: the product decides which
|
|
23
52
|
// pages carry Tag Manager (public marketing and legal pages, not consoles).
|
|
53
|
+
// It loads Tag Manager unconditionally and stays for compatibility; products
|
|
54
|
+
// switch to `consent` (D-034), which loads it only after an opt-in.
|
|
55
|
+
// `fontPreload` is opt-in too: only the product knows the hashed URL its
|
|
56
|
+
// bundler gave the face (D-033). Appended after the icons.
|
|
24
57
|
export function toTanStackHead(metadata, options = {}) {
|
|
25
58
|
const icons = options.icons === true ? brandIconLinks() : options.icons ? brandIconLinks(options.icons) : [];
|
|
26
59
|
const head = {
|
|
@@ -43,9 +76,14 @@ export function toTanStackHead(metadata, options = {}) {
|
|
|
43
76
|
{ rel: "canonical", href: metadata.canonical },
|
|
44
77
|
...metadata.alternates.map(({ hreflang, href }) => ({ rel: "alternate", hreflang, href })),
|
|
45
78
|
...icons,
|
|
79
|
+
...(options.fontPreload === undefined ? [] : fontPreloadLinks(options.fontPreload)),
|
|
46
80
|
],
|
|
47
81
|
};
|
|
48
|
-
if (options.gtm !== undefined
|
|
82
|
+
if (options.gtm !== undefined && options.consent !== undefined) {
|
|
83
|
+
throw new TypeError("toTanStackHead: pass the container id as consent.gtm, not both gtm and consent — gtm alone loads Tag Manager without consent");
|
|
84
|
+
}
|
|
85
|
+
if (options.consent !== undefined) head.scripts = [consentHeadEntry(options.consent)];
|
|
86
|
+
else if (options.gtm !== undefined) head.scripts = [gtmHeadEntry(options.gtm)];
|
|
49
87
|
return head;
|
|
50
88
|
}
|
|
51
89
|
|
package/styles.css
CHANGED
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
/* Touch: every link in the chrome is a 44px target (spec §6), as every button already is
|
|
74
74
|
(dds-css button.css). Placed before the narrow block so its menu rows can override the display. */
|
|
75
75
|
@media (pointer: coarse) {
|
|
76
|
-
.site-brand, .site-nav__list a, .site-footer__links a, .site-footer__brand a, .site-footer__langs-trigger { display: inline-flex; align-items: center; min-block-size: 44px; }
|
|
76
|
+
.site-brand, .site-nav__list a, .site-footer__links a, .site-footer__links .site-consent-trigger, .site-footer__brand a, .site-footer__langs-trigger { display: inline-flex; align-items: center; min-block-size: 44px; }
|
|
77
77
|
.site-footer__langs-list a { display: flex; align-items: center; min-block-size: 44px; }
|
|
78
78
|
}
|
|
79
79
|
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
@media (prefers-reduced-motion: reduce) { .site-header { scroll-behavior: auto; } }
|
|
95
|
-
@media (forced-colors: active) { .site-header, .site-footer, .site-status { forced-color-adjust: auto; } }
|
|
95
|
+
@media (forced-colors: active) { .site-header, .site-footer, .site-status, .site-consent { forced-color-adjust: auto; } }
|
|
96
96
|
|
|
97
97
|
.site-locale-flag { position: relative; }
|
|
98
98
|
.site-locale-flag__trigger { list-style: none; display: inline-grid; place-items: center; min-inline-size: 44px; min-block-size: 44px; border-radius: var(--dds-radius-sm); cursor: pointer; }
|
|
@@ -109,3 +109,46 @@
|
|
|
109
109
|
.site-locale-flag__option:focus-visible { outline: 2px solid var(--dds-color-border-focus); outline-offset: -2px; }
|
|
110
110
|
.site-locale-flag__option[aria-current="true"] { font-weight: 700; }
|
|
111
111
|
@media (max-width: 720px) { .site-locale-flag__list { position: static; inline-size: 100%; max-block-size: none; box-shadow: none; } }
|
|
112
|
+
|
|
113
|
+
/* Consent (D-034): a bottom bar with three equal choices, and a settings dialog.
|
|
114
|
+
The three buttons share one tone and one grid track width, so no choice is
|
|
115
|
+
drawn heavier than another. */
|
|
116
|
+
/* Room under the page while the bar is up (ConsentBanner sets the height); zero specificity, so a product body rule wins. */
|
|
117
|
+
:where(body) { padding-block-end: var(--site-consent-block-size, 0px); }
|
|
118
|
+
.site-consent { position: fixed; inset-inline: 0; inset-block-end: 0; z-index: 900; max-block-size: 100dvh; overflow-y: auto; border-block-start: 1px solid var(--dds-color-border-default); background: var(--dds-color-bg-elevated); color: var(--dds-color-text-primary); box-shadow: var(--dds-elevation-3); }
|
|
119
|
+
.site-consent__inner { inline-size: min(100% - var(--dds-space-32), 1120px); margin-inline: auto; padding-block: var(--dds-space-16); display: grid; grid-template-columns: minmax(0, 1fr) auto auto; grid-template-areas: "copy actions close"; align-items: center; gap: var(--dds-space-12) var(--dds-space-24); }
|
|
120
|
+
.site-consent__copy { grid-area: copy; display: grid; gap: var(--dds-space-4); min-inline-size: 0; }
|
|
121
|
+
.site-consent__title { margin: 0; font-size: var(--dds-typo-body-1-font-size); line-height: var(--dds-typo-body-1-line-height); font-weight: 700; }
|
|
122
|
+
.site-consent__body { margin: 0; max-inline-size: 72ch; font-size: var(--dds-typo-body-2-font-size); line-height: var(--dds-typo-body-2-line-height); color: var(--dds-color-text-secondary); }
|
|
123
|
+
.site-consent__link { color: var(--dds-color-text-brand); text-decoration: underline; text-underline-offset: 2px; }
|
|
124
|
+
.site-consent__link:focus-visible, .site-consent-trigger:focus-visible { outline: 2px solid var(--dds-color-border-focus); outline-offset: 2px; border-radius: var(--dds-radius-sm); }
|
|
125
|
+
.site-consent__actions { grid-area: actions; display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: var(--dds-space-8); }
|
|
126
|
+
.site-consent__action { inline-size: 100%; min-inline-size: 7rem; }
|
|
127
|
+
.site-consent__dismiss { grid-area: close; align-self: start; }
|
|
128
|
+
.dds-dialog.site-consent-dialog { position: relative; max-inline-size: 36rem; max-block-size: calc(100dvh - 2 * var(--dds-space-16)); overflow-y: auto; }
|
|
129
|
+
.site-consent-dialog .dds-dialog__title { padding-inline-end: var(--dds-space-40); }
|
|
130
|
+
.site-consent-dialog__close { position: absolute; inset-block-start: var(--dds-space-12); inset-inline-end: var(--dds-space-12); }
|
|
131
|
+
.site-consent-categories { display: grid; margin: 0 0 var(--dds-space-12); padding: 0; list-style: none; }
|
|
132
|
+
.site-consent-category { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: start; gap: var(--dds-space-16); padding-block: var(--dds-space-12); border-block-start: 1px solid var(--dds-color-border-default); }
|
|
133
|
+
.site-consent-category:last-child { border-block-end: 1px solid var(--dds-color-border-default); }
|
|
134
|
+
.site-consent-category__copy { display: grid; gap: var(--dds-space-4); min-inline-size: 0; }
|
|
135
|
+
.site-consent-category__title { margin: 0; font-size: var(--dds-typo-label-font-size); line-height: var(--dds-typo-label-line-height); font-weight: 600; }
|
|
136
|
+
.site-consent-category__body { margin: 0; font-size: var(--dds-typo-body-2-font-size); line-height: var(--dds-typo-body-2-line-height); color: var(--dds-color-text-secondary); }
|
|
137
|
+
.site-consent-category__status, .site-consent-category__switch { justify-self: end; }
|
|
138
|
+
.site-consent-category__status { background: var(--dds-color-bg-subtle); color: var(--dds-color-text-secondary); }
|
|
139
|
+
.site-consent-dialog__policy { margin: 0 0 var(--dds-space-16); font-size: var(--dds-typo-body-2-font-size); }
|
|
140
|
+
.site-consent-dialog .dds-dialog__actions { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
|
141
|
+
/* The footer's "쿠키 설정" reads as one of its links. */
|
|
142
|
+
.site-consent-trigger { appearance: none; margin: 0; padding: 0; border: 0; background: none; font: inherit; color: var(--dds-color-text-secondary); cursor: pointer; }
|
|
143
|
+
.site-consent-trigger:hover { color: var(--dds-color-text-primary); text-decoration: underline; }
|
|
144
|
+
@media (max-width: 720px) {
|
|
145
|
+
.site-consent__inner { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "copy close" "actions actions"; align-items: start; }
|
|
146
|
+
.site-consent__actions { grid-auto-flow: row; grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
|
147
|
+
.site-consent__action { min-inline-size: 0; }
|
|
148
|
+
}
|
|
149
|
+
@media (max-width: 480px) {
|
|
150
|
+
.site-consent-dialog .dds-dialog__actions { grid-template-columns: minmax(0, 1fr); }
|
|
151
|
+
}
|
|
152
|
+
@media (max-width: 340px) {
|
|
153
|
+
.site-consent__actions { grid-template-columns: minmax(0, 1fr); }
|
|
154
|
+
}
|