@multiplatform.one/forms 7.65.2 → 7.67.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/FloatingPanel/RegularPanel.cjs +164 -0
- package/dist/cjs/FloatingPanel/RegularPanel.native.js +169 -0
- package/dist/cjs/FloatingPanel/RegularPanel.native.js.map +1 -0
- package/dist/cjs/FloatingPanel/compactFace.cjs +6 -0
- package/dist/cjs/FloatingPanel/compactFace.native.js +6 -0
- package/dist/cjs/FloatingPanel/compactFace.native.js.map +1 -1
- package/dist/cjs/FloatingPanel/containingBlock.cjs +46 -0
- package/dist/cjs/FloatingPanel/containingBlock.native.js +51 -0
- package/dist/cjs/FloatingPanel/containingBlock.native.js.map +1 -0
- package/dist/cjs/FloatingPanel/index.cjs +2 -20
- package/dist/cjs/FloatingPanel/index.native.js +79 -45
- package/dist/cjs/FloatingPanel/index.native.js.map +1 -1
- package/dist/cjs/FloatingPanel/pointAnchor.cjs +25 -0
- package/dist/cjs/FloatingPanel/pointAnchor.native.js +26 -0
- package/dist/cjs/FloatingPanel/pointAnchor.native.js.map +1 -1
- package/dist/cjs/FloatingPanel/regularPlacement.cjs +61 -0
- package/dist/cjs/FloatingPanel/regularPlacement.native.js +65 -0
- package/dist/cjs/FloatingPanel/regularPlacement.native.js.map +1 -0
- package/dist/cjs/fields/Combobox/index.cjs +8 -10
- package/dist/cjs/fields/Combobox/index.native.js +10 -10
- package/dist/cjs/fields/Combobox/index.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/parts.cjs +1 -0
- package/dist/cjs/fields/DatePicker/parts.native.js +3 -0
- package/dist/cjs/fields/DatePicker/parts.native.js.map +1 -1
- package/dist/cjs/fields/Input/index.cjs +5 -0
- package/dist/cjs/fields/Input/index.native.js +5 -0
- package/dist/cjs/fields/Input/index.native.js.map +1 -1
- package/dist/cjs/fields/Select/InlineChoices.cjs +3 -2
- package/dist/cjs/fields/Select/InlineChoices.native.js +5 -2
- package/dist/cjs/fields/Select/InlineChoices.native.js.map +1 -1
- package/dist/cjs/fields/Select/SheetPickerRow.cjs +154 -0
- package/dist/cjs/fields/Select/SheetPickerRow.native.js +165 -0
- package/dist/cjs/fields/Select/SheetPickerRow.native.js.map +1 -0
- package/dist/cjs/fields/Select/index.cjs +64 -5
- package/dist/cjs/fields/Select/index.native.js +86 -27
- package/dist/cjs/fields/Select/index.native.js.map +1 -1
- package/dist/cjs/fields/Select/shouldInlineChoices.cjs +14 -1
- package/dist/cjs/fields/Select/shouldInlineChoices.native.js +15 -1
- package/dist/cjs/fields/Select/shouldInlineChoices.native.js.map +1 -1
- package/dist/cjs/fields/Slider/index.cjs +96 -4
- package/dist/cjs/fields/Slider/index.native.js +103 -5
- package/dist/cjs/fields/Slider/index.native.js.map +1 -1
- package/dist/cjs/fields/Switch/index.cjs +71 -1
- package/dist/cjs/fields/Switch/index.native.js +72 -1
- package/dist/cjs/fields/Switch/index.native.js.map +1 -1
- package/dist/cjs/fields/TimePicker/parts.cjs +1 -0
- package/dist/cjs/fields/TimePicker/parts.native.js +1 -0
- package/dist/cjs/fields/TimePicker/parts.native.js.map +1 -1
- package/dist/cjs/fields/ToggleGroup/index.cjs +67 -1
- package/dist/cjs/fields/ToggleGroup/index.native.js +75 -1
- package/dist/cjs/fields/ToggleGroup/index.native.js.map +1 -1
- package/dist/cjs/fields/nativeDateTime/OsDateTimeSheet.cjs +34 -19
- package/dist/cjs/fields/nativeDateTime/OsDateTimeSheet.native.js +44 -21
- package/dist/cjs/fields/nativeDateTime/OsDateTimeSheet.native.js.map +1 -1
- package/dist/cjs/fields/nativeDateTime/sheetKeyboard.cjs +54 -0
- package/dist/cjs/fields/nativeDateTime/sheetKeyboard.native.js +57 -0
- package/dist/cjs/fields/nativeDateTime/sheetKeyboard.native.js.map +1 -0
- package/dist/cjs/index.cjs +11 -0
- package/dist/cjs/index.native.js +11 -0
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/cjs/shared/overlaySizeClass.cjs +42 -0
- package/dist/cjs/shared/overlaySizeClass.native.js +45 -0
- package/dist/cjs/shared/overlaySizeClass.native.js.map +1 -0
- package/dist/cjs/shared/sheetNavigation.cjs +76 -0
- package/dist/cjs/shared/sheetNavigation.native.js +129 -0
- package/dist/cjs/shared/sheetNavigation.native.js.map +1 -0
- package/dist/cjs/shared/systemControlModules.cjs +34 -0
- package/dist/cjs/shared/systemControlModules.gnome.cjs +34 -0
- package/dist/cjs/shared/systemControlModules.gnome.native.js +37 -0
- package/dist/cjs/shared/systemControlModules.gnome.native.js.map +1 -0
- package/dist/cjs/shared/systemControlModules.native.js +77 -0
- package/dist/cjs/shared/systemControlModules.native.js.map +1 -0
- package/dist/cjs/shared/systemControls.cjs +47 -0
- package/dist/cjs/shared/systemControls.native.js +51 -0
- package/dist/cjs/shared/systemControls.native.js.map +1 -0
- package/dist/esm/FloatingPanel/RegularPanel.mjs +139 -0
- package/dist/esm/FloatingPanel/RegularPanel.mjs.map +1 -0
- package/dist/esm/FloatingPanel/RegularPanel.native.js +141 -0
- package/dist/esm/FloatingPanel/RegularPanel.native.js.map +1 -0
- package/dist/esm/FloatingPanel/compactFace.mjs +5 -1
- package/dist/esm/FloatingPanel/compactFace.mjs.map +1 -1
- package/dist/esm/FloatingPanel/compactFace.native.js +5 -1
- package/dist/esm/FloatingPanel/compactFace.native.js.map +1 -1
- package/dist/esm/FloatingPanel/containingBlock.mjs +21 -0
- package/dist/esm/FloatingPanel/containingBlock.mjs.map +1 -0
- package/dist/esm/FloatingPanel/containingBlock.native.js +23 -0
- package/dist/esm/FloatingPanel/containingBlock.native.js.map +1 -0
- package/dist/esm/FloatingPanel/index.mjs +1 -19
- package/dist/esm/FloatingPanel/index.mjs.map +1 -1
- package/dist/esm/FloatingPanel/index.native.js +83 -49
- package/dist/esm/FloatingPanel/index.native.js.map +1 -1
- package/dist/esm/FloatingPanel/pointAnchor.mjs +25 -1
- package/dist/esm/FloatingPanel/pointAnchor.mjs.map +1 -1
- package/dist/esm/FloatingPanel/pointAnchor.native.js +26 -1
- package/dist/esm/FloatingPanel/pointAnchor.native.js.map +1 -1
- package/dist/esm/FloatingPanel/regularPlacement.mjs +35 -0
- package/dist/esm/FloatingPanel/regularPlacement.mjs.map +1 -0
- package/dist/esm/FloatingPanel/regularPlacement.native.js +36 -0
- package/dist/esm/FloatingPanel/regularPlacement.native.js.map +1 -0
- package/dist/esm/fields/Combobox/index.mjs +9 -11
- package/dist/esm/fields/Combobox/index.mjs.map +1 -1
- package/dist/esm/fields/Combobox/index.native.js +11 -11
- package/dist/esm/fields/Combobox/index.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/parts.mjs +1 -0
- package/dist/esm/fields/DatePicker/parts.mjs.map +1 -1
- package/dist/esm/fields/DatePicker/parts.native.js +3 -0
- package/dist/esm/fields/DatePicker/parts.native.js.map +1 -1
- package/dist/esm/fields/Input/index.mjs +6 -1
- package/dist/esm/fields/Input/index.mjs.map +1 -1
- package/dist/esm/fields/Input/index.native.js +6 -1
- package/dist/esm/fields/Input/index.native.js.map +1 -1
- package/dist/esm/fields/Select/InlineChoices.mjs +3 -2
- package/dist/esm/fields/Select/InlineChoices.mjs.map +1 -1
- package/dist/esm/fields/Select/InlineChoices.native.js +5 -2
- package/dist/esm/fields/Select/InlineChoices.native.js.map +1 -1
- package/dist/esm/fields/Select/SheetPickerRow.mjs +129 -0
- package/dist/esm/fields/Select/SheetPickerRow.mjs.map +1 -0
- package/dist/esm/fields/Select/SheetPickerRow.native.js +137 -0
- package/dist/esm/fields/Select/SheetPickerRow.native.js.map +1 -0
- package/dist/esm/fields/Select/index.mjs +66 -7
- package/dist/esm/fields/Select/index.mjs.map +1 -1
- package/dist/esm/fields/Select/index.native.js +88 -29
- package/dist/esm/fields/Select/index.native.js.map +1 -1
- package/dist/esm/fields/Select/shouldInlineChoices.mjs +12 -1
- package/dist/esm/fields/Select/shouldInlineChoices.mjs.map +1 -1
- package/dist/esm/fields/Select/shouldInlineChoices.native.js +13 -1
- package/dist/esm/fields/Select/shouldInlineChoices.native.js.map +1 -1
- package/dist/esm/fields/Slider/index.mjs +96 -4
- package/dist/esm/fields/Slider/index.mjs.map +1 -1
- package/dist/esm/fields/Slider/index.native.js +103 -5
- package/dist/esm/fields/Slider/index.native.js.map +1 -1
- package/dist/esm/fields/Switch/index.mjs +71 -1
- package/dist/esm/fields/Switch/index.mjs.map +1 -1
- package/dist/esm/fields/Switch/index.native.js +72 -1
- package/dist/esm/fields/Switch/index.native.js.map +1 -1
- package/dist/esm/fields/TimePicker/parts.mjs +1 -0
- package/dist/esm/fields/TimePicker/parts.mjs.map +1 -1
- package/dist/esm/fields/TimePicker/parts.native.js +1 -0
- package/dist/esm/fields/TimePicker/parts.native.js.map +1 -1
- package/dist/esm/fields/ToggleGroup/index.mjs +67 -1
- package/dist/esm/fields/ToggleGroup/index.mjs.map +1 -1
- package/dist/esm/fields/ToggleGroup/index.native.js +75 -1
- package/dist/esm/fields/ToggleGroup/index.native.js.map +1 -1
- package/dist/esm/fields/nativeDateTime/OsDateTimeSheet.mjs +36 -21
- package/dist/esm/fields/nativeDateTime/OsDateTimeSheet.mjs.map +1 -1
- package/dist/esm/fields/nativeDateTime/OsDateTimeSheet.native.js +46 -23
- package/dist/esm/fields/nativeDateTime/OsDateTimeSheet.native.js.map +1 -1
- package/dist/esm/fields/nativeDateTime/sheetKeyboard.mjs +21 -0
- package/dist/esm/fields/nativeDateTime/sheetKeyboard.mjs.map +1 -0
- package/dist/esm/fields/nativeDateTime/sheetKeyboard.native.js +21 -0
- package/dist/esm/fields/nativeDateTime/sheetKeyboard.native.js.map +1 -0
- package/dist/esm/index.mjs +3 -1
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/index.native.js +3 -1
- package/dist/esm/index.native.js.map +1 -1
- package/dist/esm/shared/overlaySizeClass.mjs +14 -0
- package/dist/esm/shared/overlaySizeClass.mjs.map +1 -0
- package/dist/esm/shared/overlaySizeClass.native.js +14 -0
- package/dist/esm/shared/overlaySizeClass.native.js.map +1 -0
- package/dist/esm/shared/sheetNavigation.mjs +47 -0
- package/dist/esm/shared/sheetNavigation.mjs.map +1 -0
- package/dist/esm/shared/sheetNavigation.native.js +97 -0
- package/dist/esm/shared/sheetNavigation.native.js.map +1 -0
- package/dist/esm/shared/systemControlModules.gnome.mjs +8 -0
- package/dist/esm/shared/systemControlModules.gnome.mjs.map +1 -0
- package/dist/esm/shared/systemControlModules.gnome.native.js +8 -0
- package/dist/esm/shared/systemControlModules.gnome.native.js.map +1 -0
- package/dist/esm/shared/systemControlModules.mjs +8 -0
- package/dist/esm/shared/systemControlModules.mjs.map +1 -0
- package/dist/esm/shared/systemControlModules.native.js +47 -0
- package/dist/esm/shared/systemControlModules.native.js.map +1 -0
- package/dist/esm/shared/systemControls.mjs +19 -0
- package/dist/esm/shared/systemControls.mjs.map +1 -0
- package/dist/esm/shared/systemControls.native.js +20 -0
- package/dist/esm/shared/systemControls.native.js.map +1 -0
- package/dist/jsx/FloatingPanel/RegularPanel.mjs +139 -0
- package/dist/jsx/FloatingPanel/RegularPanel.mjs.map +1 -0
- package/dist/jsx/FloatingPanel/RegularPanel.native.js +169 -0
- package/dist/jsx/FloatingPanel/RegularPanel.native.js.map +1 -0
- package/dist/jsx/FloatingPanel/compactFace.mjs +5 -1
- package/dist/jsx/FloatingPanel/compactFace.mjs.map +1 -1
- package/dist/jsx/FloatingPanel/compactFace.native.js +6 -0
- package/dist/jsx/FloatingPanel/compactFace.native.js.map +1 -1
- package/dist/jsx/FloatingPanel/containingBlock.mjs +21 -0
- package/dist/jsx/FloatingPanel/containingBlock.mjs.map +1 -0
- package/dist/jsx/FloatingPanel/containingBlock.native.js +51 -0
- package/dist/jsx/FloatingPanel/containingBlock.native.js.map +1 -0
- package/dist/jsx/FloatingPanel/index.mjs +1 -19
- package/dist/jsx/FloatingPanel/index.mjs.map +1 -1
- package/dist/jsx/FloatingPanel/index.native.js +79 -45
- package/dist/jsx/FloatingPanel/index.native.js.map +1 -1
- package/dist/jsx/FloatingPanel/pointAnchor.mjs +25 -1
- package/dist/jsx/FloatingPanel/pointAnchor.mjs.map +1 -1
- package/dist/jsx/FloatingPanel/pointAnchor.native.js +26 -0
- package/dist/jsx/FloatingPanel/pointAnchor.native.js.map +1 -1
- package/dist/jsx/FloatingPanel/regularPlacement.mjs +35 -0
- package/dist/jsx/FloatingPanel/regularPlacement.mjs.map +1 -0
- package/dist/jsx/FloatingPanel/regularPlacement.native.js +65 -0
- package/dist/jsx/FloatingPanel/regularPlacement.native.js.map +1 -0
- package/dist/jsx/fields/Combobox/index.mjs +9 -11
- package/dist/jsx/fields/Combobox/index.mjs.map +1 -1
- package/dist/jsx/fields/Combobox/index.native.js +10 -10
- package/dist/jsx/fields/Combobox/index.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/parts.mjs +1 -0
- package/dist/jsx/fields/DatePicker/parts.mjs.map +1 -1
- package/dist/jsx/fields/DatePicker/parts.native.js +3 -0
- package/dist/jsx/fields/DatePicker/parts.native.js.map +1 -1
- package/dist/jsx/fields/Input/index.mjs +6 -1
- package/dist/jsx/fields/Input/index.mjs.map +1 -1
- package/dist/jsx/fields/Input/index.native.js +5 -0
- package/dist/jsx/fields/Input/index.native.js.map +1 -1
- package/dist/jsx/fields/Select/InlineChoices.mjs +3 -2
- package/dist/jsx/fields/Select/InlineChoices.mjs.map +1 -1
- package/dist/jsx/fields/Select/InlineChoices.native.js +5 -2
- package/dist/jsx/fields/Select/InlineChoices.native.js.map +1 -1
- package/dist/jsx/fields/Select/SheetPickerRow.mjs +129 -0
- package/dist/jsx/fields/Select/SheetPickerRow.mjs.map +1 -0
- package/dist/jsx/fields/Select/SheetPickerRow.native.js +165 -0
- package/dist/jsx/fields/Select/SheetPickerRow.native.js.map +1 -0
- package/dist/jsx/fields/Select/index.mjs +66 -7
- package/dist/jsx/fields/Select/index.mjs.map +1 -1
- package/dist/jsx/fields/Select/index.native.js +86 -27
- package/dist/jsx/fields/Select/index.native.js.map +1 -1
- package/dist/jsx/fields/Select/shouldInlineChoices.mjs +12 -1
- package/dist/jsx/fields/Select/shouldInlineChoices.mjs.map +1 -1
- package/dist/jsx/fields/Select/shouldInlineChoices.native.js +15 -1
- package/dist/jsx/fields/Select/shouldInlineChoices.native.js.map +1 -1
- package/dist/jsx/fields/Slider/index.mjs +96 -4
- package/dist/jsx/fields/Slider/index.mjs.map +1 -1
- package/dist/jsx/fields/Slider/index.native.js +103 -5
- package/dist/jsx/fields/Slider/index.native.js.map +1 -1
- package/dist/jsx/fields/Switch/index.mjs +71 -1
- package/dist/jsx/fields/Switch/index.mjs.map +1 -1
- package/dist/jsx/fields/Switch/index.native.js +72 -1
- package/dist/jsx/fields/Switch/index.native.js.map +1 -1
- package/dist/jsx/fields/TimePicker/parts.mjs +1 -0
- package/dist/jsx/fields/TimePicker/parts.mjs.map +1 -1
- package/dist/jsx/fields/TimePicker/parts.native.js +1 -0
- package/dist/jsx/fields/TimePicker/parts.native.js.map +1 -1
- package/dist/jsx/fields/ToggleGroup/index.mjs +67 -1
- package/dist/jsx/fields/ToggleGroup/index.mjs.map +1 -1
- package/dist/jsx/fields/ToggleGroup/index.native.js +75 -1
- package/dist/jsx/fields/ToggleGroup/index.native.js.map +1 -1
- package/dist/jsx/fields/nativeDateTime/OsDateTimeSheet.mjs +36 -21
- package/dist/jsx/fields/nativeDateTime/OsDateTimeSheet.mjs.map +1 -1
- package/dist/jsx/fields/nativeDateTime/OsDateTimeSheet.native.js +44 -21
- package/dist/jsx/fields/nativeDateTime/OsDateTimeSheet.native.js.map +1 -1
- package/dist/jsx/fields/nativeDateTime/sheetKeyboard.mjs +21 -0
- package/dist/jsx/fields/nativeDateTime/sheetKeyboard.mjs.map +1 -0
- package/dist/jsx/fields/nativeDateTime/sheetKeyboard.native.js +57 -0
- package/dist/jsx/fields/nativeDateTime/sheetKeyboard.native.js.map +1 -0
- package/dist/jsx/index.js +3 -1
- package/dist/jsx/index.js.map +1 -1
- package/dist/jsx/index.mjs +3 -1
- package/dist/jsx/index.mjs.map +1 -1
- package/dist/jsx/index.native.js +11 -0
- package/dist/jsx/index.native.js.map +1 -1
- package/dist/jsx/shared/overlaySizeClass.mjs +14 -0
- package/dist/jsx/shared/overlaySizeClass.mjs.map +1 -0
- package/dist/jsx/shared/overlaySizeClass.native.js +45 -0
- package/dist/jsx/shared/overlaySizeClass.native.js.map +1 -0
- package/dist/jsx/shared/sheetNavigation.mjs +47 -0
- package/dist/jsx/shared/sheetNavigation.mjs.map +1 -0
- package/dist/jsx/shared/sheetNavigation.native.js +129 -0
- package/dist/jsx/shared/sheetNavigation.native.js.map +1 -0
- package/dist/jsx/shared/systemControlModules.gnome.mjs +8 -0
- package/dist/jsx/shared/systemControlModules.gnome.mjs.map +1 -0
- package/dist/jsx/shared/systemControlModules.gnome.native.js +37 -0
- package/dist/jsx/shared/systemControlModules.gnome.native.js.map +1 -0
- package/dist/jsx/shared/systemControlModules.mjs +8 -0
- package/dist/jsx/shared/systemControlModules.mjs.map +1 -0
- package/dist/jsx/shared/systemControlModules.native.js +77 -0
- package/dist/jsx/shared/systemControlModules.native.js.map +1 -0
- package/dist/jsx/shared/systemControls.mjs +19 -0
- package/dist/jsx/shared/systemControls.mjs.map +1 -0
- package/dist/jsx/shared/systemControls.native.js +51 -0
- package/dist/jsx/shared/systemControls.native.js.map +1 -0
- package/package.json +16 -8
- package/src/FloatingPanel/FloatingPanel.menuFace.native.spec.tsx +73 -3
- package/src/FloatingPanel/FloatingPanel.regularWidth.native.spec.tsx +193 -0
- package/src/FloatingPanel/RegularPanel.tsx +159 -0
- package/src/FloatingPanel/compactFace.spec.ts +24 -1
- package/src/FloatingPanel/compactFace.ts +16 -0
- package/src/FloatingPanel/containingBlock.ts +32 -0
- package/src/FloatingPanel/index.native.tsx +80 -35
- package/src/FloatingPanel/index.tsx +1 -33
- package/src/FloatingPanel/pointAnchor.spec.ts +29 -0
- package/src/FloatingPanel/pointAnchor.ts +30 -0
- package/src/FloatingPanel/regularPlacement.spec.ts +65 -0
- package/src/FloatingPanel/regularPlacement.ts +40 -0
- package/src/fields/Combobox/Combobox.regularWidth.native.spec.tsx +94 -0
- package/src/fields/Combobox/index.tsx +11 -34
- package/src/fields/DatePicker/parts.tsx +3 -0
- package/src/fields/DatePicker/touchWeb.spec.tsx +13 -0
- package/src/fields/Input/Input.formName.spec.tsx +53 -0
- package/src/fields/Input/index.tsx +6 -1
- package/src/fields/Select/InlineChoices.tsx +6 -3
- package/src/fields/Select/SheetPickerRow.tsx +160 -0
- package/src/fields/Select/index.tsx +67 -5
- package/src/fields/Select/shouldInlineChoices.spec.ts +21 -1
- package/src/fields/Select/shouldInlineChoices.ts +26 -0
- package/src/fields/Slider/Slider.system.native.spec.tsx +168 -0
- package/src/fields/Slider/index.tsx +166 -30
- package/src/fields/Switch/Switch.system.native.spec.tsx +162 -0
- package/src/fields/Switch/index.tsx +98 -0
- package/src/fields/TimePicker/parts.tsx +1 -0
- package/src/fields/ToggleGroup/ToggleGroup.system.native.spec.tsx +192 -0
- package/src/fields/ToggleGroup/index.tsx +111 -0
- package/src/fields/nativeDateTime/OsDateTimeSheet.presentation.spec.tsx +167 -0
- package/src/fields/nativeDateTime/OsDateTimeSheet.tsx +36 -18
- package/src/fields/nativeDateTime/sheetKeyboard.spec.ts +60 -0
- package/src/fields/nativeDateTime/sheetKeyboard.ts +45 -0
- package/src/index.ts +15 -0
- package/src/shared/overlaySizeClass.spec.ts +27 -0
- package/src/shared/overlaySizeClass.ts +36 -0
- package/src/shared/sheetNavigation.ts +82 -0
- package/src/shared/systemControlModules.gnome.ts +10 -0
- package/src/shared/systemControlModules.native.spec.ts +52 -0
- package/src/shared/systemControlModules.native.ts +66 -0
- package/src/shared/systemControlModules.ts +10 -0
- package/src/shared/systemControls.ts +70 -0
- package/types/FloatingPanel/RegularPanel.d.ts +29 -0
- package/types/FloatingPanel/RegularPanel.d.ts.map +1 -0
- package/types/FloatingPanel/compactFace.d.ts +12 -0
- package/types/FloatingPanel/compactFace.d.ts.map +1 -1
- package/types/FloatingPanel/containingBlock.d.ts +14 -0
- package/types/FloatingPanel/containingBlock.d.ts.map +1 -0
- package/types/FloatingPanel/index.d.ts.map +1 -1
- package/types/FloatingPanel/index.native.d.ts +6 -1
- package/types/FloatingPanel/index.native.d.ts.map +1 -1
- package/types/FloatingPanel/pointAnchor.d.ts +12 -0
- package/types/FloatingPanel/pointAnchor.d.ts.map +1 -1
- package/types/FloatingPanel/regularPlacement.d.ts +20 -0
- package/types/FloatingPanel/regularPlacement.d.ts.map +1 -0
- package/types/fields/Combobox/index.d.ts.map +1 -1
- package/types/fields/DatePicker/parts.d.ts.map +1 -1
- package/types/fields/Input/index.d.ts.map +1 -1
- package/types/fields/Select/InlineChoices.d.ts.map +1 -1
- package/types/fields/Select/SheetPickerRow.d.ts +23 -0
- package/types/fields/Select/SheetPickerRow.d.ts.map +1 -0
- package/types/fields/Select/index.d.ts.map +1 -1
- package/types/fields/Select/shouldInlineChoices.d.ts +15 -0
- package/types/fields/Select/shouldInlineChoices.d.ts.map +1 -1
- package/types/fields/Slider/index.d.ts +7 -1
- package/types/fields/Slider/index.d.ts.map +1 -1
- package/types/fields/Switch/index.d.ts +7 -1
- package/types/fields/Switch/index.d.ts.map +1 -1
- package/types/fields/TimePicker/parts.d.ts.map +1 -1
- package/types/fields/ToggleGroup/index.d.ts +8 -1
- package/types/fields/ToggleGroup/index.d.ts.map +1 -1
- package/types/fields/nativeDateTime/OsDateTimeSheet.d.ts.map +1 -1
- package/types/fields/nativeDateTime/sheetKeyboard.d.ts +20 -0
- package/types/fields/nativeDateTime/sheetKeyboard.d.ts.map +1 -0
- package/types/index.d.ts +4 -0
- package/types/index.d.ts.map +1 -1
- package/types/shared/overlaySizeClass.d.ts +24 -0
- package/types/shared/overlaySizeClass.d.ts.map +1 -0
- package/types/shared/sheetNavigation.d.ts +31 -0
- package/types/shared/sheetNavigation.d.ts.map +1 -0
- package/types/shared/systemControlModules.d.ts +5 -0
- package/types/shared/systemControlModules.d.ts.map +1 -0
- package/types/shared/systemControlModules.gnome.d.ts +5 -0
- package/types/shared/systemControlModules.gnome.d.ts.map +1 -0
- package/types/shared/systemControlModules.native.d.ts +20 -0
- package/types/shared/systemControlModules.native.d.ts.map +1 -0
- package/types/shared/systemControls.d.ts +53 -0
- package/types/shared/systemControls.d.ts.map +1 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { keyboardFocusRingProps, useGlyphColor } from "@multiplatform.one/theme";
|
|
2
|
+
import { CaretRightIcon } from "@phosphor-icons/react";
|
|
3
|
+
import { useId, useLayoutEffect, useEffect } from "react";
|
|
4
|
+
import { Pressable } from "react-native";
|
|
5
|
+
import { isWeb, Text, View, XStack } from "tamagui";
|
|
6
|
+
import { useFieldDescribedBy } from "../../fieldLayout";
|
|
7
|
+
import { formInputColors } from "../../shared/colorRamps";
|
|
8
|
+
import { useSheetPageOpen, type SheetNavigationStore } from "../../shared/sheetNavigation";
|
|
9
|
+
import { InlineChoices, type InlineChoice } from "./InlineChoices";
|
|
10
|
+
|
|
11
|
+
const useIsoLayoutEffect = typeof window === "undefined" ? useEffect : useLayoutEffect;
|
|
12
|
+
|
|
13
|
+
export interface SheetPickerRowProps {
|
|
14
|
+
store: SheetNavigationStore;
|
|
15
|
+
label: string;
|
|
16
|
+
options: InlineChoice[];
|
|
17
|
+
value?: string;
|
|
18
|
+
placeholder?: string;
|
|
19
|
+
onValueChange: (value: string) => void;
|
|
20
|
+
onBlur?: (...args: any[]) => void;
|
|
21
|
+
disabled?: boolean;
|
|
22
|
+
id?: string;
|
|
23
|
+
knobProps: any;
|
|
24
|
+
markColor: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* A long choice list inside a sheet (LC-262, FZ-7830 round 3): a Settings row
|
|
29
|
+
* with the label, the current value and a chevron. Pressing it pushes the
|
|
30
|
+
* checkmark list onto the sheet's own navigation stack; Back returns with the
|
|
31
|
+
* value set. Nothing floats over the field.
|
|
32
|
+
*/
|
|
33
|
+
export function SheetPickerRow({
|
|
34
|
+
store,
|
|
35
|
+
label,
|
|
36
|
+
options,
|
|
37
|
+
value,
|
|
38
|
+
placeholder,
|
|
39
|
+
onValueChange,
|
|
40
|
+
onBlur,
|
|
41
|
+
disabled,
|
|
42
|
+
id,
|
|
43
|
+
knobProps,
|
|
44
|
+
markColor,
|
|
45
|
+
}: SheetPickerRowProps) {
|
|
46
|
+
const pageId = `sheet-picker-${useId()}`;
|
|
47
|
+
const pushed = useSheetPageOpen(store, pageId);
|
|
48
|
+
const describedBy = useFieldDescribedBy();
|
|
49
|
+
const current = options.find((option) => option.value === value);
|
|
50
|
+
const textColor = knobProps.textAccentColor;
|
|
51
|
+
const chevronInk = useGlyphColor("$textMuted");
|
|
52
|
+
|
|
53
|
+
const page = {
|
|
54
|
+
id: pageId,
|
|
55
|
+
title: label,
|
|
56
|
+
content: (
|
|
57
|
+
<InlineChoices
|
|
58
|
+
options={options}
|
|
59
|
+
value={value}
|
|
60
|
+
onValueChange={onValueChange}
|
|
61
|
+
disabled={disabled}
|
|
62
|
+
aria-label={label}
|
|
63
|
+
knobProps={knobProps}
|
|
64
|
+
markColor={markColor}
|
|
65
|
+
/>
|
|
66
|
+
),
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
useIsoLayoutEffect(() => {
|
|
70
|
+
if (pushed) store.update(page);
|
|
71
|
+
});
|
|
72
|
+
useEffect(() => () => store.remove(pageId), [store, pageId]);
|
|
73
|
+
|
|
74
|
+
const open = () => {
|
|
75
|
+
if (disabled) return;
|
|
76
|
+
store.push(page);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const row = (
|
|
80
|
+
<XStack
|
|
81
|
+
alignItems="center"
|
|
82
|
+
minHeight={knobProps.menuRow.minHeight}
|
|
83
|
+
paddingHorizontal={knobProps.panelPadding.padding}
|
|
84
|
+
{...knobProps.gap}
|
|
85
|
+
pointerEvents="none"
|
|
86
|
+
>
|
|
87
|
+
<Text
|
|
88
|
+
fontFamily={knobProps.body.fontFamily}
|
|
89
|
+
fontWeight={knobProps.body.fontWeight}
|
|
90
|
+
color={textColor}
|
|
91
|
+
numberOfLines={1}
|
|
92
|
+
flex={1}
|
|
93
|
+
>
|
|
94
|
+
{label}
|
|
95
|
+
</Text>
|
|
96
|
+
<Text
|
|
97
|
+
testID="sheet-picker-value"
|
|
98
|
+
fontFamily={knobProps.body.fontFamily}
|
|
99
|
+
color="$textMuted"
|
|
100
|
+
numberOfLines={1}
|
|
101
|
+
flexShrink={1}
|
|
102
|
+
>
|
|
103
|
+
{current?.label ?? placeholder}
|
|
104
|
+
</Text>
|
|
105
|
+
<CaretRightIcon size={14} weight="bold" color={chevronInk} />
|
|
106
|
+
</XStack>
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
const surface = {
|
|
110
|
+
...knobProps.borderRadius,
|
|
111
|
+
borderColor: formInputColors.border.base,
|
|
112
|
+
backgroundColor: formInputColors.background.base,
|
|
113
|
+
overflow: "hidden" as const,
|
|
114
|
+
width: "100%" as const,
|
|
115
|
+
opacity: disabled ? 0.5 : 1,
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
if (isWeb) {
|
|
119
|
+
return (
|
|
120
|
+
<View
|
|
121
|
+
id={id}
|
|
122
|
+
role="button"
|
|
123
|
+
aria-label={label}
|
|
124
|
+
aria-describedby={describedBy}
|
|
125
|
+
aria-disabled={disabled || undefined}
|
|
126
|
+
data-testid="sheet-picker-row"
|
|
127
|
+
tabIndex={disabled ? -1 : 0}
|
|
128
|
+
cursor={disabled ? "default" : "pointer"}
|
|
129
|
+
onPress={open}
|
|
130
|
+
onKeyDown={(event: any) => {
|
|
131
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
132
|
+
event.preventDefault();
|
|
133
|
+
open();
|
|
134
|
+
}
|
|
135
|
+
}}
|
|
136
|
+
onBlur={onBlur}
|
|
137
|
+
outlineWidth={0}
|
|
138
|
+
focusVisibleStyle={keyboardFocusRingProps}
|
|
139
|
+
{...surface}
|
|
140
|
+
>
|
|
141
|
+
{row}
|
|
142
|
+
</View>
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
return (
|
|
146
|
+
<View {...surface}>
|
|
147
|
+
<Pressable
|
|
148
|
+
testID="sheet-picker-row"
|
|
149
|
+
accessibilityRole="button"
|
|
150
|
+
accessibilityLabel={label}
|
|
151
|
+
accessibilityValue={{ text: current?.label ?? placeholder ?? "" }}
|
|
152
|
+
accessibilityState={{ disabled: !!disabled }}
|
|
153
|
+
disabled={disabled}
|
|
154
|
+
onPress={open}
|
|
155
|
+
>
|
|
156
|
+
{row}
|
|
157
|
+
</Pressable>
|
|
158
|
+
</View>
|
|
159
|
+
);
|
|
160
|
+
}
|
|
@@ -24,6 +24,7 @@ import type { AnyFormApi } from "../../types";
|
|
|
24
24
|
import {
|
|
25
25
|
ensureKeyboardModalityTracking,
|
|
26
26
|
keyboardFocusRingProps,
|
|
27
|
+
menuRowChecked,
|
|
27
28
|
menuRowFrame,
|
|
28
29
|
sizeRecipeForToken,
|
|
29
30
|
useGlyphColor,
|
|
@@ -65,6 +66,7 @@ import {
|
|
|
65
66
|
} from "../../FloatingPanel";
|
|
66
67
|
import { pickerCompactFace, resolveCompactFace } from "../../FloatingPanel/compactFace";
|
|
67
68
|
import { PanelPortal } from "../../FloatingPanel/PanelPortal";
|
|
69
|
+
import { fixedContainingBlockOrigin } from "../../FloatingPanel/containingBlock";
|
|
68
70
|
import { useInsideOverlay, useOverlayZIndex } from "../../shared/overlayStack";
|
|
69
71
|
import { useDragScroll } from "../../shared/useDragScroll";
|
|
70
72
|
import { useIsInTableCell } from "../../shared/tableCellContext";
|
|
@@ -72,7 +74,9 @@ import { t } from "../../shared/t";
|
|
|
72
74
|
import { orderOptionsBySelected, type SelectedOrder } from "../selectedOrder";
|
|
73
75
|
import { shouldUseIosNativeSelect } from "../nativeSelect";
|
|
74
76
|
import { InlineChoices } from "./InlineChoices";
|
|
75
|
-
import {
|
|
77
|
+
import { SheetPickerRow } from "./SheetPickerRow";
|
|
78
|
+
import { opensBesideTrigger, shouldInlineChoices, shouldPushChoices } from "./shouldInlineChoices";
|
|
79
|
+
import { useSheetNavigation } from "../../shared/sheetNavigation";
|
|
76
80
|
|
|
77
81
|
/** Undefined on web (RNW ships no ActionSheetIOS); real on iOS. */
|
|
78
82
|
const actionSheetIOS = (ReactNative as { ActionSheetIOS?: typeof ReactNative.ActionSheetIOS })
|
|
@@ -170,7 +174,7 @@ const SelectRow = styled(View, {
|
|
|
170
174
|
variants: {
|
|
171
175
|
// LC-262: the accent check alone marks the chosen row, never a grey fill.
|
|
172
176
|
selected: {
|
|
173
|
-
true: {
|
|
177
|
+
true: { ...menuRowChecked, borderRadius: 0 },
|
|
174
178
|
false: { backgroundColor: "transparent" },
|
|
175
179
|
},
|
|
176
180
|
active: {
|
|
@@ -539,6 +543,7 @@ function FloatingSelectCore({
|
|
|
539
543
|
const { style: elevatedSurfaceStyle, ...elevatedSurfaceProps } = knobProps.elevatedSurface;
|
|
540
544
|
const hydrationTouch = useTouchSurface();
|
|
541
545
|
const inTableCell = useIsInTableCell();
|
|
546
|
+
const beside = useInsideOverlay() && !inTableCell && opensBesideTrigger(options.length);
|
|
542
547
|
const describedBy = useFieldDescribedBy();
|
|
543
548
|
const glyphColor = useGlyphColor();
|
|
544
549
|
const [open, setOpen] = useState(false);
|
|
@@ -671,8 +676,31 @@ function FloatingSelectCore({
|
|
|
671
676
|
const selectedItemIndex = selectedIndex >= 0 ? selectedIndex : 0;
|
|
672
677
|
const selectedItem = listItemsRef.current[selectedItemIndex];
|
|
673
678
|
const trigger = panel.triggerRef.current;
|
|
674
|
-
if (!dropdownElement || !
|
|
679
|
+
if (!dropdownElement || !trigger) return;
|
|
680
|
+
|
|
681
|
+
if (beside) {
|
|
682
|
+
const isInitial = panel.initializingRef.current;
|
|
683
|
+
if (isInitial) dropdownElement.style.transition = "none";
|
|
684
|
+
const bounds = trigger.getBoundingClientRect();
|
|
685
|
+
const contentHeight = dropdownElement.scrollHeight;
|
|
686
|
+
const below = window.innerHeight - panelViewportPadding - bounds.bottom;
|
|
687
|
+
const above = bounds.top - panelViewportPadding;
|
|
688
|
+
const opensUp = contentHeight > below && above > below;
|
|
689
|
+
const maxHeight = Math.min(contentHeight || Infinity, opensUp ? above : below);
|
|
690
|
+
const top =
|
|
691
|
+
(opensUp ? bounds.top - maxHeight : bounds.bottom) -
|
|
692
|
+
fixedContainingBlockOrigin(dropdownElement).top;
|
|
693
|
+
dropdownElement.style.top = `${top}px`;
|
|
694
|
+
dropdownElement.style.maxHeight = `${maxHeight}px`;
|
|
695
|
+
dropdownElement.style.height = "";
|
|
696
|
+
overlayStyle.current = { top, maxHeight };
|
|
697
|
+
panel.initializingRef.current = false;
|
|
698
|
+
void dropdownElement.offsetHeight;
|
|
699
|
+
if (isInitial) dropdownElement.style.transition = panel.panelTransition;
|
|
700
|
+
return;
|
|
701
|
+
}
|
|
675
702
|
|
|
703
|
+
if (!selectedItem) return;
|
|
676
704
|
const isInitial = panel.initializingRef.current;
|
|
677
705
|
if (isInitial) dropdownElement.style.transition = "none";
|
|
678
706
|
|
|
@@ -812,6 +840,7 @@ function FloatingSelectCore({
|
|
|
812
840
|
panel.placement,
|
|
813
841
|
panel.panelTransition,
|
|
814
842
|
options.length,
|
|
843
|
+
beside,
|
|
815
844
|
]);
|
|
816
845
|
|
|
817
846
|
repositionRef.current = repositionOverlay;
|
|
@@ -1573,6 +1602,9 @@ function NativeSelectCore({
|
|
|
1573
1602
|
// A short list opens as a menu over its trigger; a long one keeps its
|
|
1574
1603
|
// sheet at page level and opens as a menu inside another overlay (FZ-7830).
|
|
1575
1604
|
compactFace={compactFace}
|
|
1605
|
+
{...(asMenu && insideOverlay && opensBesideTrigger(options.length)
|
|
1606
|
+
? { anchorMode: "attach" as const, triggerEcho: false }
|
|
1607
|
+
: null)}
|
|
1576
1608
|
triggerA11y={{
|
|
1577
1609
|
label: ariaLabel ?? fieldA11y?.label,
|
|
1578
1610
|
value: triggerValueText,
|
|
@@ -1761,6 +1793,13 @@ export function Select({
|
|
|
1761
1793
|
const shouldUseSheet = !isWeb || (!effectiveGtSm && !compactMenu);
|
|
1762
1794
|
const inTableCell = useIsInTableCell();
|
|
1763
1795
|
const inline = !inTableCell && shouldInlineChoices({ insideOverlay, multiple, options });
|
|
1796
|
+
const sheetNavigation = useSheetNavigation();
|
|
1797
|
+
const rowLabel = typeof label === "string" ? label : ariaLabel;
|
|
1798
|
+
const pushed =
|
|
1799
|
+
!inline &&
|
|
1800
|
+
!inTableCell &&
|
|
1801
|
+
Boolean(rowLabel) &&
|
|
1802
|
+
shouldPushChoices({ inSheet: Boolean(sheetNavigation), multiple, options });
|
|
1764
1803
|
// DG-CTRL-01 / DG-CTRL-05 — short single-select lists prefer RadioGroup,
|
|
1765
1804
|
// which the inline face already is.
|
|
1766
1805
|
if (!inline) {
|
|
@@ -1836,6 +1875,27 @@ export function Select({
|
|
|
1836
1875
|
handleBlur?: (...args: any[]) => void,
|
|
1837
1876
|
) => {
|
|
1838
1877
|
if (readOnly) return renderReadOnly(selectValue);
|
|
1878
|
+
if (pushed && sheetNavigation) {
|
|
1879
|
+
return (
|
|
1880
|
+
<SheetPickerRow
|
|
1881
|
+
store={sheetNavigation}
|
|
1882
|
+
label={rowLabel as string}
|
|
1883
|
+
options={options}
|
|
1884
|
+
value={typeof selectValue === "string" ? selectValue : undefined}
|
|
1885
|
+
placeholder={placeholder}
|
|
1886
|
+
onValueChange={(val) => {
|
|
1887
|
+
if (disabled) return;
|
|
1888
|
+
handleValueChange?.(val);
|
|
1889
|
+
emitValueChange(val);
|
|
1890
|
+
}}
|
|
1891
|
+
onBlur={handleBlur}
|
|
1892
|
+
disabled={disabled}
|
|
1893
|
+
id={id}
|
|
1894
|
+
knobProps={knobProps}
|
|
1895
|
+
markColor={markColor}
|
|
1896
|
+
/>
|
|
1897
|
+
);
|
|
1898
|
+
}
|
|
1839
1899
|
if (inline) {
|
|
1840
1900
|
return (
|
|
1841
1901
|
<InlineChoices
|
|
@@ -1886,7 +1946,8 @@ export function Select({
|
|
|
1886
1946
|
return (
|
|
1887
1947
|
<FieldLayout
|
|
1888
1948
|
id={id}
|
|
1889
|
-
label={label}
|
|
1949
|
+
label={pushed ? undefined : label}
|
|
1950
|
+
aria-label={pushed ? rowLabel : undefined}
|
|
1890
1951
|
labelProps={labelProps}
|
|
1891
1952
|
error={error}
|
|
1892
1953
|
helperText={helperText}
|
|
@@ -1921,7 +1982,8 @@ export function Select({
|
|
|
1921
1982
|
return (
|
|
1922
1983
|
<FieldLayout
|
|
1923
1984
|
id={id}
|
|
1924
|
-
label={label}
|
|
1985
|
+
label={pushed ? undefined : label}
|
|
1986
|
+
aria-label={pushed ? rowLabel : undefined}
|
|
1925
1987
|
labelProps={labelProps}
|
|
1926
1988
|
error={resolvedError}
|
|
1927
1989
|
helperText={helperText}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
INLINE_CHOICES_MAX,
|
|
4
|
+
opensBesideTrigger,
|
|
5
|
+
shouldInlineChoices,
|
|
6
|
+
shouldPushChoices,
|
|
7
|
+
} from "./shouldInlineChoices";
|
|
3
8
|
|
|
4
9
|
const glyph = "•";
|
|
5
10
|
const withIcons = (n: number) => Array.from({ length: n }, () => ({ icon: glyph }));
|
|
@@ -23,3 +28,18 @@ describe("shouldInlineChoices (LC-262, FZ-7830)", () => {
|
|
|
23
28
|
expect(shouldInlineChoices({ insideOverlay: true, options: [] })).toBe(false);
|
|
24
29
|
});
|
|
25
30
|
});
|
|
31
|
+
|
|
32
|
+
describe("shouldPushChoices and opensBesideTrigger (LC-262, FZ-7830 round 3)", () => {
|
|
33
|
+
it("pushes a single-choice list past five options inside a sheet", () => {
|
|
34
|
+
expect(shouldPushChoices({ inSheet: true, options: withIcons(6) })).toBe(true);
|
|
35
|
+
expect(shouldPushChoices({ inSheet: true, options: withIcons(5) })).toBe(false);
|
|
36
|
+
expect(shouldPushChoices({ inSheet: false, options: withIcons(8) })).toBe(false);
|
|
37
|
+
expect(shouldPushChoices({ inSheet: true, multiple: true, options: withIcons(8) })).toBe(false);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("opens a list of five or fewer beside its field", () => {
|
|
41
|
+
expect(opensBesideTrigger(5)).toBe(true);
|
|
42
|
+
expect(opensBesideTrigger(6)).toBe(false);
|
|
43
|
+
expect(opensBesideTrigger(0)).toBe(false);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
@@ -20,3 +20,29 @@ export function shouldInlineChoices({
|
|
|
20
20
|
if (!insideOverlay || multiple || !options?.length) return false;
|
|
21
21
|
return options.length <= INLINE_CHOICES_MAX && options.every((option) => option.icon != null);
|
|
22
22
|
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* A single-choice Select inside a sheet with more options than the inline
|
|
26
|
+
* list holds pushes its checkmark list onto the sheet's navigation stack from
|
|
27
|
+
* a Settings row (LC-262, FZ-7830 round 3), instead of a menu over the field.
|
|
28
|
+
*/
|
|
29
|
+
export function shouldPushChoices({
|
|
30
|
+
inSheet,
|
|
31
|
+
multiple,
|
|
32
|
+
options,
|
|
33
|
+
}: {
|
|
34
|
+
inSheet: boolean;
|
|
35
|
+
multiple?: boolean;
|
|
36
|
+
options: ReadonlyArray<unknown> | undefined;
|
|
37
|
+
}): boolean {
|
|
38
|
+
if (!inSheet || multiple || !options?.length) return false;
|
|
39
|
+
return options.length > INLINE_CHOICES_MAX;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* A short list inside a sheet that is not laid out inline opens as a menu
|
|
44
|
+
* beside its field, under it or above it, never over it (LC-262).
|
|
45
|
+
*/
|
|
46
|
+
export function opensBesideTrigger(optionCount: number): boolean {
|
|
47
|
+
return optionCount > 0 && optionCount <= INLINE_CHOICES_MAX;
|
|
48
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { renderWithProviders } from "@multiplatform.one/test-utils";
|
|
2
|
+
import { createDefaultThemeConfig } from "@multiplatform.one/theme";
|
|
3
|
+
import { useForm } from "@tanstack/react-form";
|
|
4
|
+
import { cleanup, fireEvent, render } from "@testing-library/react";
|
|
5
|
+
import type { ReactElement } from "react";
|
|
6
|
+
import { TamaguiProvider } from "tamagui";
|
|
7
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
8
|
+
import { Form } from "../../Form";
|
|
9
|
+
import { Slider } from "./index";
|
|
10
|
+
|
|
11
|
+
const system = vi.hoisted(() => ({
|
|
12
|
+
os: "ios" as "ios" | "android" | null,
|
|
13
|
+
installed: true,
|
|
14
|
+
}));
|
|
15
|
+
|
|
16
|
+
// The system slider as a probe: it shows the props it got and moves through
|
|
17
|
+
// onValueChange, then onSlidingComplete, the way a drag on UISlider does.
|
|
18
|
+
const SystemSliderProbe = vi.hoisted(
|
|
19
|
+
() =>
|
|
20
|
+
function SystemSliderProbe(props: Record<string, any>) {
|
|
21
|
+
return (
|
|
22
|
+
<input
|
|
23
|
+
data-testid="system-slider"
|
|
24
|
+
data-fill={props.minimumTrackTintColor}
|
|
25
|
+
data-rail={props.maximumTrackTintColor}
|
|
26
|
+
data-thumb={props.thumbTintColor ?? ""}
|
|
27
|
+
data-label={props.accessibilityLabel ?? ""}
|
|
28
|
+
data-min={props.minimumValue}
|
|
29
|
+
data-max={props.maximumValue}
|
|
30
|
+
data-step={props.step}
|
|
31
|
+
disabled={props.disabled}
|
|
32
|
+
value={props.value}
|
|
33
|
+
onChange={(event) => {
|
|
34
|
+
props.onValueChange?.(Number(event.target.value));
|
|
35
|
+
props.onSlidingComplete?.(Number(event.target.value));
|
|
36
|
+
}}
|
|
37
|
+
/>
|
|
38
|
+
);
|
|
39
|
+
},
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
vi.mock("../../shared/systemControls", async (importOriginal) => ({
|
|
43
|
+
...(await importOriginal<typeof import("../../shared/systemControls")>()),
|
|
44
|
+
systemControlPlatform: () => system.os,
|
|
45
|
+
}));
|
|
46
|
+
|
|
47
|
+
vi.mock("../../shared/systemControlModules", () => ({
|
|
48
|
+
loadSystemSlider: () => (system.installed ? SystemSliderProbe : null),
|
|
49
|
+
loadSystemSegmentedControl: () => null,
|
|
50
|
+
}));
|
|
51
|
+
|
|
52
|
+
const mpoTheme = createDefaultThemeConfig();
|
|
53
|
+
const renderInScheme = (ui: ReactElement, scheme: "light" | "dark") =>
|
|
54
|
+
render(
|
|
55
|
+
<TamaguiProvider config={mpoTheme.tamagui} defaultTheme={scheme} disableInjectCSS>
|
|
56
|
+
{ui}
|
|
57
|
+
</TamaguiProvider>,
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
afterEach(cleanup);
|
|
61
|
+
beforeEach(() => {
|
|
62
|
+
system.os = "ios";
|
|
63
|
+
system.installed = true;
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const literal = (value: string | null) => Boolean(value) && !value!.startsWith("$");
|
|
67
|
+
const mpoSlider = (container: HTMLElement) => container.querySelector('[role="slider"]');
|
|
68
|
+
|
|
69
|
+
function FormSlider({ onSubmit }: { onSubmit: (value: { volume: number }) => void }) {
|
|
70
|
+
const form = useForm({ defaultValues: { volume: 20 }, onSubmit: ({ value }) => onSubmit(value) });
|
|
71
|
+
return (
|
|
72
|
+
<Form form={form}>
|
|
73
|
+
<Slider name="volume" label="Volume" />
|
|
74
|
+
<button type="button" onClick={() => form.handleSubmit()}>
|
|
75
|
+
Save
|
|
76
|
+
</button>
|
|
77
|
+
</Form>
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// LC-266 PLATFORM-ERGONOMICS (FZ-8118). With @react-native-community/slider in
|
|
82
|
+
// the binary, iOS and Android render the system slider tinted from the theme.
|
|
83
|
+
// Without it (One's binary today, an OTA on an older build) the MPO slider.
|
|
84
|
+
describe("Slider on iOS and Android", () => {
|
|
85
|
+
it.each(["light", "dark"] as const)(
|
|
86
|
+
"renders the system slider with the %s theme's fill and rail as literals",
|
|
87
|
+
(scheme) => {
|
|
88
|
+
const result = renderInScheme(
|
|
89
|
+
<Slider label="Volume" defaultValue={[30]} min={10} max={90} step={5} />,
|
|
90
|
+
scheme,
|
|
91
|
+
);
|
|
92
|
+
const view = result.getByTestId("system-slider") as HTMLInputElement;
|
|
93
|
+
expect(view.value).toBe("30");
|
|
94
|
+
expect(view.dataset).toMatchObject({ min: "10", max: "90", step: "5", label: "Volume" });
|
|
95
|
+
expect(literal(view.getAttribute("data-fill"))).toBe(true);
|
|
96
|
+
expect(literal(view.getAttribute("data-rail"))).toBe(true);
|
|
97
|
+
expect(view.getAttribute("data-fill")).not.toBe(view.getAttribute("data-rail"));
|
|
98
|
+
expect(view.dataset.thumb).toBe("");
|
|
99
|
+
expect(mpoSlider(result.container)).toBeNull();
|
|
100
|
+
expect(result.getByText("30")).toBeTruthy();
|
|
101
|
+
},
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
it("tints the Android thumb with the fill", () => {
|
|
105
|
+
system.os = "android";
|
|
106
|
+
const result = renderInScheme(<Slider label="Volume" />, "light");
|
|
107
|
+
const view = result.getByTestId("system-slider");
|
|
108
|
+
expect(literal(view.getAttribute("data-thumb"))).toBe(true);
|
|
109
|
+
expect(view.dataset.thumb).toBe(view.dataset.fill);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it("reports a move as a one-value array and updates the readout", () => {
|
|
113
|
+
const onChange = vi.fn();
|
|
114
|
+
const result = renderWithProviders(<Slider label="Volume" onChange={onChange} />);
|
|
115
|
+
fireEvent.change(result.getByTestId("system-slider"), { target: { value: "40" } });
|
|
116
|
+
expect(onChange).toHaveBeenCalledWith([40]);
|
|
117
|
+
expect(result.getByText("40")).toBeTruthy();
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it("writes the form field it is bound to", async () => {
|
|
121
|
+
const onSubmit = vi.fn();
|
|
122
|
+
const result = renderWithProviders(<FormSlider onSubmit={onSubmit} />);
|
|
123
|
+
expect((result.getByTestId("system-slider") as HTMLInputElement).value).toBe("20");
|
|
124
|
+
fireEvent.change(result.getByTestId("system-slider"), { target: { value: "55" } });
|
|
125
|
+
fireEvent.click(result.getByText("Save"));
|
|
126
|
+
await vi.waitFor(() => expect(onSubmit).toHaveBeenCalledWith({ volume: 55 }));
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it("passes disabled through and never reports a disabled or read-only move", () => {
|
|
130
|
+
const onChange = vi.fn();
|
|
131
|
+
const result = renderWithProviders(
|
|
132
|
+
<>
|
|
133
|
+
<Slider label="Off limits" onChange={onChange} disabled />
|
|
134
|
+
<Slider label="Look only" onChange={onChange} readOnly />
|
|
135
|
+
</>,
|
|
136
|
+
);
|
|
137
|
+
const [disabledView, readOnlyView] = result.getAllByTestId("system-slider");
|
|
138
|
+
expect((disabledView as HTMLInputElement).disabled).toBe(true);
|
|
139
|
+
fireEvent.change(disabledView!, { target: { value: "40" } });
|
|
140
|
+
fireEvent.change(readOnlyView!, { target: { value: "40" } });
|
|
141
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it("falls back to the MPO slider when the binary lacks the module", () => {
|
|
145
|
+
system.installed = false;
|
|
146
|
+
const result = renderWithProviders(<Slider label="Volume" defaultValue={[30]} />);
|
|
147
|
+
expect(result.queryByTestId("system-slider")).toBeNull();
|
|
148
|
+
expect(mpoSlider(result.container)).not.toBeNull();
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it("keeps the MPO slider for a range, a vertical slider and native={false}", () => {
|
|
152
|
+
const result = renderWithProviders(
|
|
153
|
+
<>
|
|
154
|
+
<Slider label="Range" defaultValue={[10, 60]} />
|
|
155
|
+
<Slider label="Tall" sliderProps={{ orientation: "vertical" }} />
|
|
156
|
+
<Slider label="Opted out" native={false} />
|
|
157
|
+
</>,
|
|
158
|
+
);
|
|
159
|
+
expect(result.queryByTestId("system-slider")).toBeNull();
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it("keeps the MPO slider on web and GNOME", () => {
|
|
163
|
+
system.os = null;
|
|
164
|
+
const result = renderWithProviders(<Slider label="Volume" />);
|
|
165
|
+
expect(result.queryByTestId("system-slider")).toBeNull();
|
|
166
|
+
expect(mpoSlider(result.container)).not.toBeNull();
|
|
167
|
+
});
|
|
168
|
+
});
|