@multiplatform.one/forms 6.4.2 → 6.6.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 +23 -8
- package/dist/cjs/Button/index.native.js +23 -8
- package/dist/cjs/Button/index.native.js.map +1 -1
- package/dist/cjs/FieldDisplay/formatters.cjs +7 -12
- package/dist/cjs/FieldDisplay/formatters.native.js +7 -12
- package/dist/cjs/FieldDisplay/formatters.native.js.map +1 -1
- package/dist/cjs/Skeleton/index.cjs +1 -0
- package/dist/cjs/Skeleton/index.native.js +4 -0
- package/dist/cjs/Skeleton/index.native.js.map +1 -1
- package/dist/cjs/Wheel/index.cjs +1 -1
- package/dist/cjs/Wheel/index.native.js +1 -1
- package/dist/cjs/Wheel/index.native.js.map +1 -1
- package/dist/cjs/fields/Checkbox/Checkbox.cjs +22 -15
- package/dist/cjs/fields/Checkbox/Checkbox.native.js +11 -6
- package/dist/cjs/fields/Checkbox/Checkbox.native.js.map +1 -1
- package/dist/cjs/fields/Checkbox/index.cjs +9 -3
- package/dist/cjs/fields/Checkbox/index.native.js +9 -3
- package/dist/cjs/fields/Checkbox/index.native.js.map +1 -1
- package/dist/cjs/fields/ColorPicker/parts.native.js.map +1 -1
- package/dist/cjs/fields/Combobox/index.cjs +9 -4
- package/dist/cjs/fields/Combobox/index.native.js +9 -4
- package/dist/cjs/fields/Combobox/index.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/DateRangePicker.cjs +30 -20
- package/dist/cjs/fields/DatePicker/DateRangePicker.native.js +36 -21
- package/dist/cjs/fields/DatePicker/DateRangePicker.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/DatetimePicker.cjs +21 -15
- package/dist/cjs/fields/DatePicker/DatetimePicker.native.js +26 -16
- package/dist/cjs/fields/DatePicker/DatetimePicker.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/MonthPicker.cjs +24 -14
- package/dist/cjs/fields/DatePicker/MonthPicker.native.js +36 -15
- package/dist/cjs/fields/DatePicker/MonthPicker.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/MultiDatePicker.cjs +27 -18
- package/dist/cjs/fields/DatePicker/MultiDatePicker.native.js +32 -19
- package/dist/cjs/fields/DatePicker/MultiDatePicker.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/fieldValueSync.cjs +49 -0
- package/dist/cjs/fields/DatePicker/fieldValueSync.native.js +56 -0
- package/dist/cjs/fields/DatePicker/fieldValueSync.native.js.map +1 -0
- package/dist/cjs/fields/DatePicker/index.cjs +20 -14
- package/dist/cjs/fields/DatePicker/index.native.js +25 -15
- package/dist/cjs/fields/DatePicker/index.native.js.map +1 -1
- package/dist/cjs/fields/DatePicker/parts.cjs +2 -3
- package/dist/cjs/fields/DatePicker/parts.native.js +2 -3
- package/dist/cjs/fields/DatePicker/parts.native.js.map +1 -1
- package/dist/cjs/fields/Geolocation/GeolocationMap.native.js +2 -2
- package/dist/cjs/fields/RadioGroup/index.cjs +4 -6
- package/dist/cjs/fields/RadioGroup/index.native.js +7 -6
- package/dist/cjs/fields/RadioGroup/index.native.js.map +1 -1
- package/dist/cjs/fields/Rating/index.cjs +20 -3
- package/dist/cjs/fields/Rating/index.native.js +31 -6
- package/dist/cjs/fields/Rating/index.native.js.map +1 -1
- package/dist/cjs/fields/SearchInput/index.cjs +5 -1
- package/dist/cjs/fields/SearchInput/index.native.js +5 -1
- package/dist/cjs/fields/SearchInput/index.native.js.map +1 -1
- package/dist/cjs/fields/Select/index.cjs +6 -10
- package/dist/cjs/fields/Select/index.native.js +12 -10
- package/dist/cjs/fields/Select/index.native.js.map +1 -1
- package/dist/cjs/fields/Signature/index.cjs +1 -1
- package/dist/cjs/fields/Signature/index.native.js +1 -1
- package/dist/cjs/fields/Signature/index.native.js.map +1 -1
- package/dist/cjs/fields/Slider/index.cjs +16 -4
- package/dist/cjs/fields/Slider/index.native.js +24 -4
- package/dist/cjs/fields/Slider/index.native.js.map +1 -1
- package/dist/cjs/fields/TextArea/index.cjs +3 -2
- package/dist/cjs/fields/TextArea/index.native.js +5 -2
- package/dist/cjs/fields/TextArea/index.native.js.map +1 -1
- package/dist/cjs/fields/TimePicker/index.cjs +1 -1
- package/dist/cjs/fields/TimePicker/index.native.js +1 -1
- package/dist/cjs/fields/TimePicker/index.native.js.map +1 -1
- package/dist/cjs/fields/ToggleGroup/index.cjs +6 -22
- package/dist/cjs/fields/ToggleGroup/index.native.js +11 -28
- package/dist/cjs/fields/ToggleGroup/index.native.js.map +1 -1
- package/dist/cjs/shared/TimeColumn.cjs +1 -1
- package/dist/cjs/shared/TimeColumn.native.js +1 -1
- package/dist/cjs/shared/TimeColumn.native.js.map +1 -1
- package/dist/cjs/shared/colorRamps.cjs +5 -1
- package/dist/cjs/shared/colorRamps.native.js +5 -1
- package/dist/cjs/shared/colorRamps.native.js.map +1 -1
- package/dist/cjs/shared/focusManagement.cjs +7 -1
- package/dist/cjs/shared/focusManagement.native.js +5 -1
- package/dist/cjs/shared/focusManagement.native.js.map +1 -1
- package/dist/cjs/shared/t.cjs +5 -0
- package/dist/cjs/shared/t.native.js +5 -0
- package/dist/cjs/shared/t.native.js.map +1 -1
- package/dist/esm/Button/index.mjs +24 -9
- package/dist/esm/Button/index.mjs.map +1 -1
- package/dist/esm/Button/index.native.js +24 -9
- package/dist/esm/Button/index.native.js.map +1 -1
- package/dist/esm/FieldDisplay/formatters.mjs +8 -13
- package/dist/esm/FieldDisplay/formatters.mjs.map +1 -1
- package/dist/esm/FieldDisplay/formatters.native.js +8 -13
- package/dist/esm/FieldDisplay/formatters.native.js.map +1 -1
- package/dist/esm/FieldDisplay/index.mjs.map +1 -1
- package/dist/esm/FloatingPanel/index.mjs.map +1 -1
- package/dist/esm/Skeleton/index.mjs +2 -1
- package/dist/esm/Skeleton/index.mjs.map +1 -1
- package/dist/esm/Skeleton/index.native.js +5 -1
- package/dist/esm/Skeleton/index.native.js.map +1 -1
- package/dist/esm/Wheel/index.mjs +1 -1
- package/dist/esm/Wheel/index.mjs.map +1 -1
- package/dist/esm/Wheel/index.native.js +1 -1
- package/dist/esm/Wheel/index.native.js.map +1 -1
- package/dist/esm/fields/Checkbox/Checkbox.mjs +24 -17
- package/dist/esm/fields/Checkbox/Checkbox.mjs.map +1 -1
- package/dist/esm/fields/Checkbox/Checkbox.native.js +13 -8
- package/dist/esm/fields/Checkbox/Checkbox.native.js.map +1 -1
- package/dist/esm/fields/Checkbox/index.mjs +11 -5
- package/dist/esm/fields/Checkbox/index.mjs.map +1 -1
- package/dist/esm/fields/Checkbox/index.native.js +11 -5
- package/dist/esm/fields/Checkbox/index.native.js.map +1 -1
- package/dist/esm/fields/ColorPicker/index.mjs.map +1 -1
- package/dist/esm/fields/ColorPicker/parts.mjs.map +1 -1
- package/dist/esm/fields/ColorPicker/parts.native.js.map +1 -1
- package/dist/esm/fields/Combobox/index.mjs +9 -4
- package/dist/esm/fields/Combobox/index.mjs.map +1 -1
- package/dist/esm/fields/Combobox/index.native.js +9 -4
- package/dist/esm/fields/Combobox/index.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/DateRangePicker.mjs +31 -21
- package/dist/esm/fields/DatePicker/DateRangePicker.mjs.map +1 -1
- package/dist/esm/fields/DatePicker/DateRangePicker.native.js +37 -22
- package/dist/esm/fields/DatePicker/DateRangePicker.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/DatetimePicker.mjs +21 -15
- package/dist/esm/fields/DatePicker/DatetimePicker.mjs.map +1 -1
- package/dist/esm/fields/DatePicker/DatetimePicker.native.js +26 -16
- package/dist/esm/fields/DatePicker/DatetimePicker.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/MonthPicker.mjs +25 -15
- package/dist/esm/fields/DatePicker/MonthPicker.mjs.map +1 -1
- package/dist/esm/fields/DatePicker/MonthPicker.native.js +37 -16
- package/dist/esm/fields/DatePicker/MonthPicker.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/MultiDatePicker.mjs +28 -19
- package/dist/esm/fields/DatePicker/MultiDatePicker.mjs.map +1 -1
- package/dist/esm/fields/DatePicker/MultiDatePicker.native.js +33 -20
- package/dist/esm/fields/DatePicker/MultiDatePicker.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/fieldValueSync.mjs +23 -0
- package/dist/esm/fields/DatePicker/fieldValueSync.mjs.map +1 -0
- package/dist/esm/fields/DatePicker/fieldValueSync.native.js +27 -0
- package/dist/esm/fields/DatePicker/fieldValueSync.native.js.map +1 -0
- package/dist/esm/fields/DatePicker/index.mjs +21 -15
- package/dist/esm/fields/DatePicker/index.mjs.map +1 -1
- package/dist/esm/fields/DatePicker/index.native.js +26 -16
- package/dist/esm/fields/DatePicker/index.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/parts.mjs +3 -4
- package/dist/esm/fields/DatePicker/parts.mjs.map +1 -1
- package/dist/esm/fields/DatePicker/parts.native.js +3 -4
- package/dist/esm/fields/DatePicker/parts.native.js.map +1 -1
- package/dist/esm/fields/DatePicker/utils.mjs.map +1 -1
- package/dist/esm/fields/Geolocation/GeolocationMap.native.js +2 -2
- package/dist/esm/fields/ImageField/index.mjs.map +1 -1
- package/dist/esm/fields/OTPInput/index.mjs.map +1 -1
- package/dist/esm/fields/RadioGroup/index.mjs +5 -7
- package/dist/esm/fields/RadioGroup/index.mjs.map +1 -1
- package/dist/esm/fields/RadioGroup/index.native.js +8 -7
- package/dist/esm/fields/RadioGroup/index.native.js.map +1 -1
- package/dist/esm/fields/Rating/index.mjs +20 -3
- package/dist/esm/fields/Rating/index.mjs.map +1 -1
- package/dist/esm/fields/Rating/index.native.js +31 -6
- package/dist/esm/fields/Rating/index.native.js.map +1 -1
- package/dist/esm/fields/SearchInput/index.mjs +6 -2
- package/dist/esm/fields/SearchInput/index.mjs.map +1 -1
- package/dist/esm/fields/SearchInput/index.native.js +6 -2
- package/dist/esm/fields/SearchInput/index.native.js.map +1 -1
- package/dist/esm/fields/Select/index.mjs +6 -10
- package/dist/esm/fields/Select/index.mjs.map +1 -1
- package/dist/esm/fields/Select/index.native.js +12 -10
- package/dist/esm/fields/Select/index.native.js.map +1 -1
- package/dist/esm/fields/Signature/index.mjs +1 -1
- package/dist/esm/fields/Signature/index.mjs.map +1 -1
- package/dist/esm/fields/Signature/index.native.js +1 -1
- package/dist/esm/fields/Signature/index.native.js.map +1 -1
- package/dist/esm/fields/Slider/index.mjs +16 -4
- package/dist/esm/fields/Slider/index.mjs.map +1 -1
- package/dist/esm/fields/Slider/index.native.js +24 -4
- package/dist/esm/fields/Slider/index.native.js.map +1 -1
- package/dist/esm/fields/TextArea/index.mjs +3 -2
- package/dist/esm/fields/TextArea/index.mjs.map +1 -1
- package/dist/esm/fields/TextArea/index.native.js +5 -2
- package/dist/esm/fields/TextArea/index.native.js.map +1 -1
- package/dist/esm/fields/TimePicker/index.mjs +1 -1
- package/dist/esm/fields/TimePicker/index.mjs.map +1 -1
- package/dist/esm/fields/TimePicker/index.native.js +1 -1
- package/dist/esm/fields/TimePicker/index.native.js.map +1 -1
- package/dist/esm/fields/ToggleGroup/index.mjs +7 -23
- package/dist/esm/fields/ToggleGroup/index.mjs.map +1 -1
- package/dist/esm/fields/ToggleGroup/index.native.js +12 -29
- package/dist/esm/fields/ToggleGroup/index.native.js.map +1 -1
- package/dist/esm/shared/TimeColumn.mjs +1 -1
- package/dist/esm/shared/TimeColumn.mjs.map +1 -1
- package/dist/esm/shared/TimeColumn.native.js +1 -1
- package/dist/esm/shared/TimeColumn.native.js.map +1 -1
- package/dist/esm/shared/colorRamps.mjs +5 -2
- package/dist/esm/shared/colorRamps.mjs.map +1 -1
- package/dist/esm/shared/colorRamps.native.js +5 -2
- package/dist/esm/shared/colorRamps.native.js.map +1 -1
- package/dist/esm/shared/focusManagement.mjs +7 -1
- package/dist/esm/shared/focusManagement.mjs.map +1 -1
- package/dist/esm/shared/focusManagement.native.js +5 -1
- package/dist/esm/shared/focusManagement.native.js.map +1 -1
- package/dist/esm/shared/t.mjs +5 -1
- package/dist/esm/shared/t.mjs.map +1 -1
- package/dist/esm/shared/t.native.js +5 -1
- package/dist/esm/shared/t.native.js.map +1 -1
- package/dist/jsx/Button/index.mjs +24 -9
- package/dist/jsx/Button/index.mjs.map +1 -1
- package/dist/jsx/Button/index.native.js +23 -8
- package/dist/jsx/Button/index.native.js.map +1 -1
- package/dist/jsx/FieldDisplay/formatters.mjs +8 -13
- package/dist/jsx/FieldDisplay/formatters.mjs.map +1 -1
- package/dist/jsx/FieldDisplay/formatters.native.js +7 -12
- package/dist/jsx/FieldDisplay/formatters.native.js.map +1 -1
- package/dist/jsx/FieldDisplay/index.mjs.map +1 -1
- package/dist/jsx/FloatingPanel/index.mjs.map +1 -1
- package/dist/jsx/Skeleton/index.mjs +2 -1
- package/dist/jsx/Skeleton/index.mjs.map +1 -1
- package/dist/jsx/Skeleton/index.native.js +4 -0
- package/dist/jsx/Skeleton/index.native.js.map +1 -1
- package/dist/jsx/Wheel/index.mjs +1 -1
- package/dist/jsx/Wheel/index.mjs.map +1 -1
- package/dist/jsx/Wheel/index.native.js +1 -1
- package/dist/jsx/Wheel/index.native.js.map +1 -1
- package/dist/jsx/fields/Checkbox/Checkbox.mjs +24 -17
- package/dist/jsx/fields/Checkbox/Checkbox.mjs.map +1 -1
- package/dist/jsx/fields/Checkbox/Checkbox.native.js +11 -6
- package/dist/jsx/fields/Checkbox/Checkbox.native.js.map +1 -1
- package/dist/jsx/fields/Checkbox/index.mjs +11 -5
- package/dist/jsx/fields/Checkbox/index.mjs.map +1 -1
- package/dist/jsx/fields/Checkbox/index.native.js +9 -3
- package/dist/jsx/fields/Checkbox/index.native.js.map +1 -1
- package/dist/jsx/fields/ColorPicker/index.mjs.map +1 -1
- package/dist/jsx/fields/ColorPicker/parts.mjs.map +1 -1
- package/dist/jsx/fields/ColorPicker/parts.native.js.map +1 -1
- package/dist/jsx/fields/Combobox/index.mjs +9 -4
- package/dist/jsx/fields/Combobox/index.mjs.map +1 -1
- package/dist/jsx/fields/Combobox/index.native.js +9 -4
- package/dist/jsx/fields/Combobox/index.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/DateRangePicker.mjs +31 -21
- package/dist/jsx/fields/DatePicker/DateRangePicker.mjs.map +1 -1
- package/dist/jsx/fields/DatePicker/DateRangePicker.native.js +36 -21
- package/dist/jsx/fields/DatePicker/DateRangePicker.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/DatetimePicker.mjs +21 -15
- package/dist/jsx/fields/DatePicker/DatetimePicker.mjs.map +1 -1
- package/dist/jsx/fields/DatePicker/DatetimePicker.native.js +26 -16
- package/dist/jsx/fields/DatePicker/DatetimePicker.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/MonthPicker.mjs +25 -15
- package/dist/jsx/fields/DatePicker/MonthPicker.mjs.map +1 -1
- package/dist/jsx/fields/DatePicker/MonthPicker.native.js +36 -15
- package/dist/jsx/fields/DatePicker/MonthPicker.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/MultiDatePicker.mjs +28 -19
- package/dist/jsx/fields/DatePicker/MultiDatePicker.mjs.map +1 -1
- package/dist/jsx/fields/DatePicker/MultiDatePicker.native.js +32 -19
- package/dist/jsx/fields/DatePicker/MultiDatePicker.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/fieldValueSync.mjs +23 -0
- package/dist/jsx/fields/DatePicker/fieldValueSync.mjs.map +1 -0
- package/dist/jsx/fields/DatePicker/fieldValueSync.native.js +56 -0
- package/dist/jsx/fields/DatePicker/fieldValueSync.native.js.map +1 -0
- package/dist/jsx/fields/DatePicker/index.mjs +21 -15
- package/dist/jsx/fields/DatePicker/index.mjs.map +1 -1
- package/dist/jsx/fields/DatePicker/index.native.js +25 -15
- package/dist/jsx/fields/DatePicker/index.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/parts.mjs +3 -4
- package/dist/jsx/fields/DatePicker/parts.mjs.map +1 -1
- package/dist/jsx/fields/DatePicker/parts.native.js +2 -3
- package/dist/jsx/fields/DatePicker/parts.native.js.map +1 -1
- package/dist/jsx/fields/DatePicker/utils.mjs.map +1 -1
- package/dist/jsx/fields/Geolocation/GeolocationMap.native.js +2 -2
- package/dist/jsx/fields/ImageField/index.mjs.map +1 -1
- package/dist/jsx/fields/OTPInput/index.mjs.map +1 -1
- package/dist/jsx/fields/RadioGroup/index.mjs +5 -7
- package/dist/jsx/fields/RadioGroup/index.mjs.map +1 -1
- package/dist/jsx/fields/RadioGroup/index.native.js +7 -6
- package/dist/jsx/fields/RadioGroup/index.native.js.map +1 -1
- package/dist/jsx/fields/Rating/index.mjs +20 -3
- package/dist/jsx/fields/Rating/index.mjs.map +1 -1
- package/dist/jsx/fields/Rating/index.native.js +31 -6
- package/dist/jsx/fields/Rating/index.native.js.map +1 -1
- package/dist/jsx/fields/SearchInput/index.mjs +6 -2
- package/dist/jsx/fields/SearchInput/index.mjs.map +1 -1
- package/dist/jsx/fields/SearchInput/index.native.js +5 -1
- package/dist/jsx/fields/SearchInput/index.native.js.map +1 -1
- package/dist/jsx/fields/Select/index.mjs +6 -10
- package/dist/jsx/fields/Select/index.mjs.map +1 -1
- package/dist/jsx/fields/Select/index.native.js +12 -10
- package/dist/jsx/fields/Select/index.native.js.map +1 -1
- package/dist/jsx/fields/Signature/index.mjs +1 -1
- package/dist/jsx/fields/Signature/index.mjs.map +1 -1
- package/dist/jsx/fields/Signature/index.native.js +1 -1
- package/dist/jsx/fields/Signature/index.native.js.map +1 -1
- package/dist/jsx/fields/Slider/index.mjs +16 -4
- package/dist/jsx/fields/Slider/index.mjs.map +1 -1
- package/dist/jsx/fields/Slider/index.native.js +24 -4
- package/dist/jsx/fields/Slider/index.native.js.map +1 -1
- package/dist/jsx/fields/TextArea/index.mjs +3 -2
- package/dist/jsx/fields/TextArea/index.mjs.map +1 -1
- package/dist/jsx/fields/TextArea/index.native.js +5 -2
- package/dist/jsx/fields/TextArea/index.native.js.map +1 -1
- package/dist/jsx/fields/TimePicker/index.mjs +1 -1
- package/dist/jsx/fields/TimePicker/index.mjs.map +1 -1
- package/dist/jsx/fields/TimePicker/index.native.js +1 -1
- package/dist/jsx/fields/TimePicker/index.native.js.map +1 -1
- package/dist/jsx/fields/ToggleGroup/index.mjs +7 -23
- package/dist/jsx/fields/ToggleGroup/index.mjs.map +1 -1
- package/dist/jsx/fields/ToggleGroup/index.native.js +11 -28
- package/dist/jsx/fields/ToggleGroup/index.native.js.map +1 -1
- package/dist/jsx/shared/TimeColumn.mjs +1 -1
- package/dist/jsx/shared/TimeColumn.mjs.map +1 -1
- package/dist/jsx/shared/TimeColumn.native.js +1 -1
- package/dist/jsx/shared/TimeColumn.native.js.map +1 -1
- package/dist/jsx/shared/colorRamps.mjs +5 -2
- package/dist/jsx/shared/colorRamps.mjs.map +1 -1
- package/dist/jsx/shared/colorRamps.native.js +5 -1
- package/dist/jsx/shared/colorRamps.native.js.map +1 -1
- package/dist/jsx/shared/focusManagement.mjs +7 -1
- package/dist/jsx/shared/focusManagement.mjs.map +1 -1
- package/dist/jsx/shared/focusManagement.native.js +5 -1
- package/dist/jsx/shared/focusManagement.native.js.map +1 -1
- package/dist/jsx/shared/t.mjs +5 -1
- package/dist/jsx/shared/t.mjs.map +1 -1
- package/dist/jsx/shared/t.native.js +5 -0
- package/dist/jsx/shared/t.native.js.map +1 -1
- package/package.json +8 -7
- package/src/Button/Button.stories.tsx +19 -0
- package/src/Button/index.tsx +45 -12
- package/src/ControlGroup/ControlGroup.stories.tsx +12 -0
- package/src/FieldDisplay/formatters.ts +10 -14
- package/src/FieldLayout.stories.tsx +3 -2
- package/src/Form/Form.stories.tsx +13 -0
- package/src/Skeleton/index.tsx +5 -1
- package/src/fields/Checkbox/Checkbox.spec.tsx +50 -1
- package/src/fields/Checkbox/Checkbox.tsx +47 -19
- package/src/fields/Checkbox/index.tsx +23 -5
- package/src/fields/ColorPicker/ColorPicker.stories.tsx +2 -1
- package/src/fields/Combobox/index.tsx +8 -3
- package/src/fields/DatePicker/DatePicker.spec.tsx +93 -0
- package/src/fields/DatePicker/DatePicker.stories.tsx +2 -1
- package/src/fields/DatePicker/DateRangePicker.spec.tsx +72 -0
- package/src/fields/DatePicker/DateRangePicker.tsx +44 -30
- package/src/fields/DatePicker/DatetimePicker.spec.tsx +39 -0
- package/src/fields/DatePicker/DatetimePicker.tsx +1 -1
- package/src/fields/DatePicker/MonthPicker.spec.tsx +61 -0
- package/src/fields/DatePicker/MonthPicker.tsx +47 -21
- package/src/fields/DatePicker/MultiDatePicker.spec.tsx +34 -0
- package/src/fields/DatePicker/MultiDatePicker.tsx +39 -27
- package/src/fields/DatePicker/fieldValueSync.tsx +23 -0
- package/src/fields/DatePicker/parts.tsx +6 -1
- package/src/fields/FileUpload/FileUpload.stories.tsx +11 -1
- package/src/fields/Geolocation/Geolocation.stories.tsx +9 -0
- package/src/fields/Geolocation/GeolocationMap.native.tsx +2 -2
- package/src/fields/ImageField/ImageField.stories.tsx +2 -1
- package/src/fields/Input/Input.stories.tsx +19 -0
- package/src/fields/Progress/Progress.stories.tsx +19 -0
- package/src/fields/RadioGroup/RadioGroup.spec.tsx +139 -2
- package/src/fields/RadioGroup/index.tsx +2 -2
- package/src/fields/Rating/Rating.spec.tsx +43 -1
- package/src/fields/Rating/index.tsx +43 -4
- package/src/fields/SearchInput/SearchInput.spec.tsx +11 -0
- package/src/fields/SearchInput/index.tsx +6 -2
- package/src/fields/Select/Select.stories.tsx +19 -0
- package/src/fields/Select/index.tsx +12 -5
- package/src/fields/Signature/index.tsx +1 -1
- package/src/fields/Slider/Slider.spec.tsx +89 -4
- package/src/fields/Slider/Slider.stories.tsx +19 -0
- package/src/fields/Slider/index.tsx +4 -0
- package/src/fields/Stepper/Stepper.stories.tsx +12 -0
- package/src/fields/Switch/Switch.spec.tsx +50 -2
- package/src/fields/TextArea/TextArea.spec.tsx +57 -0
- package/src/fields/TextArea/TextArea.stories.tsx +19 -0
- package/src/fields/TextArea/index.tsx +10 -2
- package/src/fields/TimePicker/index.tsx +1 -1
- package/src/fields/ToggleGroup/ToggleGroup.spec.tsx +64 -1
- package/src/fields/ToggleGroup/ToggleGroup.stories.tsx +19 -0
- package/src/fields/ToggleGroup/index.tsx +31 -29
- package/src/shared/FloatingListScrollArrows.stories.tsx +4 -2
- package/src/shared/TimeColumn.tsx +1 -1
- package/src/shared/focusManagement.ts +12 -1
- package/src/shared/t.spec.ts +39 -0
- package/src/shared/t.ts +20 -0
- package/types/Button/index.d.ts +9 -1
- package/types/Button/index.d.ts.map +1 -1
- package/types/FieldDisplay/formatters.d.ts +7 -1
- package/types/FieldDisplay/formatters.d.ts.map +1 -1
- package/types/InputParts/index.d.ts +4 -4
- package/types/Skeleton/index.d.ts.map +1 -1
- package/types/fields/Checkbox/Checkbox.d.ts.map +1 -1
- package/types/fields/Checkbox/index.d.ts +3 -3
- package/types/fields/Checkbox/index.d.ts.map +1 -1
- package/types/fields/Combobox/index.d.ts.map +1 -1
- package/types/fields/DatePicker/DateRangePicker.d.ts.map +1 -1
- package/types/fields/DatePicker/DatetimePicker.d.ts.map +1 -1
- package/types/fields/DatePicker/MonthPicker.d.ts.map +1 -1
- package/types/fields/DatePicker/MultiDatePicker.d.ts.map +1 -1
- package/types/fields/DatePicker/fieldValueSync.d.ts +31 -0
- package/types/fields/DatePicker/fieldValueSync.d.ts.map +1 -0
- package/types/fields/DatePicker/index.d.ts.map +1 -1
- package/types/fields/DatePicker/parts.d.ts.map +1 -1
- package/types/fields/Input/index.d.ts +2 -2
- package/types/fields/RadioGroup/index.d.ts.map +1 -1
- package/types/fields/Rating/index.d.ts.map +1 -1
- package/types/fields/SearchInput/index.d.ts.map +1 -1
- package/types/fields/Select/index.d.ts.map +1 -1
- package/types/fields/Slider/index.d.ts.map +1 -1
- package/types/fields/TextArea/index.d.ts.map +1 -1
- package/types/fields/ToggleGroup/index.d.ts.map +1 -1
- package/types/shared/colorRamps.d.ts +14 -0
- package/types/shared/colorRamps.d.ts.map +1 -1
- package/types/shared/focusManagement.d.ts.map +1 -1
- package/types/shared/t.d.ts +16 -0
- package/types/shared/t.d.ts.map +1 -1
|
@@ -36,10 +36,10 @@ function MapFallback({ lat, lng, minHeight }: { lat: number; lng: number; minHei
|
|
|
36
36
|
backgroundColor="$backgroundHover"
|
|
37
37
|
gap="$1"
|
|
38
38
|
>
|
|
39
|
-
<Text color="$
|
|
39
|
+
<Text color="$color11" fontSize="$2">
|
|
40
40
|
{t("Map preview unavailable — requires expo-maps")}
|
|
41
41
|
</Text>
|
|
42
|
-
<Text color="$
|
|
42
|
+
<Text color="$color11" fontSize="$1">
|
|
43
43
|
{`${lat.toFixed(4)}, ${lng.toFixed(4)}`}
|
|
44
44
|
</Text>
|
|
45
45
|
</YStack>
|
|
@@ -135,7 +135,8 @@ export const ReadOnly: Story = {
|
|
|
135
135
|
export const WithError: Story = {
|
|
136
136
|
args: {
|
|
137
137
|
label: "Required Image",
|
|
138
|
-
|
|
138
|
+
// DG-COPY-02: error copy states the rule broken — never "please"/"invalid"/"error".
|
|
139
|
+
error: "An image is required",
|
|
139
140
|
required: true,
|
|
140
141
|
imageWidth: 64,
|
|
141
142
|
imageHeight: 64,
|
|
@@ -115,7 +115,26 @@ export const SkeletonState: Story = {
|
|
|
115
115
|
args: { label: "Full name", skeleton: true },
|
|
116
116
|
};
|
|
117
117
|
|
|
118
|
+
/**
|
|
119
|
+
* FOREIGN CONTRAST SPECIMEN (LC-56 STORY-HONESTY): the right column renders the
|
|
120
|
+
* RAW tamagui Input beside the house Input strictly so the difference stays
|
|
121
|
+
* visible. Raw primitives here are by design and labeled — knob/contrast probes
|
|
122
|
+
* skip this story via `parameters.foreignContrastSpecimen`.
|
|
123
|
+
*/
|
|
118
124
|
export const Comparison: StoryObj = {
|
|
125
|
+
name: "Foreign contrast specimen (raw tamagui)",
|
|
126
|
+
parameters: {
|
|
127
|
+
// Machine-readable exemption for knob/contrast probes and the LC-56 linter arm.
|
|
128
|
+
foreignContrastSpecimen: true,
|
|
129
|
+
docs: {
|
|
130
|
+
description: {
|
|
131
|
+
story:
|
|
132
|
+
"FOREIGN CONTRAST SPECIMEN (LC-56 STORY-HONESTY). The right column is the raw " +
|
|
133
|
+
"tamagui Input, rendered for contrast only: it ignores house knobs and field " +
|
|
134
|
+
"recipes by design. Probes asserting house rendering must skip this story.",
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
},
|
|
119
138
|
render: () => {
|
|
120
139
|
const ComparisonExample = () => {
|
|
121
140
|
const [customVal, setCustomVal] = useState("");
|
|
@@ -169,7 +169,26 @@ export const Interactive: Story = {
|
|
|
169
169
|
},
|
|
170
170
|
};
|
|
171
171
|
|
|
172
|
+
/**
|
|
173
|
+
* FOREIGN CONTRAST SPECIMEN (LC-56 STORY-HONESTY): the right column renders the
|
|
174
|
+
* RAW tamagui Progress beside the house Progress strictly so the difference
|
|
175
|
+
* stays visible. Raw primitives here are by design and labeled — knob/contrast
|
|
176
|
+
* probes skip this story via `parameters.foreignContrastSpecimen`.
|
|
177
|
+
*/
|
|
172
178
|
export const Comparison: Story = {
|
|
179
|
+
name: "Foreign contrast specimen (raw tamagui)",
|
|
180
|
+
parameters: {
|
|
181
|
+
// Machine-readable exemption for knob/contrast probes and the LC-56 linter arm.
|
|
182
|
+
foreignContrastSpecimen: true,
|
|
183
|
+
docs: {
|
|
184
|
+
description: {
|
|
185
|
+
story:
|
|
186
|
+
"FOREIGN CONTRAST SPECIMEN (LC-56 STORY-HONESTY). The right column is the raw " +
|
|
187
|
+
"tamagui Progress, rendered for contrast only: it ignores house knobs and " +
|
|
188
|
+
"recipes by design. Probes asserting house rendering must skip this story.",
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
},
|
|
173
192
|
render: () => (
|
|
174
193
|
<XStack gap="$6" alignItems="flex-start" padding="$4">
|
|
175
194
|
<YStack gap="$3" width={300}>
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import { useForm } from "@tanstack/react-form";
|
|
2
|
-
import { act, fireEvent, waitFor } from "@testing-library/react";
|
|
3
|
-
import { YStack } from "tamagui";
|
|
2
|
+
import { act, fireEvent, render, waitFor } from "@testing-library/react";
|
|
3
|
+
import { TamaguiProvider, YStack, createTamagui } from "tamagui";
|
|
4
4
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
5
5
|
import { renderWithProviders } from "@multiplatform.one/test-utils";
|
|
6
|
+
import {
|
|
7
|
+
createThemesBuilder,
|
|
8
|
+
defaultAccentTheme,
|
|
9
|
+
defaultBaseTheme,
|
|
10
|
+
defaultBuilderOptions,
|
|
11
|
+
} from "@multiplatform.one/theme";
|
|
12
|
+
import { configWithoutAnimations } from "@tamagui/config";
|
|
13
|
+
import { animationsCSS } from "@tamagui/config/v5-css";
|
|
6
14
|
import { Button } from "../../Button";
|
|
7
15
|
import { Form } from "../../Form";
|
|
8
16
|
import { RadioGroup } from "./index";
|
|
@@ -13,6 +21,21 @@ const mockOptions = [
|
|
|
13
21
|
{ label: "Option 3", value: "option3" },
|
|
14
22
|
];
|
|
15
23
|
|
|
24
|
+
// House builder themes for LC-05 mark assertions — created at MODULE scope:
|
|
25
|
+
// tamagui registers a config's theme variables globally at createTamagui
|
|
26
|
+
// time, and a config created after the first render (inside a test body)
|
|
27
|
+
// never resolves its tokens (Progress.spec pattern).
|
|
28
|
+
const houseThemes = createThemesBuilder(
|
|
29
|
+
defaultBaseTheme,
|
|
30
|
+
defaultAccentTheme,
|
|
31
|
+
defaultBuilderOptions,
|
|
32
|
+
).themes() as Record<string, Record<string, string>>;
|
|
33
|
+
const houseConfig = createTamagui({
|
|
34
|
+
...configWithoutAnimations,
|
|
35
|
+
animations: animationsCSS,
|
|
36
|
+
themes: houseThemes as any,
|
|
37
|
+
});
|
|
38
|
+
|
|
16
39
|
let consoleErrorSpy: ReturnType<typeof vi.spyOn> | null = null;
|
|
17
40
|
beforeEach(() => {
|
|
18
41
|
consoleErrorSpy = vi.spyOn(console, "error").mockImplementation((...args: unknown[]) => {
|
|
@@ -266,6 +289,95 @@ describe("RadioGroup Components", () => {
|
|
|
266
289
|
});
|
|
267
290
|
});
|
|
268
291
|
|
|
292
|
+
describe("late-arriving value display (create-mode seeding)", () => {
|
|
293
|
+
// The non-card variant fed the current value into tamagui as mount-only
|
|
294
|
+
// `defaultValue`, so a value applied AFTER first paint (create-mode
|
|
295
|
+
// engine seeding lands once meta loads) never displayed. The group must
|
|
296
|
+
// render controlled — and adopting a programmatic value must not emit
|
|
297
|
+
// onChange (LC-14: a seeded value is not a user edit).
|
|
298
|
+
const getRadioByValue = (container: ParentNode, value: string) =>
|
|
299
|
+
[...container.querySelectorAll("[role='radio']")].find((radio) =>
|
|
300
|
+
radio.id.endsWith(`-${value}`),
|
|
301
|
+
);
|
|
302
|
+
|
|
303
|
+
it("standalone controlled: a value arriving after mount renders checked, without onChange", async () => {
|
|
304
|
+
const onChange = vi.fn();
|
|
305
|
+
const onValueChange = vi.fn();
|
|
306
|
+
const result = renderWithProviders(
|
|
307
|
+
<RadioGroup
|
|
308
|
+
label="Status"
|
|
309
|
+
value=""
|
|
310
|
+
options={mockOptions}
|
|
311
|
+
onChange={onChange}
|
|
312
|
+
onValueChange={onValueChange}
|
|
313
|
+
/>,
|
|
314
|
+
);
|
|
315
|
+
for (const radio of result.container.querySelectorAll("[role='radio']")) {
|
|
316
|
+
expect(radio.getAttribute("aria-checked")).not.toBe("true");
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// Late seed: the upstream doc value arrives after first paint.
|
|
320
|
+
result.rerender(
|
|
321
|
+
<RadioGroup
|
|
322
|
+
label="Status"
|
|
323
|
+
value="option2"
|
|
324
|
+
options={mockOptions}
|
|
325
|
+
onChange={onChange}
|
|
326
|
+
onValueChange={onValueChange}
|
|
327
|
+
/>,
|
|
328
|
+
);
|
|
329
|
+
await waitFor(() => {
|
|
330
|
+
expect(getRadioByValue(result.container, "option2")?.getAttribute("aria-checked")).toBe(
|
|
331
|
+
"true",
|
|
332
|
+
);
|
|
333
|
+
});
|
|
334
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
335
|
+
expect(onValueChange).not.toHaveBeenCalled();
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
it("form-integrated: a field value set after mount renders checked, without onChange", async () => {
|
|
339
|
+
const onChange = vi.fn();
|
|
340
|
+
let formApi: { setFieldValue: (name: "option", value: string) => void } | undefined;
|
|
341
|
+
const TestComponent = () => {
|
|
342
|
+
const form = useForm({ defaultValues: { option: "" } });
|
|
343
|
+
formApi = form as unknown as typeof formApi;
|
|
344
|
+
return (
|
|
345
|
+
<Form form={form}>
|
|
346
|
+
<RadioGroup label="Status" name="option" options={mockOptions} onChange={onChange} />
|
|
347
|
+
</Form>
|
|
348
|
+
);
|
|
349
|
+
};
|
|
350
|
+
const result = renderWithProviders(<TestComponent />);
|
|
351
|
+
|
|
352
|
+
await act(async () => {
|
|
353
|
+
formApi?.setFieldValue("option", "option3");
|
|
354
|
+
});
|
|
355
|
+
await waitFor(() => {
|
|
356
|
+
expect(getRadioByValue(result.container, "option3")?.getAttribute("aria-checked")).toBe(
|
|
357
|
+
"true",
|
|
358
|
+
);
|
|
359
|
+
});
|
|
360
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
it("still emits exactly once for a real click after a late seed", async () => {
|
|
364
|
+
const onChange = vi.fn();
|
|
365
|
+
const result = renderWithProviders(
|
|
366
|
+
<RadioGroup label="Status" value="" options={mockOptions} onChange={onChange} />,
|
|
367
|
+
);
|
|
368
|
+
result.rerender(
|
|
369
|
+
<RadioGroup label="Status" value="option1" options={mockOptions} onChange={onChange} />,
|
|
370
|
+
);
|
|
371
|
+
const radio = getRadioByValue(result.container, "option2");
|
|
372
|
+
expect(radio).toBeTruthy();
|
|
373
|
+
await act(async () => {
|
|
374
|
+
if (radio) fireEvent.click(radio);
|
|
375
|
+
});
|
|
376
|
+
expect(onChange).toHaveBeenCalledTimes(1);
|
|
377
|
+
expect(onChange).toHaveBeenCalledWith("option2");
|
|
378
|
+
});
|
|
379
|
+
});
|
|
380
|
+
|
|
269
381
|
describe("card mode (LC-22 SELECTION-CARD)", () => {
|
|
270
382
|
const cardOptions = [
|
|
271
383
|
{ label: "Card A", value: "a", description: "Description for A" },
|
|
@@ -326,5 +438,30 @@ describe("RadioGroup Components", () => {
|
|
|
326
438
|
expect(new Set(ids).size).toBe(2);
|
|
327
439
|
});
|
|
328
440
|
});
|
|
441
|
+
|
|
442
|
+
describe("selected mark (LC-05 ONE-EMPHASIS / D-01)", () => {
|
|
443
|
+
it("paints the checked radio's indicator dot with the accent mark, never ink", () => {
|
|
444
|
+
const { container } = render(
|
|
445
|
+
<TamaguiProvider config={houseConfig} defaultTheme="light" disableInjectCSS>
|
|
446
|
+
<RadioGroup label="Choose" value="option2" options={mockOptions} />
|
|
447
|
+
</TamaguiProvider>,
|
|
448
|
+
);
|
|
449
|
+
const checked = container.querySelector('[role="radio"][aria-checked="true"]');
|
|
450
|
+
expect(checked).toBeTruthy();
|
|
451
|
+
// The indicator dot is the selection mark: it fills with the shared
|
|
452
|
+
// accent mark token ($accentBackground), not the ink/label tier.
|
|
453
|
+
const marked = Array.from(checked!.querySelectorAll("*")).filter((el) =>
|
|
454
|
+
(el as HTMLElement).className?.toString().includes("_bg-accentBackg"),
|
|
455
|
+
);
|
|
456
|
+
expect(marked.length).toBeGreaterThan(0);
|
|
457
|
+
// Unchecked radios render no accent mark.
|
|
458
|
+
const unchecked = container.querySelector('[role="radio"][aria-checked="false"]');
|
|
459
|
+
expect(unchecked).toBeTruthy();
|
|
460
|
+
const uncheckedMarked = Array.from(unchecked!.querySelectorAll("*")).filter((el) =>
|
|
461
|
+
(el as HTMLElement).className?.toString().includes("_bg-accentBackg"),
|
|
462
|
+
);
|
|
463
|
+
expect(uncheckedMarked.length).toBe(0);
|
|
464
|
+
});
|
|
465
|
+
});
|
|
329
466
|
});
|
|
330
467
|
});
|
|
@@ -280,7 +280,7 @@ export function RadioGroup({
|
|
|
280
280
|
borderWidth={radioRingWidth(knobProps.borderRadius.borderWidth)}
|
|
281
281
|
borderRadius={itemRadius}
|
|
282
282
|
outlined={knobProps.outlined}
|
|
283
|
-
{...(knobProps.transition ? {
|
|
283
|
+
{...(knobProps.transition ? { transition: knobProps.transition } : undefined)}
|
|
284
284
|
>
|
|
285
285
|
<RadioIndicatorFrame
|
|
286
286
|
borderRadius={indicatorRadius}
|
|
@@ -288,7 +288,7 @@ export function RadioGroup({
|
|
|
288
288
|
// accent — `textAccentColor` is the LABEL ink tier ($color/$color11)
|
|
289
289
|
// and made the checked radio read as ink, not as chosen (D-01).
|
|
290
290
|
backgroundColor={formSelectedColors.mark}
|
|
291
|
-
{...(knobProps.transition ? {
|
|
291
|
+
{...(knobProps.transition ? { transition: knobProps.transition } : undefined)}
|
|
292
292
|
/>
|
|
293
293
|
</RadioGlyph>
|
|
294
294
|
);
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import { describe, expect, it, vi } from "vitest";
|
|
2
|
-
import { fireEvent } from "@testing-library/react";
|
|
2
|
+
import { fireEvent, render } from "@testing-library/react";
|
|
3
3
|
import { renderWithProviders } from "@multiplatform.one/test-utils";
|
|
4
|
+
import {
|
|
5
|
+
createThemesBuilder,
|
|
6
|
+
defaultAccentTheme,
|
|
7
|
+
defaultBaseTheme,
|
|
8
|
+
defaultBuilderOptions,
|
|
9
|
+
} from "@multiplatform.one/theme";
|
|
10
|
+
import { configWithoutAnimations } from "@tamagui/config";
|
|
11
|
+
import { animationsCSS } from "@tamagui/config/v5-css";
|
|
12
|
+
import { TamaguiProvider, createTamagui } from "tamagui";
|
|
4
13
|
import { Form } from "../../Form";
|
|
5
14
|
import { Rating } from "./index";
|
|
6
15
|
|
|
@@ -8,6 +17,21 @@ const MockStarIcon = ({ size, weight, color }: { size: number; weight: string; c
|
|
|
8
17
|
<span data-testid="star" data-size={size} data-weight={weight} data-color={color} />
|
|
9
18
|
);
|
|
10
19
|
|
|
20
|
+
// House builder themes for the LC-05 mark assertion — created at MODULE
|
|
21
|
+
// scope: tamagui registers a config's theme variables globally at
|
|
22
|
+
// createTamagui time, and a config created after the first render (inside a
|
|
23
|
+
// test body) never resolves its tokens (Progress.spec pattern).
|
|
24
|
+
const houseThemes = createThemesBuilder(
|
|
25
|
+
defaultBaseTheme,
|
|
26
|
+
defaultAccentTheme,
|
|
27
|
+
defaultBuilderOptions,
|
|
28
|
+
).themes() as Record<string, Record<string, string>>;
|
|
29
|
+
const houseConfig = createTamagui({
|
|
30
|
+
...configWithoutAnimations,
|
|
31
|
+
animations: animationsCSS,
|
|
32
|
+
themes: houseThemes as any,
|
|
33
|
+
});
|
|
34
|
+
|
|
11
35
|
describe("Rating", () => {
|
|
12
36
|
describe("without form context", () => {
|
|
13
37
|
it("renders with label", () => {
|
|
@@ -97,6 +121,24 @@ describe("Rating", () => {
|
|
|
97
121
|
expect(star.getAttribute("aria-disabled")).toBe("true");
|
|
98
122
|
}
|
|
99
123
|
});
|
|
124
|
+
|
|
125
|
+
// LC-05 ONE-EMPHASIS / D-01: the FILLED star is the selection mark, so it
|
|
126
|
+
// resolves the shared accent mark token; the empty star stays neutral
|
|
127
|
+
// chrome. Stock test themes carry no $accentBackground, so mount the
|
|
128
|
+
// house builder themes for real resolution.
|
|
129
|
+
it("fills selected stars with the accent mark and empty stars with neutral chrome", () => {
|
|
130
|
+
const { container } = render(
|
|
131
|
+
<TamaguiProvider config={houseConfig} defaultTheme="light" disableInjectCSS>
|
|
132
|
+
<Rating label="Rate" value={0.6} starIcon={MockStarIcon} />
|
|
133
|
+
</TamaguiProvider>,
|
|
134
|
+
);
|
|
135
|
+
const filled = container.querySelector("[data-rating-star='filled'] [data-testid='star']");
|
|
136
|
+
const empty = container.querySelector("[data-rating-star='empty'] [data-testid='star']");
|
|
137
|
+
expect(filled).toBeTruthy();
|
|
138
|
+
expect(empty).toBeTruthy();
|
|
139
|
+
expect(filled!.getAttribute("data-color")).toContain("accentBackground");
|
|
140
|
+
expect(empty!.getAttribute("data-color")).not.toContain("accentBackground");
|
|
141
|
+
});
|
|
100
142
|
});
|
|
101
143
|
|
|
102
144
|
describe("with form context", () => {
|
|
@@ -49,7 +49,10 @@ function PointyStar({
|
|
|
49
49
|
<Svg width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
|
|
50
50
|
<Path
|
|
51
51
|
d={d}
|
|
52
|
-
|
|
52
|
+
// `transparent` rather than `none`: an empty->filled star has to
|
|
53
|
+
// interpolate its fill (LC-25), and `none` is not a colour so it can
|
|
54
|
+
// only jump. Paints identically.
|
|
55
|
+
fill={weight === "fill" ? color : "transparent"}
|
|
53
56
|
stroke={color}
|
|
54
57
|
strokeWidth={1.5}
|
|
55
58
|
strokeLinejoin="miter"
|
|
@@ -80,6 +83,32 @@ function getTransitionStyle(transition: TransitionProp | undefined, live: boolea
|
|
|
80
83
|
};
|
|
81
84
|
}
|
|
82
85
|
|
|
86
|
+
// LC-25, star ink: the visible change is the SVG `fill`/`stroke` of the glyph
|
|
87
|
+
// CHILD, and `transition` does not inherit — a declaration on the wrapper can
|
|
88
|
+
// never reach it, while the swappable `starIcon` contract ({ size, weight,
|
|
89
|
+
// color }) has no style passthrough to declare it on. A one-shot descendant
|
|
90
|
+
// stylesheet (Spinner/Wheel pattern) arms the tween on whatever glyph the
|
|
91
|
+
// contract renders, so the contract itself stays untouched.
|
|
92
|
+
const INK_STYLE_ID = "mp1-rating-ink";
|
|
93
|
+
const inkClassName = (token: string) => `mp1-rating-ink-${token}`;
|
|
94
|
+
function ensureRatingInkStyles() {
|
|
95
|
+
if (!isWeb || typeof document === "undefined") return;
|
|
96
|
+
if (document.getElementById(INK_STYLE_ID)) return;
|
|
97
|
+
const style = document.createElement("style");
|
|
98
|
+
style.id = INK_STYLE_ID;
|
|
99
|
+
// Shape elements only, never the <svg> root: a Phosphor-shaped glyph paints
|
|
100
|
+
// the root's `fill` and the shape INHERITS it, so arming both would leave
|
|
101
|
+
// the shape chasing an already-animating value and stretch the tween well
|
|
102
|
+
// past the token.
|
|
103
|
+
style.textContent = Object.entries(cssTimings)
|
|
104
|
+
.map(
|
|
105
|
+
([token, timing]) =>
|
|
106
|
+
`.${inkClassName(token)} svg * { transition: fill ${timing}, stroke ${timing}; }`,
|
|
107
|
+
)
|
|
108
|
+
.join("\n");
|
|
109
|
+
document.head.appendChild(style);
|
|
110
|
+
}
|
|
111
|
+
|
|
83
112
|
const StarWrapper = styled(View, {
|
|
84
113
|
variants: {
|
|
85
114
|
filled: {
|
|
@@ -124,10 +153,19 @@ function StarRow({
|
|
|
124
153
|
const [scrubFilled, setScrubFilled] = useState<number | null>(null);
|
|
125
154
|
const scrubbing = scrubFilled != null;
|
|
126
155
|
const displayFilled = scrubFilled ?? filledStars;
|
|
127
|
-
// LC-25: discrete star jumps tween via knob transition
|
|
128
|
-
//
|
|
129
|
-
|
|
156
|
+
// LC-25: discrete star jumps tween via knob transition. During pointer
|
|
157
|
+
// scrub, omit transition so fill tracks the pointer 1:1. `transition` is
|
|
158
|
+
// undefined exactly at animation="none" (which prefers-reduced-motion maps
|
|
159
|
+
// onto), and Axiom 3 says that position is NO motion — not a default one.
|
|
160
|
+
const motionTransition = knobProps.transition as TransitionProp | undefined;
|
|
130
161
|
const live = scrubbing;
|
|
162
|
+
ensureRatingInkStyles();
|
|
163
|
+
const inkToken =
|
|
164
|
+
isWeb && !live && motionTransition
|
|
165
|
+
? (motionTransition as string) in cssTimings
|
|
166
|
+
? (motionTransition as string)
|
|
167
|
+
: "quick"
|
|
168
|
+
: undefined;
|
|
131
169
|
|
|
132
170
|
// DG-A11Y keyboard operability: one roving tab stop (ToggleGroup pattern —
|
|
133
171
|
// a group of N buttons is one Tab entry, arrows move within). The stop
|
|
@@ -227,6 +265,7 @@ function StarRow({
|
|
|
227
265
|
data-rating-star={isFilled ? "filled" : "empty"}
|
|
228
266
|
data-rating-index={starNumber}
|
|
229
267
|
{...(!isWeb && !live ? { transition: motionTransition } : {})}
|
|
268
|
+
{...(inkToken ? { className: inkClassName(inkToken) } : undefined)}
|
|
230
269
|
style={getTransitionStyle(live ? undefined : motionTransition, live)}
|
|
231
270
|
>
|
|
232
271
|
<StarIcon
|
|
@@ -21,6 +21,17 @@ describe("SearchInput", () => {
|
|
|
21
21
|
expect(result.container.querySelector("svg")).toBeTruthy();
|
|
22
22
|
});
|
|
23
23
|
|
|
24
|
+
it("bidi-isolates the default placeholder (LC-58) and passes explicit ones through", () => {
|
|
25
|
+
// Default: FSI…PDI framing so the trailing "..." cannot reorder to
|
|
26
|
+
// "…Search" under RTL; the visible run stays byte-identical inside.
|
|
27
|
+
const result = renderWithProviders(<SearchInput />);
|
|
28
|
+
const input = result.container.querySelector("input");
|
|
29
|
+
expect(input?.getAttribute("placeholder")).toBe("\u2068Search...\u2069");
|
|
30
|
+
// Explicit placeholders are the consumer's interpolation site — the
|
|
31
|
+
// component must not double-wrap or mutate them (asserted above too).
|
|
32
|
+
expect(input?.getAttribute("placeholder")?.slice(1, -1)).toBe("Search...");
|
|
33
|
+
});
|
|
34
|
+
|
|
24
35
|
it("fires onChange per keystroke and onSearch after debounce", () => {
|
|
25
36
|
const onChange = vi.fn();
|
|
26
37
|
const onSearch = vi.fn();
|
|
@@ -12,7 +12,7 @@ import type { ReactNode } from "react";
|
|
|
12
12
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
13
13
|
import type { SizeTokens } from "tamagui";
|
|
14
14
|
import { View } from "tamagui";
|
|
15
|
-
import { t } from "../../shared/t";
|
|
15
|
+
import { bidiIsolate, t } from "../../shared/t";
|
|
16
16
|
import { Input } from "../Input";
|
|
17
17
|
import type { InputProps } from "../Input";
|
|
18
18
|
|
|
@@ -60,7 +60,11 @@ export function SearchInput({
|
|
|
60
60
|
onSearch,
|
|
61
61
|
onClear,
|
|
62
62
|
debounceMs = 300,
|
|
63
|
-
|
|
63
|
+
// Bidi-isolated at the interpolation site (LC-58): under RTL the trailing
|
|
64
|
+
// weak "..." otherwise reorders to the start ("…Search"). First-strong
|
|
65
|
+
// isolation keeps a translated RTL placeholder rendering RTL. Consumer
|
|
66
|
+
// placeholders are the consumer's interpolation site — passed through.
|
|
67
|
+
placeholder = bidiIsolate(t("Search...")),
|
|
64
68
|
clearable = true,
|
|
65
69
|
disabled,
|
|
66
70
|
size,
|
|
@@ -303,7 +303,26 @@ export const DynamicOptions: StoryObj<typeof Select> = {
|
|
|
303
303
|
},
|
|
304
304
|
};
|
|
305
305
|
|
|
306
|
+
/**
|
|
307
|
+
* FOREIGN CONTRAST SPECIMEN (LC-56 STORY-HONESTY): the right column renders the
|
|
308
|
+
* RAW tamagui Select beside the house Select strictly so the difference stays
|
|
309
|
+
* visible. Raw primitives here are by design and labeled — knob/contrast probes
|
|
310
|
+
* skip this story via `parameters.foreignContrastSpecimen`.
|
|
311
|
+
*/
|
|
306
312
|
export const Comparison: StoryObj<typeof Select> = {
|
|
313
|
+
name: "Foreign contrast specimen (raw tamagui)",
|
|
314
|
+
parameters: {
|
|
315
|
+
// Machine-readable exemption for knob/contrast probes and the LC-56 linter arm.
|
|
316
|
+
foreignContrastSpecimen: true,
|
|
317
|
+
docs: {
|
|
318
|
+
description: {
|
|
319
|
+
story:
|
|
320
|
+
"FOREIGN CONTRAST SPECIMEN (LC-56 STORY-HONESTY). The right column is the raw " +
|
|
321
|
+
"tamagui Select, rendered for contrast only: it ignores house knobs and control " +
|
|
322
|
+
"recipes by design. Probes asserting house rendering must skip this story.",
|
|
323
|
+
},
|
|
324
|
+
},
|
|
325
|
+
},
|
|
307
326
|
render: () => {
|
|
308
327
|
const ComparisonExample = () => {
|
|
309
328
|
const [customValue, setCustomValue] = useState<string>();
|
|
@@ -311,7 +311,7 @@ const SelectItem = memo(function SelectItem({
|
|
|
311
311
|
: formInputColors.background.focus,
|
|
312
312
|
},
|
|
313
313
|
})}
|
|
314
|
-
{...(ctx.knobProps.transition ? {
|
|
314
|
+
{...(ctx.knobProps.transition ? { transition: ctx.knobProps.transition } : undefined)}
|
|
315
315
|
>
|
|
316
316
|
<Text
|
|
317
317
|
fontFamily={ctx.knobProps.body.fontFamily}
|
|
@@ -839,9 +839,14 @@ function FloatingSelectCore({
|
|
|
839
839
|
cursor="pointer"
|
|
840
840
|
disabled={disabled}
|
|
841
841
|
size={knobProps.sizeToken}
|
|
842
|
+
// LC-54 PRESS-FLOOR: the size knob may shrink chrome (compact → $3
|
|
843
|
+
// = 36px) but the trigger's press target never drops below 44 —
|
|
844
|
+
// same minHeight floor the house Button holds. Without it a compact
|
|
845
|
+
// Select sat 36px beside 44px Inputs/Buttons in one control row.
|
|
846
|
+
minHeight={44}
|
|
842
847
|
{...(inTableCell
|
|
843
|
-
? // Chromeless in cells
|
|
844
|
-
{
|
|
848
|
+
? // Chromeless in cells (the floor above still applies).
|
|
849
|
+
{}
|
|
845
850
|
: {
|
|
846
851
|
borderRadius: knobProps.borderRadius.borderRadius,
|
|
847
852
|
borderWidth: knobProps.borderRadius.borderWidth,
|
|
@@ -1257,9 +1262,11 @@ function NativeSelectCore({
|
|
|
1257
1262
|
<InputParts.Box
|
|
1258
1263
|
disabled={disabled}
|
|
1259
1264
|
size={knobProps.sizeToken}
|
|
1265
|
+
// LC-54 PRESS-FLOOR: ≥44px trigger target at every size (matches
|
|
1266
|
+
// the web trigger branch above).
|
|
1267
|
+
minHeight={44}
|
|
1260
1268
|
{...(inTableCell
|
|
1261
|
-
?
|
|
1262
|
-
{ minHeight: 44 }
|
|
1269
|
+
? {}
|
|
1263
1270
|
: {
|
|
1264
1271
|
borderRadius: knobProps.borderRadius.borderRadius,
|
|
1265
1272
|
borderWidth: knobProps.borderRadius.borderWidth,
|
|
@@ -454,7 +454,7 @@ function SignatureCanvasImpl({
|
|
|
454
454
|
opacity={disabled ? 0.6 : 1}
|
|
455
455
|
aspectRatio={aspectRatio}
|
|
456
456
|
minHeight={minHeightPx}
|
|
457
|
-
{...(knobProps.transition ? {
|
|
457
|
+
{...(knobProps.transition ? { transition: knobProps.transition } : undefined)}
|
|
458
458
|
aria-required={required || undefined}
|
|
459
459
|
aria-invalid={hasError || undefined}
|
|
460
460
|
>
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
1
2
|
import { useForm } from "@tanstack/react-form";
|
|
2
3
|
import { act, fireEvent, renderHook, waitFor } from "@testing-library/react";
|
|
3
4
|
import { getSize } from "@tamagui/get-token";
|
|
@@ -205,6 +206,76 @@ describe("Slider", () => {
|
|
|
205
206
|
});
|
|
206
207
|
});
|
|
207
208
|
|
|
209
|
+
describe("late-arriving value display (create-mode seeding)", () => {
|
|
210
|
+
// The upstream value was fed into tamagui as mount-only `defaultValue`,
|
|
211
|
+
// so a value applied AFTER first paint (create-mode engine seeding,
|
|
212
|
+
// form.setFieldValue, live server merge) never moved the thumb. The
|
|
213
|
+
// slider must run controlled when an upstream value drives it — and
|
|
214
|
+
// adopting a programmatic value must not emit onChange (LC-14: a seeded
|
|
215
|
+
// value is not a user edit).
|
|
216
|
+
const getThumb = (container: ParentNode) =>
|
|
217
|
+
container.querySelector('[role="slider"]') as HTMLElement | null;
|
|
218
|
+
|
|
219
|
+
it("standalone controlled: a value arriving after mount renders, without onChange", async () => {
|
|
220
|
+
const onChange = vi.fn();
|
|
221
|
+
const onValueChange = vi.fn();
|
|
222
|
+
const result = renderWithProviders(
|
|
223
|
+
<Slider label="Progress" value={[25]} onChange={onChange} onValueChange={onValueChange} />,
|
|
224
|
+
);
|
|
225
|
+
expect(getThumb(result.container)?.getAttribute("aria-valuenow")).toBe("25");
|
|
226
|
+
|
|
227
|
+
// Late seed: the upstream doc value arrives after first paint.
|
|
228
|
+
result.rerender(
|
|
229
|
+
<Slider label="Progress" value={[75]} onChange={onChange} onValueChange={onValueChange} />,
|
|
230
|
+
);
|
|
231
|
+
await waitFor(() => {
|
|
232
|
+
expect(getThumb(result.container)?.getAttribute("aria-valuenow")).toBe("75");
|
|
233
|
+
});
|
|
234
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
235
|
+
expect(onValueChange).not.toHaveBeenCalled();
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
it("form-integrated: a field value set after mount renders, without onChange", async () => {
|
|
239
|
+
const onChange = vi.fn();
|
|
240
|
+
let formApi: { setFieldValue: (name: "volume", value: number[]) => void } | undefined;
|
|
241
|
+
const TestComponent = () => {
|
|
242
|
+
const form = useForm({ defaultValues: { volume: [10] } });
|
|
243
|
+
formApi = form as unknown as typeof formApi;
|
|
244
|
+
return (
|
|
245
|
+
<Form form={form}>
|
|
246
|
+
<Slider label="Volume" name="volume" onChange={onChange} />
|
|
247
|
+
</Form>
|
|
248
|
+
);
|
|
249
|
+
};
|
|
250
|
+
const result = renderWithProviders(<TestComponent />);
|
|
251
|
+
expect(getThumb(result.container)?.getAttribute("aria-valuenow")).toBe("10");
|
|
252
|
+
|
|
253
|
+
await act(async () => {
|
|
254
|
+
formApi?.setFieldValue("volume", [60]);
|
|
255
|
+
});
|
|
256
|
+
await waitFor(() => {
|
|
257
|
+
expect(getThumb(result.container)?.getAttribute("aria-valuenow")).toBe("60");
|
|
258
|
+
});
|
|
259
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
it("uncontrolled standalone (defaultValue only) still moves on keyboard input", async () => {
|
|
263
|
+
const onChange = vi.fn();
|
|
264
|
+
const result = renderWithProviders(
|
|
265
|
+
<Slider label="Free" defaultValue={[40]} onChange={onChange} />,
|
|
266
|
+
);
|
|
267
|
+
const thumb = getThumb(result.container);
|
|
268
|
+
expect(thumb?.getAttribute("aria-valuenow")).toBe("40");
|
|
269
|
+
await act(async () => {
|
|
270
|
+
if (thumb) fireEvent.keyDown(thumb, { key: "ArrowRight" });
|
|
271
|
+
});
|
|
272
|
+
await waitFor(() => {
|
|
273
|
+
expect(getThumb(result.container)?.getAttribute("aria-valuenow")).toBe("41");
|
|
274
|
+
});
|
|
275
|
+
expect(onChange).toHaveBeenCalledWith([41]);
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
|
|
208
279
|
describe("field integration", () => {
|
|
209
280
|
it("should render error text when provided", () => {
|
|
210
281
|
const result = renderWithProviders(
|
|
@@ -688,10 +759,24 @@ describe("Slider", () => {
|
|
|
688
759
|
});
|
|
689
760
|
|
|
690
761
|
it("track click arms the left/transform tween then disarms after the jump window", async () => {
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
)
|
|
762
|
+
// Controlled slider with the standard feedback loop (value + onChange
|
|
763
|
+
// echoing back) — a bare static `value` is a frozen controlled input
|
|
764
|
+
// now that the upstream value really drives tamagui.
|
|
765
|
+
const JumpExample = () => {
|
|
766
|
+
const [values, setValues] = useState([60]);
|
|
767
|
+
return (
|
|
768
|
+
// min > 0 so the degenerate unmeasured-layout pointer value stays truthy
|
|
769
|
+
<Slider
|
|
770
|
+
label="Jump"
|
|
771
|
+
name="jump"
|
|
772
|
+
value={values}
|
|
773
|
+
onChange={setValues}
|
|
774
|
+
min={10}
|
|
775
|
+
max={110}
|
|
776
|
+
/>
|
|
777
|
+
);
|
|
778
|
+
};
|
|
779
|
+
const result = renderWithProviders(<JumpExample />);
|
|
695
780
|
const thumb = result.container.querySelector('[role="slider"]') as HTMLElement;
|
|
696
781
|
const track = getTrack(result.container, thumb);
|
|
697
782
|
expect(track).toBeDefined();
|
|
@@ -199,7 +199,26 @@ export const Interactive: Story = {
|
|
|
199
199
|
},
|
|
200
200
|
};
|
|
201
201
|
|
|
202
|
+
/**
|
|
203
|
+
* FOREIGN CONTRAST SPECIMEN (LC-56 STORY-HONESTY): the right column renders the
|
|
204
|
+
* RAW tamagui Slider beside the house Slider strictly so the difference stays
|
|
205
|
+
* visible. Raw primitives here are by design and labeled — knob/contrast probes
|
|
206
|
+
* skip this story via `parameters.foreignContrastSpecimen`.
|
|
207
|
+
*/
|
|
202
208
|
export const Comparison: Story = {
|
|
209
|
+
name: "Foreign contrast specimen (raw tamagui)",
|
|
210
|
+
parameters: {
|
|
211
|
+
// Machine-readable exemption for knob/contrast probes and the LC-56 linter arm.
|
|
212
|
+
foreignContrastSpecimen: true,
|
|
213
|
+
docs: {
|
|
214
|
+
description: {
|
|
215
|
+
story:
|
|
216
|
+
"FOREIGN CONTRAST SPECIMEN (LC-56 STORY-HONESTY). The right column is the raw " +
|
|
217
|
+
"tamagui Slider, rendered for contrast only: it ignores house knobs and control " +
|
|
218
|
+
"recipes by design. Probes asserting house rendering must skip this story.",
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
},
|
|
203
222
|
render: () => {
|
|
204
223
|
const ComparisonExample = () => {
|
|
205
224
|
const [customVal, setCustomVal] = useState([50]);
|