@innspel/react-native 0.9.5 → 0.10.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.
package/README.md CHANGED
@@ -139,7 +139,7 @@ innsenderen alt ser i kvitteringen. «Ja, jeg også» på en kjent feil gir ikke
139
139
  | Mønstervarsel | Ser teksten ut til å inneholde e-post, telefonnummer, kortnummer, IP eller en tilgangsnøkkel, spør widgeten om det skal fjernes. Den fjerner **aldri** noe selv. |
140
140
  | Skjermbilde | Valgfritt, én eller to veier: «Legg ved skjermbilde» (skjermen bak arket, tatt ved trykk) og «Velg bilde» (fra galleriet, med din velger). Forhåndsvises og maskeres på enheten — private views automatisk på en fangst, resten med felt, pensel eller «Masker all tekst». Se under. |
141
141
  | Kvittering | Lover noe konkret, per spor, med saksnummer. Ber aldri om en vurdering av appen. Feilet bildet, sier den det — saken er sendt uansett. |
142
- | Mine innspill | Status, løftet som hører til, og svaret fra deg under saken. Det som venter på nett står øverst. |
142
+ | Mine innspill | Status, løftet som hører til, og svaret fra deg under saken. Det som venter på nett står øverst. «Legg til mer» på en åpen sak: ett felt i kortet, maks tre tillegg, aldri et svar på svaret — tilleggene står under innsenderens egen tekst, og i panelet på saken. |
143
143
 
144
144
  ## Offline
145
145
 
package/dist/index.cjs CHANGED
@@ -392,7 +392,7 @@ function useTema() {
392
392
  }
393
393
 
394
394
  // src/widget/Widget.tsx
395
- var import_core2 = require("@innspel/core");
395
+ var import_core3 = require("@innspel/core");
396
396
  var import_react11 = require("react");
397
397
  var import_react_native9 = require("react-native");
398
398
  var import_react_native_safe_area_context = require("react-native-safe-area-context");
