@eifi1/ui-kit 0.27.1 → 0.28.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/README.md +7 -5
  2. package/dist/chart.d.ts +1 -2
  3. package/dist/components/amount-input.d.ts +1 -2
  4. package/dist/components/button-group.d.ts +1 -2
  5. package/dist/components/calculator.d.ts +1 -2
  6. package/dist/components/confirm-dialog.d.ts +1 -2
  7. package/dist/components/copy-button.d.ts +1 -2
  8. package/dist/components/danger-confirm.d.ts +1 -2
  9. package/dist/components/facing-pair.d.ts +1 -2
  10. package/dist/components/file-button.d.ts +1 -2
  11. package/dist/components/file-dropzone.d.ts +1 -2
  12. package/dist/components/form-actions.d.ts +1 -2
  13. package/dist/components/iban-input.d.ts +1 -2
  14. package/dist/components/language-select.d.ts +1 -2
  15. package/dist/components/legal-page.d.ts +267 -0
  16. package/dist/components/legal-page.js +272 -0
  17. package/dist/components/legal-page.js.map +1 -0
  18. package/dist/components/legal.d.ts +70 -87
  19. package/dist/components/legal.js +232 -11
  20. package/dist/components/legal.js.map +1 -1
  21. package/dist/components/money-field.d.ts +1 -2
  22. package/dist/components/number-field.d.ts +1 -2
  23. package/dist/components/number-input.d.ts +1 -2
  24. package/dist/components/numpad-sheet.d.ts +1 -2
  25. package/dist/components/phone-input.d.ts +1 -2
  26. package/dist/components/series-chart.d.ts +1 -2
  27. package/dist/components/settings-fields.d.ts +1 -2
  28. package/dist/components/share-card.d.ts +1 -2
  29. package/dist/components/text-link.d.ts +1 -2
  30. package/dist/components/time-input.d.ts +1 -2
  31. package/dist/components/translation-review.d.ts +2 -1
  32. package/dist/components/translation-review.js.map +1 -1
  33. package/dist/components/ui.d.ts +1 -2
  34. package/dist/feedback/feedback-attachment.d.ts +1 -2
  35. package/dist/feedback/feedback-context.d.ts +1 -2
  36. package/dist/feedback/feedback-crash.d.ts +1 -2
  37. package/dist/feedback/feedback-dialog.d.ts +1 -2
  38. package/dist/feedback/feedback-inbox.d.ts +1 -2
  39. package/dist/feedback/feedback-labels.d.ts +1 -2
  40. package/dist/feedback/feedback-menu.d.ts +1 -2
  41. package/dist/feedback/feedback-record.d.ts +1 -2
  42. package/dist/feedback/feedback-row-detail.d.ts +1 -2
  43. package/dist/feedback/feedback-status-undo.d.ts +1 -2
  44. package/dist/feedback/feedback-submit.d.ts +1 -2
  45. package/dist/feedback/feedback-swipe.d.ts +1 -2
  46. package/dist/feedback/feedback-table.d.ts +1 -2
  47. package/dist/feedback/feedback-thread.d.ts +1 -2
  48. package/dist/feedback.d.ts +1 -2
  49. package/dist/hooks/use-file-drop.d.ts +1 -2
  50. package/dist/hooks/use-noindex.d.ts +26 -0
  51. package/dist/hooks/use-noindex.js +18 -0
  52. package/dist/hooks/use-noindex.js.map +1 -0
  53. package/dist/i18n/defaults.d.ts +1 -2
  54. package/dist/i18n/german.d.ts +1 -2
  55. package/dist/i18n/german.js +95 -1
  56. package/dist/i18n/german.js.map +1 -1
  57. package/dist/i18n/kit-labels.d.ts +1 -2
  58. package/dist/i18n/kit-labels.js.map +1 -1
  59. package/dist/i18n/languages.d.ts +1 -2
  60. package/dist/i18n/locales/de-CH.d.ts +1 -2
  61. package/dist/i18n/locales/en.d.ts +1 -2
  62. package/dist/i18n/locales/es.d.ts +1 -2
  63. package/dist/i18n/locales/es.js +95 -1
  64. package/dist/i18n/locales/es.js.map +1 -1
  65. package/dist/i18n/locales/fr.d.ts +1 -2
  66. package/dist/i18n/locales/fr.js +97 -1
  67. package/dist/i18n/locales/fr.js.map +1 -1
  68. package/dist/i18n/locales/hu.d.ts +1 -2
  69. package/dist/i18n/locales/hu.js +98 -1
  70. package/dist/i18n/locales/hu.js.map +1 -1
  71. package/dist/i18n/locales/it.d.ts +1 -2
  72. package/dist/i18n/locales/it.js +98 -1
  73. package/dist/i18n/locales/it.js.map +1 -1
  74. package/dist/i18n/locales/zh.d.ts +1 -2
  75. package/dist/i18n/locales/zh.js +95 -1
  76. package/dist/i18n/locales/zh.js.map +1 -1
  77. package/dist/i18n/review.d.ts +24 -5
  78. package/dist/i18n/review.js +26 -3
  79. package/dist/i18n/review.js.map +1 -1
  80. package/dist/index.d.ts +5 -4
  81. package/dist/index.js +23 -1
  82. package/dist/index.js.map +1 -1
  83. package/dist/{kit-labels-DQg82eHB.d.ts → kit-labels-Du0uHBq4.d.ts} +342 -4
  84. package/dist/lib/translation-review.d.ts +26 -3
  85. package/dist/lib/translation-review.js +10 -2
  86. package/dist/lib/translation-review.js.map +1 -1
  87. package/dist/rhf/fields.d.ts +1 -2
  88. package/dist/rhf/form.d.ts +1 -2
  89. package/dist/rhf.d.ts +1 -2
  90. package/dist/shell/app-shell.d.ts +1 -2
  91. package/dist/shell/top-bar-brand.d.ts +1 -2
  92. package/dist/shell.d.ts +1 -2
  93. package/dist/wizard/stepper-nav.d.ts +1 -2
  94. package/dist/wizard.d.ts +1 -2
  95. package/package.json +1 -1
  96. package/src/components/legal-page.tsx +601 -0
  97. package/src/components/legal.tsx +540 -46
  98. package/src/components/translation-review.tsx +2 -1
  99. package/src/hooks/use-noindex.ts +37 -0
  100. package/src/i18n/german.ts +91 -0
  101. package/src/i18n/kit-labels.tsx +4 -1
  102. package/src/i18n/locales/es.ts +91 -0
  103. package/src/i18n/locales/fr.ts +93 -0
  104. package/src/i18n/locales/hu.ts +94 -0
  105. package/src/i18n/locales/it.ts +94 -0
  106. package/src/i18n/locales/zh.ts +91 -0
  107. package/src/i18n/review.ts +57 -3
  108. package/src/index.ts +41 -2
  109. package/src/lib/translation-review.ts +43 -4
@@ -1,5 +1,5 @@
1
1
  import * as react from 'react';
2
- import { InputHTMLAttributes, ReactNode, AnchorHTMLAttributes, Ref, ReactElement, ButtonHTMLAttributes, SelectHTMLAttributes, ComponentPropsWithoutRef, TextareaHTMLAttributes, RefObject } from 'react';
2
+ import { InputHTMLAttributes, ReactNode, AnchorHTMLAttributes, Ref, ReactElement, ButtonHTMLAttributes, SelectHTMLAttributes, ComponentPropsWithoutRef, TextareaHTMLAttributes, RefObject, MouseEvent } from 'react';
3
3
  import { d as DataTableColumn, f as DataTableLabels } from './data-table-labels-DUELeXpa.js';
4
4
  import { MiniCalendarLabels, WeekDay } from './components/mini-calendar.js';
5
5
  import { CalendarHeatmapLabels } from './components/calendar-heatmap.js';
