@lmb-it/kitsconcerto-native 0.1.261 → 0.1.264
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 +6 -3
- package/animations/index.cjs.map +1 -1
- package/animations/index.js +6 -4
- package/animations/index.js.map +1 -1
- package/apps/mobile/src/Core/Dropdown/index.cjs +58 -6
- package/apps/mobile/src/Core/Dropdown/index.cjs.map +1 -1
- package/apps/mobile/src/Core/Dropdown/index.js +58 -6
- package/apps/mobile/src/Core/Dropdown/index.js.map +1 -1
- package/apps/mobile/src/Core/MultiSelect/index.cjs +17 -3
- package/apps/mobile/src/Core/MultiSelect/index.cjs.map +1 -1
- package/apps/mobile/src/Core/MultiSelect/index.js +17 -3
- package/apps/mobile/src/Core/MultiSelect/index.js.map +1 -1
- package/apps/mobile/src/Factory/helpers/readerEdge.cjs +14 -0
- package/apps/mobile/src/Factory/helpers/readerEdge.cjs.map +1 -0
- package/apps/mobile/src/Factory/helpers/readerEdge.js +12 -0
- package/apps/mobile/src/Factory/helpers/readerEdge.js.map +1 -0
- package/components/overlay/ConfirmDialog/index.cjs +3 -3
- package/components/overlay/ConfirmDialog/index.cjs.map +1 -1
- package/components/overlay/ConfirmDialog/index.js +4 -4
- package/components/overlay/ConfirmDialog/index.js.map +1 -1
- package/components/overlay/Dialog/index.cjs +3 -3
- package/components/overlay/Dialog/index.cjs.map +1 -1
- package/components/overlay/Dialog/index.js +5 -5
- 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
|
@@ -28,9 +28,8 @@ const overlayAnimations = {
|
|
|
28
28
|
// Slightly heavier damping/lower stiffness so the sheet glides up without
|
|
29
29
|
// overshoot. Exit: timed slide-down.
|
|
30
30
|
sheet: {
|
|
31
|
-
enter: { damping:
|
|
32
|
-
exitDuration:
|
|
33
|
-
},
|
|
31
|
+
enter: { damping: 26, stiffness: 140, mass: 1 },
|
|
32
|
+
exitDuration: 260},
|
|
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.
|
|
@@ -45,6 +44,10 @@ const overlayAnimations = {
|
|
|
45
44
|
keyboardGap: 8
|
|
46
45
|
}
|
|
47
46
|
};
|
|
47
|
+
function scrimExitDuration(panelExitDuration) {
|
|
48
|
+
return Math.max(overlayAnimations.scrim.exitDuration, panelExitDuration);
|
|
49
|
+
}
|
|
48
50
|
|
|
49
51
|
exports.overlayAnimations = overlayAnimations;
|
|
52
|
+
exports.scrimExitDuration = scrimExitDuration;
|
|
50
53
|
//# sourceMappingURL=index.cjs.map
|
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
|
|
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 /**\n * Dimmed backdrop behind every overlay (fade in/out).\n *\n * ⚠️ `exitDuration` is a FLOOR, not the value to pass. The scrim is the\n * panel's PARENT — read `scrimExitDuration()` below before using it.\n */\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: 26, stiffness: 140, mass: 1 },\n exitDuration: 260,\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\n/**\n * How long the SCRIM may take to leave, given the panel sitting inside it.\n *\n * ⛔ THE SCRIM CONTAINS THE PANEL, SO A SCRIM THAT FINISHES FIRST TAKES THE\n * PANEL WITH IT MID-ANIMATION. Every overlay here nests the panel inside the\n * scrim's Animated.View. React unmounts a subtree as one thing: when the\n * parent's exiting animation reports finished, the child is removed wherever\n * its own exiting animation happens to be. A 260ms slide-down under a 100ms\n * fade-out does not play for 260ms — it plays for 100 and then the sheet is\n * simply gone.\n *\n * Measured on an iPhone 16 Pro simulator, 30fps, closing the bottom sheet.\n * The flags inside the sheet are the only saturated pixels on the screen, so\n * their y is the sheet's own edge and not the screen's:\n *\n * frame flag y (of 348) sheet white scrim\n * 125 140 237 143 settled\n * 126 143 240 149 starts down\n * 127 197 253 192 54 units travelled\n * 128 gone — 234 removed\n *\n * Three frames. The sheet covered a sixth of its travel and vanished, while\n * the scrim faded normally — which is exactly the report that the overlay\n * fades and the sheet does not move.\n *\n * ⚠️ IT WAS INVISIBLE TO THE OBVIOUS MEASUREMENT. A scan for the topmost\n * bright row could not tell a sheet edge at y=655 from the page behind it at\n * y=655; both read white, so the close looked motionless in both the broken\n * and the fixed build. Only a feature that exists ONLY inside the sheet could\n * say which was on screen.\n *\n * The centred dialog has the same fault at a smaller size — 120ms of zoom-out\n * under a 100ms fade — which is why this is a rule about containment rather\n * than a number for the sheet.\n */\nexport function scrimExitDuration(panelExitDuration: number): number {\n return Math.max(overlayAnimations.scrim.exitDuration, panelExitDuration);\n}\n\nexport default overlayAnimations;\n"],"names":[],"mappings":";;AA6DO,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;AAqCO,SAAS,kBAAkB,iBAAA,EAAmC;AACjE,EAAA,OAAO,IAAA,CAAK,GAAA,CAAI,iBAAA,CAAkB,KAAA,CAAM,cAAc,iBAAiB,CAAA;AAC3E;;;;;"}
|
package/animations/index.js
CHANGED
|
@@ -26,9 +26,8 @@ const overlayAnimations = {
|
|
|
26
26
|
// Slightly heavier damping/lower stiffness so the sheet glides up without
|
|
27
27
|
// overshoot. Exit: timed slide-down.
|
|
28
28
|
sheet: {
|
|
29
|
-
enter: { damping:
|
|
30
|
-
exitDuration:
|
|
31
|
-
},
|
|
29
|
+
enter: { damping: 26, stiffness: 140, mass: 1 },
|
|
30
|
+
exitDuration: 260},
|
|
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.
|
|
@@ -43,6 +42,9 @@ const overlayAnimations = {
|
|
|
43
42
|
keyboardGap: 8
|
|
44
43
|
}
|
|
45
44
|
};
|
|
45
|
+
function scrimExitDuration(panelExitDuration) {
|
|
46
|
+
return Math.max(overlayAnimations.scrim.exitDuration, panelExitDuration);
|
|
47
|
+
}
|
|
46
48
|
|
|
47
|
-
export { overlayAnimations };
|
|
49
|
+
export { overlayAnimations, scrimExitDuration };
|
|
48
50
|
//# sourceMappingURL=index.js.map
|
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
|
|
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 /**\n * Dimmed backdrop behind every overlay (fade in/out).\n *\n * ⚠️ `exitDuration` is a FLOOR, not the value to pass. The scrim is the\n * panel's PARENT — read `scrimExitDuration()` below before using it.\n */\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: 26, stiffness: 140, mass: 1 },\n exitDuration: 260,\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\n/**\n * How long the SCRIM may take to leave, given the panel sitting inside it.\n *\n * ⛔ THE SCRIM CONTAINS THE PANEL, SO A SCRIM THAT FINISHES FIRST TAKES THE\n * PANEL WITH IT MID-ANIMATION. Every overlay here nests the panel inside the\n * scrim's Animated.View. React unmounts a subtree as one thing: when the\n * parent's exiting animation reports finished, the child is removed wherever\n * its own exiting animation happens to be. A 260ms slide-down under a 100ms\n * fade-out does not play for 260ms — it plays for 100 and then the sheet is\n * simply gone.\n *\n * Measured on an iPhone 16 Pro simulator, 30fps, closing the bottom sheet.\n * The flags inside the sheet are the only saturated pixels on the screen, so\n * their y is the sheet's own edge and not the screen's:\n *\n * frame flag y (of 348) sheet white scrim\n * 125 140 237 143 settled\n * 126 143 240 149 starts down\n * 127 197 253 192 54 units travelled\n * 128 gone — 234 removed\n *\n * Three frames. The sheet covered a sixth of its travel and vanished, while\n * the scrim faded normally — which is exactly the report that the overlay\n * fades and the sheet does not move.\n *\n * ⚠️ IT WAS INVISIBLE TO THE OBVIOUS MEASUREMENT. A scan for the topmost\n * bright row could not tell a sheet edge at y=655 from the page behind it at\n * y=655; both read white, so the close looked motionless in both the broken\n * and the fixed build. Only a feature that exists ONLY inside the sheet could\n * say which was on screen.\n *\n * The centred dialog has the same fault at a smaller size — 120ms of zoom-out\n * under a 100ms fade — which is why this is a rule about containment rather\n * than a number for the sheet.\n */\nexport function scrimExitDuration(panelExitDuration: number): number {\n return Math.max(overlayAnimations.scrim.exitDuration, panelExitDuration);\n}\n\nexport default overlayAnimations;\n"],"names":[],"mappings":"AA6DO,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;AAqCO,SAAS,kBAAkB,iBAAA,EAAmC;AACjE,EAAA,OAAO,IAAA,CAAK,GAAA,CAAI,iBAAA,CAAkB,KAAA,CAAM,cAAc,iBAAiB,CAAA;AAC3E;;;;"}
|
|
@@ -85,6 +85,7 @@ require('../RadioButton/index.cjs');
|
|
|
85
85
|
require('../Input/index.cjs');
|
|
86
86
|
require('../Input/Field.cjs');
|
|
87
87
|
require('../Input/Slot.cjs');
|
|
88
|
+
var readerEdge = require('../../Factory/helpers/readerEdge.cjs');
|
|
88
89
|
var panelGeometry = require('./panelGeometry.cjs');
|
|
89
90
|
|
|
90
91
|
const getLabel = (item, optionLabel) => {
|
|
@@ -150,6 +151,7 @@ function Dropdown({
|
|
|
150
151
|
emptyFilterMessage = "No results found",
|
|
151
152
|
filterPlaceholder = "Search...",
|
|
152
153
|
isRTL = false,
|
|
154
|
+
fontFamily,
|
|
153
155
|
popup = false,
|
|
154
156
|
renderPopup,
|
|
155
157
|
popupTitle,
|
|
@@ -172,6 +174,7 @@ function Dropdown({
|
|
|
172
174
|
const [triggerLayout, setTriggerLayout] = React.useState(null);
|
|
173
175
|
const insets = reactNativeSafeAreaContext.useSafeAreaInsets();
|
|
174
176
|
const keyboardHeight = useKeyboardHeight.useKeyboardHeight();
|
|
177
|
+
const edge = readerEdge.readerEdge(isRTL);
|
|
175
178
|
const { viewStyle: externalViewStyle, textStyle: externalTextStyle } = splitStyle(externalStyle);
|
|
176
179
|
const colors = {
|
|
177
180
|
border: t("border") || t("gray.300"),
|
|
@@ -243,9 +246,23 @@ function Dropdown({
|
|
|
243
246
|
content = React.isValidElement(rendered) ? rendered : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { children: String(rendered ?? "") });
|
|
244
247
|
} else {
|
|
245
248
|
content = /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [
|
|
246
|
-
{
|
|
247
|
-
|
|
248
|
-
|
|
249
|
+
{
|
|
250
|
+
color: colors.text,
|
|
251
|
+
fontSize: optionFontSize(),
|
|
252
|
+
fontFamily
|
|
253
|
+
},
|
|
254
|
+
/* The row starts at the reader's edge, and `writingDirection`
|
|
255
|
+
orders the glyphs inside it — which is what puts a leading flag
|
|
256
|
+
at the end an Arabic reader starts from.
|
|
257
|
+
⛔ The physical edge is COMPUTED, never named directly: React
|
|
258
|
+
Native mirrors `textAlign` when the process is RTL, so naming
|
|
259
|
+
the RTL edge for an RTL reader lands on the LTR one. See
|
|
260
|
+
`readerEdge` for the measurements. */
|
|
261
|
+
styles.optionLabelFill,
|
|
262
|
+
{
|
|
263
|
+
textAlign: edge.textAlign,
|
|
264
|
+
writingDirection: isRTL ? "rtl" : "ltr"
|
|
265
|
+
}
|
|
249
266
|
], children: getLabel(item, optionLabel) });
|
|
250
267
|
}
|
|
251
268
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -254,6 +271,20 @@ function Dropdown({
|
|
|
254
271
|
onPress: () => selectItem(item),
|
|
255
272
|
style: [
|
|
256
273
|
styles.option,
|
|
274
|
+
/* Same rule for the row itself, so the checkmark sits at the end
|
|
275
|
+
the reader finishes on rather than the one the process picks.
|
|
276
|
+
⛔ REVERSING THE ROW IS NOT WHAT MOVES THE LABEL. The comment that
|
|
277
|
+
stood here said it was, and the measurement says otherwise: a
|
|
278
|
+
shrink-wrapped Text ignores `textAlign` whichever way the row
|
|
279
|
+
runs, so `flex: 1` on the label is what gives the alignment
|
|
280
|
+
somewhere to push to. The row's direction decides only which end
|
|
281
|
+
the checkmark takes.
|
|
282
|
+
⛔ And it said the process layout "stays LTR". It does not — the
|
|
283
|
+
App calls `I18nManager.forceRTL`, which mirrors both `textAlign`
|
|
284
|
+
and `flexDirection: 'row'`. Writing the RTL edge for an RTL
|
|
285
|
+
reader therefore asked for it twice and landed on the LTR one,
|
|
286
|
+
which is the whole reported fault. See `readerEdge`. */
|
|
287
|
+
{ flexDirection: edge.flexDirection },
|
|
257
288
|
selected && highlightOnSelect && { backgroundColor: colors.optionSelected }
|
|
258
289
|
],
|
|
259
290
|
children: [
|
|
@@ -271,7 +302,20 @@ function Dropdown({
|
|
|
271
302
|
itemTemplate,
|
|
272
303
|
optionGroupLabel,
|
|
273
304
|
checkmark,
|
|
274
|
-
highlightOnSelect
|
|
305
|
+
highlightOnSelect,
|
|
306
|
+
/* ⛔ THE THIRD DISHONEST DEPENDENCY ARRAY IN THIS FAMILY. The body reads
|
|
307
|
+
these too, and a row memoised without them keeps whatever the first
|
|
308
|
+
render happened to hold — the reader's direction, the theme's face and
|
|
309
|
+
the resolved colours. Two frozen memos have already cost a release
|
|
310
|
+
each; this one is listed before it costs a third. */
|
|
311
|
+
isRTL,
|
|
312
|
+
edge.textAlign,
|
|
313
|
+
edge.flexDirection,
|
|
314
|
+
fontFamily,
|
|
315
|
+
colors.text,
|
|
316
|
+
colors.optionSelected,
|
|
317
|
+
colors.groupBg,
|
|
318
|
+
selectItem
|
|
275
319
|
]
|
|
276
320
|
);
|
|
277
321
|
const flatData = React.useMemo(() => {
|
|
@@ -309,7 +353,8 @@ function Dropdown({
|
|
|
309
353
|
{
|
|
310
354
|
borderColor: colors.filterBorder,
|
|
311
355
|
backgroundColor: colors.filterBg,
|
|
312
|
-
color: colors.filterText
|
|
356
|
+
color: colors.filterText,
|
|
357
|
+
fontFamily
|
|
313
358
|
},
|
|
314
359
|
// Every other input in this library names its own edge and
|
|
315
360
|
// direction from the reader's language. Leaving these unset let the
|
|
@@ -330,7 +375,7 @@ function Dropdown({
|
|
|
330
375
|
renderItem: ({ item, index }) => renderItem(item, index),
|
|
331
376
|
keyboardShouldPersistTaps: "handled",
|
|
332
377
|
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
|
|
378
|
+
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
379
|
}
|
|
335
380
|
),
|
|
336
381
|
panelFooterTemplate?.()
|
|
@@ -450,6 +495,13 @@ const styles = reactNative.StyleSheet.create({
|
|
|
450
495
|
disabled: {
|
|
451
496
|
opacity: 0.5
|
|
452
497
|
},
|
|
498
|
+
/* The label takes the row's spare width so `textAlign` has somewhere to
|
|
499
|
+
push to. Without it the Text shrink-wraps its glyphs and the alignment
|
|
500
|
+
has no effect — the first attempt at this fix set only `textAlign` and
|
|
501
|
+
changed nothing on screen. */
|
|
502
|
+
optionLabelFill: {
|
|
503
|
+
flex: 1
|
|
504
|
+
},
|
|
453
505
|
option: {
|
|
454
506
|
paddingHorizontal: 12,
|
|
455
507
|
paddingVertical: 10,
|
|
@@ -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 { readerEdge } from '../../Factory/helpers/readerEdge';\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 /* Physical edges to write so the content lands where the reader starts. */\n const edge = readerEdge(isRTL);\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, and `writingDirection`\n orders the glyphs inside it — which is what puts a leading flag\n at the end an Arabic reader starts from.\n ⛔ The physical edge is COMPUTED, never named directly: React\n Native mirrors `textAlign` when the process is RTL, so naming\n the RTL edge for an RTL reader lands on the LTR one. See\n `readerEdge` for the measurements. */\n styles.optionLabelFill,\n {\n textAlign: edge.textAlign,\n writingDirection: isRTL ? ('rtl' as const) : ('ltr' as const),\n },\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 /* Same rule for the row itself, so the checkmark sits at the end\n the reader finishes on rather than the one the process picks.\n ⛔ REVERSING THE ROW IS NOT WHAT MOVES THE LABEL. The comment that\n stood here said it was, and the measurement says otherwise: a\n shrink-wrapped Text ignores `textAlign` whichever way the row\n runs, so `flex: 1` on the label is what gives the alignment\n somewhere to push to. The row's direction decides only which end\n the checkmark takes.\n ⛔ And it said the process layout \"stays LTR\". It does not — the\n App calls `I18nManager.forceRTL`, which mirrors both `textAlign`\n and `flexDirection: 'row'`. Writing the RTL edge for an RTL\n reader therefore asked for it twice and landed on the LTR one,\n which is the whole reported fault. See `readerEdge`. */\n { flexDirection: edge.flexDirection },\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 /* ⛔ THE THIRD DISHONEST DEPENDENCY ARRAY IN THIS FAMILY. The body reads\n these too, and a row memoised without them keeps whatever the first\n render happened to hold — the reader's direction, the theme's face and\n the resolved colours. Two frozen memos have already cost a release\n each; this one is listed before it costs a third. */\n isRTL,\n edge.textAlign,\n edge.flexDirection,\n fontFamily,\n colors.text,\n colors.optionSelected,\n colors.groupBg,\n selectItem,\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 /* The label takes the row's spare width so `textAlign` has somewhere to\n push to. Without it the Text shrink-wraps its glyphs and the alignment\n has no effect — the first attempt at this fix set only `textAlign` and\n changed nothing on screen. */\n optionLabelFill: {\n flex: 1,\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","readerEdge","useMemo","Keyboard","useCallback","jsx","Text","jsxs","Pressable","Fragment","View","TextInput","FlatList","Input","InputField","Modal","Dimensions","computePanelGeometry","StyleSheet"],"mappings":"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"}
|
|
@@ -81,6 +81,7 @@ import '../RadioButton/index.js';
|
|
|
81
81
|
import '../Input/index.js';
|
|
82
82
|
import '../Input/Field.js';
|
|
83
83
|
import '../Input/Slot.js';
|
|
84
|
+
import { readerEdge } from '../../Factory/helpers/readerEdge.js';
|
|
84
85
|
import { computePanelGeometry } from './panelGeometry.js';
|
|
85
86
|
|
|
86
87
|
const getLabel = (item, optionLabel) => {
|
|
@@ -146,6 +147,7 @@ function Dropdown({
|
|
|
146
147
|
emptyFilterMessage = "No results found",
|
|
147
148
|
filterPlaceholder = "Search...",
|
|
148
149
|
isRTL = false,
|
|
150
|
+
fontFamily,
|
|
149
151
|
popup = false,
|
|
150
152
|
renderPopup,
|
|
151
153
|
popupTitle,
|
|
@@ -168,6 +170,7 @@ function Dropdown({
|
|
|
168
170
|
const [triggerLayout, setTriggerLayout] = useState(null);
|
|
169
171
|
const insets = useSafeAreaInsets();
|
|
170
172
|
const keyboardHeight = useKeyboardHeight();
|
|
173
|
+
const edge = readerEdge(isRTL);
|
|
171
174
|
const { viewStyle: externalViewStyle, textStyle: externalTextStyle } = splitStyle(externalStyle);
|
|
172
175
|
const colors = {
|
|
173
176
|
border: t("border") || t("gray.300"),
|
|
@@ -239,9 +242,23 @@ function Dropdown({
|
|
|
239
242
|
content = React.isValidElement(rendered) ? rendered : /* @__PURE__ */ jsx(Text, { children: String(rendered ?? "") });
|
|
240
243
|
} else {
|
|
241
244
|
content = /* @__PURE__ */ jsx(Text, { style: [
|
|
242
|
-
{
|
|
243
|
-
|
|
244
|
-
|
|
245
|
+
{
|
|
246
|
+
color: colors.text,
|
|
247
|
+
fontSize: optionFontSize(),
|
|
248
|
+
fontFamily
|
|
249
|
+
},
|
|
250
|
+
/* The row starts at the reader's edge, and `writingDirection`
|
|
251
|
+
orders the glyphs inside it — which is what puts a leading flag
|
|
252
|
+
at the end an Arabic reader starts from.
|
|
253
|
+
⛔ The physical edge is COMPUTED, never named directly: React
|
|
254
|
+
Native mirrors `textAlign` when the process is RTL, so naming
|
|
255
|
+
the RTL edge for an RTL reader lands on the LTR one. See
|
|
256
|
+
`readerEdge` for the measurements. */
|
|
257
|
+
styles.optionLabelFill,
|
|
258
|
+
{
|
|
259
|
+
textAlign: edge.textAlign,
|
|
260
|
+
writingDirection: isRTL ? "rtl" : "ltr"
|
|
261
|
+
}
|
|
245
262
|
], children: getLabel(item, optionLabel) });
|
|
246
263
|
}
|
|
247
264
|
return /* @__PURE__ */ jsxs(
|
|
@@ -250,6 +267,20 @@ function Dropdown({
|
|
|
250
267
|
onPress: () => selectItem(item),
|
|
251
268
|
style: [
|
|
252
269
|
styles.option,
|
|
270
|
+
/* Same rule for the row itself, so the checkmark sits at the end
|
|
271
|
+
the reader finishes on rather than the one the process picks.
|
|
272
|
+
⛔ REVERSING THE ROW IS NOT WHAT MOVES THE LABEL. The comment that
|
|
273
|
+
stood here said it was, and the measurement says otherwise: a
|
|
274
|
+
shrink-wrapped Text ignores `textAlign` whichever way the row
|
|
275
|
+
runs, so `flex: 1` on the label is what gives the alignment
|
|
276
|
+
somewhere to push to. The row's direction decides only which end
|
|
277
|
+
the checkmark takes.
|
|
278
|
+
⛔ And it said the process layout "stays LTR". It does not — the
|
|
279
|
+
App calls `I18nManager.forceRTL`, which mirrors both `textAlign`
|
|
280
|
+
and `flexDirection: 'row'`. Writing the RTL edge for an RTL
|
|
281
|
+
reader therefore asked for it twice and landed on the LTR one,
|
|
282
|
+
which is the whole reported fault. See `readerEdge`. */
|
|
283
|
+
{ flexDirection: edge.flexDirection },
|
|
253
284
|
selected && highlightOnSelect && { backgroundColor: colors.optionSelected }
|
|
254
285
|
],
|
|
255
286
|
children: [
|
|
@@ -267,7 +298,20 @@ function Dropdown({
|
|
|
267
298
|
itemTemplate,
|
|
268
299
|
optionGroupLabel,
|
|
269
300
|
checkmark,
|
|
270
|
-
highlightOnSelect
|
|
301
|
+
highlightOnSelect,
|
|
302
|
+
/* ⛔ THE THIRD DISHONEST DEPENDENCY ARRAY IN THIS FAMILY. The body reads
|
|
303
|
+
these too, and a row memoised without them keeps whatever the first
|
|
304
|
+
render happened to hold — the reader's direction, the theme's face and
|
|
305
|
+
the resolved colours. Two frozen memos have already cost a release
|
|
306
|
+
each; this one is listed before it costs a third. */
|
|
307
|
+
isRTL,
|
|
308
|
+
edge.textAlign,
|
|
309
|
+
edge.flexDirection,
|
|
310
|
+
fontFamily,
|
|
311
|
+
colors.text,
|
|
312
|
+
colors.optionSelected,
|
|
313
|
+
colors.groupBg,
|
|
314
|
+
selectItem
|
|
271
315
|
]
|
|
272
316
|
);
|
|
273
317
|
const flatData = useMemo(() => {
|
|
@@ -305,7 +349,8 @@ function Dropdown({
|
|
|
305
349
|
{
|
|
306
350
|
borderColor: colors.filterBorder,
|
|
307
351
|
backgroundColor: colors.filterBg,
|
|
308
|
-
color: colors.filterText
|
|
352
|
+
color: colors.filterText,
|
|
353
|
+
fontFamily
|
|
309
354
|
},
|
|
310
355
|
// Every other input in this library names its own edge and
|
|
311
356
|
// direction from the reader's language. Leaving these unset let the
|
|
@@ -326,7 +371,7 @@ function Dropdown({
|
|
|
326
371
|
renderItem: ({ item, index }) => renderItem(item, index),
|
|
327
372
|
keyboardShouldPersistTaps: "handled",
|
|
328
373
|
showsHorizontalScrollIndicator: false,
|
|
329
|
-
ListEmptyComponent: filterQuery ? /* @__PURE__ */ jsx(View, { style: styles.emptyContainer, children: /* @__PURE__ */ jsx(Text, { style: [styles.emptyText, { color: colors.emptyText }], children: emptyFilterMessage }) }) : null
|
|
374
|
+
ListEmptyComponent: filterQuery ? /* @__PURE__ */ jsx(View, { style: styles.emptyContainer, children: /* @__PURE__ */ jsx(Text, { style: [styles.emptyText, { color: colors.emptyText, fontFamily }], children: emptyFilterMessage }) }) : null
|
|
330
375
|
}
|
|
331
376
|
),
|
|
332
377
|
panelFooterTemplate?.()
|
|
@@ -446,6 +491,13 @@ const styles = StyleSheet.create({
|
|
|
446
491
|
disabled: {
|
|
447
492
|
opacity: 0.5
|
|
448
493
|
},
|
|
494
|
+
/* The label takes the row's spare width so `textAlign` has somewhere to
|
|
495
|
+
push to. Without it the Text shrink-wraps its glyphs and the alignment
|
|
496
|
+
has no effect — the first attempt at this fix set only `textAlign` and
|
|
497
|
+
changed nothing on screen. */
|
|
498
|
+
optionLabelFill: {
|
|
499
|
+
flex: 1
|
|
500
|
+
},
|
|
449
501
|
option: {
|
|
450
502
|
paddingHorizontal: 12,
|
|
451
503
|
paddingVertical: 10,
|