@@ -401,6 +401,9 @@ var import_react_native_safe_area_context = require("react-native-safe-area-cont
401
401
  var import_react3 = require("react");
402
402
  var import_react_native_svg = require("react-native-svg");
403
403
 
404
+ // ../../node_modules/ionicons/dist/svg/add-outline.svg
405
+ var add_outline_default = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="ionicon"><path d="M256 112v288M400 256H112" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32px"/></svg>';
406
+
404
407
  // ../../node_modules/ionicons/dist/svg/arrow-back-outline.svg
405
408
  var arrow_back_outline_default = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="ionicon"><path d="M244 400 100 256l144-144M120 256h292" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="48px"/></svg>';
406
409
 
@@ -496,6 +499,7 @@ var import_jsx_runtime = require("react/jsx-runtime");
496
499
  var utenTittel = (svg) => svg.replace(/<title>[\s\S]*?<\/title>/g, "");
497
500
  var IKONER = Object.fromEntries(
498
501
  Object.entries({
502
+ "add-outline": add_outline_default,
499
503
  "arrow-back-outline": arrow_back_outline_default,
500
504
  "brush-outline": brush_outline_default,
501
505
  // Fylte varianter: bare på sporvalgets to kort (DD-63), der ikonet bærer stemningen.
@@ -906,6 +910,20 @@ var tekst = {
906
910
  bildeFjernet: "Bildet er fjernet.",
907
911
  svarFra: (leietaker) => `Svar fra ${leietaker}`,
908
912
  svarFraGenerisk: "Svar",
913
+ // DD-69 — «Legg til mer»: innsenderens egne ord, ikke et svar på svaret.
914
+ leggTilMer: "Legg til mer",
915
+ leggTilMerLabel: "Legg til mer p\xE5 denne saken",
916
+ leggTilMerPlaceholder: "Hva vil du legge til?",
917
+ leggTilMerHint: "Blir st\xE5ende p\xE5 saken din, under det du alt har skrevet. Ikke et svar p\xE5 svaret \u2014 det blir ingen samtale her.",
918
+ avbryt: "Avbryt",
919
+ duLaTil: (dato) => `Du la til \xB7 ${dato}`,
920
+ lagtTil: "Lagt til",
921
+ tilleggTak: "Du har lagt til tre ganger. Har du mer, send et nytt innspill.",
922
+ tilleggLukket: "Saken er avsluttet \u2014 send et nytt innspill.",
923
+ /** F34: serverens egen setning (InnspelApiError) — aldri en rå feil. */
924
+ tilleggFeil: (arsak) => `Kunne ikke legge til: ${arsak} Teksten din er beholdt.`,
925
+ tilleggIngenNett: "Ingen nett. Teksten din er beholdt \u2014 pr\xF8v igjen n\xE5r du er p\xE5 nett.",
926
+ tilleggFeilGenerisk: "Kunne ikke legge til. Teksten din er beholdt \u2014 pr\xF8v igjen.",
909
927
  sendNytt: "Send nytt innspill",
910
928
  /** Tom tilstand: det finnes ikke noe «nytt» å sende når ingenting er sendt. */
911
929
  sendForste: "Send innspill",
@@ -1556,6 +1574,7 @@ function Kvittering({
1556
1574
  }
1557
1575
 
1558
1576
  // src/widget/MineInnspill.tsx
1577
+ var import_core = require("@innspel/core");
1559
1578
  var import_react9 = require("react");
1560
1579
  var import_react_native7 = require("react-native");
1561
1580
 
@@ -1581,14 +1600,74 @@ async function markerSvarSett(storage, n\u00E5 = Date.now()) {
1581
1600
 
1582
1601
  // src/widget/MineInnspill.tsx
1583
1602
  var import_jsx_runtime7 = require("react/jsx-runtime");
1584
- function MineInnspill({
1603
+ var MineInnspill = (0, import_react9.forwardRef)(function MineInnspill2({
1585
1604
  rader,
1586
1605
  laster,
1587
1606
  tenantName,
1588
1607
  onNytt,
1589
- storage
1590
- }) {
1608
+ storage,
1609
+ leggTil,
1610
+ onOppdatert,
1611
+ minTextLength,
1612
+ textMaxLength,
1613
+ utkastLager
1614
+ }, ref) {
1591
1615
  const tema = useTema();
1616
+ const min = minTextLength ?? 10;
1617
+ const maks = textMaxLength ?? 280;
1618
+ const [apen, setApen] = (0, import_react9.useState)(null);
1619
+ const [utkast, setUtkast] = (0, import_react9.useState)("");
1620
+ const [sender, setSender] = (0, import_react9.useState)(false);
1621
+ const [feil, setFeil] = (0, import_react9.useState)();
1622
+ const [lagtTil, setLagtTil] = (0, import_react9.useState)();
1623
+ const egetLager = (0, import_react9.useRef)(/* @__PURE__ */ new Map());
1624
+ const lager = utkastLager ?? egetLager.current;
1625
+ const rulleRef = (0, import_react9.useRef)(null);
1626
+ const kortY = (0, import_react9.useRef)(/* @__PURE__ */ new Map());
1627
+ const apneFelt = (id) => {
1628
+ setApen(id);
1629
+ setUtkast(lager.get(id) ?? "");
1630
+ setFeil(void 0);
1631
+ setLagtTil(void 0);
1632
+ const y = kortY.current.get(id);
1633
+ if (y !== void 0) rulleRef.current?.scrollTo({ y, animated: true });
1634
+ };
1635
+ const lukkFelt = () => {
1636
+ if (apen === null) return false;
1637
+ import_react_native7.Keyboard.dismiss();
1638
+ if (utkast.trim()) lager.set(apen, utkast);
1639
+ else lager.delete(apen);
1640
+ setApen(null);
1641
+ setUtkast("");
1642
+ setFeil(void 0);
1643
+ return true;
1644
+ };
1645
+ const avbryt = () => {
1646
+ if (apen !== null) lager.delete(apen);
1647
+ setApen(null);
1648
+ setUtkast("");
1649
+ setFeil(void 0);
1650
+ };
1651
+ (0, import_react9.useImperativeHandle)(ref, () => ({ lukkFelt }));
1652
+ const send = async (id) => {
1653
+ if (!leggTil) return;
1654
+ setSender(true);
1655
+ setFeil(void 0);
1656
+ try {
1657
+ const sak = await leggTil(id, utkast.trim());
1658
+ onOppdatert?.(sak);
1659
+ lager.delete(id);
1660
+ setApen(null);
1661
+ setUtkast("");
1662
+ setLagtTil(id);
1663
+ } catch (e) {
1664
+ const kode = e instanceof import_core.InnspelApiError ? e.code : void 0;
1665
+ const tekstFeil = kode === "addendum_limit_reached" ? tekst.tilleggTak : kode === "submission_closed" ? tekst.tilleggLukket : e instanceof import_core.InnspelApiError && e.message ? tekst.tilleggFeil(e.message) : e instanceof import_core.NettverksFeil ? tekst.tilleggIngenNett : tekst.tilleggFeilGenerisk;
1666
+ setFeil({ id, tekst: tekstFeil });
1667
+ } finally {
1668
+ setSender(false);
1669
+ }
1670
+ };
1592
1671
  const [visning, setVisning] = (0, import_react9.useState)(() => rader.map((rad) => ({ rad, nytt: false })));
1593
1672
  (0, import_react9.useEffect)(() => {
1594
1673
  let gjelder = true;
@@ -1606,82 +1685,198 @@ function MineInnspill({
1606
1685
  }, [storage, laster, rader]);
1607
1686
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native7.View, { style: { flex: 1, gap: tema.space.md }, children: [
1608
1687
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(H, { sub: tekst.mineUnder, children: tekst.mineTittel }),
1609
- laster ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native7.ActivityIndicator, { accessibilityLabel: "Henter innspillene dine", color: tema.color.textSecondary }) : rader.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Hint, { children: tekst.mineTom }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native7.ScrollView, { style: { flex: 1 }, contentContainerStyle: { gap: tema.space.sm }, children: visning.map(({ rad, nytt }) => {
1688
+ laster ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native7.ActivityIndicator, { accessibilityLabel: "Henter innspillene dine", color: tema.color.textSecondary }) : rader.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Hint, { children: tekst.mineTom }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native7.ScrollView, { ref: rulleRef, style: { flex: 1 }, contentContainerStyle: { gap: tema.space.sm }, keyboardShouldPersistTaps: "handled", children: visning.map(({ rad, nytt }) => {
1610
1689
  const venter = rad.pending === true;
1611
1690
  const v = venter ? venterVisning : statusVisning(rad.status, rad.type, rad.deadlineAt);
1612
1691
  const nokkel = venter ? rad.clientRef : rad.id;
1692
+ const sakId = venter ? void 0 : rad.id;
1613
1693
  const svar = venter ? void 0 : rad.reply;
1614
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Card, { dashed: venter, children: [
1615
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native7.View, { style: { flexDirection: "row", alignItems: "center", gap: tema.space.xs, flexWrap: "wrap" }, children: [
1616
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Hint, { children: venter ? `${tekst.mineIkkeSendt} \xB7 ${rad.type === "onske" ? tekst.onske : tekst.feil}` : tekst.sakHode(rad.type === "onske" ? tekst.onske : tekst.feil, rad.id) }),
1617
- nytt ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1618
- import_react_native7.Text,
1619
- {
1620
- testID: "nytt-svar",
1621
- style: {
1622
- color: tema.color.info,
1623
- backgroundColor: tema.color.infoBg,
1624
- fontSize: tema.font.tiny,
1625
- fontWeight: tema.weight.semibold,
1626
- borderRadius: tema.radius.pill,
1627
- paddingHorizontal: tema.space.sm
1694
+ const tillegg = venter ? [] : rad.addenda ?? [];
1695
+ const kanLeggeTil = !venter && !!leggTil && rad.canAddAddendum === true;
1696
+ const taketN\u00E5dd = !venter && rad.canAddAddendum === false && tillegg.length >= 3;
1697
+ const feltApent = sakId !== void 0 && apen === sakId;
1698
+ const brukt = utkast.length;
1699
+ const full = brukt >= maks;
1700
+ const visTeller = brukt >= maks * 0.8;
1701
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1702
+ import_react_native7.View,
1703
+ {
1704
+ onLayout: (e) => {
1705
+ if (sakId !== void 0) kortY.current.set(sakId, e.nativeEvent.layout.y);
1706
+ },
1707
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Card, { dashed: venter, children: [
1708
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native7.View, { style: { flexDirection: "row", alignItems: "center", gap: tema.space.xs, flexWrap: "wrap" }, children: [
1709
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Hint, { children: venter ? `${tekst.mineIkkeSendt} \xB7 ${rad.type === "onske" ? tekst.onske : tekst.feil}` : tekst.sakHode(rad.type === "onske" ? tekst.onske : tekst.feil, rad.id) }),
1710
+ nytt ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1711
+ import_react_native7.Text,
1712
+ {
1713
+ testID: "nytt-svar",
1714
+ style: {
1715
+ color: tema.color.info,
1716
+ backgroundColor: tema.color.infoBg,
1717
+ fontSize: tema.font.tiny,
1718
+ fontWeight: tema.weight.semibold,
1719
+ borderRadius: tema.radius.pill,
1720
+ paddingHorizontal: tema.space.sm
1721
+ },
1722
+ children: tekst.nyttSvar
1723
+ }
1724
+ ) : null
1725
+ ] }),
1726
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1727
+ import_react_native7.Text,
1728
+ {
1729
+ style: {
1730
+ color: tema.color.textPrimary,
1731
+ fontSize: tema.font.body,
1732
+ lineHeight: tema.lineHeight.body
1733
+ },
1734
+ children: rad.text
1735
+ }
1736
+ ),
1737
+ tillegg.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native7.View, { testID: `tillegg-${sakId}`, style: { gap: tema.space.xs }, children: tillegg.map((a) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1738
+ import_react_native7.View,
1739
+ {
1740
+ style: {
1741
+ borderLeftWidth: tema.hairline * 2,
1742
+ borderLeftColor: tema.color.border,
1743
+ paddingLeft: tema.space.sm,
1744
+ gap: tema.space.xs
1745
+ },
1746
+ children: [
1747
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native7.View, { style: { flexDirection: "row", alignItems: "center", gap: tema.space.xs }, children: [
1748
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Ikon, { navn: "add-outline", storrelse: "minste", farge: tema.color.textSecondary }),
1749
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native7.Text, { style: { color: tema.color.textSecondary, fontSize: tema.font.small }, children: tekst.duLaTil(formaterFrist(a.createdAt)) })
1750
+ ] }),
1751
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native7.Text, { style: { color: tema.color.textPrimary, fontSize: tema.font.small, lineHeight: tema.lineHeight.small }, children: a.text })
1752
+ ]
1628
1753
  },
1629
- children: tekst.nyttSvar
1630
- }
1631
- ) : null
1632
- ] }),
1633
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1634
- import_react_native7.Text,
1635
- {
1636
- style: {
1637
- color: tema.color.textPrimary,
1638
- fontSize: tema.font.body,
1639
- lineHeight: tema.lineHeight.body
1640
- },
1641
- children: rad.text
1642
- }
1643
- ),
1644
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native7.View, { style: { gap: tema.space.xs }, children: [
1645
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(StatusPill, { ikon: v.ikon, etikett: v.etikett, fg: v.fg, bg: v.bg }),
1646
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Hint, { children: v.lofte })
1647
- ] }),
1648
- !venter && rad.attachmentRemoved ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native7.View, { testID: `bilde-fjernet-${rad.id}`, style: { flexDirection: "row", gap: tema.space.xs, alignItems: "center" }, children: [
1649
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Ikon, { navn: "trash-outline", storrelse: "minste", farge: tema.color.textMuted }),
1650
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Hint, { children: tekst.bildeFjernet })
1651
- ] }) : null,
1652
- svar ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1653
- import_react_native7.View,
1654
- {
1655
- style: {
1656
- borderLeftWidth: tema.hairline * 2,
1657
- borderLeftColor: tema.color.brand,
1658
- paddingLeft: tema.space.sm,
1659
- gap: tema.space.xs
1660
- },
1661
- children: [
1662
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native7.Text, { style: { color: tema.color.textSecondary, fontSize: tema.font.small }, children: tenantName ? tekst.svarFra(tenantName) : tekst.svarFraGenerisk }),
1754
+ a.id
1755
+ )) }) : null,
1756
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native7.View, { style: { gap: tema.space.xs }, children: [
1757
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(StatusPill, { ikon: v.ikon, etikett: v.etikett, fg: v.fg, bg: v.bg }),
1758
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Hint, { children: v.lofte })
1759
+ ] }),
1760
+ sakId !== void 0 && lagtTil === sakId ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native7.Text, { accessibilityLiveRegion: "polite", testID: `lagt-til-${sakId}`, style: { color: tema.color.success, fontSize: tema.font.small }, children: tekst.lagtTil }) : null,
1761
+ feltApent ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native7.View, { testID: `tillegg-felt-${sakId}`, style: { gap: tema.space.sm }, children: [
1762
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native7.Text, { style: { color: tema.color.textSecondary, fontSize: tema.font.small }, children: tekst.leggTilMerLabel }),
1663
1763
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1664
- import_react_native7.Text,
1764
+ import_react_native7.TextInput,
1665
1765
  {
1766
+ testID: "tillegg-tekst",
1767
+ accessibilityLabel: tekst.leggTilMerLabel,
1768
+ value: utkast,
1769
+ onChangeText: setUtkast,
1770
+ maxLength: maks,
1771
+ multiline: true,
1772
+ numberOfLines: 3,
1773
+ autoFocus: true,
1774
+ placeholder: tekst.leggTilMerPlaceholder,
1775
+ placeholderTextColor: tema.color.textMuted,
1666
1776
  style: {
1777
+ backgroundColor: tema.color.surfaceRaised,
1778
+ borderWidth: tema.hairline,
1779
+ borderColor: full ? tema.color.warning : tema.color.borderStrong,
1780
+ borderRadius: tema.radius.md,
1781
+ padding: tema.space.md,
1667
1782
  color: tema.color.textPrimary,
1668
- fontSize: tema.font.small,
1669
- lineHeight: tema.lineHeight.small
1670
- },
1671
- children: svar.text
1783
+ fontSize: tema.font.body,
1784
+ lineHeight: tema.lineHeight.body,
1785
+ minHeight: tema.touch * 2,
1786
+ textAlignVertical: "top"
1787
+ }
1672
1788
  }
1673
- )
1674
- ]
1675
- }
1676
- ) : null
1677
- ] }, nokkel);
1789
+ ),
1790
+ visTeller ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1791
+ import_react_native7.Text,
1792
+ {
1793
+ testID: "tillegg-teller",
1794
+ accessibilityLiveRegion: full ? "assertive" : "polite",
1795
+ style: { alignSelf: "flex-end", color: full ? tema.color.warning : tema.color.textMuted, fontSize: tema.font.small },
1796
+ children: [
1797
+ brukt,
1798
+ " / ",
1799
+ maks,
1800
+ full ? tekst.tellerFull : ""
1801
+ ]
1802
+ }
1803
+ ) : null,
1804
+ feil?.id === sakId ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native7.Text, { accessibilityLiveRegion: "assertive", testID: `tillegg-feil-${sakId}`, style: { color: tema.color.danger, fontSize: tema.font.small, lineHeight: tema.lineHeight.small }, children: feil.tekst }) : null
1805
+ ] }) : kanLeggeTil ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1806
+ import_react_native7.Pressable,
1807
+ {
1808
+ testID: `legg-til-mer-${sakId}`,
1809
+ accessibilityRole: "button",
1810
+ accessibilityLabel: tekst.leggTilMerLabel,
1811
+ onPress: () => sakId !== void 0 && apneFelt(sakId),
1812
+ style: { alignSelf: "flex-start", minHeight: tema.touch, flexDirection: "row", alignItems: "center", gap: tema.space.xs, paddingHorizontal: tema.space.sm },
1813
+ children: [
1814
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Ikon, { navn: "add-outline", storrelse: "minste", farge: tema.color.actionSecondaryText }),
1815
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native7.Text, { style: { color: tema.color.actionSecondaryText, fontSize: tema.font.body, fontWeight: tema.weight.semibold }, children: tekst.leggTilMer })
1816
+ ]
1817
+ }
1818
+ ) : taketN\u00E5dd ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Hint, { children: tekst.tilleggTak }) : null,
1819
+ !venter && rad.attachmentRemoved ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native7.View, { testID: `bilde-fjernet-${rad.id}`, style: { flexDirection: "row", gap: tema.space.xs, alignItems: "center" }, children: [
1820
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Ikon, { navn: "trash-outline", storrelse: "minste", farge: tema.color.textMuted }),
1821
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Hint, { children: tekst.bildeFjernet })
1822
+ ] }) : null,
1823
+ svar ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1824
+ import_react_native7.View,
1825
+ {
1826
+ style: {
1827
+ borderLeftWidth: tema.hairline * 2,
1828
+ borderLeftColor: tema.color.brand,
1829
+ paddingLeft: tema.space.sm,
1830
+ gap: tema.space.xs
1831
+ },
1832
+ children: [
1833
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native7.Text, { style: { color: tema.color.textSecondary, fontSize: tema.font.small }, children: tenantName ? tekst.svarFra(tenantName) : tekst.svarFraGenerisk }),
1834
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1835
+ import_react_native7.Text,
1836
+ {
1837
+ style: {
1838
+ color: tema.color.textPrimary,
1839
+ fontSize: tema.font.small,
1840
+ lineHeight: tema.lineHeight.small
1841
+ },
1842
+ children: svar.text
1843
+ }
1844
+ )
1845
+ ]
1846
+ }
1847
+ ) : null
1848
+ ] })
1849
+ },
1850
+ nokkel
1851
+ );
1678
1852
  }) }),
