@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
|
@@ -119,7 +119,26 @@ export const CompoundPattern: Story = {
|
|
|
119
119
|
),
|
|
120
120
|
};
|
|
121
121
|
|
|
122
|
+
/**
|
|
123
|
+
* FOREIGN CONTRAST SPECIMEN (LC-56 STORY-HONESTY): the right column renders the
|
|
124
|
+
* RAW tamagui Button beside the house Button strictly so the difference stays
|
|
125
|
+
* visible. Raw primitives here are by design and labeled — knob/contrast probes
|
|
126
|
+
* skip this story via `parameters.foreignContrastSpecimen`.
|
|
127
|
+
*/
|
|
122
128
|
export const Comparison: Story = {
|
|
129
|
+
name: "Foreign contrast specimen (raw tamagui)",
|
|
130
|
+
parameters: {
|
|
131
|
+
// Machine-readable exemption for knob/contrast probes and the LC-56 linter arm.
|
|
132
|
+
foreignContrastSpecimen: true,
|
|
133
|
+
docs: {
|
|
134
|
+
description: {
|
|
135
|
+
story:
|
|
136
|
+
"FOREIGN CONTRAST SPECIMEN (LC-56 STORY-HONESTY). The right column is the raw " +
|
|
137
|
+
"tamagui Button, rendered for contrast only: it ignores house knobs and intent " +
|
|
138
|
+
"recipes by design. Probes asserting house rendering must skip this story.",
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
},
|
|
123
142
|
render: () => (
|
|
124
143
|
<XStack gap="$6" alignItems="flex-start" padding="$4" flexWrap="wrap">
|
|
125
144
|
<YStack gap="$3" width={200}>
|
package/src/Button/index.tsx
CHANGED
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
type ButtonProps as TamaguiButtonProps,
|
|
20
20
|
SizableText,
|
|
21
21
|
View,
|
|
22
|
+
XStack,
|
|
22
23
|
YStack,
|
|
23
24
|
Theme,
|
|
24
25
|
styled,
|
|
@@ -173,6 +174,14 @@ export interface ButtonProps extends Omit<TamaguiButtonProps, "form" | "icon" |
|
|
|
173
174
|
* — bare `disabled` emits `bare-disabled`.
|
|
174
175
|
*/
|
|
175
176
|
disabledReason?: string;
|
|
177
|
+
/**
|
|
178
|
+
* Where the visible reason renders relative to the control. `"below"`
|
|
179
|
+
* (default) stacks it under the button — right for forms and vertical
|
|
180
|
+
* layouts. `"inline"` puts it beside the button on the same line — for
|
|
181
|
+
* toolbar/control rows, where a stacked reason breaks the row's shared
|
|
182
|
+
* control height and wraps into cramped multi-line type.
|
|
183
|
+
*/
|
|
184
|
+
disabledReasonPlacement?: "below" | "inline";
|
|
176
185
|
}
|
|
177
186
|
|
|
178
187
|
export function Button({
|
|
@@ -198,6 +207,7 @@ export function Button({
|
|
|
198
207
|
noun,
|
|
199
208
|
actionRole,
|
|
200
209
|
disabledReason,
|
|
210
|
+
disabledReasonPlacement = "below",
|
|
201
211
|
...props
|
|
202
212
|
}: ButtonProps) {
|
|
203
213
|
const { resolvedForm: formFromHook } = useFormField({ form: formProp });
|
|
@@ -360,6 +370,15 @@ export function Button({
|
|
|
360
370
|
: isCircular
|
|
361
371
|
? { minWidth: MIN_PRESS_TARGET, minHeight: MIN_PRESS_TARGET }
|
|
362
372
|
: { minHeight: MIN_PRESS_TARGET };
|
|
373
|
+
// Axiom 3 NULL / LC-18: `circular` is a SHAPE eject, not a radius eject —
|
|
374
|
+
// a Button is R-SCALE, so in the square world (`borderRadius:none`) it goes
|
|
375
|
+
// square like every other control. The tamagui `circular` variant expands
|
|
376
|
+
// to a ~100000 radius that beats a plain borderRadius prop, so this rides
|
|
377
|
+
// an inline style (same idiom as the DatePicker day cell). Without it every
|
|
378
|
+
// `circular` Button in the catalog is an undeclared knob-immune shape
|
|
379
|
+
// (D-09 / LC-60 sweep finding: Pagination prev/next).
|
|
380
|
+
const circularSquareAtNone =
|
|
381
|
+
isCircular && knobProps.pointy ? { style: { borderRadius: 0 } } : null;
|
|
363
382
|
const buttonElement = (
|
|
364
383
|
<ButtonFrame
|
|
365
384
|
// DG-ST-03: an explained disable is aria-disabled (focusable, press
|
|
@@ -427,6 +446,7 @@ export function Button({
|
|
|
427
446
|
{...(tabIndex != null ? { tabIndex } : undefined)}
|
|
428
447
|
{...props}
|
|
429
448
|
{...circularPressFloor}
|
|
449
|
+
{...circularSquareAtNone}
|
|
430
450
|
{...(explainedDisable
|
|
431
451
|
? {
|
|
432
452
|
// No `title`: hover-only reveals are banned on disabled controls
|
|
@@ -466,19 +486,32 @@ export function Button({
|
|
|
466
486
|
|
|
467
487
|
// DG-ST-03 explain affordance: visible reason adjacent to the control —
|
|
468
488
|
// discoverable by pointer, touch, keyboard, and SR (aria-describedby)
|
|
469
|
-
// without any hover interaction (Axiom 12).
|
|
489
|
+
// without any hover interaction (Axiom 12). "below" stacks (forms);
|
|
490
|
+
// "inline" keeps toolbar rows on one shared control line, where the
|
|
491
|
+
// stacked reason wrapped into cramped multi-line type under the button.
|
|
492
|
+
const reasonText = explainedDisable ? (
|
|
493
|
+
<SizableText
|
|
494
|
+
id={reasonId}
|
|
495
|
+
size="$2"
|
|
496
|
+
color={formCommonColors.muted}
|
|
497
|
+
flexShrink={1}
|
|
498
|
+
data-mp-disabled-reason="true"
|
|
499
|
+
>
|
|
500
|
+
{disabledReason}
|
|
501
|
+
</SizableText>
|
|
502
|
+
) : null;
|
|
470
503
|
const explainedElement = explainedDisable ? (
|
|
471
|
-
|
|
472
|
-
{
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
{
|
|
480
|
-
</
|
|
481
|
-
|
|
504
|
+
disabledReasonPlacement === "inline" ? (
|
|
505
|
+
<XStack gap="$2" alignItems="center" flexShrink={1} data-mp-disabled-reason-wrapper="true">
|
|
506
|
+
{buttonElement}
|
|
507
|
+
{reasonText}
|
|
508
|
+
</XStack>
|
|
509
|
+
) : (
|
|
510
|
+
<YStack gap="$1" flexShrink={1} data-mp-disabled-reason-wrapper="true">
|
|
511
|
+
{buttonElement}
|
|
512
|
+
{reasonText}
|
|
513
|
+
</YStack>
|
|
514
|
+
)
|
|
482
515
|
) : (
|
|
483
516
|
buttonElement
|
|
484
517
|
);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { GuardrailSpecimenParameter } from "@multiplatform.one/theme";
|
|
1
2
|
import type { Meta, StoryObj } from "@storybook/react-native-web-vite";
|
|
2
3
|
import { Input as TamaguiInput, Paragraph, YStack } from "tamagui";
|
|
3
4
|
import { Button } from "../Button";
|
|
@@ -69,6 +70,17 @@ export const ChildCounts: Story = {
|
|
|
69
70
|
};
|
|
70
71
|
|
|
71
72
|
export const MixedControls: Story = {
|
|
73
|
+
parameters: {
|
|
74
|
+
// LC-57 allowlist: the middle group deliberately shows a disabled segment
|
|
75
|
+
// inside a joined strip. ControlGroup styles its DIRECT children by index,
|
|
76
|
+
// so Button's visible disabledReason wrapper cannot ride along without
|
|
77
|
+
// breaking the strip geometry — the same no-room class as icon toolbars.
|
|
78
|
+
guardrailSpecimen: {
|
|
79
|
+
warns: ["bare-disabled"],
|
|
80
|
+
reason:
|
|
81
|
+
"Disabled-segment specimen: a joined ControlGroup strip has no room for the visible reason line.",
|
|
82
|
+
} satisfies GuardrailSpecimenParameter,
|
|
83
|
+
},
|
|
72
84
|
render: () => (
|
|
73
85
|
<YStack gap="$4" maxWidth={480}>
|
|
74
86
|
<ControlGroup>
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* either component.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { formatAbsoluteDate } from "@multiplatform.one/theme";
|
|
10
|
+
import { formatAbsoluteDate, formatCurrency, formatNumber } from "@multiplatform.one/theme";
|
|
11
11
|
|
|
12
12
|
export const EMPTY = "—";
|
|
13
13
|
|
|
@@ -27,24 +27,20 @@ export function asText(v: any): string {
|
|
|
27
27
|
|
|
28
28
|
export interface NumericFormatOptions {
|
|
29
29
|
precision?: number;
|
|
30
|
-
/** ISO 4217 currency code, e.g. "USD". */
|
|
30
|
+
/** ISO 4217 currency code (or a symbol a code is known for), e.g. "USD". */
|
|
31
31
|
currency?: string;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Read-only numeric cells speak the house number registers (LC-12 render
|
|
36
|
+
* channel): the same figure reads identically in a table cell, a KPI tile
|
|
37
|
+
* and a group aggregate. `precision` pins the fraction digits a Frappe field
|
|
38
|
+
* declares; the register owns everything else.
|
|
39
|
+
*/
|
|
34
40
|
export function formatNumericText(num: number, options: NumericFormatOptions = {}): string {
|
|
35
41
|
const { precision, currency } = options;
|
|
36
|
-
if (currency) {
|
|
37
|
-
|
|
38
|
-
style: "currency",
|
|
39
|
-
currency,
|
|
40
|
-
minimumFractionDigits: precision,
|
|
41
|
-
maximumFractionDigits: precision,
|
|
42
|
-
}).format(num);
|
|
43
|
-
}
|
|
44
|
-
return new Intl.NumberFormat(undefined, {
|
|
45
|
-
minimumFractionDigits: precision,
|
|
46
|
-
maximumFractionDigits: precision,
|
|
47
|
-
}).format(num);
|
|
42
|
+
if (currency) return formatCurrency(num, { precision, symbol: currency });
|
|
43
|
+
return formatNumber(num, { precision });
|
|
48
44
|
}
|
|
49
45
|
|
|
50
46
|
// Re-exported for existing consumers; the canonical shape lives in theme.
|
|
@@ -46,7 +46,8 @@ export const ErrorStates: Story = {
|
|
|
46
46
|
id="fl-err-string"
|
|
47
47
|
label="String error"
|
|
48
48
|
helperText="Helper should be hidden"
|
|
49
|
-
error
|
|
49
|
+
// DG-COPY-02: error copy states the rule broken — never "invalid"/"please"/"error".
|
|
50
|
+
error="Value must use letters only"
|
|
50
51
|
>
|
|
51
52
|
<TamaguiInput id="fl-err-string" />
|
|
52
53
|
</FieldLayout>
|
|
@@ -96,7 +97,7 @@ export const AnatomyEdgeCases: Story = {
|
|
|
96
97
|
<FieldLayout
|
|
97
98
|
id="fl-long"
|
|
98
99
|
label="Long messages"
|
|
99
|
-
error="This
|
|
100
|
+
error="This validation message is extremely long and keeps going to make sure long validation copy wraps correctly under the control without pushing the layout sideways or clipping any of its content at narrow widths"
|
|
100
101
|
>
|
|
101
102
|
<TamaguiInput id="fl-long" />
|
|
102
103
|
</FieldLayout>
|
|
@@ -224,9 +224,14 @@ export const DynamicFields = () => {
|
|
|
224
224
|
label="Account Type"
|
|
225
225
|
name="accountType"
|
|
226
226
|
required
|
|
227
|
+
// >5 options: shorter single-select lists trip `select-too-few-options` (DG-CTRL-01).
|
|
227
228
|
options={[
|
|
228
229
|
{ label: "Personal", value: "personal" },
|
|
229
230
|
{ label: "Business", value: "business" },
|
|
231
|
+
{ label: "Nonprofit", value: "nonprofit" },
|
|
232
|
+
{ label: "Government", value: "government" },
|
|
233
|
+
{ label: "Education", value: "education" },
|
|
234
|
+
{ label: "Other", value: "other" },
|
|
230
235
|
]}
|
|
231
236
|
/>
|
|
232
237
|
|
|
@@ -323,18 +328,26 @@ InputWithLinkResolver.parameters = {
|
|
|
323
328
|
},
|
|
324
329
|
};
|
|
325
330
|
|
|
331
|
+
// Six entries: still renders without scroll (the "short list" the story demos)
|
|
332
|
+
// while clearing the ≤5 `select-too-few-options` guardrail (DG-CTRL-01).
|
|
326
333
|
const shortPriorityOptions = [
|
|
334
|
+
{ value: "lowest", label: "Lowest" },
|
|
327
335
|
{ value: "low", label: "Low" },
|
|
328
336
|
{ value: "medium", label: "Medium" },
|
|
329
337
|
{ value: "high", label: "High" },
|
|
338
|
+
{ value: "highest", label: "Highest" },
|
|
339
|
+
{ value: "critical", label: "Critical" },
|
|
330
340
|
];
|
|
331
341
|
|
|
342
|
+
// Six entries: still the "short list" the story demos, while clearing the ≤5
|
|
343
|
+
// `select-too-few-options` guardrail (DG-CTRL-01).
|
|
332
344
|
const shortCountryOptions: ComboboxOption[] = [
|
|
333
345
|
{ value: "us", label: "United States", keywords: "usa america" },
|
|
334
346
|
{ value: "ca", label: "Canada", keywords: "north america" },
|
|
335
347
|
{ value: "uk", label: "United Kingdom", keywords: "britain england" },
|
|
336
348
|
{ value: "de", label: "Germany", keywords: "europe deutschland" },
|
|
337
349
|
{ value: "fr", label: "France", keywords: "europe paris" },
|
|
350
|
+
{ value: "jp", label: "Japan", keywords: "asia tokyo" },
|
|
338
351
|
];
|
|
339
352
|
|
|
340
353
|
const countryOptions: ComboboxOption[] = [
|
package/src/Skeleton/index.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useResolvedKnobs } from "@multiplatform.one/theme";
|
|
1
|
+
import { radiusClassProps, useResolvedKnobs } from "@multiplatform.one/theme";
|
|
2
2
|
import type { GetProps } from "tamagui";
|
|
3
3
|
import { View, styled, isWeb } from "tamagui";
|
|
4
4
|
|
|
@@ -107,6 +107,10 @@ export function Skeleton({
|
|
|
107
107
|
: variant === "text" && knobProps.pointy
|
|
108
108
|
? { borderRadius: 0 }
|
|
109
109
|
: undefined)}
|
|
110
|
+
// R-PILL (spec Skeleton "circle"): the circular variant stays 1:1 and
|
|
111
|
+
// round at every radius value, so it declares the class the
|
|
112
|
+
// `radius:none` sweep licenses it under (D-09 / LC-60).
|
|
113
|
+
{...(variant === "circular" ? radiusClassProps("R-PILL", "SkeletonCircle") : undefined)}
|
|
110
114
|
{...props}
|
|
111
115
|
{...(mergedStyle ? { style: mergedStyle } : undefined)}
|
|
112
116
|
/>
|
|
@@ -1,10 +1,34 @@
|
|
|
1
|
-
import { fireEvent } from "@testing-library/react";
|
|
1
|
+
import { fireEvent, render } from "@testing-library/react";
|
|
2
2
|
import { describe, expect, it, vi } from "vitest";
|
|
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 { Checkbox } from "./Checkbox";
|
|
6
15
|
import { CheckboxGroup } from "./CheckboxGroup";
|
|
7
16
|
|
|
17
|
+
// House builder themes for the LC-05 mark assertion — created at MODULE
|
|
18
|
+
// scope: tamagui registers a config's theme variables globally at
|
|
19
|
+
// createTamagui time, and a config created after the first render (inside a
|
|
20
|
+
// test body) never resolves its tokens (Progress.spec pattern).
|
|
21
|
+
const houseThemes = createThemesBuilder(
|
|
22
|
+
defaultBaseTheme,
|
|
23
|
+
defaultAccentTheme,
|
|
24
|
+
defaultBuilderOptions,
|
|
25
|
+
).themes() as Record<string, Record<string, string>>;
|
|
26
|
+
const houseConfig = createTamagui({
|
|
27
|
+
...configWithoutAnimations,
|
|
28
|
+
animations: animationsCSS,
|
|
29
|
+
themes: houseThemes as any,
|
|
30
|
+
});
|
|
31
|
+
|
|
8
32
|
describe("Checkbox", () => {
|
|
9
33
|
describe("without form context", () => {
|
|
10
34
|
it("renders with label", () => {
|
|
@@ -256,4 +280,29 @@ describe("CheckboxGroup", () => {
|
|
|
256
280
|
expect(new Set(ids).size).toBe(2);
|
|
257
281
|
});
|
|
258
282
|
});
|
|
283
|
+
|
|
284
|
+
describe("selected mark (LC-05 ONE-EMPHASIS / D-01 census addition)", () => {
|
|
285
|
+
it("fills the checked box with the accent mark; the unchecked box stays neutral chrome", () => {
|
|
286
|
+
const { container } = render(
|
|
287
|
+
<TamaguiProvider config={houseConfig} defaultTheme="light" disableInjectCSS>
|
|
288
|
+
<Checkbox label="Checked" checked />
|
|
289
|
+
<Checkbox label="Unchecked" checked={false} />
|
|
290
|
+
</TamaguiProvider>,
|
|
291
|
+
);
|
|
292
|
+
const boxes = Array.from(container.querySelectorAll('[role="checkbox"]'));
|
|
293
|
+
expect(boxes.length).toBe(2);
|
|
294
|
+
const checked = boxes.find((b) => b.getAttribute("aria-checked") === "true");
|
|
295
|
+
const unchecked = boxes.find((b) => b.getAttribute("aria-checked") === "false");
|
|
296
|
+
expect(checked).toBeTruthy();
|
|
297
|
+
expect(unchecked).toBeTruthy();
|
|
298
|
+
// The visible glyph box (a descendant of the 44px transparent target)
|
|
299
|
+
// carries the accent mark fill only while checked.
|
|
300
|
+
const marked = (root: Element) =>
|
|
301
|
+
Array.from(root.querySelectorAll("*")).filter((el) =>
|
|
302
|
+
(el as HTMLElement).className?.toString().includes("_bg-accentBackg"),
|
|
303
|
+
);
|
|
304
|
+
expect(marked(checked!).length).toBeGreaterThan(0);
|
|
305
|
+
expect(marked(unchecked!).length).toBe(0);
|
|
306
|
+
});
|
|
307
|
+
});
|
|
259
308
|
});
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { CheckIcon as CheckRegular, MinusIcon as MinusRegular } from "@phosphor-icons/react";
|
|
2
|
+
import { useReadableTextOn } from "@multiplatform.one/theme";
|
|
2
3
|
import type { AnyFormApi } from "../../types";
|
|
3
4
|
import type { ReactNode } from "react";
|
|
4
|
-
import { useMemo } from "react";
|
|
5
|
+
import { useMemo, useState } from "react";
|
|
5
6
|
import type {
|
|
6
7
|
CheckedState,
|
|
7
8
|
CheckboxProps as TamaguiCheckboxProps,
|
|
@@ -23,7 +24,7 @@ import { getSize } from "@tamagui/get-token";
|
|
|
23
24
|
import { useIsInTableCell } from "../../shared/tableCellContext";
|
|
24
25
|
import { Skeleton } from "../../Skeleton";
|
|
25
26
|
import { Field, FieldLayout } from "../../fieldLayout";
|
|
26
|
-
import { formCommonColors, formControlColors } from "../../shared/colorRamps";
|
|
27
|
+
import { formCommonColors, formControlColors, formSelectedColors } from "../../shared/colorRamps";
|
|
27
28
|
import {
|
|
28
29
|
clampRadiusForControl,
|
|
29
30
|
clampRadiusInStateProps,
|
|
@@ -150,6 +151,15 @@ export function Checkbox({
|
|
|
150
151
|
const indicatorColor = getVariable(
|
|
151
152
|
tamaguiTheme[accentTokenKey as any]?.get("web") ?? tamaguiTheme.color?.get("web"),
|
|
152
153
|
);
|
|
154
|
+
// LC-05 ONE-EMPHASIS / D-01 (census addition): the checked box IS the
|
|
155
|
+
// selection mark, so it fills with the shared accent mark — the checked
|
|
156
|
+
// Switch track precedent — and the check/minus glyph takes the
|
|
157
|
+
// luminance-computed anchor for that fill. It painted the LABEL ink tier
|
|
158
|
+
// (`textAccentColor`) on unchanged neutral chrome — the same defect the
|
|
159
|
+
// RadioGroup dot carried — so a checked box read as chrome, not as chosen.
|
|
160
|
+
// When the accent ramp is absent, `onMark` is undefined and the glyph keeps
|
|
161
|
+
// the previous ink resolution as the declared fallback.
|
|
162
|
+
const onMark = useReadableTextOn(formSelectedColors.mark);
|
|
153
163
|
const indicatorWeight =
|
|
154
164
|
knobProps.textWeight.fontWeight === "700"
|
|
155
165
|
? "bold"
|
|
@@ -161,12 +171,12 @@ export function Checkbox({
|
|
|
161
171
|
if (children) return children;
|
|
162
172
|
return (
|
|
163
173
|
<TamaguiCheckbox.Indicator
|
|
164
|
-
{...(knobProps.transition ? {
|
|
174
|
+
{...(knobProps.transition ? { transition: knobProps.transition } : undefined)}
|
|
165
175
|
>
|
|
166
176
|
{currentChecked === "indeterminate" ? (
|
|
167
|
-
<MinusRegular color={indicatorColor} weight={indicatorWeight} />
|
|
177
|
+
<MinusRegular color={onMark ?? indicatorColor} weight={indicatorWeight} />
|
|
168
178
|
) : (
|
|
169
|
-
<CheckRegular color={indicatorColor} weight={indicatorWeight} />
|
|
179
|
+
<CheckRegular color={onMark ?? indicatorColor} weight={indicatorWeight} />
|
|
170
180
|
)}
|
|
171
181
|
</TamaguiCheckbox.Indicator>
|
|
172
182
|
);
|
|
@@ -196,20 +206,37 @@ export function Checkbox({
|
|
|
196
206
|
// Interaction-state tints stay off the (invisible) 44px frame; the knob
|
|
197
207
|
// state props (ring/halo) still apply around the target.
|
|
198
208
|
const stateBaseStyle = { backgroundColor: "transparent" };
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
{...resolvedRadius}
|
|
205
|
-
backgroundColor={knobProps.outlined ? "transparent" : formControlColors.background}
|
|
206
|
-
borderColor={formControlColors.border}
|
|
207
|
-
alignItems="center"
|
|
208
|
-
justifyContent="center"
|
|
209
|
-
>
|
|
210
|
-
{renderIndicator(currentChecked)}
|
|
211
|
-
</View>
|
|
209
|
+
// Live checked value for the standalone-uncontrolled branch: the box fill
|
|
210
|
+
// below is keyed on it (tamagui's internal state only mounts/unmounts the
|
|
211
|
+
// indicator, it cannot repaint the box).
|
|
212
|
+
const [uncontrolledChecked, setUncontrolledChecked] = useState<CheckedState | undefined>(
|
|
213
|
+
defaultValue as CheckedState | undefined,
|
|
212
214
|
);
|
|
215
|
+
const glyphBox = (currentChecked: CheckedState | undefined) => {
|
|
216
|
+
// Indeterminate is a selected-ish state: it carries the mark fill too,
|
|
217
|
+
// with the minus glyph, so "partially chosen" never reads as idle chrome.
|
|
218
|
+
const isMarked = currentChecked === true || currentChecked === "indeterminate";
|
|
219
|
+
return (
|
|
220
|
+
<View
|
|
221
|
+
width={glyphSize}
|
|
222
|
+
height={glyphSize}
|
|
223
|
+
{...knobProps.inputSurface}
|
|
224
|
+
{...resolvedRadius}
|
|
225
|
+
backgroundColor={
|
|
226
|
+
isMarked
|
|
227
|
+
? formSelectedColors.mark
|
|
228
|
+
: knobProps.outlined
|
|
229
|
+
? "transparent"
|
|
230
|
+
: formControlColors.background
|
|
231
|
+
}
|
|
232
|
+
borderColor={isMarked ? formSelectedColors.mark : formControlColors.border}
|
|
233
|
+
alignItems="center"
|
|
234
|
+
justifyContent="center"
|
|
235
|
+
>
|
|
236
|
+
{renderIndicator(currentChecked)}
|
|
237
|
+
</View>
|
|
238
|
+
);
|
|
239
|
+
};
|
|
213
240
|
// Elevation wraps the visible glyph, never the invisible target (cells
|
|
214
241
|
// keep elevation suppressed as before).
|
|
215
242
|
const renderControlContent = (currentChecked: CheckedState | undefined) =>
|
|
@@ -308,11 +335,12 @@ export function Checkbox({
|
|
|
308
335
|
{...nativeCheckboxA11y(typeof error === "string" && error ? error : undefined)}
|
|
309
336
|
onCheckedChange={(val) => {
|
|
310
337
|
if (disabled || readOnly) return;
|
|
338
|
+
setUncontrolledChecked(val);
|
|
311
339
|
handleValueChange(val);
|
|
312
340
|
}}
|
|
313
341
|
{...(onBlur ? { onBlur } : undefined)}
|
|
314
342
|
>
|
|
315
|
-
{renderControlContent(checked ??
|
|
343
|
+
{renderControlContent(checked ?? uncontrolledChecked)}
|
|
316
344
|
</CheckboxFieldFrame>
|
|
317
345
|
);
|
|
318
346
|
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import type { RovingFocusGroupProps, RovingFocusItemProps } from "@tamagui/roving-focus";
|
|
2
2
|
import { RovingFocusGroup } from "@tamagui/roving-focus";
|
|
3
3
|
import { CheckIcon as CheckRegular } from "@phosphor-icons/react";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
ensureFocusVisibleRing,
|
|
6
|
+
useReadableTextOn,
|
|
7
|
+
useResolvedKnobs,
|
|
8
|
+
} from "@multiplatform.one/theme";
|
|
5
9
|
import type { ElementRef, KeyboardEvent, PropsWithChildren } from "react";
|
|
6
10
|
import { forwardRef } from "react";
|
|
7
11
|
import type { CheckedState, YStackProps } from "tamagui";
|
|
@@ -28,7 +32,7 @@ import {
|
|
|
28
32
|
} from "./CheckboxCard";
|
|
29
33
|
import { CheckboxFieldFrame } from "./CheckboxFieldFrame";
|
|
30
34
|
import { clampRadiusForControl } from "../../shared/utils";
|
|
31
|
-
import { formControlColors } from "../../shared/colorRamps";
|
|
35
|
+
import { formControlColors, formSelectedColors } from "../../shared/colorRamps";
|
|
32
36
|
|
|
33
37
|
// ─── Checkboxes Compound Component ────────────────────────────────────────────
|
|
34
38
|
|
|
@@ -133,6 +137,10 @@ const CheckboxesCheckbox = TamaguiCheckbox.styleable((checkboxProps, ref) => {
|
|
|
133
137
|
const { values, onValuesChange } = CheckboxesContext.useStyledContext();
|
|
134
138
|
const { value: focusItemValue } = FocusItemContext.useStyledContext();
|
|
135
139
|
const { knobProps } = useResolvedKnobs();
|
|
140
|
+
// LC-05 ONE-EMPHASIS / D-01: the checked box is the selection mark, so it
|
|
141
|
+
// fills with the shared accent mark (same treatment as fields/Checkbox and
|
|
142
|
+
// the checked Switch track); unchecked chrome stays neutral.
|
|
143
|
+
const isMarked = Boolean(values[focusItemValue]);
|
|
136
144
|
const radiusToken = knobProps.borderRadius.borderRadius;
|
|
137
145
|
const cappedRadius = clampRadiusForControl(radiusToken, 2);
|
|
138
146
|
const resolvedRadius =
|
|
@@ -196,8 +204,14 @@ const CheckboxesCheckbox = TamaguiCheckbox.styleable((checkboxProps, ref) => {
|
|
|
196
204
|
height={glyphSize}
|
|
197
205
|
{...knobProps.inputSurface}
|
|
198
206
|
{...resolvedRadius}
|
|
199
|
-
backgroundColor={
|
|
200
|
-
|
|
207
|
+
backgroundColor={
|
|
208
|
+
isMarked
|
|
209
|
+
? formSelectedColors.mark
|
|
210
|
+
: knobProps.outlined
|
|
211
|
+
? "transparent"
|
|
212
|
+
: formControlColors.background
|
|
213
|
+
}
|
|
214
|
+
borderColor={isMarked ? formSelectedColors.mark : formControlColors.border}
|
|
201
215
|
alignItems="center"
|
|
202
216
|
justifyContent="center"
|
|
203
217
|
>
|
|
@@ -240,9 +254,13 @@ const CheckboxCardDescriptionSized = CheckboxCardDescription.styleable((props, r
|
|
|
240
254
|
|
|
241
255
|
const CheckboxesIndicator = TamaguiCheckbox.Indicator.styleable((indicatorProps, ref) => {
|
|
242
256
|
const { children, ...props } = indicatorProps;
|
|
257
|
+
// LC-05: the glyph rides the accent mark fill, so it takes the
|
|
258
|
+
// luminance-computed anchor for that fill (never assumed scheme ink);
|
|
259
|
+
// consumer-provided children keep their own colors (explicit eject).
|
|
260
|
+
const onMark = useReadableTextOn(formSelectedColors.mark);
|
|
243
261
|
return (
|
|
244
262
|
<TamaguiCheckbox.Indicator ref={ref} {...props}>
|
|
245
|
-
{children ?? <CheckRegular />}
|
|
263
|
+
{children ?? <CheckRegular {...(onMark ? { color: onMark } : undefined)} />}
|
|
246
264
|
</TamaguiCheckbox.Indicator>
|
|
247
265
|
);
|
|
248
266
|
});
|
|
@@ -158,7 +158,8 @@ export const WithError: Story = {
|
|
|
158
158
|
render: (args) => <ColorPicker {...args} />,
|
|
159
159
|
args: {
|
|
160
160
|
label: "Required Color",
|
|
161
|
-
|
|
161
|
+
// DG-COPY-02: error copy states the rule broken — never "please"/"invalid"/"error".
|
|
162
|
+
error: "Color must be a recognized value",
|
|
162
163
|
required: true,
|
|
163
164
|
},
|
|
164
165
|
};
|
|
@@ -333,7 +333,7 @@ const ComboboxItem = memo(function ComboboxItem({
|
|
|
333
333
|
? // Two-line rows need to grow past the size-variant height.
|
|
334
334
|
{ height: "auto", paddingVertical: "$2" }
|
|
335
335
|
: undefined)}
|
|
336
|
-
{...(ctx.knobProps.transition ? {
|
|
336
|
+
{...(ctx.knobProps.transition ? { transition: ctx.knobProps.transition } : undefined)}
|
|
337
337
|
>
|
|
338
338
|
{option.description ? (
|
|
339
339
|
<YStack flex={1} minWidth={0}>
|
|
@@ -1258,6 +1258,11 @@ function FloatingComboboxCore({
|
|
|
1258
1258
|
: {
|
|
1259
1259
|
borderRadius: knobProps.borderRadius.borderRadius,
|
|
1260
1260
|
borderWidth: knobProps.borderRadius.borderWidth,
|
|
1261
|
+
// LC-54 PRESS-FLOOR: compact/small size tokens render a sub-44
|
|
1262
|
+
// trigger (the 36px "Allocated To" quick filter breaking the
|
|
1263
|
+
// list's 44px control row) — same floor the house Select holds
|
|
1264
|
+
// on both its trigger variants.
|
|
1265
|
+
minHeight: 44,
|
|
1261
1266
|
})}
|
|
1262
1267
|
>
|
|
1263
1268
|
<SyncFocusToOpen open={open} />
|
|
@@ -1497,7 +1502,7 @@ function FloatingComboboxCore({
|
|
|
1497
1502
|
: undefined
|
|
1498
1503
|
}
|
|
1499
1504
|
onPress={handleCreate}
|
|
1500
|
-
{...(knobProps.transition ? {
|
|
1505
|
+
{...(knobProps.transition ? { transition: knobProps.transition } : undefined)}
|
|
1501
1506
|
>
|
|
1502
1507
|
<PlusIcon size={14} color={knobProps.textAccentColor} />
|
|
1503
1508
|
<Text
|
|
@@ -1538,7 +1543,7 @@ function FloatingComboboxCore({
|
|
|
1538
1543
|
: "transparent"
|
|
1539
1544
|
}
|
|
1540
1545
|
pressStyle={{ backgroundColor: formInputColors.background.focus }}
|
|
1541
|
-
{...(knobProps.transition ? {
|
|
1546
|
+
{...(knobProps.transition ? { transition: knobProps.transition } : undefined)}
|
|
1542
1547
|
>
|
|
1543
1548
|
<PlusIcon size={14} color={knobProps.textAccentColor} />
|
|
1544
1549
|
<Text
|
|
@@ -223,6 +223,99 @@ describe("DatePicker", () => {
|
|
|
223
223
|
});
|
|
224
224
|
});
|
|
225
225
|
|
|
226
|
+
describe("late-arriving value display (create-mode seeding)", () => {
|
|
227
|
+
// The form branch only ever displayed the mount-time value (`selectedDate`
|
|
228
|
+
// was never re-synced from field state), so a value applied AFTER first
|
|
229
|
+
// paint — create-mode engine seeding, form.setFieldValue, live server
|
|
230
|
+
// merge — never rendered. Adopting a programmatic value must not emit
|
|
231
|
+
// onChange (LC-14: a seeded value is not a user edit).
|
|
232
|
+
const getDisplayInput = (container: ParentNode) =>
|
|
233
|
+
container.querySelector("input") as HTMLInputElement | null;
|
|
234
|
+
|
|
235
|
+
it("standalone controlled: a value arriving after mount displays, without onChange", async () => {
|
|
236
|
+
const DatePicker = await loadDatePicker();
|
|
237
|
+
const onChange = vi.fn();
|
|
238
|
+
const onValueChange = vi.fn();
|
|
239
|
+
const result = renderWithProviders(
|
|
240
|
+
<DatePicker
|
|
241
|
+
label="Due Date"
|
|
242
|
+
value={null}
|
|
243
|
+
onChange={onChange}
|
|
244
|
+
onValueChange={onValueChange}
|
|
245
|
+
/>,
|
|
246
|
+
);
|
|
247
|
+
expect(getDisplayInput(result.container)?.value ?? "").toBe("");
|
|
248
|
+
|
|
249
|
+
// Late seed: the upstream doc value (frappe wire string) arrives after
|
|
250
|
+
// first paint.
|
|
251
|
+
result.rerender(
|
|
252
|
+
<DatePicker
|
|
253
|
+
label="Due Date"
|
|
254
|
+
value="2026-03-05"
|
|
255
|
+
onChange={onChange}
|
|
256
|
+
onValueChange={onValueChange}
|
|
257
|
+
/>,
|
|
258
|
+
);
|
|
259
|
+
await waitFor(() => {
|
|
260
|
+
expect(getDisplayInput(result.container)?.value).toBe("Mar 5, 2026");
|
|
261
|
+
});
|
|
262
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
263
|
+
expect(onValueChange).not.toHaveBeenCalled();
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it("form-integrated: a field value set after mount displays, without onChange", async () => {
|
|
267
|
+
const DatePicker = await loadDatePicker();
|
|
268
|
+
const onChange = vi.fn();
|
|
269
|
+
let formApi: { setFieldValue: (name: "date", value: string | null) => void } | undefined;
|
|
270
|
+
const TestComponent = () => {
|
|
271
|
+
const form = useForm({ defaultValues: { date: null as string | null } });
|
|
272
|
+
formApi = form as unknown as typeof formApi;
|
|
273
|
+
return (
|
|
274
|
+
<Form form={form}>
|
|
275
|
+
<DatePicker label="Due Date" name="date" onChange={onChange} />
|
|
276
|
+
</Form>
|
|
277
|
+
);
|
|
278
|
+
};
|
|
279
|
+
const result = renderWithProviders(<TestComponent />);
|
|
280
|
+
expect(getDisplayInput(result.container)?.value ?? "").toBe("");
|
|
281
|
+
|
|
282
|
+
await act(async () => {
|
|
283
|
+
formApi?.setFieldValue("date", "2026-03-05");
|
|
284
|
+
});
|
|
285
|
+
await waitFor(() => {
|
|
286
|
+
expect(getDisplayInput(result.container)?.value).toBe("Mar 5, 2026");
|
|
287
|
+
});
|
|
288
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
it("form-integrated: clearing the field value programmatically clears the display", async () => {
|
|
292
|
+
const DatePicker = await loadDatePicker();
|
|
293
|
+
const onChange = vi.fn();
|
|
294
|
+
let formApi: { setFieldValue: (name: "date", value: string | null) => void } | undefined;
|
|
295
|
+
const TestComponent = () => {
|
|
296
|
+
const form = useForm({ defaultValues: { date: "2026-03-05" as string | null } });
|
|
297
|
+
formApi = form as unknown as typeof formApi;
|
|
298
|
+
return (
|
|
299
|
+
<Form form={form}>
|
|
300
|
+
<DatePicker label="Due Date" name="date" onChange={onChange} />
|
|
301
|
+
</Form>
|
|
302
|
+
);
|
|
303
|
+
};
|
|
304
|
+
const result = renderWithProviders(<TestComponent />);
|
|
305
|
+
await waitFor(() => {
|
|
306
|
+
expect(getDisplayInput(result.container)?.value).toBe("Mar 5, 2026");
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
await act(async () => {
|
|
310
|
+
formApi?.setFieldValue("date", null);
|
|
311
|
+
});
|
|
312
|
+
await waitFor(() => {
|
|
313
|
+
expect(getDisplayInput(result.container)?.value ?? "").toBe("");
|
|
314
|
+
});
|
|
315
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
|
|
226
319
|
describe("date utilities", () => {
|
|
227
320
|
it("formats display values in the house absolute register and handles null", () => {
|
|
228
321
|
expect(formatDateDisplay(null)).toBe("");
|