@@ -42,7 +42,6 @@ import { AuthedImageLabels } from './components/authed-image.js';
42
42
  import { ImageGridLabels } from './components/image-grid.js';
43
43
  import { LightboxLabels } from './components/lightbox.js';
44
44
  import { WriteLockLabels } from './components/write-lock.js';
45
- import { LegalLabels } from './components/legal.js';
46
45
  import { RoleDefinition, AccountStateLabels } from './components/account-chips.js';
47
46
  import { ReauthDialogLabels } from './components/reauth-dialog.js';
48
47
  import { ServerWakeLabels } from './components/server-wake.js';
@@ -4733,6 +4732,342 @@ interface FormActionsProps extends Omit<ComponentPropsWithoutRef<"div">, "childr
4733
4732
  */
4734
4733
  declare function FormActions({ onCancel, onSubmit, submitLabel, cancelLabel, pendingLabel, submitIcon: SubmitIcon, submitProps, pending, submitDisabled, submitDisabledReason, commit, submitVariant, cancelVariant, size, destructive, start: startSlot, align, placement: placementProp, stickyWithin, bleed, form, submitShortcut, submitShortcutHint, children, className, style, ...rest }: FormActionsProps): react.JSX.Element;
4735
4734
 
4735
+ /**
4736
+ * The legal pages — Imprint, Privacy Policy, Terms — for every app.
4737
+ *
4738
+ * 0.19 (docs/i18n-harmonization.md H10): keksdose and kastlan each carried the same
4739
+ * shell, written twice: a back link, the title, a "closed beta, not yet reviewed by a
4740
+ * lawyer" notice, sections of heading + running text, and kastlan's row of links to the
4741
+ * three pages with the current one marked. That shape moved here; the words stayed in
4742
+ * each app.
4743
+ *
4744
+ * 0.28 (docs/legal-harmonization.md) reverses the second half: the wording that is the
4745
+ * same in all three apps is the kit's too, in all seven languages, so there is ONE text
4746
+ * to change after the lawyer's review instead of three apps drifting apart sentence by
4747
+ * sentence. This module holds the labels (every kit-owned legal word, §4.3/§4.4), the
4748
+ * column (`LegalLayout`), the section (`LegalSection`, now numbered and cross-referenced
4749
+ * inside a `LegalPage`), the links row and the public footer. The page frame, the
4750
+ * kit-owned sections and the terms checkbox are in `./legal-page`.
4751
+ *
4752
+ * `LegalLayout` stays a CONTENT COLUMN, not a page: before 0.28 keksdose showed it inside
4753
+ * its public landing header and footer and kastlan inside `AuthLayout`. `LegalPage` is
4754
+ * the frame around it that the contract (§3.2) settled on — keksdose's.
4755
+ */
4756
+ /** The three pages, by the key every app uses for them (§4.1). Kurvenschmiede's
4757
+ * `imprint` became `impressum`. */
4758
+ type LegalPageKey = "impressum" | "privacy" | "terms";
4759
+ /** The three routes (§3.1): one per page, the language from i18n, no per-language URLs. */
4760
+ declare const LEGAL_HREFS: Readonly<Record<LegalPageKey, string>>;
4761
+ /**
4762
+ * Who runs the app — the values the kit's legal sections are filled in with (§5).
4763
+ *
4764
+ * The kit holds NO personal data: every app passes the same values once, to
4765
+ * {@link LegalPage}'s `operator`. Plain strings, so the app's config or env can hold them.
4766
+ */
4767
+ interface LegalOperator {
4768
+ /** The operator's name, as the imprint prints it. */
4769
+ name: string;
4770
+ /** "9470"-shaped; printed before the city. */
4771
+ postalCode: string;
4772
+ /** The place — the imprint's address line and the terms' place of jurisdiction. */
4773
+ city: string;
4774
+ /** The canton or state, abbreviated as the place of jurisdiction writes it: "SG". */
4775
+ region: string;
4776
+ /**
4777
+ * ISO 3166-1 alpha-2: "CH". A CODE, not a name — the kit names it in the page's
4778
+ * language (`Intl.DisplayNames`, see `countryName`), so "Switzerland", "Schweiz",
4779
+ * "Suisse" and "瑞士" all come from one value.
4780
+ */
4781
+ country: string;
4782
+ /** The contact address the imprint and the privacy policy print. */
4783
+ email: string;
4784
+ /**
4785
+ * The language whose version of the legal texts is BINDING ("de-CH"), a BCP 47 code
4786
+ * (0.28.1, Marcel 2026-10-05). The lawyer reviews that one; the others are translations
4787
+ * for convenience. With it, {@link LegalPage} shows a note on every page read in
4788
+ * another language, and the terms' `language` section says which version prevails.
4789
+ * Only the language subtag counts: "de-CH" and "de" are the same language here.
4790
+ */
4791
+ bindingLanguage?: string;
4792
+ }
4793
+ /**
4794
+ * The operator as the kit's texts read it: {@link LegalOperator} with `country` already
4795
+ * NAMED in the page's language ("Schweiz", not "CH").
4796
+ *
4797
+ * The label functions take this rather than the code so they stay pure string functions
4798
+ * of plain values, like every other function label in the kit: a catalogue never calls
4799
+ * `Intl`, and a review row can be rendered from placeholders (`{{country}}`).
4800
+ */
4801
+ type LegalOperatorText = Readonly<Record<keyof LegalOperator, string>>;
4802
+ /** The language subtag of a BCP 47 code, lower-cased: "de-CH" → "de". */
4803
+ declare function baseLanguage(code: string): string;
4804
+ /** @internal The operator as the texts read it: its country named in `locale` (English
4805
+ * without one — `countryName`'s rule, so an app that set no locale reads English). */
4806
+ declare function legalOperatorText(operator: LegalOperator, locale?: string): LegalOperatorText;
4807
+ /** A kit section whose text is fixed: a heading and one body. */
4808
+ interface LegalTextSectionLabels {
4809
+ title: string;
4810
+ body: string;
4811
+ }
4812
+ /** A kit section whose text names the operator (§4.3 `{name}`, `{email}`, …). */
4813
+ interface LegalOperatorSectionLabels {
4814
+ title: string;
4815
+ /** Called with the operator, its country already named in the page's language. Line
4816
+ * breaks are kept (`white-space: pre-line`): an address is plain lines. */
4817
+ body: (operator: LegalOperatorText) => string;
4818
+ }
4819
+ /** A kit section with an app slot (or a list) between its two parts. */
4820
+ interface LegalFramedSectionLabels {
4821
+ title: string;
4822
+ /** Before the app's part. */
4823
+ lead: string;
4824
+ /** After it. */
4825
+ tail: string;
4826
+ }
4827
+ /**
4828
+ * Every word of the legal pages that is the kit's — docs/legal-harmonization.md §4.3 and
4829
+ * §4.4, verbatim. English, British spelling; the other six languages are in the
4830
+ * catalogues (`@eifi1/ui-kit/i18n/<code>`).
4831
+ *
4832
+ * Keys follow the contract: `sections.<page>.<section key>`, the section keys being
4833
+ * keksdose's (`legal_basis`, not `legalBasis`), because the same key is the section's
4834
+ * `id` (`/privacy#legal_basis`) and the app's own sections sit beside these under the
4835
+ * same names in its catalogue. Titles carry NO number: {@link LegalPage} numbers the
4836
+ * privacy and terms sections in render order (§4.1).
4837
+ */
4838
+ interface LegalLabels {
4839
+ /** The accessible name of {@link LegalLinks}' and {@link LegalFooter}'s `<nav>`. */
4840
+ navLabel: string;
4841
+ /** The short labels of the three links, everywhere the links appear (§3.3). */
4842
+ links: Record<LegalPageKey, string>;
4843
+ /** The pages' titles — the `<h1>`, and the links of the terms checkbox. */
4844
+ titles: Record<LegalPageKey, string>;
4845
+ /** The back link above the title: "← Back to home". */
4846
+ backHome: string;
4847
+ /**
4848
+ * The terms checkbox (§3.4) — ONE template with `{terms}` and `{privacy}`, which
4849
+ * become the links (named with `titles`). Not a prefix plus a joiner: a language puts
4850
+ * the links where its grammar wants them, articles included, and nothing is added
4851
+ * around a placeholder — Italian elides, "e l’{privacy}", with no space.
4852
+ */
4853
+ accept: string;
4854
+ /** The notice under the title (§3.2): `beta` on the imprint and the terms, `privacy`
4855
+ * on the privacy policy. */
4856
+ notice: {
4857
+ beta: string;
4858
+ privacy: string;
4859
+ };
4860
+ /**
4861
+ * 0.28.1: on a page read in another language than the operator's `bindingLanguage` —
4862
+ * `note` under the title, `show` on the button that switches to the binding version
4863
+ * (when the app passes `onShowBindingLanguage`). `o.bindingLanguage` is the binding
4864
+ * language's NAME in the reader's language ("German", "allemand").
4865
+ */
4866
+ translation: {
4867
+ note: (o: LegalOperatorText) => string;
4868
+ show: (o: LegalOperatorText) => string;
4869
+ };
4870
+ /** The kit's sections (§4.3), by page and section key. */
4871
+ sections: {
4872
+ impressum: {
4873
+ operator: LegalOperatorSectionLabels;
4874
+ contact: LegalOperatorSectionLabels;
4875
+ disclaimer: LegalTextSectionLabels;
4876
+ };
4877
+ privacy: {
4878
+ controller: LegalOperatorSectionLabels;
4879
+ /** The app's paragraph follows the body (§4.2): consent, where an app relies on it. */
4880
+ legal_basis: LegalTextSectionLabels;
4881
+ /** `lead`, then the app's entries as a list, then `tail`, then the app's paragraph. */
4882
+ browser: LegalFramedSectionLabels;
4883
+ /** `lead` (the rights), then the app's paragraph (export, deletion), then `tail`
4884
+ * (the supervisory authorities). */
4885
+ rights: LegalFramedSectionLabels;
4886
+ contact: LegalOperatorSectionLabels;
4887
+ };
4888
+ terms: {
4889
+ warranty: LegalTextSectionLabels;
4890
+ liability: LegalTextSectionLabels;
4891
+ changes: LegalTextSectionLabels;
4892
+ /** 0.28.1: which language's version prevails — `o.bindingLanguage`, named. */
4893
+ language: LegalOperatorSectionLabels;
4894
+ /** The place of jurisdiction is the operator's `{city} ({region}), {country}`. */
4895
+ law: LegalOperatorSectionLabels;
4896
+ };
4897
+ };
4898
+ }
4899
+ declare const DEFAULT_LEGAL_LABELS: LegalLabels;
4900
+ /** The `legal` namespace, resolved: defaults < provider < `labels` prop. The prop may be
4901
+ * partial at every depth (`{ titles: { terms: "…" } }`), as the provider's is. */
4902
+ declare function useLegalLabels(labels?: LabelOverride<LegalLabels>): LegalLabels;
4903
+ /** Where a `{ref:key}` points: the section's number on a numbered page, else its heading. */
4904
+ interface LegalRefTarget {
4905
+ number?: number;
4906
+ heading: ReactNode;
4907
+ }
4908
+ /** @internal Set by `LegalPage` around its column; `null` outside one. */
4909
+ interface LegalPageContextValue {
4910
+ page: LegalPageKey;
4911
+ /** The operator with its country named — what the kit sections are filled in with. */
4912
+ operator: LegalOperatorText;
4913
+ /** The heading level of a section that does not choose one: one below the title. */
4914
+ sectionHeading: "h2" | "h3";
4915
+ /** Every section's key, in render order — known BEFORE any section renders, so a
4916
+ * reference can point forward (keksdose's section 2 refers to section 10). */
4917
+ targets: ReadonlyMap<string, LegalRefTarget>;
4918
+ }
4919
+ /** @internal */
4920
+ declare const LegalPageContext: react.Context<LegalPageContextValue | null>;
4921
+ /** @internal The place `LegalPage` gave one section: its key and its number. Reset to
4922
+ * `null` inside a section, so a section nested in another's children takes neither. */
4923
+ interface LegalSectionSlot {
4924
+ id?: string;
4925
+ number?: number;
4926
+ }
4927
+ /** @internal */
4928
+ declare const LegalSlotContext: react.Context<LegalSectionSlot | null>;
4929
+ /** @internal Once per message. */
4930
+ declare function warnLegalOnce(message: string): void;
4931
+ /**
4932
+ * `text` with every `{ref:key}` replaced by a link to `#key` that reads the section's
4933
+ * number — the words around it stay the app's ("see section {ref:retention}", "siehe
4934
+ * Abschnitt {ref:retention}"), so each language keeps its grammar (§4.1). On the imprint,
4935
+ * which is not numbered, the link reads the section's heading instead.
4936
+ *
4937
+ * Outside a {@link LegalPage} the text is returned as it is: there is no order to count.
4938
+ * A key the page has no section for stays visible as the raw token — a broken reference
4939
+ * an app test can find (`not.toHaveTextContent("{ref:")`), not a silently wrong number.
4940
+ */
4941
+ declare function resolveLegalRefs(text: string, page: LegalPageContextValue | null): ReactNode;
4942
+ /** @internal Running text — one translation string — with its line breaks kept and its
4943
+ * `{ref:key}` tokens resolved. */
4944
+ declare function LegalText({ text, className }: {
4945
+ text: string;
4946
+ className?: string;
4947
+ }): react.JSX.Element;
4948
+ interface LegalLink {
4949
+ href: string;
4950
+ /** "Imprint", "Privacy Policy", "Terms". */
4951
+ label: ReactNode;
4952
+ }
4953
+ interface LegalLinksProps {
4954
+ /** Default (0.28): the three routes, `/impressum`, `/privacy` and `/terms`, with the
4955
+ * kit's short link labels (`legal.links`), in the contract's order. */
4956
+ links?: readonly LegalLink[];
4957
+ /** The page being shown; its link is marked `aria-current="page"`. Usually the
4958
+ * router's pathname. */
4959
+ currentHref?: string;
4960
+ /** `false` renders the links without the `<nav>` landmark — inside `AuthLayout`'s
4961
+ * `footer` or `TopBarActionMenu`'s `footer`, which are named `<nav>`s already. The row
4962
+ * keeps its spacing and `className` either way (0.27.1: it used to return the bare
4963
+ * links, so in a plain container — Kurvenschmiede's account-menu `<li>` — they ran
4964
+ * together as "ImpressumDatenschutzerklärungNutz…" and overflowed). Default true. */
4965
+ nav?: boolean;
4966
+ /** Called on a click on any of the links, before it navigates — an account menu closes
4967
+ * itself here (0.28.1, keksdose: it had to catch the click on a wrapping `<div>`). */
4968
+ onLinkClick?: (event: MouseEvent<HTMLAnchorElement>) => void;
4969
+ labels?: LabelOverride<LegalLabels>;
4970
+ className?: string;
4971
+ }
4972
+ /**
4973
+ * The legal pages as a row of quiet links, the one you are on marked (kastlan's
4974
+ * `LegalLinks`). Wraps on a phone.
4975
+ *
4976
+ * 0.28: `·` separators between the links, keksdose's footer style, wherever the links
4977
+ * appear — the account menu included (§3.3). The dots are `aria-hidden`: a screen reader
4978
+ * already hears three links, and "middle dot" between them is noise. They are flex items
4979
+ * of the row like the links, so the row's gap spaces them evenly.
4980
+ */
4981
+ declare function LegalLinks({ links, currentHref, nav, onLinkClick, labels: labelsProp, className, }: LegalLinksProps): react.JSX.Element;
4982
+ interface LegalFooterProps {
4983
+ /** Under the links, centred — the app's tagline (keksdose: "Self-hosted household
4984
+ * budgeting & bookkeeping."). */
4985
+ children?: ReactNode;
4986
+ /** Default: the three routes with the kit's link labels — see {@link LegalLinks}. */
4987
+ links?: readonly LegalLink[];
4988
+ /** Marks that link `aria-current="page"`. {@link LegalPage}'s default footer passes
4989
+ * its own page. */
4990
+ currentHref?: string;
4991
+ /**
4992
+ * Default true: the footer is a `<footer>`. `false` draws a `<div>` — for a host that is
4993
+ * a footer already: `AuthLayout`'s `footer` slot is one, and HTML forbids a footer inside
4994
+ * a footer (0.28.1, kastlan). On an `AuthLayout` page the usual choice is simpler still:
4995
+ * `footer={<LegalLinks nav={false} />}` with `footerLabel` set to the kit's `navLabel`
4996
+ * ({@link useLegalLabels}).
4997
+ */
4998
+ landmark?: boolean;
4999
+ className?: string;
5000
+ labels?: LabelOverride<LegalLabels>;
5001
+ }
5002
+ /**
5003
+ * The public footer (§3.3): the three links, centred, with their separators, in a
5004
+ * `<nav aria-label="Legal">` — on the landing or home page, every signed-out page the app
5005
+ * has, the legal pages and the 404. The rule behind it: from every page a signed-out
5006
+ * visitor can reach, the three links are one click away.
5007
+ *
5008
+ * keksdose's `SiteFooter` (features/landing/site-footer.tsx), which carried them on its
5009
+ * landing, auth, legal and 404 pages; kastlan and Kurvenschmiede had them on some pages
5010
+ * only. Its palette classes (`border-slate-200 bg-white dark:…`) became the surface and
5011
+ * border tokens, so it follows the theme like the rest of the kit.
5012
+ */
5013
+ declare function LegalFooter({ children, links, currentHref, landmark, className, labels }: LegalFooterProps): react.JSX.Element;
5014
+ interface LegalSectionProps {
5015
+ heading: ReactNode;
5016
+ /** Running text. Line breaks in it are kept (`white-space: pre-line`), so a
5017
+ * translation can hold an address or a list as plain lines. Inside a
5018
+ * {@link LegalPage}, `{ref:key}` becomes the number of section `key`, linked. */
5019
+ body?: string;
5020
+ /** Anything richer than plain text — links, a list — after `body`. A plain string
5021
+ * here has its `{ref:key}` tokens resolved too. */
5022
+ children?: ReactNode;
5023
+ /**
5024
+ * The section's `id`, for a link to it from elsewhere. Inside a {@link LegalPage} it
5025
+ * defaults to the element's React `key` — keksdose's
5026
+ * `SECTIONS.map((s) => <LegalSection key={s} … />)` gets `id="retention"` with
5027
+ * nothing added — and it is the key a `{ref:…}` names.
5028
+ */
5029
+ id?: string;
5030
+ /** The heading's element. Default `h2` under the layout's `h1` (inside a
5031
+ * `LegalPage`, one level below its title). */
5032
+ headingAs?: "h2" | "h3";
5033
+ }
5034
+ /**
5035
+ * One section: heading and running text.
5036
+ *
5037
+ * 0.28, inside a {@link LegalPage}: its `id` (the `key` unless given), its number on the
5038
+ * privacy policy and the terms ("3. Legal basis" — titles carry no number, §4.1), and
5039
+ * `{ref:key}` resolution in `body`. Outside one it is exactly the 0.19 section.
5040
+ */
5041
+ declare function LegalSection({ heading, body, children, id: idProp, headingAs }: LegalSectionProps): react.JSX.Element;
5042
+ interface LegalLayoutProps {
5043
+ /** "Imprint", "Privacy Policy", "Terms". */
5044
+ title: ReactNode;
5045
+ /** Above the title — the app's "← Back" link (`<TextLink icon={ArrowLeft}>`). Inside
5046
+ * a {@link LegalPage}, "← Back to home". */
5047
+ back?: ReactNode;
5048
+ /**
5049
+ * A notice under the title, as a warning banner with `role="note"` — page furniture,
5050
+ * not an alert. Per page, not per layout: the privacy page says something more precise
5051
+ * than the others (its technical sections describe running code).
5052
+ */
5053
+ notice?: ReactNode;
5054
+ /** 0.28.1: under the title, before the notice — {@link LegalPage}'s note that this
5055
+ * page is a translation and which language is binding. */
5056
+ translationNote?: ReactNode;
5057
+ /** The sections — {@link LegalSection}s. */
5058
+ children: ReactNode;
5059
+ /** The three pages, linked at the end of the column with the current one marked.
5060
+ * Leave out when the page's chrome already shows them (a {@link LegalFooter}). */
5061
+ links?: readonly LegalLink[];
5062
+ currentHref?: string;
5063
+ /** Default `h1`: the page's heading. */
5064
+ headingAs?: "h1" | "h2";
5065
+ /** Extra classes on the column — `px-0 py-0` inside a chrome that pads already. */
5066
+ className?: string;
5067
+ labels?: LabelOverride<LegalLabels>;
5068
+ }
5069
+ declare function LegalLayout({ title, back, notice, translationNote, children, links, currentHref, headingAs: Heading, className, labels, }: LegalLayoutProps): react.JSX.Element;
5070
+
4736
5071
  /**
4737
5072
  * Who holds one record, and the owner's every way of changing that — Kurvenschmiede's
4738
5073
  * `features/sharing/share-dialog.tsx` and keksdose's `features/budgets/budget-share-card.tsx`,
@@ -5289,7 +5624,10 @@ interface UiKitLabels {
5289
5624
  /** 0.19.0: the translation-review parts (`TranslationReviewPanel`, its editor, chip,
5290
5625
  * progress, locale tabs and export) — keksdose's /translations, for every app. */