1679
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Btn, { testID: "send-nytt", label: rader.length === 0 ? tekst.sendForste : tekst.sendNytt, onPress: onNytt })
1853
+ apen !== null ? (
1854
+ // F32: fotens plass — én primærhandling om gangen. «Send nytt innspill» er borte til
1855
+ // tillegget er sendt eller avbrutt, så første trykk aldri treffer feil knapp.
1856
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native7.View, { testID: "tillegg-fot", style: { gap: tema.space.sm }, children: [
1857
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native7.View, { style: { flexDirection: "row", gap: tema.space.sm }, children: [
1858
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1859
+ Btn,
1860
+ {
1861
+ testID: "tillegg-send",
1862
+ label: sender ? tekst.sender : tekst.send,
1863
+ disabled: utkast.length < min || sender,
1864
+ busy: sender,
1865
+ ...utkast.length < min ? { hint: tekst.forKort(min) } : {},
1866
+ onPress: () => void send(apen),
1867
+ grow: true
1868
+ }
1869
+ ),
1870
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Btn, { testID: "tillegg-avbryt", label: tekst.avbryt, variant: "secondary", onPress: avbryt, grow: true })
1871
+ ] }),
1872
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Hint, { children: tekst.leggTilMerHint })
1873
+ ] })
1874
+ ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Btn, { testID: "send-nytt", label: rader.length === 0 ? tekst.sendForste : tekst.sendNytt, onPress: onNytt })
1680
1875
  ] });
