@lmb-it/kitsconcerto-native 0.1.261 → 0.1.262
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/animations/index.cjs +1 -2
- package/animations/index.cjs.map +1 -1
- package/animations/index.js +1 -2
- package/animations/index.js.map +1 -1
- package/apps/mobile/src/Core/Dropdown/index.cjs +39 -5
- package/apps/mobile/src/Core/Dropdown/index.cjs.map +1 -1
- package/apps/mobile/src/Core/Dropdown/index.js +39 -5
- package/apps/mobile/src/Core/Dropdown/index.js.map +1 -1
- package/apps/mobile/src/Core/MultiSelect/index.cjs +15 -3
- package/apps/mobile/src/Core/MultiSelect/index.cjs.map +1 -1
- package/apps/mobile/src/Core/MultiSelect/index.js +15 -3
- package/apps/mobile/src/Core/MultiSelect/index.js.map +1 -1
- package/components/overlay/Dialog/index.cjs +2 -2
- package/components/overlay/Dialog/index.cjs.map +1 -1
- package/components/overlay/Dialog/index.js +3 -3
- package/components/overlay/Dialog/index.js.map +1 -1
- package/form/selects/Dropdown/index.cjs +3 -0
- package/form/selects/Dropdown/index.cjs.map +1 -1
- package/form/selects/Dropdown/index.js +3 -0
- package/form/selects/Dropdown/index.js.map +1 -1
- package/form/selects/MultiSelect/index.cjs +3 -0
- package/form/selects/MultiSelect/index.cjs.map +1 -1
- package/form/selects/MultiSelect/index.js +3 -0
- package/form/selects/MultiSelect/index.js.map +1 -1
- package/form-renderer/hooks/useFieldLogic.cjs +1 -1
- package/form-renderer/hooks/useFieldLogic.cjs.map +1 -1
- package/form-renderer/hooks/useFieldLogic.js +1 -1
- package/form-renderer/hooks/useFieldLogic.js.map +1 -1
- package/package.json +1 -1
package/animations/index.cjs
CHANGED
|
@@ -29,8 +29,7 @@ const overlayAnimations = {
|
|
|
29
29
|
// overshoot. Exit: timed slide-down.
|
|
30
30
|
sheet: {
|
|
31
31
|
enter: { damping: 30, stiffness: 400, mass: 1 },
|
|
32
|
-
exitDuration: 150
|
|
33
|
-
},
|
|
32
|
+
exitDuration: 150},
|
|
34
33
|
// ── Toast ────────────────────────────────────────────────
|
|
35
34
|
// One element owns the entrance: FadeInUp/FadeInDown animate opacity AND
|
|
36
35
|
// translateY together, so there is no second concurrent layer to desync.
|
package/animations/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../../../src/animations/index.ts"],"sourcesContent":["/**\n * ════════════════════════════════════════════════════════════════════════\n * Overlay animation tuning — EDIT THIS FILE TO CONTROL ALL OVERLAY MOTION\n * ════════════════════════════════════════════════════════════════════════\n *\n * Every in/out animation value used by the animated overlay components on\n * React Native (reanimated) lives here. Change a number and it updates\n * everywhere that animation is used — no need to touch the component files.\n *\n * Consumed by (native):\n * • components/overlay/Dialog/index.native.tsx\n * • components/overlay/ConfirmDialog/index.native.tsx\n * • components/overlay/Toast/index.native.tsx\n *\n * Two kinds of value:\n * • spring → reanimated `.springify().damping(d).stiffness(s)` (+ optional `.delay`)\n * - damping ↓ lower = bouncier, longer settle\n * - stiffness ↑ higher = snappier, faster\n * • duration → milliseconds for `.duration(ms)` (timing-based fade/slide)\n */\n\nexport interface ISpringConfig {\n /** reanimated `.damping()` — lower = bouncier / slower to settle. */\n damping: number;\n /** reanimated `.stiffness()` — higher = snappier / faster. */\n stiffness: number;\n /** reanimated `.mass()` — heavier = slower / more inertia. Defaults to 1. */\n mass?: number;\n /** reanimated `.delay()` in ms — wait before the animation starts. */\n delay?: number;\n}\n\nexport interface IOverlayAnimations {\n /** Dimmed backdrop behind every overlay (fade in/out). */\n scrim: { enterDuration: number; exitDuration: number };\n /** Centered Dialog panel (zoom-in spring in, timed zoom-out). */\n dialog: { enter: ISpringConfig; exitDuration: number };\n /** Confirm: centered panel, its floating icon bubble, and the content-only/prompt panel. */\n confirm: { enter: ISpringConfig; icon: ISpringConfig; content: ISpringConfig; exitDuration: number };\n
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../../src/animations/index.ts"],"sourcesContent":["/**\n * ════════════════════════════════════════════════════════════════════════\n * Overlay animation tuning — EDIT THIS FILE TO CONTROL ALL OVERLAY MOTION\n * ════════════════════════════════════════════════════════════════════════\n *\n * Every in/out animation value used by the animated overlay components on\n * React Native (reanimated) lives here. Change a number and it updates\n * everywhere that animation is used — no need to touch the component files.\n *\n * Consumed by (native):\n * • components/overlay/Dialog/index.native.tsx\n * • components/overlay/ConfirmDialog/index.native.tsx\n * • components/overlay/Toast/index.native.tsx\n *\n * Two kinds of value:\n * • spring → reanimated `.springify().damping(d).stiffness(s)` (+ optional `.delay`)\n * - damping ↓ lower = bouncier, longer settle\n * - stiffness ↑ higher = snappier, faster\n * • duration → milliseconds for `.duration(ms)` (timing-based fade/slide)\n */\n\nexport interface ISpringConfig {\n /** reanimated `.damping()` — lower = bouncier / slower to settle. */\n damping: number;\n /** reanimated `.stiffness()` — higher = snappier / faster. */\n stiffness: number;\n /** reanimated `.mass()` — heavier = slower / more inertia. Defaults to 1. */\n mass?: number;\n /** reanimated `.delay()` in ms — wait before the animation starts. */\n delay?: number;\n}\n\nexport interface IOverlayAnimations {\n /** Dimmed backdrop behind every overlay (fade in/out). */\n scrim: { enterDuration: number; exitDuration: number };\n /** Centered Dialog panel (zoom-in spring in, timed zoom-out). */\n dialog: { enter: ISpringConfig; exitDuration: number };\n /** Confirm: centered panel, its floating icon bubble, and the content-only/prompt panel. */\n confirm: { enter: ISpringConfig; icon: ISpringConfig; content: ISpringConfig; exitDuration: number };\n /**\n * Bottom sheet shared by Dialog & Confirm (slide-up spring in, timed\n * slide-down out).\n *\n * `keepMotionWhenReduced` asks Reanimated to run this one even when the\n * reader has iOS \"Reduce Motion\" on — see the note beside the value.\n */\n sheet: { enter: ISpringConfig; exitDuration: number; keepMotionWhenReduced: boolean };\n /** Toast — single merged fade+slide entrance, timed exit, re-layout, keyboard gap. */\n toast: {\n enter: ISpringConfig;\n exitDuration: number;\n layoutDuration: number;\n keyboardGap: number;\n };\n}\n\nexport const overlayAnimations: IOverlayAnimations = {\n // ── Backdrop / scrim ─────────────────────────────────────\n scrim: {\n enterDuration: 120,\n exitDuration: 100,\n },\n\n // ── Centered Dialog panel ────────────────────────────────\n // Enter: critically-ish damped spring — snappy but settles cleanly (no\n // ringing). Exit: timing-based zoom-out (springs are enter-only).\n dialog: {\n enter: { damping: 26, stiffness: 420, mass: 1 },\n exitDuration: 120,\n },\n\n // ── Confirm dialog ───────────────────────────────────────\n confirm: {\n /** Centered confirm panel pop. */\n enter: { damping: 26, stiffness: 420, mass: 1 },\n /** Floating severity-icon bubble — pops in slightly after the panel. */\n icon: { damping: 26, stiffness: 420, mass: 1, delay: 60 },\n /** Content-only / prompt panel (no header/buttons chrome). */\n content: { damping: 26, stiffness: 420, mass: 1 },\n /** Timed zoom-out for the confirm center/content panels. */\n exitDuration: 120,\n },\n\n // ── Bottom sheet (Dialog + Confirm, position=\"bottom\") ───\n // Slightly heavier damping/lower stiffness so the sheet glides up without\n // overshoot. Exit: timed slide-down.\n sheet: {\n enter: { damping: 30, stiffness: 400, mass: 1 },\n exitDuration: 150,\n /*\n * ⛔ REDUCE MOTION TURNS THIS OFF, AND THAT READS AS A FADE. Reanimated\n * honours iOS \"Reduce Motion\" by default: the entering/exiting\n * animation is skipped and the panel simply appears, so the only thing\n * left moving is the scrim's opacity. Measured on an iPhone 16 Pro\n * simulator, sheet top edge per frame at 30fps:\n * Reduce Motion OFF — 1924 → 1302 → 898 → 683 → 655 px\n * Reduce Motion ON — 655 in a single frame\n * That second row is exactly the \"it still fades\" report.\n *\n * A bottom sheet is kept moving because the platform keeps it moving:\n * iOS's own sheets still slide up under Reduce Motion — what that\n * setting removes is parallax and zoom, not the presentation of a\n * sheet. The centred Dialog's ZoomIn and the scrim's fade are NOT\n * overridden; they stay on the system default.\n */\n keepMotionWhenReduced: true,\n },\n\n // ── Toast ────────────────────────────────────────────────\n // One element owns the entrance: FadeInUp/FadeInDown animate opacity AND\n // translateY together, so there is no second concurrent layer to desync.\n toast: {\n /** Merged fade+slide entrance (position-appropriate direction). */\n enter: { damping: 30, stiffness: 400, mass: 1 },\n /** Timed fade+slide out. */\n exitDuration: 120,\n /** Re-positioning when toasts stack/unstack. */\n layoutDuration: 150,\n /** Gap (pt) kept between a bottom toast and the keyboard when it opens. */\n keyboardGap: 8,\n },\n};\n\nexport default overlayAnimations;\n"],"names":[],"mappings":";;AAwDO,MAAM,iBAAA,GAAwC;AAAA;AAAA,EAEjD,KAAA,EAAO;AAAA,IACH,aAAA,EAAe,GAAA;AAAA,IACf,YAAA,EAAc;AAAA,GAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAA,EAAQ;AAAA,IACJ,OAAO,EAAE,OAAA,EAAS,IAAI,SAAA,EAAW,GAAA,EAAK,MAAM,CAAA,EAAE;AAAA,IAC9C,YAAA,EAAc;AAAA,GAClB;AAAA;AAAA,EAGA,OAAA,EAAS;AAAA;AAAA,IAEL,OAAO,EAAE,OAAA,EAAS,IAAI,SAAA,EAAW,GAAA,EAAK,MAAM,CAAA,EAAE;AAAA;AAAA,IAE9C,IAAA,EAAM,EAAE,OAAA,EAAS,EAAA,EAAI,WAAW,GAAA,EAAK,IAAA,EAAM,CAAA,EAAG,KAAA,EAAO,EAAA,EAAG;AAAA;AAAA,IAExD,SAAS,EAAE,OAAA,EAAS,IAAI,SAAA,EAAW,GAAA,EAAK,MAAM,CAAA,EAAE;AAAA;AAAA,IAEhD,YAAA,EAAc;AAAA,GAClB;AAAA;AAAA;AAAA;AAAA,EAKA,KAAA,EAAO;AAAA,IACH,OAAO,EAAE,OAAA,EAAS,IAAI,SAAA,EAAW,GAAA,EAAK,MAAM,CAAA,EAAE;AAAA,IAC9C,YAAA,EAAc,GAkBlB,CAAA;AAAA;AAAA;AAAA;AAAA,EAKA,KAAA,EAAO;AAAA;AAAA,IAEH,OAAO,EAAE,OAAA,EAAS,IAAI,SAAA,EAAW,GAAA,EAAK,MAAM,CAAA,EAAE;AAAA;AAAA,IAE9C,YAAA,EAAc,GAAA;AAAA;AAAA,IAEd,cAAA,EAAgB,GAAA;AAAA;AAAA,IAEhB,WAAA,EAAa;AAAA;AAErB;;;;"}
|
package/animations/index.js
CHANGED
|
@@ -27,8 +27,7 @@ const overlayAnimations = {
|
|
|
27
27
|
// overshoot. Exit: timed slide-down.
|
|
28
28
|
sheet: {
|
|
29
29
|
enter: { damping: 30, stiffness: 400, mass: 1 },
|
|
30
|
-
exitDuration: 150
|
|
31
|
-
},
|
|
30
|
+
exitDuration: 150},
|
|
32
31
|
// ── Toast ────────────────────────────────────────────────
|
|
33
32
|
// One element owns the entrance: FadeInUp/FadeInDown animate opacity AND
|
|
34
33
|
// translateY together, so there is no second concurrent layer to desync.
|
package/animations/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../src/animations/index.ts"],"sourcesContent":["/**\n * ════════════════════════════════════════════════════════════════════════\n * Overlay animation tuning — EDIT THIS FILE TO CONTROL ALL OVERLAY MOTION\n * ════════════════════════════════════════════════════════════════════════\n *\n * Every in/out animation value used by the animated overlay components on\n * React Native (reanimated) lives here. Change a number and it updates\n * everywhere that animation is used — no need to touch the component files.\n *\n * Consumed by (native):\n * • components/overlay/Dialog/index.native.tsx\n * • components/overlay/ConfirmDialog/index.native.tsx\n * • components/overlay/Toast/index.native.tsx\n *\n * Two kinds of value:\n * • spring → reanimated `.springify().damping(d).stiffness(s)` (+ optional `.delay`)\n * - damping ↓ lower = bouncier, longer settle\n * - stiffness ↑ higher = snappier, faster\n * • duration → milliseconds for `.duration(ms)` (timing-based fade/slide)\n */\n\nexport interface ISpringConfig {\n /** reanimated `.damping()` — lower = bouncier / slower to settle. */\n damping: number;\n /** reanimated `.stiffness()` — higher = snappier / faster. */\n stiffness: number;\n /** reanimated `.mass()` — heavier = slower / more inertia. Defaults to 1. */\n mass?: number;\n /** reanimated `.delay()` in ms — wait before the animation starts. */\n delay?: number;\n}\n\nexport interface IOverlayAnimations {\n /** Dimmed backdrop behind every overlay (fade in/out). */\n scrim: { enterDuration: number; exitDuration: number };\n /** Centered Dialog panel (zoom-in spring in, timed zoom-out). */\n dialog: { enter: ISpringConfig; exitDuration: number };\n /** Confirm: centered panel, its floating icon bubble, and the content-only/prompt panel. */\n confirm: { enter: ISpringConfig; icon: ISpringConfig; content: ISpringConfig; exitDuration: number };\n
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/animations/index.ts"],"sourcesContent":["/**\n * ════════════════════════════════════════════════════════════════════════\n * Overlay animation tuning — EDIT THIS FILE TO CONTROL ALL OVERLAY MOTION\n * ════════════════════════════════════════════════════════════════════════\n *\n * Every in/out animation value used by the animated overlay components on\n * React Native (reanimated) lives here. Change a number and it updates\n * everywhere that animation is used — no need to touch the component files.\n *\n * Consumed by (native):\n * • components/overlay/Dialog/index.native.tsx\n * • components/overlay/ConfirmDialog/index.native.tsx\n * • components/overlay/Toast/index.native.tsx\n *\n * Two kinds of value:\n * • spring → reanimated `.springify().damping(d).stiffness(s)` (+ optional `.delay`)\n * - damping ↓ lower = bouncier, longer settle\n * - stiffness ↑ higher = snappier, faster\n * • duration → milliseconds for `.duration(ms)` (timing-based fade/slide)\n */\n\nexport interface ISpringConfig {\n /** reanimated `.damping()` — lower = bouncier / slower to settle. */\n damping: number;\n /** reanimated `.stiffness()` — higher = snappier / faster. */\n stiffness: number;\n /** reanimated `.mass()` — heavier = slower / more inertia. Defaults to 1. */\n mass?: number;\n /** reanimated `.delay()` in ms — wait before the animation starts. */\n delay?: number;\n}\n\nexport interface IOverlayAnimations {\n /** Dimmed backdrop behind every overlay (fade in/out). */\n scrim: { enterDuration: number; exitDuration: number };\n /** Centered Dialog panel (zoom-in spring in, timed zoom-out). */\n dialog: { enter: ISpringConfig; exitDuration: number };\n /** Confirm: centered panel, its floating icon bubble, and the content-only/prompt panel. */\n confirm: { enter: ISpringConfig; icon: ISpringConfig; content: ISpringConfig; exitDuration: number };\n /**\n * Bottom sheet shared by Dialog & Confirm (slide-up spring in, timed\n * slide-down out).\n *\n * `keepMotionWhenReduced` asks Reanimated to run this one even when the\n * reader has iOS \"Reduce Motion\" on — see the note beside the value.\n */\n sheet: { enter: ISpringConfig; exitDuration: number; keepMotionWhenReduced: boolean };\n /** Toast — single merged fade+slide entrance, timed exit, re-layout, keyboard gap. */\n toast: {\n enter: ISpringConfig;\n exitDuration: number;\n layoutDuration: number;\n keyboardGap: number;\n };\n}\n\nexport const overlayAnimations: IOverlayAnimations = {\n // ── Backdrop / scrim ─────────────────────────────────────\n scrim: {\n enterDuration: 120,\n exitDuration: 100,\n },\n\n // ── Centered Dialog panel ────────────────────────────────\n // Enter: critically-ish damped spring — snappy but settles cleanly (no\n // ringing). Exit: timing-based zoom-out (springs are enter-only).\n dialog: {\n enter: { damping: 26, stiffness: 420, mass: 1 },\n exitDuration: 120,\n },\n\n // ── Confirm dialog ───────────────────────────────────────\n confirm: {\n /** Centered confirm panel pop. */\n enter: { damping: 26, stiffness: 420, mass: 1 },\n /** Floating severity-icon bubble — pops in slightly after the panel. */\n icon: { damping: 26, stiffness: 420, mass: 1, delay: 60 },\n /** Content-only / prompt panel (no header/buttons chrome). */\n content: { damping: 26, stiffness: 420, mass: 1 },\n /** Timed zoom-out for the confirm center/content panels. */\n exitDuration: 120,\n },\n\n // ── Bottom sheet (Dialog + Confirm, position=\"bottom\") ───\n // Slightly heavier damping/lower stiffness so the sheet glides up without\n // overshoot. Exit: timed slide-down.\n sheet: {\n enter: { damping: 30, stiffness: 400, mass: 1 },\n exitDuration: 150,\n /*\n * ⛔ REDUCE MOTION TURNS THIS OFF, AND THAT READS AS A FADE. Reanimated\n * honours iOS \"Reduce Motion\" by default: the entering/exiting\n * animation is skipped and the panel simply appears, so the only thing\n * left moving is the scrim's opacity. Measured on an iPhone 16 Pro\n * simulator, sheet top edge per frame at 30fps:\n * Reduce Motion OFF — 1924 → 1302 → 898 → 683 → 655 px\n * Reduce Motion ON — 655 in a single frame\n * That second row is exactly the \"it still fades\" report.\n *\n * A bottom sheet is kept moving because the platform keeps it moving:\n * iOS's own sheets still slide up under Reduce Motion — what that\n * setting removes is parallax and zoom, not the presentation of a\n * sheet. The centred Dialog's ZoomIn and the scrim's fade are NOT\n * overridden; they stay on the system default.\n */\n keepMotionWhenReduced: true,\n },\n\n // ── Toast ────────────────────────────────────────────────\n // One element owns the entrance: FadeInUp/FadeInDown animate opacity AND\n // translateY together, so there is no second concurrent layer to desync.\n toast: {\n /** Merged fade+slide entrance (position-appropriate direction). */\n enter: { damping: 30, stiffness: 400, mass: 1 },\n /** Timed fade+slide out. */\n exitDuration: 120,\n /** Re-positioning when toasts stack/unstack. */\n layoutDuration: 150,\n /** Gap (pt) kept between a bottom toast and the keyboard when it opens. */\n keyboardGap: 8,\n },\n};\n\nexport default overlayAnimations;\n"],"names":[],"mappings":"AAwDO,MAAM,iBAAA,GAAwC;AAAA;AAAA,EAEjD,KAAA,EAAO;AAAA,IACH,aAAA,EAAe,GAAA;AAAA,IACf,YAAA,EAAc;AAAA,GAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAA,EAAQ;AAAA,IACJ,OAAO,EAAE,OAAA,EAAS,IAAI,SAAA,EAAW,GAAA,EAAK,MAAM,CAAA,EAAE;AAAA,IAC9C,YAAA,EAAc;AAAA,GAClB;AAAA;AAAA,EAGA,OAAA,EAAS;AAAA;AAAA,IAEL,OAAO,EAAE,OAAA,EAAS,IAAI,SAAA,EAAW,GAAA,EAAK,MAAM,CAAA,EAAE;AAAA;AAAA,IAE9C,IAAA,EAAM,EAAE,OAAA,EAAS,EAAA,EAAI,WAAW,GAAA,EAAK,IAAA,EAAM,CAAA,EAAG,KAAA,EAAO,EAAA,EAAG;AAAA;AAAA,IAExD,SAAS,EAAE,OAAA,EAAS,IAAI,SAAA,EAAW,GAAA,EAAK,MAAM,CAAA,EAAE;AAAA;AAAA,IAEhD,YAAA,EAAc;AAAA,GAClB;AAAA;AAAA;AAAA;AAAA,EAKA,KAAA,EAAO;AAAA,IACH,OAAO,EAAE,OAAA,EAAS,IAAI,SAAA,EAAW,GAAA,EAAK,MAAM,CAAA,EAAE;AAAA,IAC9C,YAAA,EAAc,GAkBlB,CAAA;AAAA;AAAA;AAAA;AAAA,EAKA,KAAA,EAAO;AAAA;AAAA,IAEH,OAAO,EAAE,OAAA,EAAS,IAAI,SAAA,EAAW,GAAA,EAAK,MAAM,CAAA,EAAE;AAAA;AAAA,IAE9C,YAAA,EAAc,GAAA;AAAA;AAAA,IAEd,cAAA,EAAgB,GAAA;AAAA;AAAA,IAEhB,WAAA,EAAa;AAAA;AAErB;;;;"}
|
|
@@ -150,6 +150,7 @@ function Dropdown({
|
|
|
150
150
|
emptyFilterMessage = "No results found",
|
|
151
151
|
filterPlaceholder = "Search...",
|
|
152
152
|
isRTL = false,
|
|
153
|
+
fontFamily,
|
|
153
154
|
popup = false,
|
|
154
155
|
renderPopup,
|
|
155
156
|
popupTitle,
|
|
@@ -243,9 +244,16 @@ function Dropdown({
|
|
|
243
244
|
content = React.isValidElement(rendered) ? rendered : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { children: String(rendered ?? "") });
|
|
244
245
|
} else {
|
|
245
246
|
content = /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [
|
|
246
|
-
{
|
|
247
|
-
|
|
248
|
-
|
|
247
|
+
{
|
|
248
|
+
color: colors.text,
|
|
249
|
+
fontSize: optionFontSize(),
|
|
250
|
+
fontFamily
|
|
251
|
+
},
|
|
252
|
+
/* The row starts at the reader's edge. A label that opens with a
|
|
253
|
+
flag — "🇦🇺 +61 (AU)" — then puts the flag where an Arabic reader
|
|
254
|
+
starts reading, which is the right. Left unset the row inherited,
|
|
255
|
+
and the flag sat on the far side of the row from the reader. */
|
|
256
|
+
isRTL ? styles.optionRtl : styles.optionLtr
|
|
249
257
|
], children: getLabel(item, optionLabel) });
|
|
250
258
|
}
|
|
251
259
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -254,6 +262,15 @@ function Dropdown({
|
|
|
254
262
|
onPress: () => selectItem(item),
|
|
255
263
|
style: [
|
|
256
264
|
styles.option,
|
|
265
|
+
/* ⛔ `textAlign` ALONE CANNOT MOVE THIS ROW. The row is a flex row
|
|
266
|
+
and the label shrink-wraps, so the line box is only as wide as
|
|
267
|
+
its glyphs and aligning text inside it changes nothing — the box
|
|
268
|
+
itself still sits at the row's start. The process layout stays
|
|
269
|
+
LTR (the reader's language is a KitsConcerto concern, not
|
|
270
|
+
`I18nManager`), so `flex-start` is the left. Reversing the row is
|
|
271
|
+
what actually moves the label, and the checkmark, to the edge an
|
|
272
|
+
Arabic reader starts from. */
|
|
273
|
+
isRTL && styles.optionRowRtl,
|
|
257
274
|
selected && highlightOnSelect && { backgroundColor: colors.optionSelected }
|
|
258
275
|
],
|
|
259
276
|
children: [
|
|
@@ -309,7 +326,8 @@ function Dropdown({
|
|
|
309
326
|
{
|
|
310
327
|
borderColor: colors.filterBorder,
|
|
311
328
|
backgroundColor: colors.filterBg,
|
|
312
|
-
color: colors.filterText
|
|
329
|
+
color: colors.filterText,
|
|
330
|
+
fontFamily
|
|
313
331
|
},
|
|
314
332
|
// Every other input in this library names its own edge and
|
|
315
333
|
// direction from the reader's language. Leaving these unset let the
|
|
@@ -330,7 +348,7 @@ function Dropdown({
|
|
|
330
348
|
renderItem: ({ item, index }) => renderItem(item, index),
|
|
331
349
|
keyboardShouldPersistTaps: "handled",
|
|
332
350
|
showsHorizontalScrollIndicator: false,
|
|
333
|
-
ListEmptyComponent: filterQuery ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles.emptyContainer, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles.emptyText, { color: colors.emptyText }], children: emptyFilterMessage }) }) : null
|
|
351
|
+
ListEmptyComponent: filterQuery ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles.emptyContainer, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles.emptyText, { color: colors.emptyText, fontFamily }], children: emptyFilterMessage }) }) : null
|
|
334
352
|
}
|
|
335
353
|
),
|
|
336
354
|
panelFooterTemplate?.()
|
|
@@ -482,6 +500,22 @@ const styles = reactNative.StyleSheet.create({
|
|
|
482
500
|
paddingVertical: 6,
|
|
483
501
|
borderBottomWidth: 1
|
|
484
502
|
},
|
|
503
|
+
optionLtr: {
|
|
504
|
+
// `flex: 1` makes the line box span the row, so `textAlign` has something
|
|
505
|
+
// to align within. Without it the box hugs the glyphs and alignment is a
|
|
506
|
+
// no-op.
|
|
507
|
+
flex: 1,
|
|
508
|
+
textAlign: "left",
|
|
509
|
+
writingDirection: "ltr"
|
|
510
|
+
},
|
|
511
|
+
optionRowRtl: {
|
|
512
|
+
flexDirection: "row-reverse"
|
|
513
|
+
},
|
|
514
|
+
optionRtl: {
|
|
515
|
+
flex: 1,
|
|
516
|
+
textAlign: "right",
|
|
517
|
+
writingDirection: "rtl"
|
|
518
|
+
},
|
|
485
519
|
listFill: {
|
|
486
520
|
flex: 1
|
|
487
521
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../../../../../../../../../apps/mobile/src/Core/Dropdown/index.tsx"],"sourcesContent":["import React, { useCallback, useMemo, useRef, useState, type ChangeEvent } from \"react\";\nimport {\n Dimensions,\n FlatList,\n Keyboard,\n Modal,\n Pressable,\n ScrollView,\n TouchableOpacity,\n View,\n StyleSheet, Text, TextInput\n} from \"react-native\";\nimport { useSafeAreaInsets } from \"react-native-safe-area-context\";\nimport { Input, InputField, type VirtualScrollerOptions } from \"../../\";\nimport { resolveThemeTokenForNative, toNativeValue } from '../../Factory/helpers/style';\nimport { useKeyboardHeight } from '../../Factory/helpers/useKeyboardHeight';\nimport { computePanelGeometry } from './panelGeometry';\n\n/* ---------------------------------------------\n Types (PrimeReact-compatible)\n---------------------------------------------- */\n\nexport interface DropdownChangeEvent<T = any> {\n originalEvent?: any;\n value: T | null;\n}\n\n\nexport interface DropdownProps<T = any> {\n value?: T | null;\n options?: T[];\n\n onChange?: (e: ChangeEvent<T>, item:any) => void;\n\n optionLabel?: string;\n optionValue?: string;\n\n placeholder?: string;\n disabled?: boolean;\n editable?: boolean;\n loading?: boolean;\n showClear?: boolean;\n isModal?: boolean;\n\n checkmark?: boolean;\n highlightOnSelect?: boolean;\n\n filter?: boolean;\n filterBy?: string;\n emptyFilterMessage?: string;\n /**\n * Placeholder for the panel's filter field.\n *\n * ⛔ THIS COMPONENT CANNOT TRANSLATE. It lives in `apps/mobile`, which\n * `packages/ui` imports — the reverse import would be a cycle between the two\n * workspaces. So the sentence is resolved by the KitsConcerto wrapper, which\n * has `useLanguage()`, and arrives here already written, exactly as\n * `emptyFilterMessage` does.\n */\n filterPlaceholder?: string;\n /**\n * Open the options in a popup that owns the screen instead of a panel\n * anchored to the trigger.\n *\n * ⛔ THE ANCHOR IS THE PROBLEM THIS ESCAPES. An anchored panel can never be\n * taller than the gap between the trigger and the keyboard, and a field in\n * the middle of a form has ~190pt of gap on a 874pt phone — a search box and\n * four rows. Sizing that gap correctly does not make it big. The popup takes\n * a fixed share of the window instead, so where the field sits stops\n * mattering.\n *\n * Default false: every existing consumer keeps the anchored panel.\n */\n popup?: boolean;\n /**\n * Supplies the popup's container. Injected by the KitsConcerto wrapper\n * because the container is this library's `KitsDialogControlled`, which\n * lives in `packages/ui` — and `packages/ui` imports THIS file, so importing\n * it back would be a cycle between the two workspaces.\n *\n * Without it `popup` falls back to the anchored panel rather than rendering\n * nothing.\n */\n renderPopup?: (args: {\n visible: boolean;\n onClose: () => void;\n title?: React.ReactNode;\n children: React.ReactNode;\n }) => React.ReactNode;\n /** Title for the popup header. The wrapper passes the field's label. */\n popupTitle?: React.ReactNode;\n /**\n * Which way the reader reads, from the wrapper's `useLanguage().isRTL`.\n *\n * ⛔ NOT `I18nManager.isRTL`. That is the PROCESS layout direction, which a\n * consumer can force at boot and which does not change when the reader\n * switches language. The filter field follows the interface language, like\n * every other input in this library.\n */\n isRTL?: boolean;\n\n itemTemplate?: (item: T) => React.ReactNode;\n valueTemplate?: (value: T | null) => React.ReactNode;\n panelFooterTemplate?: () => React.ReactNode;\n\n optionGroupLabel?: string;\n optionGroupChildren?: string;\n optionGroupTemplate?: (group: any) => React.ReactNode;\n\n virtualScrollerOptions?: VirtualScrollerOptions;\n\n invalid?: boolean;\n testID?: string;\n style?: import('react-native').ViewStyle;\n}\n\n/* ---------------------------------------------\n Helpers\n---------------------------------------------- */\n\nconst getLabel = (item: any, optionLabel?: string) => {\n if (!item) return \"\";\n if (!optionLabel) return String(item);\n return String(item[optionLabel]);\n};\n\nconst getValue = (item: any, optionValue?: string) => {\n if (!item) return null;\n if (!optionValue) return item;\n return item[optionValue];\n};\n\nconst t = resolveThemeTokenForNative;\n\n/**\n * Option-row text size, taken from the theme's own scale rather than picked.\n *\n * The rows used to set no `fontSize` at all, so they fell through to React\n * Native's default of 14 — which happens to equal the scale's `sm` step, by\n * coincidence rather than intent. `md` is the scale's body size and one step\n * up. `$fontSizes.md` resolves to '1rem' and `toNativeValue` turns that into\n * 16; the `?? 16` is the same number spelled out, for the case where a\n * consumer's theme does not declare the step.\n */\nconst optionFontSize = (): number => {\n const resolved = toNativeValue(resolveThemeTokenForNative('$fontSizes.md'));\n return typeof resolved === 'number' ? resolved : 16;\n};\n\nconst TEXT_STYLE_KEYS = new Set([\n 'fontSize', 'fontFamily', 'fontWeight', 'fontStyle',\n 'color', 'letterSpacing', 'lineHeight', 'textAlign',\n 'textDecorationLine', 'textTransform',\n]);\n\nfunction splitStyle(combined?: any): { viewStyle?: any; textStyle?: any } {\n if (!combined) return {};\n const view: Record<string, any> = {};\n const text: Record<string, any> = {};\n for (const [k, v] of Object.entries(combined)) {\n if (TEXT_STYLE_KEYS.has(k)) text[k] = v;\n else view[k] = v;\n }\n return {\n viewStyle: Object.keys(view).length ? view : undefined,\n textStyle: Object.keys(text).length ? text : undefined,\n };\n}\n\n/* ---------------------------------------------\n Component\n---------------------------------------------- */\n\nexport default function Dropdown<T = any>({\n value,\n options = [],\n onChange,\n\n optionLabel,\n optionValue,\n\n placeholder,\n disabled,\n editable,\n isModal = false,\n\n checkmark,\n highlightOnSelect = true,\n\n filter,\n filterBy,\n // ⚠️ THESE TWO ENGLISH LITERALS ARE A LAST RESORT, NOT A\n // TRANSLATION. The KitsConcerto wrapper always passes the\n // reader's own sentence; these only apply when this component\n // is used directly from `apps/mobile`, and they exist so a\n // panel can never render a blank search box or an empty\n // \"no results\" line. Recorded as English fallbacks.\n emptyFilterMessage = 'No results found',\n filterPlaceholder = 'Search...',\n isRTL = false,\n popup = false,\n renderPopup,\n popupTitle,\n\n itemTemplate,\n valueTemplate,\n panelFooterTemplate,\n\n optionGroupLabel,\n optionGroupChildren,\n optionGroupTemplate,\n\n virtualScrollerOptions,\n\n invalid,\n testID,\n style: externalStyle,\n }: DropdownProps<T>) {\n const inputRef = useRef<any>(null);\n const triggerRef = useRef<View>(null);\n const [open, setOpen] = useState(false);\n const [inputText, setInputText] = useState(\"\");\n const [filterQuery, setFilterQuery] = useState(\"\");\n const [triggerLayout, setTriggerLayout] = useState<{\n x: number; y: number; width: number; height: number;\n } | null>(null);\n const insets = useSafeAreaInsets();\n const keyboardHeight = useKeyboardHeight();\n\n const { viewStyle: externalViewStyle, textStyle: externalTextStyle } = splitStyle(externalStyle);\n\n const colors = {\n border: t('border') || t('gray.300'),\n borderInvalid: t('danger') || t('red.500'),\n bg: t('surface-card') || '#fff',\n text: t('text') || t('gray.800'),\n placeholder: t('text-secondary') || t('gray.400'),\n optionSelected: t('highlight-bg') || t('gray.100'),\n groupBg: t('surface-ground') || t('gray.50'),\n filterBorder: t('border') || t('gray.200'),\n filterBg: t('surface-ground') || t('gray.50'),\n filterText: t('text') || t('gray.800'),\n emptyText: t('text-secondary') || t('gray.400'),\n primary: t('primary'),\n };\n\n /* ---------------------------------------------\n Derived\n ---------------------------------------------- */\n\n const selectedItem = useMemo(() => {\n if (value == null) return null;\n // Search through group children when grouped\n if (optionGroupChildren) {\n for (const group of options as any[]) {\n const children = group[optionGroupChildren];\n if (Array.isArray(children)) {\n const found = children.find((c: any) => getValue(c, optionValue) === value);\n if (found) return found;\n }\n }\n return null;\n }\n return options.find(\n (o) => getValue(o, optionValue) === value\n ) ?? null;\n }, [value, options, optionValue, optionGroupChildren]);\n\n /* ---------------------------------------------\n Open / Close\n ---------------------------------------------- */\n\n const toggle = () => {\n if (disabled) return;\n Keyboard.dismiss();\n if (open) {\n setOpen(false);\n return;\n }\n setFilterQuery(\"\");\n // Measure trigger position in window so the popover can be rendered\n // inside a Modal (escaping any parent ScrollView) at the correct anchor.\n triggerRef.current?.measureInWindow((x, y, width, height) => {\n setTriggerLayout({ x, y, width, height });\n setOpen(true);\n });\n };\n\n const close = () => setOpen(false);\n\n /* ---------------------------------------------\n Selection\n ---------------------------------------------- */\n\n const selectItem = (item: T) => {\n const newValue = getValue(item, optionValue);\n\n if (!onChange) return;\n\n const syntheticEvent = {\n target: {\n value: newValue,\n },\n } as React.ChangeEvent<any>;\n\n onChange(syntheticEvent, item);\n\n setOpen(false);\n };\n\n /* ---------------------------------------------\n Render item\n ---------------------------------------------- */\n\n const renderItem = useCallback(\n (item: any, index: number) => {\n if (!item) {\n return null;\n }\n\n // Group header\n if (item.__group) {\n return (\n <Text key={`group-${index}`} style={[styles.groupLabel, { backgroundColor: colors.groupBg }]}>\n {optionGroupLabel ? item.group?.[optionGroupLabel] : \"\"}\n </Text>\n );\n }\n\n const selected =\n value != null &&\n getValue(item, optionValue) === value;\n\n let content: React.ReactElement;\n\n if (itemTemplate) {\n const rendered = itemTemplate(item);\n\n content = React.isValidElement(rendered) ? (\n rendered\n ) : (\n <Text>{String(rendered ?? \"\")}</Text>\n );\n } else {\n content = (\n <Text style={[\n { color: colors.text, fontSize: optionFontSize() },\n // A consumer-supplied size still wins over the scale.\n externalTextStyle && externalTextStyle.fontSize ? { fontSize: externalTextStyle.fontSize } : null,\n ]}>\n {getLabel(item, optionLabel)}\n </Text>\n );\n }\n\n return (\n <Pressable\n key={`item-${index}`}\n onPress={() => selectItem(item)}\n style={[\n styles.option,\n selected && highlightOnSelect && { backgroundColor: colors.optionSelected },\n ]}\n >\n {content}\n {checkmark && selected && <Text>✓</Text>}\n </Pressable>\n );\n },\n [\n value,\n optionValue,\n optionLabel,\n itemTemplate,\n optionGroupLabel,\n checkmark,\n highlightOnSelect,\n ]\n );\n\n\n /* ---------------------------------------------\n Group flattening\n ---------------------------------------------- */\n\n const flatData = useMemo(() => {\n if (!optionGroupLabel || !optionGroupChildren) {\n return options;\n }\n\n const out: any[] = [];\n options.forEach((g: any) => {\n out.push({ __group: true, group: g });\n g[optionGroupChildren]?.forEach((c: any) => out.push(c));\n });\n return out;\n }, [options]);\n\n /* ---------------------------------------------\n Filter\n ---------------------------------------------- */\n\n const filteredData = useMemo(() => {\n if (!filter || !filterQuery) return flatData;\n const q = filterQuery.toLowerCase();\n const key = filterBy || optionLabel;\n\n return flatData.filter((entry: any) => {\n // Keep group headers\n if (entry.__group) return true;\n const label = getLabel(entry, key);\n return label.toLowerCase().includes(q);\n });\n }, [flatData, filter, filterQuery, filterBy, optionLabel]);\n\n /* ---------------------------------------------\n Display value\n ---------------------------------------------- */\n\n const displayValue = valueTemplate\n ? valueTemplate(selectedItem)\n : selectedItem\n ? getLabel(selectedItem, optionLabel)\n : \"\";\n\n /* ---------------------------------------------\n Panel body — the search field and the list\n ---------------------------------------------- */\n\n /*\n * ⛔ ONE BODY, THREE CONTAINERS. The anchored panel and the centred modal\n * each carried their own copy of this markup, which is why the hardcoded\n * \"Search...\" had to be found and fixed twice. The popup would have made it\n * three. The containers differ; what is inside them does not.\n *\n * `fill` is the one real difference. In the anchored panel the container has\n * a `maxHeight` and no height, so the list must shrink-wrap its content up\n * to that ceiling (`flexShrink`). In the popup and the centred modal the\n * container has a real height, so the list takes what is left (`flex: 1`).\n */\n const panelBody = (fill: boolean, autoFocusFilter: boolean) => (\n <>\n {filter && (\n <View style={[styles.filterContainer, { borderBottomColor: colors.filterBorder }]}>\n <TextInput\n value={filterQuery}\n onChangeText={setFilterQuery}\n placeholder={filterPlaceholder}\n placeholderTextColor={colors.placeholder}\n style={[styles.filterInput, {\n borderColor: colors.filterBorder,\n backgroundColor: colors.filterBg,\n color: colors.filterText,\n },\n // Every other input in this library names its own edge and\n // direction from the reader's language. Leaving these unset let the\n // platform decide, so the field followed the process layout\n // direction instead of the person reading it.\n isRTL ? styles.filterRtl : styles.filterLtr]}\n /* ⛔ THE ANCHORED PANEL KEEPS ITS AUTOFOCUS — changing it would\n change behaviour for every consumer that has not opted in. In\n the popup the list is already the whole point and is fully\n visible, so the keyboard waits to be asked for: one tap on the\n field raises it, and until then the list has the whole sheet. */\n autoFocus={autoFocusFilter}\n />\n </View>\n )}\n <FlatList\n style={fill ? styles.listFill : styles.listShrink}\n contentContainerStyle={styles.listContent}\n data={filteredData}\n keyExtractor={(item: any, i: number) =>\n item?.__group ? `group-${i}` : `item-${i}`\n }\n renderItem={({ item, index }) => renderItem(item, index)}\n keyboardShouldPersistTaps=\"handled\"\n showsHorizontalScrollIndicator={false}\n ListEmptyComponent={\n filterQuery ? (\n <View style={styles.emptyContainer}>\n <Text style={[styles.emptyText, { color: colors.emptyText }]}>{emptyFilterMessage}</Text>\n </View>\n ) : null\n }\n />\n {panelFooterTemplate?.()}\n </>\n );\n\n /* ---------------------------------------------\n Render\n ---------------------------------------------- */\n\n const usePopup = popup && typeof renderPopup === 'function';\n\n return (\n <View style={styles.container} testID={testID}>\n <Pressable\n ref={triggerRef as any}\n style={[\n styles.control,\n { borderColor: colors.border, backgroundColor: colors.bg },\n invalid && { borderColor: colors.borderInvalid },\n disabled && styles.disabled,\n externalViewStyle,\n ]}\n onPress={toggle}\n >\n {editable ? (\n <Input style={styles.input}>\n <InputField\n ref={inputRef}\n value={inputText}\n onChangeText={setInputText}\n placeholder={placeholder}\n editable={!disabled}\n />\n </Input>\n ) : (\n <Text\n numberOfLines={1}\n style={[\n // Fill the trigger row and left-align the value/placeholder so it\n // doesn't read as centred (the row is justify=space-between, so the\n // arrow stays pinned right).\n { flex: 1, textAlign: \"left\" as const },\n displayValue ? { color: colors.text } : { color: colors.placeholder },\n externalTextStyle,\n !displayValue && { color: colors.placeholder },\n ]}>\n {displayValue || placeholder}\n </Text>\n )}\n\n <Text style={[{ color: colors.text }, externalTextStyle]}>▾</Text>\n </Pressable>\n\n {!usePopup && !isModal && (\n <Modal\n visible={open && !!triggerLayout}\n transparent\n animationType=\"none\"\n onRequestClose={close}\n >\n <Pressable style={styles.popoverOverlay} onPress={close}>\n {triggerLayout && (() => {\n const screen = Dimensions.get('window');\n const { top, maxHeight } = computePanelGeometry({\n screenHeight: screen.height,\n insetTop: insets.top,\n insetBottom: insets.bottom,\n keyboardHeight,\n triggerY: triggerLayout.y,\n triggerHeight: triggerLayout.height,\n });\n\n return (\n <View\n style={[\n styles.popoverPanel,\n {\n top,\n left: triggerLayout.x,\n width: triggerLayout.width,\n maxHeight,\n borderColor: colors.border,\n backgroundColor: colors.bg,\n },\n ]}\n onStartShouldSetResponder={() => true}\n >\n {panelBody(false, true)}\n </View>\n );\n })()}\n </Pressable>\n </Modal>\n )}\n\n {!usePopup && isModal && (\n <Modal visible={open} transparent animationType=\"fade\">\n <Pressable style={styles.modalOverlay} onPress={close}>\n <View\n style={[styles.modalPanel, { backgroundColor: colors.bg }]}\n onStartShouldSetResponder={() => true}\n >\n {panelBody(true, true)}\n </View>\n </Pressable>\n </Modal>\n )}\n\n {/* Popup — the container comes from the wrapper (this library's own\n Dialog in sheet position); everything inside it is the same body the\n other two containers render. */}\n {usePopup && renderPopup!({\n visible: open,\n onClose: close,\n title: popupTitle,\n children: panelBody(true, false),\n })}\n\n </View>\n );\n}\n\n/* ---------------------------------------------\n Styles (layout only — colors applied inline via theme tokens)\n---------------------------------------------- */\n\nconst styles = StyleSheet.create({\n container: {\n width: \"100%\",\n position: \"relative\" as const,\n },\n control: {\n flexDirection: \"row\" as const,\n alignItems: \"center\" as const,\n justifyContent: \"space-between\" as const,\n borderWidth: 1,\n borderRadius: 6,\n paddingHorizontal: 10,\n paddingVertical: 10,\n },\n disabled: {\n opacity: 0.5,\n },\n option: {\n paddingHorizontal: 12,\n paddingVertical: 10,\n flexDirection: \"row\" as const,\n justifyContent: \"space-between\" as const,\n alignItems: \"center\" as const,\n },\n groupLabel: {\n paddingHorizontal: 12,\n paddingVertical: 8,\n fontWeight: \"600\" as const,\n },\n input: {\n flex: 1,\n },\n panel: {\n position: \"absolute\" as const,\n top: \"100%\",\n left: 0,\n right: 0,\n marginTop: 4,\n borderWidth: 1,\n borderRadius: 6,\n maxHeight: 260,\n overflow: \"hidden\" as const,\n zIndex: 9999,\n },\n filterContainer: {\n paddingHorizontal: 8,\n paddingVertical: 6,\n borderBottomWidth: 1,\n },\n listFill: {\n flex: 1,\n },\n // The anchored panel is sized by `maxHeight` with no height, so the list has\n // to grow with its content up to that ceiling and then scroll inside it.\n // `flex: 1` sets flexBasis 0, which contributes nothing to a shrink-wrapping\n // parent.\n listShrink: {\n flexGrow: 0,\n flexShrink: 1,\n },\n listContent: {\n paddingBottom: 12,\n },\n filterInput: {\n fontSize: 14,\n paddingHorizontal: 8,\n paddingVertical: 6,\n borderWidth: 1,\n borderRadius: 4,\n },\n filterLtr: {\n textAlign: 'left' as const,\n writingDirection: 'ltr' as const,\n },\n filterRtl: {\n textAlign: 'right' as const,\n writingDirection: 'rtl' as const,\n },\n emptyContainer: {\n padding: 16,\n alignItems: 'center' as const,\n },\n emptyText: {\n fontSize: 14,\n },\n popoverOverlay: {\n flex: 1,\n backgroundColor: 'transparent',\n },\n popoverPanel: {\n position: 'absolute' as const,\n borderWidth: 1,\n borderRadius: 6,\n overflow: 'hidden' as const,\n elevation: 8,\n shadowColor: '#000',\n shadowOffset: { width: 0, height: 2 },\n shadowOpacity: 0.15,\n shadowRadius: 8,\n },\n modalOverlay: {\n flex: 1,\n backgroundColor: 'rgba(0,0,0,0.4)',\n justifyContent: 'center' as const,\n },\n modalPanel: {\n margin: 24,\n maxHeight: '70%',\n borderRadius: 12,\n overflow: 'hidden' as const,\n },\n});\n"],"names":["resolveThemeTokenForNative","toNativeValue","useRef","useState","useSafeAreaInsets","useKeyboardHeight","useMemo","Keyboard","useCallback","jsx","Text","jsxs","Pressable","Fragment","View","TextInput","FlatList","Input","InputField","Modal","Dimensions","computePanelGeometry","StyleSheet"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../../../../../../../../apps/mobile/src/Core/Dropdown/index.tsx"],"sourcesContent":["import React, { useCallback, useMemo, useRef, useState, type ChangeEvent } from \"react\";\nimport {\n Dimensions,\n FlatList,\n Keyboard,\n Modal,\n Pressable,\n ScrollView,\n TouchableOpacity,\n View,\n StyleSheet, Text, TextInput\n} from \"react-native\";\nimport { useSafeAreaInsets } from \"react-native-safe-area-context\";\nimport { Input, InputField, type VirtualScrollerOptions } from \"../../\";\nimport { resolveThemeTokenForNative, toNativeValue } from '../../Factory/helpers/style';\nimport { useKeyboardHeight } from '../../Factory/helpers/useKeyboardHeight';\nimport { computePanelGeometry } from './panelGeometry';\n\n/* ---------------------------------------------\n Types (PrimeReact-compatible)\n---------------------------------------------- */\n\nexport interface DropdownChangeEvent<T = any> {\n originalEvent?: any;\n value: T | null;\n}\n\n\nexport interface DropdownProps<T = any> {\n value?: T | null;\n options?: T[];\n\n onChange?: (e: ChangeEvent<T>, item:any) => void;\n\n optionLabel?: string;\n optionValue?: string;\n\n placeholder?: string;\n disabled?: boolean;\n editable?: boolean;\n loading?: boolean;\n showClear?: boolean;\n isModal?: boolean;\n\n checkmark?: boolean;\n highlightOnSelect?: boolean;\n\n filter?: boolean;\n filterBy?: string;\n emptyFilterMessage?: string;\n /**\n * Placeholder for the panel's filter field.\n *\n * ⛔ THIS COMPONENT CANNOT TRANSLATE. It lives in `apps/mobile`, which\n * `packages/ui` imports — the reverse import would be a cycle between the two\n * workspaces. So the sentence is resolved by the KitsConcerto wrapper, which\n * has `useLanguage()`, and arrives here already written, exactly as\n * `emptyFilterMessage` does.\n */\n filterPlaceholder?: string;\n /**\n * Open the options in a popup that owns the screen instead of a panel\n * anchored to the trigger.\n *\n * ⛔ THE ANCHOR IS THE PROBLEM THIS ESCAPES. An anchored panel can never be\n * taller than the gap between the trigger and the keyboard, and a field in\n * the middle of a form has ~190pt of gap on a 874pt phone — a search box and\n * four rows. Sizing that gap correctly does not make it big. The popup takes\n * a fixed share of the window instead, so where the field sits stops\n * mattering.\n *\n * Default false: every existing consumer keeps the anchored panel.\n */\n popup?: boolean;\n /**\n * Supplies the popup's container. Injected by the KitsConcerto wrapper\n * because the container is this library's `KitsDialogControlled`, which\n * lives in `packages/ui` — and `packages/ui` imports THIS file, so importing\n * it back would be a cycle between the two workspaces.\n *\n * Without it `popup` falls back to the anchored panel rather than rendering\n * nothing.\n */\n renderPopup?: (args: {\n visible: boolean;\n onClose: () => void;\n title?: React.ReactNode;\n children: React.ReactNode;\n }) => React.ReactNode;\n /** Title for the popup header. The wrapper passes the field's label. */\n popupTitle?: React.ReactNode;\n /**\n * Which way the reader reads, from the wrapper's `useLanguage().isRTL`.\n *\n * ⛔ NOT `I18nManager.isRTL`. That is the PROCESS layout direction, which a\n * consumer can force at boot and which does not change when the reader\n * switches language. The filter field follows the interface language, like\n * every other input in this library.\n */\n isRTL?: boolean;\n /**\n * Font family the consuming app's theme names for body text, resolved by the\n * KitsConcerto wrapper with `useThemedFont('body')`.\n *\n * ⛔ React Native does NOT cascade `fontFamily` through View parents, so\n * every text sink has to set it. The panel's rows and its search field set\n * none, which is why an app that swaps in its own face — AlphaMatch loads\n * Noto Kufi Arabic for its Arabic readers — saw that face everywhere except\n * inside the picker.\n */\n fontFamily?: string;\n\n itemTemplate?: (item: T) => React.ReactNode;\n valueTemplate?: (value: T | null) => React.ReactNode;\n panelFooterTemplate?: () => React.ReactNode;\n\n optionGroupLabel?: string;\n optionGroupChildren?: string;\n optionGroupTemplate?: (group: any) => React.ReactNode;\n\n virtualScrollerOptions?: VirtualScrollerOptions;\n\n invalid?: boolean;\n testID?: string;\n style?: import('react-native').ViewStyle;\n}\n\n/* ---------------------------------------------\n Helpers\n---------------------------------------------- */\n\nconst getLabel = (item: any, optionLabel?: string) => {\n if (!item) return \"\";\n if (!optionLabel) return String(item);\n return String(item[optionLabel]);\n};\n\nconst getValue = (item: any, optionValue?: string) => {\n if (!item) return null;\n if (!optionValue) return item;\n return item[optionValue];\n};\n\nconst t = resolveThemeTokenForNative;\n\n/**\n * Option-row text size, taken from the theme's own scale rather than picked.\n *\n * The rows used to set no `fontSize` at all, so they fell through to React\n * Native's default of 14 — which happens to equal the scale's `sm` step, by\n * coincidence rather than intent. `md` is the scale's body size and one step\n * up. `$fontSizes.md` resolves to '1rem' and `toNativeValue` turns that into\n * 16; the `?? 16` is the same number spelled out, for the case where a\n * consumer's theme does not declare the step.\n */\nconst optionFontSize = (): number => {\n const resolved = toNativeValue(resolveThemeTokenForNative('$fontSizes.md'));\n return typeof resolved === 'number' ? resolved : 16;\n};\n\nconst TEXT_STYLE_KEYS = new Set([\n 'fontSize', 'fontFamily', 'fontWeight', 'fontStyle',\n 'color', 'letterSpacing', 'lineHeight', 'textAlign',\n 'textDecorationLine', 'textTransform',\n]);\n\nfunction splitStyle(combined?: any): { viewStyle?: any; textStyle?: any } {\n if (!combined) return {};\n const view: Record<string, any> = {};\n const text: Record<string, any> = {};\n for (const [k, v] of Object.entries(combined)) {\n if (TEXT_STYLE_KEYS.has(k)) text[k] = v;\n else view[k] = v;\n }\n return {\n viewStyle: Object.keys(view).length ? view : undefined,\n textStyle: Object.keys(text).length ? text : undefined,\n };\n}\n\n/* ---------------------------------------------\n Component\n---------------------------------------------- */\n\nexport default function Dropdown<T = any>({\n value,\n options = [],\n onChange,\n\n optionLabel,\n optionValue,\n\n placeholder,\n disabled,\n editable,\n isModal = false,\n\n checkmark,\n highlightOnSelect = true,\n\n filter,\n filterBy,\n // ⚠️ THESE TWO ENGLISH LITERALS ARE A LAST RESORT, NOT A\n // TRANSLATION. The KitsConcerto wrapper always passes the\n // reader's own sentence; these only apply when this component\n // is used directly from `apps/mobile`, and they exist so a\n // panel can never render a blank search box or an empty\n // \"no results\" line. Recorded as English fallbacks.\n emptyFilterMessage = 'No results found',\n filterPlaceholder = 'Search...',\n isRTL = false,\n fontFamily,\n popup = false,\n renderPopup,\n popupTitle,\n\n itemTemplate,\n valueTemplate,\n panelFooterTemplate,\n\n optionGroupLabel,\n optionGroupChildren,\n optionGroupTemplate,\n\n virtualScrollerOptions,\n\n invalid,\n testID,\n style: externalStyle,\n }: DropdownProps<T>) {\n const inputRef = useRef<any>(null);\n const triggerRef = useRef<View>(null);\n const [open, setOpen] = useState(false);\n const [inputText, setInputText] = useState(\"\");\n const [filterQuery, setFilterQuery] = useState(\"\");\n const [triggerLayout, setTriggerLayout] = useState<{\n x: number; y: number; width: number; height: number;\n } | null>(null);\n const insets = useSafeAreaInsets();\n const keyboardHeight = useKeyboardHeight();\n\n const { viewStyle: externalViewStyle, textStyle: externalTextStyle } = splitStyle(externalStyle);\n\n const colors = {\n border: t('border') || t('gray.300'),\n borderInvalid: t('danger') || t('red.500'),\n bg: t('surface-card') || '#fff',\n text: t('text') || t('gray.800'),\n placeholder: t('text-secondary') || t('gray.400'),\n optionSelected: t('highlight-bg') || t('gray.100'),\n groupBg: t('surface-ground') || t('gray.50'),\n filterBorder: t('border') || t('gray.200'),\n filterBg: t('surface-ground') || t('gray.50'),\n filterText: t('text') || t('gray.800'),\n emptyText: t('text-secondary') || t('gray.400'),\n primary: t('primary'),\n };\n\n /* ---------------------------------------------\n Derived\n ---------------------------------------------- */\n\n const selectedItem = useMemo(() => {\n if (value == null) return null;\n // Search through group children when grouped\n if (optionGroupChildren) {\n for (const group of options as any[]) {\n const children = group[optionGroupChildren];\n if (Array.isArray(children)) {\n const found = children.find((c: any) => getValue(c, optionValue) === value);\n if (found) return found;\n }\n }\n return null;\n }\n return options.find(\n (o) => getValue(o, optionValue) === value\n ) ?? null;\n }, [value, options, optionValue, optionGroupChildren]);\n\n /* ---------------------------------------------\n Open / Close\n ---------------------------------------------- */\n\n const toggle = () => {\n if (disabled) return;\n Keyboard.dismiss();\n if (open) {\n setOpen(false);\n return;\n }\n setFilterQuery(\"\");\n // Measure trigger position in window so the popover can be rendered\n // inside a Modal (escaping any parent ScrollView) at the correct anchor.\n triggerRef.current?.measureInWindow((x, y, width, height) => {\n setTriggerLayout({ x, y, width, height });\n setOpen(true);\n });\n };\n\n const close = () => setOpen(false);\n\n /* ---------------------------------------------\n Selection\n ---------------------------------------------- */\n\n const selectItem = (item: T) => {\n const newValue = getValue(item, optionValue);\n\n if (!onChange) return;\n\n const syntheticEvent = {\n target: {\n value: newValue,\n },\n } as React.ChangeEvent<any>;\n\n onChange(syntheticEvent, item);\n\n setOpen(false);\n };\n\n /* ---------------------------------------------\n Render item\n ---------------------------------------------- */\n\n const renderItem = useCallback(\n (item: any, index: number) => {\n if (!item) {\n return null;\n }\n\n // Group header\n if (item.__group) {\n return (\n <Text key={`group-${index}`} style={[styles.groupLabel, { backgroundColor: colors.groupBg }]}>\n {optionGroupLabel ? item.group?.[optionGroupLabel] : \"\"}\n </Text>\n );\n }\n\n const selected =\n value != null &&\n getValue(item, optionValue) === value;\n\n let content: React.ReactElement;\n\n if (itemTemplate) {\n const rendered = itemTemplate(item);\n\n content = React.isValidElement(rendered) ? (\n rendered\n ) : (\n <Text>{String(rendered ?? \"\")}</Text>\n );\n } else {\n content = (\n <Text style={[\n {\n color: colors.text,\n fontSize: optionFontSize(),\n fontFamily,\n },\n /* The row starts at the reader's edge. A label that opens with a\n flag — \"🇦🇺 +61 (AU)\" — then puts the flag where an Arabic reader\n starts reading, which is the right. Left unset the row inherited,\n and the flag sat on the far side of the row from the reader. */\n isRTL ? styles.optionRtl : styles.optionLtr,\n ]}>\n {getLabel(item, optionLabel)}\n </Text>\n );\n }\n\n return (\n <Pressable\n key={`item-${index}`}\n onPress={() => selectItem(item)}\n style={[\n styles.option,\n /* ⛔ `textAlign` ALONE CANNOT MOVE THIS ROW. The row is a flex row\n and the label shrink-wraps, so the line box is only as wide as\n its glyphs and aligning text inside it changes nothing — the box\n itself still sits at the row's start. The process layout stays\n LTR (the reader's language is a KitsConcerto concern, not\n `I18nManager`), so `flex-start` is the left. Reversing the row is\n what actually moves the label, and the checkmark, to the edge an\n Arabic reader starts from. */\n isRTL && styles.optionRowRtl,\n selected && highlightOnSelect && { backgroundColor: colors.optionSelected },\n ]}\n >\n {content}\n {checkmark && selected && <Text>✓</Text>}\n </Pressable>\n );\n },\n [\n value,\n optionValue,\n optionLabel,\n itemTemplate,\n optionGroupLabel,\n checkmark,\n highlightOnSelect,\n ]\n );\n\n\n /* ---------------------------------------------\n Group flattening\n ---------------------------------------------- */\n\n const flatData = useMemo(() => {\n if (!optionGroupLabel || !optionGroupChildren) {\n return options;\n }\n\n const out: any[] = [];\n options.forEach((g: any) => {\n out.push({ __group: true, group: g });\n g[optionGroupChildren]?.forEach((c: any) => out.push(c));\n });\n return out;\n }, [options]);\n\n /* ---------------------------------------------\n Filter\n ---------------------------------------------- */\n\n const filteredData = useMemo(() => {\n if (!filter || !filterQuery) return flatData;\n const q = filterQuery.toLowerCase();\n const key = filterBy || optionLabel;\n\n return flatData.filter((entry: any) => {\n // Keep group headers\n if (entry.__group) return true;\n const label = getLabel(entry, key);\n return label.toLowerCase().includes(q);\n });\n }, [flatData, filter, filterQuery, filterBy, optionLabel]);\n\n /* ---------------------------------------------\n Display value\n ---------------------------------------------- */\n\n const displayValue = valueTemplate\n ? valueTemplate(selectedItem)\n : selectedItem\n ? getLabel(selectedItem, optionLabel)\n : \"\";\n\n /* ---------------------------------------------\n Panel body — the search field and the list\n ---------------------------------------------- */\n\n /*\n * ⛔ ONE BODY, THREE CONTAINERS. The anchored panel and the centred modal\n * each carried their own copy of this markup, which is why the hardcoded\n * \"Search...\" had to be found and fixed twice. The popup would have made it\n * three. The containers differ; what is inside them does not.\n *\n * `fill` is the one real difference. In the anchored panel the container has\n * a `maxHeight` and no height, so the list must shrink-wrap its content up\n * to that ceiling (`flexShrink`). In the popup and the centred modal the\n * container has a real height, so the list takes what is left (`flex: 1`).\n */\n const panelBody = (fill: boolean, autoFocusFilter: boolean) => (\n <>\n {filter && (\n <View style={[styles.filterContainer, { borderBottomColor: colors.filterBorder }]}>\n <TextInput\n value={filterQuery}\n onChangeText={setFilterQuery}\n placeholder={filterPlaceholder}\n placeholderTextColor={colors.placeholder}\n style={[styles.filterInput, {\n borderColor: colors.filterBorder,\n backgroundColor: colors.filterBg,\n color: colors.filterText,\n fontFamily,\n },\n // Every other input in this library names its own edge and\n // direction from the reader's language. Leaving these unset let the\n // platform decide, so the field followed the process layout\n // direction instead of the person reading it.\n isRTL ? styles.filterRtl : styles.filterLtr]}\n /* ⛔ THE ANCHORED PANEL KEEPS ITS AUTOFOCUS — changing it would\n change behaviour for every consumer that has not opted in. In\n the popup the list is already the whole point and is fully\n visible, so the keyboard waits to be asked for: one tap on the\n field raises it, and until then the list has the whole sheet. */\n autoFocus={autoFocusFilter}\n />\n </View>\n )}\n <FlatList\n style={fill ? styles.listFill : styles.listShrink}\n contentContainerStyle={styles.listContent}\n data={filteredData}\n keyExtractor={(item: any, i: number) =>\n item?.__group ? `group-${i}` : `item-${i}`\n }\n renderItem={({ item, index }) => renderItem(item, index)}\n keyboardShouldPersistTaps=\"handled\"\n showsHorizontalScrollIndicator={false}\n ListEmptyComponent={\n filterQuery ? (\n <View style={styles.emptyContainer}>\n <Text style={[styles.emptyText, { color: colors.emptyText, fontFamily }]}>{emptyFilterMessage}</Text>\n </View>\n ) : null\n }\n />\n {panelFooterTemplate?.()}\n </>\n );\n\n /* ---------------------------------------------\n Render\n ---------------------------------------------- */\n\n const usePopup = popup && typeof renderPopup === 'function';\n\n return (\n <View style={styles.container} testID={testID}>\n <Pressable\n ref={triggerRef as any}\n style={[\n styles.control,\n { borderColor: colors.border, backgroundColor: colors.bg },\n invalid && { borderColor: colors.borderInvalid },\n disabled && styles.disabled,\n externalViewStyle,\n ]}\n onPress={toggle}\n >\n {editable ? (\n <Input style={styles.input}>\n <InputField\n ref={inputRef}\n value={inputText}\n onChangeText={setInputText}\n placeholder={placeholder}\n editable={!disabled}\n />\n </Input>\n ) : (\n <Text\n numberOfLines={1}\n style={[\n // Fill the trigger row and left-align the value/placeholder so it\n // doesn't read as centred (the row is justify=space-between, so the\n // arrow stays pinned right).\n { flex: 1, textAlign: \"left\" as const },\n displayValue ? { color: colors.text } : { color: colors.placeholder },\n externalTextStyle,\n !displayValue && { color: colors.placeholder },\n ]}>\n {displayValue || placeholder}\n </Text>\n )}\n\n <Text style={[{ color: colors.text }, externalTextStyle]}>▾</Text>\n </Pressable>\n\n {!usePopup && !isModal && (\n <Modal\n visible={open && !!triggerLayout}\n transparent\n animationType=\"none\"\n onRequestClose={close}\n >\n <Pressable style={styles.popoverOverlay} onPress={close}>\n {triggerLayout && (() => {\n const screen = Dimensions.get('window');\n const { top, maxHeight } = computePanelGeometry({\n screenHeight: screen.height,\n insetTop: insets.top,\n insetBottom: insets.bottom,\n keyboardHeight,\n triggerY: triggerLayout.y,\n triggerHeight: triggerLayout.height,\n });\n\n return (\n <View\n style={[\n styles.popoverPanel,\n {\n top,\n left: triggerLayout.x,\n width: triggerLayout.width,\n maxHeight,\n borderColor: colors.border,\n backgroundColor: colors.bg,\n },\n ]}\n onStartShouldSetResponder={() => true}\n >\n {panelBody(false, true)}\n </View>\n );\n })()}\n </Pressable>\n </Modal>\n )}\n\n {!usePopup && isModal && (\n <Modal visible={open} transparent animationType=\"fade\">\n <Pressable style={styles.modalOverlay} onPress={close}>\n <View\n style={[styles.modalPanel, { backgroundColor: colors.bg }]}\n onStartShouldSetResponder={() => true}\n >\n {panelBody(true, true)}\n </View>\n </Pressable>\n </Modal>\n )}\n\n {/* Popup — the container comes from the wrapper (this library's own\n Dialog in sheet position); everything inside it is the same body the\n other two containers render. */}\n {usePopup && renderPopup!({\n visible: open,\n onClose: close,\n title: popupTitle,\n children: panelBody(true, false),\n })}\n\n </View>\n );\n}\n\n/* ---------------------------------------------\n Styles (layout only — colors applied inline via theme tokens)\n---------------------------------------------- */\n\nconst styles = StyleSheet.create({\n container: {\n width: \"100%\",\n position: \"relative\" as const,\n },\n control: {\n flexDirection: \"row\" as const,\n alignItems: \"center\" as const,\n justifyContent: \"space-between\" as const,\n borderWidth: 1,\n borderRadius: 6,\n paddingHorizontal: 10,\n paddingVertical: 10,\n },\n disabled: {\n opacity: 0.5,\n },\n option: {\n paddingHorizontal: 12,\n paddingVertical: 10,\n flexDirection: \"row\" as const,\n justifyContent: \"space-between\" as const,\n alignItems: \"center\" as const,\n },\n groupLabel: {\n paddingHorizontal: 12,\n paddingVertical: 8,\n fontWeight: \"600\" as const,\n },\n input: {\n flex: 1,\n },\n panel: {\n position: \"absolute\" as const,\n top: \"100%\",\n left: 0,\n right: 0,\n marginTop: 4,\n borderWidth: 1,\n borderRadius: 6,\n maxHeight: 260,\n overflow: \"hidden\" as const,\n zIndex: 9999,\n },\n filterContainer: {\n paddingHorizontal: 8,\n paddingVertical: 6,\n borderBottomWidth: 1,\n },\n optionLtr: {\n // `flex: 1` makes the line box span the row, so `textAlign` has something\n // to align within. Without it the box hugs the glyphs and alignment is a\n // no-op.\n flex: 1,\n textAlign: 'left' as const,\n writingDirection: 'ltr' as const,\n },\n optionRowRtl: {\n flexDirection: 'row-reverse' as const,\n },\n optionRtl: {\n flex: 1,\n textAlign: 'right' as const,\n writingDirection: 'rtl' as const,\n },\n listFill: {\n flex: 1,\n },\n // The anchored panel is sized by `maxHeight` with no height, so the list has\n // to grow with its content up to that ceiling and then scroll inside it.\n // `flex: 1` sets flexBasis 0, which contributes nothing to a shrink-wrapping\n // parent.\n listShrink: {\n flexGrow: 0,\n flexShrink: 1,\n },\n listContent: {\n paddingBottom: 12,\n },\n filterInput: {\n fontSize: 14,\n paddingHorizontal: 8,\n paddingVertical: 6,\n borderWidth: 1,\n borderRadius: 4,\n },\n filterLtr: {\n textAlign: 'left' as const,\n writingDirection: 'ltr' as const,\n },\n filterRtl: {\n textAlign: 'right' as const,\n writingDirection: 'rtl' as const,\n },\n emptyContainer: {\n padding: 16,\n alignItems: 'center' as const,\n },\n emptyText: {\n fontSize: 14,\n },\n popoverOverlay: {\n flex: 1,\n backgroundColor: 'transparent',\n },\n popoverPanel: {\n position: 'absolute' as const,\n borderWidth: 1,\n borderRadius: 6,\n overflow: 'hidden' as const,\n elevation: 8,\n shadowColor: '#000',\n shadowOffset: { width: 0, height: 2 },\n shadowOpacity: 0.15,\n shadowRadius: 8,\n },\n modalOverlay: {\n flex: 1,\n backgroundColor: 'rgba(0,0,0,0.4)',\n justifyContent: 'center' as const,\n },\n modalPanel: {\n margin: 24,\n maxHeight: '70%',\n borderRadius: 12,\n overflow: 'hidden' as const,\n },\n});\n"],"names":["resolveThemeTokenForNative","toNativeValue","useRef","useState","useSafeAreaInsets","useKeyboardHeight","useMemo","Keyboard","useCallback","jsx","Text","jsxs","Pressable","Fragment","View","TextInput","FlatList","Input","InputField","Modal","Dimensions","computePanelGeometry","StyleSheet"],"mappings":"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"}
|
|
@@ -146,6 +146,7 @@ function Dropdown({
|
|
|
146
146
|
emptyFilterMessage = "No results found",
|
|
147
147
|
filterPlaceholder = "Search...",
|
|
148
148
|
isRTL = false,
|
|
149
|
+
fontFamily,
|
|
149
150
|
popup = false,
|
|
150
151
|
renderPopup,
|
|
151
152
|
popupTitle,
|
|
@@ -239,9 +240,16 @@ function Dropdown({
|
|
|
239
240
|
content = React.isValidElement(rendered) ? rendered : /* @__PURE__ */ jsx(Text, { children: String(rendered ?? "") });
|
|
240
241
|
} else {
|
|
241
242
|
content = /* @__PURE__ */ jsx(Text, { style: [
|
|
242
|
-
{
|
|
243
|
-
|
|
244
|
-
|
|
243
|
+
{
|
|
244
|
+
color: colors.text,
|
|
245
|
+
fontSize: optionFontSize(),
|
|
246
|
+
fontFamily
|
|
247
|
+
},
|
|
248
|
+
/* The row starts at the reader's edge. A label that opens with a
|
|
249
|
+
flag — "🇦🇺 +61 (AU)" — then puts the flag where an Arabic reader
|
|
250
|
+
starts reading, which is the right. Left unset the row inherited,
|
|
251
|
+
and the flag sat on the far side of the row from the reader. */
|
|
252
|
+
isRTL ? styles.optionRtl : styles.optionLtr
|
|
245
253
|
], children: getLabel(item, optionLabel) });
|
|
246
254
|
}
|
|
247
255
|
return /* @__PURE__ */ jsxs(
|
|
@@ -250,6 +258,15 @@ function Dropdown({
|
|
|
250
258
|
onPress: () => selectItem(item),
|
|
251
259
|
style: [
|
|
252
260
|
styles.option,
|
|
261
|
+
/* ⛔ `textAlign` ALONE CANNOT MOVE THIS ROW. The row is a flex row
|
|
262
|
+
and the label shrink-wraps, so the line box is only as wide as
|
|
263
|
+
its glyphs and aligning text inside it changes nothing — the box
|
|
264
|
+
itself still sits at the row's start. The process layout stays
|
|
265
|
+
LTR (the reader's language is a KitsConcerto concern, not
|
|
266
|
+
`I18nManager`), so `flex-start` is the left. Reversing the row is
|
|
267
|
+
what actually moves the label, and the checkmark, to the edge an
|
|
268
|
+
Arabic reader starts from. */
|
|
269
|
+
isRTL && styles.optionRowRtl,
|
|
253
270
|
selected && highlightOnSelect && { backgroundColor: colors.optionSelected }
|
|
254
271
|
],
|
|
255
272
|
children: [
|
|
@@ -305,7 +322,8 @@ function Dropdown({
|
|
|
305
322
|
{
|
|
306
323
|
borderColor: colors.filterBorder,
|
|
307
324
|
backgroundColor: colors.filterBg,
|
|
308
|
-
color: colors.filterText
|
|
325
|
+
color: colors.filterText,
|
|
326
|
+
fontFamily
|
|
309
327
|
},
|
|
310
328
|
// Every other input in this library names its own edge and
|
|
311
329
|
// direction from the reader's language. Leaving these unset let the
|
|
@@ -326,7 +344,7 @@ function Dropdown({
|
|
|
326
344
|
renderItem: ({ item, index }) => renderItem(item, index),
|
|
327
345
|
keyboardShouldPersistTaps: "handled",
|
|
328
346
|
showsHorizontalScrollIndicator: false,
|
|
329
|
-
ListEmptyComponent: filterQuery ? /* @__PURE__ */ jsx(View, { style: styles.emptyContainer, children: /* @__PURE__ */ jsx(Text, { style: [styles.emptyText, { color: colors.emptyText }], children: emptyFilterMessage }) }) : null
|
|
347
|
+
ListEmptyComponent: filterQuery ? /* @__PURE__ */ jsx(View, { style: styles.emptyContainer, children: /* @__PURE__ */ jsx(Text, { style: [styles.emptyText, { color: colors.emptyText, fontFamily }], children: emptyFilterMessage }) }) : null
|
|
330
348
|
}
|
|
331
349
|
),
|
|
332
350
|
panelFooterTemplate?.()
|
|
@@ -478,6 +496,22 @@ const styles = StyleSheet.create({
|
|
|
478
496
|
paddingVertical: 6,
|
|
479
497
|
borderBottomWidth: 1
|
|
480
498
|
},
|
|
499
|
+
optionLtr: {
|
|
500
|
+
// `flex: 1` makes the line box span the row, so `textAlign` has something
|
|
501
|
+
// to align within. Without it the box hugs the glyphs and alignment is a
|
|
502
|
+
// no-op.
|
|
503
|
+
flex: 1,
|
|
504
|
+
textAlign: "left",
|
|
505
|
+
writingDirection: "ltr"
|
|
506
|
+
},
|
|
507
|
+
optionRowRtl: {
|
|
508
|
+
flexDirection: "row-reverse"
|
|
509
|
+
},
|
|
510
|
+
optionRtl: {
|
|
511
|
+
flex: 1,
|
|
512
|
+
textAlign: "right",
|
|
513
|
+
writingDirection: "rtl"
|
|
514
|
+
},
|
|
481
515
|
listFill: {
|
|
482
516
|
flex: 1
|
|
483
517
|
},
|