@innspel/react-native 0.4.1 → 0.5.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
@@ -4,11 +4,21 @@ Innsendingswidgeten for React Native. Et ark over vertsappen din — aldri en
4
4
  flytende knapp over innholdet.
5
5
 
6
6
  ```bash
7
- npm install @innspel/react-native @innspel/core
7
+ npm install @innspel/react-native @innspel/core react-native-safe-area-context
8
8
  ```
9
9
 
10
- `react` og `react-native` er peer-avhengigheter. Widgeten krever ikke Expo, men
11
- virker i Expo.
10
+ I Expo: `npx expo install react-native-safe-area-context`, så versjonen passer SDK-et.
11
+
12
+ `react`, `react-native` og `react-native-safe-area-context` (4.0 eller nyere) er
13
+ peer-avhengigheter. Widgeten krever ikke Expo, men virker i Expo.
14
+
15
+ **Hvorfor safe-area-context:** på edge-to-edge (Android 15+, Expo SDK 53+) tegner
16
+ React Natives `Modal` under status- og navigasjonslinja uansett props, og React
17
+ Native har ingen egen måte å lese de linjenes høyde på Android. Uten insets havner
18
+ Send-knappen under navigasjonslinja. Har appen en `SafeAreaProvider` (expo-router har
19
+ det), leses insetsene derfra; ellers brukes vinduets insets fra oppstart. Du trenger
20
+ ikke legge til en provider for widgetens skyld. Arket løftes også over tastaturet,
21
+ siden vinduet ikke lenger krymper for det på edge-to-edge.
12
22
 
13
23
  ## Quickstart
14
24
 
package/dist/index.cjs CHANGED
@@ -143,6 +143,7 @@ var t = {
143
143
  pill: 999
144
144
  },