1681
- }
1876
+ });
1682
1877
 
1683
1878
  // src/widget/Skjermbilde.tsx
1684
- var import_core = require("@innspel/core");
1879
+ var import_core2 = require("@innspel/core");
1685
1880
  var import_react10 = require("react");
1686
1881
  var import_react_native8 = require("react-native");
1687
1882
  var import_jsx_runtime8 = require("react/jsx-runtime");
@@ -1708,7 +1903,7 @@ function Skjermbilde({
1708
1903
  return { width: Math.floor(bilde.width * s), height: Math.floor(bilde.height * s) };
1709
1904
  }, [ramme, bilde.width, bilde.height]);
1710
1905
  const automasker = (0, import_react10.useMemo)(
1711
- () => visning ? automaskerRot.map((r) => (0, import_core.skaler)(r, rotStorrelse, visning)) : [],
1906
+ () => visning ? automaskerRot.map((r) => (0, import_core2.skaler)(r, rotStorrelse, visning)) : [],
1712
1907
  [automaskerRot, rotStorrelse, visning]
1713
1908
  );
1714
1909
  const onLayout = (0, import_react10.useCallback)((e) => {
@@ -1719,13 +1914,13 @@ function Skjermbilde({
1719
1914
  const onGrant = (e) => {
1720
1915
  if (!visning) return;
1721
1916
  const p = punkt(e);
1722
- const treff = egne.findIndex((r) => (0, import_core.treffer)(p, r));
1917
+ const treff = egne.findIndex((r) => (0, import_core2.treffer)(p, r));
1723
1918
  if (treff >= 0) {
1724
1919
  setEgne((x) => x.filter((_, i) => i !== treff));
1725
1920
  return;
1726
1921
  }
1727
1922
  if (verktoy === "felt") {
1728
- const r = (0, import_core.trykkTilRekt)(p, { width: tema.touch * 4, height: tema.touch }, visning);
1923
+ const r = (0, import_core2.trykkTilRekt)(p, { width: tema.touch * 4, height: tema.touch }, visning);
1729
1924
  if (r) setEgne((x) => [...x, r]);
1730
1925
  return;
1731
1926
  }
@@ -1737,7 +1932,7 @@ function Skjermbilde({
1737
1932
  };
1738
1933
  const onRelease = () => {
1739
1934
  if (verktoy !== "pensel" || !visning || strok.current.length === 0) return;
1740
- const rekter = (0, import_core.strokTilRekter)(strok.current, screenRules.brushWidth, visning);
1935
+ const rekter = (0, import_core2.strokTilRekter)(strok.current, screenRules.brushWidth, visning);
1741
1936
  strok.current = [];
1742
1937
  if (rekter.length) setEgne((x) => [...x, ...rekter]);
1743
1938
  };
@@ -2089,9 +2284,12 @@ function Widget({
2089
2284
  setVedlegg(void 0);
2090
2285
  setSteg("felt");
2091
2286
  }, []);
2287
+ const mineRef = (0, import_react11.useRef)(null);
2288
+ const tilleggUtkast = (0, import_react11.useRef)(/* @__PURE__ */ new Map());
2092
2289
  const gaaTilbake = (0, import_react11.useCallback)(() => {
2093
2290
  setFeil(void 0);
2094
2291
  if (steg === "mine") {
2292
+ if (mineRef.current?.lukkFelt()) return;
2095
2293
  if (mineDirekte) lukk();
2096
2294
  else setSteg("valg");
2097
2295
  return;
@@ -2138,8 +2336,8 @@ function Widget({
2138
2336
  setSteg("kvittering");
2139
2337
  onSubmitted?.(res.status === "queued" ? { type: spor, queued: true } : { type: spor, queued: false, id: res.submission.id });
2140
2338
  } catch (e) {
2141
- if (e instanceof import_core2.InnspelQueueFullError) setFeil(e.userMessage);
2142
- else if (e instanceof import_core2.InnspelApiError) setFeil(e.message);
2339
+ if (e instanceof import_core3.InnspelQueueFullError) setFeil(e.userMessage);
2340
+ else if (e instanceof import_core3.InnspelApiError) setFeil(e.message);
2143
2341
  else setFeil("tjeneren svarte ikke.");
2144
2342
  } finally {
2145
2343
  setSender(false);
@@ -2153,7 +2351,7 @@ function Widget({
2153
2351
  setKvittering({ art: "jaOgsa", nr: res.id });
2154
2352
  setSteg("kvittering");
2155
2353
  } catch (e) {
2156
- setFeil(e instanceof import_core2.InnspelApiError ? e.message : "tjeneren svarte ikke.");
2354
+ setFeil(e instanceof import_core3.InnspelApiError ? e.message : "tjeneren svarte ikke.");
2157
2355
  } finally {
2158
2356
  setSender(false);
2159
2357
  }
@@ -2314,11 +2512,17 @@ function Widget({
2314
2512
  steg === "mine" ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2315
2513
  MineInnspill,
2316
2514
  {
2515
+ ref: mineRef,
2516
+ utkastLager: tilleggUtkast.current,
2317
2517
  storage: client.storage,
2318
2518
  rader: mine,
2319
2519
  laster: lasterMine,
2320
2520
  ...tenantName ? { tenantName } : {},
2321
- onNytt: nyttFraMine
2521
+ onNytt: nyttFraMine,
2522
+ leggTil: (id, text) => client.subjects.addAddendum(id, text),
2523
+ onOppdatert: (sak) => setMine((liste) => liste.map((r) => r.pending !== true && r.id === sak.id ? sak : r)),
2524
+ minTextLength: innstillinger.minTextLength,
2525
+ textMaxLength: innstillinger.textMaxLength
2322
2526
  }
2323
2527
  ) : null
2324
2528
  ]
@@ -2426,7 +2630,7 @@ function InnspelPrivate({ children, style }) {
2426
2630
  }
2427
2631
 
2428
2632
  // src/program/InnspelProgram.tsx
2429
- var import_core3 = require("@innspel/core");
2633
+ var import_core4 = require("@innspel/core");
2430
2634
  var import_react18 = require("react");
2431
2635
  var import_react_native16 = require("react-native");
2432
2636
 
@@ -2874,7 +3078,7 @@ function InnspelProgram({
2874
3078
  }
2875
3079
  setDialog(void 0);
2876
3080
  } catch (e) {
2877
- setSvarFeil(e instanceof import_core3.InnspelApiError ? e.message : "tjeneren svarte ikke.");
3081
+ setSvarFeil(e instanceof import_core4.InnspelApiError ? e.message : "tjeneren svarte ikke.");
2878
3082
  } finally {
2879
3083
  setSender(false);
2880
3084
  }
@@ -2903,7 +3107,7 @@ function InnspelProgram({
2903
3107
  setViserAksept(false);
2904
3108
  onEndring?.(ny);
2905
3109
  } catch (e) {
2906
- setFeil(e instanceof import_core3.InnspelApiError ? e.message : "tjeneren svarte ikke.");
3110
+ setFeil(e instanceof import_core4.InnspelApiError ? e.message : "tjeneren svarte ikke.");
2907
3111
  } finally {
2908
3112
  setSender(false);
2909
3113
  }
@@ -2917,7 +3121,7 @@ function InnspelProgram({
2917
3121
  setViserGaaUt(false);
2918
3122
  onEndring?.(null);
2919
3123
  } catch (e) {
2920
- setFeil(e instanceof import_core3.InnspelApiError ? e.message : "tjeneren svarte ikke.");
3124
+ setFeil(e instanceof import_core4.InnspelApiError ? e.message : "tjeneren svarte ikke.");
2921
3125
  } finally {
2922
3126
  setSender(false);
2923
3127
  }