@sweberdev/witness 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/ai-sdk.cjs.map +1 -1
- package/dist/ai-sdk.js +1 -1
- package/dist/bin.cjs +294 -6
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +3 -2
- package/dist/bin.js.map +1 -1
- package/dist/chunk-F7OWVTCS.js +307 -0
- package/dist/chunk-F7OWVTCS.js.map +1 -0
- package/dist/{chunk-APXU3MTX.js → chunk-GXMGYIOK.js} +3 -1
- package/dist/chunk-GXMGYIOK.js.map +1 -0
- package/dist/{chunk-DHX7SNWE.js → chunk-O6TADCND.js} +10 -3
- package/dist/chunk-O6TADCND.js.map +1 -0
- package/dist/{chunk-UBRK4CTM.js → chunk-PT57EYD7.js} +14 -10
- package/dist/chunk-PT57EYD7.js.map +1 -0
- package/dist/cli.cjs +294 -6
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +3 -2
- package/dist/elements-auto.cjs +9 -2
- package/dist/elements-auto.cjs.map +1 -1
- package/dist/elements-auto.js +1 -1
- package/dist/elements.cjs +9 -2
- package/dist/elements.cjs.map +1 -1
- package/dist/elements.d.cts +1 -1
- package/dist/elements.d.ts +1 -1
- package/dist/elements.js +1 -1
- package/dist/index.cjs +297 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +45 -2
- package/dist/index.d.ts +45 -2
- package/dist/index.js +13 -1
- package/package.json +2 -2
- package/src/cli.ts +9 -7
- package/src/elements.ts +9 -2
- package/src/image.ts +4 -3
- package/src/index.ts +13 -0
- package/src/media.ts +460 -0
- package/dist/chunk-APXU3MTX.js.map +0 -1
- package/dist/chunk-DHX7SNWE.js.map +0 -1
- package/dist/chunk-UBRK4CTM.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/elements-auto.ts","../src/disclosure.ts","../src/i18n.ts","../src/types.ts","../src/elements.ts"],"sourcesContent":["import { defineWitnessElements } from \"./elements.js\";\n\ndefineWitnessElements();\n\nexport { defineWitnessElements, WitnessLabelElement, WitnessNoticeElement } from \"./elements.js\";\n","import type { DisclosureKind } from \"./types.js\";\n\n/** Minimal key-value storage, e.g. `localStorage`. */\nexport interface DisclosureStorage {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n}\n\nexport interface DisclosureEvent {\n type: \"shown\" | \"acknowledged\";\n /** Your id for this disclosure, e.g. \"support-chat\". */\n id: string;\n kind: DisclosureKind;\n /** Bump the version when the wording changes, so people see the new text once. */\n version: string;\n locale: string;\n /** ISO 8601 timestamp. */\n at: string;\n}\n\nexport interface DisclosureOptions {\n /** Your id for this disclosure. Default: the kind. */\n id?: string;\n /** Default `chatbot`. */\n kind?: DisclosureKind;\n /** Default `1`. */\n version?: string;\n /** Locale shown, recorded in events. Default `en`. */\n locale?: string;\n /**\n * Where the acknowledgement is remembered: `local` (default), `session`, `memory` or your\n * own storage. Falls back to memory when browser storage is unavailable.\n */\n storage?: \"local\" | \"session\" | \"memory\" | DisclosureStorage;\n /**\n * Called when the notice is shown or acknowledged. Send these to your log (for example\n * Logarithm) to keep evidence of what people were told and when.\n */\n onEvent?: (event: DisclosureEvent) => void;\n /** Clock for tests. */\n now?: () => Date;\n}\n\nexport interface Disclosure {\n readonly id: string;\n readonly kind: DisclosureKind;\n readonly version: string;\n /** True until this version was acknowledged. */\n needsAcknowledgement(): boolean;\n /** When this version was acknowledged, or `null`. */\n acknowledgedAt(): string | null;\n /** Records that the notice was rendered. Emits a `shown` event once per instance. */\n markShown(): void;\n /** Records the acknowledgement and emits an `acknowledged` event. */\n acknowledge(): void;\n /** Forgets the acknowledgement. */\n reset(): void;\n /** Called whenever the acknowledgement changes. Returns an unsubscribe function. */\n subscribe(listener: () => void): () => void;\n}\n\nconst PREFIX = \"witness:ack:\";\n\n/**\n * Tracks whether a person has seen and acknowledged an AI disclosure.\n *\n * Article 50(5) asks for the information \"at the latest at the time of the first interaction\n * or exposure\". Keep a compact label visible after the acknowledgement: the acknowledgement\n * only collapses the notice, it does not make it disappear.\n */\nexport function createDisclosure(options: DisclosureOptions = {}): Disclosure {\n const kind = options.kind ?? \"chatbot\";\n const id = options.id ?? kind;\n const version = options.version ?? \"1\";\n const locale = options.locale ?? \"en\";\n const now = options.now ?? (() => new Date());\n const storage = resolveStorage(options.storage);\n const key = `${PREFIX}${id}`;\n const listeners = new Set<() => void>();\n let shown = false;\n\n const read = (): { version: string; at: string } | null => {\n try {\n const raw = storage.getItem(key);\n if (!raw) return null;\n const parsed = JSON.parse(raw) as { version?: unknown; at?: unknown };\n if (typeof parsed.version !== \"string\" || typeof parsed.at !== \"string\") return null;\n return { version: parsed.version, at: parsed.at };\n } catch {\n return null;\n }\n };\n\n const emit = (type: DisclosureEvent[\"type\"], at: string) => {\n options.onEvent?.({ type, id, kind, version, locale, at });\n };\n\n const notify = () => {\n for (const listener of listeners) listener();\n };\n\n return {\n id,\n kind,\n version,\n needsAcknowledgement: () => read()?.version !== version,\n acknowledgedAt: () => {\n const entry = read();\n return entry?.version === version ? entry.at : null;\n },\n markShown() {\n if (shown) return;\n shown = true;\n emit(\"shown\", now().toISOString());\n },\n acknowledge() {\n const at = now().toISOString();\n try {\n storage.setItem(key, JSON.stringify({ version, at }));\n } catch {\n // Storage full or blocked: the acknowledgement lasts for this page only.\n }\n emit(\"acknowledged\", at);\n notify();\n },\n reset() {\n try {\n storage.removeItem(key);\n } catch {\n // ignore\n }\n notify();\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n };\n}\n\nfunction resolveStorage(option: DisclosureOptions[\"storage\"]): DisclosureStorage {\n if (option && typeof option === \"object\") return option;\n if (option !== \"memory\") {\n try {\n const candidate = option === \"session\" ? globalThis.sessionStorage : globalThis.localStorage;\n if (candidate) {\n const probe = `${PREFIX}probe`;\n candidate.setItem(probe, \"1\");\n candidate.removeItem(probe);\n return candidate;\n }\n } catch {\n // fall through to memory\n }\n }\n return memoryStorage();\n}\n\n/** In-memory storage, e.g. for server rendering or tests. */\nexport function memoryStorage(): DisclosureStorage {\n const map = new Map<string, string>();\n return {\n getItem: (key) => map.get(key) ?? null,\n setItem: (key, value) => {\n map.set(key, value);\n },\n removeItem: (key) => {\n map.delete(key);\n },\n };\n}\n","import type {\n DisclosureKind,\n DisclosureText,\n LocaleMessages,\n LocaleOverride,\n UiText,\n} from \"./types.js\";\n\nconst en: LocaleMessages = {\n kinds: {\n chatbot: {\n label: \"AI assistant\",\n title: \"You are chatting with an AI\",\n body: \"This assistant is an AI system, not a person. Its answers are generated automatically and can be wrong.\",\n },\n generated: {\n label: \"AI-generated\",\n title: \"AI-generated content\",\n body: \"This content was generated by an AI system.\",\n },\n edited: {\n label: \"AI-edited\",\n title: \"Edited with AI\",\n body: \"This content was edited or altered with an AI system.\",\n },\n deepfake: {\n label: \"Artificially generated\",\n title: \"Artificially generated or manipulated\",\n body: \"This content was generated or manipulated with AI. It may show people, places or events differently from how they really were.\",\n },\n \"emotion-recognition\": {\n label: \"Emotion recognition\",\n title: \"Emotion recognition is active\",\n body: \"This service uses an AI system that recognises emotions or intentions from your data.\",\n },\n \"biometric-categorisation\": {\n label: \"Biometric categorisation\",\n title: \"Biometric categorisation is active\",\n body: \"This service uses an AI system that assigns people to categories based on biometric data.\",\n },\n },\n ui: {\n acknowledge: \"Got it\",\n details: \"About this label\",\n generatedWith: \"Generated with {generator}\",\n createdOn: \"Created on {date}\",\n humanReviewed: \"Reviewed by a person\",\n moreInfo: \"How we use AI\",\n close: \"Close\",\n },\n};\n\nconst de: LocaleMessages = {\n kinds: {\n chatbot: {\n label: \"KI-Assistent\",\n title: \"Sie chatten mit einer KI\",\n body: \"Dieser Assistent ist ein KI-System und kein Mensch. Seine Antworten werden automatisch erzeugt und können falsch sein.\",\n },\n generated: {\n label: \"KI-generiert\",\n title: \"KI-generierter Inhalt\",\n body: \"Dieser Inhalt wurde von einem KI-System erzeugt.\",\n },\n edited: {\n label: \"Mit KI bearbeitet\",\n title: \"Mit KI bearbeitet\",\n body: \"Dieser Inhalt wurde mit einem KI-System bearbeitet oder verändert.\",\n },\n deepfake: {\n label: \"Künstlich erzeugt\",\n title: \"Künstlich erzeugt oder verändert\",\n body: \"Dieser Inhalt wurde mit KI erzeugt oder verändert. Er kann Personen, Orte oder Ereignisse anders zeigen, als sie wirklich waren.\",\n },\n \"emotion-recognition\": {\n label: \"Emotionserkennung\",\n title: \"Emotionserkennung ist aktiv\",\n body: \"Dieser Dienst setzt ein KI-System ein, das aus Ihren Daten Emotionen oder Absichten erkennt.\",\n },\n \"biometric-categorisation\": {\n label: \"Biometrische Kategorisierung\",\n title: \"Biometrische Kategorisierung ist aktiv\",\n body: \"Dieser Dienst setzt ein KI-System ein, das Personen anhand biometrischer Daten Kategorien zuordnet.\",\n },\n },\n ui: {\n acknowledge: \"Verstanden\",\n details: \"Über diese Kennzeichnung\",\n generatedWith: \"Erzeugt mit {generator}\",\n createdOn: \"Erstellt am {date}\",\n humanReviewed: \"Von einem Menschen geprüft\",\n moreInfo: \"Wie wir KI einsetzen\",\n close: \"Schliessen\",\n },\n};\n\nconst fr: LocaleMessages = {\n kinds: {\n chatbot: {\n label: \"Assistant IA\",\n title: \"Vous discutez avec une IA\",\n body: \"Cet assistant est un système d’IA, pas une personne. Ses réponses sont générées automatiquement et peuvent être erronées.\",\n },\n generated: {\n label: \"Généré par IA\",\n title: \"Contenu généré par IA\",\n body: \"Ce contenu a été généré par un système d’IA.\",\n },\n edited: {\n label: \"Modifié par IA\",\n title: \"Modifié avec l’IA\",\n body: \"Ce contenu a été modifié ou altéré à l’aide d’un système d’IA.\",\n },\n deepfake: {\n label: \"Généré artificiellement\",\n title: \"Généré ou manipulé artificiellement\",\n body: \"Ce contenu a été généré ou manipulé avec l’IA. Il peut montrer des personnes, des lieux ou des événements autrement qu’ils n’ont réellement été.\",\n },\n \"emotion-recognition\": {\n label: \"Reconnaissance des émotions\",\n title: \"La reconnaissance des émotions est active\",\n body: \"Ce service utilise un système d’IA qui reconnaît des émotions ou des intentions à partir de vos données.\",\n },\n \"biometric-categorisation\": {\n label: \"Catégorisation biométrique\",\n title: \"La catégorisation biométrique est active\",\n body: \"Ce service utilise un système d’IA qui classe les personnes dans des catégories à partir de données biométriques.\",\n },\n },\n ui: {\n acknowledge: \"Compris\",\n details: \"À propos de ce label\",\n generatedWith: \"Généré avec {generator}\",\n createdOn: \"Créé le {date}\",\n humanReviewed: \"Vérifié par une personne\",\n moreInfo: \"Comment nous utilisons l’IA\",\n close: \"Fermer\",\n },\n};\n\nconst it: LocaleMessages = {\n kinds: {\n chatbot: {\n label: \"Assistente IA\",\n title: \"Stai parlando con un’IA\",\n body: \"Questo assistente è un sistema di IA, non una persona. Le sue risposte sono generate automaticamente e possono essere sbagliate.\",\n },\n generated: {\n label: \"Generato con IA\",\n title: \"Contenuto generato con IA\",\n body: \"Questo contenuto è stato generato da un sistema di IA.\",\n },\n edited: {\n label: \"Modificato con IA\",\n title: \"Modificato con l’IA\",\n body: \"Questo contenuto è stato modificato o alterato con un sistema di IA.\",\n },\n deepfake: {\n label: \"Generato artificialmente\",\n title: \"Generato o manipolato artificialmente\",\n body: \"Questo contenuto è stato generato o manipolato con l’IA. Può mostrare persone, luoghi o eventi in modo diverso da come sono stati realmente.\",\n },\n \"emotion-recognition\": {\n label: \"Riconoscimento delle emozioni\",\n title: \"Il riconoscimento delle emozioni è attivo\",\n body: \"Questo servizio utilizza un sistema di IA che riconosce emozioni o intenzioni a partire dai tuoi dati.\",\n },\n \"biometric-categorisation\": {\n label: \"Categorizzazione biometrica\",\n title: \"La categorizzazione biometrica è attiva\",\n body: \"Questo servizio utilizza un sistema di IA che assegna le persone a categorie in base a dati biometrici.\",\n },\n },\n ui: {\n acknowledge: \"Ho capito\",\n details: \"Informazioni su questa etichetta\",\n generatedWith: \"Generato con {generator}\",\n createdOn: \"Creato il {date}\",\n humanReviewed: \"Verificato da una persona\",\n moreInfo: \"Come usiamo l’IA\",\n close: \"Chiudi\",\n },\n};\n\nconst registry = new Map<string, LocaleMessages>([\n [\"en\", en],\n [\"de\", de],\n [\"fr\", fr],\n [\"it\", it],\n]);\n\n/** The locales bundled with the free package. */\nexport const BUILT_IN_LOCALES = [\"en\", \"de\", \"fr\", \"it\"] as const;\n\n/**\n * Adds or replaces a locale, e.g. one of the 24 EU languages from Witness Pro.\n * A partial override is merged over the existing locale of that code, or over English.\n */\nexport function registerLocale(code: string, messages: LocaleMessages | LocaleOverride): void {\n const key = code.toLowerCase();\n const base = registry.get(key) ?? registry.get(key.split(\"-\")[0] ?? \"\") ?? en;\n registry.set(key, mergeMessages(base, messages));\n}\n\n/** Codes of all registered locales. */\nexport function registeredLocales(): string[] {\n return [...registry.keys()];\n}\n\n/**\n * Picks the best registered locale for a tag such as \"de-CH\" or a list of tags such as\n * `navigator.languages`. Falls back to English.\n */\nexport function resolveLocale(input?: string | readonly string[] | null): string {\n const tags = input == null ? [] : typeof input === \"string\" ? [input] : input;\n for (const tag of tags) {\n const lower = tag.toLowerCase();\n if (registry.has(lower)) return lower;\n const language = lower.split(\"-\")[0] ?? \"\";\n if (registry.has(language)) return language;\n }\n return \"en\";\n}\n\n/** All messages of a locale, with an optional override merged in. */\nexport function getMessages(\n locale?: string | readonly string[] | null,\n override?: LocaleOverride,\n): LocaleMessages {\n const messages = registry.get(resolveLocale(locale)) ?? en;\n return override ? mergeMessages(messages, override) : messages;\n}\n\n/** Wording for one disclosure kind. */\nexport function disclosureText(\n kind: DisclosureKind,\n locale?: string | readonly string[] | null,\n override?: LocaleOverride,\n): DisclosureText {\n return getMessages(locale, override).kinds[kind];\n}\n\n/** Replaces `{name}` placeholders. Unknown placeholders stay as they are. */\nexport function format(template: string, values: Record<string, string | undefined>): string {\n return template.replace(/\\{(\\w+)\\}/g, (match, name: string) => values[name] ?? match);\n}\n\nfunction mergeMessages(\n base: LocaleMessages,\n override: LocaleMessages | LocaleOverride,\n): LocaleMessages {\n const kinds = { ...base.kinds };\n for (const [kind, text] of Object.entries(override.kinds ?? {})) {\n const key = kind as DisclosureKind;\n kinds[key] = { ...base.kinds[key], ...(text as Partial<DisclosureText>) };\n }\n const ui: UiText = { ...base.ui, ...(override.ui ?? {}) };\n return { kinds, ui };\n}\n","/**\n * The transparency situations Article 50 of the EU AI Act describes.\n *\n * - `chatbot`: a person interacts directly with an AI system (Art. 50(1)).\n * - `generated`: image, audio, video or text produced by an AI system (Art. 50(2) and 50(4)).\n * - `edited`: existing content altered with an AI system (Art. 50(2) and 50(4)).\n * - `deepfake`: generated or manipulated content that resembles real people, objects,\n * places or events and could falsely appear authentic (Art. 50(4)).\n * - `emotion-recognition` and `biometric-categorisation`: people are exposed to such a\n * system (Art. 50(3)).\n */\nexport type DisclosureKind =\n | \"chatbot\"\n | \"generated\"\n | \"edited\"\n | \"deepfake\"\n | \"emotion-recognition\"\n | \"biometric-categorisation\";\n\nexport const DISCLOSURE_KINDS: readonly DisclosureKind[] = [\n \"chatbot\",\n \"generated\",\n \"edited\",\n \"deepfake\",\n \"emotion-recognition\",\n \"biometric-categorisation\",\n];\n\n/** The kinds that describe a piece of content and can be written into a marking. */\nexport type ContentKind = \"generated\" | \"edited\" | \"deepfake\";\n\n/**\n * IPTC Digital Source Type values relevant to AI. See\n * https://cv.iptc.org/newscodes/digitalsourcetype/\n */\nexport type SourceType =\n | \"trainedAlgorithmicMedia\"\n | \"compositeWithTrainedAlgorithmicMedia\"\n | \"algorithmicallyEnhanced\"\n | \"algorithmicMedia\"\n | \"compositeSynthetic\";\n\n/** Wording for one disclosure kind in one language. */\nexport interface DisclosureText {\n /** Two or three words for a badge, e.g. \"AI-generated\". */\n label: string;\n /** One line for the heading of a notice. */\n title: string;\n /** One or two plain sentences that explain the label. */\n body: string;\n}\n\n/** Interface strings shared by the notice and label components. */\nexport interface UiText {\n /** Button that collapses the chatbot notice. */\n acknowledge: string;\n /** Accessible name of the button that opens label details. */\n details: string;\n /** \"Generated with {generator}\". `{generator}` is replaced. */\n generatedWith: string;\n /** \"Created on {date}\". `{date}` is replaced. */\n createdOn: string;\n /** Shown when a person reviewed the content and took editorial responsibility. */\n humanReviewed: string;\n /** Link text to a page with more information. */\n moreInfo: string;\n /** Closes the details popover. */\n close: string;\n}\n\nexport interface LocaleMessages {\n kinds: Record<DisclosureKind, DisclosureText>;\n ui: UiText;\n}\n\n/** A partial override of a locale, e.g. to switch German to the informal \"du\". */\nexport interface LocaleOverride {\n kinds?: Partial<Record<DisclosureKind, Partial<DisclosureText>>>;\n ui?: Partial<UiText>;\n}\n\n/** What a marking says about a piece of content. Input for {@link createMarking}. */\nexport interface MarkingInput {\n /** Defaults to `generated`. */\n kind?: ContentKind;\n /** Defaults from `kind`: `trainedAlgorithmicMedia`, or the composite type for `edited`. */\n sourceType?: SourceType;\n /** Name of the AI system or model, e.g. \"gpt-image-2\" or \"Claude\". */\n generator?: string;\n /** Version of the AI system, if known. */\n generatorVersion?: string;\n /** Who provides or operates the AI system, e.g. your company. */\n provider?: string;\n /** ISO 8601 timestamp. Defaults to now. */\n createdAt?: string | Date;\n /** A page that explains how and why you use AI. */\n disclosureUrl?: string;\n /** A person reviewed the content and holds editorial responsibility (Art. 50(4), text). */\n humanReviewed?: boolean;\n /** Free text, e.g. \"Image generated from the prompt by the newsroom\". */\n description?: string;\n}\n\n/** A normalised marking with all defaults applied. */\nexport interface Marking {\n kind: ContentKind;\n sourceType: SourceType;\n generator?: string;\n generatorVersion?: string;\n provider?: string;\n createdAt: string;\n disclosureUrl?: string;\n humanReviewed: boolean;\n description?: string;\n}\n","/**\n * Framework-free custom elements:\n *\n * - `<witness-notice>`: the chatbot notice (Art. 50(1)). Expanded until acknowledged, then a\n * compact label that can be reopened.\n * - `<witness-label>`: a badge for AI-generated or AI-edited content with a details popover.\n *\n * Import `@sweberdev/witness/elements` to register both, or call `defineWitnessElements()`.\n */\n\nimport { createDisclosure, type Disclosure, type DisclosureEvent } from \"./disclosure.js\";\nimport { format, getMessages } from \"./i18n.js\";\nimport { DISCLOSURE_KINDS, type DisclosureKind } from \"./types.js\";\n\nconst BaseElement: typeof HTMLElement =\n typeof HTMLElement === \"undefined\" ? (class {} as unknown as typeof HTMLElement) : HTMLElement;\n\nconst SHARED_CSS = `\n:host { --witness-accent: #003399; --witness-accent-text: #ffffff; --witness-bg: #ffffff;\n --witness-fg: #1a1a1a; --witness-muted: #555b66; --witness-border: #d7dbe3; --witness-radius: 8px;\n font: inherit; color: var(--witness-fg); }\n@media (prefers-color-scheme: dark) {\n :host { --witness-accent: #8fb0ff; --witness-accent-text: #0b1530; --witness-bg: #15181f;\n --witness-fg: #eef1f6; --witness-muted: #a9b0bd; --witness-border: #2c323d; }\n}\n.icon { display: inline-flex; align-items: center; justify-content: center; min-width: 1.75em;\n height: 1.5em; padding: 0 .3em; border-radius: 4px; background: var(--witness-accent);\n color: var(--witness-accent-text); font-weight: 700; font-size: .75em; letter-spacing: .02em;\n line-height: 1; flex: none; }\nbutton { font: inherit; cursor: pointer; }\nbutton:focus-visible, a:focus-visible { outline: 2px solid var(--witness-accent); outline-offset: 2px; }\na { color: inherit; }\n.muted { color: var(--witness-muted); }\n`;\n\nconst NOTICE_CSS = `${SHARED_CSS}\n:host { display: block; }\n.notice { display: flex; gap: .75em; align-items: flex-start; padding: .875em 1em;\n border: 1px solid var(--witness-border); border-left: 4px solid var(--witness-accent);\n border-radius: var(--witness-radius); background: var(--witness-bg); }\n.notice h2 { font-size: 1em; margin: 0 0 .25em; }\n.notice p { margin: 0 0 .75em; line-height: 1.45; }\n.actions { display: flex; gap: .75em; align-items: center; flex-wrap: wrap; }\n.ack { padding: .4em .9em; border-radius: 6px; border: 0; background: var(--witness-accent);\n color: var(--witness-accent-text); font-weight: 600; }\n.compact { display: inline-flex; gap: .5em; align-items: center; padding: .25em .5em;\n border: 1px solid var(--witness-border); border-radius: 999px; background: var(--witness-bg);\n color: var(--witness-fg); font-size: .875em; }\n`;\n\nconst LABEL_CSS = `${SHARED_CSS}\n:host { display: inline-block; position: relative; font-size: .875em; }\n:host([variant=\"overlay\"]) { position: absolute; inset-block-start: .5em; inset-inline-end: .5em; z-index: 1; }\n.badge { display: inline-flex; gap: .4em; align-items: center; padding: .2em .55em .2em .25em;\n border: 1px solid var(--witness-border); border-radius: 999px; background: var(--witness-bg);\n color: var(--witness-fg); }\n.panel { position: absolute; inset-block-start: calc(100% + .4em); inset-inline-end: 0; z-index: 10;\n width: max-content; max-width: min(22em, 80vw); padding: .75em .875em; text-align: start;\n border: 1px solid var(--witness-border); border-radius: var(--witness-radius);\n background: var(--witness-bg); box-shadow: 0 6px 24px rgb(0 0 0 / .15); line-height: 1.45; }\n:host([variant=\"inline\"]) .panel, :host(:not([variant])) .panel { inset-inline-end: auto; inset-inline-start: 0; }\n.panel strong { display: block; margin-bottom: .25em; }\n.panel p { margin: 0 0 .4em; }\n.panel ul { margin: .4em 0; padding-inline-start: 1.1em; }\n.close { position: absolute; inset-block-start: .35em; inset-inline-end: .35em; border: 0;\n background: none; color: var(--witness-muted); font-size: 1.1em; line-height: 1; padding: .2em .35em; }\n[hidden] { display: none !important; }\n`;\n\nfunction locale(el: HTMLElement): string[] {\n const own = el.getAttribute(\"locale\") ?? el.closest(\"[lang]\")?.getAttribute(\"lang\");\n if (own) return [own];\n return typeof navigator !== \"undefined\" ? [...navigator.languages] : [];\n}\n\nfunction kindOf(el: HTMLElement, fallback: DisclosureKind): DisclosureKind {\n const value = el.getAttribute(\"kind\") as DisclosureKind | null;\n return value && DISCLOSURE_KINDS.includes(value) ? value : fallback;\n}\n\nfunction h<K extends keyof HTMLElementTagNameMap>(\n doc: Document,\n tag: K,\n attrs: Record<string, string> = {},\n ...children: Array<Node | string | null>\n): HTMLElementTagNameMap[K] {\n const el = doc.createElement(tag);\n for (const [name, value] of Object.entries(attrs)) el.setAttribute(name, value);\n for (const child of children) {\n if (child !== null) el.append(child);\n }\n return el;\n}\n\nfunction icon(doc: Document): HTMLElement {\n return h(doc, \"span\", { class: \"icon\", \"aria-hidden\": \"true\", part: \"icon\" }, \"AI\");\n}\n\n/** `<witness-notice kind=\"chatbot\" locale=\"de\" disclosure-id=\"support\" version=\"2\" href=\"/ki\">` */\nexport class WitnessNoticeElement extends BaseElement {\n static observedAttributes = [\"kind\", \"locale\", \"disclosure-id\", \"version\", \"href\", \"storage\"];\n\n #disclosure: Disclosure | null = null;\n #unsubscribe: (() => void) | null = null;\n #expanded = false;\n\n connectedCallback(): void {\n if (!this.shadowRoot) this.attachShadow({ mode: \"open\" });\n this.#setup();\n }\n\n disconnectedCallback(): void {\n this.#unsubscribe?.();\n this.#unsubscribe = null;\n }\n\n attributeChangedCallback(): void {\n if (this.isConnected && this.shadowRoot) this.#setup();\n }\n\n /** Forgets the acknowledgement and shows the full notice again. */\n reset(): void {\n this.#disclosure?.reset();\n }\n\n get disclosure(): Disclosure | null {\n return this.#disclosure;\n }\n\n #setup(): void {\n this.#unsubscribe?.();\n const storage = this.getAttribute(\"storage\");\n const kind = kindOf(this, \"chatbot\");\n const tags = locale(this);\n this.#disclosure = createDisclosure({\n kind,\n id: this.getAttribute(\"disclosure-id\") ?? kind,\n version: this.getAttribute(\"version\") ?? \"1\",\n locale: getLocaleCode(tags),\n ...(storage === \"session\" || storage === \"memory\" || storage === \"local\" ? { storage } : {}),\n onEvent: (event) => this.#dispatch(event),\n });\n this.#expanded = false;\n this.#unsubscribe = this.#disclosure.subscribe(() => {\n this.#expanded = false;\n this.#render();\n });\n this.#render();\n }\n\n #dispatch(event: DisclosureEvent): void {\n this.dispatchEvent(\n new CustomEvent(`witness-${event.type}`, { detail: event, bubbles: true, composed: true }),\n );\n }\n\n #render(): void {\n const root = this.shadowRoot;\n const disclosure = this.#disclosure;\n if (!root || !disclosure) return;\n const doc = this.ownerDocument;\n const messages = getMessages(locale(this));\n const text = messages.kinds[disclosure.kind];\n const href = this.getAttribute(\"href\");\n const full = this.#expanded || disclosure.needsAcknowledgement();\n\n const style = h(doc, \"style\", {}, NOTICE_CSS);\n if (full) {\n const ack = h(\n doc,\n \"button\",\n { type: \"button\", class: \"ack\", part: \"button\" },\n messages.ui.acknowledge,\n );\n ack.addEventListener(\"click\", () => disclosure.acknowledge());\n const link = href ? h(doc, \"a\", { href, part: \"link\" }, messages.ui.moreInfo) : null;\n const box = h(\n doc,\n \"section\",\n { class: \"notice\", role: \"note\", \"aria-labelledby\": \"title\", part: \"notice\" },\n icon(doc),\n h(\n doc,\n \"div\",\n {},\n h(doc, \"h2\", { id: \"title\", part: \"title\" }, text.title),\n h(doc, \"p\", { part: \"body\" }, h(doc, \"slot\", {}, text.body)),\n h(doc, \"div\", { class: \"actions\" }, ack, link),\n ),\n );\n root.replaceChildren(style, box);\n disclosure.markShown();\n } else {\n const reopen = h(\n doc,\n \"button\",\n {\n type: \"button\",\n class: \"compact\",\n \"aria-label\": `${text.label}: ${messages.ui.details}`,\n part: \"compact\",\n },\n icon(doc),\n text.label,\n );\n reopen.addEventListener(\"click\", () => {\n this.#expanded = true;\n this.#render();\n });\n root.replaceChildren(style, reopen);\n }\n }\n}\n\n/** `<witness-label kind=\"generated\" generator=\"Claude\" created=\"2026-10-05\" reviewed href=\"/ki\">` */\nexport class WitnessLabelElement extends BaseElement {\n static observedAttributes = [\n \"kind\",\n \"locale\",\n \"generator\",\n \"generator-version\",\n \"created\",\n \"reviewed\",\n \"href\",\n \"variant\",\n ];\n\n #open = false;\n #onKey = (event: KeyboardEvent) => {\n if (event.key === \"Escape\" && this.#open) {\n this.#toggle(false);\n this.shadowRoot?.querySelector<HTMLButtonElement>(\".badge\")?.focus();\n }\n };\n #onOutside = (event: Event) => {\n if (this.#open && !event.composedPath().includes(this)) this.#toggle(false);\n };\n\n connectedCallback(): void {\n if (!this.shadowRoot) this.attachShadow({ mode: \"open\" });\n this.ownerDocument.addEventListener(\"keydown\", this.#onKey);\n this.ownerDocument.addEventListener(\"click\", this.#onOutside);\n this.#render();\n }\n\n disconnectedCallback(): void {\n this.ownerDocument.removeEventListener(\"keydown\", this.#onKey);\n this.ownerDocument.removeEventListener(\"click\", this.#onOutside);\n }\n\n attributeChangedCallback(): void {\n if (this.isConnected && this.shadowRoot) this.#render();\n }\n\n #toggle(open: boolean): void {\n this.#open = open;\n this.#render();\n }\n\n #render(): void {\n const root = this.shadowRoot;\n if (!root) return;\n const doc = this.ownerDocument;\n const tags = locale(this);\n const messages = getMessages(tags);\n const kind = kindOf(this, \"generated\");\n const text = messages.kinds[kind];\n const generator = [this.getAttribute(\"generator\"), this.getAttribute(\"generator-version\")]\n .filter(Boolean)\n .join(\" \");\n const created = this.getAttribute(\"created\");\n const href = this.getAttribute(\"href\");\n\n const badge = h(\n doc,\n \"button\",\n {\n type: \"button\",\n class: \"badge\",\n part: \"badge\",\n \"aria-expanded\": String(this.#open),\n \"aria-controls\": \"panel\",\n title: messages.ui.details,\n },\n icon(doc),\n h(doc, \"span\", { part: \"label\" }, text.label),\n );\n badge.addEventListener(\"click\", () => this.#toggle(!this.#open));\n\n const facts = h(doc, \"ul\", {});\n if (generator) facts.append(h(doc, \"li\", {}, format(messages.ui.generatedWith, { generator })));\n if (created) {\n facts.append(\n h(doc, \"li\", {}, format(messages.ui.createdOn, { date: formatDate(created, tags) })),\n );\n }\n if (this.hasAttribute(\"reviewed\")) facts.append(h(doc, \"li\", {}, messages.ui.humanReviewed));\n\n const close = h(\n doc,\n \"button\",\n { type: \"button\", class: \"close\", \"aria-label\": messages.ui.close },\n \"×\",\n );\n close.addEventListener(\"click\", () => this.#toggle(false));\n\n const panel = h(\n doc,\n \"div\",\n { id: \"panel\", class: \"panel\", role: \"dialog\", \"aria-label\": text.title, part: \"panel\" },\n close,\n h(doc, \"strong\", {}, text.title),\n h(doc, \"p\", {}, text.body),\n facts.childElementCount > 0 ? facts : null,\n href ? h(doc, \"a\", { href, part: \"link\" }, messages.ui.moreInfo) : null,\n );\n if (!this.#open) panel.hidden = true;\n root.replaceChildren(h(doc, \"style\", {}, LABEL_CSS), badge, panel);\n }\n}\n\nfunction formatDate(value: string, tags: string[]): string {\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return value;\n try {\n return new Intl.DateTimeFormat(tags.length > 0 ? tags : undefined, {\n dateStyle: \"medium\",\n }).format(date);\n } catch {\n return value;\n }\n}\n\nfunction getLocaleCode(tags: string[]): string {\n return tags[0] ?? \"en\";\n}\n\n/** Registers `<witness-notice>` and `<witness-label>` once. Safe to call during SSR. */\nexport function defineWitnessElements(): void {\n if (typeof customElements === \"undefined\") return;\n if (!customElements.get(\"witness-notice\"))\n customElements.define(\"witness-notice\", WitnessNoticeElement);\n if (!customElements.get(\"witness-label\"))\n customElements.define(\"witness-label\", WitnessLabelElement);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"witness-notice\": WitnessNoticeElement;\n \"witness-label\": WitnessLabelElement;\n }\n interface HTMLElementEventMap {\n \"witness-shown\": CustomEvent<DisclosureEvent>;\n \"witness-acknowledged\": CustomEvent<DisclosureEvent>;\n }\n}\n"],"mappings":"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","names":["locale","locale"]}
|
|
1
|
+
{"version":3,"sources":["../src/elements-auto.ts","../src/disclosure.ts","../src/i18n.ts","../src/types.ts","../src/elements.ts"],"sourcesContent":["import { defineWitnessElements } from \"./elements.js\";\n\ndefineWitnessElements();\n\nexport { defineWitnessElements, WitnessLabelElement, WitnessNoticeElement } from \"./elements.js\";\n","import type { DisclosureKind } from \"./types.js\";\n\n/** Minimal key-value storage, e.g. `localStorage`. */\nexport interface DisclosureStorage {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n}\n\nexport interface DisclosureEvent {\n type: \"shown\" | \"acknowledged\";\n /** Your id for this disclosure, e.g. \"support-chat\". */\n id: string;\n kind: DisclosureKind;\n /** Bump the version when the wording changes, so people see the new text once. */\n version: string;\n locale: string;\n /** ISO 8601 timestamp. */\n at: string;\n}\n\nexport interface DisclosureOptions {\n /** Your id for this disclosure. Default: the kind. */\n id?: string;\n /** Default `chatbot`. */\n kind?: DisclosureKind;\n /** Default `1`. */\n version?: string;\n /** Locale shown, recorded in events. Default `en`. */\n locale?: string;\n /**\n * Where the acknowledgement is remembered: `local` (default), `session`, `memory` or your\n * own storage. Falls back to memory when browser storage is unavailable.\n */\n storage?: \"local\" | \"session\" | \"memory\" | DisclosureStorage;\n /**\n * Called when the notice is shown or acknowledged. Send these to your log (for example\n * Logarithm) to keep evidence of what people were told and when.\n */\n onEvent?: (event: DisclosureEvent) => void;\n /** Clock for tests. */\n now?: () => Date;\n}\n\nexport interface Disclosure {\n readonly id: string;\n readonly kind: DisclosureKind;\n readonly version: string;\n /** True until this version was acknowledged. */\n needsAcknowledgement(): boolean;\n /** When this version was acknowledged, or `null`. */\n acknowledgedAt(): string | null;\n /** Records that the notice was rendered. Emits a `shown` event once per instance. */\n markShown(): void;\n /** Records the acknowledgement and emits an `acknowledged` event. */\n acknowledge(): void;\n /** Forgets the acknowledgement. */\n reset(): void;\n /** Called whenever the acknowledgement changes. Returns an unsubscribe function. */\n subscribe(listener: () => void): () => void;\n}\n\nconst PREFIX = \"witness:ack:\";\n\n/**\n * Tracks whether a person has seen and acknowledged an AI disclosure.\n *\n * Article 50(5) asks for the information \"at the latest at the time of the first interaction\n * or exposure\". Keep a compact label visible after the acknowledgement: the acknowledgement\n * only collapses the notice, it does not make it disappear.\n */\nexport function createDisclosure(options: DisclosureOptions = {}): Disclosure {\n const kind = options.kind ?? \"chatbot\";\n const id = options.id ?? kind;\n const version = options.version ?? \"1\";\n const locale = options.locale ?? \"en\";\n const now = options.now ?? (() => new Date());\n const storage = resolveStorage(options.storage);\n const key = `${PREFIX}${id}`;\n const listeners = new Set<() => void>();\n let shown = false;\n\n const read = (): { version: string; at: string } | null => {\n try {\n const raw = storage.getItem(key);\n if (!raw) return null;\n const parsed = JSON.parse(raw) as { version?: unknown; at?: unknown };\n if (typeof parsed.version !== \"string\" || typeof parsed.at !== \"string\") return null;\n return { version: parsed.version, at: parsed.at };\n } catch {\n return null;\n }\n };\n\n const emit = (type: DisclosureEvent[\"type\"], at: string) => {\n options.onEvent?.({ type, id, kind, version, locale, at });\n };\n\n const notify = () => {\n for (const listener of listeners) listener();\n };\n\n return {\n id,\n kind,\n version,\n needsAcknowledgement: () => read()?.version !== version,\n acknowledgedAt: () => {\n const entry = read();\n return entry?.version === version ? entry.at : null;\n },\n markShown() {\n if (shown) return;\n shown = true;\n emit(\"shown\", now().toISOString());\n },\n acknowledge() {\n const at = now().toISOString();\n try {\n storage.setItem(key, JSON.stringify({ version, at }));\n } catch {\n // Storage full or blocked: the acknowledgement lasts for this page only.\n }\n emit(\"acknowledged\", at);\n notify();\n },\n reset() {\n try {\n storage.removeItem(key);\n } catch {\n // ignore\n }\n notify();\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n };\n}\n\nfunction resolveStorage(option: DisclosureOptions[\"storage\"]): DisclosureStorage {\n if (option && typeof option === \"object\") return option;\n if (option !== \"memory\") {\n try {\n const candidate = option === \"session\" ? globalThis.sessionStorage : globalThis.localStorage;\n if (candidate) {\n const probe = `${PREFIX}probe`;\n candidate.setItem(probe, \"1\");\n candidate.removeItem(probe);\n return candidate;\n }\n } catch {\n // fall through to memory\n }\n }\n return memoryStorage();\n}\n\n/** In-memory storage, e.g. for server rendering or tests. */\nexport function memoryStorage(): DisclosureStorage {\n const map = new Map<string, string>();\n return {\n getItem: (key) => map.get(key) ?? null,\n setItem: (key, value) => {\n map.set(key, value);\n },\n removeItem: (key) => {\n map.delete(key);\n },\n };\n}\n","import type {\n DisclosureKind,\n DisclosureText,\n LocaleMessages,\n LocaleOverride,\n UiText,\n} from \"./types.js\";\n\nconst en: LocaleMessages = {\n kinds: {\n chatbot: {\n label: \"AI assistant\",\n title: \"You are chatting with an AI\",\n body: \"This assistant is an AI system, not a person. Its answers are generated automatically and can be wrong.\",\n },\n generated: {\n label: \"AI-generated\",\n title: \"AI-generated content\",\n body: \"This content was generated by an AI system.\",\n },\n edited: {\n label: \"AI-edited\",\n title: \"Edited with AI\",\n body: \"This content was edited or altered with an AI system.\",\n },\n deepfake: {\n label: \"Artificially generated\",\n title: \"Artificially generated or manipulated\",\n body: \"This content was generated or manipulated with AI. It may show people, places or events differently from how they really were.\",\n },\n \"emotion-recognition\": {\n label: \"Emotion recognition\",\n title: \"Emotion recognition is active\",\n body: \"This service uses an AI system that recognises emotions or intentions from your data.\",\n },\n \"biometric-categorisation\": {\n label: \"Biometric categorisation\",\n title: \"Biometric categorisation is active\",\n body: \"This service uses an AI system that assigns people to categories based on biometric data.\",\n },\n },\n ui: {\n acknowledge: \"Got it\",\n details: \"About this label\",\n generatedWith: \"Generated with {generator}\",\n createdOn: \"Created on {date}\",\n humanReviewed: \"Reviewed by a person\",\n moreInfo: \"How we use AI\",\n close: \"Close\",\n },\n};\n\nconst de: LocaleMessages = {\n kinds: {\n chatbot: {\n label: \"KI-Assistent\",\n title: \"Sie chatten mit einer KI\",\n body: \"Dieser Assistent ist ein KI-System und kein Mensch. Seine Antworten werden automatisch erzeugt und können falsch sein.\",\n },\n generated: {\n label: \"KI-generiert\",\n title: \"KI-generierter Inhalt\",\n body: \"Dieser Inhalt wurde von einem KI-System erzeugt.\",\n },\n edited: {\n label: \"Mit KI bearbeitet\",\n title: \"Mit KI bearbeitet\",\n body: \"Dieser Inhalt wurde mit einem KI-System bearbeitet oder verändert.\",\n },\n deepfake: {\n label: \"Künstlich erzeugt\",\n title: \"Künstlich erzeugt oder verändert\",\n body: \"Dieser Inhalt wurde mit KI erzeugt oder verändert. Er kann Personen, Orte oder Ereignisse anders zeigen, als sie wirklich waren.\",\n },\n \"emotion-recognition\": {\n label: \"Emotionserkennung\",\n title: \"Emotionserkennung ist aktiv\",\n body: \"Dieser Dienst setzt ein KI-System ein, das aus Ihren Daten Emotionen oder Absichten erkennt.\",\n },\n \"biometric-categorisation\": {\n label: \"Biometrische Kategorisierung\",\n title: \"Biometrische Kategorisierung ist aktiv\",\n body: \"Dieser Dienst setzt ein KI-System ein, das Personen anhand biometrischer Daten Kategorien zuordnet.\",\n },\n },\n ui: {\n acknowledge: \"Verstanden\",\n details: \"Über diese Kennzeichnung\",\n generatedWith: \"Erzeugt mit {generator}\",\n createdOn: \"Erstellt am {date}\",\n humanReviewed: \"Von einem Menschen geprüft\",\n moreInfo: \"Wie wir KI einsetzen\",\n close: \"Schliessen\",\n },\n};\n\nconst fr: LocaleMessages = {\n kinds: {\n chatbot: {\n label: \"Assistant IA\",\n title: \"Vous discutez avec une IA\",\n body: \"Cet assistant est un système d’IA, pas une personne. Ses réponses sont générées automatiquement et peuvent être erronées.\",\n },\n generated: {\n label: \"Généré par IA\",\n title: \"Contenu généré par IA\",\n body: \"Ce contenu a été généré par un système d’IA.\",\n },\n edited: {\n label: \"Modifié par IA\",\n title: \"Modifié avec l’IA\",\n body: \"Ce contenu a été modifié ou altéré à l’aide d’un système d’IA.\",\n },\n deepfake: {\n label: \"Généré artificiellement\",\n title: \"Généré ou manipulé artificiellement\",\n body: \"Ce contenu a été généré ou manipulé avec l’IA. Il peut montrer des personnes, des lieux ou des événements autrement qu’ils n’ont réellement été.\",\n },\n \"emotion-recognition\": {\n label: \"Reconnaissance des émotions\",\n title: \"La reconnaissance des émotions est active\",\n body: \"Ce service utilise un système d’IA qui reconnaît des émotions ou des intentions à partir de vos données.\",\n },\n \"biometric-categorisation\": {\n label: \"Catégorisation biométrique\",\n title: \"La catégorisation biométrique est active\",\n body: \"Ce service utilise un système d’IA qui classe les personnes dans des catégories à partir de données biométriques.\",\n },\n },\n ui: {\n acknowledge: \"Compris\",\n details: \"À propos de ce label\",\n generatedWith: \"Généré avec {generator}\",\n createdOn: \"Créé le {date}\",\n humanReviewed: \"Vérifié par une personne\",\n moreInfo: \"Comment nous utilisons l’IA\",\n close: \"Fermer\",\n },\n};\n\nconst it: LocaleMessages = {\n kinds: {\n chatbot: {\n label: \"Assistente IA\",\n title: \"Stai parlando con un’IA\",\n body: \"Questo assistente è un sistema di IA, non una persona. Le sue risposte sono generate automaticamente e possono essere sbagliate.\",\n },\n generated: {\n label: \"Generato con IA\",\n title: \"Contenuto generato con IA\",\n body: \"Questo contenuto è stato generato da un sistema di IA.\",\n },\n edited: {\n label: \"Modificato con IA\",\n title: \"Modificato con l’IA\",\n body: \"Questo contenuto è stato modificato o alterato con un sistema di IA.\",\n },\n deepfake: {\n label: \"Generato artificialmente\",\n title: \"Generato o manipolato artificialmente\",\n body: \"Questo contenuto è stato generato o manipolato con l’IA. Può mostrare persone, luoghi o eventi in modo diverso da come sono stati realmente.\",\n },\n \"emotion-recognition\": {\n label: \"Riconoscimento delle emozioni\",\n title: \"Il riconoscimento delle emozioni è attivo\",\n body: \"Questo servizio utilizza un sistema di IA che riconosce emozioni o intenzioni a partire dai tuoi dati.\",\n },\n \"biometric-categorisation\": {\n label: \"Categorizzazione biometrica\",\n title: \"La categorizzazione biometrica è attiva\",\n body: \"Questo servizio utilizza un sistema di IA che assegna le persone a categorie in base a dati biometrici.\",\n },\n },\n ui: {\n acknowledge: \"Ho capito\",\n details: \"Informazioni su questa etichetta\",\n generatedWith: \"Generato con {generator}\",\n createdOn: \"Creato il {date}\",\n humanReviewed: \"Verificato da una persona\",\n moreInfo: \"Come usiamo l’IA\",\n close: \"Chiudi\",\n },\n};\n\nconst registry = new Map<string, LocaleMessages>([\n [\"en\", en],\n [\"de\", de],\n [\"fr\", fr],\n [\"it\", it],\n]);\n\n/** The locales bundled with the free package. */\nexport const BUILT_IN_LOCALES = [\"en\", \"de\", \"fr\", \"it\"] as const;\n\n/**\n * Adds or replaces a locale, e.g. one of the 24 EU languages from Witness Pro.\n * A partial override is merged over the existing locale of that code, or over English.\n */\nexport function registerLocale(code: string, messages: LocaleMessages | LocaleOverride): void {\n const key = code.toLowerCase();\n const base = registry.get(key) ?? registry.get(key.split(\"-\")[0] ?? \"\") ?? en;\n registry.set(key, mergeMessages(base, messages));\n}\n\n/** Codes of all registered locales. */\nexport function registeredLocales(): string[] {\n return [...registry.keys()];\n}\n\n/**\n * Picks the best registered locale for a tag such as \"de-CH\" or a list of tags such as\n * `navigator.languages`. Falls back to English.\n */\nexport function resolveLocale(input?: string | readonly string[] | null): string {\n const tags = input == null ? [] : typeof input === \"string\" ? [input] : input;\n for (const tag of tags) {\n const lower = tag.toLowerCase();\n if (registry.has(lower)) return lower;\n const language = lower.split(\"-\")[0] ?? \"\";\n if (registry.has(language)) return language;\n }\n return \"en\";\n}\n\n/** All messages of a locale, with an optional override merged in. */\nexport function getMessages(\n locale?: string | readonly string[] | null,\n override?: LocaleOverride,\n): LocaleMessages {\n const messages = registry.get(resolveLocale(locale)) ?? en;\n return override ? mergeMessages(messages, override) : messages;\n}\n\n/** Wording for one disclosure kind. */\nexport function disclosureText(\n kind: DisclosureKind,\n locale?: string | readonly string[] | null,\n override?: LocaleOverride,\n): DisclosureText {\n return getMessages(locale, override).kinds[kind];\n}\n\n/** Replaces `{name}` placeholders. Unknown placeholders stay as they are. */\nexport function format(template: string, values: Record<string, string | undefined>): string {\n return template.replace(/\\{(\\w+)\\}/g, (match, name: string) => values[name] ?? match);\n}\n\nfunction mergeMessages(\n base: LocaleMessages,\n override: LocaleMessages | LocaleOverride,\n): LocaleMessages {\n const kinds = { ...base.kinds };\n for (const [kind, text] of Object.entries(override.kinds ?? {})) {\n const key = kind as DisclosureKind;\n kinds[key] = { ...base.kinds[key], ...(text as Partial<DisclosureText>) };\n }\n const ui: UiText = { ...base.ui, ...(override.ui ?? {}) };\n return { kinds, ui };\n}\n","/**\n * The transparency situations Article 50 of the EU AI Act describes.\n *\n * - `chatbot`: a person interacts directly with an AI system (Art. 50(1)).\n * - `generated`: image, audio, video or text produced by an AI system (Art. 50(2) and 50(4)).\n * - `edited`: existing content altered with an AI system (Art. 50(2) and 50(4)).\n * - `deepfake`: generated or manipulated content that resembles real people, objects,\n * places or events and could falsely appear authentic (Art. 50(4)).\n * - `emotion-recognition` and `biometric-categorisation`: people are exposed to such a\n * system (Art. 50(3)).\n */\nexport type DisclosureKind =\n | \"chatbot\"\n | \"generated\"\n | \"edited\"\n | \"deepfake\"\n | \"emotion-recognition\"\n | \"biometric-categorisation\";\n\nexport const DISCLOSURE_KINDS: readonly DisclosureKind[] = [\n \"chatbot\",\n \"generated\",\n \"edited\",\n \"deepfake\",\n \"emotion-recognition\",\n \"biometric-categorisation\",\n];\n\n/** The kinds that describe a piece of content and can be written into a marking. */\nexport type ContentKind = \"generated\" | \"edited\" | \"deepfake\";\n\n/**\n * IPTC Digital Source Type values relevant to AI. See\n * https://cv.iptc.org/newscodes/digitalsourcetype/\n */\nexport type SourceType =\n | \"trainedAlgorithmicMedia\"\n | \"compositeWithTrainedAlgorithmicMedia\"\n | \"algorithmicallyEnhanced\"\n | \"algorithmicMedia\"\n | \"compositeSynthetic\";\n\n/** Wording for one disclosure kind in one language. */\nexport interface DisclosureText {\n /** Two or three words for a badge, e.g. \"AI-generated\". */\n label: string;\n /** One line for the heading of a notice. */\n title: string;\n /** One or two plain sentences that explain the label. */\n body: string;\n}\n\n/** Interface strings shared by the notice and label components. */\nexport interface UiText {\n /** Button that collapses the chatbot notice. */\n acknowledge: string;\n /** Accessible name of the button that opens label details. */\n details: string;\n /** \"Generated with {generator}\". `{generator}` is replaced. */\n generatedWith: string;\n /** \"Created on {date}\". `{date}` is replaced. */\n createdOn: string;\n /** Shown when a person reviewed the content and took editorial responsibility. */\n humanReviewed: string;\n /** Link text to a page with more information. */\n moreInfo: string;\n /** Closes the details popover. */\n close: string;\n}\n\nexport interface LocaleMessages {\n kinds: Record<DisclosureKind, DisclosureText>;\n ui: UiText;\n}\n\n/** A partial override of a locale, e.g. to switch German to the informal \"du\". */\nexport interface LocaleOverride {\n kinds?: Partial<Record<DisclosureKind, Partial<DisclosureText>>>;\n ui?: Partial<UiText>;\n}\n\n/** What a marking says about a piece of content. Input for {@link createMarking}. */\nexport interface MarkingInput {\n /** Defaults to `generated`. */\n kind?: ContentKind;\n /** Defaults from `kind`: `trainedAlgorithmicMedia`, or the composite type for `edited`. */\n sourceType?: SourceType;\n /** Name of the AI system or model, e.g. \"gpt-image-2\" or \"Claude\". */\n generator?: string;\n /** Version of the AI system, if known. */\n generatorVersion?: string;\n /** Who provides or operates the AI system, e.g. your company. */\n provider?: string;\n /** ISO 8601 timestamp. Defaults to now. */\n createdAt?: string | Date;\n /** A page that explains how and why you use AI. */\n disclosureUrl?: string;\n /** A person reviewed the content and holds editorial responsibility (Art. 50(4), text). */\n humanReviewed?: boolean;\n /** Free text, e.g. \"Image generated from the prompt by the newsroom\". */\n description?: string;\n}\n\n/** A normalised marking with all defaults applied. */\nexport interface Marking {\n kind: ContentKind;\n sourceType: SourceType;\n generator?: string;\n generatorVersion?: string;\n provider?: string;\n createdAt: string;\n disclosureUrl?: string;\n humanReviewed: boolean;\n description?: string;\n}\n","/**\n * Framework-free custom elements:\n *\n * - `<witness-notice>`: the chatbot notice (Art. 50(1)). Expanded until acknowledged, then a\n * compact label that can be reopened.\n * - `<witness-label>`: a badge for AI-generated or AI-edited content with a details popover.\n *\n * Import `@sweberdev/witness/elements` to register both, or call `defineWitnessElements()`.\n */\n\nimport { createDisclosure, type Disclosure, type DisclosureEvent } from \"./disclosure.js\";\nimport { format, getMessages } from \"./i18n.js\";\nimport { DISCLOSURE_KINDS, type DisclosureKind } from \"./types.js\";\n\nconst BaseElement: typeof HTMLElement =\n typeof HTMLElement === \"undefined\" ? (class {} as unknown as typeof HTMLElement) : HTMLElement;\n\nconst SHARED_CSS = `\n:host { --witness-accent: #003399; --witness-accent-text: #ffffff; --witness-bg: #ffffff;\n --witness-fg: #1a1a1a; --witness-muted: #555b66; --witness-border: #d7dbe3; --witness-radius: 8px;\n font: inherit; color: var(--witness-fg); }\n@media (prefers-color-scheme: dark) {\n :host { --witness-accent: #8fb0ff; --witness-accent-text: #0b1530; --witness-bg: #15181f;\n --witness-fg: #eef1f6; --witness-muted: #a9b0bd; --witness-border: #2c323d; }\n}\n.icon { display: inline-flex; align-items: center; justify-content: center; min-width: 1.75em;\n height: 1.5em; padding: 0 .3em; border-radius: 4px; background: var(--witness-accent);\n color: var(--witness-accent-text); font-weight: 700; font-size: .75em; letter-spacing: .02em;\n line-height: 1; flex: none; }\nbutton { font: inherit; cursor: pointer; }\nbutton:focus-visible, a:focus-visible { outline: 2px solid var(--witness-accent); outline-offset: 2px; }\na { color: inherit; }\n.muted { color: var(--witness-muted); }\n`;\n\nconst NOTICE_CSS = `${SHARED_CSS}\n:host { display: block; }\n.notice { display: flex; gap: .75em; align-items: flex-start; padding: .875em 1em;\n border: 1px solid var(--witness-border); border-left: 4px solid var(--witness-accent);\n border-radius: var(--witness-radius); background: var(--witness-bg); }\n.notice h2 { font-size: 1em; margin: 0 0 .25em; }\n.notice p { margin: 0 0 .75em; line-height: 1.45; }\n.actions { display: flex; gap: .75em; align-items: center; flex-wrap: wrap; }\n.ack { padding: .4em .9em; border-radius: 6px; border: 0; background: var(--witness-accent);\n color: var(--witness-accent-text); font-weight: 600; }\n.compact { display: inline-flex; gap: .5em; align-items: center; padding: .25em .5em;\n border: 1px solid var(--witness-border); border-radius: 999px; background: var(--witness-bg);\n color: var(--witness-fg); font-size: .875em; }\n`;\n\nconst LABEL_CSS = `${SHARED_CSS}\n:host { display: inline-block; position: relative; font-size: .875em; }\n:host([variant=\"overlay\"]) { position: absolute; inset-block-start: .5em; inset-inline-end: .5em; z-index: 1; }\n.badge { display: inline-flex; gap: .4em; align-items: center; padding: .2em .55em .2em .25em;\n border: 1px solid var(--witness-border); border-radius: 999px; background: var(--witness-bg);\n color: var(--witness-fg); }\n.panel { position: absolute; inset-block-start: calc(100% + .4em); inset-inline-end: 0; z-index: 10;\n width: max-content; max-width: min(22em, 80vw); padding: .75em .875em; text-align: start;\n border: 1px solid var(--witness-border); border-radius: var(--witness-radius);\n background: var(--witness-bg); box-shadow: 0 6px 24px rgb(0 0 0 / .15); line-height: 1.45; }\n:host([variant=\"inline\"]) .panel, :host(:not([variant])) .panel { inset-inline-end: auto; inset-inline-start: 0; }\n.panel strong { display: block; margin-bottom: .25em; }\n.panel p { margin: 0 0 .4em; }\n.panel ul { margin: .4em 0; padding-inline-start: 1.1em; }\n.close { position: absolute; inset-block-start: .35em; inset-inline-end: .35em; border: 0;\n background: none; color: var(--witness-muted); font-size: 1.1em; line-height: 1; padding: .2em .35em; }\n[hidden] { display: none !important; }\n`;\n\nfunction locale(el: HTMLElement): string[] {\n const own = el.getAttribute(\"locale\") ?? el.closest(\"[lang]\")?.getAttribute(\"lang\");\n if (own) return [own];\n return typeof navigator !== \"undefined\" ? [...navigator.languages] : [];\n}\n\nfunction kindOf(el: HTMLElement, fallback: DisclosureKind): DisclosureKind {\n const value = el.getAttribute(\"kind\") as DisclosureKind | null;\n return value && DISCLOSURE_KINDS.includes(value) ? value : fallback;\n}\n\nfunction h<K extends keyof HTMLElementTagNameMap>(\n doc: Document,\n tag: K,\n attrs: Record<string, string> = {},\n ...children: Array<Node | string | null>\n): HTMLElementTagNameMap[K] {\n const el = doc.createElement(tag);\n for (const [name, value] of Object.entries(attrs)) el.setAttribute(name, value);\n for (const child of children) {\n if (child !== null) el.append(child);\n }\n return el;\n}\n\nfunction icon(doc: Document): HTMLElement {\n return h(doc, \"span\", { class: \"icon\", \"aria-hidden\": \"true\", part: \"icon\" }, \"AI\");\n}\n\n/** `<witness-notice kind=\"chatbot\" locale=\"de\" disclosure-id=\"support\" version=\"2\" href=\"/ki\">` */\nexport class WitnessNoticeElement extends BaseElement {\n static observedAttributes = [\"kind\", \"locale\", \"disclosure-id\", \"version\", \"href\", \"storage\"];\n\n #disclosure: Disclosure | null = null;\n #unsubscribe: (() => void) | null = null;\n #expanded = false;\n /** `id@version` of the disclosure a `shown` event was sent for, so attribute changes don't repeat it. */\n #shownFor: string | null = null;\n\n connectedCallback(): void {\n if (!this.shadowRoot) this.attachShadow({ mode: \"open\" });\n this.#setup();\n }\n\n disconnectedCallback(): void {\n this.#unsubscribe?.();\n this.#unsubscribe = null;\n }\n\n attributeChangedCallback(_name: string, oldValue: string | null, newValue: string | null): void {\n if (oldValue === newValue) return;\n if (this.isConnected && this.shadowRoot) this.#setup();\n }\n\n /** Forgets the acknowledgement and shows the full notice again. */\n reset(): void {\n this.#disclosure?.reset();\n }\n\n get disclosure(): Disclosure | null {\n return this.#disclosure;\n }\n\n #setup(): void {\n this.#unsubscribe?.();\n const storage = this.getAttribute(\"storage\");\n const kind = kindOf(this, \"chatbot\");\n const tags = locale(this);\n this.#disclosure = createDisclosure({\n kind,\n id: this.getAttribute(\"disclosure-id\") ?? kind,\n version: this.getAttribute(\"version\") ?? \"1\",\n locale: getLocaleCode(tags),\n ...(storage === \"session\" || storage === \"memory\" || storage === \"local\" ? { storage } : {}),\n onEvent: (event) => this.#dispatch(event),\n });\n this.#expanded = false;\n this.#unsubscribe = this.#disclosure.subscribe(() => {\n this.#expanded = false;\n this.#render();\n });\n this.#render();\n }\n\n #dispatch(event: DisclosureEvent): void {\n this.dispatchEvent(\n new CustomEvent(`witness-${event.type}`, { detail: event, bubbles: true, composed: true }),\n );\n }\n\n #render(): void {\n const root = this.shadowRoot;\n const disclosure = this.#disclosure;\n if (!root || !disclosure) return;\n const doc = this.ownerDocument;\n const messages = getMessages(locale(this));\n const text = messages.kinds[disclosure.kind];\n const href = this.getAttribute(\"href\");\n const full = this.#expanded || disclosure.needsAcknowledgement();\n\n const style = h(doc, \"style\", {}, NOTICE_CSS);\n if (full) {\n const ack = h(\n doc,\n \"button\",\n { type: \"button\", class: \"ack\", part: \"button\" },\n messages.ui.acknowledge,\n );\n ack.addEventListener(\"click\", () => disclosure.acknowledge());\n const link = href ? h(doc, \"a\", { href, part: \"link\" }, messages.ui.moreInfo) : null;\n const box = h(\n doc,\n \"section\",\n { class: \"notice\", role: \"note\", \"aria-labelledby\": \"title\", part: \"notice\" },\n icon(doc),\n h(\n doc,\n \"div\",\n {},\n h(doc, \"h2\", { id: \"title\", part: \"title\" }, text.title),\n h(doc, \"p\", { part: \"body\" }, h(doc, \"slot\", {}, text.body)),\n h(doc, \"div\", { class: \"actions\" }, ack, link),\n ),\n );\n root.replaceChildren(style, box);\n const shownFor = `${disclosure.id}@${disclosure.version}`;\n if (this.#shownFor !== shownFor) {\n this.#shownFor = shownFor;\n disclosure.markShown();\n }\n } else {\n const reopen = h(\n doc,\n \"button\",\n {\n type: \"button\",\n class: \"compact\",\n \"aria-label\": `${text.label}: ${messages.ui.details}`,\n part: \"compact\",\n },\n icon(doc),\n text.label,\n );\n reopen.addEventListener(\"click\", () => {\n this.#expanded = true;\n this.#render();\n });\n root.replaceChildren(style, reopen);\n }\n }\n}\n\n/** `<witness-label kind=\"generated\" generator=\"Claude\" created=\"2026-10-05\" reviewed href=\"/ki\">` */\nexport class WitnessLabelElement extends BaseElement {\n static observedAttributes = [\n \"kind\",\n \"locale\",\n \"generator\",\n \"generator-version\",\n \"created\",\n \"reviewed\",\n \"href\",\n \"variant\",\n ];\n\n #open = false;\n #onKey = (event: KeyboardEvent) => {\n if (event.key === \"Escape\" && this.#open) {\n this.#toggle(false);\n this.shadowRoot?.querySelector<HTMLButtonElement>(\".badge\")?.focus();\n }\n };\n #onOutside = (event: Event) => {\n if (this.#open && !event.composedPath().includes(this)) this.#toggle(false);\n };\n\n connectedCallback(): void {\n if (!this.shadowRoot) this.attachShadow({ mode: \"open\" });\n this.ownerDocument.addEventListener(\"keydown\", this.#onKey);\n this.ownerDocument.addEventListener(\"click\", this.#onOutside);\n this.#render();\n }\n\n disconnectedCallback(): void {\n this.ownerDocument.removeEventListener(\"keydown\", this.#onKey);\n this.ownerDocument.removeEventListener(\"click\", this.#onOutside);\n }\n\n attributeChangedCallback(): void {\n if (this.isConnected && this.shadowRoot) this.#render();\n }\n\n #toggle(open: boolean): void {\n this.#open = open;\n this.#render();\n }\n\n #render(): void {\n const root = this.shadowRoot;\n if (!root) return;\n const doc = this.ownerDocument;\n const tags = locale(this);\n const messages = getMessages(tags);\n const kind = kindOf(this, \"generated\");\n const text = messages.kinds[kind];\n const generator = [this.getAttribute(\"generator\"), this.getAttribute(\"generator-version\")]\n .filter(Boolean)\n .join(\" \");\n const created = this.getAttribute(\"created\");\n const href = this.getAttribute(\"href\");\n\n const badge = h(\n doc,\n \"button\",\n {\n type: \"button\",\n class: \"badge\",\n part: \"badge\",\n \"aria-expanded\": String(this.#open),\n \"aria-controls\": \"panel\",\n title: messages.ui.details,\n },\n icon(doc),\n h(doc, \"span\", { part: \"label\" }, text.label),\n );\n badge.addEventListener(\"click\", () => this.#toggle(!this.#open));\n\n const facts = h(doc, \"ul\", {});\n if (generator) facts.append(h(doc, \"li\", {}, format(messages.ui.generatedWith, { generator })));\n if (created) {\n facts.append(\n h(doc, \"li\", {}, format(messages.ui.createdOn, { date: formatDate(created, tags) })),\n );\n }\n if (this.hasAttribute(\"reviewed\")) facts.append(h(doc, \"li\", {}, messages.ui.humanReviewed));\n\n const close = h(\n doc,\n \"button\",\n { type: \"button\", class: \"close\", \"aria-label\": messages.ui.close },\n \"×\",\n );\n close.addEventListener(\"click\", () => this.#toggle(false));\n\n const panel = h(\n doc,\n \"div\",\n { id: \"panel\", class: \"panel\", role: \"dialog\", \"aria-label\": text.title, part: \"panel\" },\n close,\n h(doc, \"strong\", {}, text.title),\n h(doc, \"p\", {}, text.body),\n facts.childElementCount > 0 ? facts : null,\n href ? h(doc, \"a\", { href, part: \"link\" }, messages.ui.moreInfo) : null,\n );\n if (!this.#open) panel.hidden = true;\n root.replaceChildren(h(doc, \"style\", {}, LABEL_CSS), badge, panel);\n }\n}\n\nfunction formatDate(value: string, tags: string[]): string {\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return value;\n try {\n return new Intl.DateTimeFormat(tags.length > 0 ? tags : undefined, {\n dateStyle: \"medium\",\n }).format(date);\n } catch {\n return value;\n }\n}\n\nfunction getLocaleCode(tags: string[]): string {\n return tags[0] ?? \"en\";\n}\n\n/** Registers `<witness-notice>` and `<witness-label>` once. Safe to call during SSR. */\nexport function defineWitnessElements(): void {\n if (typeof customElements === \"undefined\") return;\n if (!customElements.get(\"witness-notice\"))\n customElements.define(\"witness-notice\", WitnessNoticeElement);\n if (!customElements.get(\"witness-label\"))\n customElements.define(\"witness-label\", WitnessLabelElement);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"witness-notice\": WitnessNoticeElement;\n \"witness-label\": WitnessLabelElement;\n }\n interface HTMLElementEventMap {\n \"witness-shown\": CustomEvent<DisclosureEvent>;\n \"witness-acknowledged\": CustomEvent<DisclosureEvent>;\n }\n}\n"],"mappings":"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","names":["locale","locale"]}
|
package/dist/elements-auto.js
CHANGED
package/dist/elements.cjs
CHANGED
|
@@ -415,6 +415,8 @@ var WitnessNoticeElement = class extends BaseElement {
|
|
|
415
415
|
#disclosure = null;
|
|
416
416
|
#unsubscribe = null;
|
|
417
417
|
#expanded = false;
|
|
418
|
+
/** `id@version` of the disclosure a `shown` event was sent for, so attribute changes don't repeat it. */
|
|
419
|
+
#shownFor = null;
|
|
418
420
|
connectedCallback() {
|
|
419
421
|
if (!this.shadowRoot) this.attachShadow({ mode: "open" });
|
|
420
422
|
this.#setup();
|
|
@@ -423,7 +425,8 @@ var WitnessNoticeElement = class extends BaseElement {
|
|
|
423
425
|
this.#unsubscribe?.();
|
|
424
426
|
this.#unsubscribe = null;
|
|
425
427
|
}
|
|
426
|
-
attributeChangedCallback() {
|
|
428
|
+
attributeChangedCallback(_name, oldValue, newValue) {
|
|
429
|
+
if (oldValue === newValue) return;
|
|
427
430
|
if (this.isConnected && this.shadowRoot) this.#setup();
|
|
428
431
|
}
|
|
429
432
|
/** Forgets the acknowledgement and shows the full notice again. */
|
|
@@ -492,7 +495,11 @@ var WitnessNoticeElement = class extends BaseElement {
|
|
|
492
495
|
)
|
|
493
496
|
);
|
|
494
497
|
root.replaceChildren(style, box);
|
|
495
|
-
disclosure.
|
|
498
|
+
const shownFor = `${disclosure.id}@${disclosure.version}`;
|
|
499
|
+
if (this.#shownFor !== shownFor) {
|
|
500
|
+
this.#shownFor = shownFor;
|
|
501
|
+
disclosure.markShown();
|
|
502
|
+
}
|
|
496
503
|
} else {
|
|
497
504
|
const reopen = h(
|
|
498
505
|
doc,
|
package/dist/elements.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/elements.ts","../src/disclosure.ts","../src/i18n.ts","../src/types.ts"],"sourcesContent":["/**\n * Framework-free custom elements:\n *\n * - `<witness-notice>`: the chatbot notice (Art. 50(1)). Expanded until acknowledged, then a\n * compact label that can be reopened.\n * - `<witness-label>`: a badge for AI-generated or AI-edited content with a details popover.\n *\n * Import `@sweberdev/witness/elements` to register both, or call `defineWitnessElements()`.\n */\n\nimport { createDisclosure, type Disclosure, type DisclosureEvent } from \"./disclosure.js\";\nimport { format, getMessages } from \"./i18n.js\";\nimport { DISCLOSURE_KINDS, type DisclosureKind } from \"./types.js\";\n\nconst BaseElement: typeof HTMLElement =\n typeof HTMLElement === \"undefined\" ? (class {} as unknown as typeof HTMLElement) : HTMLElement;\n\nconst SHARED_CSS = `\n:host { --witness-accent: #003399; --witness-accent-text: #ffffff; --witness-bg: #ffffff;\n --witness-fg: #1a1a1a; --witness-muted: #555b66; --witness-border: #d7dbe3; --witness-radius: 8px;\n font: inherit; color: var(--witness-fg); }\n@media (prefers-color-scheme: dark) {\n :host { --witness-accent: #8fb0ff; --witness-accent-text: #0b1530; --witness-bg: #15181f;\n --witness-fg: #eef1f6; --witness-muted: #a9b0bd; --witness-border: #2c323d; }\n}\n.icon { display: inline-flex; align-items: center; justify-content: center; min-width: 1.75em;\n height: 1.5em; padding: 0 .3em; border-radius: 4px; background: var(--witness-accent);\n color: var(--witness-accent-text); font-weight: 700; font-size: .75em; letter-spacing: .02em;\n line-height: 1; flex: none; }\nbutton { font: inherit; cursor: pointer; }\nbutton:focus-visible, a:focus-visible { outline: 2px solid var(--witness-accent); outline-offset: 2px; }\na { color: inherit; }\n.muted { color: var(--witness-muted); }\n`;\n\nconst NOTICE_CSS = `${SHARED_CSS}\n:host { display: block; }\n.notice { display: flex; gap: .75em; align-items: flex-start; padding: .875em 1em;\n border: 1px solid var(--witness-border); border-left: 4px solid var(--witness-accent);\n border-radius: var(--witness-radius); background: var(--witness-bg); }\n.notice h2 { font-size: 1em; margin: 0 0 .25em; }\n.notice p { margin: 0 0 .75em; line-height: 1.45; }\n.actions { display: flex; gap: .75em; align-items: center; flex-wrap: wrap; }\n.ack { padding: .4em .9em; border-radius: 6px; border: 0; background: var(--witness-accent);\n color: var(--witness-accent-text); font-weight: 600; }\n.compact { display: inline-flex; gap: .5em; align-items: center; padding: .25em .5em;\n border: 1px solid var(--witness-border); border-radius: 999px; background: var(--witness-bg);\n color: var(--witness-fg); font-size: .875em; }\n`;\n\nconst LABEL_CSS = `${SHARED_CSS}\n:host { display: inline-block; position: relative; font-size: .875em; }\n:host([variant=\"overlay\"]) { position: absolute; inset-block-start: .5em; inset-inline-end: .5em; z-index: 1; }\n.badge { display: inline-flex; gap: .4em; align-items: center; padding: .2em .55em .2em .25em;\n border: 1px solid var(--witness-border); border-radius: 999px; background: var(--witness-bg);\n color: var(--witness-fg); }\n.panel { position: absolute; inset-block-start: calc(100% + .4em); inset-inline-end: 0; z-index: 10;\n width: max-content; max-width: min(22em, 80vw); padding: .75em .875em; text-align: start;\n border: 1px solid var(--witness-border); border-radius: var(--witness-radius);\n background: var(--witness-bg); box-shadow: 0 6px 24px rgb(0 0 0 / .15); line-height: 1.45; }\n:host([variant=\"inline\"]) .panel, :host(:not([variant])) .panel { inset-inline-end: auto; inset-inline-start: 0; }\n.panel strong { display: block; margin-bottom: .25em; }\n.panel p { margin: 0 0 .4em; }\n.panel ul { margin: .4em 0; padding-inline-start: 1.1em; }\n.close { position: absolute; inset-block-start: .35em; inset-inline-end: .35em; border: 0;\n background: none; color: var(--witness-muted); font-size: 1.1em; line-height: 1; padding: .2em .35em; }\n[hidden] { display: none !important; }\n`;\n\nfunction locale(el: HTMLElement): string[] {\n const own = el.getAttribute(\"locale\") ?? el.closest(\"[lang]\")?.getAttribute(\"lang\");\n if (own) return [own];\n return typeof navigator !== \"undefined\" ? [...navigator.languages] : [];\n}\n\nfunction kindOf(el: HTMLElement, fallback: DisclosureKind): DisclosureKind {\n const value = el.getAttribute(\"kind\") as DisclosureKind | null;\n return value && DISCLOSURE_KINDS.includes(value) ? value : fallback;\n}\n\nfunction h<K extends keyof HTMLElementTagNameMap>(\n doc: Document,\n tag: K,\n attrs: Record<string, string> = {},\n ...children: Array<Node | string | null>\n): HTMLElementTagNameMap[K] {\n const el = doc.createElement(tag);\n for (const [name, value] of Object.entries(attrs)) el.setAttribute(name, value);\n for (const child of children) {\n if (child !== null) el.append(child);\n }\n return el;\n}\n\nfunction icon(doc: Document): HTMLElement {\n return h(doc, \"span\", { class: \"icon\", \"aria-hidden\": \"true\", part: \"icon\" }, \"AI\");\n}\n\n/** `<witness-notice kind=\"chatbot\" locale=\"de\" disclosure-id=\"support\" version=\"2\" href=\"/ki\">` */\nexport class WitnessNoticeElement extends BaseElement {\n static observedAttributes = [\"kind\", \"locale\", \"disclosure-id\", \"version\", \"href\", \"storage\"];\n\n #disclosure: Disclosure | null = null;\n #unsubscribe: (() => void) | null = null;\n #expanded = false;\n\n connectedCallback(): void {\n if (!this.shadowRoot) this.attachShadow({ mode: \"open\" });\n this.#setup();\n }\n\n disconnectedCallback(): void {\n this.#unsubscribe?.();\n this.#unsubscribe = null;\n }\n\n attributeChangedCallback(): void {\n if (this.isConnected && this.shadowRoot) this.#setup();\n }\n\n /** Forgets the acknowledgement and shows the full notice again. */\n reset(): void {\n this.#disclosure?.reset();\n }\n\n get disclosure(): Disclosure | null {\n return this.#disclosure;\n }\n\n #setup(): void {\n this.#unsubscribe?.();\n const storage = this.getAttribute(\"storage\");\n const kind = kindOf(this, \"chatbot\");\n const tags = locale(this);\n this.#disclosure = createDisclosure({\n kind,\n id: this.getAttribute(\"disclosure-id\") ?? kind,\n version: this.getAttribute(\"version\") ?? \"1\",\n locale: getLocaleCode(tags),\n ...(storage === \"session\" || storage === \"memory\" || storage === \"local\" ? { storage } : {}),\n onEvent: (event) => this.#dispatch(event),\n });\n this.#expanded = false;\n this.#unsubscribe = this.#disclosure.subscribe(() => {\n this.#expanded = false;\n this.#render();\n });\n this.#render();\n }\n\n #dispatch(event: DisclosureEvent): void {\n this.dispatchEvent(\n new CustomEvent(`witness-${event.type}`, { detail: event, bubbles: true, composed: true }),\n );\n }\n\n #render(): void {\n const root = this.shadowRoot;\n const disclosure = this.#disclosure;\n if (!root || !disclosure) return;\n const doc = this.ownerDocument;\n const messages = getMessages(locale(this));\n const text = messages.kinds[disclosure.kind];\n const href = this.getAttribute(\"href\");\n const full = this.#expanded || disclosure.needsAcknowledgement();\n\n const style = h(doc, \"style\", {}, NOTICE_CSS);\n if (full) {\n const ack = h(\n doc,\n \"button\",\n { type: \"button\", class: \"ack\", part: \"button\" },\n messages.ui.acknowledge,\n );\n ack.addEventListener(\"click\", () => disclosure.acknowledge());\n const link = href ? h(doc, \"a\", { href, part: \"link\" }, messages.ui.moreInfo) : null;\n const box = h(\n doc,\n \"section\",\n { class: \"notice\", role: \"note\", \"aria-labelledby\": \"title\", part: \"notice\" },\n icon(doc),\n h(\n doc,\n \"div\",\n {},\n h(doc, \"h2\", { id: \"title\", part: \"title\" }, text.title),\n h(doc, \"p\", { part: \"body\" }, h(doc, \"slot\", {}, text.body)),\n h(doc, \"div\", { class: \"actions\" }, ack, link),\n ),\n );\n root.replaceChildren(style, box);\n disclosure.markShown();\n } else {\n const reopen = h(\n doc,\n \"button\",\n {\n type: \"button\",\n class: \"compact\",\n \"aria-label\": `${text.label}: ${messages.ui.details}`,\n part: \"compact\",\n },\n icon(doc),\n text.label,\n );\n reopen.addEventListener(\"click\", () => {\n this.#expanded = true;\n this.#render();\n });\n root.replaceChildren(style, reopen);\n }\n }\n}\n\n/** `<witness-label kind=\"generated\" generator=\"Claude\" created=\"2026-10-05\" reviewed href=\"/ki\">` */\nexport class WitnessLabelElement extends BaseElement {\n static observedAttributes = [\n \"kind\",\n \"locale\",\n \"generator\",\n \"generator-version\",\n \"created\",\n \"reviewed\",\n \"href\",\n \"variant\",\n ];\n\n #open = false;\n #onKey = (event: KeyboardEvent) => {\n if (event.key === \"Escape\" && this.#open) {\n this.#toggle(false);\n this.shadowRoot?.querySelector<HTMLButtonElement>(\".badge\")?.focus();\n }\n };\n #onOutside = (event: Event) => {\n if (this.#open && !event.composedPath().includes(this)) this.#toggle(false);\n };\n\n connectedCallback(): void {\n if (!this.shadowRoot) this.attachShadow({ mode: \"open\" });\n this.ownerDocument.addEventListener(\"keydown\", this.#onKey);\n this.ownerDocument.addEventListener(\"click\", this.#onOutside);\n this.#render();\n }\n\n disconnectedCallback(): void {\n this.ownerDocument.removeEventListener(\"keydown\", this.#onKey);\n this.ownerDocument.removeEventListener(\"click\", this.#onOutside);\n }\n\n attributeChangedCallback(): void {\n if (this.isConnected && this.shadowRoot) this.#render();\n }\n\n #toggle(open: boolean): void {\n this.#open = open;\n this.#render();\n }\n\n #render(): void {\n const root = this.shadowRoot;\n if (!root) return;\n const doc = this.ownerDocument;\n const tags = locale(this);\n const messages = getMessages(tags);\n const kind = kindOf(this, \"generated\");\n const text = messages.kinds[kind];\n const generator = [this.getAttribute(\"generator\"), this.getAttribute(\"generator-version\")]\n .filter(Boolean)\n .join(\" \");\n const created = this.getAttribute(\"created\");\n const href = this.getAttribute(\"href\");\n\n const badge = h(\n doc,\n \"button\",\n {\n type: \"button\",\n class: \"badge\",\n part: \"badge\",\n \"aria-expanded\": String(this.#open),\n \"aria-controls\": \"panel\",\n title: messages.ui.details,\n },\n icon(doc),\n h(doc, \"span\", { part: \"label\" }, text.label),\n );\n badge.addEventListener(\"click\", () => this.#toggle(!this.#open));\n\n const facts = h(doc, \"ul\", {});\n if (generator) facts.append(h(doc, \"li\", {}, format(messages.ui.generatedWith, { generator })));\n if (created) {\n facts.append(\n h(doc, \"li\", {}, format(messages.ui.createdOn, { date: formatDate(created, tags) })),\n );\n }\n if (this.hasAttribute(\"reviewed\")) facts.append(h(doc, \"li\", {}, messages.ui.humanReviewed));\n\n const close = h(\n doc,\n \"button\",\n { type: \"button\", class: \"close\", \"aria-label\": messages.ui.close },\n \"×\",\n );\n close.addEventListener(\"click\", () => this.#toggle(false));\n\n const panel = h(\n doc,\n \"div\",\n { id: \"panel\", class: \"panel\", role: \"dialog\", \"aria-label\": text.title, part: \"panel\" },\n close,\n h(doc, \"strong\", {}, text.title),\n h(doc, \"p\", {}, text.body),\n facts.childElementCount > 0 ? facts : null,\n href ? h(doc, \"a\", { href, part: \"link\" }, messages.ui.moreInfo) : null,\n );\n if (!this.#open) panel.hidden = true;\n root.replaceChildren(h(doc, \"style\", {}, LABEL_CSS), badge, panel);\n }\n}\n\nfunction formatDate(value: string, tags: string[]): string {\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return value;\n try {\n return new Intl.DateTimeFormat(tags.length > 0 ? tags : undefined, {\n dateStyle: \"medium\",\n }).format(date);\n } catch {\n return value;\n }\n}\n\nfunction getLocaleCode(tags: string[]): string {\n return tags[0] ?? \"en\";\n}\n\n/** Registers `<witness-notice>` and `<witness-label>` once. Safe to call during SSR. */\nexport function defineWitnessElements(): void {\n if (typeof customElements === \"undefined\") return;\n if (!customElements.get(\"witness-notice\"))\n customElements.define(\"witness-notice\", WitnessNoticeElement);\n if (!customElements.get(\"witness-label\"))\n customElements.define(\"witness-label\", WitnessLabelElement);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"witness-notice\": WitnessNoticeElement;\n \"witness-label\": WitnessLabelElement;\n }\n interface HTMLElementEventMap {\n \"witness-shown\": CustomEvent<DisclosureEvent>;\n \"witness-acknowledged\": CustomEvent<DisclosureEvent>;\n }\n}\n","import type { DisclosureKind } from \"./types.js\";\n\n/** Minimal key-value storage, e.g. `localStorage`. */\nexport interface DisclosureStorage {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n}\n\nexport interface DisclosureEvent {\n type: \"shown\" | \"acknowledged\";\n /** Your id for this disclosure, e.g. \"support-chat\". */\n id: string;\n kind: DisclosureKind;\n /** Bump the version when the wording changes, so people see the new text once. */\n version: string;\n locale: string;\n /** ISO 8601 timestamp. */\n at: string;\n}\n\nexport interface DisclosureOptions {\n /** Your id for this disclosure. Default: the kind. */\n id?: string;\n /** Default `chatbot`. */\n kind?: DisclosureKind;\n /** Default `1`. */\n version?: string;\n /** Locale shown, recorded in events. Default `en`. */\n locale?: string;\n /**\n * Where the acknowledgement is remembered: `local` (default), `session`, `memory` or your\n * own storage. Falls back to memory when browser storage is unavailable.\n */\n storage?: \"local\" | \"session\" | \"memory\" | DisclosureStorage;\n /**\n * Called when the notice is shown or acknowledged. Send these to your log (for example\n * Logarithm) to keep evidence of what people were told and when.\n */\n onEvent?: (event: DisclosureEvent) => void;\n /** Clock for tests. */\n now?: () => Date;\n}\n\nexport interface Disclosure {\n readonly id: string;\n readonly kind: DisclosureKind;\n readonly version: string;\n /** True until this version was acknowledged. */\n needsAcknowledgement(): boolean;\n /** When this version was acknowledged, or `null`. */\n acknowledgedAt(): string | null;\n /** Records that the notice was rendered. Emits a `shown` event once per instance. */\n markShown(): void;\n /** Records the acknowledgement and emits an `acknowledged` event. */\n acknowledge(): void;\n /** Forgets the acknowledgement. */\n reset(): void;\n /** Called whenever the acknowledgement changes. Returns an unsubscribe function. */\n subscribe(listener: () => void): () => void;\n}\n\nconst PREFIX = \"witness:ack:\";\n\n/**\n * Tracks whether a person has seen and acknowledged an AI disclosure.\n *\n * Article 50(5) asks for the information \"at the latest at the time of the first interaction\n * or exposure\". Keep a compact label visible after the acknowledgement: the acknowledgement\n * only collapses the notice, it does not make it disappear.\n */\nexport function createDisclosure(options: DisclosureOptions = {}): Disclosure {\n const kind = options.kind ?? \"chatbot\";\n const id = options.id ?? kind;\n const version = options.version ?? \"1\";\n const locale = options.locale ?? \"en\";\n const now = options.now ?? (() => new Date());\n const storage = resolveStorage(options.storage);\n const key = `${PREFIX}${id}`;\n const listeners = new Set<() => void>();\n let shown = false;\n\n const read = (): { version: string; at: string } | null => {\n try {\n const raw = storage.getItem(key);\n if (!raw) return null;\n const parsed = JSON.parse(raw) as { version?: unknown; at?: unknown };\n if (typeof parsed.version !== \"string\" || typeof parsed.at !== \"string\") return null;\n return { version: parsed.version, at: parsed.at };\n } catch {\n return null;\n }\n };\n\n const emit = (type: DisclosureEvent[\"type\"], at: string) => {\n options.onEvent?.({ type, id, kind, version, locale, at });\n };\n\n const notify = () => {\n for (const listener of listeners) listener();\n };\n\n return {\n id,\n kind,\n version,\n needsAcknowledgement: () => read()?.version !== version,\n acknowledgedAt: () => {\n const entry = read();\n return entry?.version === version ? entry.at : null;\n },\n markShown() {\n if (shown) return;\n shown = true;\n emit(\"shown\", now().toISOString());\n },\n acknowledge() {\n const at = now().toISOString();\n try {\n storage.setItem(key, JSON.stringify({ version, at }));\n } catch {\n // Storage full or blocked: the acknowledgement lasts for this page only.\n }\n emit(\"acknowledged\", at);\n notify();\n },\n reset() {\n try {\n storage.removeItem(key);\n } catch {\n // ignore\n }\n notify();\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n };\n}\n\nfunction resolveStorage(option: DisclosureOptions[\"storage\"]): DisclosureStorage {\n if (option && typeof option === \"object\") return option;\n if (option !== \"memory\") {\n try {\n const candidate = option === \"session\" ? globalThis.sessionStorage : globalThis.localStorage;\n if (candidate) {\n const probe = `${PREFIX}probe`;\n candidate.setItem(probe, \"1\");\n candidate.removeItem(probe);\n return candidate;\n }\n } catch {\n // fall through to memory\n }\n }\n return memoryStorage();\n}\n\n/** In-memory storage, e.g. for server rendering or tests. */\nexport function memoryStorage(): DisclosureStorage {\n const map = new Map<string, string>();\n return {\n getItem: (key) => map.get(key) ?? null,\n setItem: (key, value) => {\n map.set(key, value);\n },\n removeItem: (key) => {\n map.delete(key);\n },\n };\n}\n","import type {\n DisclosureKind,\n DisclosureText,\n LocaleMessages,\n LocaleOverride,\n UiText,\n} from \"./types.js\";\n\nconst en: LocaleMessages = {\n kinds: {\n chatbot: {\n label: \"AI assistant\",\n title: \"You are chatting with an AI\",\n body: \"This assistant is an AI system, not a person. Its answers are generated automatically and can be wrong.\",\n },\n generated: {\n label: \"AI-generated\",\n title: \"AI-generated content\",\n body: \"This content was generated by an AI system.\",\n },\n edited: {\n label: \"AI-edited\",\n title: \"Edited with AI\",\n body: \"This content was edited or altered with an AI system.\",\n },\n deepfake: {\n label: \"Artificially generated\",\n title: \"Artificially generated or manipulated\",\n body: \"This content was generated or manipulated with AI. It may show people, places or events differently from how they really were.\",\n },\n \"emotion-recognition\": {\n label: \"Emotion recognition\",\n title: \"Emotion recognition is active\",\n body: \"This service uses an AI system that recognises emotions or intentions from your data.\",\n },\n \"biometric-categorisation\": {\n label: \"Biometric categorisation\",\n title: \"Biometric categorisation is active\",\n body: \"This service uses an AI system that assigns people to categories based on biometric data.\",\n },\n },\n ui: {\n acknowledge: \"Got it\",\n details: \"About this label\",\n generatedWith: \"Generated with {generator}\",\n createdOn: \"Created on {date}\",\n humanReviewed: \"Reviewed by a person\",\n moreInfo: \"How we use AI\",\n close: \"Close\",\n },\n};\n\nconst de: LocaleMessages = {\n kinds: {\n chatbot: {\n label: \"KI-Assistent\",\n title: \"Sie chatten mit einer KI\",\n body: \"Dieser Assistent ist ein KI-System und kein Mensch. Seine Antworten werden automatisch erzeugt und können falsch sein.\",\n },\n generated: {\n label: \"KI-generiert\",\n title: \"KI-generierter Inhalt\",\n body: \"Dieser Inhalt wurde von einem KI-System erzeugt.\",\n },\n edited: {\n label: \"Mit KI bearbeitet\",\n title: \"Mit KI bearbeitet\",\n body: \"Dieser Inhalt wurde mit einem KI-System bearbeitet oder verändert.\",\n },\n deepfake: {\n label: \"Künstlich erzeugt\",\n title: \"Künstlich erzeugt oder verändert\",\n body: \"Dieser Inhalt wurde mit KI erzeugt oder verändert. Er kann Personen, Orte oder Ereignisse anders zeigen, als sie wirklich waren.\",\n },\n \"emotion-recognition\": {\n label: \"Emotionserkennung\",\n title: \"Emotionserkennung ist aktiv\",\n body: \"Dieser Dienst setzt ein KI-System ein, das aus Ihren Daten Emotionen oder Absichten erkennt.\",\n },\n \"biometric-categorisation\": {\n label: \"Biometrische Kategorisierung\",\n title: \"Biometrische Kategorisierung ist aktiv\",\n body: \"Dieser Dienst setzt ein KI-System ein, das Personen anhand biometrischer Daten Kategorien zuordnet.\",\n },\n },\n ui: {\n acknowledge: \"Verstanden\",\n details: \"Über diese Kennzeichnung\",\n generatedWith: \"Erzeugt mit {generator}\",\n createdOn: \"Erstellt am {date}\",\n humanReviewed: \"Von einem Menschen geprüft\",\n moreInfo: \"Wie wir KI einsetzen\",\n close: \"Schliessen\",\n },\n};\n\nconst fr: LocaleMessages = {\n kinds: {\n chatbot: {\n label: \"Assistant IA\",\n title: \"Vous discutez avec une IA\",\n body: \"Cet assistant est un système d’IA, pas une personne. Ses réponses sont générées automatiquement et peuvent être erronées.\",\n },\n generated: {\n label: \"Généré par IA\",\n title: \"Contenu généré par IA\",\n body: \"Ce contenu a été généré par un système d’IA.\",\n },\n edited: {\n label: \"Modifié par IA\",\n title: \"Modifié avec l’IA\",\n body: \"Ce contenu a été modifié ou altéré à l’aide d’un système d’IA.\",\n },\n deepfake: {\n label: \"Généré artificiellement\",\n title: \"Généré ou manipulé artificiellement\",\n body: \"Ce contenu a été généré ou manipulé avec l’IA. Il peut montrer des personnes, des lieux ou des événements autrement qu’ils n’ont réellement été.\",\n },\n \"emotion-recognition\": {\n label: \"Reconnaissance des émotions\",\n title: \"La reconnaissance des émotions est active\",\n body: \"Ce service utilise un système d’IA qui reconnaît des émotions ou des intentions à partir de vos données.\",\n },\n \"biometric-categorisation\": {\n label: \"Catégorisation biométrique\",\n title: \"La catégorisation biométrique est active\",\n body: \"Ce service utilise un système d’IA qui classe les personnes dans des catégories à partir de données biométriques.\",\n },\n },\n ui: {\n acknowledge: \"Compris\",\n details: \"À propos de ce label\",\n generatedWith: \"Généré avec {generator}\",\n createdOn: \"Créé le {date}\",\n humanReviewed: \"Vérifié par une personne\",\n moreInfo: \"Comment nous utilisons l’IA\",\n close: \"Fermer\",\n },\n};\n\nconst it: LocaleMessages = {\n kinds: {\n chatbot: {\n label: \"Assistente IA\",\n title: \"Stai parlando con un’IA\",\n body: \"Questo assistente è un sistema di IA, non una persona. Le sue risposte sono generate automaticamente e possono essere sbagliate.\",\n },\n generated: {\n label: \"Generato con IA\",\n title: \"Contenuto generato con IA\",\n body: \"Questo contenuto è stato generato da un sistema di IA.\",\n },\n edited: {\n label: \"Modificato con IA\",\n title: \"Modificato con l’IA\",\n body: \"Questo contenuto è stato modificato o alterato con un sistema di IA.\",\n },\n deepfake: {\n label: \"Generato artificialmente\",\n title: \"Generato o manipolato artificialmente\",\n body: \"Questo contenuto è stato generato o manipolato con l’IA. Può mostrare persone, luoghi o eventi in modo diverso da come sono stati realmente.\",\n },\n \"emotion-recognition\": {\n label: \"Riconoscimento delle emozioni\",\n title: \"Il riconoscimento delle emozioni è attivo\",\n body: \"Questo servizio utilizza un sistema di IA che riconosce emozioni o intenzioni a partire dai tuoi dati.\",\n },\n \"biometric-categorisation\": {\n label: \"Categorizzazione biometrica\",\n title: \"La categorizzazione biometrica è attiva\",\n body: \"Questo servizio utilizza un sistema di IA che assegna le persone a categorie in base a dati biometrici.\",\n },\n },\n ui: {\n acknowledge: \"Ho capito\",\n details: \"Informazioni su questa etichetta\",\n generatedWith: \"Generato con {generator}\",\n createdOn: \"Creato il {date}\",\n humanReviewed: \"Verificato da una persona\",\n moreInfo: \"Come usiamo l’IA\",\n close: \"Chiudi\",\n },\n};\n\nconst registry = new Map<string, LocaleMessages>([\n [\"en\", en],\n [\"de\", de],\n [\"fr\", fr],\n [\"it\", it],\n]);\n\n/** The locales bundled with the free package. */\nexport const BUILT_IN_LOCALES = [\"en\", \"de\", \"fr\", \"it\"] as const;\n\n/**\n * Adds or replaces a locale, e.g. one of the 24 EU languages from Witness Pro.\n * A partial override is merged over the existing locale of that code, or over English.\n */\nexport function registerLocale(code: string, messages: LocaleMessages | LocaleOverride): void {\n const key = code.toLowerCase();\n const base = registry.get(key) ?? registry.get(key.split(\"-\")[0] ?? \"\") ?? en;\n registry.set(key, mergeMessages(base, messages));\n}\n\n/** Codes of all registered locales. */\nexport function registeredLocales(): string[] {\n return [...registry.keys()];\n}\n\n/**\n * Picks the best registered locale for a tag such as \"de-CH\" or a list of tags such as\n * `navigator.languages`. Falls back to English.\n */\nexport function resolveLocale(input?: string | readonly string[] | null): string {\n const tags = input == null ? [] : typeof input === \"string\" ? [input] : input;\n for (const tag of tags) {\n const lower = tag.toLowerCase();\n if (registry.has(lower)) return lower;\n const language = lower.split(\"-\")[0] ?? \"\";\n if (registry.has(language)) return language;\n }\n return \"en\";\n}\n\n/** All messages of a locale, with an optional override merged in. */\nexport function getMessages(\n locale?: string | readonly string[] | null,\n override?: LocaleOverride,\n): LocaleMessages {\n const messages = registry.get(resolveLocale(locale)) ?? en;\n return override ? mergeMessages(messages, override) : messages;\n}\n\n/** Wording for one disclosure kind. */\nexport function disclosureText(\n kind: DisclosureKind,\n locale?: string | readonly string[] | null,\n override?: LocaleOverride,\n): DisclosureText {\n return getMessages(locale, override).kinds[kind];\n}\n\n/** Replaces `{name}` placeholders. Unknown placeholders stay as they are. */\nexport function format(template: string, values: Record<string, string | undefined>): string {\n return template.replace(/\\{(\\w+)\\}/g, (match, name: string) => values[name] ?? match);\n}\n\nfunction mergeMessages(\n base: LocaleMessages,\n override: LocaleMessages | LocaleOverride,\n): LocaleMessages {\n const kinds = { ...base.kinds };\n for (const [kind, text] of Object.entries(override.kinds ?? {})) {\n const key = kind as DisclosureKind;\n kinds[key] = { ...base.kinds[key], ...(text as Partial<DisclosureText>) };\n }\n const ui: UiText = { ...base.ui, ...(override.ui ?? {}) };\n return { kinds, ui };\n}\n","/**\n * The transparency situations Article 50 of the EU AI Act describes.\n *\n * - `chatbot`: a person interacts directly with an AI system (Art. 50(1)).\n * - `generated`: image, audio, video or text produced by an AI system (Art. 50(2) and 50(4)).\n * - `edited`: existing content altered with an AI system (Art. 50(2) and 50(4)).\n * - `deepfake`: generated or manipulated content that resembles real people, objects,\n * places or events and could falsely appear authentic (Art. 50(4)).\n * - `emotion-recognition` and `biometric-categorisation`: people are exposed to such a\n * system (Art. 50(3)).\n */\nexport type DisclosureKind =\n | \"chatbot\"\n | \"generated\"\n | \"edited\"\n | \"deepfake\"\n | \"emotion-recognition\"\n | \"biometric-categorisation\";\n\nexport const DISCLOSURE_KINDS: readonly DisclosureKind[] = [\n \"chatbot\",\n \"generated\",\n \"edited\",\n \"deepfake\",\n \"emotion-recognition\",\n \"biometric-categorisation\",\n];\n\n/** The kinds that describe a piece of content and can be written into a marking. */\nexport type ContentKind = \"generated\" | \"edited\" | \"deepfake\";\n\n/**\n * IPTC Digital Source Type values relevant to AI. See\n * https://cv.iptc.org/newscodes/digitalsourcetype/\n */\nexport type SourceType =\n | \"trainedAlgorithmicMedia\"\n | \"compositeWithTrainedAlgorithmicMedia\"\n | \"algorithmicallyEnhanced\"\n | \"algorithmicMedia\"\n | \"compositeSynthetic\";\n\n/** Wording for one disclosure kind in one language. */\nexport interface DisclosureText {\n /** Two or three words for a badge, e.g. \"AI-generated\". */\n label: string;\n /** One line for the heading of a notice. */\n title: string;\n /** One or two plain sentences that explain the label. */\n body: string;\n}\n\n/** Interface strings shared by the notice and label components. */\nexport interface UiText {\n /** Button that collapses the chatbot notice. */\n acknowledge: string;\n /** Accessible name of the button that opens label details. */\n details: string;\n /** \"Generated with {generator}\". `{generator}` is replaced. */\n generatedWith: string;\n /** \"Created on {date}\". `{date}` is replaced. */\n createdOn: string;\n /** Shown when a person reviewed the content and took editorial responsibility. */\n humanReviewed: string;\n /** Link text to a page with more information. */\n moreInfo: string;\n /** Closes the details popover. */\n close: string;\n}\n\nexport interface LocaleMessages {\n kinds: Record<DisclosureKind, DisclosureText>;\n ui: UiText;\n}\n\n/** A partial override of a locale, e.g. to switch German to the informal \"du\". */\nexport interface LocaleOverride {\n kinds?: Partial<Record<DisclosureKind, Partial<DisclosureText>>>;\n ui?: Partial<UiText>;\n}\n\n/** What a marking says about a piece of content. Input for {@link createMarking}. */\nexport interface MarkingInput {\n /** Defaults to `generated`. */\n kind?: ContentKind;\n /** Defaults from `kind`: `trainedAlgorithmicMedia`, or the composite type for `edited`. */\n sourceType?: SourceType;\n /** Name of the AI system or model, e.g. \"gpt-image-2\" or \"Claude\". */\n generator?: string;\n /** Version of the AI system, if known. */\n generatorVersion?: string;\n /** Who provides or operates the AI system, e.g. your company. */\n provider?: string;\n /** ISO 8601 timestamp. Defaults to now. */\n createdAt?: string | Date;\n /** A page that explains how and why you use AI. */\n disclosureUrl?: string;\n /** A person reviewed the content and holds editorial responsibility (Art. 50(4), text). */\n humanReviewed?: boolean;\n /** Free text, e.g. \"Image generated from the prompt by the newsroom\". */\n description?: string;\n}\n\n/** A normalised marking with all defaults applied. */\nexport interface Marking {\n kind: ContentKind;\n sourceType: SourceType;\n generator?: string;\n generatorVersion?: string;\n provider?: string;\n createdAt: string;\n disclosureUrl?: string;\n humanReviewed: boolean;\n description?: string;\n}\n"],"mappings":"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","names":["locale","locale"]}
|
|
1
|
+
{"version":3,"sources":["../src/elements.ts","../src/disclosure.ts","../src/i18n.ts","../src/types.ts"],"sourcesContent":["/**\n * Framework-free custom elements:\n *\n * - `<witness-notice>`: the chatbot notice (Art. 50(1)). Expanded until acknowledged, then a\n * compact label that can be reopened.\n * - `<witness-label>`: a badge for AI-generated or AI-edited content with a details popover.\n *\n * Import `@sweberdev/witness/elements` to register both, or call `defineWitnessElements()`.\n */\n\nimport { createDisclosure, type Disclosure, type DisclosureEvent } from \"./disclosure.js\";\nimport { format, getMessages } from \"./i18n.js\";\nimport { DISCLOSURE_KINDS, type DisclosureKind } from \"./types.js\";\n\nconst BaseElement: typeof HTMLElement =\n typeof HTMLElement === \"undefined\" ? (class {} as unknown as typeof HTMLElement) : HTMLElement;\n\nconst SHARED_CSS = `\n:host { --witness-accent: #003399; --witness-accent-text: #ffffff; --witness-bg: #ffffff;\n --witness-fg: #1a1a1a; --witness-muted: #555b66; --witness-border: #d7dbe3; --witness-radius: 8px;\n font: inherit; color: var(--witness-fg); }\n@media (prefers-color-scheme: dark) {\n :host { --witness-accent: #8fb0ff; --witness-accent-text: #0b1530; --witness-bg: #15181f;\n --witness-fg: #eef1f6; --witness-muted: #a9b0bd; --witness-border: #2c323d; }\n}\n.icon { display: inline-flex; align-items: center; justify-content: center; min-width: 1.75em;\n height: 1.5em; padding: 0 .3em; border-radius: 4px; background: var(--witness-accent);\n color: var(--witness-accent-text); font-weight: 700; font-size: .75em; letter-spacing: .02em;\n line-height: 1; flex: none; }\nbutton { font: inherit; cursor: pointer; }\nbutton:focus-visible, a:focus-visible { outline: 2px solid var(--witness-accent); outline-offset: 2px; }\na { color: inherit; }\n.muted { color: var(--witness-muted); }\n`;\n\nconst NOTICE_CSS = `${SHARED_CSS}\n:host { display: block; }\n.notice { display: flex; gap: .75em; align-items: flex-start; padding: .875em 1em;\n border: 1px solid var(--witness-border); border-left: 4px solid var(--witness-accent);\n border-radius: var(--witness-radius); background: var(--witness-bg); }\n.notice h2 { font-size: 1em; margin: 0 0 .25em; }\n.notice p { margin: 0 0 .75em; line-height: 1.45; }\n.actions { display: flex; gap: .75em; align-items: center; flex-wrap: wrap; }\n.ack { padding: .4em .9em; border-radius: 6px; border: 0; background: var(--witness-accent);\n color: var(--witness-accent-text); font-weight: 600; }\n.compact { display: inline-flex; gap: .5em; align-items: center; padding: .25em .5em;\n border: 1px solid var(--witness-border); border-radius: 999px; background: var(--witness-bg);\n color: var(--witness-fg); font-size: .875em; }\n`;\n\nconst LABEL_CSS = `${SHARED_CSS}\n:host { display: inline-block; position: relative; font-size: .875em; }\n:host([variant=\"overlay\"]) { position: absolute; inset-block-start: .5em; inset-inline-end: .5em; z-index: 1; }\n.badge { display: inline-flex; gap: .4em; align-items: center; padding: .2em .55em .2em .25em;\n border: 1px solid var(--witness-border); border-radius: 999px; background: var(--witness-bg);\n color: var(--witness-fg); }\n.panel { position: absolute; inset-block-start: calc(100% + .4em); inset-inline-end: 0; z-index: 10;\n width: max-content; max-width: min(22em, 80vw); padding: .75em .875em; text-align: start;\n border: 1px solid var(--witness-border); border-radius: var(--witness-radius);\n background: var(--witness-bg); box-shadow: 0 6px 24px rgb(0 0 0 / .15); line-height: 1.45; }\n:host([variant=\"inline\"]) .panel, :host(:not([variant])) .panel { inset-inline-end: auto; inset-inline-start: 0; }\n.panel strong { display: block; margin-bottom: .25em; }\n.panel p { margin: 0 0 .4em; }\n.panel ul { margin: .4em 0; padding-inline-start: 1.1em; }\n.close { position: absolute; inset-block-start: .35em; inset-inline-end: .35em; border: 0;\n background: none; color: var(--witness-muted); font-size: 1.1em; line-height: 1; padding: .2em .35em; }\n[hidden] { display: none !important; }\n`;\n\nfunction locale(el: HTMLElement): string[] {\n const own = el.getAttribute(\"locale\") ?? el.closest(\"[lang]\")?.getAttribute(\"lang\");\n if (own) return [own];\n return typeof navigator !== \"undefined\" ? [...navigator.languages] : [];\n}\n\nfunction kindOf(el: HTMLElement, fallback: DisclosureKind): DisclosureKind {\n const value = el.getAttribute(\"kind\") as DisclosureKind | null;\n return value && DISCLOSURE_KINDS.includes(value) ? value : fallback;\n}\n\nfunction h<K extends keyof HTMLElementTagNameMap>(\n doc: Document,\n tag: K,\n attrs: Record<string, string> = {},\n ...children: Array<Node | string | null>\n): HTMLElementTagNameMap[K] {\n const el = doc.createElement(tag);\n for (const [name, value] of Object.entries(attrs)) el.setAttribute(name, value);\n for (const child of children) {\n if (child !== null) el.append(child);\n }\n return el;\n}\n\nfunction icon(doc: Document): HTMLElement {\n return h(doc, \"span\", { class: \"icon\", \"aria-hidden\": \"true\", part: \"icon\" }, \"AI\");\n}\n\n/** `<witness-notice kind=\"chatbot\" locale=\"de\" disclosure-id=\"support\" version=\"2\" href=\"/ki\">` */\nexport class WitnessNoticeElement extends BaseElement {\n static observedAttributes = [\"kind\", \"locale\", \"disclosure-id\", \"version\", \"href\", \"storage\"];\n\n #disclosure: Disclosure | null = null;\n #unsubscribe: (() => void) | null = null;\n #expanded = false;\n /** `id@version` of the disclosure a `shown` event was sent for, so attribute changes don't repeat it. */\n #shownFor: string | null = null;\n\n connectedCallback(): void {\n if (!this.shadowRoot) this.attachShadow({ mode: \"open\" });\n this.#setup();\n }\n\n disconnectedCallback(): void {\n this.#unsubscribe?.();\n this.#unsubscribe = null;\n }\n\n attributeChangedCallback(_name: string, oldValue: string | null, newValue: string | null): void {\n if (oldValue === newValue) return;\n if (this.isConnected && this.shadowRoot) this.#setup();\n }\n\n /** Forgets the acknowledgement and shows the full notice again. */\n reset(): void {\n this.#disclosure?.reset();\n }\n\n get disclosure(): Disclosure | null {\n return this.#disclosure;\n }\n\n #setup(): void {\n this.#unsubscribe?.();\n const storage = this.getAttribute(\"storage\");\n const kind = kindOf(this, \"chatbot\");\n const tags = locale(this);\n this.#disclosure = createDisclosure({\n kind,\n id: this.getAttribute(\"disclosure-id\") ?? kind,\n version: this.getAttribute(\"version\") ?? \"1\",\n locale: getLocaleCode(tags),\n ...(storage === \"session\" || storage === \"memory\" || storage === \"local\" ? { storage } : {}),\n onEvent: (event) => this.#dispatch(event),\n });\n this.#expanded = false;\n this.#unsubscribe = this.#disclosure.subscribe(() => {\n this.#expanded = false;\n this.#render();\n });\n this.#render();\n }\n\n #dispatch(event: DisclosureEvent): void {\n this.dispatchEvent(\n new CustomEvent(`witness-${event.type}`, { detail: event, bubbles: true, composed: true }),\n );\n }\n\n #render(): void {\n const root = this.shadowRoot;\n const disclosure = this.#disclosure;\n if (!root || !disclosure) return;\n const doc = this.ownerDocument;\n const messages = getMessages(locale(this));\n const text = messages.kinds[disclosure.kind];\n const href = this.getAttribute(\"href\");\n const full = this.#expanded || disclosure.needsAcknowledgement();\n\n const style = h(doc, \"style\", {}, NOTICE_CSS);\n if (full) {\n const ack = h(\n doc,\n \"button\",\n { type: \"button\", class: \"ack\", part: \"button\" },\n messages.ui.acknowledge,\n );\n ack.addEventListener(\"click\", () => disclosure.acknowledge());\n const link = href ? h(doc, \"a\", { href, part: \"link\" }, messages.ui.moreInfo) : null;\n const box = h(\n doc,\n \"section\",\n { class: \"notice\", role: \"note\", \"aria-labelledby\": \"title\", part: \"notice\" },\n icon(doc),\n h(\n doc,\n \"div\",\n {},\n h(doc, \"h2\", { id: \"title\", part: \"title\" }, text.title),\n h(doc, \"p\", { part: \"body\" }, h(doc, \"slot\", {}, text.body)),\n h(doc, \"div\", { class: \"actions\" }, ack, link),\n ),\n );\n root.replaceChildren(style, box);\n const shownFor = `${disclosure.id}@${disclosure.version}`;\n if (this.#shownFor !== shownFor) {\n this.#shownFor = shownFor;\n disclosure.markShown();\n }\n } else {\n const reopen = h(\n doc,\n \"button\",\n {\n type: \"button\",\n class: \"compact\",\n \"aria-label\": `${text.label}: ${messages.ui.details}`,\n part: \"compact\",\n },\n icon(doc),\n text.label,\n );\n reopen.addEventListener(\"click\", () => {\n this.#expanded = true;\n this.#render();\n });\n root.replaceChildren(style, reopen);\n }\n }\n}\n\n/** `<witness-label kind=\"generated\" generator=\"Claude\" created=\"2026-10-05\" reviewed href=\"/ki\">` */\nexport class WitnessLabelElement extends BaseElement {\n static observedAttributes = [\n \"kind\",\n \"locale\",\n \"generator\",\n \"generator-version\",\n \"created\",\n \"reviewed\",\n \"href\",\n \"variant\",\n ];\n\n #open = false;\n #onKey = (event: KeyboardEvent) => {\n if (event.key === \"Escape\" && this.#open) {\n this.#toggle(false);\n this.shadowRoot?.querySelector<HTMLButtonElement>(\".badge\")?.focus();\n }\n };\n #onOutside = (event: Event) => {\n if (this.#open && !event.composedPath().includes(this)) this.#toggle(false);\n };\n\n connectedCallback(): void {\n if (!this.shadowRoot) this.attachShadow({ mode: \"open\" });\n this.ownerDocument.addEventListener(\"keydown\", this.#onKey);\n this.ownerDocument.addEventListener(\"click\", this.#onOutside);\n this.#render();\n }\n\n disconnectedCallback(): void {\n this.ownerDocument.removeEventListener(\"keydown\", this.#onKey);\n this.ownerDocument.removeEventListener(\"click\", this.#onOutside);\n }\n\n attributeChangedCallback(): void {\n if (this.isConnected && this.shadowRoot) this.#render();\n }\n\n #toggle(open: boolean): void {\n this.#open = open;\n this.#render();\n }\n\n #render(): void {\n const root = this.shadowRoot;\n if (!root) return;\n const doc = this.ownerDocument;\n const tags = locale(this);\n const messages = getMessages(tags);\n const kind = kindOf(this, \"generated\");\n const text = messages.kinds[kind];\n const generator = [this.getAttribute(\"generator\"), this.getAttribute(\"generator-version\")]\n .filter(Boolean)\n .join(\" \");\n const created = this.getAttribute(\"created\");\n const href = this.getAttribute(\"href\");\n\n const badge = h(\n doc,\n \"button\",\n {\n type: \"button\",\n class: \"badge\",\n part: \"badge\",\n \"aria-expanded\": String(this.#open),\n \"aria-controls\": \"panel\",\n title: messages.ui.details,\n },\n icon(doc),\n h(doc, \"span\", { part: \"label\" }, text.label),\n );\n badge.addEventListener(\"click\", () => this.#toggle(!this.#open));\n\n const facts = h(doc, \"ul\", {});\n if (generator) facts.append(h(doc, \"li\", {}, format(messages.ui.generatedWith, { generator })));\n if (created) {\n facts.append(\n h(doc, \"li\", {}, format(messages.ui.createdOn, { date: formatDate(created, tags) })),\n );\n }\n if (this.hasAttribute(\"reviewed\")) facts.append(h(doc, \"li\", {}, messages.ui.humanReviewed));\n\n const close = h(\n doc,\n \"button\",\n { type: \"button\", class: \"close\", \"aria-label\": messages.ui.close },\n \"×\",\n );\n close.addEventListener(\"click\", () => this.#toggle(false));\n\n const panel = h(\n doc,\n \"div\",\n { id: \"panel\", class: \"panel\", role: \"dialog\", \"aria-label\": text.title, part: \"panel\" },\n close,\n h(doc, \"strong\", {}, text.title),\n h(doc, \"p\", {}, text.body),\n facts.childElementCount > 0 ? facts : null,\n href ? h(doc, \"a\", { href, part: \"link\" }, messages.ui.moreInfo) : null,\n );\n if (!this.#open) panel.hidden = true;\n root.replaceChildren(h(doc, \"style\", {}, LABEL_CSS), badge, panel);\n }\n}\n\nfunction formatDate(value: string, tags: string[]): string {\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return value;\n try {\n return new Intl.DateTimeFormat(tags.length > 0 ? tags : undefined, {\n dateStyle: \"medium\",\n }).format(date);\n } catch {\n return value;\n }\n}\n\nfunction getLocaleCode(tags: string[]): string {\n return tags[0] ?? \"en\";\n}\n\n/** Registers `<witness-notice>` and `<witness-label>` once. Safe to call during SSR. */\nexport function defineWitnessElements(): void {\n if (typeof customElements === \"undefined\") return;\n if (!customElements.get(\"witness-notice\"))\n customElements.define(\"witness-notice\", WitnessNoticeElement);\n if (!customElements.get(\"witness-label\"))\n customElements.define(\"witness-label\", WitnessLabelElement);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"witness-notice\": WitnessNoticeElement;\n \"witness-label\": WitnessLabelElement;\n }\n interface HTMLElementEventMap {\n \"witness-shown\": CustomEvent<DisclosureEvent>;\n \"witness-acknowledged\": CustomEvent<DisclosureEvent>;\n }\n}\n","import type { DisclosureKind } from \"./types.js\";\n\n/** Minimal key-value storage, e.g. `localStorage`. */\nexport interface DisclosureStorage {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n}\n\nexport interface DisclosureEvent {\n type: \"shown\" | \"acknowledged\";\n /** Your id for this disclosure, e.g. \"support-chat\". */\n id: string;\n kind: DisclosureKind;\n /** Bump the version when the wording changes, so people see the new text once. */\n version: string;\n locale: string;\n /** ISO 8601 timestamp. */\n at: string;\n}\n\nexport interface DisclosureOptions {\n /** Your id for this disclosure. Default: the kind. */\n id?: string;\n /** Default `chatbot`. */\n kind?: DisclosureKind;\n /** Default `1`. */\n version?: string;\n /** Locale shown, recorded in events. Default `en`. */\n locale?: string;\n /**\n * Where the acknowledgement is remembered: `local` (default), `session`, `memory` or your\n * own storage. Falls back to memory when browser storage is unavailable.\n */\n storage?: \"local\" | \"session\" | \"memory\" | DisclosureStorage;\n /**\n * Called when the notice is shown or acknowledged. Send these to your log (for example\n * Logarithm) to keep evidence of what people were told and when.\n */\n onEvent?: (event: DisclosureEvent) => void;\n /** Clock for tests. */\n now?: () => Date;\n}\n\nexport interface Disclosure {\n readonly id: string;\n readonly kind: DisclosureKind;\n readonly version: string;\n /** True until this version was acknowledged. */\n needsAcknowledgement(): boolean;\n /** When this version was acknowledged, or `null`. */\n acknowledgedAt(): string | null;\n /** Records that the notice was rendered. Emits a `shown` event once per instance. */\n markShown(): void;\n /** Records the acknowledgement and emits an `acknowledged` event. */\n acknowledge(): void;\n /** Forgets the acknowledgement. */\n reset(): void;\n /** Called whenever the acknowledgement changes. Returns an unsubscribe function. */\n subscribe(listener: () => void): () => void;\n}\n\nconst PREFIX = \"witness:ack:\";\n\n/**\n * Tracks whether a person has seen and acknowledged an AI disclosure.\n *\n * Article 50(5) asks for the information \"at the latest at the time of the first interaction\n * or exposure\". Keep a compact label visible after the acknowledgement: the acknowledgement\n * only collapses the notice, it does not make it disappear.\n */\nexport function createDisclosure(options: DisclosureOptions = {}): Disclosure {\n const kind = options.kind ?? \"chatbot\";\n const id = options.id ?? kind;\n const version = options.version ?? \"1\";\n const locale = options.locale ?? \"en\";\n const now = options.now ?? (() => new Date());\n const storage = resolveStorage(options.storage);\n const key = `${PREFIX}${id}`;\n const listeners = new Set<() => void>();\n let shown = false;\n\n const read = (): { version: string; at: string } | null => {\n try {\n const raw = storage.getItem(key);\n if (!raw) return null;\n const parsed = JSON.parse(raw) as { version?: unknown; at?: unknown };\n if (typeof parsed.version !== \"string\" || typeof parsed.at !== \"string\") return null;\n return { version: parsed.version, at: parsed.at };\n } catch {\n return null;\n }\n };\n\n const emit = (type: DisclosureEvent[\"type\"], at: string) => {\n options.onEvent?.({ type, id, kind, version, locale, at });\n };\n\n const notify = () => {\n for (const listener of listeners) listener();\n };\n\n return {\n id,\n kind,\n version,\n needsAcknowledgement: () => read()?.version !== version,\n acknowledgedAt: () => {\n const entry = read();\n return entry?.version === version ? entry.at : null;\n },\n markShown() {\n if (shown) return;\n shown = true;\n emit(\"shown\", now().toISOString());\n },\n acknowledge() {\n const at = now().toISOString();\n try {\n storage.setItem(key, JSON.stringify({ version, at }));\n } catch {\n // Storage full or blocked: the acknowledgement lasts for this page only.\n }\n emit(\"acknowledged\", at);\n notify();\n },\n reset() {\n try {\n storage.removeItem(key);\n } catch {\n // ignore\n }\n notify();\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n };\n}\n\nfunction resolveStorage(option: DisclosureOptions[\"storage\"]): DisclosureStorage {\n if (option && typeof option === \"object\") return option;\n if (option !== \"memory\") {\n try {\n const candidate = option === \"session\" ? globalThis.sessionStorage : globalThis.localStorage;\n if (candidate) {\n const probe = `${PREFIX}probe`;\n candidate.setItem(probe, \"1\");\n candidate.removeItem(probe);\n return candidate;\n }\n } catch {\n // fall through to memory\n }\n }\n return memoryStorage();\n}\n\n/** In-memory storage, e.g. for server rendering or tests. */\nexport function memoryStorage(): DisclosureStorage {\n const map = new Map<string, string>();\n return {\n getItem: (key) => map.get(key) ?? null,\n setItem: (key, value) => {\n map.set(key, value);\n },\n removeItem: (key) => {\n map.delete(key);\n },\n };\n}\n","import type {\n DisclosureKind,\n DisclosureText,\n LocaleMessages,\n LocaleOverride,\n UiText,\n} from \"./types.js\";\n\nconst en: LocaleMessages = {\n kinds: {\n chatbot: {\n label: \"AI assistant\",\n title: \"You are chatting with an AI\",\n body: \"This assistant is an AI system, not a person. Its answers are generated automatically and can be wrong.\",\n },\n generated: {\n label: \"AI-generated\",\n title: \"AI-generated content\",\n body: \"This content was generated by an AI system.\",\n },\n edited: {\n label: \"AI-edited\",\n title: \"Edited with AI\",\n body: \"This content was edited or altered with an AI system.\",\n },\n deepfake: {\n label: \"Artificially generated\",\n title: \"Artificially generated or manipulated\",\n body: \"This content was generated or manipulated with AI. It may show people, places or events differently from how they really were.\",\n },\n \"emotion-recognition\": {\n label: \"Emotion recognition\",\n title: \"Emotion recognition is active\",\n body: \"This service uses an AI system that recognises emotions or intentions from your data.\",\n },\n \"biometric-categorisation\": {\n label: \"Biometric categorisation\",\n title: \"Biometric categorisation is active\",\n body: \"This service uses an AI system that assigns people to categories based on biometric data.\",\n },\n },\n ui: {\n acknowledge: \"Got it\",\n details: \"About this label\",\n generatedWith: \"Generated with {generator}\",\n createdOn: \"Created on {date}\",\n humanReviewed: \"Reviewed by a person\",\n moreInfo: \"How we use AI\",\n close: \"Close\",\n },\n};\n\nconst de: LocaleMessages = {\n kinds: {\n chatbot: {\n label: \"KI-Assistent\",\n title: \"Sie chatten mit einer KI\",\n body: \"Dieser Assistent ist ein KI-System und kein Mensch. Seine Antworten werden automatisch erzeugt und können falsch sein.\",\n },\n generated: {\n label: \"KI-generiert\",\n title: \"KI-generierter Inhalt\",\n body: \"Dieser Inhalt wurde von einem KI-System erzeugt.\",\n },\n edited: {\n label: \"Mit KI bearbeitet\",\n title: \"Mit KI bearbeitet\",\n body: \"Dieser Inhalt wurde mit einem KI-System bearbeitet oder verändert.\",\n },\n deepfake: {\n label: \"Künstlich erzeugt\",\n title: \"Künstlich erzeugt oder verändert\",\n body: \"Dieser Inhalt wurde mit KI erzeugt oder verändert. Er kann Personen, Orte oder Ereignisse anders zeigen, als sie wirklich waren.\",\n },\n \"emotion-recognition\": {\n label: \"Emotionserkennung\",\n title: \"Emotionserkennung ist aktiv\",\n body: \"Dieser Dienst setzt ein KI-System ein, das aus Ihren Daten Emotionen oder Absichten erkennt.\",\n },\n \"biometric-categorisation\": {\n label: \"Biometrische Kategorisierung\",\n title: \"Biometrische Kategorisierung ist aktiv\",\n body: \"Dieser Dienst setzt ein KI-System ein, das Personen anhand biometrischer Daten Kategorien zuordnet.\",\n },\n },\n ui: {\n acknowledge: \"Verstanden\",\n details: \"Über diese Kennzeichnung\",\n generatedWith: \"Erzeugt mit {generator}\",\n createdOn: \"Erstellt am {date}\",\n humanReviewed: \"Von einem Menschen geprüft\",\n moreInfo: \"Wie wir KI einsetzen\",\n close: \"Schliessen\",\n },\n};\n\nconst fr: LocaleMessages = {\n kinds: {\n chatbot: {\n label: \"Assistant IA\",\n title: \"Vous discutez avec une IA\",\n body: \"Cet assistant est un système d’IA, pas une personne. Ses réponses sont générées automatiquement et peuvent être erronées.\",\n },\n generated: {\n label: \"Généré par IA\",\n title: \"Contenu généré par IA\",\n body: \"Ce contenu a été généré par un système d’IA.\",\n },\n edited: {\n label: \"Modifié par IA\",\n title: \"Modifié avec l’IA\",\n body: \"Ce contenu a été modifié ou altéré à l’aide d’un système d’IA.\",\n },\n deepfake: {\n label: \"Généré artificiellement\",\n title: \"Généré ou manipulé artificiellement\",\n body: \"Ce contenu a été généré ou manipulé avec l’IA. Il peut montrer des personnes, des lieux ou des événements autrement qu’ils n’ont réellement été.\",\n },\n \"emotion-recognition\": {\n label: \"Reconnaissance des émotions\",\n title: \"La reconnaissance des émotions est active\",\n body: \"Ce service utilise un système d’IA qui reconnaît des émotions ou des intentions à partir de vos données.\",\n },\n \"biometric-categorisation\": {\n label: \"Catégorisation biométrique\",\n title: \"La catégorisation biométrique est active\",\n body: \"Ce service utilise un système d’IA qui classe les personnes dans des catégories à partir de données biométriques.\",\n },\n },\n ui: {\n acknowledge: \"Compris\",\n details: \"À propos de ce label\",\n generatedWith: \"Généré avec {generator}\",\n createdOn: \"Créé le {date}\",\n humanReviewed: \"Vérifié par une personne\",\n moreInfo: \"Comment nous utilisons l’IA\",\n close: \"Fermer\",\n },\n};\n\nconst it: LocaleMessages = {\n kinds: {\n chatbot: {\n label: \"Assistente IA\",\n title: \"Stai parlando con un’IA\",\n body: \"Questo assistente è un sistema di IA, non una persona. Le sue risposte sono generate automaticamente e possono essere sbagliate.\",\n },\n generated: {\n label: \"Generato con IA\",\n title: \"Contenuto generato con IA\",\n body: \"Questo contenuto è stato generato da un sistema di IA.\",\n },\n edited: {\n label: \"Modificato con IA\",\n title: \"Modificato con l’IA\",\n body: \"Questo contenuto è stato modificato o alterato con un sistema di IA.\",\n },\n deepfake: {\n label: \"Generato artificialmente\",\n title: \"Generato o manipolato artificialmente\",\n body: \"Questo contenuto è stato generato o manipolato con l’IA. Può mostrare persone, luoghi o eventi in modo diverso da come sono stati realmente.\",\n },\n \"emotion-recognition\": {\n label: \"Riconoscimento delle emozioni\",\n title: \"Il riconoscimento delle emozioni è attivo\",\n body: \"Questo servizio utilizza un sistema di IA che riconosce emozioni o intenzioni a partire dai tuoi dati.\",\n },\n \"biometric-categorisation\": {\n label: \"Categorizzazione biometrica\",\n title: \"La categorizzazione biometrica è attiva\",\n body: \"Questo servizio utilizza un sistema di IA che assegna le persone a categorie in base a dati biometrici.\",\n },\n },\n ui: {\n acknowledge: \"Ho capito\",\n details: \"Informazioni su questa etichetta\",\n generatedWith: \"Generato con {generator}\",\n createdOn: \"Creato il {date}\",\n humanReviewed: \"Verificato da una persona\",\n moreInfo: \"Come usiamo l’IA\",\n close: \"Chiudi\",\n },\n};\n\nconst registry = new Map<string, LocaleMessages>([\n [\"en\", en],\n [\"de\", de],\n [\"fr\", fr],\n [\"it\", it],\n]);\n\n/** The locales bundled with the free package. */\nexport const BUILT_IN_LOCALES = [\"en\", \"de\", \"fr\", \"it\"] as const;\n\n/**\n * Adds or replaces a locale, e.g. one of the 24 EU languages from Witness Pro.\n * A partial override is merged over the existing locale of that code, or over English.\n */\nexport function registerLocale(code: string, messages: LocaleMessages | LocaleOverride): void {\n const key = code.toLowerCase();\n const base = registry.get(key) ?? registry.get(key.split(\"-\")[0] ?? \"\") ?? en;\n registry.set(key, mergeMessages(base, messages));\n}\n\n/** Codes of all registered locales. */\nexport function registeredLocales(): string[] {\n return [...registry.keys()];\n}\n\n/**\n * Picks the best registered locale for a tag such as \"de-CH\" or a list of tags such as\n * `navigator.languages`. Falls back to English.\n */\nexport function resolveLocale(input?: string | readonly string[] | null): string {\n const tags = input == null ? [] : typeof input === \"string\" ? [input] : input;\n for (const tag of tags) {\n const lower = tag.toLowerCase();\n if (registry.has(lower)) return lower;\n const language = lower.split(\"-\")[0] ?? \"\";\n if (registry.has(language)) return language;\n }\n return \"en\";\n}\n\n/** All messages of a locale, with an optional override merged in. */\nexport function getMessages(\n locale?: string | readonly string[] | null,\n override?: LocaleOverride,\n): LocaleMessages {\n const messages = registry.get(resolveLocale(locale)) ?? en;\n return override ? mergeMessages(messages, override) : messages;\n}\n\n/** Wording for one disclosure kind. */\nexport function disclosureText(\n kind: DisclosureKind,\n locale?: string | readonly string[] | null,\n override?: LocaleOverride,\n): DisclosureText {\n return getMessages(locale, override).kinds[kind];\n}\n\n/** Replaces `{name}` placeholders. Unknown placeholders stay as they are. */\nexport function format(template: string, values: Record<string, string | undefined>): string {\n return template.replace(/\\{(\\w+)\\}/g, (match, name: string) => values[name] ?? match);\n}\n\nfunction mergeMessages(\n base: LocaleMessages,\n override: LocaleMessages | LocaleOverride,\n): LocaleMessages {\n const kinds = { ...base.kinds };\n for (const [kind, text] of Object.entries(override.kinds ?? {})) {\n const key = kind as DisclosureKind;\n kinds[key] = { ...base.kinds[key], ...(text as Partial<DisclosureText>) };\n }\n const ui: UiText = { ...base.ui, ...(override.ui ?? {}) };\n return { kinds, ui };\n}\n","/**\n * The transparency situations Article 50 of the EU AI Act describes.\n *\n * - `chatbot`: a person interacts directly with an AI system (Art. 50(1)).\n * - `generated`: image, audio, video or text produced by an AI system (Art. 50(2) and 50(4)).\n * - `edited`: existing content altered with an AI system (Art. 50(2) and 50(4)).\n * - `deepfake`: generated or manipulated content that resembles real people, objects,\n * places or events and could falsely appear authentic (Art. 50(4)).\n * - `emotion-recognition` and `biometric-categorisation`: people are exposed to such a\n * system (Art. 50(3)).\n */\nexport type DisclosureKind =\n | \"chatbot\"\n | \"generated\"\n | \"edited\"\n | \"deepfake\"\n | \"emotion-recognition\"\n | \"biometric-categorisation\";\n\nexport const DISCLOSURE_KINDS: readonly DisclosureKind[] = [\n \"chatbot\",\n \"generated\",\n \"edited\",\n \"deepfake\",\n \"emotion-recognition\",\n \"biometric-categorisation\",\n];\n\n/** The kinds that describe a piece of content and can be written into a marking. */\nexport type ContentKind = \"generated\" | \"edited\" | \"deepfake\";\n\n/**\n * IPTC Digital Source Type values relevant to AI. See\n * https://cv.iptc.org/newscodes/digitalsourcetype/\n */\nexport type SourceType =\n | \"trainedAlgorithmicMedia\"\n | \"compositeWithTrainedAlgorithmicMedia\"\n | \"algorithmicallyEnhanced\"\n | \"algorithmicMedia\"\n | \"compositeSynthetic\";\n\n/** Wording for one disclosure kind in one language. */\nexport interface DisclosureText {\n /** Two or three words for a badge, e.g. \"AI-generated\". */\n label: string;\n /** One line for the heading of a notice. */\n title: string;\n /** One or two plain sentences that explain the label. */\n body: string;\n}\n\n/** Interface strings shared by the notice and label components. */\nexport interface UiText {\n /** Button that collapses the chatbot notice. */\n acknowledge: string;\n /** Accessible name of the button that opens label details. */\n details: string;\n /** \"Generated with {generator}\". `{generator}` is replaced. */\n generatedWith: string;\n /** \"Created on {date}\". `{date}` is replaced. */\n createdOn: string;\n /** Shown when a person reviewed the content and took editorial responsibility. */\n humanReviewed: string;\n /** Link text to a page with more information. */\n moreInfo: string;\n /** Closes the details popover. */\n close: string;\n}\n\nexport interface LocaleMessages {\n kinds: Record<DisclosureKind, DisclosureText>;\n ui: UiText;\n}\n\n/** A partial override of a locale, e.g. to switch German to the informal \"du\". */\nexport interface LocaleOverride {\n kinds?: Partial<Record<DisclosureKind, Partial<DisclosureText>>>;\n ui?: Partial<UiText>;\n}\n\n/** What a marking says about a piece of content. Input for {@link createMarking}. */\nexport interface MarkingInput {\n /** Defaults to `generated`. */\n kind?: ContentKind;\n /** Defaults from `kind`: `trainedAlgorithmicMedia`, or the composite type for `edited`. */\n sourceType?: SourceType;\n /** Name of the AI system or model, e.g. \"gpt-image-2\" or \"Claude\". */\n generator?: string;\n /** Version of the AI system, if known. */\n generatorVersion?: string;\n /** Who provides or operates the AI system, e.g. your company. */\n provider?: string;\n /** ISO 8601 timestamp. Defaults to now. */\n createdAt?: string | Date;\n /** A page that explains how and why you use AI. */\n disclosureUrl?: string;\n /** A person reviewed the content and holds editorial responsibility (Art. 50(4), text). */\n humanReviewed?: boolean;\n /** Free text, e.g. \"Image generated from the prompt by the newsroom\". */\n description?: string;\n}\n\n/** A normalised marking with all defaults applied. */\nexport interface Marking {\n kind: ContentKind;\n sourceType: SourceType;\n generator?: string;\n generatorVersion?: string;\n provider?: string;\n createdAt: string;\n disclosureUrl?: string;\n humanReviewed: boolean;\n description?: string;\n}\n"],"mappings":"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","names":["locale","locale"]}
|
package/dist/elements.d.cts
CHANGED
|
@@ -18,7 +18,7 @@ declare class WitnessNoticeElement extends BaseElement {
|
|
|
18
18
|
static observedAttributes: string[];
|
|
19
19
|
connectedCallback(): void;
|
|
20
20
|
disconnectedCallback(): void;
|
|
21
|
-
attributeChangedCallback(): void;
|
|
21
|
+
attributeChangedCallback(_name: string, oldValue: string | null, newValue: string | null): void;
|
|
22
22
|
/** Forgets the acknowledgement and shows the full notice again. */
|
|
23
23
|
reset(): void;
|
|
24
24
|
get disclosure(): Disclosure | null;
|
package/dist/elements.d.ts
CHANGED
|
@@ -18,7 +18,7 @@ declare class WitnessNoticeElement extends BaseElement {
|
|
|
18
18
|
static observedAttributes: string[];
|
|
19
19
|
connectedCallback(): void;
|
|
20
20
|
disconnectedCallback(): void;
|
|
21
|
-
attributeChangedCallback(): void;
|
|
21
|
+
attributeChangedCallback(_name: string, oldValue: string | null, newValue: string | null): void;
|
|
22
22
|
/** Forgets the acknowledgement and shows the full notice again. */
|
|
23
23
|
reset(): void;
|
|
24
24
|
get disclosure(): Disclosure | null;
|