@multiplatform.one/forms 7.70.0 → 7.72.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/Button/index.cjs +16 -0
- package/dist/cjs/Button/index.native.js +16 -0
- package/dist/cjs/Button/index.native.js.map +1 -1
- package/dist/cjs/FloatingPanel/echoContext.cjs +39 -0
- package/dist/cjs/FloatingPanel/echoContext.native.js +42 -0
- package/dist/cjs/FloatingPanel/echoContext.native.js.map +1 -0
- package/dist/cjs/FloatingPanel/index.cjs +212 -80
- package/dist/cjs/FloatingPanel/index.native.js +92 -17
- package/dist/cjs/FloatingPanel/index.native.js.map +1 -1
- package/dist/cjs/FloatingPanel/panelWidth.cjs +92 -0
- package/dist/cjs/FloatingPanel/panelWidth.native.js +99 -0
- package/dist/cjs/FloatingPanel/panelWidth.native.js.map +1 -0
- package/dist/cjs/FloatingPanel/pointAnchor.cjs +15 -5
- package/dist/cjs/FloatingPanel/pointAnchor.native.js +15 -5
- package/dist/cjs/FloatingPanel/pointAnchor.native.js.map +1 -1
- package/dist/cjs/FloatingPanel/useFloatingPanel.cjs +58 -4
- package/dist/cjs/FloatingPanel/useFloatingPanel.native.js +69 -4
- package/dist/cjs/FloatingPanel/useFloatingPanel.native.js.map +1 -1
- package/dist/cjs/InputParts/index.cjs +20 -1
- package/dist/cjs/InputParts/index.native.js +22 -2
- package/dist/cjs/InputParts/index.native.js.map +1 -1
- package/dist/cjs/Wheel/NativeWheel.native.js +1 -1
- package/dist/cjs/Wheel/NativeWheel.native.js.map +1 -1
- package/dist/cjs/Wheel/index.cjs +2 -1
- package/dist/cjs/Wheel/index.native.js +4 -1
- package/dist/cjs/Wheel/index.native.js.map +1 -1
- package/dist/cjs/Wheel/wheelShared.cjs +6 -1
- package/dist/cjs/Wheel/wheelShared.native.js +7 -1
- package/dist/cjs/Wheel/wheelShared.native.js.map +1 -1
- package/dist/cjs/fields/Combobox/index.cjs +1 -0
- package/dist/cjs/fields/Combobox/index.native.js +1 -0
- package/dist/cjs/fields/Combobox/index.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/DatetimePicker.catalog.cjs +6 -30
- package/dist/cjs/fields/DatePicker/DatetimePicker.catalog.native.js +11 -34
- package/dist/cjs/fields/DatePicker/DatetimePicker.catalog.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/DatetimePicker.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/catalog.cjs +2 -28
- package/dist/cjs/fields/DatePicker/catalog.native.js +2 -30
- package/dist/cjs/fields/DatePicker/catalog.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/index.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/parts.cjs +11 -20
- package/dist/cjs/fields/DatePicker/parts.native.js +13 -22
- package/dist/cjs/fields/DatePicker/parts.native.js.map +1 -1
- package/dist/cjs/fields/SearchInput/index.cjs +23 -1
- package/dist/cjs/fields/SearchInput/index.native.js +23 -1
- package/dist/cjs/fields/SearchInput/index.native.js.map +1 -1
- package/dist/cjs/fields/Select/index.cjs +65 -44
- package/dist/cjs/fields/Select/index.native.js +69 -47
- package/dist/cjs/fields/Select/index.native.js.map +1 -1
- package/dist/cjs/fields/Select/shouldInlineChoices.cjs +3 -1
- package/dist/cjs/fields/Select/shouldInlineChoices.native.js +3 -1
- package/dist/cjs/fields/Select/shouldInlineChoices.native.js.map +1 -1
- package/dist/cjs/fields/TimePicker/catalog.cjs +4 -25
- package/dist/cjs/fields/TimePicker/catalog.native.js +7 -29
- package/dist/cjs/fields/TimePicker/catalog.native.js.map +1 -1
- package/dist/cjs/fields/TimePicker/index.native.js.map +1 -1
- package/dist/cjs/fields/TimePicker/parts.cjs +8 -21
- package/dist/cjs/fields/TimePicker/parts.native.js +8 -21
- package/dist/cjs/fields/TimePicker/parts.native.js.map +1 -1
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/cjs/shared/floatingList.cjs +13 -4
- package/dist/cjs/shared/floatingList.native.js +15 -4
- package/dist/cjs/shared/floatingList.native.js.map +1 -1
- package/dist/esm/Button/index.mjs +17 -1
- package/dist/esm/Button/index.mjs.map +1 -1
- package/dist/esm/Button/index.native.js +17 -1
- package/dist/esm/Button/index.native.js.map +1 -1
- package/dist/esm/FloatingPanel/echoContext.mjs +11 -0
- package/dist/esm/FloatingPanel/echoContext.mjs.map +1 -0
- package/dist/esm/FloatingPanel/echoContext.native.js +11 -0
- package/dist/esm/FloatingPanel/echoContext.native.js.map +1 -0
- package/dist/esm/FloatingPanel/index.mjs +213 -83
- package/dist/esm/FloatingPanel/index.mjs.map +1 -1
- package/dist/esm/FloatingPanel/index.native.js +92 -19
- package/dist/esm/FloatingPanel/index.native.js.map +1 -1
- package/dist/esm/FloatingPanel/panelWidth.mjs +63 -0
- package/dist/esm/FloatingPanel/panelWidth.mjs.map +1 -0
- package/dist/esm/FloatingPanel/panelWidth.native.js +67 -0
- package/dist/esm/FloatingPanel/panelWidth.native.js.map +1 -0
- package/dist/esm/FloatingPanel/pointAnchor.mjs +15 -5
- package/dist/esm/FloatingPanel/pointAnchor.mjs.map +1 -1
- package/dist/esm/FloatingPanel/pointAnchor.native.js +15 -5
- package/dist/esm/FloatingPanel/pointAnchor.native.js.map +1 -1
- package/dist/esm/FloatingPanel/useFloatingPanel.mjs +58 -5
- package/dist/esm/FloatingPanel/useFloatingPanel.mjs.map +1 -1
- package/dist/esm/FloatingPanel/useFloatingPanel.native.js +69 -5
- package/dist/esm/FloatingPanel/useFloatingPanel.native.js.map +1 -1
- package/dist/esm/InputParts/index.mjs +21 -2
- package/dist/esm/InputParts/index.mjs.map +1 -1
- package/dist/esm/InputParts/index.native.js +23 -3
- package/dist/esm/InputParts/index.native.js.map +1 -1
- package/dist/esm/Wheel/NativeWheel.native.js +1 -1
- package/dist/esm/Wheel/NativeWheel.native.js.map +1 -1
- package/dist/esm/Wheel/index.mjs +2 -1
- package/dist/esm/Wheel/index.mjs.map +1 -1
- package/dist/esm/Wheel/index.native.js +4 -1
- package/dist/esm/Wheel/index.native.js.map +1 -1
- package/dist/esm/Wheel/wheelShared.mjs +6 -1
- package/dist/esm/Wheel/wheelShared.mjs.map +1 -1
- package/dist/esm/Wheel/wheelShared.native.js +7 -1
- package/dist/esm/Wheel/wheelShared.native.js.map +1 -1
- package/dist/esm/fields/Combobox/index.mjs +1 -0
- package/dist/esm/fields/Combobox/index.mjs.map +1 -1
- package/dist/esm/fields/Combobox/index.native.js +1 -0
- package/dist/esm/fields/Combobox/index.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/DatetimePicker.catalog.mjs +6 -30
- package/dist/esm/fields/DatePicker/DatetimePicker.catalog.mjs.map +1 -1
- package/dist/esm/fields/DatePicker/DatetimePicker.catalog.native.js +11 -34
- package/dist/esm/fields/DatePicker/DatetimePicker.catalog.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/DatetimePicker.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/catalog.mjs +2 -28
- package/dist/esm/fields/DatePicker/catalog.mjs.map +1 -1
- package/dist/esm/fields/DatePicker/catalog.native.js +2 -30
- package/dist/esm/fields/DatePicker/catalog.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/index.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/parts.mjs +11 -20
- package/dist/esm/fields/DatePicker/parts.mjs.map +1 -1
- package/dist/esm/fields/DatePicker/parts.native.js +13 -22
- package/dist/esm/fields/DatePicker/parts.native.js.map +1 -1
- package/dist/esm/fields/SearchInput/index.mjs +25 -3
- package/dist/esm/fields/SearchInput/index.mjs.map +1 -1
- package/dist/esm/fields/SearchInput/index.native.js +25 -3
- package/dist/esm/fields/SearchInput/index.native.js.map +1 -1
- package/dist/esm/fields/Select/index.mjs +66 -45
- package/dist/esm/fields/Select/index.mjs.map +1 -1
- package/dist/esm/fields/Select/index.native.js +70 -48
- package/dist/esm/fields/Select/index.native.js.map +1 -1
- package/dist/esm/fields/Select/shouldInlineChoices.mjs +3 -1
- package/dist/esm/fields/Select/shouldInlineChoices.mjs.map +1 -1
- package/dist/esm/fields/Select/shouldInlineChoices.native.js +3 -1
- package/dist/esm/fields/Select/shouldInlineChoices.native.js.map +1 -1
- package/dist/esm/fields/TimePicker/catalog.mjs +4 -25
- package/dist/esm/fields/TimePicker/catalog.mjs.map +1 -1
- package/dist/esm/fields/TimePicker/catalog.native.js +7 -29
- package/dist/esm/fields/TimePicker/catalog.native.js.map +1 -1
- package/dist/esm/fields/TimePicker/index.native.js.map +1 -1
- package/dist/esm/fields/TimePicker/parts.mjs +8 -21
- package/dist/esm/fields/TimePicker/parts.mjs.map +1 -1
- package/dist/esm/fields/TimePicker/parts.native.js +8 -21
- package/dist/esm/fields/TimePicker/parts.native.js.map +1 -1
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/index.native.js.map +1 -1
- package/dist/esm/shared/floatingList.mjs +14 -5
- package/dist/esm/shared/floatingList.mjs.map +1 -1
- package/dist/esm/shared/floatingList.native.js +16 -5
- package/dist/esm/shared/floatingList.native.js.map +1 -1
- package/dist/jsx/Button/index.mjs +17 -1
- package/dist/jsx/Button/index.mjs.map +1 -1
- package/dist/jsx/Button/index.native.js +16 -0
- package/dist/jsx/Button/index.native.js.map +1 -1
- package/dist/jsx/FloatingPanel/echoContext.mjs +11 -0
- package/dist/jsx/FloatingPanel/echoContext.mjs.map +1 -0
- package/dist/jsx/FloatingPanel/echoContext.native.js +42 -0
- package/dist/jsx/FloatingPanel/echoContext.native.js.map +1 -0
- package/dist/jsx/FloatingPanel/index.mjs +213 -83
- package/dist/jsx/FloatingPanel/index.mjs.map +1 -1
- package/dist/jsx/FloatingPanel/index.native.js +92 -17
- package/dist/jsx/FloatingPanel/index.native.js.map +1 -1
- package/dist/jsx/FloatingPanel/panelWidth.mjs +63 -0
- package/dist/jsx/FloatingPanel/panelWidth.mjs.map +1 -0
- package/dist/jsx/FloatingPanel/panelWidth.native.js +99 -0
- package/dist/jsx/FloatingPanel/panelWidth.native.js.map +1 -0
- package/dist/jsx/FloatingPanel/pointAnchor.mjs +15 -5
- package/dist/jsx/FloatingPanel/pointAnchor.mjs.map +1 -1
- package/dist/jsx/FloatingPanel/pointAnchor.native.js +15 -5
- package/dist/jsx/FloatingPanel/pointAnchor.native.js.map +1 -1
- package/dist/jsx/FloatingPanel/useFloatingPanel.mjs +58 -5
- package/dist/jsx/FloatingPanel/useFloatingPanel.mjs.map +1 -1
- package/dist/jsx/FloatingPanel/useFloatingPanel.native.js +69 -4
- package/dist/jsx/FloatingPanel/useFloatingPanel.native.js.map +1 -1
- package/dist/jsx/InputParts/index.mjs +21 -2
- package/dist/jsx/InputParts/index.mjs.map +1 -1
- package/dist/jsx/InputParts/index.native.js +22 -2
- package/dist/jsx/InputParts/index.native.js.map +1 -1
- package/dist/jsx/Wheel/NativeWheel.native.js +1 -1
- package/dist/jsx/Wheel/NativeWheel.native.js.map +1 -1
- package/dist/jsx/Wheel/index.mjs +2 -1
- package/dist/jsx/Wheel/index.mjs.map +1 -1
- package/dist/jsx/Wheel/index.native.js +4 -1
- package/dist/jsx/Wheel/index.native.js.map +1 -1
- package/dist/jsx/Wheel/wheelShared.mjs +6 -1
- package/dist/jsx/Wheel/wheelShared.mjs.map +1 -1
- package/dist/jsx/Wheel/wheelShared.native.js +7 -1
- package/dist/jsx/Wheel/wheelShared.native.js.map +1 -1
- package/dist/jsx/fields/Combobox/index.mjs +1 -0
- package/dist/jsx/fields/Combobox/index.mjs.map +1 -1
- package/dist/jsx/fields/Combobox/index.native.js +1 -0
- package/dist/jsx/fields/Combobox/index.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/DatetimePicker.catalog.mjs +6 -30
- package/dist/jsx/fields/DatePicker/DatetimePicker.catalog.mjs.map +1 -1
- package/dist/jsx/fields/DatePicker/DatetimePicker.catalog.native.js +11 -34
- package/dist/jsx/fields/DatePicker/DatetimePicker.catalog.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/DatetimePicker.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/catalog.mjs +2 -28
- package/dist/jsx/fields/DatePicker/catalog.mjs.map +1 -1
- package/dist/jsx/fields/DatePicker/catalog.native.js +2 -30
- package/dist/jsx/fields/DatePicker/catalog.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/index.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/parts.mjs +11 -20
- package/dist/jsx/fields/DatePicker/parts.mjs.map +1 -1
- package/dist/jsx/fields/DatePicker/parts.native.js +13 -22
- package/dist/jsx/fields/DatePicker/parts.native.js.map +1 -1
- package/dist/jsx/fields/SearchInput/index.mjs +25 -3
- package/dist/jsx/fields/SearchInput/index.mjs.map +1 -1
- package/dist/jsx/fields/SearchInput/index.native.js +23 -1
- package/dist/jsx/fields/SearchInput/index.native.js.map +1 -1
- package/dist/jsx/fields/Select/index.mjs +66 -45
- package/dist/jsx/fields/Select/index.mjs.map +1 -1
- package/dist/jsx/fields/Select/index.native.js +69 -47
- package/dist/jsx/fields/Select/index.native.js.map +1 -1
- package/dist/jsx/fields/Select/shouldInlineChoices.mjs +3 -1
- package/dist/jsx/fields/Select/shouldInlineChoices.mjs.map +1 -1
- package/dist/jsx/fields/Select/shouldInlineChoices.native.js +3 -1
- package/dist/jsx/fields/Select/shouldInlineChoices.native.js.map +1 -1
- package/dist/jsx/fields/TimePicker/catalog.mjs +4 -25
- package/dist/jsx/fields/TimePicker/catalog.mjs.map +1 -1
- package/dist/jsx/fields/TimePicker/catalog.native.js +7 -29
- package/dist/jsx/fields/TimePicker/catalog.native.js.map +1 -1
- package/dist/jsx/fields/TimePicker/index.native.js.map +1 -1
- package/dist/jsx/fields/TimePicker/parts.mjs +8 -21
- package/dist/jsx/fields/TimePicker/parts.mjs.map +1 -1
- package/dist/jsx/fields/TimePicker/parts.native.js +8 -21
- package/dist/jsx/fields/TimePicker/parts.native.js.map +1 -1
- package/dist/jsx/index.js.map +1 -1
- package/dist/jsx/index.mjs.map +1 -1
- package/dist/jsx/index.native.js.map +1 -1
- package/dist/jsx/shared/floatingList.mjs +14 -5
- package/dist/jsx/shared/floatingList.mjs.map +1 -1
- package/dist/jsx/shared/floatingList.native.js +15 -4
- package/dist/jsx/shared/floatingList.native.js.map +1 -1
- package/package.json +8 -8
- package/src/Button/index.tsx +22 -0
- package/src/FloatingPanel/FloatingPanel.echoStretch.spec.tsx +67 -0
- package/src/FloatingPanel/FloatingPanel.menuFace.native.spec.tsx +193 -2
- package/src/FloatingPanel/FloatingPanel.seamlessCover.spec.tsx +237 -0
- package/src/FloatingPanel/echoContext.ts +22 -0
- package/src/FloatingPanel/index.native.tsx +106 -9
- package/src/FloatingPanel/index.tsx +310 -102
- package/src/FloatingPanel/panelWidth.spec.ts +158 -0
- package/src/FloatingPanel/panelWidth.ts +122 -0
- package/src/FloatingPanel/panelWidthContract.spec.ts +10 -10
- package/src/FloatingPanel/pointAnchor.spec.ts +64 -2
- package/src/FloatingPanel/pointAnchor.ts +28 -3
- package/src/FloatingPanel/useFloatingPanel.spec.tsx +124 -4
- package/src/FloatingPanel/useFloatingPanel.ts +106 -33
- package/src/InputParts/index.tsx +30 -1
- package/src/Wheel/NativeWheel.native.tsx +1 -1
- package/src/Wheel/Wheel.spec.tsx +9 -0
- package/src/Wheel/index.tsx +12 -3
- package/src/Wheel/wheelShared.ts +6 -2
- package/src/fields/Combobox/index.tsx +1 -0
- package/src/fields/DatePicker/DatePicker.stories.tsx +3 -3
- package/src/fields/DatePicker/DatetimePicker.catalog.tsx +17 -45
- package/src/fields/DatePicker/DatetimePicker.native.tsx +3 -0
- package/src/fields/DatePicker/catalog.tsx +8 -39
- package/src/fields/DatePicker/index.native.tsx +3 -0
- package/src/fields/DatePicker/parts.tsx +13 -23
- package/src/fields/DatePicker/seamlessCover.spec.tsx +180 -0
- package/src/fields/DatePicker/touchWeb.spec.tsx +109 -167
- package/src/fields/SearchInput/SearchInput.spec.tsx +40 -0
- package/src/fields/SearchInput/index.tsx +47 -2
- package/src/fields/Select/Select.containingBlock.spec.tsx +191 -0
- package/src/fields/Select/Select.stories.tsx +43 -0
- package/src/fields/Select/index.tsx +109 -45
- package/src/fields/Select/shouldInlineChoices.spec.ts +13 -0
- package/src/fields/Select/shouldInlineChoices.ts +6 -0
- package/src/fields/TimePicker/catalog.tsx +12 -33
- package/src/fields/TimePicker/index.native.tsx +2 -0
- package/src/fields/TimePicker/parts.tsx +6 -20
- package/src/index.ts +1 -0
- package/src/shared/floatingList.tsx +21 -5
- package/types/Button/index.d.ts.map +1 -1
- package/types/FloatingPanel/echoContext.d.ts +14 -0
- package/types/FloatingPanel/echoContext.d.ts.map +1 -0
- package/types/FloatingPanel/index.d.ts +59 -0
- package/types/FloatingPanel/index.d.ts.map +1 -1
- package/types/FloatingPanel/index.native.d.ts +9 -1
- package/types/FloatingPanel/index.native.d.ts.map +1 -1
- package/types/FloatingPanel/panelWidth.d.ts +71 -0
- package/types/FloatingPanel/panelWidth.d.ts.map +1 -0
- package/types/FloatingPanel/pointAnchor.d.ts +8 -1
- package/types/FloatingPanel/pointAnchor.d.ts.map +1 -1
- package/types/FloatingPanel/useFloatingPanel.d.ts +33 -2
- package/types/FloatingPanel/useFloatingPanel.d.ts.map +1 -1
- package/types/InputParts/index.d.ts +5 -1
- package/types/InputParts/index.d.ts.map +1 -1
- package/types/Wheel/index.d.ts.map +1 -1
- package/types/Wheel/wheelShared.d.ts +2 -1
- package/types/Wheel/wheelShared.d.ts.map +1 -1
- package/types/fields/Combobox/index.d.ts.map +1 -1
- package/types/fields/DatePicker/DatetimePicker.catalog.d.ts +6 -0
- package/types/fields/DatePicker/DatetimePicker.catalog.d.ts.map +1 -1
- package/types/fields/DatePicker/DatetimePicker.native.d.ts +3 -0
- package/types/fields/DatePicker/DatetimePicker.native.d.ts.map +1 -1
- package/types/fields/DatePicker/catalog.d.ts +6 -0
- package/types/fields/DatePicker/catalog.d.ts.map +1 -1
- package/types/fields/DatePicker/index.native.d.ts +3 -0
- package/types/fields/DatePicker/index.native.d.ts.map +1 -1
- package/types/fields/DatePicker/parts.d.ts +5 -7
- package/types/fields/DatePicker/parts.d.ts.map +1 -1
- package/types/fields/Input/index.d.ts +3 -1
- package/types/fields/Input/index.d.ts.map +1 -1
- package/types/fields/SearchInput/index.d.ts +11 -0
- package/types/fields/SearchInput/index.d.ts.map +1 -1
- package/types/fields/Select/index.d.ts +8 -1
- package/types/fields/Select/index.d.ts.map +1 -1
- package/types/fields/Select/shouldInlineChoices.d.ts +5 -1
- package/types/fields/Select/shouldInlineChoices.d.ts.map +1 -1
- package/types/fields/TimePicker/catalog.d.ts +7 -1
- package/types/fields/TimePicker/catalog.d.ts.map +1 -1
- package/types/fields/TimePicker/index.native.d.ts +2 -0
- package/types/fields/TimePicker/index.native.d.ts.map +1 -1
- package/types/fields/TimePicker/parts.d.ts +1 -3
- package/types/fields/TimePicker/parts.d.ts.map +1 -1
- package/types/index.d.ts +1 -0
- package/types/index.d.ts.map +1 -1
- package/types/shared/floatingList.d.ts +5 -1
- package/types/shared/floatingList.d.ts.map +1 -1
- package/dist/cjs/shared/touchWebPicker.cjs +0 -136
- package/dist/cjs/shared/touchWebPicker.native.js +0 -154
- package/dist/cjs/shared/touchWebPicker.native.js.map +0 -1
- package/dist/esm/shared/touchWebPicker.mjs +0 -105
- package/dist/esm/shared/touchWebPicker.mjs.map +0 -1
- package/dist/esm/shared/touchWebPicker.native.js +0 -120
- package/dist/esm/shared/touchWebPicker.native.js.map +0 -1
- package/dist/jsx/shared/touchWebPicker.mjs +0 -105
- package/dist/jsx/shared/touchWebPicker.mjs.map +0 -1
- package/dist/jsx/shared/touchWebPicker.native.js +0 -154
- package/dist/jsx/shared/touchWebPicker.native.js.map +0 -1
- package/src/shared/touchWebPicker.spec.ts +0 -98
- package/src/shared/touchWebPicker.tsx +0 -158
- package/types/shared/touchWebPicker.d.ts +0 -40
- package/types/shared/touchWebPicker.d.ts.map +0 -1
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LC-112 width setting (FZ-8438 r3, Clay on the desktop Date shot): "it can
|
|
3
|
+
* collapse to the content, it can be the full width of the initial input
|
|
4
|
+
* button, or it can open up to be the full width of the screen, or it can be
|
|
5
|
+
* a fixed size that it opens to."
|
|
6
|
+
*/
|
|
7
|
+
import { describe, expect, it } from "vitest";
|
|
8
|
+
import { MENU_MIN_WIDTH } from "./compactFace";
|
|
9
|
+
import {
|
|
10
|
+
echoOffset,
|
|
11
|
+
panelLeftForWidth,
|
|
12
|
+
panelWidthBox,
|
|
13
|
+
screenBounds,
|
|
14
|
+
slidesAlongScreen,
|
|
15
|
+
} from "./panelWidth";
|
|
16
|
+
|
|
17
|
+
describe("panelWidthBox", () => {
|
|
18
|
+
it('"content" floors at an echoed trigger and leaves the width to its rows', () => {
|
|
19
|
+
expect(panelWidthBox("content", { trigger: 240, available: 1000, echo: true })).toEqual({
|
|
20
|
+
minWidth: 240,
|
|
21
|
+
maxWidth: 1000,
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('"content" without an echo has no trigger floor', () => {
|
|
26
|
+
expect(panelWidthBox("content", { trigger: 44, available: 1000, echo: false }).minWidth).toBe(
|
|
27
|
+
0,
|
|
28
|
+
);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('"content" keeps a platform floor (the native 250pt pull-down)', () => {
|
|
32
|
+
expect(
|
|
33
|
+
panelWidthBox("content", { trigger: 44, available: 370, echo: false, floor: MENU_MIN_WIDTH })
|
|
34
|
+
.minWidth,
|
|
35
|
+
).toBe(MENU_MIN_WIDTH);
|
|
36
|
+
expect(
|
|
37
|
+
panelWidthBox("content", { trigger: 44, available: 220, echo: false, floor: MENU_MIN_WIDTH })
|
|
38
|
+
.minWidth,
|
|
39
|
+
).toBe(220);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('"trigger" pins min, width and max to the trigger', () => {
|
|
43
|
+
expect(panelWidthBox("trigger", { trigger: 240, available: 1000, echo: true })).toEqual({
|
|
44
|
+
minWidth: 240,
|
|
45
|
+
width: 240,
|
|
46
|
+
maxWidth: 240,
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('"screen" pins the box to the room between the margins', () => {
|
|
51
|
+
expect(panelWidthBox("screen", { trigger: 240, available: 370, echo: true })).toEqual({
|
|
52
|
+
minWidth: 370,
|
|
53
|
+
width: 370,
|
|
54
|
+
maxWidth: 370,
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("a number is that width, capped at the room", () => {
|
|
59
|
+
expect(panelWidthBox(320, { trigger: 240, available: 1000, echo: true }).width).toBe(320);
|
|
60
|
+
expect(panelWidthBox(180, { trigger: 240, available: 1000, echo: true }).width).toBe(180);
|
|
61
|
+
expect(panelWidthBox(600, { trigger: 240, available: 370, echo: true }).width).toBe(370);
|
|
62
|
+
expect(panelWidthBox(-5, { trigger: 240, available: 370, echo: true }).width).toBe(0);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
describe("panelLeftForWidth", () => {
|
|
67
|
+
const bounds = { boundsLeft: 10, boundsRight: 1430 };
|
|
68
|
+
|
|
69
|
+
it("keeps the trigger's start edge while the panel fits", () => {
|
|
70
|
+
expect(panelLeftForWidth({ triggerLeft: 200, triggerRight: 440, width: 320, ...bounds })).toBe(
|
|
71
|
+
200,
|
|
72
|
+
);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it("slides back inside the end margin", () => {
|
|
76
|
+
expect(
|
|
77
|
+
panelLeftForWidth({ triggerLeft: 1300, triggerRight: 1420, width: 320, ...bounds }),
|
|
78
|
+
).toBe(1110);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("a screen-wide panel sits on the start margin", () => {
|
|
82
|
+
expect(panelLeftForWidth({ triggerLeft: 200, triggerRight: 440, width: 1420, ...bounds })).toBe(
|
|
83
|
+
10,
|
|
84
|
+
);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it("right to left keeps the trigger's right edge", () => {
|
|
88
|
+
expect(
|
|
89
|
+
panelLeftForWidth({
|
|
90
|
+
triggerLeft: 1000,
|
|
91
|
+
triggerRight: 1240,
|
|
92
|
+
width: 320,
|
|
93
|
+
rtl: true,
|
|
94
|
+
...bounds,
|
|
95
|
+
}),
|
|
96
|
+
).toBe(920);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
describe("echoOffset", () => {
|
|
101
|
+
it("is the trigger's distance from the panel's start edge", () => {
|
|
102
|
+
expect(
|
|
103
|
+
echoOffset({ triggerLeft: 200, triggerRight: 440, panelLeft: 10, panelWidth: 1420 }),
|
|
104
|
+
).toBe(190);
|
|
105
|
+
expect(
|
|
106
|
+
echoOffset({ triggerLeft: 200, triggerRight: 440, panelLeft: 200, panelWidth: 320 }),
|
|
107
|
+
).toBe(0);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it("measures from the right edge in right to left", () => {
|
|
111
|
+
expect(
|
|
112
|
+
echoOffset({
|
|
113
|
+
triggerLeft: 1000,
|
|
114
|
+
triggerRight: 1240,
|
|
115
|
+
panelLeft: 10,
|
|
116
|
+
panelWidth: 1420,
|
|
117
|
+
rtl: true,
|
|
118
|
+
}),
|
|
119
|
+
).toBe(190);
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
describe("slidesAlongScreen", () => {
|
|
124
|
+
it("is true only for the widths not tied to the trigger's start edge", () => {
|
|
125
|
+
expect(slidesAlongScreen("screen")).toBe(true);
|
|
126
|
+
expect(slidesAlongScreen(320)).toBe(true);
|
|
127
|
+
expect(slidesAlongScreen("content")).toBe(false);
|
|
128
|
+
expect(slidesAlongScreen("trigger")).toBe(false);
|
|
129
|
+
expect(slidesAlongScreen(undefined)).toBe(false);
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
describe("screenBounds", () => {
|
|
134
|
+
const bounds = { boundsLeft: 10, boundsRight: 1430 };
|
|
135
|
+
|
|
136
|
+
it("a trigger in the page gutter lends its inset to both sides", () => {
|
|
137
|
+
// Field at the 16pt gutter, margins at 10: the panel spans 16..1424, so
|
|
138
|
+
// its start edge is the trigger's and the rows line up under the echo.
|
|
139
|
+
expect(screenBounds({ triggerLeft: 16, triggerRight: 276, ...bounds })).toEqual({
|
|
140
|
+
left: 16,
|
|
141
|
+
right: 1424,
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it("a trigger deep in the page keeps the safe margins", () => {
|
|
146
|
+
expect(screenBounds({ triggerLeft: 600, triggerRight: 860, ...bounds })).toEqual({
|
|
147
|
+
left: 10,
|
|
148
|
+
right: 1430,
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it("right to left measures the gutter from the right edge", () => {
|
|
153
|
+
expect(screenBounds({ triggerLeft: 1164, triggerRight: 1414, rtl: true, ...bounds })).toEqual({
|
|
154
|
+
left: 26,
|
|
155
|
+
right: 1414,
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
});
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How wide a panel opens over its trigger (LC-112, FZ-8438 r3). One setting
|
|
3
|
+
* for every picker and menu, on the web and native:
|
|
4
|
+
*
|
|
5
|
+
* - `"content"`: the panel hugs its content. While it echoes its trigger it
|
|
6
|
+
* is never narrower than the trigger, so the echo keeps its box.
|
|
7
|
+
* - `"trigger"`: exactly the trigger's width. Content wraps or scrolls.
|
|
8
|
+
* - `"screen"`: the room between the screen's safe margins. The top edge
|
|
9
|
+
* still sits on the trigger's top edge.
|
|
10
|
+
* - a number: that many points, capped at the room between the margins.
|
|
11
|
+
*/
|
|
12
|
+
export type PanelWidth = "content" | "trigger" | "screen" | number;
|
|
13
|
+
|
|
14
|
+
export interface PanelWidthBox {
|
|
15
|
+
minWidth: number;
|
|
16
|
+
/** Set for every mode but `"content"`, which leaves the width to its rows. */
|
|
17
|
+
width?: number;
|
|
18
|
+
maxWidth: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function panelWidthBox(
|
|
22
|
+
panelWidth: PanelWidth,
|
|
23
|
+
{
|
|
24
|
+
trigger,
|
|
25
|
+
available,
|
|
26
|
+
echo,
|
|
27
|
+
floor = 0,
|
|
28
|
+
}: {
|
|
29
|
+
/** The trigger's width. */
|
|
30
|
+
trigger: number;
|
|
31
|
+
/** The room between the screen's safe margins. */
|
|
32
|
+
available: number;
|
|
33
|
+
/** The panel's first row repeats the trigger. */
|
|
34
|
+
echo: boolean;
|
|
35
|
+
/** A platform minimum for `"content"` (the native pull-down's 250pt). */
|
|
36
|
+
floor?: number;
|
|
37
|
+
},
|
|
38
|
+
): PanelWidthBox {
|
|
39
|
+
const room = Math.max(0, available);
|
|
40
|
+
const pinned = (width: number) => {
|
|
41
|
+
const w = Math.max(0, Math.min(width, room));
|
|
42
|
+
return { minWidth: w, width: w, maxWidth: w };
|
|
43
|
+
};
|
|
44
|
+
if (panelWidth === "trigger") return pinned(trigger);
|
|
45
|
+
if (panelWidth === "screen") return pinned(room);
|
|
46
|
+
if (typeof panelWidth === "number") return pinned(panelWidth);
|
|
47
|
+
return { minWidth: Math.min(Math.max(echo ? trigger : 0, floor), room), maxWidth: room };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* A panel whose width is not tied to its trigger's box (`"screen"`, or a fixed
|
|
52
|
+
* width wider than the room from the trigger's start edge) slides along the
|
|
53
|
+
* screen to stay inside the margins. Its echo row is moved back over the
|
|
54
|
+
* trigger by the returned offset, so the trigger's content stays in place.
|
|
55
|
+
*/
|
|
56
|
+
export function panelLeftForWidth({
|
|
57
|
+
triggerLeft,
|
|
58
|
+
triggerRight,
|
|
59
|
+
width,
|
|
60
|
+
boundsLeft,
|
|
61
|
+
boundsRight,
|
|
62
|
+
rtl = false,
|
|
63
|
+
}: {
|
|
64
|
+
triggerLeft: number;
|
|
65
|
+
triggerRight: number;
|
|
66
|
+
width: number;
|
|
67
|
+
boundsLeft: number;
|
|
68
|
+
boundsRight: number;
|
|
69
|
+
rtl?: boolean;
|
|
70
|
+
}): number {
|
|
71
|
+
const want = rtl ? triggerRight - width : triggerLeft;
|
|
72
|
+
return Math.max(boundsLeft, Math.min(want, boundsRight - width));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** How far the echo row moves from the panel's start edge to sit on its trigger. */
|
|
76
|
+
export function echoOffset({
|
|
77
|
+
triggerLeft,
|
|
78
|
+
triggerRight,
|
|
79
|
+
panelLeft,
|
|
80
|
+
panelWidth,
|
|
81
|
+
rtl = false,
|
|
82
|
+
}: {
|
|
83
|
+
triggerLeft: number;
|
|
84
|
+
triggerRight: number;
|
|
85
|
+
panelLeft: number;
|
|
86
|
+
panelWidth: number;
|
|
87
|
+
rtl?: boolean;
|
|
88
|
+
}): number {
|
|
89
|
+
return rtl ? panelLeft + panelWidth - triggerRight : triggerLeft - panelLeft;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** True for the widths that are not tied to the trigger's start edge. */
|
|
93
|
+
export function slidesAlongScreen(panelWidth: PanelWidth | undefined): boolean {
|
|
94
|
+
return panelWidth === "screen" || typeof panelWidth === "number";
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* The bounds a `"screen"` panel spans. A trigger that sits in the page's start
|
|
99
|
+
* gutter, up to `gutter` points inside the safe margins, lends that inset to
|
|
100
|
+
* both sides, so the panel's start edge stays on the trigger's start edge and
|
|
101
|
+
* the rows line up under the echo. A trigger deeper in the page gets the safe
|
|
102
|
+
* margins as they are.
|
|
103
|
+
*/
|
|
104
|
+
export function screenBounds({
|
|
105
|
+
triggerLeft,
|
|
106
|
+
triggerRight,
|
|
107
|
+
boundsLeft,
|
|
108
|
+
boundsRight,
|
|
109
|
+
rtl = false,
|
|
110
|
+
gutter = 32,
|
|
111
|
+
}: {
|
|
112
|
+
triggerLeft: number;
|
|
113
|
+
triggerRight: number;
|
|
114
|
+
boundsLeft: number;
|
|
115
|
+
boundsRight: number;
|
|
116
|
+
rtl?: boolean;
|
|
117
|
+
gutter?: number;
|
|
118
|
+
}): { left: number; right: number } {
|
|
119
|
+
const inset = rtl ? boundsRight - triggerRight : triggerLeft - boundsLeft;
|
|
120
|
+
const margin = inset > 0 && inset <= gutter ? inset : 0;
|
|
121
|
+
return { left: boundsLeft + margin, right: boundsRight - margin };
|
|
122
|
+
}
|
|
@@ -7,9 +7,10 @@
|
|
|
7
7
|
* DatePicker measured 262px of calendar under a 289px trigger purely because
|
|
8
8
|
* the call site said `fitContent`.
|
|
9
9
|
*
|
|
10
|
-
* Calendar grids
|
|
11
|
-
*
|
|
12
|
-
* Text listboxes retain at-least-trigger; icon/button launchers
|
|
10
|
+
* Calendar grids opened from a field are the field grown open (LC-112
|
|
11
|
+
* seamless cover, FZ-8438): at least the field's width, superseding MPO-262's
|
|
12
|
+
* fit-content. Text listboxes retain at-least-trigger; icon/button launchers
|
|
13
|
+
* may hug.
|
|
13
14
|
* The Icon glyph grid pins to its field exactly (match-trigger): fixed 64px
|
|
14
15
|
* cells wrap into more columns on a wider field instead of stretching.
|
|
15
16
|
*/
|
|
@@ -21,13 +22,16 @@ import { describe, expect, it } from "vitest";
|
|
|
21
22
|
const fieldsDir = resolve(dirname(fileURLToPath(import.meta.url)), "..", "fields");
|
|
22
23
|
|
|
23
24
|
/** Pickers whose trigger is a form FIELD: the panel may never be narrower. */
|
|
24
|
-
const fieldShapedPickers = [
|
|
25
|
+
const fieldShapedPickers = [
|
|
26
|
+
"TimePicker/catalog.tsx",
|
|
27
|
+
"ColorPicker/parts.tsx",
|
|
28
|
+
"DatePicker/parts.tsx",
|
|
29
|
+
"DatePicker/DatetimePicker.catalog.tsx",
|
|
30
|
+
];
|
|
25
31
|
|
|
26
32
|
/** Field-triggered pickers pinned to the field's width exactly. */
|
|
27
33
|
const matchTriggerPickers = ["Icon/index.tsx"];
|
|
28
34
|
|
|
29
|
-
const intrinsicGridPickers = ["DatePicker/parts.tsx", "DatePicker/DatetimePicker.catalog.tsx"];
|
|
30
|
-
|
|
31
35
|
/** Panels opened from an icon/button trigger, where fit-content is correct. */
|
|
32
36
|
const buttonShapedPickers = ["Geolocation/index.tsx"];
|
|
33
37
|
|
|
@@ -36,10 +40,6 @@ function read(relative: string): string {
|
|
|
36
40
|
}
|
|
37
41
|
|
|
38
42
|
describe("FloatingPanel width contract (MPO-38, MPO-262)", () => {
|
|
39
|
-
it.each(intrinsicGridPickers)("%s hugs its calendar grid", (relative) => {
|
|
40
|
-
expect(read(relative)).toContain('widthMode="fit-content"');
|
|
41
|
-
});
|
|
42
|
-
|
|
43
43
|
it.each(fieldShapedPickers)("%s declares at-least-trigger", (relative) => {
|
|
44
44
|
const source = read(relative);
|
|
45
45
|
expect(source).toContain('widthMode="at-least-trigger"');
|
|
@@ -154,7 +154,14 @@ describe("placeOverTrigger (FZ-7830, LC-112 where no sheet may take it)", () =>
|
|
|
154
154
|
height: 180,
|
|
155
155
|
bounds: phone,
|
|
156
156
|
});
|
|
157
|
-
expect(placed).toEqual({
|
|
157
|
+
expect(placed).toEqual({
|
|
158
|
+
left: 20,
|
|
159
|
+
top: 200,
|
|
160
|
+
width: 200,
|
|
161
|
+
maxHeight: 600,
|
|
162
|
+
shifted: false,
|
|
163
|
+
end: false,
|
|
164
|
+
});
|
|
158
165
|
});
|
|
159
166
|
|
|
160
167
|
it("is at least the trigger's width", () => {
|
|
@@ -209,6 +216,54 @@ describe("placeOverTrigger (FZ-7830, LC-112 where no sheet may take it)", () =>
|
|
|
209
216
|
expect(placed.maxHeight).toBe(743);
|
|
210
217
|
});
|
|
211
218
|
|
|
219
|
+
it("opens an icon menu from the trigger's top trailing corner at the end edge (FZ-8438)", () => {
|
|
220
|
+
const placed = placeOverTrigger({
|
|
221
|
+
trigger,
|
|
222
|
+
width: 200,
|
|
223
|
+
height: 180,
|
|
224
|
+
bounds: phone,
|
|
225
|
+
align: "auto",
|
|
226
|
+
});
|
|
227
|
+
expect(placed).toMatchObject({ left: 144, top: 200, end: true, shifted: false });
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
it("keeps a bar button's corner inside the viewport margin (FZ-8438)", () => {
|
|
231
|
+
const placed = placeOverTrigger({
|
|
232
|
+
trigger: { x: 342, y: 60, width: 44, height: 44 },
|
|
233
|
+
width: 250,
|
|
234
|
+
height: 180,
|
|
235
|
+
bounds: phone,
|
|
236
|
+
align: "auto",
|
|
237
|
+
});
|
|
238
|
+
expect(placed.left).toBe(342 + 44 - 250);
|
|
239
|
+
expect(placed.end).toBe(true);
|
|
240
|
+
expect(placed.shifted).toBe(false);
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it("mirrors the icon menu in RTL: a leading-edge button opens from its left corner (FZ-8438)", () => {
|
|
244
|
+
const placed = placeOverTrigger({
|
|
245
|
+
trigger: { x: 4, y: 60, width: 44, height: 44 },
|
|
246
|
+
width: 250,
|
|
247
|
+
height: 180,
|
|
248
|
+
bounds: phone,
|
|
249
|
+
rtl: true,
|
|
250
|
+
align: "auto",
|
|
251
|
+
});
|
|
252
|
+
expect(placed.left).toBe(4);
|
|
253
|
+
expect(placed.end).toBe(true);
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
it("keeps the start corner for an icon menu that fits (FZ-8438)", () => {
|
|
257
|
+
const placed = placeOverTrigger({
|
|
258
|
+
trigger: { x: 20, y: 200, width: 44, height: 44 },
|
|
259
|
+
width: 200,
|
|
260
|
+
height: 180,
|
|
261
|
+
bounds: phone,
|
|
262
|
+
align: "auto",
|
|
263
|
+
});
|
|
264
|
+
expect(placed).toMatchObject({ left: 20, end: false, shifted: false });
|
|
265
|
+
});
|
|
266
|
+
|
|
212
267
|
it("never grows wider than the bounds", () => {
|
|
213
268
|
const placed = placeOverTrigger({
|
|
214
269
|
trigger: { x: 20, y: 200, width: 120, height: 44 },
|
|
@@ -227,7 +282,14 @@ describe("placeBesideTrigger (FZ-7830 round 3, LC-262: beside the trigger, never
|
|
|
227
282
|
|
|
228
283
|
it("opens under the trigger when it fits", () => {
|
|
229
284
|
const placed = placeBesideTrigger({ trigger: field, width: 200, height: 180, bounds: phone });
|
|
230
|
-
expect(placed).toEqual({
|
|
285
|
+
expect(placed).toEqual({
|
|
286
|
+
left: 16,
|
|
287
|
+
top: 344,
|
|
288
|
+
width: 358,
|
|
289
|
+
maxHeight: 180,
|
|
290
|
+
shifted: false,
|
|
291
|
+
end: false,
|
|
292
|
+
});
|
|
231
293
|
});
|
|
232
294
|
|
|
233
295
|
it("opens above the trigger when there is more room there, its bottom on the trigger's top", () => {
|
|
@@ -136,6 +136,8 @@ export interface TriggerPlacement {
|
|
|
136
136
|
maxHeight: number;
|
|
137
137
|
/** The menu moved off the trigger's top start corner to stay on screen. */
|
|
138
138
|
shifted: boolean;
|
|
139
|
+
/** An `"auto"` menu took the trigger's top trailing corner instead. */
|
|
140
|
+
end: boolean;
|
|
139
141
|
}
|
|
140
142
|
|
|
141
143
|
/**
|
|
@@ -151,17 +153,32 @@ export function placeOverTrigger({
|
|
|
151
153
|
height,
|
|
152
154
|
bounds,
|
|
153
155
|
rtl = false,
|
|
156
|
+
align = "start",
|
|
154
157
|
}: {
|
|
155
158
|
trigger: TriggerRect;
|
|
156
159
|
width: number;
|
|
157
160
|
height: number;
|
|
158
161
|
bounds: PanelBounds;
|
|
159
162
|
rtl?: boolean;
|
|
163
|
+
/**
|
|
164
|
+
* `"auto"` (a menu with no echo row) opens from the trailing top corner when
|
|
165
|
+
* the leading one would run off the end edge and the trailing one fits.
|
|
166
|
+
*/
|
|
167
|
+
align?: "start" | "auto";
|
|
160
168
|
}): TriggerPlacement {
|
|
161
169
|
const room = Math.max(0, bounds.right - bounds.left);
|
|
162
170
|
const w = Math.min(Math.max(width, trigger.width), room);
|
|
163
|
-
const
|
|
164
|
-
const
|
|
171
|
+
const startLeft = rtl ? trigger.x + trigger.width - w : trigger.x;
|
|
172
|
+
const endLeft = rtl ? trigger.x : trigger.x + trigger.width - w;
|
|
173
|
+
// Only the free edge has to clear the padded bounds: the aligned edge is
|
|
174
|
+
// the trigger's own, so a bar button inside the margin keeps its corner.
|
|
175
|
+
const startFree = rtl ? startLeft >= bounds.left : startLeft + w <= bounds.right;
|
|
176
|
+
const endFree = rtl ? endLeft + w <= bounds.right : endLeft >= bounds.left;
|
|
177
|
+
const auto = align === "auto";
|
|
178
|
+
const end = auto && !startFree && endFree;
|
|
179
|
+
const wantLeft = end ? endLeft : startLeft;
|
|
180
|
+
const keep = auto && (end || startFree);
|
|
181
|
+
const left = keep ? wantLeft : Math.max(bounds.left, Math.min(wantLeft, bounds.right - w));
|
|
165
182
|
const h = Math.min(height, Math.max(0, bounds.bottom - bounds.top));
|
|
166
183
|
const top = Math.max(bounds.top, Math.min(trigger.y, bounds.bottom - h));
|
|
167
184
|
return {
|
|
@@ -170,6 +187,7 @@ export function placeOverTrigger({
|
|
|
170
187
|
width: w,
|
|
171
188
|
maxHeight: Math.max(0, bounds.bottom - top),
|
|
172
189
|
shifted: left !== wantLeft || top !== trigger.y,
|
|
190
|
+
end,
|
|
173
191
|
};
|
|
174
192
|
}
|
|
175
193
|
|
|
@@ -200,5 +218,12 @@ export function placeBesideTrigger({
|
|
|
200
218
|
const opensUp = height > below && above > below;
|
|
201
219
|
const maxHeight = Math.min(height, opensUp ? above : below);
|
|
202
220
|
const top = opensUp ? trigger.y - maxHeight : trigger.y + trigger.height;
|
|
203
|
-
return {
|
|
221
|
+
return {
|
|
222
|
+
left,
|
|
223
|
+
top,
|
|
224
|
+
width: w,
|
|
225
|
+
maxHeight,
|
|
226
|
+
shifted: left !== wantLeft || opensUp,
|
|
227
|
+
end: false,
|
|
228
|
+
};
|
|
204
229
|
}
|
|
@@ -22,11 +22,13 @@ import { FloatingPanel } from "./index";
|
|
|
22
22
|
import { renderWithProviders } from "@multiplatform.one/test-utils";
|
|
23
23
|
import { Preset, type Knobs } from "@multiplatform.one/theme";
|
|
24
24
|
import { afterEach, describe, expect, it } from "vitest";
|
|
25
|
+
import { type PanelWidth } from "./panelWidth";
|
|
25
26
|
import {
|
|
26
27
|
type PanelWidthMode,
|
|
27
28
|
measureDrawnRadius,
|
|
28
29
|
panelAnchorOffset,
|
|
29
30
|
panelCoverOffset,
|
|
31
|
+
panelViewportPadding,
|
|
30
32
|
resolvePanelWidthMode,
|
|
31
33
|
useFloatingPanel,
|
|
32
34
|
} from "./useFloatingPanel";
|
|
@@ -35,10 +37,14 @@ function Harness({
|
|
|
35
37
|
open,
|
|
36
38
|
fitContent,
|
|
37
39
|
widthMode,
|
|
40
|
+
panelWidth,
|
|
41
|
+
echo,
|
|
38
42
|
}: {
|
|
39
43
|
open: boolean;
|
|
40
44
|
fitContent?: boolean;
|
|
41
45
|
widthMode?: PanelWidthMode;
|
|
46
|
+
panelWidth?: PanelWidth;
|
|
47
|
+
echo?: boolean;
|
|
42
48
|
}) {
|
|
43
49
|
const panel = useFloatingPanel({
|
|
44
50
|
open,
|
|
@@ -46,6 +52,8 @@ function Harness({
|
|
|
46
52
|
useAutoUpdate: false,
|
|
47
53
|
fitContent,
|
|
48
54
|
widthMode,
|
|
55
|
+
panelWidth,
|
|
56
|
+
echo,
|
|
49
57
|
});
|
|
50
58
|
return (
|
|
51
59
|
<>
|
|
@@ -76,7 +84,12 @@ function mockRect(el: HTMLElement, rect: { x: number; y: number; width: number;
|
|
|
76
84
|
/** Open the panel against a trigger of a known geometry and hand back the
|
|
77
85
|
* floating element once floating-ui has positioned it. */
|
|
78
86
|
async function openAgainstTrigger(
|
|
79
|
-
props: {
|
|
87
|
+
props: {
|
|
88
|
+
fitContent?: boolean;
|
|
89
|
+
widthMode?: PanelWidthMode;
|
|
90
|
+
panelWidth?: PanelWidth;
|
|
91
|
+
echo?: boolean;
|
|
92
|
+
},
|
|
80
93
|
triggerRect: { x: number; y: number; width: number; height: number },
|
|
81
94
|
) {
|
|
82
95
|
const result = renderWithProviders(<Harness open={false} {...props} />);
|
|
@@ -173,6 +186,90 @@ describe("FloatingPanel and DropdownMenu open over their trigger (MPO-38 cover r
|
|
|
173
186
|
});
|
|
174
187
|
});
|
|
175
188
|
|
|
189
|
+
describe("FloatingPanel panelWidth setting (LC-112, FZ-8438 r3)", () => {
|
|
190
|
+
const room = () =>
|
|
191
|
+
(document.documentElement.clientWidth || window.innerWidth) - 2 * panelViewportPadding;
|
|
192
|
+
|
|
193
|
+
it('"content" hugs its rows but never drops below an echoed trigger', async () => {
|
|
194
|
+
const result = await openAgainstTrigger({ panelWidth: "content" }, trigger);
|
|
195
|
+
await waitFor(() => {
|
|
196
|
+
const el = result.getByTestId("anchor-floating");
|
|
197
|
+
expect(el.style.minWidth).toBe("240px");
|
|
198
|
+
expect(el.style.width).toBe("");
|
|
199
|
+
expect(el.style.maxWidth).toBe(`${room()}px`);
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it('"content" without an echo (an icon trigger) has no trigger floor', async () => {
|
|
204
|
+
const result = await openAgainstTrigger({ panelWidth: "content", echo: false }, trigger);
|
|
205
|
+
await waitFor(() => {
|
|
206
|
+
const el = result.getByTestId("anchor-floating");
|
|
207
|
+
expect(el.style.minWidth).toBe("0px");
|
|
208
|
+
expect(el.style.width).toBe("");
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
it('"trigger" is exactly the trigger\'s width', async () => {
|
|
213
|
+
const result = await openAgainstTrigger({ panelWidth: "trigger" }, trigger);
|
|
214
|
+
await waitFor(() => {
|
|
215
|
+
const el = result.getByTestId("anchor-floating");
|
|
216
|
+
expect([el.style.minWidth, el.style.width, el.style.maxWidth]).toEqual([
|
|
217
|
+
"240px",
|
|
218
|
+
"240px",
|
|
219
|
+
"240px",
|
|
220
|
+
]);
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
it('"screen" from a trigger in the page gutter spans the gutters, both sides', async () => {
|
|
225
|
+
// The trigger sits 16 in: the panel takes that inset at each end, so its
|
|
226
|
+
// start edge is the trigger's and its rows line up under the echo.
|
|
227
|
+
const result = await openAgainstTrigger({ panelWidth: "screen" }, trigger);
|
|
228
|
+
const gutters = (document.documentElement.clientWidth || window.innerWidth) - 2 * trigger.x;
|
|
229
|
+
await waitFor(() => {
|
|
230
|
+
const el = result.getByTestId("anchor-floating");
|
|
231
|
+
expect(el.style.width).toBe(`${gutters}px`);
|
|
232
|
+
expect(el.style.maxWidth).toBe(`${gutters}px`);
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
it('"screen" from a trigger deep in the page is the room between the safe margins', async () => {
|
|
237
|
+
const result = await openAgainstTrigger({ panelWidth: "screen" }, { ...trigger, x: 400 });
|
|
238
|
+
await waitFor(() => {
|
|
239
|
+
const el = result.getByTestId("anchor-floating");
|
|
240
|
+
expect(el.style.width).toBe(`${room()}px`);
|
|
241
|
+
expect(el.style.maxWidth).toBe(`${room()}px`);
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
it("a number is a fixed width, wider or narrower than the trigger", async () => {
|
|
246
|
+
const wide = await openAgainstTrigger({ panelWidth: 320 }, trigger);
|
|
247
|
+
await waitFor(() => {
|
|
248
|
+
expect(wide.getByTestId("anchor-floating").style.width).toBe("320px");
|
|
249
|
+
});
|
|
250
|
+
wide.unmount();
|
|
251
|
+
const narrow = await openAgainstTrigger({ panelWidth: 180 }, trigger);
|
|
252
|
+
await waitFor(() => {
|
|
253
|
+
const el = narrow.getByTestId("anchor-floating");
|
|
254
|
+
expect([el.style.minWidth, el.style.width, el.style.maxWidth]).toEqual([
|
|
255
|
+
"180px",
|
|
256
|
+
"180px",
|
|
257
|
+
"180px",
|
|
258
|
+
]);
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
it("wins over widthMode when both are set", async () => {
|
|
263
|
+
const result = await openAgainstTrigger(
|
|
264
|
+
{ widthMode: "fit-content", panelWidth: "trigger" },
|
|
265
|
+
trigger,
|
|
266
|
+
);
|
|
267
|
+
await waitFor(() => {
|
|
268
|
+
expect(result.getByTestId("anchor-floating").style.width).toBe("240px");
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
});
|
|
272
|
+
|
|
176
273
|
describe("FloatingPanel width modes (MPO-38)", () => {
|
|
177
274
|
it("resolves the deprecated boolean onto the three modes", () => {
|
|
178
275
|
expect(resolvePanelWidthMode(undefined, undefined)).toBe("at-least-trigger");
|
|
@@ -441,14 +538,15 @@ describe("FloatingPanel drawn radius (MPO-129)", () => {
|
|
|
441
538
|
/**
|
|
442
539
|
* CONTAINER-CAP (MPO-56). Part 2b files floating panels under DG-RAD-04: the
|
|
443
540
|
* class value on the panel's own padding is the ceiling, and the trigger's
|
|
444
|
-
* drawn arc (above)
|
|
541
|
+
* drawn arc (above) lowers it. A covering panel takes the arc whole (FZ-8438).
|
|
445
542
|
*/
|
|
446
|
-
function RadiusHarness({ open }: { open: boolean }) {
|
|
447
|
-
const panel = useFloatingPanel({ open, onOpenChange: () => {}, useAutoUpdate: false });
|
|
543
|
+
function RadiusHarness({ open, cover = false }: { open: boolean; cover?: boolean }) {
|
|
544
|
+
const panel = useFloatingPanel({ open, onOpenChange: () => {}, useAutoUpdate: false, cover });
|
|
448
545
|
return (
|
|
449
546
|
<div
|
|
450
547
|
data-testid="radius-trigger"
|
|
451
548
|
data-radius={String(panel.dropdownRadius)}
|
|
549
|
+
data-inset={String(panel.coverCornerInset)}
|
|
452
550
|
ref={panel.setReferenceRef}
|
|
453
551
|
/>
|
|
454
552
|
);
|
|
@@ -513,4 +611,26 @@ describe("FloatingPanel radius is CONTAINER-CAP on its padding (DG-RAD-04, MPO-5
|
|
|
513
611
|
);
|
|
514
612
|
await waitFor(() => expect(anchor.getAttribute("data-radius")).toBe("18"));
|
|
515
613
|
});
|
|
614
|
+
|
|
615
|
+
it("a covering panel takes the trigger's drawn arc exactly, past the cap (LC-112, FZ-8438)", async () => {
|
|
616
|
+
const result = renderWithProviders(
|
|
617
|
+
<Preset overrides={{ borderRadius: "full" }}>
|
|
618
|
+
<RadiusHarness open={false} cover />
|
|
619
|
+
</Preset>,
|
|
620
|
+
);
|
|
621
|
+
const anchor = result.getByTestId("radius-trigger");
|
|
622
|
+
Object.assign(anchor.style, {
|
|
623
|
+
borderTopLeftRadius: "50px",
|
|
624
|
+
backgroundColor: "rgb(255, 255, 255)",
|
|
625
|
+
});
|
|
626
|
+
mockRect(anchor, { x: 0, y: 0, width: 240, height: 44 });
|
|
627
|
+
result.rerender(
|
|
628
|
+
<Preset overrides={{ borderRadius: "full" }}>
|
|
629
|
+
<RadiusHarness open cover />
|
|
630
|
+
</Preset>,
|
|
631
|
+
);
|
|
632
|
+
await waitFor(() => expect(anchor.getAttribute("data-radius")).toBe("22"));
|
|
633
|
+
// Past the cap, the bottom insets by the arc's sagitta at 45° so rows clear it.
|
|
634
|
+
expect(anchor.getAttribute("data-inset")).toBe(String(Math.ceil(22 * (1 - Math.SQRT1_2))));
|
|
635
|
+
});
|
|
516
636
|
});
|