@oxyhq/bloom 0.6.24 → 0.7.1
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/lib/commonjs/alert-dialog/AlertDialog.js +109 -0
- package/lib/commonjs/alert-dialog/AlertDialog.js.map +1 -0
- package/lib/commonjs/alert-dialog/AlertDialogHost.js +50 -0
- package/lib/commonjs/alert-dialog/AlertDialogHost.js.map +1 -0
- package/lib/commonjs/alert-dialog/confirm-store.js +80 -0
- package/lib/commonjs/alert-dialog/confirm-store.js.map +1 -0
- package/lib/commonjs/alert-dialog/index.js +19 -0
- package/lib/commonjs/alert-dialog/index.js.map +1 -0
- package/lib/commonjs/alert-dialog/index.web.js +19 -0
- package/lib/commonjs/alert-dialog/index.web.js.map +1 -0
- package/lib/commonjs/alert-dialog/types.js +6 -0
- package/lib/commonjs/alert-dialog/types.js.map +1 -0
- package/lib/commonjs/combobox/Combobox.js +227 -0
- package/lib/commonjs/combobox/Combobox.js.map +1 -0
- package/lib/commonjs/combobox/index.js +11 -0
- package/lib/commonjs/combobox/index.js.map +1 -0
- package/lib/commonjs/combobox/index.web.js +11 -0
- package/lib/commonjs/combobox/index.web.js.map +1 -0
- package/lib/commonjs/combobox/types.js +6 -0
- package/lib/commonjs/combobox/types.js.map +1 -0
- package/lib/commonjs/command/Command.js +256 -0
- package/lib/commonjs/command/Command.js.map +1 -0
- package/lib/commonjs/command/index.js +10 -0
- package/lib/commonjs/command/index.js.map +1 -0
- package/lib/commonjs/command/index.web.js +10 -0
- package/lib/commonjs/command/index.web.js.map +1 -0
- package/lib/commonjs/command/types.js +6 -0
- package/lib/commonjs/command/types.js.map +1 -0
- package/lib/commonjs/field/Field.js +68 -0
- package/lib/commonjs/field/Field.js.map +1 -0
- package/lib/commonjs/field/index.js +13 -0
- package/lib/commonjs/field/index.js.map +1 -0
- package/lib/commonjs/field/types.js +6 -0
- package/lib/commonjs/field/types.js.map +1 -0
- package/lib/commonjs/index.js +117 -25
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/index.web.js +117 -25
- package/lib/commonjs/index.web.js.map +1 -1
- package/lib/commonjs/input-group/InputGroup.js +172 -0
- package/lib/commonjs/input-group/InputGroup.js.map +1 -0
- package/lib/commonjs/input-group/index.js +19 -0
- package/lib/commonjs/input-group/index.js.map +1 -0
- package/lib/commonjs/input-group/types.js +6 -0
- package/lib/commonjs/input-group/types.js.map +1 -0
- package/lib/commonjs/item/Item.js +172 -0
- package/lib/commonjs/item/Item.js.map +1 -0
- package/lib/commonjs/item/index.js +13 -0
- package/lib/commonjs/item/index.js.map +1 -0
- package/lib/commonjs/item/types.js +6 -0
- package/lib/commonjs/item/types.js.map +1 -0
- package/lib/commonjs/kbd/Kbd.js +79 -0
- package/lib/commonjs/kbd/Kbd.js.map +1 -0
- package/lib/commonjs/kbd/index.js +13 -0
- package/lib/commonjs/kbd/index.js.map +1 -0
- package/lib/commonjs/kbd/types.js +6 -0
- package/lib/commonjs/kbd/types.js.map +1 -0
- package/lib/commonjs/label/Label.js +60 -0
- package/lib/commonjs/label/Label.js.map +1 -0
- package/lib/commonjs/label/index.js +13 -0
- package/lib/commonjs/label/index.js.map +1 -0
- package/lib/commonjs/label/types.js +6 -0
- package/lib/commonjs/label/types.js.map +1 -0
- package/lib/commonjs/popover/context.js +18 -0
- package/lib/commonjs/popover/context.js.map +1 -0
- package/lib/commonjs/popover/index.js +111 -0
- package/lib/commonjs/popover/index.js.map +1 -0
- package/lib/commonjs/popover/index.web.js +286 -0
- package/lib/commonjs/popover/index.web.js.map +1 -0
- package/lib/commonjs/popover/types.js +6 -0
- package/lib/commonjs/popover/types.js.map +1 -0
- package/lib/commonjs/react-native-css.d.js +2 -0
- package/lib/commonjs/react-native-css.d.js.map +1 -0
- package/lib/commonjs/slider/Slider.js +255 -0
- package/lib/commonjs/slider/Slider.js.map +1 -0
- package/lib/commonjs/slider/index.js +13 -0
- package/lib/commonjs/slider/index.js.map +1 -0
- package/lib/commonjs/slider/types.js +6 -0
- package/lib/commonjs/slider/types.js.map +1 -0
- package/lib/commonjs/theme/BloomThemeProvider.js +39 -7
- package/lib/commonjs/theme/BloomThemeProvider.js.map +1 -1
- package/lib/commonjs/theme/color-presets.js +118 -118
- package/lib/commonjs/theme/color-presets.js.map +1 -1
- package/lib/commonjs/theme/color-scope/index.js +28 -6
- package/lib/commonjs/theme/color-scope/index.js.map +1 -1
- package/lib/commonjs/theme/color-scope/style-builder.js +35 -0
- package/lib/commonjs/theme/color-scope/style-builder.js.map +1 -1
- package/lib/commonjs/theme/native-root-vars.js +105 -0
- package/lib/commonjs/theme/native-root-vars.js.map +1 -0
- package/lib/commonjs/theme/native-root-vars.web.js +27 -0
- package/lib/commonjs/theme/native-root-vars.web.js.map +1 -0
- package/lib/commonjs/theme/preset-vars.js +4 -1
- package/lib/commonjs/theme/preset-vars.js.map +1 -1
- package/lib/module/alert-dialog/AlertDialog.js +104 -0
- package/lib/module/alert-dialog/AlertDialog.js.map +1 -0
- package/lib/module/alert-dialog/AlertDialogHost.js +45 -0
- package/lib/module/alert-dialog/AlertDialogHost.js.map +1 -0
- package/lib/module/alert-dialog/confirm-store.js +73 -0
- package/lib/module/alert-dialog/confirm-store.js.map +1 -0
- package/lib/module/alert-dialog/index.js +9 -0
- package/lib/module/alert-dialog/index.js.map +1 -0
- package/lib/module/alert-dialog/index.web.js +9 -0
- package/lib/module/alert-dialog/index.web.js.map +1 -0
- package/lib/module/alert-dialog/types.js +4 -0
- package/lib/module/alert-dialog/types.js.map +1 -0
- package/lib/module/combobox/Combobox.js +222 -0
- package/lib/module/combobox/Combobox.js.map +1 -0
- package/lib/module/combobox/index.js +6 -0
- package/lib/module/combobox/index.js.map +1 -0
- package/lib/module/combobox/index.web.js +6 -0
- package/lib/module/combobox/index.web.js.map +1 -0
- package/lib/module/combobox/types.js +4 -0
- package/lib/module/combobox/types.js.map +1 -0
- package/lib/module/command/Command.js +251 -0
- package/lib/module/command/Command.js.map +1 -0
- package/lib/module/command/index.js +6 -0
- package/lib/module/command/index.js.map +1 -0
- package/lib/module/command/index.web.js +6 -0
- package/lib/module/command/index.web.js.map +1 -0
- package/lib/module/command/types.js +4 -0
- package/lib/module/command/types.js.map +1 -0
- package/lib/module/field/Field.js +63 -0
- package/lib/module/field/Field.js.map +1 -0
- package/lib/module/field/index.js +4 -0
- package/lib/module/field/index.js.map +1 -0
- package/lib/module/field/types.js +4 -0
- package/lib/module/field/types.js.map +1 -0
- package/lib/module/index.js +10 -3
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.web.js +10 -3
- package/lib/module/index.web.js.map +1 -1
- package/lib/module/input-group/InputGroup.js +167 -0
- package/lib/module/input-group/InputGroup.js.map +1 -0
- package/lib/module/input-group/index.js +4 -0
- package/lib/module/input-group/index.js.map +1 -0
- package/lib/module/input-group/types.js +4 -0
- package/lib/module/input-group/types.js.map +1 -0
- package/lib/module/item/Item.js +167 -0
- package/lib/module/item/Item.js.map +1 -0
- package/lib/module/item/index.js +4 -0
- package/lib/module/item/index.js.map +1 -0
- package/lib/module/item/types.js +4 -0
- package/lib/module/item/types.js.map +1 -0
- package/lib/module/kbd/Kbd.js +74 -0
- package/lib/module/kbd/Kbd.js.map +1 -0
- package/lib/module/kbd/index.js +4 -0
- package/lib/module/kbd/index.js.map +1 -0
- package/lib/module/kbd/types.js +4 -0
- package/lib/module/kbd/types.js.map +1 -0
- package/lib/module/label/Label.js +55 -0
- package/lib/module/label/Label.js.map +1 -0
- package/lib/module/label/index.js +4 -0
- package/lib/module/label/index.js.map +1 -0
- package/lib/module/label/types.js +4 -0
- package/lib/module/label/types.js.map +1 -0
- package/lib/module/popover/context.js +13 -0
- package/lib/module/popover/context.js.map +1 -0
- package/lib/module/popover/index.js +95 -0
- package/lib/module/popover/index.js.map +1 -0
- package/lib/module/popover/index.web.js +274 -0
- package/lib/module/popover/index.web.js.map +1 -0
- package/lib/module/popover/types.js +4 -0
- package/lib/module/popover/types.js.map +1 -0
- package/lib/module/react-native-css.d.js +2 -0
- package/lib/module/react-native-css.d.js.map +1 -0
- package/lib/module/slider/Slider.js +250 -0
- package/lib/module/slider/Slider.js.map +1 -0
- package/lib/module/slider/index.js +4 -0
- package/lib/module/slider/index.js.map +1 -0
- package/lib/module/slider/types.js +4 -0
- package/lib/module/slider/types.js.map +1 -0
- package/lib/module/theme/BloomThemeProvider.js +40 -8
- package/lib/module/theme/BloomThemeProvider.js.map +1 -1
- package/lib/module/theme/color-presets.js +118 -118
- package/lib/module/theme/color-presets.js.map +1 -1
- package/lib/module/theme/color-scope/index.js +29 -7
- package/lib/module/theme/color-scope/index.js.map +1 -1
- package/lib/module/theme/color-scope/style-builder.js +35 -0
- package/lib/module/theme/color-scope/style-builder.js.map +1 -1
- package/lib/module/theme/native-root-vars.js +101 -0
- package/lib/module/theme/native-root-vars.js.map +1 -0
- package/lib/module/theme/native-root-vars.web.js +23 -0
- package/lib/module/theme/native-root-vars.web.js.map +1 -0
- package/lib/module/theme/preset-vars.js +4 -1
- package/lib/module/theme/preset-vars.js.map +1 -1
- package/lib/typescript/commonjs/alert-dialog/AlertDialog.d.ts +21 -0
- package/lib/typescript/commonjs/alert-dialog/AlertDialog.d.ts.map +1 -0
- package/lib/typescript/commonjs/alert-dialog/AlertDialogHost.d.ts +15 -0
- package/lib/typescript/commonjs/alert-dialog/AlertDialogHost.d.ts.map +1 -0
- package/lib/typescript/commonjs/alert-dialog/confirm-store.d.ts +31 -0
- package/lib/typescript/commonjs/alert-dialog/confirm-store.d.ts.map +1 -0
- package/lib/typescript/commonjs/alert-dialog/index.d.ts +8 -0
- package/lib/typescript/commonjs/alert-dialog/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/alert-dialog/index.web.d.ts +8 -0
- package/lib/typescript/commonjs/alert-dialog/index.web.d.ts.map +1 -0
- package/lib/typescript/commonjs/alert-dialog/types.d.ts +44 -0
- package/lib/typescript/commonjs/alert-dialog/types.d.ts.map +1 -0
- package/lib/typescript/commonjs/combobox/Combobox.d.ts +33 -0
- package/lib/typescript/commonjs/combobox/Combobox.d.ts.map +1 -0
- package/lib/typescript/commonjs/combobox/index.d.ts +6 -0
- package/lib/typescript/commonjs/combobox/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/combobox/index.web.d.ts +6 -0
- package/lib/typescript/commonjs/combobox/index.web.d.ts.map +1 -0
- package/lib/typescript/commonjs/combobox/types.d.ts +40 -0
- package/lib/typescript/commonjs/combobox/types.d.ts.map +1 -0
- package/lib/typescript/commonjs/command/Command.d.ts +22 -0
- package/lib/typescript/commonjs/command/Command.d.ts.map +1 -0
- package/lib/typescript/commonjs/command/index.d.ts +6 -0
- package/lib/typescript/commonjs/command/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/command/index.web.d.ts +6 -0
- package/lib/typescript/commonjs/command/index.web.d.ts.map +1 -0
- package/lib/typescript/commonjs/command/types.d.ts +46 -0
- package/lib/typescript/commonjs/command/types.d.ts.map +1 -0
- package/lib/typescript/commonjs/field/Field.d.ts +4 -0
- package/lib/typescript/commonjs/field/Field.d.ts.map +1 -0
- package/lib/typescript/commonjs/field/index.d.ts +3 -0
- package/lib/typescript/commonjs/field/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/field/types.d.ts +26 -0
- package/lib/typescript/commonjs/field/types.d.ts.map +1 -0
- package/lib/typescript/commonjs/icons/common.d.ts +8 -8
- package/lib/typescript/commonjs/index.d.ts +19 -0
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.web.d.ts +19 -0
- package/lib/typescript/commonjs/index.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/input-group/InputGroup.d.ts +9 -0
- package/lib/typescript/commonjs/input-group/InputGroup.d.ts.map +1 -0
- package/lib/typescript/commonjs/input-group/index.d.ts +3 -0
- package/lib/typescript/commonjs/input-group/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/input-group/types.d.ts +35 -0
- package/lib/typescript/commonjs/input-group/types.d.ts.map +1 -0
- package/lib/typescript/commonjs/item/Item.d.ts +4 -0
- package/lib/typescript/commonjs/item/Item.d.ts.map +1 -0
- package/lib/typescript/commonjs/item/index.d.ts +3 -0
- package/lib/typescript/commonjs/item/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/item/types.d.ts +45 -0
- package/lib/typescript/commonjs/item/types.d.ts.map +1 -0
- package/lib/typescript/commonjs/kbd/Kbd.d.ts +4 -0
- package/lib/typescript/commonjs/kbd/Kbd.d.ts.map +1 -0
- package/lib/typescript/commonjs/kbd/index.d.ts +3 -0
- package/lib/typescript/commonjs/kbd/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/kbd/types.d.ts +13 -0
- package/lib/typescript/commonjs/kbd/types.d.ts.map +1 -0
- package/lib/typescript/commonjs/label/Label.d.ts +4 -0
- package/lib/typescript/commonjs/label/Label.d.ts.map +1 -0
- package/lib/typescript/commonjs/label/index.d.ts +3 -0
- package/lib/typescript/commonjs/label/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/label/types.d.ts +27 -0
- package/lib/typescript/commonjs/label/types.d.ts.map +1 -0
- package/lib/typescript/commonjs/popover/context.d.ts +15 -0
- package/lib/typescript/commonjs/popover/context.d.ts.map +1 -0
- package/lib/typescript/commonjs/popover/index.d.ts +14 -0
- package/lib/typescript/commonjs/popover/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/popover/index.web.d.ts +14 -0
- package/lib/typescript/commonjs/popover/index.web.d.ts.map +1 -0
- package/lib/typescript/commonjs/popover/types.d.ts +54 -0
- package/lib/typescript/commonjs/popover/types.d.ts.map +1 -0
- package/lib/typescript/commonjs/slider/Slider.d.ts +4 -0
- package/lib/typescript/commonjs/slider/Slider.d.ts.map +1 -0
- package/lib/typescript/commonjs/slider/index.d.ts +3 -0
- package/lib/typescript/commonjs/slider/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/slider/types.d.ts +30 -0
- package/lib/typescript/commonjs/slider/types.d.ts.map +1 -0
- package/lib/typescript/commonjs/theme/BloomThemeProvider.d.ts.map +1 -1
- package/lib/typescript/commonjs/theme/color-scope/index.d.ts +9 -2
- package/lib/typescript/commonjs/theme/color-scope/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/theme/color-scope/style-builder.d.ts +32 -0
- package/lib/typescript/commonjs/theme/color-scope/style-builder.d.ts.map +1 -1
- package/lib/typescript/commonjs/theme/native-root-vars.d.ts +89 -0
- package/lib/typescript/commonjs/theme/native-root-vars.d.ts.map +1 -0
- package/lib/typescript/commonjs/theme/native-root-vars.web.d.ts +20 -0
- package/lib/typescript/commonjs/theme/native-root-vars.web.d.ts.map +1 -0
- package/lib/typescript/commonjs/theme/preset-vars.d.ts.map +1 -1
- package/lib/typescript/module/alert-dialog/AlertDialog.d.ts +21 -0
- package/lib/typescript/module/alert-dialog/AlertDialog.d.ts.map +1 -0
- package/lib/typescript/module/alert-dialog/AlertDialogHost.d.ts +15 -0
- package/lib/typescript/module/alert-dialog/AlertDialogHost.d.ts.map +1 -0
- package/lib/typescript/module/alert-dialog/confirm-store.d.ts +31 -0
- package/lib/typescript/module/alert-dialog/confirm-store.d.ts.map +1 -0
- package/lib/typescript/module/alert-dialog/index.d.ts +8 -0
- package/lib/typescript/module/alert-dialog/index.d.ts.map +1 -0
- package/lib/typescript/module/alert-dialog/index.web.d.ts +8 -0
- package/lib/typescript/module/alert-dialog/index.web.d.ts.map +1 -0
- package/lib/typescript/module/alert-dialog/types.d.ts +44 -0
- package/lib/typescript/module/alert-dialog/types.d.ts.map +1 -0
- package/lib/typescript/module/combobox/Combobox.d.ts +33 -0
- package/lib/typescript/module/combobox/Combobox.d.ts.map +1 -0
- package/lib/typescript/module/combobox/index.d.ts +6 -0
- package/lib/typescript/module/combobox/index.d.ts.map +1 -0
- package/lib/typescript/module/combobox/index.web.d.ts +6 -0
- package/lib/typescript/module/combobox/index.web.d.ts.map +1 -0
- package/lib/typescript/module/combobox/types.d.ts +40 -0
- package/lib/typescript/module/combobox/types.d.ts.map +1 -0
- package/lib/typescript/module/command/Command.d.ts +22 -0
- package/lib/typescript/module/command/Command.d.ts.map +1 -0
- package/lib/typescript/module/command/index.d.ts +6 -0
- package/lib/typescript/module/command/index.d.ts.map +1 -0
- package/lib/typescript/module/command/index.web.d.ts +6 -0
- package/lib/typescript/module/command/index.web.d.ts.map +1 -0
- package/lib/typescript/module/command/types.d.ts +46 -0
- package/lib/typescript/module/command/types.d.ts.map +1 -0
- package/lib/typescript/module/field/Field.d.ts +4 -0
- package/lib/typescript/module/field/Field.d.ts.map +1 -0
- package/lib/typescript/module/field/index.d.ts +3 -0
- package/lib/typescript/module/field/index.d.ts.map +1 -0
- package/lib/typescript/module/field/types.d.ts +26 -0
- package/lib/typescript/module/field/types.d.ts.map +1 -0
- package/lib/typescript/module/icons/common.d.ts +8 -8
- package/lib/typescript/module/index.d.ts +19 -0
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/index.web.d.ts +19 -0
- package/lib/typescript/module/index.web.d.ts.map +1 -1
- package/lib/typescript/module/input-group/InputGroup.d.ts +9 -0
- package/lib/typescript/module/input-group/InputGroup.d.ts.map +1 -0
- package/lib/typescript/module/input-group/index.d.ts +3 -0
- package/lib/typescript/module/input-group/index.d.ts.map +1 -0
- package/lib/typescript/module/input-group/types.d.ts +35 -0
- package/lib/typescript/module/input-group/types.d.ts.map +1 -0
- package/lib/typescript/module/item/Item.d.ts +4 -0
- package/lib/typescript/module/item/Item.d.ts.map +1 -0
- package/lib/typescript/module/item/index.d.ts +3 -0
- package/lib/typescript/module/item/index.d.ts.map +1 -0
- package/lib/typescript/module/item/types.d.ts +45 -0
- package/lib/typescript/module/item/types.d.ts.map +1 -0
- package/lib/typescript/module/kbd/Kbd.d.ts +4 -0
- package/lib/typescript/module/kbd/Kbd.d.ts.map +1 -0
- package/lib/typescript/module/kbd/index.d.ts +3 -0
- package/lib/typescript/module/kbd/index.d.ts.map +1 -0
- package/lib/typescript/module/kbd/types.d.ts +13 -0
- package/lib/typescript/module/kbd/types.d.ts.map +1 -0
- package/lib/typescript/module/label/Label.d.ts +4 -0
- package/lib/typescript/module/label/Label.d.ts.map +1 -0
- package/lib/typescript/module/label/index.d.ts +3 -0
- package/lib/typescript/module/label/index.d.ts.map +1 -0
- package/lib/typescript/module/label/types.d.ts +27 -0
- package/lib/typescript/module/label/types.d.ts.map +1 -0
- package/lib/typescript/module/popover/context.d.ts +15 -0
- package/lib/typescript/module/popover/context.d.ts.map +1 -0
- package/lib/typescript/module/popover/index.d.ts +14 -0
- package/lib/typescript/module/popover/index.d.ts.map +1 -0
- package/lib/typescript/module/popover/index.web.d.ts +14 -0
- package/lib/typescript/module/popover/index.web.d.ts.map +1 -0
- package/lib/typescript/module/popover/types.d.ts +54 -0
- package/lib/typescript/module/popover/types.d.ts.map +1 -0
- package/lib/typescript/module/slider/Slider.d.ts +4 -0
- package/lib/typescript/module/slider/Slider.d.ts.map +1 -0
- package/lib/typescript/module/slider/index.d.ts +3 -0
- package/lib/typescript/module/slider/index.d.ts.map +1 -0
- package/lib/typescript/module/slider/types.d.ts +30 -0
- package/lib/typescript/module/slider/types.d.ts.map +1 -0
- package/lib/typescript/module/theme/BloomThemeProvider.d.ts.map +1 -1
- package/lib/typescript/module/theme/color-scope/index.d.ts +9 -2
- package/lib/typescript/module/theme/color-scope/index.d.ts.map +1 -1
- package/lib/typescript/module/theme/color-scope/style-builder.d.ts +32 -0
- package/lib/typescript/module/theme/color-scope/style-builder.d.ts.map +1 -1
- package/lib/typescript/module/theme/native-root-vars.d.ts +89 -0
- package/lib/typescript/module/theme/native-root-vars.d.ts.map +1 -0
- package/lib/typescript/module/theme/native-root-vars.web.d.ts +20 -0
- package/lib/typescript/module/theme/native-root-vars.web.d.ts.map +1 -0
- package/lib/typescript/module/theme/preset-vars.d.ts.map +1 -1
- package/package.json +141 -1
- package/src/__tests__/Field.test.tsx +55 -0
- package/src/__tests__/InputGroup.test.tsx +44 -0
- package/src/__tests__/Item.test.tsx +73 -0
- package/src/__tests__/Kbd.test.tsx +27 -0
- package/src/__tests__/Label.test.tsx +30 -0
- package/src/__tests__/Slider.test.tsx +38 -0
- package/src/__tests__/confirm-store.test.ts +58 -0
- package/src/__tests__/native-root-vars.test.ts +125 -0
- package/src/alert-dialog/AlertDialog.stories.tsx +61 -0
- package/src/alert-dialog/AlertDialog.tsx +120 -0
- package/src/alert-dialog/AlertDialogHost.tsx +51 -0
- package/src/alert-dialog/confirm-store.ts +77 -0
- package/src/alert-dialog/index.ts +13 -0
- package/src/alert-dialog/index.web.ts +13 -0
- package/src/alert-dialog/types.ts +46 -0
- package/src/combobox/Combobox.stories.tsx +40 -0
- package/src/combobox/Combobox.tsx +274 -0
- package/src/combobox/index.ts +6 -0
- package/src/combobox/index.web.ts +6 -0
- package/src/combobox/types.ts +41 -0
- package/src/command/Command.stories.tsx +60 -0
- package/src/command/Command.tsx +276 -0
- package/src/command/index.ts +6 -0
- package/src/command/index.web.ts +6 -0
- package/src/command/types.ts +47 -0
- package/src/field/Field.stories.tsx +54 -0
- package/src/field/Field.tsx +77 -0
- package/src/field/index.ts +2 -0
- package/src/field/types.ts +26 -0
- package/src/index.ts +23 -0
- package/src/index.web.ts +23 -0
- package/src/input-group/InputGroup.stories.tsx +65 -0
- package/src/input-group/InputGroup.tsx +184 -0
- package/src/input-group/index.ts +2 -0
- package/src/input-group/types.ts +36 -0
- package/src/item/Item.stories.tsx +43 -0
- package/src/item/Item.tsx +180 -0
- package/src/item/index.ts +2 -0
- package/src/item/types.ts +45 -0
- package/src/kbd/Kbd.stories.tsx +36 -0
- package/src/kbd/Kbd.tsx +76 -0
- package/src/kbd/index.ts +2 -0
- package/src/kbd/types.ts +13 -0
- package/src/label/Label.stories.tsx +32 -0
- package/src/label/Label.tsx +64 -0
- package/src/label/index.ts +2 -0
- package/src/label/types.ts +27 -0
- package/src/popover/Popover.stories.tsx +61 -0
- package/src/popover/context.ts +26 -0
- package/src/popover/index.tsx +104 -0
- package/src/popover/index.web.tsx +325 -0
- package/src/popover/types.ts +60 -0
- package/src/react-native-css.d.ts +69 -0
- package/src/slider/Slider.stories.tsx +46 -0
- package/src/slider/Slider.tsx +275 -0
- package/src/slider/index.ts +2 -0
- package/src/slider/types.ts +30 -0
- package/src/theme/BloomThemeProvider.tsx +32 -6
- package/src/theme/color-presets.ts +118 -118
- package/src/theme/color-scope/index.tsx +30 -8
- package/src/theme/color-scope/style-builder.ts +40 -0
- package/src/theme/native-root-vars.ts +102 -0
- package/src/theme/native-root-vars.web.ts +22 -0
- package/src/theme/preset-vars.ts +4 -1
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import {
|
|
2
|
+
confirm,
|
|
3
|
+
getConfirmQueue,
|
|
4
|
+
resolveConfirm,
|
|
5
|
+
subscribeConfirms,
|
|
6
|
+
} from '../alert-dialog/confirm-store';
|
|
7
|
+
|
|
8
|
+
describe('confirm-store', () => {
|
|
9
|
+
afterEach(() => {
|
|
10
|
+
// Drain any leftover entries between tests.
|
|
11
|
+
for (const entry of [...getConfirmQueue()]) {
|
|
12
|
+
resolveConfirm(entry.id, false);
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('enqueues an entry and delivers it to a subscriber', () => {
|
|
17
|
+
const seen: number[] = [];
|
|
18
|
+
const unsub = subscribeConfirms((q) => seen.push(q.length));
|
|
19
|
+
|
|
20
|
+
void confirm({ title: 'Delete?' });
|
|
21
|
+
|
|
22
|
+
expect(getConfirmQueue()).toHaveLength(1);
|
|
23
|
+
expect(getConfirmQueue()[0]?.title).toBe('Delete?');
|
|
24
|
+
// Initial delivery (0) + enqueue (1).
|
|
25
|
+
expect(seen[seen.length - 1]).toBe(1);
|
|
26
|
+
unsub();
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('resolves the promise with true on confirm', async () => {
|
|
30
|
+
const promise = confirm({ title: 'Save?' });
|
|
31
|
+
const id = getConfirmQueue()[0]?.id;
|
|
32
|
+
expect(id).toBeTruthy();
|
|
33
|
+
if (id) resolveConfirm(id, true);
|
|
34
|
+
await expect(promise).resolves.toBe(true);
|
|
35
|
+
expect(getConfirmQueue()).toHaveLength(0);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('resolves the promise with false on cancel', async () => {
|
|
39
|
+
const promise = confirm({ title: 'Discard?' });
|
|
40
|
+
const id = getConfirmQueue()[0]?.id;
|
|
41
|
+
if (id) resolveConfirm(id, false);
|
|
42
|
+
await expect(promise).resolves.toBe(false);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('drains queued entries to a late subscriber', () => {
|
|
46
|
+
void confirm({ title: 'Queued before subscribe' });
|
|
47
|
+
let delivered: number | null = null;
|
|
48
|
+
const unsub = subscribeConfirms((q) => {
|
|
49
|
+
delivered = q.length;
|
|
50
|
+
});
|
|
51
|
+
expect(delivered).toBe(1);
|
|
52
|
+
unsub();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('ignores resolving an unknown id', () => {
|
|
56
|
+
expect(() => resolveConfirm('does-not-exist', true)).not.toThrow();
|
|
57
|
+
});
|
|
58
|
+
});
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
type SetCall = ReadonlyArray<readonly [string]>;
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Verifies the native/default variant `theme/native-root-vars.ts` publishes the
|
|
5
|
+
* active preset into react-native-css's GLOBAL `rootVariables` family with the
|
|
6
|
+
* exact keying and value shape react-native-css itself uses for compiled `:root`
|
|
7
|
+
* vars, and that the web fork `theme/native-root-vars.web.ts` is an inert no-op.
|
|
8
|
+
*
|
|
9
|
+
* - keys are written WITHOUT the leading `--` (the family is keyed by the bare
|
|
10
|
+
* name — confirmed against react-native-css@3.0.7's compiler, which stores
|
|
11
|
+
* `:root { --x }` via `slice(2)` and looks up `var(--x)` by the bare name);
|
|
12
|
+
* - each value is a single-element value-array `[[value]]` (`VariableValue[]`);
|
|
13
|
+
* - the native variant reaches react-native-css via a STATIC ESM import (so
|
|
14
|
+
* Metro resolves the `module` build — the SAME family the renderer reads);
|
|
15
|
+
* - the web variant never imports react-native-css and writes nothing.
|
|
16
|
+
*
|
|
17
|
+
* react-native-css is NOT a Bloom dependency (it arrives transitively via the
|
|
18
|
+
* host's NativeWind install), so the subpath is mocked virtually here — both for
|
|
19
|
+
* the runtime `.set` capture AND so ts-jest can compile the static import. The
|
|
20
|
+
* ambient `src/react-native-css.d.ts` declares the subpath's types for `tsc`.
|
|
21
|
+
*/
|
|
22
|
+
describe('applyNativeRootVars (native variant)', () => {
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
jest.resetModules();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('writes preset vars to rootVariables with the leading -- stripped', () => {
|
|
28
|
+
const sets: Record<string, SetCall> = {};
|
|
29
|
+
|
|
30
|
+
jest.isolateModules(() => {
|
|
31
|
+
jest.doMock(
|
|
32
|
+
'react-native-css/native-internal',
|
|
33
|
+
() => ({
|
|
34
|
+
rootVariables: (name: string) => ({
|
|
35
|
+
set: (value: SetCall) => {
|
|
36
|
+
sets[name] = value;
|
|
37
|
+
},
|
|
38
|
+
}),
|
|
39
|
+
}),
|
|
40
|
+
{ virtual: true },
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
const { applyNativeRootVars } = require('../theme/native-root-vars') as {
|
|
44
|
+
applyNativeRootVars: (preset: string, mode: 'light' | 'dark') => void;
|
|
45
|
+
};
|
|
46
|
+
applyNativeRootVars('blue', 'light');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// Keys are bare (no `--`), and the raw HSL triple is present unwrapped.
|
|
50
|
+
expect(sets).toHaveProperty('primary');
|
|
51
|
+
expect(sets).not.toHaveProperty('--primary');
|
|
52
|
+
expect(sets.primary).toEqual([['205 87% 53%']]);
|
|
53
|
+
|
|
54
|
+
// Resolved Tailwind v4 `--color-*` vars are written too, also bare-keyed.
|
|
55
|
+
expect(sets).toHaveProperty('color-primary');
|
|
56
|
+
expect(sets['color-primary']).toEqual([['hsl(205 87% 53%)']]);
|
|
57
|
+
|
|
58
|
+
// Every value is a single-element value-array `[[value]]` of strings.
|
|
59
|
+
for (const value of Object.values(sets)) {
|
|
60
|
+
expect(Array.isArray(value)).toBe(true);
|
|
61
|
+
expect(value).toHaveLength(1);
|
|
62
|
+
expect(value[0]).toHaveLength(1);
|
|
63
|
+
expect(typeof value[0]?.[0]).toBe('string');
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('reflects the resolved mode (dark preset differs from light)', () => {
|
|
68
|
+
const collect = (mode: 'light' | 'dark'): Record<string, SetCall> => {
|
|
69
|
+
const sets: Record<string, SetCall> = {};
|
|
70
|
+
jest.isolateModules(() => {
|
|
71
|
+
jest.doMock(
|
|
72
|
+
'react-native-css/native-internal',
|
|
73
|
+
() => ({
|
|
74
|
+
rootVariables: (name: string) => ({
|
|
75
|
+
set: (value: SetCall) => {
|
|
76
|
+
sets[name] = value;
|
|
77
|
+
},
|
|
78
|
+
}),
|
|
79
|
+
}),
|
|
80
|
+
{ virtual: true },
|
|
81
|
+
);
|
|
82
|
+
const { applyNativeRootVars } = require('../theme/native-root-vars') as {
|
|
83
|
+
applyNativeRootVars: (preset: string, mode: 'light' | 'dark') => void;
|
|
84
|
+
};
|
|
85
|
+
applyNativeRootVars('teal', mode);
|
|
86
|
+
});
|
|
87
|
+
return sets;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
expect(collect('light').background).not.toEqual(collect('dark').background);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('guards when rootVariables is not callable (defensive, never throws)', () => {
|
|
94
|
+
jest.isolateModules(() => {
|
|
95
|
+
jest.doMock(
|
|
96
|
+
'react-native-css/native-internal',
|
|
97
|
+
() => ({ rootVariables: undefined }),
|
|
98
|
+
{ virtual: true },
|
|
99
|
+
);
|
|
100
|
+
const { applyNativeRootVars } = require('../theme/native-root-vars') as {
|
|
101
|
+
applyNativeRootVars: (preset: string, mode: 'light' | 'dark') => void;
|
|
102
|
+
};
|
|
103
|
+
expect(() => applyNativeRootVars('blue', 'light')).not.toThrow();
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
describe('applyNativeRootVars (web fork)', () => {
|
|
109
|
+
beforeEach(() => {
|
|
110
|
+
jest.resetModules();
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('no-ops on web (vars are written to documentElement there instead)', () => {
|
|
114
|
+
// The web fork must never touch react-native-css. We assert it neither
|
|
115
|
+
// imports the subpath nor throws — it is a pure no-op with the same
|
|
116
|
+
// signature as the native variant.
|
|
117
|
+
jest.isolateModules(() => {
|
|
118
|
+
const { applyNativeRootVars } = require('../theme/native-root-vars.web') as {
|
|
119
|
+
applyNativeRootVars: (preset: string, mode: 'light' | 'dark') => void;
|
|
120
|
+
};
|
|
121
|
+
expect(() => applyNativeRootVars('blue', 'light')).not.toThrow();
|
|
122
|
+
expect(applyNativeRootVars('blue', 'light')).toBeUndefined();
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
});
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { View } from 'react-native';
|
|
3
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
4
|
+
|
|
5
|
+
import { AlertDialog, AlertDialogHost, confirm } from './index';
|
|
6
|
+
import { Button } from '../button';
|
|
7
|
+
import { Text } from '../typography';
|
|
8
|
+
|
|
9
|
+
const meta: Meta = {
|
|
10
|
+
title: 'Overlays/AlertDialog',
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export default meta;
|
|
14
|
+
|
|
15
|
+
type Story = StoryObj;
|
|
16
|
+
|
|
17
|
+
export const Declarative: Story = {
|
|
18
|
+
render: () => {
|
|
19
|
+
const [open, setOpen] = useState(false);
|
|
20
|
+
return (
|
|
21
|
+
<View style={{ padding: 40 }}>
|
|
22
|
+
<Button onPress={() => setOpen(true)}>Delete app</Button>
|
|
23
|
+
<AlertDialog
|
|
24
|
+
visible={open}
|
|
25
|
+
onClose={() => setOpen(false)}
|
|
26
|
+
title="Delete this app?"
|
|
27
|
+
description="This permanently removes the application and all of its credentials. This cannot be undone."
|
|
28
|
+
confirmLabel="Delete"
|
|
29
|
+
destructive
|
|
30
|
+
onConfirm={() => {}}
|
|
31
|
+
/>
|
|
32
|
+
</View>
|
|
33
|
+
);
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
function ImperativeDemo() {
|
|
38
|
+
const [result, setResult] = useState<string>('—');
|
|
39
|
+
return (
|
|
40
|
+
<View style={{ padding: 40, gap: 12 }}>
|
|
41
|
+
<AlertDialogHost />
|
|
42
|
+
<Button
|
|
43
|
+
onPress={async () => {
|
|
44
|
+
const ok = await confirm({
|
|
45
|
+
title: 'Sign out everywhere?',
|
|
46
|
+
description: 'You will need to sign in again on all devices.',
|
|
47
|
+
confirmLabel: 'Sign out',
|
|
48
|
+
destructive: true,
|
|
49
|
+
});
|
|
50
|
+
setResult(ok ? 'confirmed' : 'cancelled');
|
|
51
|
+
}}>
|
|
52
|
+
Sign out everywhere
|
|
53
|
+
</Button>
|
|
54
|
+
<Text>{`Result: ${result}`}</Text>
|
|
55
|
+
</View>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export const ImperativeConfirm: Story = {
|
|
60
|
+
render: () => <ImperativeDemo />,
|
|
61
|
+
};
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import React, { memo, useCallback } from 'react';
|
|
2
|
+
import { StyleSheet, View } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import { Button } from '../button';
|
|
5
|
+
import { useTheme } from '../theme/use-theme';
|
|
6
|
+
import { Text } from '../typography';
|
|
7
|
+
import { fontSize, space } from '../styles/tokens';
|
|
8
|
+
import type { CenteredDialogProps } from '../dialog';
|
|
9
|
+
import type { AlertDialogProps } from './types';
|
|
10
|
+
|
|
11
|
+
type CenteredDialogComponent = React.ComponentType<CenteredDialogProps>;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Build the `AlertDialog` component bound to a platform `CenteredDialog`.
|
|
15
|
+
*
|
|
16
|
+
* `CenteredDialog` is platform-forked (native RN `Modal` vs pure-DOM web
|
|
17
|
+
* overlay), and this repo never relies on implicit `.web` resolution — the
|
|
18
|
+
* platform entry files (`index.ts` / `index.web.ts`) inject the correct
|
|
19
|
+
* `CenteredDialog` here. The body below is single-source, no duplication.
|
|
20
|
+
*
|
|
21
|
+
* `AlertDialog` is a thin wrapper over `CenteredDialog` that lays out a title,
|
|
22
|
+
* description and a confirm/cancel action row. Reach for the imperative
|
|
23
|
+
* `confirm()` helper + `<AlertDialogHost />` to trigger a confirm from an
|
|
24
|
+
* event handler without owning visible state.
|
|
25
|
+
*/
|
|
26
|
+
export function createAlertDialog(CenteredDialog: CenteredDialogComponent) {
|
|
27
|
+
const AlertDialogComponent = function AlertDialog({
|
|
28
|
+
visible,
|
|
29
|
+
onClose,
|
|
30
|
+
title,
|
|
31
|
+
description,
|
|
32
|
+
confirmLabel = 'Confirm',
|
|
33
|
+
cancelLabel = 'Cancel',
|
|
34
|
+
onConfirm,
|
|
35
|
+
onCancel,
|
|
36
|
+
destructive = false,
|
|
37
|
+
hideCancel = false,
|
|
38
|
+
dismissible = false,
|
|
39
|
+
cardStyle,
|
|
40
|
+
testID,
|
|
41
|
+
}: AlertDialogProps) {
|
|
42
|
+
const theme = useTheme();
|
|
43
|
+
|
|
44
|
+
const handleCancel = useCallback(() => {
|
|
45
|
+
onCancel?.();
|
|
46
|
+
onClose();
|
|
47
|
+
}, [onCancel, onClose]);
|
|
48
|
+
|
|
49
|
+
const handleConfirm = useCallback(() => {
|
|
50
|
+
onConfirm?.();
|
|
51
|
+
onClose();
|
|
52
|
+
}, [onConfirm, onClose]);
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<CenteredDialog
|
|
56
|
+
visible={visible}
|
|
57
|
+
onClose={dismissible ? onClose : () => {}}
|
|
58
|
+
dismissible={dismissible}
|
|
59
|
+
title={title}
|
|
60
|
+
showClose={false}
|
|
61
|
+
accessibilityLabel={title}
|
|
62
|
+
cardStyle={cardStyle}
|
|
63
|
+
testID={testID}
|
|
64
|
+
footer={
|
|
65
|
+
<View style={styles.actions}>
|
|
66
|
+
{!hideCancel ? (
|
|
67
|
+
<Button
|
|
68
|
+
variant="secondary"
|
|
69
|
+
size="medium"
|
|
70
|
+
onPress={handleCancel}
|
|
71
|
+
style={styles.action}
|
|
72
|
+
accessibilityLabel={cancelLabel}>
|
|
73
|
+
{cancelLabel}
|
|
74
|
+
</Button>
|
|
75
|
+
) : null}
|
|
76
|
+
<Button
|
|
77
|
+
variant="primary"
|
|
78
|
+
size="medium"
|
|
79
|
+
onPress={handleConfirm}
|
|
80
|
+
style={[
|
|
81
|
+
styles.action,
|
|
82
|
+
destructive && { backgroundColor: theme.colors.negative },
|
|
83
|
+
]}
|
|
84
|
+
textStyle={destructive ? { color: theme.colors.negativeForeground } : undefined}
|
|
85
|
+
accessibilityLabel={confirmLabel}>
|
|
86
|
+
{confirmLabel}
|
|
87
|
+
</Button>
|
|
88
|
+
</View>
|
|
89
|
+
}>
|
|
90
|
+
{description ? (
|
|
91
|
+
<Text
|
|
92
|
+
style={{
|
|
93
|
+
fontSize: fontSize.md,
|
|
94
|
+
lineHeight: fontSize.md * 1.4,
|
|
95
|
+
color: theme.colors.textSecondary,
|
|
96
|
+
}}>
|
|
97
|
+
{description}
|
|
98
|
+
</Text>
|
|
99
|
+
) : null}
|
|
100
|
+
</CenteredDialog>
|
|
101
|
+
);
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const AlertDialog = memo(AlertDialogComponent);
|
|
105
|
+
AlertDialog.displayName = 'AlertDialog';
|
|
106
|
+
return AlertDialog;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export type AlertDialogType = ReturnType<typeof createAlertDialog>;
|
|
110
|
+
|
|
111
|
+
const styles = StyleSheet.create({
|
|
112
|
+
actions: {
|
|
113
|
+
flexDirection: 'row',
|
|
114
|
+
justifyContent: 'flex-end',
|
|
115
|
+
gap: space.sm,
|
|
116
|
+
},
|
|
117
|
+
action: {
|
|
118
|
+
minWidth: 96,
|
|
119
|
+
},
|
|
120
|
+
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
resolveConfirm,
|
|
5
|
+
subscribeConfirms,
|
|
6
|
+
type ConfirmEntry,
|
|
7
|
+
} from './confirm-store';
|
|
8
|
+
import type { AlertDialogType } from './AlertDialog';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Build the `<AlertDialogHost />` bound to a platform `AlertDialog`. The
|
|
12
|
+
* platform entry files (`index.ts` / `index.web.ts`) inject the correct one.
|
|
13
|
+
*
|
|
14
|
+
* The host mounts the imperative `confirm()` UI. Wrap your app root once
|
|
15
|
+
* (after `BloomThemeProvider`) and you can call `confirm()` from anywhere —
|
|
16
|
+
* including before the host mounts (entries are queued and drained on
|
|
17
|
+
* subscribe). Confirms present one at a time in FIFO order.
|
|
18
|
+
*/
|
|
19
|
+
export function createAlertDialogHost(AlertDialog: AlertDialogType) {
|
|
20
|
+
function ConfirmHost({ entry }: { entry: ConfirmEntry }) {
|
|
21
|
+
return (
|
|
22
|
+
<AlertDialog
|
|
23
|
+
visible
|
|
24
|
+
title={entry.title}
|
|
25
|
+
description={entry.description}
|
|
26
|
+
confirmLabel={entry.confirmLabel}
|
|
27
|
+
cancelLabel={entry.cancelLabel}
|
|
28
|
+
destructive={entry.destructive}
|
|
29
|
+
hideCancel={entry.hideCancel}
|
|
30
|
+
dismissible={entry.dismissible}
|
|
31
|
+
onConfirm={() => resolveConfirm(entry.id, true)}
|
|
32
|
+
onCancel={() => resolveConfirm(entry.id, false)}
|
|
33
|
+
onClose={() => resolveConfirm(entry.id, false)}
|
|
34
|
+
/>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function AlertDialogHost() {
|
|
39
|
+
const [queue, setQueue] = useState<readonly ConfirmEntry[]>([]);
|
|
40
|
+
|
|
41
|
+
useEffect(() => subscribeConfirms(setQueue), []);
|
|
42
|
+
|
|
43
|
+
const head = queue[0];
|
|
44
|
+
if (!head) return null;
|
|
45
|
+
|
|
46
|
+
return <ConfirmHost key={head.id} entry={head} />;
|
|
47
|
+
}
|
|
48
|
+
AlertDialogHost.displayName = 'AlertDialogHost';
|
|
49
|
+
|
|
50
|
+
return AlertDialogHost;
|
|
51
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { ConfirmOptions } from './types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Imperative confirm store.
|
|
5
|
+
*
|
|
6
|
+
* Mirrors the `dialog/alert-store` pattern: a module-scope queue + a single
|
|
7
|
+
* subscriber (the `<AlertDialogHost />` mounted in the app tree). `confirm()`
|
|
8
|
+
* enqueues an entry and resolves a promise with the user's choice. Entries
|
|
9
|
+
* enqueued before the host mounts drain on subscribe — no lost confirms.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
let idCounter = 0;
|
|
13
|
+
function genId(): string {
|
|
14
|
+
idCounter += 1;
|
|
15
|
+
return `bloom-confirm-${idCounter}`;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface ConfirmEntry extends ConfirmOptions {
|
|
19
|
+
id: string;
|
|
20
|
+
resolve: (confirmed: boolean) => void;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
type Listener = (queue: ConfirmEntry[]) => void;
|
|
24
|
+
|
|
25
|
+
let queue: ConfirmEntry[] = [];
|
|
26
|
+
let listener: Listener | null = null;
|
|
27
|
+
|
|
28
|
+
function emit(): void {
|
|
29
|
+
if (listener) listener(queue);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Show a Bloom confirm dialog and resolve with the user's choice.
|
|
34
|
+
*
|
|
35
|
+
* ```ts
|
|
36
|
+
* const ok = await confirm({
|
|
37
|
+
* title: 'Delete app?',
|
|
38
|
+
* description: 'This cannot be undone.',
|
|
39
|
+
* confirmLabel: 'Delete',
|
|
40
|
+
* destructive: true,
|
|
41
|
+
* });
|
|
42
|
+
* if (ok) await doDelete();
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export function confirm(options: ConfirmOptions): Promise<boolean> {
|
|
46
|
+
return new Promise<boolean>((resolve) => {
|
|
47
|
+
const id = genId();
|
|
48
|
+
queue = [...queue, { ...options, id, resolve }];
|
|
49
|
+
emit();
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Resolve and remove an entry. Called by the host on confirm/cancel/dismiss. */
|
|
54
|
+
export function resolveConfirm(id: string, confirmed: boolean): void {
|
|
55
|
+
const entry = queue.find((e) => e.id === id);
|
|
56
|
+
if (!entry) return;
|
|
57
|
+
queue = queue.filter((e) => e.id !== id);
|
|
58
|
+
entry.resolve(confirmed);
|
|
59
|
+
emit();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Subscribe to queue changes (single-subscriber model; latest wins). Delivers
|
|
64
|
+
* the current queue synchronously so a freshly mounted host catches up.
|
|
65
|
+
*/
|
|
66
|
+
export function subscribeConfirms(fn: Listener): () => void {
|
|
67
|
+
listener = fn;
|
|
68
|
+
fn(queue);
|
|
69
|
+
return () => {
|
|
70
|
+
if (listener === fn) listener = null;
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Inspect the current queue. Used by tests. */
|
|
75
|
+
export function getConfirmQueue(): readonly ConfirmEntry[] {
|
|
76
|
+
return queue;
|
|
77
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { CenteredDialog } from '../dialog/index';
|
|
2
|
+
import { createAlertDialog } from './AlertDialog';
|
|
3
|
+
import { createAlertDialogHost } from './AlertDialogHost';
|
|
4
|
+
|
|
5
|
+
export const AlertDialog = createAlertDialog(CenteredDialog);
|
|
6
|
+
export const AlertDialogHost = createAlertDialogHost(AlertDialog);
|
|
7
|
+
|
|
8
|
+
export { confirm } from './confirm-store';
|
|
9
|
+
export type {
|
|
10
|
+
AlertDialogProps,
|
|
11
|
+
AlertDialogActionStyle,
|
|
12
|
+
ConfirmOptions,
|
|
13
|
+
} from './types';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { CenteredDialog } from '../dialog/index.web';
|
|
2
|
+
import { createAlertDialog } from './AlertDialog';
|
|
3
|
+
import { createAlertDialogHost } from './AlertDialogHost';
|
|
4
|
+
|
|
5
|
+
export const AlertDialog = createAlertDialog(CenteredDialog);
|
|
6
|
+
export const AlertDialogHost = createAlertDialogHost(AlertDialog);
|
|
7
|
+
|
|
8
|
+
export { confirm } from './confirm-store';
|
|
9
|
+
export type {
|
|
10
|
+
AlertDialogProps,
|
|
11
|
+
AlertDialogActionStyle,
|
|
12
|
+
ConfirmOptions,
|
|
13
|
+
} from './types';
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { StyleProp, ViewStyle } from 'react-native';
|
|
2
|
+
|
|
3
|
+
export type AlertDialogActionStyle = 'default' | 'cancel' | 'destructive';
|
|
4
|
+
|
|
5
|
+
export interface AlertDialogProps {
|
|
6
|
+
/** Whether the dialog is mounted + visible (controlled). */
|
|
7
|
+
visible: boolean;
|
|
8
|
+
/** Close request — backdrop tap, Escape, cancel, or after confirm. */
|
|
9
|
+
onClose: () => void;
|
|
10
|
+
/** Headline. */
|
|
11
|
+
title: string;
|
|
12
|
+
/** Supporting copy. */
|
|
13
|
+
description?: string;
|
|
14
|
+
/** Confirm button label. Defaults to `'Confirm'`. */
|
|
15
|
+
confirmLabel?: string;
|
|
16
|
+
/** Cancel button label. Defaults to `'Cancel'`. */
|
|
17
|
+
cancelLabel?: string;
|
|
18
|
+
/** Confirm handler. The dialog closes after it runs (sync). */
|
|
19
|
+
onConfirm?: () => void;
|
|
20
|
+
/** Cancel handler. Runs in addition to `onClose`. */
|
|
21
|
+
onCancel?: () => void;
|
|
22
|
+
/**
|
|
23
|
+
* Style the confirm button as destructive (negative color). Defaults to
|
|
24
|
+
* `false`.
|
|
25
|
+
*/
|
|
26
|
+
destructive?: boolean;
|
|
27
|
+
/** Render only the confirm button (no cancel). Defaults to `false`. */
|
|
28
|
+
hideCancel?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Tap-outside / Escape dismisses. Defaults to `false` — alert dialogs are
|
|
31
|
+
* usually blocking until answered.
|
|
32
|
+
*/
|
|
33
|
+
dismissible?: boolean;
|
|
34
|
+
cardStyle?: StyleProp<ViewStyle>;
|
|
35
|
+
testID?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface ConfirmOptions {
|
|
39
|
+
title: string;
|
|
40
|
+
description?: string;
|
|
41
|
+
confirmLabel?: string;
|
|
42
|
+
cancelLabel?: string;
|
|
43
|
+
destructive?: boolean;
|
|
44
|
+
hideCancel?: boolean;
|
|
45
|
+
dismissible?: boolean;
|
|
46
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { View } from 'react-native';
|
|
3
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
4
|
+
|
|
5
|
+
import { Combobox } from './index';
|
|
6
|
+
import type { ComboboxOption } from './types';
|
|
7
|
+
|
|
8
|
+
const meta: Meta = {
|
|
9
|
+
title: 'Forms/Combobox',
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export default meta;
|
|
13
|
+
|
|
14
|
+
type Story = StoryObj;
|
|
15
|
+
|
|
16
|
+
const FRAMEWORKS: ComboboxOption[] = [
|
|
17
|
+
{ value: 'react', label: 'React' },
|
|
18
|
+
{ value: 'vue', label: 'Vue', description: 'The Progressive Framework' },
|
|
19
|
+
{ value: 'svelte', label: 'Svelte' },
|
|
20
|
+
{ value: 'solid', label: 'Solid' },
|
|
21
|
+
{ value: 'angular', label: 'Angular' },
|
|
22
|
+
{ value: 'qwik', label: 'Qwik', description: 'Resumable' },
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
export const Basic: Story = {
|
|
26
|
+
render: () => {
|
|
27
|
+
const [value, setValue] = useState<string | null>(null);
|
|
28
|
+
return (
|
|
29
|
+
<View style={{ width: 320, padding: 40 }}>
|
|
30
|
+
<Combobox
|
|
31
|
+
options={FRAMEWORKS}
|
|
32
|
+
value={value}
|
|
33
|
+
onValueChange={setValue}
|
|
34
|
+
placeholder="Pick a framework…"
|
|
35
|
+
label="Framework"
|
|
36
|
+
/>
|
|
37
|
+
</View>
|
|
38
|
+
);
|
|
39
|
+
},
|
|
40
|
+
};
|