5291
5626
  translationReview: TranslationReviewLabels;
5292
- /** 0.19.0: `LegalLinks`' navigation name — the legal pages' shell, for every app. */
5627
+ /** 0.19.0: `LegalLinks`' navigation name. 0.28.0: every kit-owned word of the legal
5628
+ * pages — the link labels, titles, back link, terms checkbox and notices, and the
5629
+ * sections that are the same in every app, filled in with the app's operator
5630
+ * (docs/legal-harmonization.md §4.3/§4.4). */
5293
5631
  legal: LegalLabels;
5294
5632
  /** 0.22.0: the screen-reader words of `Input` / `Textarea`'s `showCount` counter. */
5295
5633
  characterCount: CharacterCountLabels;
@@ -5500,4 +5838,4 @@ declare function useKitFileLabels(prop?: Partial<FileLabels>): FileLabels;
5500
5838
  */
5501
5839
  declare function missingKitLabels(labels: UiKitLabelOverrides | undefined, reference: UiKitLabels): string[];
5502
5840
 
5503
- export { type FeedbackContext as $, type FeedbackAttachmentError as A, type FeedbackAttachmentErrorInfo as B, ChatComposer as C, DEFAULT_ATTACHMENT_ACCEPT as D, FeedbackAttachmentField as E, FEEDBACK_ATTACHMENT_ACCEPT as F, type FeedbackAttachmentFieldLabels as G, type FeedbackAttachmentFieldMultipleProps as H, type FeedbackAttachmentFieldProps as I, type FeedbackAttachmentFieldRefsProps as J, type FeedbackAttachmentFieldSingleProps as K, type FeedbackAttachmentLabels as L, type FeedbackAttachmentRef as M, type FeedbackAttachmentRefsError as N, FeedbackAwaitingToggle as O, type FeedbackAwaitingToggleProps as P, type FeedbackCategory as Q, FeedbackCategoryBadge as R, type FeedbackCategoryLabels as S, type FeedbackCategoryOption as T, type FeedbackColumnsOptions as U, FeedbackComposer as V, type FeedbackComposerAttachment as W, type FeedbackComposerHandle as X, type FeedbackComposerLabels as Y, type FeedbackComposerProps as Z, type FeedbackComposerSlotContext as _, type ChatComposerHandle as a, feedbackAttachmentUrls as a$, FeedbackContextBox as a0, type FeedbackContextBoxProps as a1, type FeedbackContextInput as a2, type FeedbackContextLabels as a3, FeedbackDetail as a4, type FeedbackDetailLabels as a5, type FeedbackDetailPatch as a6, FeedbackDetailSection as a7, type FeedbackDetailUpdate as a8, FeedbackDialog as a9, FeedbackStatusBadge as aA, type FeedbackStatusChange as aB, type FeedbackStatusLabels as aC, type FeedbackStatusMutate as aD, type FeedbackStatusPatch as aE, type FeedbackStatusRow as aF, FeedbackStatusTransitions as aG, type FeedbackStatusUndoOptions as aH, FeedbackSubject as aI, type FeedbackSubjectProps as aJ, type FeedbackSubmission as aK, type FeedbackSubmitHint as aL, type FeedbackSubmitter as aM, type FeedbackTableRow as aN, FeedbackThread as aO, type FeedbackThreadAttachment as aP, type FeedbackThreadEvent as aQ, type FeedbackThreadItem as aR, type FeedbackThreadLabels as aS, type FeedbackThreadMessage as aT, type FeedbackThreadProps as aU, type FeedbackToastLabels as aV, type FeedbackUpload as aW, type UseFeedbackColumnsOptions as aX, appendRework as aY, attachmentName as aZ, feedbackAttachmentLine as a_, type FeedbackDialogLabels as aa, type FeedbackDialogMultipleProps as ab, type FeedbackDialogProps as ac, type FeedbackDialogSingleProps as ad, type FeedbackDialogTextLabels as ae, FeedbackEmptyState as af, type FeedbackEmptyStateProps as ag, type FeedbackEnvironment as ah, FeedbackMenu as ai, type FeedbackMenuLabels as aj, type FeedbackMenuProps as ak, FeedbackMobileCard as al, type FeedbackMobileCardProps as am, type FeedbackMultipleSubmission as an, type FeedbackNoteAttachment as ao, FeedbackNoteEditor as ap, type FeedbackPageLabels as aq, FeedbackProse as ar, type FeedbackRecord as as, type FeedbackRenderDate as at, FeedbackReworkSection as au, type FeedbackReworkSectionProps as av, type FeedbackRowAccess as aw, FeedbackRowDetail as ax, type FeedbackRowDetailProps as ay, type FeedbackStatus as az, type ChatComposerLabels as b, type ConfirmProviderProps as b$, feedbackCategoryRank as b0, feedbackColumns as b1, feedbackContext as b2, feedbackEnvironment as b3, feedbackMobileGroupBy as b4, feedbackPageHref as b5, feedbackPagePath as b6, feedbackPageUrl as b7, feedbackRowAccess as b8, feedbackSubmitter as b9, type ButtonVariant as bA, type CalculatorLabels as bB, Card as bC, CardAction as bD, type CardActionProps as bE, CardContent as bF, type CardContentProps as bG, type CardDensity as bH, CardDescription as bI, type CardDescriptionProps as bJ, CardFooter as bK, type CardFooterProps as bL, CardHeader as bM, type CardHeaderProps as bN, type CardProps as bO, CardTitle as bP, type CardTitleLevel as bQ, type CardTitleProps as bR, type CardTone as bS, type CharacterCountLabels as bT, type ChartTooltipPlacement as bU, type ComboboxLabels as bV, type CommonLabels as bW, type ConfirmDialogLabels as bX, type ConfirmFn as bY, type ConfirmOptions as bZ, ConfirmProvider as b_, feedbackSubmitterEmail as ba, isFeedbackAwaiting as bb, isImageAttachment as bc, nextFeedbackStatus as bd, pastedName as be, replaceDescription as bf, reworkCount as bg, selectableFeedbackStatuses as bh, splitBodyAttachments as bi, splitDescription as bj, useFeedbackCategoryLabels as bk, useFeedbackColumns as bl, useFeedbackDetailLabels as bm, useFeedbackPageLabels as bn, useFeedbackRenderDate as bo, useFeedbackStatusLabels as bp, useFeedbackStatusUndo as bq, useFeedbackToastLabels as br, visibleFeedbackStatuses as bs, type AppShellLabels as bt, Button as bu, type ButtonClassesOptions as bv, type ButtonLinkProps as bw, type ButtonProps as bx, type ButtonSize as by, type ButtonTone as bz, type ChatComposerProps as c, type FormActionsPlacement as c$, type ConfirmTone as c0, CopyButton as c1, type CopyButtonLabels as c2, type CopyButtonProps as c3, type CurrencyLabels as c4, CurrentPasswordInput as c5, type CurrentPasswordInputLabels as c6, type CurrentPasswordInputProps as c7, DEFAULT_APP_SHELL_LABELS as c8, DEFAULT_CALCULATOR_LABELS as c9, EmptyState as cA, type EmptyStateProps as cB, FIELD_BASE as cC, FIELD_DISPLAY as cD, FIELD_FLOATING_PAD as cE, FIELD_INVALID as cF, FIELD_TRIGGER as cG, FIELD_WRITABLE_LOOK as cH, FLOATING_INPUT_CLASS as cI, FLOATING_LABEL_CLASS as cJ, FieldChevron as cK, type FieldChevronProps as cL, FieldHint as cM, type FieldHintProps as cN, FileButton as cO, type FileButtonProps as cP, type FileLabels as cQ, type FilePickerLabels as cR, type FileRejection as cS, type FileRejectionReason as cT, type FileScreenOptions as cU, FloatingField as cV, type FloatingFieldProps as cW, FormActions as cX, type FormActionsAlign as cY, type FormActionsDestructive as cZ, type FormActionsLabels as c_, DEFAULT_CHARACTER_COUNT_LABELS as ca, DEFAULT_COMBOBOX_LABELS as cb, DEFAULT_COMMON_LABELS as cc, DEFAULT_CONFIRM_DIALOG_LABELS as cd, DEFAULT_COPY_BUTTON_LABELS as ce, DEFAULT_CURRENCY_LABELS as cf, DEFAULT_DANGER_CONFIRM_LABELS as cg, DEFAULT_DATE_PICKER_LABELS as ch, DEFAULT_FILE_LABELS as ci, DEFAULT_FILE_PICKER_LABELS as cj, DEFAULT_FORM_ACTIONS_LABELS as ck, DEFAULT_IBAN_INPUT_LABELS as cl, DEFAULT_MULTI_SELECT_LABELS as cm, DEFAULT_PASSWORD_REVEAL_LABELS as cn, DEFAULT_PHONE_INPUT_LABELS as co, DEFAULT_PICKER_SHEET_LABELS as cp, DEFAULT_SHARE_CARD_LABELS as cq, DEFAULT_SWIPEABLE_ROW_LABELS as cr, DEFAULT_TABS_LABELS as cs, DEFAULT_TOP_BAR_LABELS as ct, DangerConfirm as cu, type DangerConfirmLabels as cv, type DangerConfirmProps as cw, type DangerConfirmValues as cx, type DangerConsequence as cy, type DatePickerLabels as cz, type ChatComposerSlotContext as d, UiKitProvider as d$, type FormActionsProps as d0, type FormActionsStickyWithin as d1, type FormActionsSubmitProps as d2, type FormActionsSubmitShortcut as d3, IbanInput as d4, type IbanInputLabels as d5, type IbanInputProps as d6, IconButton as d7, type IconButtonGlyphSize as d8, type IconButtonLinkProps as d9, type ShareCandidate as dA, ShareCard as dB, type ShareCardLabels as dC, type ShareCardProps as dD, ShareDialog as dE, type ShareDialogProps as dF, type ShareGrantee as dG, SharePanel as dH, type SharePanelProps as dI, type SharePendingGrant as dJ, type ShareRole as dK, Spinner as dL, type SpinnerProps as dM, type SwipeableRowLabels as dN, type TabItem as dO, Tabs as dP, type TabsLabels as dQ, type TabsProps as dR, Textarea as dS, type TextareaProps as dT, type TopBarLabels as dU, TypedConfirmField as dV, type TypedConfirmFieldLabels as dW, type TypedConfirmFieldProps as dX, type TypedMatch as dY, type UiKitLabelOverrides as dZ, type UiKitLabels as d_, type IconButtonProps as da, type IconButtonSize as db, type IconButtonTone as dc, type IconButtonToneColor as dd, type IconButtonVariant as de, Input as df, type InputProps as dg, type KitDateFormatContext as dh, type KitDateFormatter as di, type KitLinkComponent as dj, type KitLinkProps as dk, Label as dl, type LabelOverride as dm, type LabelProps as dn, type MultiSelectLabels as dp, PHONE_QUERY as dq, type PasswordRevealLabels as dr, PhoneInput as ds, type PhoneInputLabels as dt, type PhoneInputProps as du, type PickerSheetLabels as dv, type ResponsiveFormActionsPlacement as dw, Select as dx, type SelectProps as dy, type ShareAddRequest as dz, DEFAULT_FEEDBACK_ATTACHMENT_LABELS as e, type UiKitProviderProps as e0, type UseFilePickerOptions as e1, type UseFilePickerReturn as e2, buttonClasses as e3, formatFileSize as e4, matchesAccept as e5, missingKitLabels as e6, resolvePasswordRevealLabels as e7, typedMatches as e8, useConfirm as e9, useFilePicker as ea, useKitChartTooltipPlacement as eb, useKitDateFormatter as ec, useKitFileLabels as ed, useKitLabelOverrides as ee, useKitLabels as ef, useKitLink as eg, useKitLocale as eh, useKitWeekStart as ei, type FilePickHandler as ej, usePromisePending as ek, formatAccept as el, judgePick as em, screenFiles as en, summariseRejections as eo, DEFAULT_FEEDBACK_CATEGORY_LABELS as f, DEFAULT_FEEDBACK_COMPOSER_LABELS as g, DEFAULT_FEEDBACK_CONTEXT_LABELS as h, DEFAULT_FEEDBACK_DETAIL_LABELS as i, DEFAULT_FEEDBACK_DIALOG_LABELS as j, DEFAULT_FEEDBACK_MENU_LABELS as k, DEFAULT_FEEDBACK_PAGE_LABELS as l, DEFAULT_FEEDBACK_STATUS_LABELS as m, DEFAULT_FEEDBACK_THREAD_LABELS as n, DEFAULT_FEEDBACK_TOAST_LABELS as o, DEFAULT_MAX_ATTACHMENTS as p, DEFAULT_MAX_ATTACHMENT_BYTES as q, FEEDBACK_AUTHOR_EDITABLE_STATUSES as r, FEEDBACK_AWAITING_STATUSES as s, FEEDBACK_CATEGORY_META as t, FEEDBACK_CATEGORY_ORDER as u, FEEDBACK_PICKABLE_CATEGORIES as v, FEEDBACK_REWORKABLE_STATUSES as w, FEEDBACK_STATUS_META as x, FEEDBACK_STATUS_ORDER as y, FEEDBACK_UNDO_DURATION as z };
5841
+ export { type FeedbackContext as $, type FeedbackAttachmentError as A, type FeedbackAttachmentErrorInfo as B, ChatComposer as C, DEFAULT_ATTACHMENT_ACCEPT as D, FeedbackAttachmentField as E, FEEDBACK_ATTACHMENT_ACCEPT as F, type FeedbackAttachmentFieldLabels as G, type FeedbackAttachmentFieldMultipleProps as H, type FeedbackAttachmentFieldProps as I, type FeedbackAttachmentFieldRefsProps as J, type FeedbackAttachmentFieldSingleProps as K, type FeedbackAttachmentLabels as L, type FeedbackAttachmentRef as M, type FeedbackAttachmentRefsError as N, FeedbackAwaitingToggle as O, type FeedbackAwaitingToggleProps as P, type FeedbackCategory as Q, FeedbackCategoryBadge as R, type FeedbackCategoryLabels as S, type FeedbackCategoryOption as T, type FeedbackColumnsOptions as U, FeedbackComposer as V, type FeedbackComposerAttachment as W, type FeedbackComposerHandle as X, type FeedbackComposerLabels as Y, type FeedbackComposerProps as Z, type FeedbackComposerSlotContext as _, type ChatComposerHandle as a, feedbackAttachmentUrls as a$, FeedbackContextBox as a0, type FeedbackContextBoxProps as a1, type FeedbackContextInput as a2, type FeedbackContextLabels as a3, FeedbackDetail as a4, type FeedbackDetailLabels as a5, type FeedbackDetailPatch as a6, FeedbackDetailSection as a7, type FeedbackDetailUpdate as a8, FeedbackDialog as a9, FeedbackStatusBadge as aA, type FeedbackStatusChange as aB, type FeedbackStatusLabels as aC, type FeedbackStatusMutate as aD, type FeedbackStatusPatch as aE, type FeedbackStatusRow as aF, FeedbackStatusTransitions as aG, type FeedbackStatusUndoOptions as aH, FeedbackSubject as aI, type FeedbackSubjectProps as aJ, type FeedbackSubmission as aK, type FeedbackSubmitHint as aL, type FeedbackSubmitter as aM, type FeedbackTableRow as aN, FeedbackThread as aO, type FeedbackThreadAttachment as aP, type FeedbackThreadEvent as aQ, type FeedbackThreadItem as aR, type FeedbackThreadLabels as aS, type FeedbackThreadMessage as aT, type FeedbackThreadProps as aU, type FeedbackToastLabels as aV, type FeedbackUpload as aW, type UseFeedbackColumnsOptions as aX, appendRework as aY, attachmentName as aZ, feedbackAttachmentLine as a_, type FeedbackDialogLabels as aa, type FeedbackDialogMultipleProps as ab, type FeedbackDialogProps as ac, type FeedbackDialogSingleProps as ad, type FeedbackDialogTextLabels as ae, FeedbackEmptyState as af, type FeedbackEmptyStateProps as ag, type FeedbackEnvironment as ah, FeedbackMenu as ai, type FeedbackMenuLabels as aj, type FeedbackMenuProps as ak, FeedbackMobileCard as al, type FeedbackMobileCardProps as am, type FeedbackMultipleSubmission as an, type FeedbackNoteAttachment as ao, FeedbackNoteEditor as ap, type FeedbackPageLabels as aq, FeedbackProse as ar, type FeedbackRecord as as, type FeedbackRenderDate as at, FeedbackReworkSection as au, type FeedbackReworkSectionProps as av, type FeedbackRowAccess as aw, FeedbackRowDetail as ax, type FeedbackRowDetailProps as ay, type FeedbackStatus as az, type ChatComposerLabels as b, type ConfirmProviderProps as b$, feedbackCategoryRank as b0, feedbackColumns as b1, feedbackContext as b2, feedbackEnvironment as b3, feedbackMobileGroupBy as b4, feedbackPageHref as b5, feedbackPagePath as b6, feedbackPageUrl as b7, feedbackRowAccess as b8, feedbackSubmitter as b9, type ButtonVariant as bA, type CalculatorLabels as bB, Card as bC, CardAction as bD, type CardActionProps as bE, CardContent as bF, type CardContentProps as bG, type CardDensity as bH, CardDescription as bI, type CardDescriptionProps as bJ, CardFooter as bK, type CardFooterProps as bL, CardHeader as bM, type CardHeaderProps as bN, type CardProps as bO, CardTitle as bP, type CardTitleLevel as bQ, type CardTitleProps as bR, type CardTone as bS, type CharacterCountLabels as bT, type ChartTooltipPlacement as bU, type ComboboxLabels as bV, type CommonLabels as bW, type ConfirmDialogLabels as bX, type ConfirmFn as bY, type ConfirmOptions as bZ, ConfirmProvider as b_, feedbackSubmitterEmail as ba, isFeedbackAwaiting as bb, isImageAttachment as bc, nextFeedbackStatus as bd, pastedName as be, replaceDescription as bf, reworkCount as bg, selectableFeedbackStatuses as bh, splitBodyAttachments as bi, splitDescription as bj, useFeedbackCategoryLabels as bk, useFeedbackColumns as bl, useFeedbackDetailLabels as bm, useFeedbackPageLabels as bn, useFeedbackRenderDate as bo, useFeedbackStatusLabels as bp, useFeedbackStatusUndo as bq, useFeedbackToastLabels as br, visibleFeedbackStatuses as bs, type AppShellLabels as bt, Button as bu, type ButtonClassesOptions as bv, type ButtonLinkProps as bw, type ButtonProps as bx, type ButtonSize as by, type ButtonTone as bz, type ChatComposerProps as c, type FormActionsLabels as c$, type ConfirmTone as c0, CopyButton as c1, type CopyButtonLabels as c2, type CopyButtonProps as c3, type CurrencyLabels as c4, CurrentPasswordInput as c5, type CurrentPasswordInputLabels as c6, type CurrentPasswordInputProps as c7, DEFAULT_APP_SHELL_LABELS as c8, DEFAULT_CALCULATOR_LABELS as c9, type DatePickerLabels as cA, EmptyState as cB, type EmptyStateProps as cC, FIELD_BASE as cD, FIELD_DISPLAY as cE, FIELD_FLOATING_PAD as cF, FIELD_INVALID as cG, FIELD_TRIGGER as cH, FIELD_WRITABLE_LOOK as cI, FLOATING_INPUT_CLASS as cJ, FLOATING_LABEL_CLASS as cK, FieldChevron as cL, type FieldChevronProps as cM, FieldHint as cN, type FieldHintProps as cO, FileButton as cP, type FileButtonProps as cQ, type FileLabels as cR, type FilePickerLabels as cS, type FileRejection as cT, type FileRejectionReason as cU, type FileScreenOptions as cV, FloatingField as cW, type FloatingFieldProps as cX, FormActions as cY, type FormActionsAlign as cZ, type FormActionsDestructive as c_, DEFAULT_CHARACTER_COUNT_LABELS as ca, DEFAULT_COMBOBOX_LABELS as cb, DEFAULT_COMMON_LABELS as cc, DEFAULT_CONFIRM_DIALOG_LABELS as cd, DEFAULT_COPY_BUTTON_LABELS as ce, DEFAULT_CURRENCY_LABELS as cf, DEFAULT_DANGER_CONFIRM_LABELS as cg, DEFAULT_DATE_PICKER_LABELS as ch, DEFAULT_FILE_LABELS as ci, DEFAULT_FILE_PICKER_LABELS as cj, DEFAULT_FORM_ACTIONS_LABELS as ck, DEFAULT_IBAN_INPUT_LABELS as cl, DEFAULT_LEGAL_LABELS as cm, DEFAULT_MULTI_SELECT_LABELS as cn, DEFAULT_PASSWORD_REVEAL_LABELS as co, DEFAULT_PHONE_INPUT_LABELS as cp, DEFAULT_PICKER_SHEET_LABELS as cq, DEFAULT_SHARE_CARD_LABELS as cr, DEFAULT_SWIPEABLE_ROW_LABELS as cs, DEFAULT_TABS_LABELS as ct, DEFAULT_TOP_BAR_LABELS as cu, DangerConfirm as cv, type DangerConfirmLabels as cw, type DangerConfirmProps as cx, type DangerConfirmValues as cy, type DangerConsequence as cz, type ChatComposerSlotContext as d, type SharePendingGrant as d$, type FormActionsPlacement as d0, type FormActionsProps as d1, type FormActionsStickyWithin as d2, type FormActionsSubmitProps as d3, type FormActionsSubmitShortcut as d4, IbanInput as d5, type IbanInputLabels as d6, type IbanInputProps as d7, IconButton as d8, type IconButtonGlyphSize as d9, type LegalOperator as dA, type LegalOperatorSectionLabels as dB, type LegalOperatorText as dC, type LegalPageKey as dD, LegalSection as dE, type LegalSectionProps as dF, type LegalTextSectionLabels as dG, type MultiSelectLabels as dH, PHONE_QUERY as dI, type PasswordRevealLabels as dJ, PhoneInput as dK, type PhoneInputLabels as dL, type PhoneInputProps as dM, type PickerSheetLabels as dN, type ResponsiveFormActionsPlacement as dO, Select as dP, type SelectProps as dQ, type ShareAddRequest as dR, type ShareCandidate as dS, ShareCard as dT, type ShareCardLabels as dU, type ShareCardProps as dV, ShareDialog as dW, type ShareDialogProps as dX, type ShareGrantee as dY, SharePanel as dZ, type SharePanelProps as d_, type IconButtonLinkProps as da, type IconButtonProps as db, type IconButtonSize as dc, type IconButtonTone as dd, type IconButtonToneColor as de, type IconButtonVariant as df, Input as dg, type InputProps as dh, type KitDateFormatContext as di, type KitDateFormatter as dj, type KitLinkComponent as dk, type KitLinkProps as dl, LEGAL_HREFS as dm, Label as dn, type LabelOverride as dp, type LabelProps as dq, LegalFooter as dr, type LegalFooterProps as ds, type LegalFramedSectionLabels as dt, type LegalLabels as du, LegalLayout as dv, type LegalLayoutProps as dw, type LegalLink as dx, LegalLinks as dy, type LegalLinksProps as dz, DEFAULT_FEEDBACK_ATTACHMENT_LABELS as e, type ShareRole as e0, Spinner as e1, type SpinnerProps as e2, type SwipeableRowLabels as e3, type TabItem as e4, Tabs as e5, type TabsLabels as e6, type TabsProps as e7, Textarea as e8, type TextareaProps as e9, useKitLocale as eA, useKitWeekStart as eB, useLegalLabels as eC, type FilePickHandler as eD, usePromisePending as eE, formatAccept as eF, judgePick as eG, screenFiles as eH, summariseRejections as eI, LegalPageContext as eJ, type LegalPageContextValue as eK, type LegalRefTarget as eL, type LegalSectionSlot as eM, LegalSlotContext as eN, LegalText as eO, baseLanguage as eP, resolveLegalRefs as eQ, warnLegalOnce as eR, type TopBarLabels as ea, TypedConfirmField as eb, type TypedConfirmFieldLabels as ec, type TypedConfirmFieldProps as ed, type TypedMatch as ee, type UiKitLabelOverrides as ef, type UiKitLabels as eg, UiKitProvider as eh, type UiKitProviderProps as ei, type UseFilePickerOptions as ej, type UseFilePickerReturn as ek, buttonClasses as el, formatFileSize as em, legalOperatorText as en, matchesAccept as eo, missingKitLabels as ep, resolvePasswordRevealLabels as eq, typedMatches as er, useConfirm as es, useFilePicker as et, useKitChartTooltipPlacement as eu, useKitDateFormatter as ev, useKitFileLabels as ew, useKitLabelOverrides as ex, useKitLabels as ey, useKitLink as ez, DEFAULT_FEEDBACK_CATEGORY_LABELS as f, DEFAULT_FEEDBACK_COMPOSER_LABELS as g, DEFAULT_FEEDBACK_CONTEXT_LABELS as h, DEFAULT_FEEDBACK_DETAIL_LABELS as i, DEFAULT_FEEDBACK_DIALOG_LABELS as j, DEFAULT_FEEDBACK_MENU_LABELS as k, DEFAULT_FEEDBACK_PAGE_LABELS as l, DEFAULT_FEEDBACK_STATUS_LABELS as m, DEFAULT_FEEDBACK_THREAD_LABELS as n, DEFAULT_FEEDBACK_TOAST_LABELS as o, DEFAULT_MAX_ATTACHMENTS as p, DEFAULT_MAX_ATTACHMENT_BYTES as q, FEEDBACK_AUTHOR_EDITABLE_STATUSES as r, FEEDBACK_AWAITING_STATUSES as s, FEEDBACK_CATEGORY_META as t, FEEDBACK_CATEGORY_ORDER as u, FEEDBACK_PICKABLE_CATEGORIES as v, FEEDBACK_REWORKABLE_STATUSES as w, FEEDBACK_STATUS_META as x, FEEDBACK_STATUS_ORDER as y, FEEDBACK_UNDO_DURATION as z };
@@ -147,9 +147,32 @@ declare function placeholderMismatch(text: string, reference: string): boolean;
147
147
  * developer adds the string).
