@innspel/react-native 0.2.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -143,8 +143,26 @@ WebP; høyst 5 MB og 4096 × 4096.
143
143
 
144
144
  ## Betaprogram
145
145
 
146
- Betaprogram-fanen kommer i M3. `innspel.programs.list()` finnes allerede i
147
- kjernen om du vil bygge din egen.
146
+ ```tsx
147
+ import { InnspelProgram } from '@innspel/react-native';
148
+
149
+ <InnspelProgram invitationToken={tokenFraDyplenke} />
150
+ ```
151
+
152
+ Sett den der invitasjonen hører hjemme — typisk øverst på hjemskjermen. Uten
153
+ invitasjon og uten deltakelse rendrer den **ingenting**.
154
+
155
+ Den viser invitasjonsbanneret, aksepten med tallene (N oppgaver × M minutter,
156
+ dato til dato, maks K kontakter), oppgavene, kjente feil du slipper å melde, og
157
+ «Gå ut av programmet» med bekreftelse. Utgangen er umiddelbar.
158
+
159
+ **Tokenet kommer fra deg.** Plattformen sender aldri invitasjonen: du får
160
+ `program.invitation_created` som webhook med engangs-tokenet og pseudonymet,
161
+ løser pseudonymet til din egen bruker, og sender lenken i din egen kanal. Fanger
162
+ appen tokenet fra dyplenken og gir det hit, kan testeren bli med. Uten token
163
+ vises invitasjonen fortsatt, men «Bli med» er inaktiv.
164
+
165
+ Oppgavene med utfall og «Hvordan gikk det?» kommer i neste versjon.
148
166
 
149
167
  ## Versjoner
150
168
 
package/dist/index.cjs CHANGED
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  InnspelPrivate: () => InnspelPrivate,
24
+ InnspelProgram: () => InnspelProgram,
24
25
  InnspelProvider: () => InnspelProvider,
25
26
  byggTema: () => byggTema,
26
27
  createMemoryStorage: () => createMemoryStorage,
@@ -583,6 +584,40 @@ var tekst = {
583
584
  svarFra: (leietaker) => `Svar fra ${leietaker}`,
584
585
  svarFraGenerisk: "Svar",
585
586
  sendNytt: "Send nytt innspill",
587
+ // 3a — invitasjonsbanneret (DD-12)
588
+ invitasjonRegion: "Invitasjon til betaprogram",
589
+ invitasjonHva: (navn) => `Vil du teste \xAB${navn}\xBB?`,
590
+ invitasjonKontakter: (maks) => `Vi tar kontakt maks ${maks} ganger. Du kan g\xE5 ut n\xE5r som helst.`,
591
+ lesMer: "Les mer og bli med",
592
+ avvisInvitasjon: "Avvis invitasjonen",
593
+ // 3b — aksepten (DD-13, DD-32, DD-37)
594
+ akseptHva: "Hva testes",
595
+ /** DD-32: tallene på én linje, FØR forklaringen — N oppgaver · ca. M min hver · dato–dato · maks K kontakter. */
596
+ akseptTall: (oppgaver, minutter, periode2, kontakter) => `${oppgaver} oppgaver \xB7 ca. ${minutter} min hver \xB7 ${periode2} \xB7 maks ${kontakter} kontakter`,
597
+ akseptOppgaver: "Hva vi ber om",
598
+ akseptOppgaveTid: (minutter) => `ca. ${minutter} min`,
599
+ akseptKjenteFeil: (antall) => `Kjente feil (${antall})`,
600
+ akseptKjenteFeilUnder: "Disse trenger du ikke melde \u2014 vi vet om dem.",
601
+ akseptInnsamling: "Hva som samles inn",
602
+ akseptInnsamlingTekst: "Skjerm, appversjon, plattform, OS og hva du svarer. Aldri navn, e-post, telefon eller posisjon.",
603
+ akseptVilkar: "Les vilk\xE5rene (\xE5pnes i nettleser)",
604
+ akseptVilkarHint: "Bare en lenke. Ingen avkryssing, ingen signatur \u2014 \xABBli med\xBB binder deg ikke til noe.",
605
+ akseptIngenVilkar: "Ingen vilk\xE5r, ingen avtale \u2014 plattformen kjenner ikke navnet ditt og kan ikke inng\xE5 \xE9n.",
606
+ akseptUtgang: "Du kan g\xE5 ut n\xE5r som helst \u2014 herfra.",
607
+ bliMed: "Bli med",
608
+ bliMedHint: "Samtykket gjelder bare dette programmet.",
609
+ /** DD-12: tokenet er engangs og kom i leietakerens egen kanal — plattformen sender aldri. */
610
+ bliMedUtenToken: "\xC5pne lenken vi sendte deg for \xE5 bli med.",
611
+ akseptFeil: (arsak) => `Kunne ikke bli med: ${arsak}`,
612
+ // 3c (M3.1-delen) — deltakelsen og «Gå ut» (DD-36)
613
+ deltakelseRegion: "Ditt betaprogram",
614
+ deltakelsePeriode: (periode2, brukt, maks) => `${periode2} \xB7 ${brukt} av ${maks} kontakter brukt`,
615
+ deltakelseOppgaverKommer: "Oppgavene kan gj\xF8res n\xE5r det passer deg.",
616
+ gaaUt: "G\xE5 ut av programmet",
617
+ gaaUtTittel: "G\xE5 ut av programmet?",
618
+ gaaUtTekst: (navn) => `Du tas ut av testgruppen med en gang. \xAB${navn}\xBB sl\xE5s av for deg, og vi tar ikke kontakt igjen. Det du allerede har svart, beholdes.`,
619
+ bliVaerende: "Bli v\xE6rende",
620
+ gaaUtBekreft: "G\xE5 ut",
586
621
  // Felles
587
622
  tilbake: "Tilbake",
588
623
  lukk: "Lukk",
@@ -1793,6 +1828,309 @@ function InnspelPrivate({ children, style }) {
1793
1828
  return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native11.View, { ref, collapsable: false, style, testID: "innspel-privat", children });
1794
1829
  }
