@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
|
@@ -333,6 +333,10 @@ function SliderControl({
|
|
|
333
333
|
const trackActive = (
|
|
334
334
|
<TamaguiSlider.TrackActive
|
|
335
335
|
backgroundColor={formControlColors.border}
|
|
336
|
+
// The fill rides the same radius as the track it sits in: without it
|
|
337
|
+
// tamagui's default left a pill fill inside a square track at
|
|
338
|
+
// `borderRadius:none` — an undeclared knob-immune shape (D-09 / LC-60).
|
|
339
|
+
borderRadius={borderRadius}
|
|
336
340
|
transition={transitionProp}
|
|
337
341
|
/>
|
|
338
342
|
);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { action } from "@multiplatform.one/storybook";
|
|
2
|
+
import type { GuardrailSpecimenParameter } from "@multiplatform.one/theme";
|
|
2
3
|
import type { Meta, StoryObj } from "@storybook/react-native-web-vite";
|
|
3
4
|
import { useForm } from "@tanstack/react-form";
|
|
4
5
|
import { useState } from "react";
|
|
@@ -94,6 +95,17 @@ export const Basic: Story = {
|
|
|
94
95
|
};
|
|
95
96
|
|
|
96
97
|
export const Disabled: Story = {
|
|
98
|
+
parameters: {
|
|
99
|
+
// LC-57 allowlist: this story IS the disabled-dial demo. Stepper has no
|
|
100
|
+
// disabledReason plumbing (component-contract change, tracked separately),
|
|
101
|
+
// so its +/- buttons bare-disable here by design. The warn still fires;
|
|
102
|
+
// the harvester tolerates exactly this code on this story.
|
|
103
|
+
guardrailSpecimen: {
|
|
104
|
+
warns: ["bare-disabled"],
|
|
105
|
+
reason:
|
|
106
|
+
"Disabled-dial specimen: the whole field rests disabled and Stepper has no disabledReason plumbing yet.",
|
|
107
|
+
} satisfies GuardrailSpecimenParameter,
|
|
108
|
+
},
|
|
97
109
|
args: {
|
|
98
110
|
label: "Disabled Field",
|
|
99
111
|
disabled: true,
|
|
@@ -1,12 +1,35 @@
|
|
|
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 { 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 { Switch } from "./index";
|
|
9
17
|
|
|
18
|
+
// House builder themes for the LC-05 mark assertion — created at MODULE
|
|
19
|
+
// scope: tamagui registers a config's theme variables globally at
|
|
20
|
+
// createTamagui time, and a config created after the first render (inside a
|
|
21
|
+
// test body) never resolves its tokens (Progress.spec pattern).
|
|
22
|
+
const houseThemes = createThemesBuilder(
|
|
23
|
+
defaultBaseTheme,
|
|
24
|
+
defaultAccentTheme,
|
|
25
|
+
defaultBuilderOptions,
|
|
26
|
+
).themes() as Record<string, Record<string, string>>;
|
|
27
|
+
const houseConfig = createTamagui({
|
|
28
|
+
...configWithoutAnimations,
|
|
29
|
+
animations: animationsCSS,
|
|
30
|
+
themes: houseThemes as any,
|
|
31
|
+
});
|
|
32
|
+
|
|
10
33
|
describe("Switch", () => {
|
|
11
34
|
describe("without form context", () => {
|
|
12
35
|
it("should render with label and helper text correctly", () => {
|
|
@@ -315,4 +338,29 @@ describe("Switch", () => {
|
|
|
315
338
|
});
|
|
316
339
|
});
|
|
317
340
|
});
|
|
341
|
+
|
|
342
|
+
describe("checked track mark (LC-05 ONE-EMPHASIS / UX-002)", () => {
|
|
343
|
+
// The checked Switch track IS a selection mark, so it resolves the shared
|
|
344
|
+
// accent mark token; the unchecked track stays neutral chrome. Stock test
|
|
345
|
+
// themes carry no $accentBackground, so mount the house builder themes
|
|
346
|
+
// for real resolution.
|
|
347
|
+
it("paints the checked track with the accent mark and the unchecked track neutral", () => {
|
|
348
|
+
const { container } = render(
|
|
349
|
+
<TamaguiProvider config={houseConfig} defaultTheme="light" disableInjectCSS>
|
|
350
|
+
<YStack>
|
|
351
|
+
<Switch label="On" name="on" defaultValue={true} />
|
|
352
|
+
<Switch label="Off" name="off" defaultValue={false} />
|
|
353
|
+
</YStack>
|
|
354
|
+
</TamaguiProvider>,
|
|
355
|
+
);
|
|
356
|
+
const switches = Array.from(container.querySelectorAll("[role='switch']"));
|
|
357
|
+
expect(switches.length).toBe(2);
|
|
358
|
+
const on = switches.find((s) => s.getAttribute("aria-checked") === "true") as HTMLElement;
|
|
359
|
+
const off = switches.find((s) => s.getAttribute("aria-checked") === "false") as HTMLElement;
|
|
360
|
+
expect(on).toBeTruthy();
|
|
361
|
+
expect(off).toBeTruthy();
|
|
362
|
+
expect(on.className).toContain("_bg-accentBackg");
|
|
363
|
+
expect(off.className).not.toContain("_bg-accentBackg");
|
|
364
|
+
});
|
|
365
|
+
});
|
|
318
366
|
});
|
|
@@ -182,6 +182,63 @@ describe("TextArea", () => {
|
|
|
182
182
|
});
|
|
183
183
|
});
|
|
184
184
|
|
|
185
|
+
describe("late-arriving value display (create-mode seeding)", () => {
|
|
186
|
+
// The DOM textarea itself adopts late `defaultValue` updates while
|
|
187
|
+
// pristine (React DOM keeps the value attribute synced), but `charCount`
|
|
188
|
+
// was mount-only state — a value applied AFTER first paint (create-mode
|
|
189
|
+
// engine seeding, setFieldValue) rendered a stale count. Adopting a
|
|
190
|
+
// programmatic value must not emit onChange (LC-14).
|
|
191
|
+
it("form-integrated: a field value set after mount displays with a live count, without onChange", async () => {
|
|
192
|
+
const onChange = vi.fn();
|
|
193
|
+
const onChangeText = vi.fn();
|
|
194
|
+
let formApi: { setFieldValue: (name: "notes", value: string) => void } | undefined;
|
|
195
|
+
const TestComponent = () => {
|
|
196
|
+
const form = useForm({ defaultValues: { notes: "" } });
|
|
197
|
+
formApi = form as unknown as typeof formApi;
|
|
198
|
+
return (
|
|
199
|
+
<Form form={form}>
|
|
200
|
+
<TextArea
|
|
201
|
+
label="Notes"
|
|
202
|
+
name="notes"
|
|
203
|
+
showCount
|
|
204
|
+
onChange={onChange}
|
|
205
|
+
onChangeText={onChangeText}
|
|
206
|
+
/>
|
|
207
|
+
</Form>
|
|
208
|
+
);
|
|
209
|
+
};
|
|
210
|
+
const result = renderWithProviders(<TestComponent />);
|
|
211
|
+
expect(result.findTextElement("0 characters")).toBeDefined();
|
|
212
|
+
|
|
213
|
+
await act(async () => {
|
|
214
|
+
formApi?.setFieldValue("notes", "seeded text");
|
|
215
|
+
});
|
|
216
|
+
await waitFor(() => {
|
|
217
|
+
expect((result.getTextArea() as HTMLTextAreaElement)?.value).toBe("seeded text");
|
|
218
|
+
expect(result.findTextElement("11 characters")).toBeDefined();
|
|
219
|
+
});
|
|
220
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
221
|
+
expect(onChangeText).not.toHaveBeenCalled();
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
it("standalone controlled: a value arriving after mount updates the count, without onChange", async () => {
|
|
225
|
+
const onChangeText = vi.fn();
|
|
226
|
+
const result = renderWithProviders(
|
|
227
|
+
<TextArea label="Notes" value="" showCount onChangeText={onChangeText} />,
|
|
228
|
+
);
|
|
229
|
+
expect(result.findTextElement("0 characters")).toBeDefined();
|
|
230
|
+
|
|
231
|
+
result.rerender(
|
|
232
|
+
<TextArea label="Notes" value="late value" showCount onChangeText={onChangeText} />,
|
|
233
|
+
);
|
|
234
|
+
await waitFor(() => {
|
|
235
|
+
expect((result.getTextArea() as HTMLTextAreaElement)?.value).toBe("late value");
|
|
236
|
+
expect(result.findTextElement("10 characters")).toBeDefined();
|
|
237
|
+
});
|
|
238
|
+
expect(onChangeText).not.toHaveBeenCalled();
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
|
|
185
242
|
describe("with useForm hook directly", () => {
|
|
186
243
|
it("should handle form submission with useForm", async () => {
|
|
187
244
|
const onSubmitMock = vi.fn();
|
|
@@ -190,7 +190,26 @@ export const AutoResize: Story = {
|
|
|
190
190
|
},
|
|
191
191
|
};
|
|
192
192
|
|
|
193
|
+
/**
|
|
194
|
+
* FOREIGN CONTRAST SPECIMEN (LC-56 STORY-HONESTY): the right column renders the
|
|
195
|
+
* RAW tamagui TextArea beside the house TextArea strictly so the difference
|
|
196
|
+
* stays visible. Raw primitives here are by design and labeled — knob/contrast
|
|
197
|
+
* probes skip this story via `parameters.foreignContrastSpecimen`.
|
|
198
|
+
*/
|
|
193
199
|
export const Comparison: Story = {
|
|
200
|
+
name: "Foreign contrast specimen (raw tamagui)",
|
|
201
|
+
parameters: {
|
|
202
|
+
// Machine-readable exemption for knob/contrast probes and the LC-56 linter arm.
|
|
203
|
+
foreignContrastSpecimen: true,
|
|
204
|
+
docs: {
|
|
205
|
+
description: {
|
|
206
|
+
story:
|
|
207
|
+
"FOREIGN CONTRAST SPECIMEN (LC-56 STORY-HONESTY). The right column is the raw " +
|
|
208
|
+
"tamagui TextArea, rendered for contrast only: it ignores house knobs and field " +
|
|
209
|
+
"recipes by design. Probes asserting house rendering must skip this story.",
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
},
|
|
194
213
|
render: () => {
|
|
195
214
|
const ComparisonExample = () => {
|
|
196
215
|
const [customVal, setCustomVal] = useState("");
|
|
@@ -171,6 +171,14 @@ export function TextArea({
|
|
|
171
171
|
|
|
172
172
|
const isControlled = value !== undefined;
|
|
173
173
|
|
|
174
|
+
// Count from the live value whenever an upstream source drives the field
|
|
175
|
+
// (controlled `value` prop or TanStack field state): the mount-only
|
|
176
|
+
// charCount state froze counts for values applied after first paint
|
|
177
|
+
// (create-mode seeding, setFieldValue). Uncontrolled standalone keeps the
|
|
178
|
+
// keystroke-fed local state (its defaultValue never changes underneath).
|
|
179
|
+
const countFrom = (textValue: string | undefined) =>
|
|
180
|
+
isControlled || !!(resolvedForm && name) ? (textValue ?? "").length : charCount;
|
|
181
|
+
|
|
174
182
|
const renderTextArea = (
|
|
175
183
|
textValue: string | undefined,
|
|
176
184
|
handleChange?: (text: string) => void,
|
|
@@ -178,7 +186,7 @@ export function TextArea({
|
|
|
178
186
|
hasError?: boolean,
|
|
179
187
|
) => (
|
|
180
188
|
<>
|
|
181
|
-
{showCount && countPosition.startsWith("top") && renderCount(
|
|
189
|
+
{showCount && countPosition.startsWith("top") && renderCount(countFrom(textValue))}
|
|
182
190
|
<YStack position="relative">
|
|
183
191
|
<InputParts.Box
|
|
184
192
|
height="auto"
|
|
@@ -232,7 +240,7 @@ export function TextArea({
|
|
|
232
240
|
</InputParts.Box>
|
|
233
241
|
{renderOverlay?.()}
|
|
234
242
|
</YStack>
|
|
235
|
-
{showCount && countPosition.startsWith("bottom") && renderCount(
|
|
243
|
+
{showCount && countPosition.startsWith("bottom") && renderCount(countFrom(textValue))}
|
|
236
244
|
</>
|
|
237
245
|
);
|
|
238
246
|
|
|
@@ -106,7 +106,7 @@ function AmPmColumn({
|
|
|
106
106
|
backgroundColor={isSelected ? formInputColors.background.focus : "transparent"}
|
|
107
107
|
hoverStyle={{ backgroundColor: formInputColors.background.focus }}
|
|
108
108
|
onPress={() => onChange(period)}
|
|
109
|
-
{...(knobProps.transition ? {
|
|
109
|
+
{...(knobProps.transition ? { transition: knobProps.transition } : undefined)}
|
|
110
110
|
>
|
|
111
111
|
<Text
|
|
112
112
|
fontSize="$3"
|
|
@@ -1,10 +1,52 @@
|
|
|
1
|
-
import { fireEvent, screen } from "@testing-library/react";
|
|
1
|
+
import { fireEvent, render, screen } from "@testing-library/react";
|
|
2
2
|
import { afterEach, beforeEach, 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 type { ReactElement } from "react";
|
|
13
|
+
import { TamaguiProvider, createTamagui } from "tamagui";
|
|
4
14
|
import { __resetDevWarnSeen } from "../../shared/devWarn";
|
|
5
15
|
import { Form } from "../../Form";
|
|
6
16
|
import { ToggleGroup } from "./index";
|
|
7
17
|
|
|
18
|
+
// The stock test themes carry no accent ramp, so token resolution for the
|
|
19
|
+
// LC-05 selected mark is invisible under renderWithProviders. Mount the house
|
|
20
|
+
// builder themes (the same ones apps run) to assert the real resolved fill —
|
|
21
|
+
// the pattern Progress.spec.tsx established.
|
|
22
|
+
const houseThemes = createThemesBuilder(
|
|
23
|
+
defaultBaseTheme,
|
|
24
|
+
defaultAccentTheme,
|
|
25
|
+
defaultBuilderOptions,
|
|
26
|
+
).themes() as Record<string, Record<string, string>>;
|
|
27
|
+
|
|
28
|
+
const houseConfig = createTamagui({
|
|
29
|
+
...configWithoutAnimations,
|
|
30
|
+
animations: animationsCSS,
|
|
31
|
+
themes: houseThemes as any,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
function renderWithHouseThemes(ui: ReactElement) {
|
|
35
|
+
return render(
|
|
36
|
+
<TamaguiProvider config={houseConfig} defaultTheme="light" disableInjectCSS>
|
|
37
|
+
{ui}
|
|
38
|
+
</TamaguiProvider>,
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* First three numeric groups (h, s, l) of an hsla() string — the digit prefix
|
|
44
|
+
* Tamagui embeds in the atomic class it generates for a concrete color value.
|
|
45
|
+
*/
|
|
46
|
+
function hslDigits(hsla: string): string {
|
|
47
|
+
return (hsla.match(/\d+/g) ?? []).slice(0, 3).join("");
|
|
48
|
+
}
|
|
49
|
+
|
|
8
50
|
const options = [
|
|
9
51
|
{ label: "Left", value: "left" },
|
|
10
52
|
{ label: "Center", value: "center" },
|
|
@@ -162,4 +204,25 @@ describe("ToggleGroup", () => {
|
|
|
162
204
|
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining("bare-disabled"));
|
|
163
205
|
});
|
|
164
206
|
});
|
|
207
|
+
|
|
208
|
+
describe("selected mark (LC-05 ONE-EMPHASIS / D-01)", () => {
|
|
209
|
+
it("fills the selected segment with the accent-tinted surface, never the neutral tier", () => {
|
|
210
|
+
const { container } = renderWithHouseThemes(
|
|
211
|
+
<ToggleGroup label="Alignment" options={options} defaultValue="left" />,
|
|
212
|
+
);
|
|
213
|
+
// Segmented-control selection strength is pinned at TINTED (D-01
|
|
214
|
+
// ViewSwitcher rider): the accent ramp's surface tier in a light scheme
|
|
215
|
+
// is its palest step (accent11) — the same channel ViewSwitcher takes.
|
|
216
|
+
const tint = houseThemes.light.accent11;
|
|
217
|
+
expect(tint).toBeTruthy();
|
|
218
|
+
const selected = container.querySelector('[data-state="on"]') as HTMLElement;
|
|
219
|
+
const idle = container.querySelector('[data-state="off"]') as HTMLElement;
|
|
220
|
+
expect(selected).toBeTruthy();
|
|
221
|
+
expect(idle).toBeTruthy();
|
|
222
|
+
expect(selected.className).toContain(`_bg-hsla${hslDigits(tint)}`);
|
|
223
|
+
expect(idle.className).not.toContain(`_bg-hsla${hslDigits(tint)}`);
|
|
224
|
+
// Ink marks selection nowhere: the old neutral $color8 fill is gone.
|
|
225
|
+
expect(selected.className).not.toContain("_bg-color8");
|
|
226
|
+
});
|
|
227
|
+
});
|
|
165
228
|
});
|
|
@@ -252,7 +252,26 @@ const alignmentOptions = [
|
|
|
252
252
|
{ label: "Right", value: "right" },
|
|
253
253
|
];
|
|
254
254
|
|
|
255
|
+
/**
|
|
256
|
+
* FOREIGN CONTRAST SPECIMEN (LC-56 STORY-HONESTY): the right column renders the
|
|
257
|
+
* RAW tamagui ToggleGroup beside the house ToggleGroup strictly so the
|
|
258
|
+
* difference stays visible. Raw primitives here are by design and labeled —
|
|
259
|
+
* knob/contrast probes skip this story via `parameters.foreignContrastSpecimen`.
|
|
260
|
+
*/
|
|
255
261
|
export const Comparison: Story = {
|
|
262
|
+
name: "Foreign contrast specimen (raw tamagui)",
|
|
263
|
+
parameters: {
|
|
264
|
+
// Machine-readable exemption for knob/contrast probes and the LC-56 linter arm.
|
|
265
|
+
foreignContrastSpecimen: true,
|
|
266
|
+
docs: {
|
|
267
|
+
description: {
|
|
268
|
+
story:
|
|
269
|
+
"FOREIGN CONTRAST SPECIMEN (LC-56 STORY-HONESTY). The right column is the raw " +
|
|
270
|
+
"tamagui ToggleGroup, rendered for contrast only: it ignores house knobs and " +
|
|
271
|
+
"control recipes by design. Probes asserting house rendering must skip this story.",
|
|
272
|
+
},
|
|
273
|
+
},
|
|
274
|
+
},
|
|
256
275
|
render: () => {
|
|
257
276
|
const ComparisonExample = () => {
|
|
258
277
|
const [customVal, setCustomVal] = useState("left");
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
ensureFocusVisibleRing,
|
|
5
5
|
ensureKeyboardModalityTracking,
|
|
6
6
|
keyboardFocusRingProps,
|
|
7
|
+
useAccentTintedSurface,
|
|
7
8
|
useReadableTextOn,
|
|
8
9
|
wasKeyboardFocus,
|
|
9
10
|
} from "@multiplatform.one/theme";
|
|
@@ -30,6 +31,11 @@ import {
|
|
|
30
31
|
useResolvedValidators,
|
|
31
32
|
} from "../../shared/utils";
|
|
32
33
|
|
|
34
|
+
// NOTE: no `active` variant here — the selected fill is runtime-resolved
|
|
35
|
+
// (accent-tinted surface, LC-05/D-01), so it rides direct props re-applied
|
|
36
|
+
// through hover/press. A static variant would expand at its key position and
|
|
37
|
+
// paint its stale value OVER those direct props (the exact drift the LC-40
|
|
38
|
+
// wash comment below records for the disabled tier).
|
|
33
39
|
const ToggleItemFrame = styled(TamaguiToggleGroup.Item, {
|
|
34
40
|
cursor: "pointer",
|
|
35
41
|
userSelect: "none",
|
|
@@ -56,20 +62,6 @@ const ToggleItemFrame = styled(TamaguiToggleGroup.Item, {
|
|
|
56
62
|
},
|
|
57
63
|
},
|
|
58
64
|
},
|
|
59
|
-
active: {
|
|
60
|
-
true: {
|
|
61
|
-
backgroundColor: formButtonColors.border.active,
|
|
62
|
-
borderColor: formButtonColors.border.active,
|
|
63
|
-
hoverStyle: {
|
|
64
|
-
backgroundColor: formButtonColors.border.active,
|
|
65
|
-
borderColor: formButtonColors.border.active,
|
|
66
|
-
},
|
|
67
|
-
pressStyle: {
|
|
68
|
-
backgroundColor: formButtonColors.border.active,
|
|
69
|
-
borderColor: formButtonColors.border.active,
|
|
70
|
-
},
|
|
71
|
-
},
|
|
72
|
-
},
|
|
73
65
|
} as const,
|
|
74
66
|
});
|
|
75
67
|
|
|
@@ -244,11 +236,19 @@ export function ToggleGroup({
|
|
|
244
236
|
id: idProp,
|
|
245
237
|
compact,
|
|
246
238
|
});
|
|
247
|
-
//
|
|
248
|
-
//
|
|
249
|
-
//
|
|
250
|
-
//
|
|
251
|
-
|
|
239
|
+
// LC-05 / D-01: selection is ONE accent language across every choice-control
|
|
240
|
+
// family — this selected segment filled with the neutral `$color8` tier, the
|
|
241
|
+
// catalog's last ink/neutral-marked selection surface. Segmented-control
|
|
242
|
+
// STRENGTH is pinned at TINTED (the D-01 ViewSwitcher rider — not the solid
|
|
243
|
+
// an accent CTA takes), so the fill is the accent ramp's surface tier
|
|
244
|
+
// mirrored by scheme, the same channel ViewSwitcher resolves. When the
|
|
245
|
+
// accent ramp is absent (tint sub-themes) the neutral tier stays as the
|
|
246
|
+
// declared fallback so selection never goes invisible.
|
|
247
|
+
// UX-018 / Axiom 15 kept: the label is the paper/ink anchor luminance-picked
|
|
248
|
+
// for the ACTUAL fill, never an assumed scheme token.
|
|
249
|
+
const selectedTint = useAccentTintedSurface();
|
|
250
|
+
const selectedFill = selectedTint ?? formButtonColors.border.active;
|
|
251
|
+
const onSelectedLabel = useReadableTextOn(selectedFill);
|
|
252
252
|
// Chromium drops keyboard modality when tamagui's group redirects focus to
|
|
253
253
|
// an item, so :focus-visible/focusVisibleStyle can miss — paint the ring
|
|
254
254
|
// manually on keyboard-origin focus (see theme keyboardFocusRing).
|
|
@@ -344,9 +344,13 @@ export function ToggleGroup({
|
|
|
344
344
|
const itemDisabled = Boolean(disabled || option.disabled);
|
|
345
345
|
const itemDescribedBy = option.disabled ? itemReasonIdFor(option.disabledReason) : undefined;
|
|
346
346
|
const isTabStop = index === tabStopIndex;
|
|
347
|
+
// The accent-tinted selected fill (border rides the fill, as the
|
|
348
|
+
// neutral chip's did) — re-applied through hover/press below so the
|
|
349
|
+
// neutral state layer never paints over the selection mark (the LC-05
|
|
350
|
+
// rule the checked Switch track and ViewSwitcher chip already follow).
|
|
347
351
|
const activeColors = {
|
|
348
|
-
backgroundColor:
|
|
349
|
-
borderColor:
|
|
352
|
+
backgroundColor: selectedFill,
|
|
353
|
+
borderColor: selectedFill,
|
|
350
354
|
};
|
|
351
355
|
|
|
352
356
|
return (
|
|
@@ -365,18 +369,16 @@ export function ToggleGroup({
|
|
|
365
369
|
paddingHorizontal="$2"
|
|
366
370
|
borderWidth={knobProps.borderRadius.borderWidth}
|
|
367
371
|
outlined={knobProps.outlined}
|
|
368
|
-
|
|
372
|
+
transition={knobProps.transition}
|
|
369
373
|
disabled={itemDisabled}
|
|
370
374
|
{...(itemDescribedBy ? { "aria-describedby": itemDescribedBy } : undefined)}
|
|
371
375
|
// LC-40 DISABLED-VISIBLE (was DG-ST-03 hand-roll): segments are
|
|
372
|
-
// text-bearing chrome — a disabled segment drops the live
|
|
373
|
-
// fill entirely
|
|
374
|
-
//
|
|
375
|
-
//
|
|
376
|
-
//
|
|
377
|
-
// option stays visible (Axiom 6), not aria-only.
|
|
376
|
+
// text-bearing chrome — a disabled segment drops the live selected
|
|
377
|
+
// fill entirely, so the wash owns the chrome and the label pins to
|
|
378
|
+
// the lowest AA tier below. A SELECTED disabled segment takes the
|
|
379
|
+
// recipe's stronger selected tier so the chosen option stays
|
|
380
|
+
// visible (Axiom 6), not aria-only.
|
|
378
381
|
{...(selected && !itemDisabled ? activeColors : undefined)}
|
|
379
|
-
{...(selected && !itemDisabled ? { active: true, activeStyle: activeColors } : undefined)}
|
|
380
382
|
{...(itemDisabled
|
|
381
383
|
? selected
|
|
382
384
|
? disabledState.selectedSurfaceKnobProps
|
|
@@ -15,7 +15,9 @@ const manyOptions = Array.from({ length: 60 }, (_, i) => ({
|
|
|
15
15
|
label: `Option ${i + 1}`,
|
|
16
16
|
}));
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
// Six entries: short enough that the floating list never scrolls (the story's
|
|
19
|
+
// point) while clearing the ≤5 `select-too-few-options` guardrail (DG-CTRL-01).
|
|
20
|
+
const fewOptions = Array.from({ length: 6 }, (_, i) => ({
|
|
19
21
|
value: `option-${i + 1}`,
|
|
20
22
|
label: `Option ${i + 1}`,
|
|
21
23
|
}));
|
|
@@ -45,7 +47,7 @@ export const ShortSelect: Story = {
|
|
|
45
47
|
<YStack maxWidth={320}>
|
|
46
48
|
<Select
|
|
47
49
|
id="fls-short"
|
|
48
|
-
label="
|
|
50
|
+
label="Six options"
|
|
49
51
|
options={fewOptions}
|
|
50
52
|
helperText="No arrows expected"
|
|
51
53
|
/>
|
|
@@ -66,7 +66,7 @@ export function TimeColumn({
|
|
|
66
66
|
justifyContent="center"
|
|
67
67
|
backgroundColor={isSelected ? formInputColors.background.focus : "transparent"}
|
|
68
68
|
hoverStyle={{ backgroundColor: formInputColors.background.focus }}
|
|
69
|
-
{...(knobProps.transition ? {
|
|
69
|
+
{...(knobProps.transition ? { transition: knobProps.transition } : undefined)}
|
|
70
70
|
>
|
|
71
71
|
<Text
|
|
72
72
|
fontSize="$4"
|
|
@@ -66,6 +66,10 @@ function restoreLater(
|
|
|
66
66
|
insideRef?: RefObject<HTMLElement | null>,
|
|
67
67
|
) {
|
|
68
68
|
const restore = () => {
|
|
69
|
+
// Fires from the unmount path, so the document can be gone by now (a test
|
|
70
|
+
// environment torn down inside the retry window). `isConnected` stays
|
|
71
|
+
// stale-true on a detached node, so it does not cover this.
|
|
72
|
+
if (!canUseDom()) return;
|
|
69
73
|
const target = prevRef.current;
|
|
70
74
|
if (!target || !target.isConnected) return;
|
|
71
75
|
if (focusIsDropped(insideRef?.current ?? null)) target.focus();
|
|
@@ -102,11 +106,17 @@ export function useSheetModalFocus(open: boolean, frameRef: RefObject<HTMLElemen
|
|
|
102
106
|
|
|
103
107
|
// Focus moves in once the sheet has mounted its frame (spring start).
|
|
104
108
|
const focusIn = () => {
|
|
109
|
+
if (!canUseDom()) return;
|
|
105
110
|
if (frame.contains(document.activeElement)) return;
|
|
106
111
|
const first = frame.querySelector<HTMLElement>(FOCUSABLE);
|
|
107
112
|
(first ?? frame).focus({ preventScroll: true });
|
|
108
113
|
};
|
|
109
|
-
|
|
114
|
+
// Both frames are tracked: cancelling only the outer one leaves the inner
|
|
115
|
+
// callback live once the outer has already run.
|
|
116
|
+
let innerRaf = 0;
|
|
117
|
+
const raf = requestAnimationFrame(() => {
|
|
118
|
+
innerRaf = requestAnimationFrame(focusIn);
|
|
119
|
+
});
|
|
110
120
|
|
|
111
121
|
// Light Tab trap: cycle within the frame (modal sheet owns focus).
|
|
112
122
|
const onKeyDown = (e: KeyboardEvent) => {
|
|
@@ -132,6 +142,7 @@ export function useSheetModalFocus(open: boolean, frameRef: RefObject<HTMLElemen
|
|
|
132
142
|
frame.addEventListener("keydown", onKeyDown);
|
|
133
143
|
return () => {
|
|
134
144
|
cancelAnimationFrame(raf);
|
|
145
|
+
cancelAnimationFrame(innerRaf);
|
|
135
146
|
frame.removeEventListener("keydown", onKeyDown);
|
|
136
147
|
restoreLater(prevRef, frameRef);
|
|
137
148
|
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { bidiIsolate, t } from "./t";
|
|
3
|
+
|
|
4
|
+
describe("t (uninitialized-i18n fallback)", () => {
|
|
5
|
+
it("returns the key with {{var}} interpolation applied", () => {
|
|
6
|
+
expect(t("Delete row {{row}}", { row: 3 })).toBe("Delete row 3");
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it("leaves unknown variables as-is", () => {
|
|
10
|
+
expect(t("Delete row {{row}}", { other: 1 })).toBe("Delete row {{row}}");
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
describe("bidiIsolate (LC-58 BIDI-ISOLATION)", () => {
|
|
15
|
+
it("wraps the run in FSI…PDI so RTL contexts cannot reorder it", () => {
|
|
16
|
+
expect(bidiIsolate("1–5 of 5")).toBe("\u20681–5 of 5\u2069");
|
|
17
|
+
expect(bidiIsolate("Search...")).toBe("\u2068Search...\u2069");
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("keeps LTR content byte-identical inside the isolates", () => {
|
|
21
|
+
// First-strong isolation adds only the invisible FSI/PDI frame — the
|
|
22
|
+
// visible run is unchanged, so LTR rendering is unaffected.
|
|
23
|
+
const isolated = bidiIsolate("Search...");
|
|
24
|
+
expect(isolated.slice(1, -1)).toBe("Search...");
|
|
25
|
+
expect(isolated.startsWith("\u2068")).toBe(true);
|
|
26
|
+
expect(isolated.endsWith("\u2069")).toBe(true);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("preserves an RTL run's own base direction (first-strong semantics)", () => {
|
|
30
|
+
// An Arabic run keeps its first strong character (RTL) as the isolate's
|
|
31
|
+
// base direction — isolation never forces LTR on translated copy.
|
|
32
|
+
const rtl = "بحث…";
|
|
33
|
+
expect(bidiIsolate(rtl)).toBe(`\u2068${rtl}\u2069`);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("leaves empty strings alone (nothing to isolate)", () => {
|
|
37
|
+
expect(bidiIsolate("")).toBe("");
|
|
38
|
+
});
|
|
39
|
+
});
|
package/src/shared/t.ts
CHANGED
|
@@ -21,3 +21,23 @@ export function t(key: string, options?: TOptions): string {
|
|
|
21
21
|
}
|
|
22
22
|
return interpolate(key, options);
|
|
23
23
|
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* First-strong bidi isolation — FSI…PDI (`\u2068…\u2069`), the string form of
|
|
27
|
+
* `<bdi>` (LC-58 BIDI-ISOLATION). Same helper as `components/src/shared/t.ts`
|
|
28
|
+
* and `table/src/utils/withInterp.ts` (the interpolation-home duplication
|
|
29
|
+
* precedent) — the helper lives beside each package's `t()` interpolator.
|
|
30
|
+
* Formatted runs that mix directions inside an RTL paragraph reorder by the
|
|
31
|
+
* bidi algorithm's rules — "1–5 of 5" renders "of 5 5–1", a trailing
|
|
32
|
+
* "Search..." ellipsis flips to "…Search" — because each weak/latin segment
|
|
33
|
+
* resolves independently. Isolating the WHOLE run gives it its own base
|
|
34
|
+
* direction from its first strong character, so untranslated latin copy
|
|
35
|
+
* renders LTR as a unit while translated RTL copy still renders RTL. Apply
|
|
36
|
+
* at the interpolation site of visible strings; never per-string manual
|
|
37
|
+
* marks, never aria-labels (invisible to reorder; breaks exact-match label
|
|
38
|
+
* queries).
|
|
39
|
+
*/
|
|
40
|
+
export function bidiIsolate(text: string): string {
|
|
41
|
+
if (!text) return text;
|
|
42
|
+
return `\u2068${text}\u2069`;
|
|
43
|
+
}
|
package/types/Button/index.d.ts
CHANGED
|
@@ -40,8 +40,16 @@ export interface ButtonProps extends Omit<TamaguiButtonProps, "form" | "icon" |
|
|
|
40
40
|
* — bare `disabled` emits `bare-disabled`.
|
|
41
41
|
*/
|
|
42
42
|
disabledReason?: string;
|
|
43
|
+
/**
|
|
44
|
+
* Where the visible reason renders relative to the control. `"below"`
|
|
45
|
+
* (default) stacks it under the button — right for forms and vertical
|
|
46
|
+
* layouts. `"inline"` puts it beside the button on the same line — for
|
|
47
|
+
* toolbar/control rows, where a stacked reason breaks the row's shared
|
|
48
|
+
* control height and wraps into cramped multi-line type.
|
|
49
|
+
*/
|
|
50
|
+
disabledReasonPlacement?: "below" | "inline";
|
|
43
51
|
}
|
|
44
|
-
export declare function Button({ children, action, form: formProp, loading, accent, error, warning, success, skeleton, outlined, disabled, theme, onPress, onKeyDown, tabIndex, icon, iconAfter, compact, verb, noun, actionRole, disabledReason, ...props }: ButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
52
|
+
export declare function Button({ children, action, form: formProp, loading, accent, error, warning, success, skeleton, outlined, disabled, theme, onPress, onKeyDown, tabIndex, icon, iconAfter, compact, verb, noun, actionRole, disabledReason, disabledReasonPlacement, ...props }: ButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
45
53
|
export declare namespace Button {
|
|
46
54
|
var Icon: (props: {
|
|
47
55
|
children: React.ReactNode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Button/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,aAAa,EAClB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAQf,OAAO,EAEL,KAAK,WAAW,IAAI,kBAAkB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Button/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,aAAa,EAClB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAQf,OAAO,EAEL,KAAK,WAAW,IAAI,kBAAkB,EASvC,MAAM,SAAS,CAAC;AAIjB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAI3C,OAAO,KAAK,EAAE,UAAU,EAAuB,MAAM,cAAc,CAAC;AAyBpE,0DAA0D;AAC1D,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;AAElE,KAAK,QAAQ,GAAG,SAAS,GAAG,aAAa,CAAC;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAgF7D,MAAM,WAAW,WAAY,SAAQ,IAAI,CAAC,kBAAkB,EAAE,MAAM,GAAG,MAAM,GAAG,WAAW,CAAC;IAC1F,MAAM,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;IAC5B,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,SAAS,CAAC,EAAE,QAAQ,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;;OAMG;IACH,uBAAuB,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;CAC9C;AAED,wBAAgB,MAAM,CAAC,EACrB,QAAQ,EACR,MAAM,EACN,IAAI,EAAE,QAAQ,EACd,OAAO,EACP,MAAM,EACN,KAAK,EACL,OAAO,EACP,OAAO,EACP,QAAgB,EAChB,QAAQ,EACR,QAAQ,EACR,KAAK,EACL,OAAO,EACP,SAAS,EACT,QAAQ,EACR,IAAI,EACJ,SAAS,EACT,OAAO,EACP,IAAI,EACJ,IAAI,EACJ,UAAU,EACV,cAAc,EACd,uBAAiC,EACjC,GAAG,KAAK,EACT,EAAE,WAAW,2CAuTb;yBAhVe,MAAM;;;iBA0BS,CAAC;YAAsB,CAAC"}
|
|
@@ -10,9 +10,15 @@ export declare const EMPTY = "\u2014";
|
|
|
10
10
|
export declare function asText(v: any): string;
|
|
11
11
|
export interface NumericFormatOptions {
|
|
12
12
|
precision?: number;
|
|
13
|
-
/** ISO 4217 currency code, e.g. "USD". */
|
|
13
|
+
/** ISO 4217 currency code (or a symbol a code is known for), e.g. "USD". */
|
|
14
14
|
currency?: string;
|
|
15
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* Read-only numeric cells speak the house number registers (LC-12 render
|
|
18
|
+
* channel): the same figure reads identically in a table cell, a KPI tile
|
|
19
|
+
* and a group aggregate. `precision` pins the fraction digits a Frappe field
|
|
20
|
+
* declares; the register owns everything else.
|
|
21
|
+
*/
|
|
16
22
|
export declare function formatNumericText(num: number, options?: NumericFormatOptions): string;
|
|
17
23
|
export { ISO_DATE_ONLY } from "@multiplatform.one/theme";
|
|
18
24
|
export interface DateFormatOptions {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formatters.d.ts","sourceRoot":"","sources":["../../src/FieldDisplay/formatters.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,eAAO,MAAM,KAAK,WAAM,CAAC;AAEzB,wBAAgB,MAAM,CAAC,CAAC,EAAE,GAAG,GAAG,MAAM,CAYrC;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,
|
|
1
|
+
{"version":3,"file":"formatters.d.ts","sourceRoot":"","sources":["../../src/FieldDisplay/formatters.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,eAAO,MAAM,KAAK,WAAM,CAAC;AAEzB,wBAAgB,MAAM,CAAC,CAAC,EAAE,GAAG,GAAG,MAAM,CAYrC;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,oBAAyB,GAAG,MAAM,CAIzF;AAGD,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEzD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,GAAE,iBAAsB,GAAG,MAAM,CAIlF"}
|