148
148
  */
149
149
  declare function reviewStatus(review: TranslationReview | null | undefined, text: string, reference: string): ReviewStatus;
150
- /** Whether `key` lies in `area`: the key IS the area, or sits under it — `legal.terms`
151
- * and kastlan's `legal:terms` are in `legal`, `legalese.title` is not. */
150
+ /**
151
+ * Whether `key` lies in `area`: the key IS the area, or sits under it — `legal.terms`
152
+ * and kastlan's `legal:terms` are in `legal`, `legalese.title` is not.
153
+ *
154
+ * 0.28: the kit's own words of that area too — `kit.legal.sections.terms.law.body(…)`
155
+ * is in `legal`. All three apps list the kit's labels under `kit.`
156
+ * (`flattenStrings(kitLabelStrings(labels), "kit.")`), and since 0.28 the kit writes
157
+ * the shared legal sections, so a lawyer with a `["legal"]` grant who was not shown
158
+ * `kit.legal.*` would not see half of the Privacy Policy — and the server would refuse
159
+ * the verdicts (docs/legal-harmonization.md §7.5). server-kit's `in_areas` and the apps'
160
+ * copies of it apply the same rule.
161
+ */
152
162
  declare function keyInArea(key: string, area: string): boolean;
163
+ /**
164
+ * The area of `areas` that `key` lies in ({@link keyInArea}), or `undefined` — the
165
+ * translation page's grouping by the same rule the filter and the server use, so
166
+ * `kit.legal.sections.privacy.rights.lead` is grouped under `legal` with the app's own
167
+ * legal texts instead of under `kit.legal`:
168
+ *
169
+ * const namespaceOf = (key: string) => reviewAreaOf(key, ["legal"]) ?? ownNamespaceOf(key);
170
+ *
171
+ * Where two areas both hold the key (`legal` and `legal.privacy`), the longer — the more
172
+ * specific — wins, whatever their order. `inArea` is the app's own rule, as for
173
+ * {@link keyInAreas}.
174
+ */
175
+ declare function reviewAreaOf(key: string, areas: readonly string[], inArea?: (key: string, area: string) => boolean): string | undefined;
153
176
  /**
154
177
  * Whether `key` lies in one of `areas` — the scope a reviewer may be limited to
155
178
  * (keksdose: `["legal"]`, a lawyer who judges the Imprint, the Privacy Policy and the
@@ -348,4 +371,4 @@ interface TranslationCorrection {
348
371
  * string included), as the export file lists them. */
