@kywi-software/js 0.6.2 → 0.6.3
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/dist/audience/dom-patcher.d.ts.map +1 -1
- package/dist/audience/selfid-widget.d.ts +13 -2
- package/dist/audience/selfid-widget.d.ts.map +1 -1
- package/dist/kywi.esm.js +24 -4
- package/dist/kywi.esm.js.map +3 -3
- package/dist/kywi.js +24 -4
- package/dist/kywi.js.map +3 -3
- package/package.json +2 -2
package/dist/kywi.esm.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/context.ts", "../src/entity.ts", "../src/feed.ts", "../src/render-feed.ts", "../src/module-system.ts", "../src/form-hooks.ts", "../src/experiments/index.ts", "../../core/src/audiences/types.ts", "../../core/src/audiences/evaluator/glob.ts", "../../core/src/audiences/evaluator/instant-match.ts", "../../core/src/audiences/evaluator/score.ts", "../../core/src/audiences/evaluator/condition-registry.ts", "../../core/src/audiences/evaluator/resolver.ts", "../src/audience/behavioral-collector.ts", "../src/audience/selfid-collector.ts", "../src/audience/evaluate.ts", "../src/audience/dom-patcher.ts", "../src/cookies.ts", "../src/audience/transparency-styles.ts", "../src/audience/transparency.ts", "../src/audience/preview.ts", "../src/audience/data-layer.ts", "../src/audience/adapter-runner.ts", "../src/audience/selfid-submit.ts", "../src/audience/selfid-widget.ts", "../src/personalization/badge.ts", "../src/audience/index.ts", "../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["// packages/kywi-js/src/context.ts\nimport type { KywiContext } from './types.js'\n\nexport function readContext(): KywiContext {\n const meta = (name: string): string => {\n if (typeof document === 'undefined') return ''\n const el = document.querySelector(`meta[name=\"kywi:${name}\"]`)\n return el?.getAttribute('content') ?? ''\n }\n return {\n siteId: meta('site-id') || document?.documentElement?.getAttribute('data-kywi-site') || '',\n locale: document?.documentElement?.lang || 'en',\n themePath: meta('theme-path') || '',\n basePath: meta('base-path') || '/',\n csrfToken: meta('csrf-token') || '',\n isEditMode: document?.body?.classList?.contains('kywi-edit-mode') ?? false,\n }\n}\n", "// packages/kywi-js/src/entity.ts\nimport type { KywiEntityObject } from './types.js'\n\nfunction createEntity(type: string, basePath: string, csrfToken: string, data: Record<string, unknown>): KywiEntityObject {\n const fields = { ...data }\n const dirty = new Map<string, unknown>()\n const errors: string[] = []\n const headers: Record<string, string> = { 'Content-Type': 'application/json' }\n if (csrfToken) headers['X-CSRF-Token'] = csrfToken\n\n const entity: KywiEntityObject = {\n get(field: string) { return fields[field] },\n set(field: string, value: unknown) { fields[field] = value; dirty.set(field, value); return entity },\n async save() {\n const id = fields['id'] as string | undefined\n const url = id ? `${basePath}/content/${type}/${id}` : `${basePath}/content/${type}`\n const res = await fetch(url, { method: id ? 'PUT' : 'POST', headers, body: JSON.stringify(Object.fromEntries(dirty)) })\n const json = await res.json() as { data?: Record<string, unknown>; error?: { message: string } }\n if (!res.ok || json.error) { errors.push(json.error?.message ?? 'Save failed'); throw entity }\n if (json.data) Object.assign(fields, json.data)\n dirty.clear()\n return entity\n },\n async delete() {\n const id = fields['id'] as string\n await fetch(`${basePath}/content/${type}/${id}`, { method: 'DELETE', headers })\n },\n getErrors() { return [...errors] },\n async loadBy(field: string, value: string) {\n const url = field === 'id' ? `${basePath}/content/${type}/${value}` : `${basePath}/content/${type}?${field}=${encodeURIComponent(value)}`\n const res = await fetch(url, { headers })\n const json = await res.json() as { data?: Record<string, unknown>; error?: { message: string } }\n if (!res.ok || json.error) { errors.push(json.error?.message ?? 'Load failed'); throw entity }\n if (json.data) Object.assign(fields, json.data)\n return entity\n },\n }\n return entity\n}\n\nexport function createEntityFactory(basePath: string, csrfToken: string) {\n return (type: string): KywiEntityObject => createEntity(type, basePath, csrfToken, {})\n}\n", "// packages/kywi-js/src/feed.ts\nimport type { KywiEntityObject, KywiFeedResult } from './types.js'\n\ninterface Filter { field: string; operator: string; value?: unknown; conjunction: 'and' | 'or' }\n\nexport type AggregateFunction = 'count' | 'sum' | 'min' | 'max' | 'avg'\nexport type AggregateResult = Record<string, unknown>\n\nclass PropBuilder {\n constructor(private builder: FeedBuilder, private field: string, private conj: 'and' | 'or') {}\n private add(op: string, value?: unknown) { this.builder._filters.push({ field: this.field, operator: op, value, conjunction: this.conj }); return this.builder }\n isEQ(v: unknown) { return this.add('eq', v) }\n isNEQ(v: unknown) { return this.add('neq', v) }\n isLT(v: unknown) { return this.add('lt', v) }\n isLTE(v: unknown) { return this.add('lte', v) }\n isGT(v: unknown) { return this.add('gt', v) }\n isGTE(v: unknown) { return this.add('gte', v) }\n beginsWith(v: unknown) { return this.add('beginsWith', v) }\n endsWith(v: unknown) { return this.add('endsWith', v) }\n contains(v: unknown) { return this.add('contains', v) }\n isNull() { return this.add('isNull') }\n isNotNull() { return this.add('isNotNull') }\n}\n\nclass FeedBuilder {\n _filters: Filter[] = []\n private _sort: { field: string; direction: 'asc' | 'desc' } | null = null\n private _limit: number | null = null\n private _page: number | null = null\n constructor(private contentType: string, private basePath: string, private csrfToken: string) {}\n\n where(): this { return this }\n prop(field: string) { return new PropBuilder(this, field, 'and') }\n andProp(field: string) { return new PropBuilder(this, field, 'and') }\n orProp(field: string) { return new PropBuilder(this, field, 'or') }\n sort(field: string, direction: 'asc' | 'desc' = 'asc'): this { this._sort = { field, direction }; return this }\n maxItems(n: number): this { this._limit = n; return this }\n page(n: number): this { this._page = n; return this }\n\n private buildBody(): Record<string, unknown> {\n const filterArray = this._filters.map(f => ({\n field: f.field,\n operator: f.operator,\n value: f.value,\n conjunction: f.conjunction,\n }))\n const body: Record<string, unknown> = { contentType: this.contentType }\n if (filterArray.length > 0) body['filters'] = filterArray\n if (this._sort) body['sort'] = this._sort\n if (this._limit !== null) body['limit'] = this._limit\n if (this._page !== null) body['page'] = this._page\n return body\n }\n\n private buildHeaders(): Record<string, string> {\n const headers: Record<string, string> = { 'Content-Type': 'application/json' }\n if (this.csrfToken) headers['X-CSRF-Token'] = this.csrfToken\n return headers\n }\n\n async aggregate(fn: AggregateFunction, field?: string): Promise<AggregateResult> {\n const body = this.buildBody()\n const agg: Record<string, string> = { function: fn }\n if (field) agg['field'] = field\n body['aggregate'] = agg\n\n const res = await fetch(`${this.basePath}/feeds/aggregate`, {\n method: 'POST',\n headers: this.buildHeaders(),\n body: JSON.stringify(body),\n })\n const json = await res.json() as { data?: AggregateResult }\n return json.data ?? {}\n }\n\n async getQuery(): Promise<KywiFeedResult> {\n const body = this.buildBody()\n const res = await fetch(`${this.basePath}/feeds/query`, {\n method: 'POST',\n headers: this.buildHeaders(),\n body: JSON.stringify(body),\n })\n // Two response envelopes are supported:\n // 1. The live @kywi-software/core server (POST /feeds/query -> jsonOk(executeFeedQuery))\n // returns { data: { items, total, page, pageSize, totalPages } }.\n // 2. A flatter { data: [ ...items ], meta: { total, page, totalPages } } shape.\n // Normalise both so the decoupled client works against the real API.\n const json = await res.json() as {\n data?: Array<Record<string, unknown>> | { items?: Array<Record<string, unknown>>; total?: number; page?: number; pageSize?: number; totalPages?: number }\n meta?: { total?: number; page?: number; totalPages?: number }\n }\n\n const payload = json.data\n const rawItems: Array<Record<string, unknown>> = Array.isArray(payload)\n ? payload\n : (payload?.items ?? [])\n const total = Array.isArray(payload) ? (json.meta?.total ?? rawItems.length) : (payload?.total ?? rawItems.length)\n const page = Array.isArray(payload) ? (json.meta?.page ?? 1) : (payload?.page ?? 1)\n const pages = Array.isArray(payload) ? (json.meta?.totalPages ?? 0) : (payload?.totalPages ?? 0)\n\n const items: KywiEntityObject[] = rawItems.map(d => ({\n get(field: string) { return d[field] },\n set() { throw new Error('Feed results are read-only') },\n save() { return Promise.reject(new Error('Feed results are read-only')) },\n delete() { return Promise.reject(new Error('Feed results are read-only')) },\n getErrors() { return [] },\n loadBy() { return Promise.reject(new Error('Use Kywi.getEntity() to load by field')) },\n }))\n\n return { items, total, page, pages }\n }\n}\n\nexport function createFeedFactory(basePath: string, csrfToken: string) {\n return (type: string) => new FeedBuilder(type, basePath, csrfToken)\n}\n", "// packages/kywi-js/src/render-feed.ts\nimport type { KywiEntityObject, KywiFeedResult } from './types.js'\n\ninterface RenderFeedOptions {\n feed: { getQuery(): Promise<KywiFeedResult> }\n container: HTMLElement\n template: (item: KywiEntityObject) => string | Node\n loadingText?: string; emptyText?: string\n wrapperTag?: string; wrapperClass?: string\n unsafeHtml?: boolean\n onRender?: (container: HTMLElement) => void\n}\n\nexport async function renderFeed(options: RenderFeedOptions): Promise<void> {\n const { feed, container, template, loadingText = '', emptyText = '', wrapperTag = 'div', wrapperClass, unsafeHtml = false, onRender } = options\n if (loadingText) container.textContent = loadingText\n const result = await feed.getQuery()\n container.textContent = ''\n if (result.items.length === 0) { if (emptyText) container.textContent = emptyText; return }\n const wrapper = document.createElement(wrapperTag)\n if (wrapperClass) wrapper.className = wrapperClass\n for (const item of result.items) {\n const rendered = template(item)\n if (rendered instanceof Node) {\n wrapper.appendChild(rendered)\n } else if (unsafeHtml) {\n const span = document.createElement('span')\n // intentional: caller explicitly opts in via unsafeHtml\n span['innerHTML'] = rendered\n wrapper.appendChild(span)\n } else {\n const span = document.createElement('span')\n span.textContent = rendered // SAFE: always textContent for string templates\n wrapper.appendChild(span)\n }\n }\n container.appendChild(wrapper)\n if (onRender) onRender(container)\n}\n", "// packages/kywi-js/src/module-system.ts\nimport { Kywi } from './index.js'\nimport type { KywiModuleContext } from './types.js'\n\nfunction readParams(el: HTMLElement): Record<string, string> {\n const params: Record<string, string> = {}\n for (const attr of Array.from(el.attributes)) {\n if (attr.name.startsWith('data-kywi-param-')) {\n params[attr.name.slice(16)] = attr.value\n }\n }\n return params\n}\n\nexport function initModules(): void {\n const elements = document.querySelectorAll('[data-kywi-module]')\n for (const el of Array.from(elements)) {\n const htmlEl = el as HTMLElement\n const moduleName = htmlEl.getAttribute('data-kywi-module')\n if (!moduleName) continue\n const def = Kywi.Module[moduleName]\n if (!def || !def.renderClient) continue\n const context: KywiModuleContext = { targetEl: htmlEl, ...readParams(htmlEl) }\n def.renderClient.call({ context, ...def })\n }\n}\n", "// packages/kywi-js/src/form-hooks.ts\nimport { Kywi } from './index.js'\n\nexport function initFormHooks(): void {\n const forms = document.querySelectorAll('[data-kywi-form]')\n for (const formEl of Array.from(forms)) {\n const htmlForm = formEl as HTMLFormElement\n const hooks = Kywi.DisplayObject.Form._hooks\n if (hooks['onAfterRender']) hooks['onAfterRender'].call({ context: { targetEl: htmlForm } })\n htmlForm.addEventListener('submit', (e) => {\n if (hooks['onSubmit']) {\n const result = hooks['onSubmit'].call({ context: { targetEl: htmlForm } })\n if (result === false) e.preventDefault()\n }\n })\n }\n}\n\nexport async function submitKywiForm(form: HTMLFormElement, endpoint: string): Promise<void> {\n const formData = new FormData(form)\n const data: Record<string, string> = {}\n formData.forEach((value, key) => { data[key] = value as string })\n\n const res = await fetch(endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(data),\n })\n const json = await res.json() as { success: boolean; errors?: Record<string, string>; data?: Record<string, unknown> }\n const hooks = Kywi.DisplayObject.Form._hooks\n\n if (!json.success && json.errors) {\n if (typeof hooks['onAfterErrorRender'] === 'function') {\n hooks['onAfterErrorRender']({ errors: json.errors, targetEl: form })\n }\n } else if (json.success && json.data) {\n if (typeof hooks['onAfterResponseRender'] === 'function') {\n hooks['onAfterResponseRender']({ response: json.data, targetEl: form })\n }\n }\n}\n", "// packages/kywi-js/src/experiments/index.ts\n//\n// Client-side A/B experiment beacons. Reads the server-rendered kywi:* meta\n// tags, confirms the exposure, and reports conversion signals (pageview,\n// form-submit, custom) back to the runtime endpoints. Fire-and-forget: every\n// call is best-effort and never throws into the host page.\n\nimport { readContext } from '../context.js'\nimport type { KywiContext } from '../types.js'\n\nexport interface ConversionSignal {\n type: 'pageview' | 'form_submit' | 'custom'\n url?: string\n formId?: string\n eventName?: string\n}\n\nexport interface ExperimentBootConfig {\n context?: KywiContext\n apiBase?: string\n visitorId?: string\n currentPath?: string\n /** Auto-emit a pageview conversion signal on boot (default true). */\n autoPageview?: boolean\n}\n\nexport interface ExperimentRuntime {\n /** Emit a custom conversion event, e.g. kywi.track('signup'). */\n track(eventName: string): void\n /** Emit a raw conversion signal. */\n trackConversion(signal: ConversionSignal): void\n}\n\nfunction apiBaseFrom(ctx: KywiContext): string {\n return ctx.basePath && ctx.basePath !== '/' ? `${ctx.basePath}/api/v1` : '/api/v1'\n}\n\nfunction metaContent(name: string): string | null {\n if (typeof document === 'undefined') return null\n return document.querySelector(`meta[name=\"kywi:${name}\"]`)?.getAttribute('content') ?? null\n}\n\n// A single document-level submit listener is installed once and routes to the\n// most recent boot's handler \u2014 booting twice must not double-count conversions.\nlet submitListenerInstalled = false\nlet currentFormConversion: ((formId: string) => void) | null = null\n\nfunction installFormListener(): void {\n if (submitListenerInstalled || typeof document === 'undefined') return\n submitListenerInstalled = true\n document.addEventListener(\n 'submit',\n (e) => {\n const form = e.target as HTMLElement | null\n if (!form || form.tagName !== 'FORM') return\n const formId = form.getAttribute('data-kywi-form-id') ?? form.getAttribute('id')\n if (formId && currentFormConversion) currentFormConversion(formId)\n },\n true,\n )\n}\n\nfunction beacon(url: string, body: unknown, csrfToken?: string): void {\n try {\n void fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...(csrfToken ? { 'X-CSRF-Token': csrfToken } : {}) },\n body: JSON.stringify(body),\n keepalive: true,\n }).catch(() => {})\n } catch {\n /* never throw into the host page */\n }\n}\n\n/**\n * Boot the experiment beacons. Safe to call once per page load; when no\n * experiment meta is present it only wires the conversion listeners.\n */\nexport function bootExperiments(config: ExperimentBootConfig = {}): ExperimentRuntime {\n const ctx = config.context ?? readContext()\n const apiBase = config.apiBase ?? apiBaseFrom(ctx)\n const csrf = ctx.csrfToken || undefined\n const experimentId = metaContent('experiment-id')\n const visitorId = config.visitorId ?? metaContent('visitor-id') ?? undefined\n const currentPath = config.currentPath ?? (typeof location !== 'undefined' ? location.pathname : '/')\n\n function trackConversion(signal: ConversionSignal): void {\n beacon(`${apiBase}/kywi/experiments/conversion`, { visitorId, event: signal }, csrf)\n }\n function track(eventName: string): void {\n trackConversion({ type: 'custom', eventName })\n }\n\n // 1) Exposure \u2014 confirm the server-rendered variant was seen. The variant is\n // recomputed server-side, so we only send the experiment + visitor ids.\n if (experimentId) {\n beacon(`${apiBase}/kywi/experiments/exposure`, { experimentId, visitorId }, csrf)\n }\n\n // 2) Pageview conversion signal \u2014 lets pageview-goal experiments convert when\n // an enrolled visitor lands on the goal path.\n if (config.autoPageview !== false) {\n trackConversion({ type: 'pageview', url: currentPath })\n }\n\n // 3) Form-submit conversion \u2014 capture submits of any tagged form. The listener\n // is installed once; this boot becomes its active handler.\n currentFormConversion = (formId: string) => trackConversion({ type: 'form_submit', formId })\n installFormListener()\n\n const runtime: ExperimentRuntime = { track, trackConversion }\n\n // Expose on the data layer so analytics / manual conversions can reach it.\n const g = ((globalThis as unknown as { kywi?: Record<string, unknown> }).kywi ?? {})\n g['track'] = track\n g['trackConversion'] = trackConversion\n ;(globalThis as unknown as { kywi?: Record<string, unknown> }).kywi = g\n\n return runtime\n}\n", "// \u2500\u2500 Visitor Signals \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface VisitorSignals {\n utm: {\n source: string | null\n medium: string | null\n campaign: string | null\n term: string | null\n content: string | null\n }\n referrer: {\n raw: string | null\n domain: string | null\n sourceType: 'organic' | 'paid' | 'social' | 'email' | 'direct' | 'other'\n }\n session: {\n pageViewCount: number\n totalPageViews: number\n sessionDuration: number\n entryPage: string\n pagesVisited: string[]\n }\n behavioral: {\n categoryScores: Record<string, number>\n totalScore: number\n }\n selfId: Record<string, string>\n identity: {\n visitorId: string\n isKnown: boolean\n maLeadId: string | null\n }\n adapters: Record<string, unknown>\n meta: {\n isOptedOut: boolean\n isPreview: boolean\n previewAudienceId: string | null\n resolvedAt: 'server' | 'client'\n }\n}\n\n// \u2500\u2500 Evaluation Result \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface VisitorContext {\n request: Request\n partialSignals?: Partial<VisitorSignals>\n}\n\nexport interface AudienceResult {\n winningAudienceId: string | null\n allMatchedIds: string[]\n signals: VisitorSignals\n isOptedOut: boolean\n}\n\n// \u2500\u2500 Audience & Rule Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport type AudienceStatus = 'active' | 'draft' | 'archived'\n\nexport interface Audience {\n id: string\n siteId: string\n name: string\n description: string | null\n priority: number\n status: AudienceStatus\n conditionGroups: ConditionGroup[]\n scoreThreshold: number | null\n createdAt: Date\n updatedAt: Date\n}\n\nexport interface ConditionGroup {\n id: string\n audienceId: string\n sortOrder: number\n conditions: Condition[]\n}\n\nexport type Condition = InstantMatchCondition | ScoreContributionCondition\n\nexport interface InstantMatchCondition {\n type: 'instant'\n id: string\n groupId: string\n signal: InstantSignalRef\n operator: InstantOperator\n value: string | string[]\n}\n\nexport type InstantSignalRef =\n | 'utm.source' | 'utm.medium' | 'utm.campaign' | 'utm.term' | 'utm.content'\n | 'referrer.domain' | 'referrer.sourceType'\n | `selfId.${string}`\n | `adapter.${string}`\n | 'identity.isKnown'\n | 'session.entryPage'\n | 'session.pagesVisited'\n\nexport type InstantOperator =\n | 'equals' | 'not_equals' | 'contains' | 'starts_with' | 'matches_glob'\n | 'is_one_of' | 'is_true' | 'is_false'\n | 'gte' | 'lte'\n\nexport interface ScoreContributionCondition {\n type: 'score'\n id: string\n groupId: string\n trigger: ScoreTrigger\n points: number\n threshold?: number\n category?: string\n pattern?: string\n /**\n * For `trigger: 'signalMatch'` \u2014 award `points` when an arbitrary instant\n * signal matches (e.g. `utm.campaign contains 'enterprise' \u2192 +30`). Reuses the\n * instant-match operator set so any signal (UTM / referrer / self-ID / adapter)\n * can contribute to a score, not just the five behavioral triggers.\n */\n signal?: InstantSignalRef\n operator?: InstantOperator\n value?: string | string[]\n}\n\nexport type ScoreTrigger =\n | 'pageViewCount'\n | 'totalPageViews'\n | 'urlMatch'\n | 'categoryViewed'\n | 'timeOnSite'\n | 'signalMatch'\n\n// \u2500\u2500 Self-ID Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface SelfIdField {\n id: string\n siteId: string\n label: string\n picklist: Array<{ value: string; label: string }>\n required: boolean\n sortOrder: number\n}\n\nexport interface SelfIdWidgetConfig {\n id: string\n siteId: string\n displayMode: 'hello_bar_top' | 'hello_bar_bottom' | 'modal' | 'inline' | 'drawer'\n trigger: SelfIdTrigger\n headline: string\n subheadline: string | null\n fieldIds: string[]\n submitLabel: string\n skipLabel: string | null\n frequency: 'once_visitor' | 'once_session' | 'always'\n}\n\nexport type SelfIdTrigger =\n | { type: 'immediate' }\n | { type: 'scroll'; depth: number }\n | { type: 'delay'; seconds: number }\n | { type: 'manual' }\n\n// \u2500\u2500 Preview Token \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface PreviewTokenPayload {\n jti: string\n audienceId: string\n expiresAt: number\n}\n\n// \u2500\u2500 Default Signals \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport function createEmptySignals(): VisitorSignals {\n return {\n utm: { source: null, medium: null, campaign: null, term: null, content: null },\n referrer: { raw: null, domain: null, sourceType: 'direct' },\n session: { pageViewCount: 0, totalPageViews: 0, sessionDuration: 0, entryPage: '/', pagesVisited: [] },\n behavioral: { categoryScores: {}, totalScore: 0 },\n selfId: {},\n identity: { visitorId: '', isKnown: false, maLeadId: null },\n adapters: {},\n meta: { isOptedOut: false, isPreview: false, previewAudienceId: null, resolvedAt: 'server' },\n }\n}\n", "export function matchGlob(pattern: string, value: string): boolean {\n const parts = pattern.split('*')\n if (parts.length === 1) return pattern === value\n let pos = 0\n const first = parts[0]!\n if (first !== '') {\n if (!value.startsWith(first)) return false\n pos = first.length\n }\n for (let i = 1; i < parts.length - 1; i++) {\n const part = parts[i]!\n if (part === '') continue\n const idx = value.indexOf(part, pos)\n if (idx < 0) return false\n pos = idx + part.length\n }\n const last = parts[parts.length - 1]!\n if (last !== '') {\n if (!value.endsWith(last)) return false\n if (value.length - last.length < pos) return false\n }\n return true\n}\n", "import type { VisitorSignals, InstantMatchCondition, InstantSignalRef } from '../types.js'\nimport { matchGlob } from './glob.js'\n\nexport function resolveSignalValue(signals: VisitorSignals, ref: InstantSignalRef): string | null {\n if (ref === 'utm.source') return signals.utm.source\n if (ref === 'utm.medium') return signals.utm.medium\n if (ref === 'utm.campaign') return signals.utm.campaign\n if (ref === 'utm.term') return signals.utm.term\n if (ref === 'utm.content') return signals.utm.content\n if (ref === 'referrer.domain') return signals.referrer.domain\n if (ref === 'referrer.sourceType') return signals.referrer.sourceType\n if (ref === 'identity.isKnown') return signals.identity.isKnown ? 'true' : 'false'\n if (ref === 'session.entryPage') return signals.session.entryPage\n if (ref === 'session.pagesVisited') return signals.session.pagesVisited.join(',')\n if (ref.startsWith('selfId.')) {\n const key = ref.slice(7)\n return signals.selfId[key] ?? null\n }\n if (ref.startsWith('adapter.')) {\n const key = ref.slice(8)\n const val = signals.adapters[key]\n return val !== undefined && val !== null ? String(val) : null\n }\n return null\n}\n\nexport function evaluateInstantCondition(condition: InstantMatchCondition, signals: VisitorSignals): boolean {\n const actual = resolveSignalValue(signals, condition.signal)\n const expected = condition.value\n switch (condition.operator) {\n case 'equals': return actual === expected\n case 'not_equals': return actual !== expected\n case 'contains': return actual !== null && typeof expected === 'string' && actual.includes(expected)\n case 'starts_with': return actual !== null && typeof expected === 'string' && actual.startsWith(expected)\n case 'matches_glob': return actual !== null && typeof expected === 'string' && matchGlob(expected, actual)\n case 'is_one_of': return actual !== null && Array.isArray(condition.value) && condition.value.includes(actual)\n case 'is_true': return actual === 'true'\n case 'is_false': return actual === 'false'\n case 'gte': return actual !== null && typeof expected === 'string' && Number(actual) >= Number(expected)\n case 'lte': return actual !== null && typeof expected === 'string' && Number(actual) <= Number(expected)\n default: return false\n }\n}\n", "import type { VisitorSignals, ScoreContributionCondition } from '../types.js'\nimport { matchGlob } from './glob.js'\nimport { evaluateInstantCondition } from './instant-match.js'\n\nfunction evaluateOneScore(cond: ScoreContributionCondition, signals: VisitorSignals): number {\n const threshold = cond.threshold ?? 0\n switch (cond.trigger) {\n case 'pageViewCount': return signals.session.pageViewCount >= threshold ? cond.points : 0\n case 'totalPageViews': return signals.session.totalPageViews >= threshold ? cond.points : 0\n case 'timeOnSite': return signals.session.sessionDuration >= threshold ? cond.points : 0\n case 'categoryViewed': {\n const cat = cond.category ?? ''\n const score = signals.behavioral.categoryScores[cat]\n return score !== undefined && score >= threshold ? cond.points : 0\n }\n case 'urlMatch': {\n const pattern = cond.pattern ?? '*'\n const matched = signals.session.pagesVisited.some(url => matchGlob(pattern, url))\n return matched ? cond.points : 0\n }\n case 'signalMatch': {\n // Award points when an arbitrary instant signal matches. Reuses the\n // instant-match evaluator so every operator/signal is supported.\n if (!cond.signal || !cond.operator) return 0\n const matched = evaluateInstantCondition(\n {\n type: 'instant',\n id: cond.id,\n groupId: cond.groupId,\n signal: cond.signal,\n operator: cond.operator,\n value: cond.value ?? '',\n },\n signals,\n )\n return matched ? cond.points : 0\n }\n default: return 0\n }\n}\n\nexport function evaluateScoreConditions(conditions: ScoreContributionCondition[], signals: VisitorSignals): number {\n let total = 0\n for (const cond of conditions) { total += evaluateOneScore(cond, signals) }\n return total\n}\n", "import type { Condition, VisitorSignals } from '../types.js'\n\n// \u2500\u2500\u2500 Custom Condition Type Registry \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// Allows third-party code (plugins, adapters, custom app code) to register\n// additional condition type evaluators without forking the core evaluator.\n//\n// Usage:\n// import { registerConditionType } from '@kywi-software/core'\n//\n// registerConditionType('my_custom_type', (condition, signals) => {\n// // Return true if the condition matches the current visitor signals\n// return signals.adapters['my_adapter'] === condition.value\n// })\n\ntype ConditionEvaluator = (condition: Condition, signals: VisitorSignals) => boolean\n\nconst registry = new Map<string, ConditionEvaluator>()\n\n/**\n * Register a custom condition type evaluator.\n *\n * @param name - The condition `type` string this evaluator handles.\n * @param evaluate - Pure function that returns `true` when the condition matches.\n *\n * Calling this with an already-registered name overwrites the previous evaluator.\n */\nexport function registerConditionType(name: string, evaluate: ConditionEvaluator): void {\n registry.set(name, evaluate)\n}\n\n/**\n * Remove a previously registered condition type evaluator.\n * No-op if the name was never registered.\n */\nexport function unregisterConditionType(name: string): void {\n registry.delete(name)\n}\n\n/**\n * Evaluate a condition using a registered custom evaluator.\n * Returns `false` if no evaluator is registered for the condition's type.\n */\nexport function evaluateCustomCondition(condition: Condition, signals: VisitorSignals): boolean {\n const evaluator = registry.get(condition.type)\n if (!evaluator) return false\n return evaluator(condition, signals)\n}\n\n/**\n * Returns true if a custom evaluator is registered for the given condition type name.\n */\nexport function hasConditionType(name: string): boolean {\n return registry.has(name)\n}\n\n/**\n * Returns the names of all registered custom condition types.\n */\nexport function listConditionTypes(): string[] {\n return [...registry.keys()]\n}\n", "import type { Audience, VisitorSignals, ConditionGroup, InstantMatchCondition, ScoreContributionCondition } from '../types.js'\nimport { evaluateInstantCondition } from './instant-match.js'\nimport { evaluateScoreConditions } from './score.js'\nimport { hasConditionType, evaluateCustomCondition } from './condition-registry.js'\n\nexport interface ConditionTrace {\n conditionId: string\n type: 'instant' | 'score'\n passed: boolean\n scoreContributed?: number\n}\n\nexport interface EvaluationTrace {\n audienceId: string\n matched: boolean\n groupTraces: Array<{ groupId: string; matched: boolean; conditionTraces: ConditionTrace[] }>\n totalScore?: number\n}\n\nexport interface ResolveResult {\n winningAudienceId: string | null\n allMatchedIds: string[]\n traces: EvaluationTrace[]\n}\n\n// Evaluate one group: AND all instant + custom conditions, accumulate score conditions\nfunction evaluateGroup(group: ConditionGroup, signals: VisitorSignals) {\n const conditionTraces: ConditionTrace[] = []\n const instants: InstantMatchCondition[] = []\n const scores: ScoreContributionCondition[] = []\n const customs: typeof group.conditions = []\n\n for (const c of group.conditions) {\n // The Condition union only models 'instant'/'score', but the registry\n // dispatches custom condition kinds by their `type` string at runtime.\n // Capture it as a string so the custom branch stays reachable.\n const conditionType: string = c.type\n if (c.type === 'instant') instants.push(c)\n else if (c.type === 'score') scores.push(c)\n else if (hasConditionType(conditionType)) customs.push(c)\n // Unknown types with no registered evaluator are silently skipped\n }\n\n let allInstantsPassed = true\n\n for (const ic of instants) {\n const passed = evaluateInstantCondition(ic, signals)\n conditionTraces.push({ conditionId: ic.id, type: 'instant', passed })\n if (!passed) allInstantsPassed = false\n }\n\n // Custom conditions are ANDed with instant conditions\n for (const cc of customs) {\n const passed = evaluateCustomCondition(cc, signals)\n conditionTraces.push({ conditionId: cc.id, type: cc.type as 'instant', passed })\n if (!passed) allInstantsPassed = false\n }\n\n const totalScore = evaluateScoreConditions(scores, signals)\n for (const sc of scores) {\n const contributed = evaluateScoreConditions([sc], signals)\n conditionTraces.push({ conditionId: sc.id, type: 'score', passed: contributed > 0, scoreContributed: contributed })\n }\n\n return { matched: allInstantsPassed, conditionTraces, totalScore }\n}\n\nexport function resolveAudiences(audiences: Audience[], signals: VisitorSignals): ResolveResult {\n const allMatchedIds: string[] = []\n const traces: EvaluationTrace[] = []\n\n for (const audience of audiences) {\n const groupTraces: EvaluationTrace['groupTraces'] = []\n let audienceMatched = false\n let accumulatedScore = 0\n\n for (const group of audience.conditionGroups) {\n const { matched, conditionTraces, totalScore } = evaluateGroup(group, signals)\n accumulatedScore += totalScore\n groupTraces.push({ groupId: group.id, matched, conditionTraces })\n if (matched) audienceMatched = true\n }\n\n if (audience.scoreThreshold !== null) {\n const scoreThresholdMet = accumulatedScore >= audience.scoreThreshold\n const hasInstantConditions = audience.conditionGroups.some(g => g.conditions.some(c => c.type === 'instant'))\n if (hasInstantConditions) {\n audienceMatched = audienceMatched && scoreThresholdMet\n } else {\n audienceMatched = scoreThresholdMet\n }\n }\n\n traces.push({\n audienceId: audience.id,\n matched: audienceMatched,\n groupTraces,\n ...(accumulatedScore > 0 ? { totalScore: accumulatedScore } : {}),\n })\n if (audienceMatched) allMatchedIds.push(audience.id)\n }\n\n return { winningAudienceId: allMatchedIds[0] ?? null, allMatchedIds, traces }\n}\n", "// packages/kywi-js/src/audience/behavioral-collector.ts\nconst SESSION_KEY = 'kywi_session'\nconst TOTAL_VIEWS_KEY = 'kywi_total_views'\nconst CATEGORY_SCORES_KEY = 'kywi_category_scores'\nconst SESSION_START_KEY = 'kywi_session_start'\n\ninterface SessionData { pageViewCount: number; entryPage: string; pagesVisited: string[] }\n\nexport interface BehavioralResult {\n session: { pageViewCount: number; totalPageViews: number; sessionDuration: number; entryPage: string; pagesVisited: string[] }\n behavioral: { categoryScores: Record<string, number>; totalScore: number }\n}\n\nfunction getSession(): SessionData {\n const raw = sessionStorage.getItem(SESSION_KEY)\n if (raw) { try { return JSON.parse(raw) as SessionData } catch { /* fall through */ } }\n return { pageViewCount: 0, entryPage: '', pagesVisited: [] }\n}\n\nfunction getSessionStart(): number {\n const raw = sessionStorage.getItem(SESSION_START_KEY)\n if (raw) return Number(raw)\n const now = Date.now()\n sessionStorage.setItem(SESSION_START_KEY, String(now))\n return now\n}\n\nfunction getCategoryScores(): Record<string, number> {\n const raw = localStorage.getItem(CATEGORY_SCORES_KEY)\n if (raw) { try { return JSON.parse(raw) as Record<string, number> } catch { /* fall through */ } }\n return {}\n}\n\nexport function collectBehavioral(currentPath: string, category?: string): BehavioralResult {\n const session = getSession()\n session.pageViewCount += 1\n if (!session.entryPage) session.entryPage = currentPath\n session.pagesVisited.push(currentPath)\n sessionStorage.setItem(SESSION_KEY, JSON.stringify(session))\n\n const totalViews = (Number(localStorage.getItem(TOTAL_VIEWS_KEY)) || 0) + 1\n localStorage.setItem(TOTAL_VIEWS_KEY, String(totalViews))\n\n const sessionStart = getSessionStart()\n const categoryScores = getCategoryScores()\n if (category) {\n categoryScores[category] = (categoryScores[category] ?? 0) + 1\n localStorage.setItem(CATEGORY_SCORES_KEY, JSON.stringify(categoryScores))\n }\n\n return {\n session: { pageViewCount: session.pageViewCount, totalPageViews: totalViews, sessionDuration: Math.floor((Date.now() - sessionStart) / 1000), entryPage: session.entryPage, pagesVisited: session.pagesVisited },\n behavioral: { categoryScores, totalScore: 0 },\n }\n}\n", "// packages/kywi-js/src/audience/selfid-collector.ts\nconst SELFID_KEY = 'kywi_selfid'\n\nexport function collectSelfId(): Record<string, string> {\n const raw = localStorage.getItem(SELFID_KEY)\n if (!raw) return {}\n try { return JSON.parse(raw) as Record<string, string> } catch { return {} }\n}\n\nexport function storeSelfId(responses: Record<string, string>): void {\n localStorage.setItem(SELFID_KEY, JSON.stringify(responses))\n}\n", "// packages/kywi-js/src/audience/evaluate.ts\nimport type { Audience, VisitorSignals, AudienceResult } from '@kywi-software/core/audiences/types'\nimport { createEmptySignals } from '@kywi-software/core/audiences/types'\nimport { resolveAudiences } from '@kywi-software/core/evaluator'\nimport { collectBehavioral } from './behavioral-collector.js'\nimport { collectSelfId } from './selfid-collector.js'\n\nfunction merge(base: VisitorSignals, partial: Partial<VisitorSignals>): VisitorSignals {\n return {\n utm: partial.utm ?? base.utm, referrer: partial.referrer ?? base.referrer,\n session: partial.session ?? base.session, behavioral: partial.behavioral ?? base.behavioral,\n selfId: { ...base.selfId, ...partial.selfId }, identity: partial.identity ?? base.identity,\n adapters: { ...base.adapters, ...partial.adapters }, meta: { ...base.meta, ...partial.meta },\n }\n}\n\nexport function evaluateClientSide(\n audiences: Audience[], serverSignals: Partial<VisitorSignals>, currentPath: string, pageCategory?: string,\n): AudienceResult {\n let signals = merge(createEmptySignals(), serverSignals)\n const client = collectBehavioral(currentPath, pageCategory)\n const selfId = collectSelfId()\n signals = merge(signals, { session: client.session, behavioral: client.behavioral, selfId, meta: { ...signals.meta, resolvedAt: 'client' } })\n const { winningAudienceId, allMatchedIds } = resolveAudiences(audiences, signals)\n const isOptedOut = signals.meta.isOptedOut\n return { winningAudienceId: isOptedOut ? null : winningAudienceId, allMatchedIds, signals, isOptedOut }\n}\n", "// packages/kywi-js/src/audience/dom-patcher.ts\nexport function patchVariantContainers(winningAudienceId: string | null): void {\n const containers = document.querySelectorAll('.kywi-variant-container')\n for (const container of Array.from(containers)) {\n const el = container as HTMLElement\n el.classList.remove('kywi-variant-loading')\n el.removeAttribute('aria-busy')\n const skeleton = el.querySelector('.kywi-variant-skeleton')\n if (skeleton) skeleton.remove()\n const target = winningAudienceId ?? 'default'\n el.setAttribute('data-variant', target)\n for (const child of Array.from(el.querySelectorAll('[data-kywi-variant]'))) {\n const h = child as HTMLElement\n h.style.display = h.getAttribute('data-kywi-variant') === target ? '' : 'none'\n }\n }\n}\n", "// packages/kywi-js/src/cookies.ts\nexport const COOKIE_NAMES = {\n SIGNALS: 'kywi_signals', VISITOR: 'kywi_visitor', UTM: 'kywi_utm',\n AUDIENCE: 'kywi_audience', OPTOUT: 'kywi_optout', KNOWN: 'kywi_known',\n PREVIEW_INIT: 'kywi_preview_init',\n} as const\n\nexport function readCookies(): Map<string, string> {\n const map = new Map<string, string>()\n if (typeof document === 'undefined') return map\n for (const pair of document.cookie.split(';')) {\n const trimmed = pair.trim()\n const eqIdx = trimmed.indexOf('=')\n if (eqIdx < 0) continue\n map.set(trimmed.slice(0, eqIdx), decodeURIComponent(trimmed.slice(eqIdx + 1)))\n }\n return map\n}\n\nexport function setCookie(name: string, value: string, maxAge?: number): void {\n let str = `${name}=${encodeURIComponent(value)}; Path=/; SameSite=Lax`\n if (maxAge !== undefined && maxAge >= 0) str += `; Max-Age=${maxAge}`\n document.cookie = str\n}\n\nexport function deleteCookie(name: string): void {\n document.cookie = `${name}=; Path=/; Max-Age=0`\n}\n", "// packages/kywi-js/src/audience/transparency-styles.ts\n//\n// The transparency bar is injected into arbitrary host sites (any theme, any\n// reset, any CSS framework), so it can never rely on the host page shipping\n// `.kywi-transparency-*` rules \u2014 it has to carry its own, self-contained,\n// namespaced styles. This module injects a single `<style>` tag into\n// `<head>` the first time the bar is rendered and is a no-op after that.\n\nconst STYLE_ELEMENT_ID = 'kywi-transparency-styles'\n\nconst CSS = `\n.kywi-transparency-bar,\n.kywi-transparency-bar * {\n box-sizing: border-box;\n}\n.kywi-transparency-bar {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 2147483000;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 12px;\n margin: 0;\n padding: 12px 16px;\n background: rgba(23, 23, 28, 0.96);\n color: #f4f4f5;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif;\n font-size: 13px;\n line-height: 1.4;\n border-top: 1px solid rgba(255, 255, 255, 0.12);\n box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.25);\n animation: kywi-transparency-in 220ms ease-out;\n}\n@media (prefers-reduced-motion: reduce) {\n .kywi-transparency-bar { animation: none; }\n}\n@keyframes kywi-transparency-in {\n from { transform: translateY(100%); opacity: 0; }\n to { transform: translateY(0); opacity: 1; }\n}\n.kywi-transparency-text {\n flex: 1 1 240px;\n color: #f4f4f5;\n}\n.kywi-transparency-bar button {\n appearance: none;\n -webkit-appearance: none;\n font-family: inherit;\n font-size: 12px;\n line-height: 1.4;\n cursor: pointer;\n border-radius: 999px;\n transition: background 120ms ease, border-color 120ms ease, color 120ms ease;\n}\n.kywi-transparency-opt-out,\n.kywi-transparency-opt-in {\n flex: 0 0 auto;\n padding: 6px 14px;\n border: 1px solid rgba(255, 255, 255, 0.35);\n background: transparent;\n color: #f4f4f5;\n font-weight: 600;\n}\n.kywi-transparency-opt-out:hover,\n.kywi-transparency-opt-in:hover {\n background: rgba(255, 255, 255, 0.12);\n border-color: rgba(255, 255, 255, 0.5);\n}\n.kywi-transparency-dismiss {\n flex: 0 0 auto;\n width: 26px;\n height: 26px;\n padding: 0;\n border: 1px solid transparent;\n background: transparent;\n color: #d4d4d8;\n font-size: 13px;\n}\n.kywi-transparency-dismiss:hover {\n background: rgba(255, 255, 255, 0.1);\n color: #f4f4f5;\n}\n.kywi-transparency-bar button:focus-visible {\n outline: 2px solid #7dd3fc;\n outline-offset: 2px;\n}\n@media (max-width: 480px) {\n .kywi-transparency-bar {\n padding: 10px 12px;\n }\n .kywi-transparency-text {\n flex-basis: 100%;\n }\n}\n`\n\n/** Injects the transparency bar's stylesheet into `<head>` exactly once. */\nexport function ensureTransparencyStyles(): void {\n if (typeof document === 'undefined') return\n if (document.getElementById(STYLE_ELEMENT_ID)) return\n const style = document.createElement('style')\n style.id = STYLE_ELEMENT_ID\n style.textContent = CSS\n document.head.appendChild(style)\n}\n", "// packages/kywi-js/src/audience/transparency.ts\nimport { COOKIE_NAMES, setCookie, deleteCookie } from '../cookies.js'\nimport { ensureTransparencyStyles } from './transparency-styles.js'\n\nconst DISMISSED_KEY = 'kywi_transparency_dismissed'\n\nexport function isDismissed(): boolean { return localStorage.getItem(DISMISSED_KEY) === '1' }\nexport function dismiss(): void { localStorage.setItem(DISMISSED_KEY, '1'); removeBar() }\n\nfunction removeBar(): void { document.querySelector('.kywi-transparency-bar')?.remove() }\n\nexport function optOut(): void { setCookie(COOKIE_NAMES.OPTOUT, '1', 365 * 24 * 3600); deleteCookie(COOKIE_NAMES.AUDIENCE) }\nexport function optIn(): void { deleteCookie(COOKIE_NAMES.OPTOUT) }\n\ninterface TransparencyState { isPersonalized: boolean; isOptedOut: boolean; hasMatchAvailable: boolean }\n\nfunction createButton(className: string, text: string, onClick: () => void): HTMLButtonElement {\n const btn = document.createElement('button')\n btn.className = className\n btn.type = 'button'\n btn.textContent = text\n btn.addEventListener('click', onClick)\n return btn\n}\n\nexport function renderTransparencyBar(state: TransparencyState): void {\n removeBar()\n if (isDismissed()) return\n\n if ((state.isPersonalized && !state.isOptedOut) || (state.isOptedOut && state.hasMatchAvailable)) {\n ensureTransparencyStyles()\n }\n\n if (state.isPersonalized && !state.isOptedOut) {\n const bar = document.createElement('div')\n bar.className = 'kywi-transparency-bar kywi-transparency-active'\n bar.setAttribute('role', 'status')\n const text = document.createElement('span')\n text.className = 'kywi-transparency-text'\n text.textContent = 'This page has been personalized based on your browsing context.'\n bar.appendChild(text)\n bar.appendChild(createButton('kywi-transparency-opt-out', 'Opt out', () => { optOut(); window.location.reload() }))\n const dismissBtn = createButton('kywi-transparency-dismiss', '\\u2715', () => dismiss())\n dismissBtn.setAttribute('aria-label', 'Dismiss')\n bar.appendChild(dismissBtn)\n document.body.appendChild(bar)\n } else if (state.isOptedOut && state.hasMatchAvailable) {\n const bar = document.createElement('div')\n bar.className = 'kywi-transparency-bar kywi-transparency-opted-out'\n bar.setAttribute('role', 'status')\n const text = document.createElement('span')\n text.className = 'kywi-transparency-text'\n text.textContent = 'A personalized experience is available.'\n bar.appendChild(text)\n bar.appendChild(createButton('kywi-transparency-opt-in', 'Enable', () => { optIn(); window.location.reload() }))\n const dismissBtn = createButton('kywi-transparency-dismiss', '\\u2715', () => dismiss())\n dismissBtn.setAttribute('aria-label', 'Dismiss')\n bar.appendChild(dismissBtn)\n document.body.appendChild(bar)\n }\n}\n", "// packages/kywi-js/src/audience/preview.ts\nimport { COOKIE_NAMES, readCookies, deleteCookie } from '../cookies.js'\n\nconst PREVIEW_KEY = 'kywi_preview_audience'\n\nexport function getPreviewAudienceId(): string | null { return sessionStorage.getItem(PREVIEW_KEY) }\nexport function setPreviewAudienceId(id: string): void { sessionStorage.setItem(PREVIEW_KEY, id) }\nexport function clearPreview(): void { sessionStorage.removeItem(PREVIEW_KEY) }\n\nexport function checkPreviewInit(): void {\n const cookies = readCookies()\n const initId = cookies.get(COOKIE_NAMES.PREVIEW_INIT)\n if (initId) { setPreviewAudienceId(initId); deleteCookie(COOKIE_NAMES.PREVIEW_INIT) }\n}\n\nexport function renderPreviewBanner(audienceName: string): void {\n document.querySelector('.kywi-preview-banner')?.remove()\n const banner = document.createElement('div')\n banner.className = 'kywi-preview-banner'\n banner.setAttribute('role', 'status')\n const text = document.createElement('span')\n text.className = 'kywi-preview-text'\n text.textContent = 'Previewing as: '\n const strong = document.createElement('strong')\n strong.textContent = audienceName\n text.appendChild(strong)\n banner.appendChild(text)\n const exitBtn = document.createElement('button')\n exitBtn.className = 'kywi-preview-exit'\n exitBtn.type = 'button'\n exitBtn.textContent = 'Exit Preview'\n exitBtn.addEventListener('click', () => { clearPreview(); window.location.reload() })\n banner.appendChild(exitBtn)\n document.body.appendChild(banner)\n}\n", "// packages/kywi-js/src/audience/data-layer.ts\nimport type { KywiVisitor } from '../types.js'\n\nexport function populateDataLayer(visitor: KywiVisitor): void {\n const g = ((window as any).kywi ?? {}) as { visitor?: KywiVisitor }\n g.visitor = visitor\n ;(window as any).kywi = g\n}\n\nexport function fireKywiReady(): void { window.dispatchEvent(new CustomEvent('kywiReady')) }\n\nexport interface ServerMeta { audienceId: string | null; experimentId: string | null; variantId: string | null; visitorId: string }\n\nexport function readServerMeta(): ServerMeta {\n const m = (n: string) => document.querySelector(`meta[name=\"kywi:${n}\"]`)?.getAttribute('content') ?? null\n return { audienceId: m('audience-id'), experimentId: m('experiment-id'), variantId: m('variant-id'), visitorId: m('visitor-id') ?? '' }\n}\n", "// packages/kywi-js/src/audience/adapter-runner.ts\nimport type { VisitorSignals } from '@kywi-software/core/audiences/types'\n\ninterface PullAdapter {\n id: string\n side: 'client' | 'server-proxy'\n fields: string[]\n collect: (signals: Partial<VisitorSignals>) => Promise<Record<string, unknown>>\n}\n\nconst CACHE_PREFIX = 'kywi_adapter_'\n\nfunction getCached(adapterId: string): Record<string, unknown> | null {\n const raw = sessionStorage.getItem(CACHE_PREFIX + adapterId)\n if (!raw) return null\n try { return JSON.parse(raw) as Record<string, unknown> } catch { return null }\n}\n\nfunction setCache(adapterId: string, data: Record<string, unknown>): void {\n sessionStorage.setItem(CACHE_PREFIX + adapterId, JSON.stringify(data))\n}\n\nexport async function runClientAdapters(\n adapters: PullAdapter[], currentSignals: Partial<VisitorSignals>,\n apiBase = '/api/v1',\n): Promise<Record<string, unknown>> {\n const merged: Record<string, unknown> = {}\n\n const tasks = adapters.map(async (adapter) => {\n const cached = getCached(adapter.id)\n if (cached) return cached\n\n let result: Record<string, unknown>\n if (adapter.side === 'server-proxy') {\n // The proxy lives in the CMS runtime namespace (`{apiBase}/kywi/adapters/:id`),\n // alongside the audience-assignment and identity routes \u2014 not a bare\n // `/api/kywi/...` path, which would miss a handler mounted at `/api/v1`.\n const res = await fetch(`${apiBase}/kywi/adapters/${adapter.id}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ signals: currentSignals }),\n })\n const json = await res.json() as { data?: Record<string, unknown> }\n result = json.data ?? {}\n } else {\n result = await adapter.collect(currentSignals)\n }\n\n setCache(adapter.id, result)\n return result\n })\n\n const results = await Promise.all(tasks)\n for (const r of results) Object.assign(merged, r)\n return merged\n}\n", "// packages/kywi-js/src/audience/selfid-submit.ts\nimport { storeSelfId } from './selfid-collector.js'\nimport { evaluateClientSide } from './evaluate.js'\nimport { patchVariantContainers } from './dom-patcher.js'\nimport { populateDataLayer, fireKywiReady, readServerMeta } from './data-layer.js'\nimport { readCookies, COOKIE_NAMES } from '../cookies.js'\nimport type { Audience, VisitorSignals } from '@kywi-software/core/audiences/types'\n\nexport function handleSelfIdSubmit(\n responses: Record<string, string>,\n audiences?: Audience[],\n currentPath?: string,\n): void {\n // 1. Store responses (replaces previous)\n storeSelfId(responses)\n\n // 2. Re-evaluate if audiences provided\n if (audiences && currentPath) {\n const cookies = readCookies()\n const serverMeta = readServerMeta()\n const serverSignals: Partial<VisitorSignals> = {\n identity: { visitorId: serverMeta.visitorId || cookies.get(COOKIE_NAMES.VISITOR) || '', isKnown: cookies.has(COOKIE_NAMES.KNOWN), maLeadId: null },\n meta: { isOptedOut: cookies.has(COOKIE_NAMES.OPTOUT), isPreview: false, previewAudienceId: null, resolvedAt: 'server' },\n }\n const result = evaluateClientSide(audiences, serverSignals, currentPath)\n patchVariantContainers(result.winningAudienceId)\n populateDataLayer({\n visitorId: result.signals.identity.visitorId,\n audienceId: result.winningAudienceId,\n experimentId: serverMeta.experimentId,\n variantId: serverMeta.variantId,\n isPreview: false,\n isOptedOut: result.isOptedOut,\n })\n }\n}\n", "// packages/kywi-js/src/audience/selfid-widget.ts\nimport { storeSelfId } from './selfid-collector.js'\nimport { handleSelfIdSubmit } from './selfid-submit.js'\nimport type { Audience } from '@kywi-software/core/audiences/types'\n\nconst SHOWN_KEY = 'kywi_selfid_shown'\nconst MS_PER_DAY = 86_400_000\n\nexport interface SelfIdFieldConfig {\n id: string\n label: string\n type: 'text' | 'select' | 'email'\n options?: string[]\n required?: boolean\n}\n\n/** When the widget is shown, once frequency allows. Defaults to immediate. */\nexport type SelfIdWidgetTrigger =\n | { type: 'immediate' }\n | { type: 'scroll'; depth: number }\n | { type: 'delay'; seconds: number }\n | { type: 'manual' }\n\nexport interface SelfIdWidgetConfig {\n fields: SelfIdFieldConfig[]\n headline?: string\n subheadline?: string\n submitLabel?: string\n skipLabel?: string\n displayMode?: 'modal' | 'inline' | 'slide-in'\n frequency?: 'once' | 'session' | 'daily' | 'always'\n trigger?: SelfIdWidgetTrigger\n /**\n * The full audience rule definitions to re-evaluate client-side after a\n * submission. These flow straight into `handleSelfIdSubmit` \u2192\n * `evaluateClientSide` \u2192 `resolveAudiences`, which iterates each audience's\n * `conditionGroups`, so full `Audience` objects are required (not id strings).\n */\n audiences?: Audience[]\n currentPath?: string\n}\n\nexport interface SelfIdWidget {\n shouldShow(): boolean\n markShown(): void\n render(container: HTMLElement): void\n handleSubmit(responses: Record<string, string>): void\n}\n\nexport function createSelfIdWidget(config: SelfIdWidgetConfig): SelfIdWidget {\n const frequency = config.frequency ?? 'once'\n const displayMode = config.displayMode ?? 'inline'\n\n function shouldShow(): boolean {\n if (frequency === 'always') return true\n if (frequency === 'session') return false\n\n const raw = localStorage.getItem(SHOWN_KEY)\n if (!raw) return true\n\n if (frequency === 'once') return false\n\n // 'daily' \u2014 true if more than 24h since last shown\n const ts = Number(raw)\n return !isNaN(ts) && Date.now() - ts > MS_PER_DAY\n }\n\n function markShown(): void {\n localStorage.setItem(SHOWN_KEY, String(Date.now()))\n }\n\n function handleSubmit(responses: Record<string, string>): void {\n storeSelfId(responses)\n // Attempt the immediate variant swap, but never let a personalization/resolver\n // error skip markShown() \u2014 otherwise a `frequency: 'once'` widget re-shows on\n // every subsequent page load forever (issue #80). The `finally` keeps the\n // frequency gate honored even if `handleSelfIdSubmit` throws.\n try {\n handleSelfIdSubmit(responses, config.audiences ?? [], config.currentPath ?? '/')\n } finally {\n markShown()\n }\n }\n\n function render(container: HTMLElement): void {\n container.replaceChildren()\n container.className = `kywi-selfid-widget kywi-selfid-${displayMode}`\n\n if (config.headline) {\n const h = document.createElement('h3')\n h.className = 'kywi-selfid-headline'\n h.textContent = config.headline\n container.appendChild(h)\n }\n\n if (config.subheadline) {\n const p = document.createElement('p')\n p.className = 'kywi-selfid-subheadline'\n p.textContent = config.subheadline\n container.appendChild(p)\n }\n\n const form = document.createElement('form')\n form.className = 'kywi-selfid-form'\n\n for (const field of config.fields) {\n const fieldWrap = document.createElement('div')\n fieldWrap.className = 'kywi-selfid-field'\n\n const label = document.createElement('label')\n label.htmlFor = `kywi-field-${field.id}`\n label.textContent = field.label\n fieldWrap.appendChild(label)\n\n let input: HTMLInputElement | HTMLSelectElement\n\n if (field.type === 'select') {\n const select = document.createElement('select')\n select.id = `kywi-field-${field.id}`\n select.name = field.id\n if (field.required) select.required = true\n if (field.options) {\n const placeholder = document.createElement('option')\n placeholder.value = ''\n placeholder.textContent = ''\n select.appendChild(placeholder)\n for (const opt of field.options) {\n const option = document.createElement('option')\n option.value = opt\n option.textContent = opt\n select.appendChild(option)\n }\n }\n input = select\n } else {\n const inp = document.createElement('input')\n inp.id = `kywi-field-${field.id}`\n inp.name = field.id\n inp.type = field.type\n if (field.required) inp.required = true\n input = inp\n }\n\n fieldWrap.appendChild(input)\n form.appendChild(fieldWrap)\n }\n\n const actions = document.createElement('div')\n actions.className = 'kywi-selfid-actions'\n\n const submitBtn = document.createElement('button')\n submitBtn.type = 'submit'\n submitBtn.className = 'kywi-selfid-submit'\n submitBtn.textContent = config.submitLabel ?? 'Submit'\n actions.appendChild(submitBtn)\n\n if (config.skipLabel) {\n const skipBtn = document.createElement('button')\n skipBtn.type = 'button'\n skipBtn.className = 'kywi-selfid-skip'\n skipBtn.textContent = config.skipLabel\n skipBtn.addEventListener('click', () => {\n markShown()\n container.replaceChildren()\n })\n actions.appendChild(skipBtn)\n }\n\n form.appendChild(actions)\n\n form.addEventListener('submit', (e) => {\n e.preventDefault()\n const data = new FormData(form)\n const responses: Record<string, string> = {}\n data.forEach((value, key) => {\n responses[key] = String(value)\n })\n handleSubmit(responses)\n })\n\n container.appendChild(form)\n }\n\n return { shouldShow, markShown, render, handleSubmit }\n}\n", "// packages/kywi-js/src/personalization/badge.ts\nimport { COOKIE_NAMES, readCookies, setCookie, deleteCookie } from '../cookies.js'\n\nfunction isOptedOut(): boolean {\n return readCookies().has(COOKIE_NAMES.OPTOUT)\n}\n\nfunction createButton(className: string, text: string, onClick: () => void): HTMLButtonElement {\n const btn = document.createElement('button')\n btn.className = className\n btn.type = 'button'\n btn.textContent = text\n btn.addEventListener('click', onClick)\n return btn\n}\n\nexport function renderPersonalizationBadge(): void {\n const containers = document.querySelectorAll('[data-kywi-personalization-badge]')\n if (containers.length === 0) return\n\n for (const container of Array.from(containers)) {\n // Clear existing badge to avoid duplication\n const existing = container.querySelector('.kywi-personalization-badge')\n if (existing) existing.remove()\n\n const badge = document.createElement('div')\n badge.className = 'kywi-personalization-badge'\n\n const optedOut = isOptedOut()\n\n const status = document.createElement('span')\n status.className = 'kywi-badge-status'\n status.textContent = optedOut ? 'Personalization disabled' : 'Personalization active'\n badge.appendChild(status)\n\n if (optedOut) {\n badge.appendChild(createButton('kywi-badge-opt-in', 'Opt in', () => {\n deleteCookie(COOKIE_NAMES.OPTOUT)\n renderPersonalizationBadge()\n }))\n } else {\n badge.appendChild(createButton('kywi-badge-opt-out', 'Opt out', () => {\n setCookie(COOKIE_NAMES.OPTOUT, '1', 365 * 24 * 3600)\n deleteCookie(COOKIE_NAMES.AUDIENCE)\n renderPersonalizationBadge()\n }))\n }\n\n container.appendChild(badge)\n }\n}\n", "// packages/kywi-js/src/audience/index.ts\nimport type { Audience, VisitorSignals } from '@kywi-software/core/audiences/types'\nimport { evaluateClientSide } from './evaluate.js'\nimport { patchVariantContainers } from './dom-patcher.js'\nimport { renderTransparencyBar } from './transparency.js'\nimport { checkPreviewInit, getPreviewAudienceId, renderPreviewBanner } from './preview.js'\nimport { populateDataLayer, fireKywiReady, readServerMeta } from './data-layer.js'\nimport { readCookies, COOKIE_NAMES } from '../cookies.js'\nimport { runClientAdapters } from './adapter-runner.js'\nimport { Kywi } from '../index.js'\nimport { createSelfIdWidget, type SelfIdWidgetConfig } from './selfid-widget.js'\nimport { renderPersonalizationBadge } from '../personalization/badge.js'\n\nexport interface AudienceBootConfig {\n audiences: Audience[]\n currentPath: string\n pageCategory?: string\n serverSignals?: Partial<VisitorSignals>\n adapters?: Array<{ id: string; side: 'client' | 'server-proxy'; fields: string[]; collect: (s: Partial<VisitorSignals>) => Promise<Record<string, unknown>> }>\n selfIdWidget?: SelfIdWidgetConfig\n /**\n * Base path of the mounted CMS API (e.g. `/api/v1`). Runtime calls\n * (server-proxy adapters, audience assignment) are made under `{apiBase}/kywi/*`.\n * Defaults to the same `{basePath}/api/v1` derivation the entity/feed factories\n * use, so it matches the reference app's mount out of the box.\n */\n apiBase?: string\n}\n\n/** The mounted CMS API base \u2014 mirrors the derivation in Kywi.boot(). */\nfunction resolveApiBase(explicit?: string): string {\n if (explicit) return explicit\n const basePath = Kywi.context?.basePath\n if (!basePath || basePath === '/') return '/api/v1'\n return `${basePath}/api/v1`\n}\n\nexport async function bootAudienceEngine(config: AudienceBootConfig): Promise<void> {\n const { audiences, currentPath, pageCategory, serverSignals } = config\n const apiBase = resolveApiBase(config.apiBase)\n checkPreviewInit()\n const serverMeta = readServerMeta()\n const previewId = getPreviewAudienceId()\n\n if (previewId) {\n patchVariantContainers(previewId)\n renderPreviewBanner(previewId)\n renderPersonalizationBadge()\n populateDataLayer({ visitorId: serverMeta.visitorId, audienceId: previewId, experimentId: null, variantId: null, isPreview: true, isOptedOut: false })\n fireKywiReady()\n return\n }\n\n const cookies = readCookies()\n let merged: Partial<VisitorSignals> = {\n ...serverSignals,\n identity: { visitorId: serverMeta.visitorId || cookies.get(COOKIE_NAMES.VISITOR) || '', isKnown: cookies.has(COOKIE_NAMES.KNOWN), maLeadId: null },\n meta: { isOptedOut: cookies.has(COOKIE_NAMES.OPTOUT), isPreview: false, previewAudienceId: null, resolvedAt: 'server' },\n }\n\n // Run client-side adapters if configured\n if (config.adapters && config.adapters.length > 0) {\n const adapterResults = await runClientAdapters(config.adapters, merged, apiBase)\n merged.adapters = { ...merged.adapters, ...adapterResults }\n }\n\n const result = evaluateClientSide(audiences, merged, currentPath, pageCategory)\n patchVariantContainers(result.winningAudienceId)\n renderTransparencyBar({ isPersonalized: result.winningAudienceId !== null, isOptedOut: result.isOptedOut, hasMatchAvailable: result.allMatchedIds.length > 0 })\n // Render the opt-out badge wherever a personalizationBadge module was placed.\n renderPersonalizationBadge()\n populateDataLayer({ visitorId: result.signals.identity.visitorId, audienceId: result.winningAudienceId, experimentId: serverMeta.experimentId, variantId: serverMeta.variantId, isPreview: false, isOptedOut: result.isOptedOut })\n fireKywiReady()\n\n if (result.winningAudienceId && result.winningAudienceId !== serverMeta.audienceId) {\n fetch(`${apiBase}/kywi/audience`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...(Kywi.context?.csrfToken ? { 'X-CSRF-Token': Kywi.context.csrfToken } : {}) },\n body: JSON.stringify({ audienceId: result.winningAudienceId }),\n }).catch(() => {})\n }\n\n // Self-ID widget \u2014 mount when frequency allows, timed by its trigger.\n if (config.selfIdWidget) {\n const widget = createSelfIdWidget(config.selfIdWidget)\n if (widget.shouldShow()) {\n const doRender = () => {\n const existing = document.getElementById('kywi-selfid-container')\n const container = existing ?? document.createElement('div')\n if (!container.id) {\n container.id = 'kywi-selfid-container'\n document.body.appendChild(container)\n }\n widget.render(container)\n }\n scheduleSelfIdWidget(config.selfIdWidget.trigger, doRender)\n }\n }\n}\n\n/**\n * Show the self-ID widget per its trigger: immediately, after a delay, or once\n * the visitor scrolls past a depth fraction (0-1). `manual` never auto-shows \u2014\n * the host page decides. An absent trigger behaves as immediate.\n */\nfunction scheduleSelfIdWidget(trigger: SelfIdWidgetConfig['trigger'], render: () => void): void {\n if (!trigger || trigger.type === 'immediate') { render(); return }\n if (trigger.type === 'manual') return\n if (trigger.type === 'delay') {\n window.setTimeout(render, Math.max(0, trigger.seconds) * 1000)\n return\n }\n // scroll: fire once when scrolled past `depth` (fraction of scrollable height).\n const target = Math.min(Math.max(trigger.depth, 0), 1)\n let fired = false\n const onScroll = () => {\n if (fired) return\n const scrollable = document.documentElement.scrollHeight - window.innerHeight\n const progress = scrollable > 0 ? window.scrollY / scrollable : 1\n if (progress >= target) {\n fired = true\n window.removeEventListener('scroll', onScroll)\n render()\n }\n }\n window.addEventListener('scroll', onScroll, { passive: true })\n onScroll()\n}\n", "// packages/kywi-js/src/index.ts\nimport type { KywiContext, KywiModuleDefinition } from './types.js'\nimport { readContext } from './context.js'\nimport { createEntityFactory } from './entity.js'\nimport { createFeedFactory } from './feed.js'\nimport { renderFeed } from './render-feed.js'\nimport { initModules } from './module-system.js'\nimport { initFormHooks } from './form-hooks.js'\nimport { bootExperiments } from './experiments/index.js'\n\ntype PreInitCallback = (kywi: typeof Kywi) => void\nconst preInitCallbacks: PreInitCallback[] = []\nlet booted = false\n\nexport const Kywi = {\n version: '0.1.0',\n context: null as unknown as KywiContext,\n Module: {} as Record<string, KywiModuleDefinition>,\n preInit(fn: PreInitCallback): void {\n if (booted) { fn(Kywi) } else { preInitCallbacks.push(fn) }\n },\n UI: {\n extend(definition: KywiModuleDefinition): KywiModuleDefinition {\n return { ...definition }\n },\n },\n DisplayObject: {\n Form: {\n _hooks: {} as Record<string, (...args: unknown[]) => unknown>,\n extend(methods: Record<string, (...args: unknown[]) => unknown>): void {\n Object.assign(Kywi.DisplayObject.Form._hooks, methods)\n },\n },\n },\n getEntity: null as unknown as (type: string) => any,\n getFeed: null as unknown as (type: string) => any,\n renderFeed: null as unknown as (options: any) => void,\n boot(): void {\n if (booted) return\n Kywi.context = readContext()\n for (const fn of preInitCallbacks) { fn(Kywi) }\n const basePath = Kywi.context.basePath === '/' ? '/api/v1' : `${Kywi.context.basePath}/api/v1`\n Kywi.getEntity = createEntityFactory(basePath, Kywi.context.csrfToken)\n Kywi.getFeed = createFeedFactory(basePath, Kywi.context.csrfToken)\n Kywi.renderFeed = renderFeed\n initModules()\n initFormHooks()\n // A/B experiment beacons: confirm exposure of the server-rendered variant\n // and wire conversion signals (pageview / form-submit / kywi.track).\n bootExperiments({ context: Kywi.context })\n booted = true\n },\n}\n\nif (typeof globalThis !== 'undefined') { (globalThis as any).Kywi = Kywi }\nif (typeof document !== 'undefined') {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', () => Kywi.boot())\n } else {\n Kywi.boot()\n }\n}\n\nexport { bootAudienceEngine } from './audience/index.js'\nexport { bootExperiments, type ExperimentRuntime, type ConversionSignal } from './experiments/index.js'\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["isOptedOut", "createButton"]
|
|
4
|
+
"sourcesContent": ["// packages/kywi-js/src/context.ts\nimport type { KywiContext } from './types.js'\n\nexport function readContext(): KywiContext {\n const meta = (name: string): string => {\n if (typeof document === 'undefined') return ''\n const el = document.querySelector(`meta[name=\"kywi:${name}\"]`)\n return el?.getAttribute('content') ?? ''\n }\n return {\n siteId: meta('site-id') || document?.documentElement?.getAttribute('data-kywi-site') || '',\n locale: document?.documentElement?.lang || 'en',\n themePath: meta('theme-path') || '',\n basePath: meta('base-path') || '/',\n csrfToken: meta('csrf-token') || '',\n isEditMode: document?.body?.classList?.contains('kywi-edit-mode') ?? false,\n }\n}\n", "// packages/kywi-js/src/entity.ts\nimport type { KywiEntityObject } from './types.js'\n\nfunction createEntity(type: string, basePath: string, csrfToken: string, data: Record<string, unknown>): KywiEntityObject {\n const fields = { ...data }\n const dirty = new Map<string, unknown>()\n const errors: string[] = []\n const headers: Record<string, string> = { 'Content-Type': 'application/json' }\n if (csrfToken) headers['X-CSRF-Token'] = csrfToken\n\n const entity: KywiEntityObject = {\n get(field: string) { return fields[field] },\n set(field: string, value: unknown) { fields[field] = value; dirty.set(field, value); return entity },\n async save() {\n const id = fields['id'] as string | undefined\n const url = id ? `${basePath}/content/${type}/${id}` : `${basePath}/content/${type}`\n const res = await fetch(url, { method: id ? 'PUT' : 'POST', headers, body: JSON.stringify(Object.fromEntries(dirty)) })\n const json = await res.json() as { data?: Record<string, unknown>; error?: { message: string } }\n if (!res.ok || json.error) { errors.push(json.error?.message ?? 'Save failed'); throw entity }\n if (json.data) Object.assign(fields, json.data)\n dirty.clear()\n return entity\n },\n async delete() {\n const id = fields['id'] as string\n await fetch(`${basePath}/content/${type}/${id}`, { method: 'DELETE', headers })\n },\n getErrors() { return [...errors] },\n async loadBy(field: string, value: string) {\n const url = field === 'id' ? `${basePath}/content/${type}/${value}` : `${basePath}/content/${type}?${field}=${encodeURIComponent(value)}`\n const res = await fetch(url, { headers })\n const json = await res.json() as { data?: Record<string, unknown>; error?: { message: string } }\n if (!res.ok || json.error) { errors.push(json.error?.message ?? 'Load failed'); throw entity }\n if (json.data) Object.assign(fields, json.data)\n return entity\n },\n }\n return entity\n}\n\nexport function createEntityFactory(basePath: string, csrfToken: string) {\n return (type: string): KywiEntityObject => createEntity(type, basePath, csrfToken, {})\n}\n", "// packages/kywi-js/src/feed.ts\nimport type { KywiEntityObject, KywiFeedResult } from './types.js'\n\ninterface Filter { field: string; operator: string; value?: unknown; conjunction: 'and' | 'or' }\n\nexport type AggregateFunction = 'count' | 'sum' | 'min' | 'max' | 'avg'\nexport type AggregateResult = Record<string, unknown>\n\nclass PropBuilder {\n constructor(private builder: FeedBuilder, private field: string, private conj: 'and' | 'or') {}\n private add(op: string, value?: unknown) { this.builder._filters.push({ field: this.field, operator: op, value, conjunction: this.conj }); return this.builder }\n isEQ(v: unknown) { return this.add('eq', v) }\n isNEQ(v: unknown) { return this.add('neq', v) }\n isLT(v: unknown) { return this.add('lt', v) }\n isLTE(v: unknown) { return this.add('lte', v) }\n isGT(v: unknown) { return this.add('gt', v) }\n isGTE(v: unknown) { return this.add('gte', v) }\n beginsWith(v: unknown) { return this.add('beginsWith', v) }\n endsWith(v: unknown) { return this.add('endsWith', v) }\n contains(v: unknown) { return this.add('contains', v) }\n isNull() { return this.add('isNull') }\n isNotNull() { return this.add('isNotNull') }\n}\n\nclass FeedBuilder {\n _filters: Filter[] = []\n private _sort: { field: string; direction: 'asc' | 'desc' } | null = null\n private _limit: number | null = null\n private _page: number | null = null\n constructor(private contentType: string, private basePath: string, private csrfToken: string) {}\n\n where(): this { return this }\n prop(field: string) { return new PropBuilder(this, field, 'and') }\n andProp(field: string) { return new PropBuilder(this, field, 'and') }\n orProp(field: string) { return new PropBuilder(this, field, 'or') }\n sort(field: string, direction: 'asc' | 'desc' = 'asc'): this { this._sort = { field, direction }; return this }\n maxItems(n: number): this { this._limit = n; return this }\n page(n: number): this { this._page = n; return this }\n\n private buildBody(): Record<string, unknown> {\n const filterArray = this._filters.map(f => ({\n field: f.field,\n operator: f.operator,\n value: f.value,\n conjunction: f.conjunction,\n }))\n const body: Record<string, unknown> = { contentType: this.contentType }\n if (filterArray.length > 0) body['filters'] = filterArray\n if (this._sort) body['sort'] = this._sort\n if (this._limit !== null) body['limit'] = this._limit\n if (this._page !== null) body['page'] = this._page\n return body\n }\n\n private buildHeaders(): Record<string, string> {\n const headers: Record<string, string> = { 'Content-Type': 'application/json' }\n if (this.csrfToken) headers['X-CSRF-Token'] = this.csrfToken\n return headers\n }\n\n async aggregate(fn: AggregateFunction, field?: string): Promise<AggregateResult> {\n const body = this.buildBody()\n const agg: Record<string, string> = { function: fn }\n if (field) agg['field'] = field\n body['aggregate'] = agg\n\n const res = await fetch(`${this.basePath}/feeds/aggregate`, {\n method: 'POST',\n headers: this.buildHeaders(),\n body: JSON.stringify(body),\n })\n const json = await res.json() as { data?: AggregateResult }\n return json.data ?? {}\n }\n\n async getQuery(): Promise<KywiFeedResult> {\n const body = this.buildBody()\n const res = await fetch(`${this.basePath}/feeds/query`, {\n method: 'POST',\n headers: this.buildHeaders(),\n body: JSON.stringify(body),\n })\n // Two response envelopes are supported:\n // 1. The live @kywi-software/core server (POST /feeds/query -> jsonOk(executeFeedQuery))\n // returns { data: { items, total, page, pageSize, totalPages } }.\n // 2. A flatter { data: [ ...items ], meta: { total, page, totalPages } } shape.\n // Normalise both so the decoupled client works against the real API.\n const json = await res.json() as {\n data?: Array<Record<string, unknown>> | { items?: Array<Record<string, unknown>>; total?: number; page?: number; pageSize?: number; totalPages?: number }\n meta?: { total?: number; page?: number; totalPages?: number }\n }\n\n const payload = json.data\n const rawItems: Array<Record<string, unknown>> = Array.isArray(payload)\n ? payload\n : (payload?.items ?? [])\n const total = Array.isArray(payload) ? (json.meta?.total ?? rawItems.length) : (payload?.total ?? rawItems.length)\n const page = Array.isArray(payload) ? (json.meta?.page ?? 1) : (payload?.page ?? 1)\n const pages = Array.isArray(payload) ? (json.meta?.totalPages ?? 0) : (payload?.totalPages ?? 0)\n\n const items: KywiEntityObject[] = rawItems.map(d => ({\n get(field: string) { return d[field] },\n set() { throw new Error('Feed results are read-only') },\n save() { return Promise.reject(new Error('Feed results are read-only')) },\n delete() { return Promise.reject(new Error('Feed results are read-only')) },\n getErrors() { return [] },\n loadBy() { return Promise.reject(new Error('Use Kywi.getEntity() to load by field')) },\n }))\n\n return { items, total, page, pages }\n }\n}\n\nexport function createFeedFactory(basePath: string, csrfToken: string) {\n return (type: string) => new FeedBuilder(type, basePath, csrfToken)\n}\n", "// packages/kywi-js/src/render-feed.ts\nimport type { KywiEntityObject, KywiFeedResult } from './types.js'\n\ninterface RenderFeedOptions {\n feed: { getQuery(): Promise<KywiFeedResult> }\n container: HTMLElement\n template: (item: KywiEntityObject) => string | Node\n loadingText?: string; emptyText?: string\n wrapperTag?: string; wrapperClass?: string\n unsafeHtml?: boolean\n onRender?: (container: HTMLElement) => void\n}\n\nexport async function renderFeed(options: RenderFeedOptions): Promise<void> {\n const { feed, container, template, loadingText = '', emptyText = '', wrapperTag = 'div', wrapperClass, unsafeHtml = false, onRender } = options\n if (loadingText) container.textContent = loadingText\n const result = await feed.getQuery()\n container.textContent = ''\n if (result.items.length === 0) { if (emptyText) container.textContent = emptyText; return }\n const wrapper = document.createElement(wrapperTag)\n if (wrapperClass) wrapper.className = wrapperClass\n for (const item of result.items) {\n const rendered = template(item)\n if (rendered instanceof Node) {\n wrapper.appendChild(rendered)\n } else if (unsafeHtml) {\n const span = document.createElement('span')\n // intentional: caller explicitly opts in via unsafeHtml\n span['innerHTML'] = rendered\n wrapper.appendChild(span)\n } else {\n const span = document.createElement('span')\n span.textContent = rendered // SAFE: always textContent for string templates\n wrapper.appendChild(span)\n }\n }\n container.appendChild(wrapper)\n if (onRender) onRender(container)\n}\n", "// packages/kywi-js/src/module-system.ts\nimport { Kywi } from './index.js'\nimport type { KywiModuleContext } from './types.js'\n\nfunction readParams(el: HTMLElement): Record<string, string> {\n const params: Record<string, string> = {}\n for (const attr of Array.from(el.attributes)) {\n if (attr.name.startsWith('data-kywi-param-')) {\n params[attr.name.slice(16)] = attr.value\n }\n }\n return params\n}\n\nexport function initModules(): void {\n const elements = document.querySelectorAll('[data-kywi-module]')\n for (const el of Array.from(elements)) {\n const htmlEl = el as HTMLElement\n const moduleName = htmlEl.getAttribute('data-kywi-module')\n if (!moduleName) continue\n const def = Kywi.Module[moduleName]\n if (!def || !def.renderClient) continue\n const context: KywiModuleContext = { targetEl: htmlEl, ...readParams(htmlEl) }\n def.renderClient.call({ context, ...def })\n }\n}\n", "// packages/kywi-js/src/form-hooks.ts\nimport { Kywi } from './index.js'\n\nexport function initFormHooks(): void {\n const forms = document.querySelectorAll('[data-kywi-form]')\n for (const formEl of Array.from(forms)) {\n const htmlForm = formEl as HTMLFormElement\n const hooks = Kywi.DisplayObject.Form._hooks\n if (hooks['onAfterRender']) hooks['onAfterRender'].call({ context: { targetEl: htmlForm } })\n htmlForm.addEventListener('submit', (e) => {\n if (hooks['onSubmit']) {\n const result = hooks['onSubmit'].call({ context: { targetEl: htmlForm } })\n if (result === false) e.preventDefault()\n }\n })\n }\n}\n\nexport async function submitKywiForm(form: HTMLFormElement, endpoint: string): Promise<void> {\n const formData = new FormData(form)\n const data: Record<string, string> = {}\n formData.forEach((value, key) => { data[key] = value as string })\n\n const res = await fetch(endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(data),\n })\n const json = await res.json() as { success: boolean; errors?: Record<string, string>; data?: Record<string, unknown> }\n const hooks = Kywi.DisplayObject.Form._hooks\n\n if (!json.success && json.errors) {\n if (typeof hooks['onAfterErrorRender'] === 'function') {\n hooks['onAfterErrorRender']({ errors: json.errors, targetEl: form })\n }\n } else if (json.success && json.data) {\n if (typeof hooks['onAfterResponseRender'] === 'function') {\n hooks['onAfterResponseRender']({ response: json.data, targetEl: form })\n }\n }\n}\n", "// packages/kywi-js/src/experiments/index.ts\n//\n// Client-side A/B experiment beacons. Reads the server-rendered kywi:* meta\n// tags, confirms the exposure, and reports conversion signals (pageview,\n// form-submit, custom) back to the runtime endpoints. Fire-and-forget: every\n// call is best-effort and never throws into the host page.\n\nimport { readContext } from '../context.js'\nimport type { KywiContext } from '../types.js'\n\nexport interface ConversionSignal {\n type: 'pageview' | 'form_submit' | 'custom'\n url?: string\n formId?: string\n eventName?: string\n}\n\nexport interface ExperimentBootConfig {\n context?: KywiContext\n apiBase?: string\n visitorId?: string\n currentPath?: string\n /** Auto-emit a pageview conversion signal on boot (default true). */\n autoPageview?: boolean\n}\n\nexport interface ExperimentRuntime {\n /** Emit a custom conversion event, e.g. kywi.track('signup'). */\n track(eventName: string): void\n /** Emit a raw conversion signal. */\n trackConversion(signal: ConversionSignal): void\n}\n\nfunction apiBaseFrom(ctx: KywiContext): string {\n return ctx.basePath && ctx.basePath !== '/' ? `${ctx.basePath}/api/v1` : '/api/v1'\n}\n\nfunction metaContent(name: string): string | null {\n if (typeof document === 'undefined') return null\n return document.querySelector(`meta[name=\"kywi:${name}\"]`)?.getAttribute('content') ?? null\n}\n\n// A single document-level submit listener is installed once and routes to the\n// most recent boot's handler \u2014 booting twice must not double-count conversions.\nlet submitListenerInstalled = false\nlet currentFormConversion: ((formId: string) => void) | null = null\n\nfunction installFormListener(): void {\n if (submitListenerInstalled || typeof document === 'undefined') return\n submitListenerInstalled = true\n document.addEventListener(\n 'submit',\n (e) => {\n const form = e.target as HTMLElement | null\n if (!form || form.tagName !== 'FORM') return\n const formId = form.getAttribute('data-kywi-form-id') ?? form.getAttribute('id')\n if (formId && currentFormConversion) currentFormConversion(formId)\n },\n true,\n )\n}\n\nfunction beacon(url: string, body: unknown, csrfToken?: string): void {\n try {\n void fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...(csrfToken ? { 'X-CSRF-Token': csrfToken } : {}) },\n body: JSON.stringify(body),\n keepalive: true,\n }).catch(() => {})\n } catch {\n /* never throw into the host page */\n }\n}\n\n/**\n * Boot the experiment beacons. Safe to call once per page load; when no\n * experiment meta is present it only wires the conversion listeners.\n */\nexport function bootExperiments(config: ExperimentBootConfig = {}): ExperimentRuntime {\n const ctx = config.context ?? readContext()\n const apiBase = config.apiBase ?? apiBaseFrom(ctx)\n const csrf = ctx.csrfToken || undefined\n const experimentId = metaContent('experiment-id')\n const visitorId = config.visitorId ?? metaContent('visitor-id') ?? undefined\n const currentPath = config.currentPath ?? (typeof location !== 'undefined' ? location.pathname : '/')\n\n function trackConversion(signal: ConversionSignal): void {\n beacon(`${apiBase}/kywi/experiments/conversion`, { visitorId, event: signal }, csrf)\n }\n function track(eventName: string): void {\n trackConversion({ type: 'custom', eventName })\n }\n\n // 1) Exposure \u2014 confirm the server-rendered variant was seen. The variant is\n // recomputed server-side, so we only send the experiment + visitor ids.\n if (experimentId) {\n beacon(`${apiBase}/kywi/experiments/exposure`, { experimentId, visitorId }, csrf)\n }\n\n // 2) Pageview conversion signal \u2014 lets pageview-goal experiments convert when\n // an enrolled visitor lands on the goal path.\n if (config.autoPageview !== false) {\n trackConversion({ type: 'pageview', url: currentPath })\n }\n\n // 3) Form-submit conversion \u2014 capture submits of any tagged form. The listener\n // is installed once; this boot becomes its active handler.\n currentFormConversion = (formId: string) => trackConversion({ type: 'form_submit', formId })\n installFormListener()\n\n const runtime: ExperimentRuntime = { track, trackConversion }\n\n // Expose on the data layer so analytics / manual conversions can reach it.\n const g = ((globalThis as unknown as { kywi?: Record<string, unknown> }).kywi ?? {})\n g['track'] = track\n g['trackConversion'] = trackConversion\n ;(globalThis as unknown as { kywi?: Record<string, unknown> }).kywi = g\n\n return runtime\n}\n", "// \u2500\u2500 Visitor Signals \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface VisitorSignals {\n utm: {\n source: string | null\n medium: string | null\n campaign: string | null\n term: string | null\n content: string | null\n }\n referrer: {\n raw: string | null\n domain: string | null\n sourceType: 'organic' | 'paid' | 'social' | 'email' | 'direct' | 'other'\n }\n session: {\n pageViewCount: number\n totalPageViews: number\n sessionDuration: number\n entryPage: string\n pagesVisited: string[]\n }\n behavioral: {\n categoryScores: Record<string, number>\n totalScore: number\n }\n selfId: Record<string, string>\n identity: {\n visitorId: string\n isKnown: boolean\n maLeadId: string | null\n }\n adapters: Record<string, unknown>\n meta: {\n isOptedOut: boolean\n isPreview: boolean\n previewAudienceId: string | null\n resolvedAt: 'server' | 'client'\n }\n}\n\n// \u2500\u2500 Evaluation Result \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface VisitorContext {\n request: Request\n partialSignals?: Partial<VisitorSignals>\n}\n\nexport interface AudienceResult {\n winningAudienceId: string | null\n allMatchedIds: string[]\n signals: VisitorSignals\n isOptedOut: boolean\n}\n\n// \u2500\u2500 Audience & Rule Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport type AudienceStatus = 'active' | 'draft' | 'archived'\n\nexport interface Audience {\n id: string\n siteId: string\n name: string\n description: string | null\n priority: number\n status: AudienceStatus\n conditionGroups: ConditionGroup[]\n scoreThreshold: number | null\n createdAt: Date\n updatedAt: Date\n}\n\nexport interface ConditionGroup {\n id: string\n audienceId: string\n sortOrder: number\n conditions: Condition[]\n}\n\nexport type Condition = InstantMatchCondition | ScoreContributionCondition\n\nexport interface InstantMatchCondition {\n type: 'instant'\n id: string\n groupId: string\n signal: InstantSignalRef\n operator: InstantOperator\n value: string | string[]\n}\n\nexport type InstantSignalRef =\n | 'utm.source' | 'utm.medium' | 'utm.campaign' | 'utm.term' | 'utm.content'\n | 'referrer.domain' | 'referrer.sourceType'\n | `selfId.${string}`\n | `adapter.${string}`\n | 'identity.isKnown'\n | 'session.entryPage'\n | 'session.pagesVisited'\n\nexport type InstantOperator =\n | 'equals' | 'not_equals' | 'contains' | 'starts_with' | 'matches_glob'\n | 'is_one_of' | 'is_true' | 'is_false'\n | 'gte' | 'lte'\n\nexport interface ScoreContributionCondition {\n type: 'score'\n id: string\n groupId: string\n trigger: ScoreTrigger\n points: number\n threshold?: number\n category?: string\n pattern?: string\n /**\n * For `trigger: 'signalMatch'` \u2014 award `points` when an arbitrary instant\n * signal matches (e.g. `utm.campaign contains 'enterprise' \u2192 +30`). Reuses the\n * instant-match operator set so any signal (UTM / referrer / self-ID / adapter)\n * can contribute to a score, not just the five behavioral triggers.\n */\n signal?: InstantSignalRef\n operator?: InstantOperator\n value?: string | string[]\n}\n\nexport type ScoreTrigger =\n | 'pageViewCount'\n | 'totalPageViews'\n | 'urlMatch'\n | 'categoryViewed'\n | 'timeOnSite'\n | 'signalMatch'\n\n// \u2500\u2500 Self-ID Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface SelfIdField {\n id: string\n siteId: string\n label: string\n picklist: Array<{ value: string; label: string }>\n required: boolean\n sortOrder: number\n}\n\nexport interface SelfIdWidgetConfig {\n id: string\n siteId: string\n displayMode: 'hello_bar_top' | 'hello_bar_bottom' | 'modal' | 'inline' | 'drawer'\n trigger: SelfIdTrigger\n headline: string\n subheadline: string | null\n fieldIds: string[]\n submitLabel: string\n skipLabel: string | null\n frequency: 'once_visitor' | 'once_session' | 'always'\n}\n\nexport type SelfIdTrigger =\n | { type: 'immediate' }\n | { type: 'scroll'; depth: number }\n | { type: 'delay'; seconds: number }\n | { type: 'manual' }\n\n// \u2500\u2500 Preview Token \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface PreviewTokenPayload {\n jti: string\n audienceId: string\n expiresAt: number\n}\n\n// \u2500\u2500 Default Signals \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport function createEmptySignals(): VisitorSignals {\n return {\n utm: { source: null, medium: null, campaign: null, term: null, content: null },\n referrer: { raw: null, domain: null, sourceType: 'direct' },\n session: { pageViewCount: 0, totalPageViews: 0, sessionDuration: 0, entryPage: '/', pagesVisited: [] },\n behavioral: { categoryScores: {}, totalScore: 0 },\n selfId: {},\n identity: { visitorId: '', isKnown: false, maLeadId: null },\n adapters: {},\n meta: { isOptedOut: false, isPreview: false, previewAudienceId: null, resolvedAt: 'server' },\n }\n}\n", "export function matchGlob(pattern: string, value: string): boolean {\n const parts = pattern.split('*')\n if (parts.length === 1) return pattern === value\n let pos = 0\n const first = parts[0]!\n if (first !== '') {\n if (!value.startsWith(first)) return false\n pos = first.length\n }\n for (let i = 1; i < parts.length - 1; i++) {\n const part = parts[i]!\n if (part === '') continue\n const idx = value.indexOf(part, pos)\n if (idx < 0) return false\n pos = idx + part.length\n }\n const last = parts[parts.length - 1]!\n if (last !== '') {\n if (!value.endsWith(last)) return false\n if (value.length - last.length < pos) return false\n }\n return true\n}\n", "import type { VisitorSignals, InstantMatchCondition, InstantSignalRef } from '../types.js'\nimport { matchGlob } from './glob.js'\n\nexport function resolveSignalValue(signals: VisitorSignals, ref: InstantSignalRef): string | null {\n if (ref === 'utm.source') return signals.utm.source\n if (ref === 'utm.medium') return signals.utm.medium\n if (ref === 'utm.campaign') return signals.utm.campaign\n if (ref === 'utm.term') return signals.utm.term\n if (ref === 'utm.content') return signals.utm.content\n if (ref === 'referrer.domain') return signals.referrer.domain\n if (ref === 'referrer.sourceType') return signals.referrer.sourceType\n if (ref === 'identity.isKnown') return signals.identity.isKnown ? 'true' : 'false'\n if (ref === 'session.entryPage') return signals.session.entryPage\n if (ref === 'session.pagesVisited') return signals.session.pagesVisited.join(',')\n if (ref.startsWith('selfId.')) {\n const key = ref.slice(7)\n return signals.selfId[key] ?? null\n }\n if (ref.startsWith('adapter.')) {\n const key = ref.slice(8)\n const val = signals.adapters[key]\n return val !== undefined && val !== null ? String(val) : null\n }\n return null\n}\n\nexport function evaluateInstantCondition(condition: InstantMatchCondition, signals: VisitorSignals): boolean {\n const actual = resolveSignalValue(signals, condition.signal)\n const expected = condition.value\n switch (condition.operator) {\n case 'equals': return actual === expected\n case 'not_equals': return actual !== expected\n case 'contains': return actual !== null && typeof expected === 'string' && actual.includes(expected)\n case 'starts_with': return actual !== null && typeof expected === 'string' && actual.startsWith(expected)\n case 'matches_glob': return actual !== null && typeof expected === 'string' && matchGlob(expected, actual)\n case 'is_one_of': return actual !== null && Array.isArray(condition.value) && condition.value.includes(actual)\n case 'is_true': return actual === 'true'\n case 'is_false': return actual === 'false'\n case 'gte': return actual !== null && typeof expected === 'string' && Number(actual) >= Number(expected)\n case 'lte': return actual !== null && typeof expected === 'string' && Number(actual) <= Number(expected)\n default: return false\n }\n}\n", "import type { VisitorSignals, ScoreContributionCondition } from '../types.js'\nimport { matchGlob } from './glob.js'\nimport { evaluateInstantCondition } from './instant-match.js'\n\nfunction evaluateOneScore(cond: ScoreContributionCondition, signals: VisitorSignals): number {\n const threshold = cond.threshold ?? 0\n switch (cond.trigger) {\n case 'pageViewCount': return signals.session.pageViewCount >= threshold ? cond.points : 0\n case 'totalPageViews': return signals.session.totalPageViews >= threshold ? cond.points : 0\n case 'timeOnSite': return signals.session.sessionDuration >= threshold ? cond.points : 0\n case 'categoryViewed': {\n const cat = cond.category ?? ''\n const score = signals.behavioral.categoryScores[cat]\n return score !== undefined && score >= threshold ? cond.points : 0\n }\n case 'urlMatch': {\n const pattern = cond.pattern ?? '*'\n const matched = signals.session.pagesVisited.some(url => matchGlob(pattern, url))\n return matched ? cond.points : 0\n }\n case 'signalMatch': {\n // Award points when an arbitrary instant signal matches. Reuses the\n // instant-match evaluator so every operator/signal is supported.\n if (!cond.signal || !cond.operator) return 0\n const matched = evaluateInstantCondition(\n {\n type: 'instant',\n id: cond.id,\n groupId: cond.groupId,\n signal: cond.signal,\n operator: cond.operator,\n value: cond.value ?? '',\n },\n signals,\n )\n return matched ? cond.points : 0\n }\n default: return 0\n }\n}\n\nexport function evaluateScoreConditions(conditions: ScoreContributionCondition[], signals: VisitorSignals): number {\n let total = 0\n for (const cond of conditions) { total += evaluateOneScore(cond, signals) }\n return total\n}\n", "import type { Condition, VisitorSignals } from '../types.js'\n\n// \u2500\u2500\u2500 Custom Condition Type Registry \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// Allows third-party code (plugins, adapters, custom app code) to register\n// additional condition type evaluators without forking the core evaluator.\n//\n// Usage:\n// import { registerConditionType } from '@kywi-software/core'\n//\n// registerConditionType('my_custom_type', (condition, signals) => {\n// // Return true if the condition matches the current visitor signals\n// return signals.adapters['my_adapter'] === condition.value\n// })\n\ntype ConditionEvaluator = (condition: Condition, signals: VisitorSignals) => boolean\n\nconst registry = new Map<string, ConditionEvaluator>()\n\n/**\n * Register a custom condition type evaluator.\n *\n * @param name - The condition `type` string this evaluator handles.\n * @param evaluate - Pure function that returns `true` when the condition matches.\n *\n * Calling this with an already-registered name overwrites the previous evaluator.\n */\nexport function registerConditionType(name: string, evaluate: ConditionEvaluator): void {\n registry.set(name, evaluate)\n}\n\n/**\n * Remove a previously registered condition type evaluator.\n * No-op if the name was never registered.\n */\nexport function unregisterConditionType(name: string): void {\n registry.delete(name)\n}\n\n/**\n * Evaluate a condition using a registered custom evaluator.\n * Returns `false` if no evaluator is registered for the condition's type.\n */\nexport function evaluateCustomCondition(condition: Condition, signals: VisitorSignals): boolean {\n const evaluator = registry.get(condition.type)\n if (!evaluator) return false\n return evaluator(condition, signals)\n}\n\n/**\n * Returns true if a custom evaluator is registered for the given condition type name.\n */\nexport function hasConditionType(name: string): boolean {\n return registry.has(name)\n}\n\n/**\n * Returns the names of all registered custom condition types.\n */\nexport function listConditionTypes(): string[] {\n return [...registry.keys()]\n}\n", "import type { Audience, VisitorSignals, ConditionGroup, InstantMatchCondition, ScoreContributionCondition } from '../types.js'\nimport { evaluateInstantCondition } from './instant-match.js'\nimport { evaluateScoreConditions } from './score.js'\nimport { hasConditionType, evaluateCustomCondition } from './condition-registry.js'\n\nexport interface ConditionTrace {\n conditionId: string\n type: 'instant' | 'score'\n passed: boolean\n scoreContributed?: number\n}\n\nexport interface EvaluationTrace {\n audienceId: string\n matched: boolean\n groupTraces: Array<{ groupId: string; matched: boolean; conditionTraces: ConditionTrace[] }>\n totalScore?: number\n}\n\nexport interface ResolveResult {\n winningAudienceId: string | null\n allMatchedIds: string[]\n traces: EvaluationTrace[]\n}\n\n// Evaluate one group: AND all instant + custom conditions, accumulate score conditions\nfunction evaluateGroup(group: ConditionGroup, signals: VisitorSignals) {\n const conditionTraces: ConditionTrace[] = []\n const instants: InstantMatchCondition[] = []\n const scores: ScoreContributionCondition[] = []\n const customs: typeof group.conditions = []\n\n for (const c of group.conditions) {\n // The Condition union only models 'instant'/'score', but the registry\n // dispatches custom condition kinds by their `type` string at runtime.\n // Capture it as a string so the custom branch stays reachable.\n const conditionType: string = c.type\n if (c.type === 'instant') instants.push(c)\n else if (c.type === 'score') scores.push(c)\n else if (hasConditionType(conditionType)) customs.push(c)\n // Unknown types with no registered evaluator are silently skipped\n }\n\n let allInstantsPassed = true\n\n for (const ic of instants) {\n const passed = evaluateInstantCondition(ic, signals)\n conditionTraces.push({ conditionId: ic.id, type: 'instant', passed })\n if (!passed) allInstantsPassed = false\n }\n\n // Custom conditions are ANDed with instant conditions\n for (const cc of customs) {\n const passed = evaluateCustomCondition(cc, signals)\n conditionTraces.push({ conditionId: cc.id, type: cc.type as 'instant', passed })\n if (!passed) allInstantsPassed = false\n }\n\n const totalScore = evaluateScoreConditions(scores, signals)\n for (const sc of scores) {\n const contributed = evaluateScoreConditions([sc], signals)\n conditionTraces.push({ conditionId: sc.id, type: 'score', passed: contributed > 0, scoreContributed: contributed })\n }\n\n return { matched: allInstantsPassed, conditionTraces, totalScore }\n}\n\nexport function resolveAudiences(audiences: Audience[], signals: VisitorSignals): ResolveResult {\n const allMatchedIds: string[] = []\n const traces: EvaluationTrace[] = []\n\n for (const audience of audiences) {\n const groupTraces: EvaluationTrace['groupTraces'] = []\n let audienceMatched = false\n let accumulatedScore = 0\n\n for (const group of audience.conditionGroups) {\n const { matched, conditionTraces, totalScore } = evaluateGroup(group, signals)\n accumulatedScore += totalScore\n groupTraces.push({ groupId: group.id, matched, conditionTraces })\n if (matched) audienceMatched = true\n }\n\n if (audience.scoreThreshold !== null) {\n const scoreThresholdMet = accumulatedScore >= audience.scoreThreshold\n const hasInstantConditions = audience.conditionGroups.some(g => g.conditions.some(c => c.type === 'instant'))\n if (hasInstantConditions) {\n audienceMatched = audienceMatched && scoreThresholdMet\n } else {\n audienceMatched = scoreThresholdMet\n }\n }\n\n traces.push({\n audienceId: audience.id,\n matched: audienceMatched,\n groupTraces,\n ...(accumulatedScore > 0 ? { totalScore: accumulatedScore } : {}),\n })\n if (audienceMatched) allMatchedIds.push(audience.id)\n }\n\n return { winningAudienceId: allMatchedIds[0] ?? null, allMatchedIds, traces }\n}\n", "// packages/kywi-js/src/audience/behavioral-collector.ts\nconst SESSION_KEY = 'kywi_session'\nconst TOTAL_VIEWS_KEY = 'kywi_total_views'\nconst CATEGORY_SCORES_KEY = 'kywi_category_scores'\nconst SESSION_START_KEY = 'kywi_session_start'\n\ninterface SessionData { pageViewCount: number; entryPage: string; pagesVisited: string[] }\n\nexport interface BehavioralResult {\n session: { pageViewCount: number; totalPageViews: number; sessionDuration: number; entryPage: string; pagesVisited: string[] }\n behavioral: { categoryScores: Record<string, number>; totalScore: number }\n}\n\nfunction getSession(): SessionData {\n const raw = sessionStorage.getItem(SESSION_KEY)\n if (raw) { try { return JSON.parse(raw) as SessionData } catch { /* fall through */ } }\n return { pageViewCount: 0, entryPage: '', pagesVisited: [] }\n}\n\nfunction getSessionStart(): number {\n const raw = sessionStorage.getItem(SESSION_START_KEY)\n if (raw) return Number(raw)\n const now = Date.now()\n sessionStorage.setItem(SESSION_START_KEY, String(now))\n return now\n}\n\nfunction getCategoryScores(): Record<string, number> {\n const raw = localStorage.getItem(CATEGORY_SCORES_KEY)\n if (raw) { try { return JSON.parse(raw) as Record<string, number> } catch { /* fall through */ } }\n return {}\n}\n\nexport function collectBehavioral(currentPath: string, category?: string): BehavioralResult {\n const session = getSession()\n session.pageViewCount += 1\n if (!session.entryPage) session.entryPage = currentPath\n session.pagesVisited.push(currentPath)\n sessionStorage.setItem(SESSION_KEY, JSON.stringify(session))\n\n const totalViews = (Number(localStorage.getItem(TOTAL_VIEWS_KEY)) || 0) + 1\n localStorage.setItem(TOTAL_VIEWS_KEY, String(totalViews))\n\n const sessionStart = getSessionStart()\n const categoryScores = getCategoryScores()\n if (category) {\n categoryScores[category] = (categoryScores[category] ?? 0) + 1\n localStorage.setItem(CATEGORY_SCORES_KEY, JSON.stringify(categoryScores))\n }\n\n return {\n session: { pageViewCount: session.pageViewCount, totalPageViews: totalViews, sessionDuration: Math.floor((Date.now() - sessionStart) / 1000), entryPage: session.entryPage, pagesVisited: session.pagesVisited },\n behavioral: { categoryScores, totalScore: 0 },\n }\n}\n", "// packages/kywi-js/src/audience/selfid-collector.ts\nconst SELFID_KEY = 'kywi_selfid'\n\nexport function collectSelfId(): Record<string, string> {\n const raw = localStorage.getItem(SELFID_KEY)\n if (!raw) return {}\n try { return JSON.parse(raw) as Record<string, string> } catch { return {} }\n}\n\nexport function storeSelfId(responses: Record<string, string>): void {\n localStorage.setItem(SELFID_KEY, JSON.stringify(responses))\n}\n", "// packages/kywi-js/src/audience/evaluate.ts\nimport type { Audience, VisitorSignals, AudienceResult } from '@kywi-software/core/audiences/types'\nimport { createEmptySignals } from '@kywi-software/core/audiences/types'\nimport { resolveAudiences } from '@kywi-software/core/evaluator'\nimport { collectBehavioral } from './behavioral-collector.js'\nimport { collectSelfId } from './selfid-collector.js'\n\nfunction merge(base: VisitorSignals, partial: Partial<VisitorSignals>): VisitorSignals {\n return {\n utm: partial.utm ?? base.utm, referrer: partial.referrer ?? base.referrer,\n session: partial.session ?? base.session, behavioral: partial.behavioral ?? base.behavioral,\n selfId: { ...base.selfId, ...partial.selfId }, identity: partial.identity ?? base.identity,\n adapters: { ...base.adapters, ...partial.adapters }, meta: { ...base.meta, ...partial.meta },\n }\n}\n\nexport function evaluateClientSide(\n audiences: Audience[], serverSignals: Partial<VisitorSignals>, currentPath: string, pageCategory?: string,\n): AudienceResult {\n let signals = merge(createEmptySignals(), serverSignals)\n const client = collectBehavioral(currentPath, pageCategory)\n const selfId = collectSelfId()\n signals = merge(signals, { session: client.session, behavioral: client.behavioral, selfId, meta: { ...signals.meta, resolvedAt: 'client' } })\n const { winningAudienceId, allMatchedIds } = resolveAudiences(audiences, signals)\n const isOptedOut = signals.meta.isOptedOut\n return { winningAudienceId: isOptedOut ? null : winningAudienceId, allMatchedIds, signals, isOptedOut }\n}\n", "// packages/kywi-js/src/audience/dom-patcher.ts\nexport function patchVariantContainers(winningAudienceId: string | null): void {\n const containers = document.querySelectorAll('.kywi-variant-container')\n for (const container of Array.from(containers)) {\n const el = container as HTMLElement\n const arms = Array.from(el.querySelectorAll('[data-kywi-variant]'))\n\n // Only module-level containers (VariantContainerModule in\n // packages/core/src/layout/modules-extended.tsx) render every arm into the\n // DOM for this client-side swap \u2014 each tagged `[data-kywi-variant]`, with at\n // least a \"default\" arm present even while loading. Section-level containers\n // (SectionRenderer's VariantContainerRenderer in packages/core/src/layout/\n // renderer.tsx, and components/personalization/VariantContainer.tsx) share\n // the `.kywi-variant-container` selector but are fully server-resolved: they\n // render only the winning arm's markup directly, so they never have any\n // `[data-kywi-variant]` children. That \"has arms to toggle\" structure is the\n // most robust discriminator available (unlike a class or `data-mode`\n // attribute, it can't drift out of sync with what this function actually\n // needs to do) \u2014 skip anything without arms so we never overwrite a\n // server-resolved container's `data-variant` with a client-side audience id\n // that disagrees with the content already rendered (kywi-cms#99).\n if (arms.length === 0) continue\n\n el.classList.remove('kywi-variant-loading')\n el.removeAttribute('aria-busy')\n const skeleton = el.querySelector('.kywi-variant-skeleton')\n if (skeleton) skeleton.remove()\n const target = winningAudienceId ?? 'default'\n el.setAttribute('data-variant', target)\n for (const child of arms) {\n const h = child as HTMLElement\n h.style.display = h.getAttribute('data-kywi-variant') === target ? '' : 'none'\n }\n }\n}\n", "// packages/kywi-js/src/cookies.ts\nexport const COOKIE_NAMES = {\n SIGNALS: 'kywi_signals', VISITOR: 'kywi_visitor', UTM: 'kywi_utm',\n AUDIENCE: 'kywi_audience', OPTOUT: 'kywi_optout', KNOWN: 'kywi_known',\n PREVIEW_INIT: 'kywi_preview_init',\n} as const\n\nexport function readCookies(): Map<string, string> {\n const map = new Map<string, string>()\n if (typeof document === 'undefined') return map\n for (const pair of document.cookie.split(';')) {\n const trimmed = pair.trim()\n const eqIdx = trimmed.indexOf('=')\n if (eqIdx < 0) continue\n map.set(trimmed.slice(0, eqIdx), decodeURIComponent(trimmed.slice(eqIdx + 1)))\n }\n return map\n}\n\nexport function setCookie(name: string, value: string, maxAge?: number): void {\n let str = `${name}=${encodeURIComponent(value)}; Path=/; SameSite=Lax`\n if (maxAge !== undefined && maxAge >= 0) str += `; Max-Age=${maxAge}`\n document.cookie = str\n}\n\nexport function deleteCookie(name: string): void {\n document.cookie = `${name}=; Path=/; Max-Age=0`\n}\n", "// packages/kywi-js/src/audience/transparency-styles.ts\n//\n// The transparency bar is injected into arbitrary host sites (any theme, any\n// reset, any CSS framework), so it can never rely on the host page shipping\n// `.kywi-transparency-*` rules \u2014 it has to carry its own, self-contained,\n// namespaced styles. This module injects a single `<style>` tag into\n// `<head>` the first time the bar is rendered and is a no-op after that.\n\nconst STYLE_ELEMENT_ID = 'kywi-transparency-styles'\n\nconst CSS = `\n.kywi-transparency-bar,\n.kywi-transparency-bar * {\n box-sizing: border-box;\n}\n.kywi-transparency-bar {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 2147483000;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 12px;\n margin: 0;\n padding: 12px 16px;\n background: rgba(23, 23, 28, 0.96);\n color: #f4f4f5;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif;\n font-size: 13px;\n line-height: 1.4;\n border-top: 1px solid rgba(255, 255, 255, 0.12);\n box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.25);\n animation: kywi-transparency-in 220ms ease-out;\n}\n@media (prefers-reduced-motion: reduce) {\n .kywi-transparency-bar { animation: none; }\n}\n@keyframes kywi-transparency-in {\n from { transform: translateY(100%); opacity: 0; }\n to { transform: translateY(0); opacity: 1; }\n}\n.kywi-transparency-text {\n flex: 1 1 240px;\n color: #f4f4f5;\n}\n.kywi-transparency-bar button {\n appearance: none;\n -webkit-appearance: none;\n font-family: inherit;\n font-size: 12px;\n line-height: 1.4;\n cursor: pointer;\n border-radius: 999px;\n transition: background 120ms ease, border-color 120ms ease, color 120ms ease;\n}\n.kywi-transparency-opt-out,\n.kywi-transparency-opt-in {\n flex: 0 0 auto;\n padding: 6px 14px;\n border: 1px solid rgba(255, 255, 255, 0.35);\n background: transparent;\n color: #f4f4f5;\n font-weight: 600;\n}\n.kywi-transparency-opt-out:hover,\n.kywi-transparency-opt-in:hover {\n background: rgba(255, 255, 255, 0.12);\n border-color: rgba(255, 255, 255, 0.5);\n}\n.kywi-transparency-dismiss {\n flex: 0 0 auto;\n width: 26px;\n height: 26px;\n padding: 0;\n border: 1px solid transparent;\n background: transparent;\n color: #d4d4d8;\n font-size: 13px;\n}\n.kywi-transparency-dismiss:hover {\n background: rgba(255, 255, 255, 0.1);\n color: #f4f4f5;\n}\n.kywi-transparency-bar button:focus-visible {\n outline: 2px solid #7dd3fc;\n outline-offset: 2px;\n}\n@media (max-width: 480px) {\n .kywi-transparency-bar {\n padding: 10px 12px;\n }\n .kywi-transparency-text {\n flex-basis: 100%;\n }\n}\n`\n\n/** Injects the transparency bar's stylesheet into `<head>` exactly once. */\nexport function ensureTransparencyStyles(): void {\n if (typeof document === 'undefined') return\n if (document.getElementById(STYLE_ELEMENT_ID)) return\n const style = document.createElement('style')\n style.id = STYLE_ELEMENT_ID\n style.textContent = CSS\n document.head.appendChild(style)\n}\n", "// packages/kywi-js/src/audience/transparency.ts\nimport { COOKIE_NAMES, setCookie, deleteCookie } from '../cookies.js'\nimport { ensureTransparencyStyles } from './transparency-styles.js'\n\nconst DISMISSED_KEY = 'kywi_transparency_dismissed'\n\nexport function isDismissed(): boolean { return localStorage.getItem(DISMISSED_KEY) === '1' }\nexport function dismiss(): void { localStorage.setItem(DISMISSED_KEY, '1'); removeBar() }\n\nfunction removeBar(): void { document.querySelector('.kywi-transparency-bar')?.remove() }\n\nexport function optOut(): void { setCookie(COOKIE_NAMES.OPTOUT, '1', 365 * 24 * 3600); deleteCookie(COOKIE_NAMES.AUDIENCE) }\nexport function optIn(): void { deleteCookie(COOKIE_NAMES.OPTOUT) }\n\ninterface TransparencyState { isPersonalized: boolean; isOptedOut: boolean; hasMatchAvailable: boolean }\n\nfunction createButton(className: string, text: string, onClick: () => void): HTMLButtonElement {\n const btn = document.createElement('button')\n btn.className = className\n btn.type = 'button'\n btn.textContent = text\n btn.addEventListener('click', onClick)\n return btn\n}\n\nexport function renderTransparencyBar(state: TransparencyState): void {\n removeBar()\n if (isDismissed()) return\n\n if ((state.isPersonalized && !state.isOptedOut) || (state.isOptedOut && state.hasMatchAvailable)) {\n ensureTransparencyStyles()\n }\n\n if (state.isPersonalized && !state.isOptedOut) {\n const bar = document.createElement('div')\n bar.className = 'kywi-transparency-bar kywi-transparency-active'\n bar.setAttribute('role', 'status')\n const text = document.createElement('span')\n text.className = 'kywi-transparency-text'\n text.textContent = 'This page has been personalized based on your browsing context.'\n bar.appendChild(text)\n bar.appendChild(createButton('kywi-transparency-opt-out', 'Opt out', () => { optOut(); window.location.reload() }))\n const dismissBtn = createButton('kywi-transparency-dismiss', '\\u2715', () => dismiss())\n dismissBtn.setAttribute('aria-label', 'Dismiss')\n bar.appendChild(dismissBtn)\n document.body.appendChild(bar)\n } else if (state.isOptedOut && state.hasMatchAvailable) {\n const bar = document.createElement('div')\n bar.className = 'kywi-transparency-bar kywi-transparency-opted-out'\n bar.setAttribute('role', 'status')\n const text = document.createElement('span')\n text.className = 'kywi-transparency-text'\n text.textContent = 'A personalized experience is available.'\n bar.appendChild(text)\n bar.appendChild(createButton('kywi-transparency-opt-in', 'Enable', () => { optIn(); window.location.reload() }))\n const dismissBtn = createButton('kywi-transparency-dismiss', '\\u2715', () => dismiss())\n dismissBtn.setAttribute('aria-label', 'Dismiss')\n bar.appendChild(dismissBtn)\n document.body.appendChild(bar)\n }\n}\n", "// packages/kywi-js/src/audience/preview.ts\nimport { COOKIE_NAMES, readCookies, deleteCookie } from '../cookies.js'\n\nconst PREVIEW_KEY = 'kywi_preview_audience'\n\nexport function getPreviewAudienceId(): string | null { return sessionStorage.getItem(PREVIEW_KEY) }\nexport function setPreviewAudienceId(id: string): void { sessionStorage.setItem(PREVIEW_KEY, id) }\nexport function clearPreview(): void { sessionStorage.removeItem(PREVIEW_KEY) }\n\nexport function checkPreviewInit(): void {\n const cookies = readCookies()\n const initId = cookies.get(COOKIE_NAMES.PREVIEW_INIT)\n if (initId) { setPreviewAudienceId(initId); deleteCookie(COOKIE_NAMES.PREVIEW_INIT) }\n}\n\nexport function renderPreviewBanner(audienceName: string): void {\n document.querySelector('.kywi-preview-banner')?.remove()\n const banner = document.createElement('div')\n banner.className = 'kywi-preview-banner'\n banner.setAttribute('role', 'status')\n const text = document.createElement('span')\n text.className = 'kywi-preview-text'\n text.textContent = 'Previewing as: '\n const strong = document.createElement('strong')\n strong.textContent = audienceName\n text.appendChild(strong)\n banner.appendChild(text)\n const exitBtn = document.createElement('button')\n exitBtn.className = 'kywi-preview-exit'\n exitBtn.type = 'button'\n exitBtn.textContent = 'Exit Preview'\n exitBtn.addEventListener('click', () => { clearPreview(); window.location.reload() })\n banner.appendChild(exitBtn)\n document.body.appendChild(banner)\n}\n", "// packages/kywi-js/src/audience/data-layer.ts\nimport type { KywiVisitor } from '../types.js'\n\nexport function populateDataLayer(visitor: KywiVisitor): void {\n const g = ((window as any).kywi ?? {}) as { visitor?: KywiVisitor }\n g.visitor = visitor\n ;(window as any).kywi = g\n}\n\nexport function fireKywiReady(): void { window.dispatchEvent(new CustomEvent('kywiReady')) }\n\nexport interface ServerMeta { audienceId: string | null; experimentId: string | null; variantId: string | null; visitorId: string }\n\nexport function readServerMeta(): ServerMeta {\n const m = (n: string) => document.querySelector(`meta[name=\"kywi:${n}\"]`)?.getAttribute('content') ?? null\n return { audienceId: m('audience-id'), experimentId: m('experiment-id'), variantId: m('variant-id'), visitorId: m('visitor-id') ?? '' }\n}\n", "// packages/kywi-js/src/audience/adapter-runner.ts\nimport type { VisitorSignals } from '@kywi-software/core/audiences/types'\n\ninterface PullAdapter {\n id: string\n side: 'client' | 'server-proxy'\n fields: string[]\n collect: (signals: Partial<VisitorSignals>) => Promise<Record<string, unknown>>\n}\n\nconst CACHE_PREFIX = 'kywi_adapter_'\n\nfunction getCached(adapterId: string): Record<string, unknown> | null {\n const raw = sessionStorage.getItem(CACHE_PREFIX + adapterId)\n if (!raw) return null\n try { return JSON.parse(raw) as Record<string, unknown> } catch { return null }\n}\n\nfunction setCache(adapterId: string, data: Record<string, unknown>): void {\n sessionStorage.setItem(CACHE_PREFIX + adapterId, JSON.stringify(data))\n}\n\nexport async function runClientAdapters(\n adapters: PullAdapter[], currentSignals: Partial<VisitorSignals>,\n apiBase = '/api/v1',\n): Promise<Record<string, unknown>> {\n const merged: Record<string, unknown> = {}\n\n const tasks = adapters.map(async (adapter) => {\n const cached = getCached(adapter.id)\n if (cached) return cached\n\n let result: Record<string, unknown>\n if (adapter.side === 'server-proxy') {\n // The proxy lives in the CMS runtime namespace (`{apiBase}/kywi/adapters/:id`),\n // alongside the audience-assignment and identity routes \u2014 not a bare\n // `/api/kywi/...` path, which would miss a handler mounted at `/api/v1`.\n const res = await fetch(`${apiBase}/kywi/adapters/${adapter.id}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ signals: currentSignals }),\n })\n const json = await res.json() as { data?: Record<string, unknown> }\n result = json.data ?? {}\n } else {\n result = await adapter.collect(currentSignals)\n }\n\n setCache(adapter.id, result)\n return result\n })\n\n const results = await Promise.all(tasks)\n for (const r of results) Object.assign(merged, r)\n return merged\n}\n", "// packages/kywi-js/src/audience/selfid-submit.ts\nimport { storeSelfId } from './selfid-collector.js'\nimport { evaluateClientSide } from './evaluate.js'\nimport { patchVariantContainers } from './dom-patcher.js'\nimport { populateDataLayer, fireKywiReady, readServerMeta } from './data-layer.js'\nimport { readCookies, COOKIE_NAMES } from '../cookies.js'\nimport type { Audience, VisitorSignals } from '@kywi-software/core/audiences/types'\n\nexport function handleSelfIdSubmit(\n responses: Record<string, string>,\n audiences?: Audience[],\n currentPath?: string,\n): void {\n // 1. Store responses (replaces previous)\n storeSelfId(responses)\n\n // 2. Re-evaluate if audiences provided\n if (audiences && currentPath) {\n const cookies = readCookies()\n const serverMeta = readServerMeta()\n const serverSignals: Partial<VisitorSignals> = {\n identity: { visitorId: serverMeta.visitorId || cookies.get(COOKIE_NAMES.VISITOR) || '', isKnown: cookies.has(COOKIE_NAMES.KNOWN), maLeadId: null },\n meta: { isOptedOut: cookies.has(COOKIE_NAMES.OPTOUT), isPreview: false, previewAudienceId: null, resolvedAt: 'server' },\n }\n const result = evaluateClientSide(audiences, serverSignals, currentPath)\n patchVariantContainers(result.winningAudienceId)\n populateDataLayer({\n visitorId: result.signals.identity.visitorId,\n audienceId: result.winningAudienceId,\n experimentId: serverMeta.experimentId,\n variantId: serverMeta.variantId,\n isPreview: false,\n isOptedOut: result.isOptedOut,\n })\n }\n}\n", "// packages/kywi-js/src/audience/selfid-widget.ts\nimport { storeSelfId } from './selfid-collector.js'\nimport { handleSelfIdSubmit } from './selfid-submit.js'\nimport type { Audience } from '@kywi-software/core/audiences/types'\n\nconst SHOWN_KEY = 'kywi_selfid_shown'\nconst MS_PER_DAY = 86_400_000\n\n/** Display modes that render their own explicit dismiss control (issue #97). */\nconst DISMISSIBLE_MODES = new Set(['hello_bar_top', 'hello_bar_bottom', 'drawer'])\n\n/** A picklist option: the value submitted, and the label shown to the visitor. */\nexport interface SelfIdFieldOption {\n value: string\n label: string\n}\n\nexport interface SelfIdFieldConfig {\n id: string\n label: string\n type: 'text' | 'select' | 'email'\n /**\n * Either `{value, label}` pairs (current server shape \u2014 see\n * resolveSelfIdWidget in the create-kywi-app scaffold) or bare strings (older\n * config shape, kept for backward compatibility). A bare string is treated as\n * both its own value and its own label.\n */\n options?: Array<string | SelfIdFieldOption>\n required?: boolean\n}\n\n/** Normalize a picklist option to `{value, label}`, treating a bare string as both. */\nfunction normalizeOption(opt: string | SelfIdFieldOption): SelfIdFieldOption {\n return typeof opt === 'string' ? { value: opt, label: opt } : opt\n}\n\n/** When the widget is shown, once frequency allows. Defaults to immediate. */\nexport type SelfIdWidgetTrigger =\n | { type: 'immediate' }\n | { type: 'scroll'; depth: number }\n | { type: 'delay'; seconds: number }\n | { type: 'manual' }\n\nexport interface SelfIdWidgetConfig {\n fields: SelfIdFieldConfig[]\n headline?: string\n subheadline?: string\n submitLabel?: string\n skipLabel?: string\n displayMode?: 'modal' | 'inline' | 'slide-in' | 'hello_bar_top' | 'hello_bar_bottom' | 'drawer'\n frequency?: 'once' | 'session' | 'daily' | 'always'\n trigger?: SelfIdWidgetTrigger\n /**\n * The full audience rule definitions to re-evaluate client-side after a\n * submission. These flow straight into `handleSelfIdSubmit` \u2192\n * `evaluateClientSide` \u2192 `resolveAudiences`, which iterates each audience's\n * `conditionGroups`, so full `Audience` objects are required (not id strings).\n */\n audiences?: Audience[]\n currentPath?: string\n}\n\nexport interface SelfIdWidget {\n shouldShow(): boolean\n markShown(): void\n render(container: HTMLElement): void\n handleSubmit(responses: Record<string, string>): void\n}\n\nexport function createSelfIdWidget(config: SelfIdWidgetConfig): SelfIdWidget {\n const frequency = config.frequency ?? 'once'\n const displayMode = config.displayMode ?? 'inline'\n\n function shouldShow(): boolean {\n if (frequency === 'always') return true\n if (frequency === 'session') return false\n\n const raw = localStorage.getItem(SHOWN_KEY)\n if (!raw) return true\n\n if (frequency === 'once') return false\n\n // 'daily' \u2014 true if more than 24h since last shown\n const ts = Number(raw)\n return !isNaN(ts) && Date.now() - ts > MS_PER_DAY\n }\n\n function markShown(): void {\n localStorage.setItem(SHOWN_KEY, String(Date.now()))\n }\n\n function handleSubmit(responses: Record<string, string>): void {\n storeSelfId(responses)\n // Attempt the immediate variant swap, but never let a personalization/resolver\n // error skip markShown() \u2014 otherwise a `frequency: 'once'` widget re-shows on\n // every subsequent page load forever (issue #80). The `finally` keeps the\n // frequency gate honored even if `handleSelfIdSubmit` throws.\n try {\n handleSelfIdSubmit(responses, config.audiences ?? [], config.currentPath ?? '/')\n } finally {\n markShown()\n }\n }\n\n function render(container: HTMLElement): void {\n container.replaceChildren()\n // Style hook uses kebab-case (kywi-selfid-hello-bar-top) even though the\n // config value is snake_case (hello_bar_top), matching the existing\n // kywi-selfid-slide-in convention.\n const displayModeClass = displayMode.replace(/_/g, '-')\n container.className = `kywi-selfid-widget kywi-selfid-${displayModeClass}`\n\n if (DISMISSIBLE_MODES.has(displayMode)) {\n const dismissBtn = document.createElement('button')\n dismissBtn.type = 'button'\n dismissBtn.className = 'kywi-selfid-dismiss'\n dismissBtn.setAttribute('aria-label', 'Dismiss')\n dismissBtn.textContent = '\u00D7'\n dismissBtn.addEventListener('click', () => {\n markShown()\n container.replaceChildren()\n })\n container.appendChild(dismissBtn)\n }\n\n if (config.headline) {\n const h = document.createElement('h3')\n h.className = 'kywi-selfid-headline'\n h.textContent = config.headline\n container.appendChild(h)\n }\n\n if (config.subheadline) {\n const p = document.createElement('p')\n p.className = 'kywi-selfid-subheadline'\n p.textContent = config.subheadline\n container.appendChild(p)\n }\n\n const form = document.createElement('form')\n form.className = 'kywi-selfid-form'\n\n for (const field of config.fields) {\n const fieldWrap = document.createElement('div')\n fieldWrap.className = 'kywi-selfid-field'\n\n const label = document.createElement('label')\n label.htmlFor = `kywi-field-${field.id}`\n label.textContent = field.label\n fieldWrap.appendChild(label)\n\n let input: HTMLInputElement | HTMLSelectElement\n\n if (field.type === 'select') {\n const select = document.createElement('select')\n select.id = `kywi-field-${field.id}`\n select.name = field.id\n if (field.required) select.required = true\n if (field.options) {\n const placeholder = document.createElement('option')\n placeholder.value = ''\n placeholder.textContent = ''\n select.appendChild(placeholder)\n for (const opt of field.options) {\n const { value, label } = normalizeOption(opt)\n const option = document.createElement('option')\n option.value = value\n option.textContent = label\n select.appendChild(option)\n }\n }\n input = select\n } else {\n const inp = document.createElement('input')\n inp.id = `kywi-field-${field.id}`\n inp.name = field.id\n inp.type = field.type\n if (field.required) inp.required = true\n input = inp\n }\n\n fieldWrap.appendChild(input)\n form.appendChild(fieldWrap)\n }\n\n const actions = document.createElement('div')\n actions.className = 'kywi-selfid-actions'\n\n const submitBtn = document.createElement('button')\n submitBtn.type = 'submit'\n submitBtn.className = 'kywi-selfid-submit'\n submitBtn.textContent = config.submitLabel ?? 'Submit'\n actions.appendChild(submitBtn)\n\n if (config.skipLabel) {\n const skipBtn = document.createElement('button')\n skipBtn.type = 'button'\n skipBtn.className = 'kywi-selfid-skip'\n skipBtn.textContent = config.skipLabel\n skipBtn.addEventListener('click', () => {\n markShown()\n container.replaceChildren()\n })\n actions.appendChild(skipBtn)\n }\n\n form.appendChild(actions)\n\n form.addEventListener('submit', (e) => {\n e.preventDefault()\n const data = new FormData(form)\n const responses: Record<string, string> = {}\n data.forEach((value, key) => {\n responses[key] = String(value)\n })\n handleSubmit(responses)\n })\n\n container.appendChild(form)\n }\n\n return { shouldShow, markShown, render, handleSubmit }\n}\n", "// packages/kywi-js/src/personalization/badge.ts\nimport { COOKIE_NAMES, readCookies, setCookie, deleteCookie } from '../cookies.js'\n\nfunction isOptedOut(): boolean {\n return readCookies().has(COOKIE_NAMES.OPTOUT)\n}\n\nfunction createButton(className: string, text: string, onClick: () => void): HTMLButtonElement {\n const btn = document.createElement('button')\n btn.className = className\n btn.type = 'button'\n btn.textContent = text\n btn.addEventListener('click', onClick)\n return btn\n}\n\nexport function renderPersonalizationBadge(): void {\n const containers = document.querySelectorAll('[data-kywi-personalization-badge]')\n if (containers.length === 0) return\n\n for (const container of Array.from(containers)) {\n // Clear existing badge to avoid duplication\n const existing = container.querySelector('.kywi-personalization-badge')\n if (existing) existing.remove()\n\n const badge = document.createElement('div')\n badge.className = 'kywi-personalization-badge'\n\n const optedOut = isOptedOut()\n\n const status = document.createElement('span')\n status.className = 'kywi-badge-status'\n status.textContent = optedOut ? 'Personalization disabled' : 'Personalization active'\n badge.appendChild(status)\n\n if (optedOut) {\n badge.appendChild(createButton('kywi-badge-opt-in', 'Opt in', () => {\n deleteCookie(COOKIE_NAMES.OPTOUT)\n renderPersonalizationBadge()\n }))\n } else {\n badge.appendChild(createButton('kywi-badge-opt-out', 'Opt out', () => {\n setCookie(COOKIE_NAMES.OPTOUT, '1', 365 * 24 * 3600)\n deleteCookie(COOKIE_NAMES.AUDIENCE)\n renderPersonalizationBadge()\n }))\n }\n\n container.appendChild(badge)\n }\n}\n", "// packages/kywi-js/src/audience/index.ts\nimport type { Audience, VisitorSignals } from '@kywi-software/core/audiences/types'\nimport { evaluateClientSide } from './evaluate.js'\nimport { patchVariantContainers } from './dom-patcher.js'\nimport { renderTransparencyBar } from './transparency.js'\nimport { checkPreviewInit, getPreviewAudienceId, renderPreviewBanner } from './preview.js'\nimport { populateDataLayer, fireKywiReady, readServerMeta } from './data-layer.js'\nimport { readCookies, COOKIE_NAMES } from '../cookies.js'\nimport { runClientAdapters } from './adapter-runner.js'\nimport { Kywi } from '../index.js'\nimport { createSelfIdWidget, type SelfIdWidgetConfig } from './selfid-widget.js'\nimport { renderPersonalizationBadge } from '../personalization/badge.js'\n\nexport interface AudienceBootConfig {\n audiences: Audience[]\n currentPath: string\n pageCategory?: string\n serverSignals?: Partial<VisitorSignals>\n adapters?: Array<{ id: string; side: 'client' | 'server-proxy'; fields: string[]; collect: (s: Partial<VisitorSignals>) => Promise<Record<string, unknown>> }>\n selfIdWidget?: SelfIdWidgetConfig\n /**\n * Base path of the mounted CMS API (e.g. `/api/v1`). Runtime calls\n * (server-proxy adapters, audience assignment) are made under `{apiBase}/kywi/*`.\n * Defaults to the same `{basePath}/api/v1` derivation the entity/feed factories\n * use, so it matches the reference app's mount out of the box.\n */\n apiBase?: string\n}\n\n/** The mounted CMS API base \u2014 mirrors the derivation in Kywi.boot(). */\nfunction resolveApiBase(explicit?: string): string {\n if (explicit) return explicit\n const basePath = Kywi.context?.basePath\n if (!basePath || basePath === '/') return '/api/v1'\n return `${basePath}/api/v1`\n}\n\nexport async function bootAudienceEngine(config: AudienceBootConfig): Promise<void> {\n const { audiences, currentPath, pageCategory, serverSignals } = config\n const apiBase = resolveApiBase(config.apiBase)\n checkPreviewInit()\n const serverMeta = readServerMeta()\n const previewId = getPreviewAudienceId()\n\n if (previewId) {\n patchVariantContainers(previewId)\n renderPreviewBanner(previewId)\n renderPersonalizationBadge()\n populateDataLayer({ visitorId: serverMeta.visitorId, audienceId: previewId, experimentId: null, variantId: null, isPreview: true, isOptedOut: false })\n fireKywiReady()\n return\n }\n\n const cookies = readCookies()\n let merged: Partial<VisitorSignals> = {\n ...serverSignals,\n identity: { visitorId: serverMeta.visitorId || cookies.get(COOKIE_NAMES.VISITOR) || '', isKnown: cookies.has(COOKIE_NAMES.KNOWN), maLeadId: null },\n meta: { isOptedOut: cookies.has(COOKIE_NAMES.OPTOUT), isPreview: false, previewAudienceId: null, resolvedAt: 'server' },\n }\n\n // Run client-side adapters if configured\n if (config.adapters && config.adapters.length > 0) {\n const adapterResults = await runClientAdapters(config.adapters, merged, apiBase)\n merged.adapters = { ...merged.adapters, ...adapterResults }\n }\n\n const result = evaluateClientSide(audiences, merged, currentPath, pageCategory)\n patchVariantContainers(result.winningAudienceId)\n renderTransparencyBar({ isPersonalized: result.winningAudienceId !== null, isOptedOut: result.isOptedOut, hasMatchAvailable: result.allMatchedIds.length > 0 })\n // Render the opt-out badge wherever a personalizationBadge module was placed.\n renderPersonalizationBadge()\n populateDataLayer({ visitorId: result.signals.identity.visitorId, audienceId: result.winningAudienceId, experimentId: serverMeta.experimentId, variantId: serverMeta.variantId, isPreview: false, isOptedOut: result.isOptedOut })\n fireKywiReady()\n\n if (result.winningAudienceId && result.winningAudienceId !== serverMeta.audienceId) {\n fetch(`${apiBase}/kywi/audience`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...(Kywi.context?.csrfToken ? { 'X-CSRF-Token': Kywi.context.csrfToken } : {}) },\n body: JSON.stringify({ audienceId: result.winningAudienceId }),\n }).catch(() => {})\n }\n\n // Self-ID widget \u2014 mount when frequency allows, timed by its trigger.\n if (config.selfIdWidget) {\n const widget = createSelfIdWidget(config.selfIdWidget)\n if (widget.shouldShow()) {\n const doRender = () => {\n const existing = document.getElementById('kywi-selfid-container')\n const container = existing ?? document.createElement('div')\n if (!container.id) {\n container.id = 'kywi-selfid-container'\n document.body.appendChild(container)\n }\n widget.render(container)\n }\n scheduleSelfIdWidget(config.selfIdWidget.trigger, doRender)\n }\n }\n}\n\n/**\n * Show the self-ID widget per its trigger: immediately, after a delay, or once\n * the visitor scrolls past a depth fraction (0-1). `manual` never auto-shows \u2014\n * the host page decides. An absent trigger behaves as immediate.\n */\nfunction scheduleSelfIdWidget(trigger: SelfIdWidgetConfig['trigger'], render: () => void): void {\n if (!trigger || trigger.type === 'immediate') { render(); return }\n if (trigger.type === 'manual') return\n if (trigger.type === 'delay') {\n window.setTimeout(render, Math.max(0, trigger.seconds) * 1000)\n return\n }\n // scroll: fire once when scrolled past `depth` (fraction of scrollable height).\n const target = Math.min(Math.max(trigger.depth, 0), 1)\n let fired = false\n const onScroll = () => {\n if (fired) return\n const scrollable = document.documentElement.scrollHeight - window.innerHeight\n const progress = scrollable > 0 ? window.scrollY / scrollable : 1\n if (progress >= target) {\n fired = true\n window.removeEventListener('scroll', onScroll)\n render()\n }\n }\n window.addEventListener('scroll', onScroll, { passive: true })\n onScroll()\n}\n", "// packages/kywi-js/src/index.ts\nimport type { KywiContext, KywiModuleDefinition } from './types.js'\nimport { readContext } from './context.js'\nimport { createEntityFactory } from './entity.js'\nimport { createFeedFactory } from './feed.js'\nimport { renderFeed } from './render-feed.js'\nimport { initModules } from './module-system.js'\nimport { initFormHooks } from './form-hooks.js'\nimport { bootExperiments } from './experiments/index.js'\n\ntype PreInitCallback = (kywi: typeof Kywi) => void\nconst preInitCallbacks: PreInitCallback[] = []\nlet booted = false\n\nexport const Kywi = {\n version: '0.1.0',\n context: null as unknown as KywiContext,\n Module: {} as Record<string, KywiModuleDefinition>,\n preInit(fn: PreInitCallback): void {\n if (booted) { fn(Kywi) } else { preInitCallbacks.push(fn) }\n },\n UI: {\n extend(definition: KywiModuleDefinition): KywiModuleDefinition {\n return { ...definition }\n },\n },\n DisplayObject: {\n Form: {\n _hooks: {} as Record<string, (...args: unknown[]) => unknown>,\n extend(methods: Record<string, (...args: unknown[]) => unknown>): void {\n Object.assign(Kywi.DisplayObject.Form._hooks, methods)\n },\n },\n },\n getEntity: null as unknown as (type: string) => any,\n getFeed: null as unknown as (type: string) => any,\n renderFeed: null as unknown as (options: any) => void,\n boot(): void {\n if (booted) return\n Kywi.context = readContext()\n for (const fn of preInitCallbacks) { fn(Kywi) }\n const basePath = Kywi.context.basePath === '/' ? '/api/v1' : `${Kywi.context.basePath}/api/v1`\n Kywi.getEntity = createEntityFactory(basePath, Kywi.context.csrfToken)\n Kywi.getFeed = createFeedFactory(basePath, Kywi.context.csrfToken)\n Kywi.renderFeed = renderFeed\n initModules()\n initFormHooks()\n // A/B experiment beacons: confirm exposure of the server-rendered variant\n // and wire conversion signals (pageview / form-submit / kywi.track).\n bootExperiments({ context: Kywi.context })\n booted = true\n },\n}\n\nif (typeof globalThis !== 'undefined') { (globalThis as any).Kywi = Kywi }\nif (typeof document !== 'undefined') {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', () => Kywi.boot())\n } else {\n Kywi.boot()\n }\n}\n\nexport { bootAudienceEngine } from './audience/index.js'\nexport { bootExperiments, type ExperimentRuntime, type ConversionSignal } from './experiments/index.js'\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["isOptedOut", "label", "createButton"]
|
|
7
7
|
}
|
package/dist/kywi.js
CHANGED
|
@@ -711,13 +711,15 @@ var Kywi = (() => {
|
|
|
711
711
|
const containers = document.querySelectorAll(".kywi-variant-container");
|
|
712
712
|
for (const container of Array.from(containers)) {
|
|
713
713
|
const el = container;
|
|
714
|
+
const arms = Array.from(el.querySelectorAll("[data-kywi-variant]"));
|
|
715
|
+
if (arms.length === 0) continue;
|
|
714
716
|
el.classList.remove("kywi-variant-loading");
|
|
715
717
|
el.removeAttribute("aria-busy");
|
|
716
718
|
const skeleton = el.querySelector(".kywi-variant-skeleton");
|
|
717
719
|
if (skeleton) skeleton.remove();
|
|
718
720
|
const target = winningAudienceId ?? "default";
|
|
719
721
|
el.setAttribute("data-variant", target);
|
|
720
|
-
for (const child of
|
|
722
|
+
for (const child of arms) {
|
|
721
723
|
const h = child;
|
|
722
724
|
h.style.display = h.getAttribute("data-kywi-variant") === target ? "" : "none";
|
|
723
725
|
}
|
|
@@ -1043,6 +1045,10 @@ var Kywi = (() => {
|
|
|
1043
1045
|
// src/audience/selfid-widget.ts
|
|
1044
1046
|
var SHOWN_KEY = "kywi_selfid_shown";
|
|
1045
1047
|
var MS_PER_DAY = 864e5;
|
|
1048
|
+
var DISMISSIBLE_MODES = /* @__PURE__ */ new Set(["hello_bar_top", "hello_bar_bottom", "drawer"]);
|
|
1049
|
+
function normalizeOption(opt) {
|
|
1050
|
+
return typeof opt === "string" ? { value: opt, label: opt } : opt;
|
|
1051
|
+
}
|
|
1046
1052
|
function createSelfIdWidget(config) {
|
|
1047
1053
|
const frequency = config.frequency ?? "once";
|
|
1048
1054
|
const displayMode = config.displayMode ?? "inline";
|
|
@@ -1068,7 +1074,20 @@ var Kywi = (() => {
|
|
|
1068
1074
|
}
|
|
1069
1075
|
function render(container) {
|
|
1070
1076
|
container.replaceChildren();
|
|
1071
|
-
|
|
1077
|
+
const displayModeClass = displayMode.replace(/_/g, "-");
|
|
1078
|
+
container.className = `kywi-selfid-widget kywi-selfid-${displayModeClass}`;
|
|
1079
|
+
if (DISMISSIBLE_MODES.has(displayMode)) {
|
|
1080
|
+
const dismissBtn = document.createElement("button");
|
|
1081
|
+
dismissBtn.type = "button";
|
|
1082
|
+
dismissBtn.className = "kywi-selfid-dismiss";
|
|
1083
|
+
dismissBtn.setAttribute("aria-label", "Dismiss");
|
|
1084
|
+
dismissBtn.textContent = "\xD7";
|
|
1085
|
+
dismissBtn.addEventListener("click", () => {
|
|
1086
|
+
markShown();
|
|
1087
|
+
container.replaceChildren();
|
|
1088
|
+
});
|
|
1089
|
+
container.appendChild(dismissBtn);
|
|
1090
|
+
}
|
|
1072
1091
|
if (config.headline) {
|
|
1073
1092
|
const h = document.createElement("h3");
|
|
1074
1093
|
h.className = "kywi-selfid-headline";
|
|
@@ -1102,9 +1121,10 @@ var Kywi = (() => {
|
|
|
1102
1121
|
placeholder.textContent = "";
|
|
1103
1122
|
select.appendChild(placeholder);
|
|
1104
1123
|
for (const opt of field.options) {
|
|
1124
|
+
const { value, label: label2 } = normalizeOption(opt);
|
|
1105
1125
|
const option = document.createElement("option");
|
|
1106
|
-
option.value =
|
|
1107
|
-
option.textContent =
|
|
1126
|
+
option.value = value;
|
|
1127
|
+
option.textContent = label2;
|
|
1108
1128
|
select.appendChild(option);
|
|
1109
1129
|
}
|
|
1110
1130
|
}
|