1795
1830
 
1831
+ // src/program/InnspelProgram.tsx
1832
+ var import_core3 = require("@innspel/core");
1833
+ var import_react14 = require("react");
1834
+ var import_react_native13 = require("react-native");
1835
+
1836
+ // src/program/Aksept.tsx
1837
+ var import_react13 = require("react");
1838
+ var import_react_native12 = require("react-native");
1839
+
1840
+ // src/program/periode.ts
1841
+ var MANEDER = [
1842
+ "januar",
1843
+ "februar",
1844
+ "mars",
1845
+ "april",
1846
+ "mai",
1847
+ "juni",
1848
+ "juli",
1849
+ "august",
1850
+ "september",
1851
+ "oktober",
1852
+ "november",
1853
+ "desember"
1854
+ ];
1855
+ function periode(opensAt, closesAt) {
1856
+ const fra = new Date(opensAt);
1857
+ const til = new Date(closesAt);
1858
+ if (Number.isNaN(fra.getTime()) || Number.isNaN(til.getTime())) return "";
1859
+ const sammeManed = fra.getMonth() === til.getMonth() && fra.getFullYear() === til.getFullYear();
1860
+ return sammeManed ? `${fra.getDate()}.\u2013${til.getDate()}. ${MANEDER[til.getMonth()]}` : `${fra.getDate()}. ${MANEDER[fra.getMonth()]} \u2013 ${til.getDate()}. ${MANEDER[til.getMonth()]}`;
1861
+ }
1862
+ function minutterPerOppgave(tasks) {
1863
+ if (tasks.length === 0) return 0;
1864
+ return Math.round(tasks.reduce((sum, t2) => sum + t2.estimatedMinutes, 0) / tasks.length);
1865
+ }
1866
+
1867
+ // src/program/Aksept.tsx
1868
+ var import_jsx_runtime11 = require("react/jsx-runtime");
1869
+ function Aksept({
1870
+ program,
1871
+ harToken,
1872
+ sender,
1873
+ feil,
1874
+ onBliMed,
1875
+ onLukk
1876
+ }) {
1877
+ const tema = useTema();
1878
+ const tall = tekst.akseptTall(
1879
+ program.tasks.length,
1880
+ minutterPerOppgave(program.tasks),
1881
+ periode(program.opensAt, program.closesAt),
1882
+ program.maxContacts
1883
+ );
1884
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native12.Modal, { visible: true, transparent: true, animationType: "slide", onRequestClose: onLukk, accessibilityViewIsModal: true, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native12.View, { style: { flex: 1, backgroundColor: tema.color.scrim, justifyContent: "flex-end" }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
1885
+ import_react_native12.View,
1886
+ {
1887
+ testID: "program-aksept",
1888
+ accessibilityViewIsModal: true,
1889
+ style: {
1890
+ backgroundColor: tema.color.bg,
1891
+ borderTopLeftRadius: tema.radius.lg * 2,
1892
+ borderTopRightRadius: tema.radius.lg * 2,
1893
+ padding: tema.screenPadding,
1894
+ gap: tema.space.md,
1895
+ maxHeight: "92%",
1896
+ minHeight: "60%"
1897
+ },
1898
+ children: [
1899
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_react_native12.View, { style: { flexDirection: "row", justifyContent: "space-between", alignItems: "center" }, children: [
1900
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Btn, { variant: "ghost", testID: "aksept-tilbake", ikon: "\u2190", label: tekst.tilbake, onPress: onLukk }),
1901
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native12.View, {})
1902
+ ] }),
1903
+ feil ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Banner, { live: true, ikon: "\u26A0", tone: "danger", children: tekst.akseptFeil(feil) }) : null,
1904
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_react_native12.ScrollView, { contentContainerStyle: { gap: tema.space.md }, children: [
1905
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(H, { sub: tekst.akseptHva, children: program.name }),
1906
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1907
+ import_react_native12.Text,
1908
+ {
1909
+ accessibilityRole: "text",
1910
+ style: {
1911
+ color: tema.color.textPrimary,
1912
+ fontSize: tema.font.body,
1913
+ lineHeight: tema.lineHeight.body,
1914
+ fontWeight: tema.weight.semibold
1915
+ },
1916
+ children: tall
1917
+ }
1918
+ ),
1919
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native12.Text, { style: { color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body }, children: program.hypothesis }),
1920
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Card, { children: [
1921
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(H, { children: tekst.akseptOppgaver }),
1922
+ program.tasks.map((o) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_react_native12.View, { style: { gap: tema.space.xs }, children: [
1923
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native12.Text, { style: { color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body }, children: o.title }),
1924
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Hint, { children: [
1925
+ tekst.akseptOppgaveTid(o.estimatedMinutes),
1926
+ o.screenHint ? ` \xB7 ${o.screenHint}` : ""
1927
+ ] })
1928
+ ] }, o.id))
1929
+ ] }),
1930
+ program.knownIssues.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Card, { children: [
1931
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(H, { sub: tekst.akseptKjenteFeilUnder, children: tekst.akseptKjenteFeil(program.knownIssues.length) }),
1932
+ program.knownIssues.map((k) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_react_native12.View, { style: { gap: tema.space.xs }, children: [
1933
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native12.Text, { style: { color: tema.color.textPrimary, fontSize: tema.font.small, lineHeight: tema.lineHeight.small }, children: k.title }),
1934
+ k.workaround ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_react_native12.Text, { style: { color: tema.color.textSecondary, fontSize: tema.font.small, lineHeight: tema.lineHeight.small }, children: [
1935
+ tekst.omvei,
1936
+ " ",
1937
+ k.workaround
1938
+ ] }) : null,
1939
+ k.fixedIn ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1940
+ StatusPill,
1941
+ {
1942
+ ikon: k.status === "fikset" ? "\u2713" : "\u{1F527}",
1943
+ etikett: k.status === "fikset" ? tekst.rettetI(k.fixedIn) : tekst.rettesI(k.fixedIn),
1944
+ farge: k.status === "fikset" ? "success" : "info"
1945
+ }
1946
+ ) : null
1947
+ ] }, k.id))
1948
+ ] }) : null,
1949
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Card, { children: [
1950
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(H, { sub: tekst.akseptInnsamlingTekst, children: tekst.akseptInnsamling }),
1951
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Hint, { children: tekst.kontekstAldri })
1952
+ ] }),
1953
+ program.termsUrl && !program.commitmentFree ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_react_native12.View, { style: { gap: tema.space.xs }, children: [
1954
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1955
+ import_react_native12.Pressable,
1956
+ {
1957
+ testID: "vilkar-lenke",
1958
+ accessibilityRole: "link",
1959
+ accessibilityLabel: tekst.akseptVilkar,
1960
+ onPress: () => void import_react_native12.Linking.openURL(String(program.termsUrl)),
1961
+ style: { minHeight: tema.touch, justifyContent: "center" },
1962
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_react_native12.Text, { style: { color: tema.color.textPrimary, fontSize: tema.font.body, textDecorationLine: "underline" }, children: [
1963
+ "\u{1F517} ",
1964
+ tekst.akseptVilkar
1965
+ ] })
1966
+ }
1967
+ ),
1968
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Hint, { children: tekst.akseptVilkarHint })
1969
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Hint, { children: tekst.akseptIngenVilkar }),
1970
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_react_native12.Text, { style: { color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body }, children: [
1971
+ "\u{1F6AA} ",
1972
+ tekst.akseptUtgang
1973
+ ] })
1974
+ ] }),
1975
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1976
+ Btn,
1977
+ {
1978
+ testID: "bli-med",
1979
+ label: tekst.bliMed,
1980
+ disabled: !harToken || sender,
1981
+ hint: harToken ? tekst.bliMedHint : tekst.bliMedUtenToken,
1982
+ onPress: onBliMed
1983
+ }
1984
+ )
1985
+ ]
1986
+ }
1987
+ ) }) });
1988
+ }
1989
+
1990
+ // src/program/InnspelProgram.tsx
1991
+ var import_jsx_runtime12 = require("react/jsx-runtime");
1992
+ function InnspelProgram({
1993
+ invitationToken,
1994
+ onEndring
1995
+ }) {
1996
+ const { client } = useInnspel();
1997
+ const tema = useTema();
1998
+ const [mine, setMine] = (0, import_react14.useState)();
1999
+ const [deltakelse, setDeltakelse] = (0, import_react14.useState)();
2000
+ const [viserAksept, setViserAksept] = (0, import_react14.useState)(false);
2001
+ const [viserGaaUt, setViserGaaUt] = (0, import_react14.useState)(false);
2002
+ const [avvist, setAvvist] = (0, import_react14.useState)(false);
2003
+ const [sender, setSender] = (0, import_react14.useState)(false);
2004
+ const [feil, setFeil] = (0, import_react14.useState)();
2005
+ (0, import_react14.useEffect)(() => {
2006
+ if (client.isAnonymous) return;
2007
+ let levende = true;
2008
+ void client.programs.list().then((svar) => {
2009
+ if (!levende) return;
2010
+ setMine(svar);
2011
+ setDeltakelse(svar.participations.find((p) => p.status !== "trukket"));
2012
+ }).catch(() => void 0);
2013
+ return () => {
2014
+ levende = false;
2015
+ };
2016
+ }, [client]);
2017
+ const bliMed = (0, import_react14.useCallback)(async () => {
2018
+ if (!invitationToken) return;
2019
+ setSender(true);
2020
+ setFeil(void 0);
2021
+ try {
2022
+ const ny = await client.programs.accept(invitationToken);
2023
+ setDeltakelse(ny);
2024
+ setViserAksept(false);
2025
+ onEndring?.(ny);
2026
+ } catch (e) {
2027
+ setFeil(e instanceof import_core3.InnspelApiError ? e.message : "tjeneren svarte ikke.");
2028
+ } finally {
2029
+ setSender(false);
2030
+ }
2031
+ }, [client, invitationToken, onEndring]);
2032
+ const gaaUt = (0, import_react14.useCallback)(async () => {
2033
+ if (!deltakelse) return;
2034
+ setSender(true);
2035
+ try {
2036
+ await client.programs.withdraw(deltakelse.id);
2037
+ setDeltakelse(void 0);
2038
+ setViserGaaUt(false);
2039
+ onEndring?.(null);
2040
+ } catch (e) {
2041
+ setFeil(e instanceof import_core3.InnspelApiError ? e.message : "tjeneren svarte ikke.");
2042
+ } finally {
2043
+ setSender(false);
2044
+ }
2045
+ }, [client, deltakelse, onEndring]);
2046
+ const invitasjon = deltakelse ? void 0 : mine?.invitations[0];
2047
+ const program = deltakelse?.program ?? invitasjon?.program;
2048
+ if (!program) return null;
2049
+ if (deltakelse) {
2050
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react_native13.View, { testID: "program-deltakelse", accessibilityLabel: tekst.deltakelseRegion, style: { gap: tema.space.sm }, children: [
2051
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Card, { children: [
2052
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(H, { sub: tekst.deltakelsePeriode(periode(program.opensAt, program.closesAt), deltakelse.contactsSent, program.maxContacts), children: program.name }),
2053
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Hint, { children: tekst.deltakelseOppgaverKommer }),
2054
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Btn, { variant: "ghost", testID: "gaa-ut", ikon: "\u{1F6AA}", label: tekst.gaaUt, onPress: () => setViserGaaUt(true) })
2055
+ ] }),
2056
+ viserGaaUt ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native13.Modal, { visible: true, transparent: true, animationType: "fade", onRequestClose: () => setViserGaaUt(false), accessibilityViewIsModal: true, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native13.View, { style: { flex: 1, backgroundColor: tema.color.scrim, justifyContent: "flex-end", padding: tema.space.md }, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2057
+ import_react_native13.View,
2058
+ {
2059
+ testID: "gaa-ut-dialog",
2060
+ accessibilityViewIsModal: true,
2061
+ style: {
2062
+ backgroundColor: tema.color.surface,
2063
+ borderRadius: tema.radius.lg,
2064
+ borderWidth: tema.hairline,
2065
+ borderColor: tema.color.borderStrong,
2066
+ padding: tema.space.md,
2067
+ gap: tema.space.md
2068
+ },
2069
+ children: [
2070
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(H, { children: tekst.gaaUtTittel }),
2071
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native13.Text, { style: { color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body }, children: tekst.gaaUtTekst(program.name) }),
2072
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react_native13.View, { style: { flexDirection: "row", gap: tema.space.sm }, children: [
2073
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Btn, { grow: true, variant: "secondary", testID: "bli-vaerende", label: tekst.bliVaerende, onPress: () => setViserGaaUt(false) }),
2074
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Btn, { grow: true, variant: "danger", testID: "bekreft-gaa-ut", ikon: "\u{1F6AA}", label: tekst.gaaUtBekreft, disabled: sender, onPress: () => void gaaUt() })
2075
+ ] })
2076
+ ]
2077
+ }
2078
+ ) }) }) : null
2079
+ ] });
2080
+ }
2081
+ if (!invitasjon || avvist) return null;
2082
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
2083
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2084
+ import_react_native13.View,
2085
+ {
2086
+ testID: "program-banner",
2087
+ accessibilityLabel: tekst.invitasjonRegion,
2088
+ style: {
2089
+ backgroundColor: tema.color.brandBg,
2090
+ borderRadius: tema.radius.lg,
2091
+ borderWidth: tema.hairline,
2092
+ borderColor: tema.color.brand,
2093
+ padding: tema.space.md,
2094
+ gap: tema.space.sm
2095
+ },
2096
+ children: [
2097
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react_native13.View, { style: { flexDirection: "row", gap: tema.space.sm, alignItems: "flex-start" }, children: [
2098
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native13.Text, { accessibilityElementsHidden: true, importantForAccessibility: "no", style: { fontSize: tema.font.h3 }, children: "\u{1F9EA}" }),
2099
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react_native13.View, { style: { flex: 1, gap: tema.space.xs }, children: [
2100
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native13.Text, { style: { color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body }, children: tekst.invitasjonHva(program.name) }),
2101
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Hint, { children: tekst.invitasjonKontakter(program.maxContacts) })
2102
+ ] }),
2103
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2104
+ import_react_native13.Pressable,
2105
+ {
2106
+ testID: "avvis-invitasjon",
2107
+ accessibilityRole: "button",
2108
+ accessibilityLabel: tekst.avvisInvitasjon,
2109
+ onPress: () => setAvvist(true),
2110
+ style: { minWidth: tema.touch, minHeight: tema.touch, alignItems: "center", justifyContent: "center" },
2111
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native13.Text, { style: { color: tema.color.textSecondary, fontSize: tema.font.body }, children: "\u2715" })
2112
+ }
2113
+ )
2114
+ ] }),
2115
+ feil && !viserAksept ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Banner, { live: true, ikon: "\u26A0", tone: "danger", children: tekst.akseptFeil(feil) }) : null,
2116
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Btn, { variant: "secondary", testID: "les-mer", label: tekst.lesMer, onPress: () => setViserAksept(true) })
2117
+ ]
2118
+ }
2119
+ ),
2120
+ viserAksept ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2121
+ Aksept,
2122
+ {
2123
+ program,
2124
+ harToken: !!invitationToken,
2125
+ sender,
2126
+ ...feil ? { feil } : {},
2127
+ onBliMed: () => void bliMed(),
2128
+ onLukk: () => setViserAksept(false)
2129
+ }
2130
+ ) : null
2131
+ ] });
2132
+ }
2133
+
1796
2134
  // src/lagring.ts
1797
2135
  function createStorage(pakke) {
1798
2136
  return {
@@ -1816,6 +2154,7 @@ function createMemoryStorage() {
1816
2154
  // Annotate the CommonJS export names for ESM import in node:
1817
2155
  0 && (module.exports = {
1818
2156
  InnspelPrivate,
2157
+ InnspelProgram,
1819
2158
  InnspelProvider,
1820
2159
  byggTema,
1821
2160
  createMemoryStorage,