145
145
  font: {
146
+ display: 40,
146
147
  h1: 24,
147
148
  h2: 21,
148
149
  h3: 18,
@@ -151,6 +152,7 @@ var t = {
151
152
  tiny: 11
152
153
  },
153
154
  lineHeight: {
155
+ display: 48,
154
156
  h1: 30,
155
157
  h2: 27,
156
158
  h3: 24,
@@ -169,6 +171,7 @@ var t = {
169
171
  base: 200,
170
172
  slow: 320
171
173
  },
174
+ icon: { inline: 20, minste: 16 },
172
175
  touch: 48,
173
176
  screenPadding: 24,
174
177
  hairline: 1
@@ -227,6 +230,7 @@ var light = {
227
230
  pill: 999
228
231
  },
229
232
  font: {
233
+ display: 40,
230
234
  h1: 24,
231
235
  h2: 21,
232
236
  h3: 18,
@@ -235,6 +239,7 @@ var light = {
235
239
  tiny: 11
236
240
  },
237
241
  lineHeight: {
242
+ display: 48,
238
243
  h1: 30,
239
244
  h2: 27,
240
245
  h3: 24,
@@ -253,6 +258,7 @@ var light = {
253
258
  base: 200,
254
259
  slow: 320
255
260
  },
261
+ icon: { inline: 20, minste: 16 },
256
262
  touch: 48,
257
263
  screenPadding: 24,
258
264
  hairline: 1
@@ -286,6 +292,7 @@ function useTema() {
286
292
  var import_core2 = require("@innspel/core");
287
293
  var import_react10 = require("react");
288
294
  var import_react_native9 = require("react-native");
295
+ var import_react_native_safe_area_context = require("react-native-safe-area-context");
289
296
 
290
297
  // src/widget/Felt.tsx
291
298
  var import_react4 = require("react");
@@ -506,7 +513,13 @@ var tekst = {
506
513
  rettesI: (versjon) => `Rettes i ${versjon}`,
507
514
  rettetI: (versjon) => `Rettet i ${versjon}`,
508
515
  // 2d + 2e — feltet og kontekstlinja
509
- feltLabelFeil: "Din feil",
516
+ /**
517
+ * «Ditt innspill», ikke «Din feil» (DD-54). «Din» festet saken til personen, og
518
+ * «feil» karakteriserte den før noen hadde lest den — innsenderen leste det som
519
+ * skyld. Ønskesporet beholder «Ditt ønske»: et ønske er ingen feil, og der finnes
520
+ * ikke problemet. De to står aldri ved siden av hverandre; sporet velges før dette.
521
+ */
522
+ feltLabelFeil: "Ditt innspill",
510
523
  feltLabelOnske: "Ditt \xF8nske",
511
524
  /** DD-45: to spørsmål i feilsporet. Kilde: Sentry «What's the bug? What did you expect?» */
512
525
  placeholderFeil: "Hva skjedde? Hva forventet du?",
@@ -1475,6 +1488,7 @@ function Widget({
1475
1488
  tenantName
1476
1489
  }) {
1477
1490
  const tema = useTema();
1491
+ const insets = (0, import_react10.useContext)(import_react_native_safe_area_context.SafeAreaInsetsContext) ?? import_react_native_safe_area_context.initialWindowMetrics?.insets ?? { top: 0, bottom: 0, left: 0, right: 0 };
1478
1492
  const skjermbilde = useSkjermbilde();
1479
1493
  const previewRef = (0, import_react10.useRef)(null);
1480
1494
  const [steg, setSteg] = (0, import_react10.useState)("valg");
@@ -1668,108 +1682,119 @@ function Widget({
1668
1682
  animationType: "slide",
1669
1683
  onRequestClose: lukk,
1670
1684
  accessibilityViewIsModal: true,
1671
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native9.View, { style: { flex: 1, backgroundColor: tema.color.scrim, justifyContent: "flex-end" }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1672
- import_react_native9.View,
1685
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1686
+ import_react_native9.KeyboardAvoidingView,
1673
1687
  {
1674
- testID: "innspel-widget",
1675
- accessibilityViewIsModal: true,
1676
- accessibilityRole: "none",
1677
- style: {
1678
- backgroundColor: tema.color.bg,
1679
- borderTopLeftRadius: tema.radius.lg * 2,
1680
- borderTopRightRadius: tema.radius.lg * 2,
1681
- padding: tema.screenPadding,
1682
- gap: tema.space.md,
1683
- maxHeight: "92%",
1684
- minHeight: "60%"
1685
- },
1686
- children: [
1687
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native9.View, { style: { flexDirection: "row", justifyContent: "space-between", alignItems: "center" }, children: [
1688
- steg === "skjermbilde" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Btn, { variant: "ghost", testID: "tilbake", ikon: "\u2190", label: tekst.tilbake, onPress: fjernBilde }) : steg !== "valg" && steg !== "kvittering" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Btn, { variant: "ghost", testID: "tilbake", ikon: "\u2190", label: tekst.tilbake, onPress: nullstill }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native9.View, {}),
1689
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1690
- import_react_native9.Pressable,
1691
- {
1692
- testID: "lukk",
1693
- accessibilityRole: "button",
1694
- accessibilityLabel: tekst.lukk,
1695
- onPress: lukk,
1696
- style: { minWidth: tema.touch, minHeight: tema.touch, alignItems: "center", justifyContent: "center" },
1697
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native9.Text, { style: { color: tema.color.textSecondary, fontSize: tema.font.body }, children: "\u2715" })
1698
- }
1699
- )
1700
- ] }),
1701
- feil ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Banner, { live: true, ikon: "\u26A0", tone: "danger", children: tekst.sendefeilBanner(feil) }) : null,
1702
- steg === "valg" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
1703
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Valg, { onVelg: velgSpor }),
1704
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Btn, { variant: "ghost", testID: "mine-innspill", ikon: "\u{1F4CB}", label: tekst.mineTittel, onPress: visMine })
1705
- ] }) : null,
1706
- steg === "kjenteFeil" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1707
- KjenteFeil,
1708
- {
1709
- kort,
1710
- spor,
1711
- laster: lasterKort,
1712
- onJaOgsa: jaOgsa,
1713
- onLigner: (k) => {
1714
- setLenketTil(k);
1715
- setSteg("felt");
1716
- },
1717
- onNei: () => spor === "onske" ? void send() : setSteg("felt")
1718
- }
1719
- ) : null,
1720
- steg === "felt" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1721
- Felt,
1722
- {
1723
- spor,
1724
- verdi,
1725
- onEndre: endreTekst,
1726
- minTextLength: innstillinger.minTextLength,
1727
- textMaxLength: innstillinger.textMaxLength,
1728
- kontekst: client.context,
1729
- fjernedeFelter: fjernede,
1730
- onFjernKontekst: (f) => setFjernede((x) => [...x, f]),
1731
- ...lenketTil ? { lenketTil, onFjernLenke: () => setLenketTil(void 0) } : {},
1732
- funn,
1733
- onSend: send,
1734
- sender,
1735
- ...skjermbildeMulig ? { onSkjermbilde: taSkjermbilde } : {},
1736
- harVedlegg: vedlegg !== void 0,
1737
- onFjernVedlegg: fjernBilde
1738
- }
1739
- ) : null,
1740
- steg === "skjermbilde" && bilde ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1741
- Skjermbilde,
1742
- {
1743
- bilde,
1744
- automaskerRot: automasker,
1745
- rotStorrelse,
1746
- previewRef,
1747
- komponerer,
1748
- onFjern: fjernBilde,
1749
- onLeggVed: leggVedBilde
1750
- }
1751
- ) : null,
1752
- steg === "kvittering" && kvittering ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1753
- Kvittering,
1754
- {
1755
- art: kvittering.art,
1756
- ...kvittering.nr ? { saksnummer: kvittering.nr } : {},
1757
- ...kvittering.vedlegg ? { vedlegg: kvittering.vedlegg } : {},
1758
- onLukk: lukk
1759
- }
1760
- ) : null,
1761
- steg === "mine" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1762
- MineInnspill,
1763
- {
1764
- rader: mine,
1765
- laster: lasterMine,
1766
- ...tenantName ? { tenantName } : {},
1767
- onNytt: nullstill
1768
- }
1769
- ) : null
1770
- ]
1688
+ behavior: "padding",
1689
+ keyboardVerticalOffset: -insets.bottom,
1690
+ style: { flex: 1, backgroundColor: tema.color.scrim, justifyContent: "flex-end", paddingTop: insets.top },
1691
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1692
+ import_react_native9.View,
1693
+ {
1694
+ testID: "innspel-widget",
1695
+ accessibilityViewIsModal: true,
1696
+ accessibilityRole: "none",
1697
+ style: {
1698
+ backgroundColor: tema.color.bg,
1699
+ borderTopLeftRadius: tema.radius.lg * 2,
1700
+ borderTopRightRadius: tema.radius.lg * 2,
1701
+ padding: tema.screenPadding,
1702
+ paddingBottom: tema.screenPadding + insets.bottom,
1703
+ paddingLeft: tema.screenPadding + insets.left,
1704
+ paddingRight: tema.screenPadding + insets.right,
1705
+ gap: tema.space.md,
1706
+ maxHeight: "92%",
1707
+ minHeight: "60%"
1708
+ },
1709
+ children: [
1710
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native9.View, { style: { flexDirection: "row", justifyContent: "space-between", alignItems: "center" }, children: [
1711
+ steg === "skjermbilde" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Btn, { variant: "ghost", testID: "tilbake", ikon: "\u2190", label: tekst.tilbake, onPress: fjernBilde }) : steg !== "valg" && steg !== "kvittering" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Btn, { variant: "ghost", testID: "tilbake", ikon: "\u2190", label: tekst.tilbake, onPress: nullstill }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native9.View, {}),
1712
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1713
+ import_react_native9.Pressable,
1714
+ {
1715
+ testID: "lukk",
1716
+ accessibilityRole: "button",
1717
+ accessibilityLabel: tekst.lukk,
1718
+ onPress: lukk,
1719
+ style: { minWidth: tema.touch, minHeight: tema.touch, alignItems: "center", justifyContent: "center" },
1720
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native9.Text, { style: { color: tema.color.textSecondary, fontSize: tema.font.body }, children: "\u2715" })
1721
+ }
1722
+ )
1723
+ ] }),
1724
+ feil ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Banner, { live: true, ikon: "\u26A0", tone: "danger", children: tekst.sendefeilBanner(feil) }) : null,
1725
+ steg === "valg" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
1726
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Valg, { onVelg: velgSpor }),
1727
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Btn, { variant: "ghost", testID: "mine-innspill", ikon: "\u{1F4CB}", label: tekst.mineTittel, onPress: visMine })
1728
+ ] }) : null,
1729
+ steg === "kjenteFeil" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1730
+ KjenteFeil,
1731
+ {
1732
+ kort,
1733
+ spor,
1734
+ laster: lasterKort,
1735
+ onJaOgsa: jaOgsa,
1736
+ onLigner: (k) => {
1737
+ setLenketTil(k);
1738
+ setSteg("felt");
1739
+ },
1740
+ onNei: () => spor === "onske" ? void send() : setSteg("felt")
1741
+ }
1742
+ ) : null,
1743
+ steg === "felt" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1744
+ Felt,
1745
+ {
1746
+ spor,
1747
+ verdi,
1748
+ onEndre: endreTekst,
1749
+ minTextLength: innstillinger.minTextLength,
1750
+ textMaxLength: innstillinger.textMaxLength,
1751
+ kontekst: client.context,
1752
+ fjernedeFelter: fjernede,
1753
+ onFjernKontekst: (f) => setFjernede((x) => [...x, f]),
1754
+ ...lenketTil ? { lenketTil, onFjernLenke: () => setLenketTil(void 0) } : {},
1755
+ funn,
1756
+ onSend: send,
1757
+ sender,
1758
+ ...skjermbildeMulig ? { onSkjermbilde: taSkjermbilde } : {},
1759
+ harVedlegg: vedlegg !== void 0,
1760
+ onFjernVedlegg: fjernBilde
1761
+ }
1762
+ ) : null,
1763
+ steg === "skjermbilde" && bilde ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1764
+ Skjermbilde,
1765
+ {
1766
+ bilde,
1767
+ automaskerRot: automasker,
1768
+ rotStorrelse,
1769
+ previewRef,
1770
+ komponerer,
1771
+ onFjern: fjernBilde,
1772
+ onLeggVed: leggVedBilde
1773
+ }
1774
+ ) : null,
1775
+ steg === "kvittering" && kvittering ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1776
+ Kvittering,
1777
+ {
1778
+ art: kvittering.art,
1779
+ ...kvittering.nr ? { saksnummer: kvittering.nr } : {},
1780
+ ...kvittering.vedlegg ? { vedlegg: kvittering.vedlegg } : {},
1781
+ onLukk: lukk
1782
+ }
1783
+ ) : null,
1784
+ steg === "mine" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1785
+ MineInnspill,
1786
+ {
1787
+ rader: mine,
1788
+ laster: lasterMine,
1789
+ ...tenantName ? { tenantName } : {},
1790
+ onNytt: nullstill
1791
+ }
1792
+ ) : null
1793
+ ]
1794
+ }
1795
+ )
1771
1796
  }
1772
- ) })
1797
+ )
1773
1798
  }
1774
1799
  );
1775
1800
  }