349
372
  declare function translationCorrections(rows: readonly TranslationRow[]): TranslationCorrection[];
350
373
 
351
- export { type ApiTranslationReview, type ApiTranslationReviewWrite, DEFAULT_TRANSLATION_REVIEW_FILTER, DEFAULT_TRANSLATION_REVIEW_SWIPE, REVIEW_STATUSES, type ReviewStatus, TRANSLATION_REVIEW_SWIPE_ACTIONS, type TranslationCorrection, type TranslationReview, type TranslationReviewFilter, type TranslationReviewKey, type TranslationReviewSwipeAction, type TranslationReviewSwipeBinding, type TranslationReviewSwipePlan, type TranslationReviewUndo, type TranslationReviewWrite, type TranslationRow, type TranslationRowGroup, type TranslationRowsInput, type TranslationSummary, type TranslationVerdict, dropReviews, filterTranslationRows, flattenStrings, fromApiReview, groupTranslationRows, keyInArea, keyInAreas, keyNamespace, mergeReviews, placeholderMismatch, placeholderTokens, reviewStatus, reviewUndo, reviewWrite, summariseRows, toApiWrite, translationCorrections, translationReviewSwipePlan, translationRows, unreviewedRows };
374
+ export { type ApiTranslationReview, type ApiTranslationReviewWrite, DEFAULT_TRANSLATION_REVIEW_FILTER, DEFAULT_TRANSLATION_REVIEW_SWIPE, REVIEW_STATUSES, type ReviewStatus, TRANSLATION_REVIEW_SWIPE_ACTIONS, type TranslationCorrection, type TranslationReview, type TranslationReviewFilter, type TranslationReviewKey, type TranslationReviewSwipeAction, type TranslationReviewSwipeBinding, type TranslationReviewSwipePlan, type TranslationReviewUndo, type TranslationReviewWrite, type TranslationRow, type TranslationRowGroup, type TranslationRowsInput, type TranslationSummary, type TranslationVerdict, dropReviews, filterTranslationRows, flattenStrings, fromApiReview, groupTranslationRows, keyInArea, keyInAreas, keyNamespace, mergeReviews, placeholderMismatch, placeholderTokens, reviewAreaOf, reviewStatus, reviewUndo, reviewWrite, summariseRows, toApiWrite, translationCorrections, translationReviewSwipePlan, translationRows, unreviewedRows };
@@ -51,7 +51,7 @@ function placeholderTokens(text) {
51
51
  const found = [];
52
52
  for (const m of text.matchAll(PLACEHOLDER_RE)) {
53
53
  if (m[1]) found.push(`{{${m[1]}}}`);
54
- else if (m[2]) found.push(`{${m[2]}}`);
54
+ else if (m[2]) found.push(m[2] === "ref" ? m[0] : `{${m[2]}}`);
55
55
  else if (m[3]) found.push(`<${m[3]}>`);
56
56
  else if (m[4]) found.push(`$t(${m[4]})`);
57
57
  }
@@ -69,7 +69,14 @@ function reviewStatus(review, text, reference) {
69
69
  return review.verdict === "APPROVED" ? "approved" : "needs_change";
70
70
  }
71
71
  function keyInArea(key, area) {
72
- return key === area || key.startsWith(`${area}.`) || key.startsWith(`${area}:`);
72
+ return key === area || key.startsWith(`${area}.`) || key.startsWith(`${area}:`) || key.startsWith(`kit.${area}.`);
73
+ }
74
+ function reviewAreaOf(key, areas, inArea = keyInArea) {
75
+ let found;
76
+ for (const area of areas) {
77
+ if (inArea(key, area) && (found === void 0 || area.length > found.length)) found = area;
78
+ }
79
+ return found;
73
80
  }
74
81
  function keyInAreas(key, areas, inArea = keyInArea) {
75
82
  return !areas || areas.some((area) => inArea(key, area));
@@ -248,6 +255,7 @@ export {
248
255
  mergeReviews,
249
256
  placeholderMismatch,
250
257
  placeholderTokens,
258
+ reviewAreaOf,
251
259
  reviewStatus,
252
260
  reviewUndo,
253
261
  reviewWrite,