From 5895cf14132f964c2d7e1aa0af0c3721808379b0 Mon Sep 17 00:00:00 2001 From: gengyang Date: Tue, 31 Mar 2020 13:47:59 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20support=20parsing=20fusi?= =?UTF-8?q?on=20source=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/material-parser/src/Materialize.ts | 48 - .../src/accesser/BaseAccesser.ts | 26 - .../src/accesser/LocalAccesser.ts | 78 -- .../src/accesser/OnlineAccesser.ts | 121 -- .../src/extensions/MatConfigManifest.ts | 37 - .../material-parser/src/extensions/index.ts | 6 - packages/material-parser/src/generate.ts | 59 + .../src/generator/Generator.ts | 175 --- packages/material-parser/src/index.ts | 24 +- packages/material-parser/src/localize.ts | 108 ++ .../src/otter-core/schema/types.ts | 75 +- .../src/parse/handlers/defaultPropsHandler.ts | 150 +++ .../src/{parser => parse}/handlers/index.ts | 6 +- .../handlers/propTypeHandler.ts | 8 +- packages/material-parser/src/parse/index.ts | 39 + .../{parser => parse}/resolver/checkIsIIFE.ts | 0 .../src/{parser => parse}/resolver/index.ts | 78 +- .../{parser => parse}/resolver/resolveHOC.ts | 1 + .../{parser => parse}/resolver/resolveIIFE.ts | 15 +- .../src/parse/resolver/resolveImport.ts | 60 + .../resolver/resolveTranspiledClass.ts | 10 +- .../material-parser/src/parse/transform.ts | 138 ++ .../material-parser/src/parser/BaseParser.ts | 76 -- .../material-parser/src/parser/ReactParser.ts | 704 ---------- packages/material-parser/src/scan.ts | 74 + .../material-parser/src/scanner/Scanner.ts | 170 --- .../material-parser/src/types/IAccesser.ts | 4 +- .../src/types/IExtensionConfigManifest.ts | 6 +- .../material-parser/src/types/IGenerator.ts | 20 - .../src/types/IMaterialParsedModel.ts | 66 +- .../src/types/IMaterialScanModel.ts | 4 +- .../src/types/IMaterializeOptions.ts | 8 - packages/material-parser/src/types/IParser.ts | 42 - .../material-parser/src/types/IScanner.ts | 32 - packages/material-parser/src/types/index.ts | 3 +- packages/material-parser/test/Materialize.ts | 63 - .../test/accesser/LocalAccesser.ts | 29 - .../test/accesser/OnlineAccesser.ts | 42 - .../accesser/snapshots/LocalAccesser.ts.md | 529 -------- .../accesser/snapshots/LocalAccesser.ts.snap | Bin 3727 -> 0 bytes .../accesser/snapshots/OnlineAccesser.ts.md | 408 ------ .../accesser/snapshots/OnlineAccesser.ts.snap | Bin 2896 -> 0 bytes .../__snapshots__/test/Materialize.ts.md | 188 --- .../__snapshots__/test/Materialize.ts.snap | Bin 1723 -> 0 bytes .../test/accesser/LocalAccesser.ts.md | 188 --- .../test/accesser/LocalAccesser.ts.snap | Bin 1734 -> 0 bytes .../test/generator/Generator.ts.md | 1135 ---------------- .../test/generator/Generator.ts.snap | Bin 6077 -> 0 bytes .../fixtures/__snapshots__/test/index.ts.md | 1074 +++++++++++++++ .../fixtures/__snapshots__/test/index.ts.snap | Bin 0 -> 6148 bytes .../test/parser/ReactParser.ts.md | 474 ------- .../test/parser/ReactParser.ts.snap | Bin 3287 -> 0 bytes .../fixtures/__snapshots__/test/scan.ts.md | 132 ++ .../fixtures/__snapshots__/test/scan.ts.snap | Bin 0 -> 1656 bytes .../__snapshots__/test/scanner/Scanner.ts.md | 623 --------- .../test/scanner/Scanner.ts.snap | Bin 3591 -> 0 bytes .../fusion-next-component/package.json | 19 +- .../fusion-next-component/src/.editorconfig | 22 + .../fusion-next-component/src/.eslintrc | 5 + .../fusion-next-component/src/.stylelintrc | 17 + .../src/@alife/next/affix/container.js | 5 - .../src/@alife/next/affix/manifest.js | 1 - .../src/@alife/next/animate/container.js | 5 - .../src/@alife/next/animate/manifest.js | 1 - .../src/@alife/next/badge/container.js | 5 - .../src/@alife/next/badge/manifest.js | 1 - .../src/@alife/next/balloon/container.js | 5 - .../src/@alife/next/balloon/manifest.js | 1 - .../src/@alife/next/breadcrumb/container.js | 5 - .../src/@alife/next/breadcrumb/manifest.js | 1 - .../src/@alife/next/button/container.js | 5 - .../src/@alife/next/button/manifest.js | 1 - .../src/@alife/next/calendar/container.js | 5 - .../src/@alife/next/calendar/manifest.js | 1 - .../src/@alife/next/card/container.js | 5 - .../src/@alife/next/card/manifest.js | 1 - .../@alife/next/cascader-select/container.js | 5 - .../@alife/next/cascader-select/manifest.js | 1 - .../src/@alife/next/cascader/container.js | 5 - .../src/@alife/next/cascader/manifest.js | 1 - .../src/@alife/next/checkbox/container.js | 5 - .../src/@alife/next/checkbox/manifest.js | 1 - .../src/@alife/next/collapse/container.js | 5 - .../src/@alife/next/collapse/manifest.js | 1 - .../@alife/next/config-provider/container.js | 5 - .../@alife/next/config-provider/manifest.js | 1 - .../src/@alife/next/date-picker/container.js | 5 - .../src/@alife/next/date-picker/manifest.js | 1 - .../src/@alife/next/dialog/container.js | 5 - .../src/@alife/next/dialog/manifest.js | 1 - .../src/@alife/next/drawer/container.js | 5 - .../src/@alife/next/drawer/manifest.js | 1 - .../src/@alife/next/dropdown/container.js | 5 - .../src/@alife/next/dropdown/manifest.js | 1 - .../src/@alife/next/field/container.js | 5 - .../src/@alife/next/field/manifest.js | 1 - .../src/@alife/next/form/container.js | 5 - .../src/@alife/next/form/manifest.js | 1 - .../src/@alife/next/grid/container.js | 5 - .../src/@alife/next/grid/manifest.js | 1 - .../src/@alife/next/icon/container.js | 5 - .../src/@alife/next/icon/manifest.js | 1 - .../src/@alife/next/input/container.js | 5 - .../src/@alife/next/input/manifest.js | 1 - .../src/@alife/next/loading/container.js | 5 - .../src/@alife/next/loading/manifest.js | 1 - .../src/@alife/next/menu-button/container.js | 5 - .../src/@alife/next/menu-button/manifest.js | 1 - .../src/@alife/next/menu/container.js | 5 - .../src/@alife/next/menu/manifest.js | 1 - .../src/@alife/next/message/container.js | 5 - .../src/@alife/next/message/manifest.js | 1 - .../src/@alife/next/nav/container.js | 5 - .../src/@alife/next/nav/manifest.js | 1 - .../@alife/next/number-picker/container.js | 5 - .../src/@alife/next/number-picker/manifest.js | 1 - .../src/@alife/next/overlay/container.js | 5 - .../src/@alife/next/overlay/manifest.js | 1 - .../src/@alife/next/pagination/container.js | 5 - .../src/@alife/next/pagination/manifest.js | 1 - .../src/@alife/next/paragraph/container.js | 5 - .../src/@alife/next/paragraph/manifest.js | 1 - .../src/@alife/next/progress/container.js | 5 - .../src/@alife/next/progress/manifest.js | 1 - .../src/@alife/next/radio/container.js | 5 - .../src/@alife/next/radio/manifest.js | 1 - .../src/@alife/next/range/container.js | 5 - .../src/@alife/next/range/manifest.js | 1 - .../src/@alife/next/rating/container.js | 5 - .../src/@alife/next/rating/manifest.js | 1 - .../src/@alife/next/search/container.js | 5 - .../src/@alife/next/search/manifest.js | 1 - .../src/@alife/next/select/container.js | 5 - .../src/@alife/next/select/manifest.js | 1 - .../src/@alife/next/slider/container.js | 5 - .../src/@alife/next/slider/manifest.js | 1 - .../src/@alife/next/split-button/container.js | 5 - .../src/@alife/next/split-button/manifest.js | 1 - .../src/@alife/next/step/container.js | 5 - .../src/@alife/next/step/manifest.js | 1 - .../src/@alife/next/switch/container.js | 5 - .../src/@alife/next/switch/manifest.js | 1 - .../src/@alife/next/tab/container.js | 5 - .../src/@alife/next/tab/manifest.js | 1 - .../src/@alife/next/table/container.js | 5 - .../src/@alife/next/table/manifest.js | 1 - .../src/@alife/next/tag/container.js | 5 - .../src/@alife/next/tag/manifest.js | 1 - .../src/@alife/next/time-picker/container.js | 5 - .../src/@alife/next/time-picker/manifest.js | 1 - .../src/@alife/next/timeline/container.js | 5 - .../src/@alife/next/timeline/manifest.js | 1 - .../src/@alife/next/transfer/container.js | 5 - .../src/@alife/next/transfer/manifest.js | 1 - .../src/@alife/next/tree-select/container.js | 5 - .../src/@alife/next/tree-select/manifest.js | 1 - .../src/@alife/next/tree/container.js | 5 - .../src/@alife/next/tree/manifest.js | 1 - .../src/@alife/next/upload/container.js | 5 - .../src/@alife/next/upload/manifest.js | 1 - .../src/@alife/next/virtual-list/container.js | 5 - .../src/@alife/next/virtual-list/manifest.js | 1 - .../fusion-next-component/src/affix/index.jsx | 280 ++++ .../fusion-next-component/src/affix/main.scss | 1 + .../fusion-next-component/src/affix/style.js | 1 + .../fusion-next-component/src/affix/util.js | 24 + .../src/animate/.stylelintrc | 9 + .../src/animate/animate.jsx | 178 +++ .../src/animate/child.jsx | 263 ++++ .../src/animate/expand.jsx | 146 ++ .../src/animate/index.jsx | 6 + .../src/animate/main.scss | 145 ++ .../scss/_attention-seekers/_buttonClick.scss | 14 + .../scss/_attention-seekers/_press.scss | 14 + .../scss/_attention-seekers/_pulse.scss | 21 + .../scss/_attention-seekers/_shake.scss | 32 + .../scss/_attention-seekers/_unpress.scss | 14 + .../_attention-seekers/attention-seekers.scss | 7 + .../scss/_bounce-entrances/_bounceIn.scss | 48 + .../_bounce-entrances/bounce-entrances.scss | 3 + .../scss/_bounce-exits/_bounceOut.scss | 27 + .../scss/_bounce-exits/bounce-exits.scss | 3 + .../scss/_expand-entrances/_expandInDown.scss | 22 + .../scss/_expand-entrances/_expandInUp.scss | 22 + .../scss/_expand-entrances/_withFade.scss | 24 + .../scss/_expand-exits/_expandOutDown.scss | 22 + .../scss/_expand-exits/_expandOutUp.scss | 22 + .../animate/scss/_expand-exits/_withFade.scss | 21 + .../scss/_fading-entrances/_fadeIn.scss | 18 + .../scss/_fading-entrances/_fadeInDown.scss | 20 + .../_fading-entrances/_fadeInDownBig.scss | 20 + .../scss/_fading-entrances/_fadeInLeft.scss | 20 + .../_fading-entrances/_fadeInLeftBig.scss | 20 + .../scss/_fading-entrances/_fadeInRight.scss | 20 + .../_fading-entrances/_fadeInRightBig.scss | 20 + .../scss/_fading-entrances/_fadeInUp.scss | 19 + .../scss/_fading-entrances/_fadeInUpBig.scss | 20 + .../_fading-entrances/fading-entrances.scss | 11 + .../animate/scss/_fading-exits/_fadeOut.scss | 18 + .../scss/_fading-exits/_fadeOutDown.scss | 20 + .../scss/_fading-exits/_fadeOutDownBig.scss | 20 + .../scss/_fading-exits/_fadeOutLeft.scss | 20 + .../scss/_fading-exits/_fadeOutLeftBig.scss | 20 + .../scss/_fading-exits/_fadeOutRight.scss | 20 + .../scss/_fading-exits/_fadeOutRightBig.scss | 20 + .../scss/_fading-exits/_fadeOutUp.scss | 20 + .../scss/_fading-exits/_fadeOutUpBig.scss | 20 + .../scss/_fading-exits/fading-exits.scss | 11 + .../scss/_other-entrances/_pressIn.scss | 14 + .../scss/_other-entrances/_pressInSmall.scss | 14 + .../scss/_other-entrances/_waterIn.scss | 17 + .../_other-entrances/other-entrances.scss | 5 + .../animate/scss/_other-exits/_pressOut.scss | 14 + .../scss/_other-exits/_pressOutSmall.scss | 14 + .../animate/scss/_other-exits/_waterOut.scss | 17 + .../scss/_other-exits/other-exits.scss | 5 + .../scss/_sliding-entrances/_slideInDown.scss | 20 + .../scss/_sliding-entrances/_slideInLeft.scss | 20 + .../_sliding-entrances/_slideInRight.scss | 20 + .../scss/_sliding-entrances/_slideInUp.scss | 20 + .../_sliding-entrances/sliding-entrances.scss | 6 + .../scss/_sliding-exits/_slideOutDown.scss | 19 + .../scss/_sliding-exits/_slideOutLeft.scss | 19 + .../scss/_sliding-exits/_slideOutRight.scss | 19 + .../scss/_sliding-exits/_slideOutUp.scss | 19 + .../scss/_sliding-exits/sliding-exits.scss | 6 + .../scss/_zooming-entrances/_zoomIn.scss | 19 + .../scss/_zooming-entrances/_zoomInDown.scss | 22 + .../scss/_zooming-entrances/_zoomInLeft.scss | 22 + .../scss/_zooming-entrances/_zoomInPulse.scss | 24 + .../scss/_zooming-entrances/_zoomInQuick.scss | 19 + .../scss/_zooming-entrances/_zoomInRight.scss | 22 + .../scss/_zooming-entrances/_zoomInUp.scss | 22 + .../_zooming-entrances/zooming-entrances.scss | 9 + .../animate/scss/_zooming-exits/_zoomOut.scss | 22 + .../scss/_zooming-exits/_zoomOutDown.scss | 23 + .../scss/_zooming-exits/_zoomOutLeft.scss | 21 + .../scss/_zooming-exits/_zoomOutPulse.scss | 20 + .../scss/_zooming-exits/_zoomOutQuick.scss | 19 + .../scss/_zooming-exits/_zoomOutRight.scss | 21 + .../scss/_zooming-exits/_zoomOutUp.scss | 23 + .../scss/_zooming-exits/zooming-exits.scss | 9 + .../src/animate/scss/mixin.scss | 105 ++ .../src/animate/scss/variable.scss | 19 + .../src/animate/style.js | 1 + .../src/avatar/index.jsx | 149 +++ .../src/avatar/main.scss | 44 + .../src/avatar/scss/mixin.scss | 17 + .../src/avatar/scss/variable.scss | 42 + .../fusion-next-component/src/avatar/style.js | 2 + .../fusion-next-component/src/badge/index.jsx | 106 ++ .../fusion-next-component/src/badge/main.scss | 120 ++ .../fusion-next-component/src/badge/rtl.scss | 12 + .../src/badge/scss/function.scss | 4 + .../src/badge/scss/mixin.scss | 44 + .../src/badge/scss/placeholder.scss | 4 + .../src/badge/scss/variable.scss | 67 + .../fusion-next-component/src/badge/style.js | 2 + .../fusion-next-component/src/badge/sup.jsx | 221 +++ .../src/balloon/alignMap.js | 202 +++ .../src/balloon/balloon.jsx | 398 ++++++ .../src/balloon/index.jsx | 46 + .../src/balloon/inner.jsx | 106 ++ .../src/balloon/main.scss | 120 ++ .../src/balloon/rtl.scss | 206 +++ .../src/balloon/scss/mixin.scss | 318 +++++ .../src/balloon/scss/variable.scss | 186 +++ .../src/balloon/style.js | 4 + .../src/balloon/tooltip.jsx | 193 +++ .../fusion-next-component/src/balloon/util.js | 26 + .../fusion-next-component/src/box/index.jsx | 252 ++++ .../fusion-next-component/src/box/main.scss | 13 + .../src/box/scss/mixin.scss | 4 + .../src/box/scss/variable.scss | 18 + .../fusion-next-component/src/box/style.js | 1 + .../src/breadcrumb/index.jsx | 247 ++++ .../src/breadcrumb/item.jsx | 70 + .../src/breadcrumb/main.scss | 35 + .../src/breadcrumb/scss/mixin.scss | 131 ++ .../src/breadcrumb/scss/variable.scss | 82 ++ .../src/breadcrumb/style.js | 2 + .../fusion-next-component/src/build.js | 51 - .../src/button/index.jsx | 42 + .../src/button/main.scss | 396 ++++++ .../fusion-next-component/src/button/rtl.scss | 119 ++ .../src/button/scss/mixin.scss | 54 + .../src/button/scss/normalize.scss | 15 + .../src/button/scss/variable.scss | 522 ++++++++ .../fusion-next-component/src/button/style.js | 2 + .../src/button/view/button.jsx | 208 +++ .../src/button/view/group.jsx | 62 + .../src/calendar/.eslintrc | 5 + .../src/calendar/calendar.jsx | 354 +++++ .../src/calendar/head/card-header.jsx | 118 ++ .../src/calendar/head/date-panel-header.jsx | 173 +++ .../src/calendar/head/menu.jsx | 70 + .../src/calendar/head/month-panel-header.jsx | 50 + .../src/calendar/head/range-panel-header.jsx | 253 ++++ .../src/calendar/head/year-panel-header.jsx | 55 + .../src/calendar/index.jsx | 82 ++ .../src/calendar/main.scss | 38 + .../src/calendar/range-calendar.jsx | 411 ++++++ .../src/calendar/rtl.scss | 69 + .../src/calendar/scss/animation.scss | 45 + .../src/calendar/scss/header.scss | 126 ++ .../src/calendar/scss/mixin.scss | 26 + .../src/calendar/scss/normalize.scss | 13 + .../src/calendar/scss/table.scss | 290 ++++ .../src/calendar/scss/variable.scss | 371 ++++++ .../src/calendar/style.js | 4 + .../src/calendar/table/date-table-head.jsx | 28 + .../src/calendar/table/date-table.jsx | 166 +++ .../src/calendar/table/month-table.jsx | 96 ++ .../src/calendar/table/year-table.jsx | 106 ++ .../src/calendar/utils/index.js | 129 ++ .../src/card/actions.jsx | 41 + .../src/card/bullet-header.jsx | 70 + .../fusion-next-component/src/card/card.jsx | 127 ++ .../src/card/collapse-content.jsx | 147 ++ .../src/card/content.jsx | 44 + .../src/card/divider.jsx | 50 + .../fusion-next-component/src/card/header.jsx | 73 + .../fusion-next-component/src/card/index.jsx | 39 + .../fusion-next-component/src/card/main.scss | 197 +++ .../fusion-next-component/src/card/media.jsx | 74 + .../fusion-next-component/src/card/rtl.scss | 26 + .../src/card/scss/mixin.scss | 2 + .../src/card/scss/normalize.scss | 13 + .../src/card/scss/variable.scss | 163 +++ .../fusion-next-component/src/card/style.js | 3 + .../src/cascader-select/cascader-select.jsx | 919 +++++++++++++ .../src/cascader-select/index.jsx | 41 + .../src/cascader-select/main.scss | 35 + .../src/cascader-select/scss/variable.scss | 17 + .../src/cascader-select/style.js | 3 + .../src/cascader/cascader.jsx | 889 ++++++++++++ .../src/cascader/index.jsx | 26 + .../src/cascader/item.jsx | 174 +++ .../src/cascader/main.scss | 94 ++ .../src/cascader/menu.jsx | 111 ++ .../src/cascader/rtl.scss | 24 + .../src/cascader/scss/variable.scss | 63 + .../src/cascader/style.js | 3 + .../src/cascader/utils.js | 215 +++ .../src/checkbox/checkbox-group.jsx | 275 ++++ .../src/checkbox/checkbox.jsx | 321 +++++ .../src/checkbox/index.jsx | 6 + .../src/checkbox/main.scss | 189 +++ .../src/checkbox/rtl.scss | 12 + .../src/checkbox/scss/variable.scss | 86 ++ .../src/checkbox/style.js | 3 + .../src/collapse/collapse.jsx | 259 ++++ .../src/collapse/index.jsx | 6 + .../src/collapse/main.scss | 119 ++ .../src/collapse/panel.jsx | 115 ++ .../src/collapse/rtl.scss | 12 + .../src/collapse/scss/mixin.scss | 1 + .../src/collapse/scss/variable.scss | 108 ++ .../src/collapse/style.js | 2 + .../src/config-provider/cache.js | 42 + .../src/config-provider/config.jsx | 254 ++++ .../src/config-provider/consumer.jsx | 73 + .../src/config-provider/error-boundary.jsx | 63 + .../src/config-provider/get-context-props.jsx | 89 ++ .../src/config-provider/index.jsx | 230 ++++ .../src/config-provider/main.scss | 0 .../src/config-provider/style.js | 1 + .../src/core/base/_accessibility.scss | 11 + .../src/core/base/_normalize.scss | 449 +++++++ .../src/core/base/_reset.scss | 38 + .../src/core/base/_typography.scss | 143 ++ .../src/core/form-element.scss | 48 + .../src/core/index-noreset.scss | 24 + .../fusion-next-component/src/core/index.scss | 1 + .../fusion-next-component/src/core/mask.scss | 21 + .../fusion-next-component/src/core/popup.scss | 13 + .../fusion-next-component/src/core/reset.scss | 6 + .../src/core/style/_color.scss | 300 +++++ .../src/core/style/_corner.scss | 51 + .../src/core/style/_font.scss | 177 +++ .../src/core/style/_global.scss | 38 + .../src/core/style/_icon.scss | 373 ++++++ .../src/core/style/_line.scss | 61 + .../src/core/style/_motion.scss | 10 + .../src/core/style/_shadow.scss | 207 +++ .../src/core/style/_size.scss | 285 ++++ .../src/core/util/_function.scss | 183 +++ .../src/core/util/_mixin.scss | 570 ++++++++ .../src/core/utility/_form-element.scss | 82 ++ .../src/core/utility/_mask.scss | 20 + .../src/core/utility/_popup.scss | 51 + .../src/date-picker/date-picker.jsx | 748 +++++++++++ .../src/date-picker/index.jsx | 79 ++ .../src/date-picker/main.scss | 68 + .../src/date-picker/module/panel-footer.jsx | 90 ++ .../src/date-picker/month-picker.jsx | 505 +++++++ .../src/date-picker/range-picker.jsx | 1182 ++++++++++++++++ .../src/date-picker/rtl.scss | 75 ++ .../src/date-picker/scss/date-picker.scss | 33 + .../src/date-picker/scss/mixin.scss | 18 + .../src/date-picker/scss/range-picker.scss | 111 ++ .../src/date-picker/scss/variable.scss | 50 + .../src/date-picker/style.js | 6 + .../src/date-picker/util/index.js | 183 +++ .../src/date-picker/week-picker.jsx | 464 +++++++ .../src/date-picker/year-picker.jsx | 488 +++++++ .../src/demo-helper/.stylelintrc | 13 + .../src/demo-helper/icon.scss | 471 +++++++ .../src/demo-helper/index.jsx | 768 +++++++++++ .../src/demo-helper/main.scss | 295 ++++ .../src/demo-helper/style.js | 1 + .../src/dialog/dialog.jsx | 413 ++++++ .../src/dialog/index.jsx | 71 + .../src/dialog/inner.jsx | 212 +++ .../src/dialog/main.scss | 134 ++ .../fusion-next-component/src/dialog/rtl.scss | 27 + .../src/dialog/scss/variable.scss | 138 ++ .../fusion-next-component/src/dialog/show.jsx | 261 ++++ .../fusion-next-component/src/dialog/style.js | 5 + .../src/divider/index.jsx | 71 + .../src/divider/main.scss | 125 ++ .../src/divider/scss/mixin.scss | 4 + .../src/divider/scss/variable.scss | 58 + .../src/divider/style.js | 1 + .../src/drawer/drawer.jsx | 282 ++++ .../src/drawer/index.jsx | 6 + .../src/drawer/inner.jsx | 134 ++ .../src/drawer/main.scss | 89 ++ .../fusion-next-component/src/drawer/rtl.scss | 1 + .../src/drawer/scss/mixin.scss | 2 + .../src/drawer/scss/variable.scss | 105 ++ .../fusion-next-component/src/drawer/style.js | 3 + .../src/dropdown/dropdown.jsx | 168 +++ .../src/dropdown/index.jsx | 22 + .../src/dropdown/main.scss | 0 .../src/dropdown/style.js | 2 + .../fusion-next-component/src/field/index.js | 43 + .../fusion-next-component/src/field/main.scss | 1 + .../fusion-next-component/src/field/style.js | 1 + .../fusion-next-component/src/field/utils.js | 49 + .../src/form/enhance.jsx | 112 ++ .../fusion-next-component/src/form/error.jsx | 106 ++ .../fusion-next-component/src/form/form.jsx | 259 ++++ .../fusion-next-component/src/form/index.jsx | 36 + .../fusion-next-component/src/form/item.jsx | 516 +++++++ .../fusion-next-component/src/form/main.scss | 254 ++++ .../fusion-next-component/src/form/reset.jsx | 72 + .../src/form/scss/mixin.scss | 39 + .../src/form/scss/variable.scss | 73 + .../fusion-next-component/src/form/style.js | 4 + .../fusion-next-component/src/form/submit.jsx | 75 ++ .../fusion-next-component/src/grid/col.jsx | 193 +++ .../fusion-next-component/src/grid/index.jsx | 30 + .../fusion-next-component/src/grid/main.scss | 113 ++ .../fusion-next-component/src/grid/row.jsx | 167 +++ .../fusion-next-component/src/grid/rtl.scss | 43 + .../src/grid/scss/mixin.scss | 168 +++ .../src/grid/scss/variable.scss | 50 + .../fusion-next-component/src/grid/style.js | 1 + .../src/icon/icon-font.jsx | 75 ++ .../fusion-next-component/src/icon/index.jsx | 109 ++ .../fusion-next-component/src/icon/main.scss | 145 ++ .../fusion-next-component/src/icon/rtl.scss | 8 + .../fusion-next-component/src/icon/style.js | 1 + .../fusion-next-component/src/index.js | 59 + .../fusion-next-component/src/input/base.jsx | 300 +++++ .../fusion-next-component/src/input/group.jsx | 96 ++ .../fusion-next-component/src/input/index.jsx | 20 + .../fusion-next-component/src/input/input.jsx | 405 ++++++ .../fusion-next-component/src/input/main.scss | 425 ++++++ .../src/input/password.jsx | 54 + .../fusion-next-component/src/input/rtl.scss | 145 ++ .../src/input/scss/mixin.scss | 135 ++ .../src/input/scss/variable.scss | 213 +++ .../fusion-next-component/src/input/style.js | 2 + .../src/input/textarea.jsx | 308 +++++ .../fusion-next-component/src/list/index.jsx | 6 + .../fusion-next-component/src/list/item.jsx | 76 ++ .../fusion-next-component/src/list/list.jsx | 81 ++ .../fusion-next-component/src/list/main.scss | 123 ++ .../fusion-next-component/src/list/rtl.scss | 24 + .../src/list/scss/mixin.scss | 4 + .../src/list/scss/variable.scss | 94 ++ .../fusion-next-component/src/list/style.js | 1 + .../src/loading/index.jsx | 191 +++ .../src/loading/main.scss | 222 +++ .../src/loading/rtl.scss | 33 + .../src/loading/scss/mixin.scss | 63 + .../src/loading/scss/variable.scss | 44 + .../src/loading/style.js | 4 + .../fusion-next-component/src/locale/en-us.js | 136 ++ .../fusion-next-component/src/locale/ja-jp.js | 134 ++ .../fusion-next-component/src/locale/zh-cn.js | 134 ++ .../fusion-next-component/src/locale/zh-tw.js | 134 ++ .../src/menu-button/index.jsx | 250 ++++ .../src/menu-button/main.scss | 63 + .../src/menu-button/scss/mixin.scss | 2 + .../src/menu-button/scss/variable.scss | 52 + .../src/menu-button/style.js | 5 + .../fusion-next-component/src/menu/index.jsx | 52 + .../fusion-next-component/src/menu/main.scss | 253 ++++ .../fusion-next-component/src/menu/rtl.scss | 42 + .../src/menu/scss/mixin.scss | 17 + .../src/menu/scss/variable.scss | 144 ++ .../fusion-next-component/src/menu/style.js | 5 + .../src/menu/view/checkable-item.jsx | 143 ++ .../src/menu/view/checkbox-item.jsx | 62 + .../src/menu/view/create.jsx | 193 +++ .../src/menu/view/divider.jsx | 28 + .../src/menu/view/group.jsx | 74 + .../src/menu/view/item.jsx | 229 ++++ .../src/menu/view/menu.jsx | 1033 ++++++++++++++ .../src/menu/view/popup-item.jsx | 308 +++++ .../src/menu/view/radio-item.jsx | 53 + .../src/menu/view/selectable-item.jsx | 173 +++ .../src/menu/view/sub-menu.jsx | 310 +++++ .../src/menu/view/util.js | 10 + .../src/message/index.jsx | 16 + .../src/message/main.scss | 346 +++++ .../src/message/message.jsx | 204 +++ .../src/message/rtl.scss | 27 + .../src/message/scss/mixin.scss | 103 ++ .../src/message/scss/variable.scss | 422 ++++++ .../src/message/style.js | 4 + .../src/message/toast.jsx | 294 ++++ .../src/mixin-ui-state/index.jsx | 52 + .../fusion-next-component/src/nav/group.jsx | 56 + .../fusion-next-component/src/nav/index.jsx | 14 + .../fusion-next-component/src/nav/item.jsx | 63 + .../fusion-next-component/src/nav/main.scss | 428 ++++++ .../fusion-next-component/src/nav/nav.jsx | 297 +++++ .../src/nav/popup-item.jsx | 75 ++ .../fusion-next-component/src/nav/rtl.scss | 90 ++ .../src/nav/scss/mixin.scss | 193 +++ .../src/nav/scss/variable.scss | 425 ++++++ .../fusion-next-component/src/nav/style.js | 4 + .../fusion-next-component/src/nav/sub-nav.jsx | 84 ++ .../src/notification/config.js | 8 + .../src/notification/index.jsx | 283 ++++ .../src/notification/main.scss | 42 + .../src/notification/style.js | 3 + .../src/number-picker/index.jsx | 13 + .../src/number-picker/main.scss | 317 +++++ .../src/number-picker/number-picker.jsx | 619 +++++++++ .../src/number-picker/scss/mixin.scss | 4 + .../src/number-picker/scss/variable.scss | 85 ++ .../src/number-picker/style.js | 4 + .../src/overlay/gateway.jsx | 68 + .../src/overlay/index.jsx | 15 + .../src/overlay/main.scss | 24 + .../src/overlay/manager.js | 21 + .../src/overlay/overlay.jsx | 822 ++++++++++++ .../src/overlay/popup.jsx | 383 ++++++ .../src/overlay/position.jsx | 149 +++ .../src/overlay/scss/variable.scss | 1 + .../src/overlay/style.js | 2 + .../src/overlay/utils/find-node.js | 29 + .../src/overlay/utils/position.js | 539 ++++++++ .../src/pagination/index.jsx | 3 + .../src/pagination/main.scss | 248 ++++ .../src/pagination/pagination.jsx | 676 ++++++++++ .../src/pagination/rtl.scss | 106 ++ .../src/pagination/scss/mixin.scss | 146 ++ .../src/pagination/scss/variable.scss | 258 ++++ .../src/pagination/style.js | 4 + .../src/paragraph/index.jsx | 68 + .../src/paragraph/main.scss | 23 + .../src/paragraph/scss/mixin.scss | 2 + .../src/paragraph/scss/variable.scss | 35 + .../src/paragraph/style.js | 1 + .../src/progress/index.jsx | 33 + .../src/progress/main.scss | 173 +++ .../src/progress/rtl.scss | 12 + .../src/progress/scss/mixin.scss | 30 + .../src/progress/scss/variable.scss | 161 +++ .../src/progress/style.js | 1 + .../src/progress/view/progress-circle.jsx | 173 +++ .../src/progress/view/progress-line.jsx | 89 ++ .../src/progress/view/progress.jsx | 78 ++ .../fusion-next-component/src/radio/index.jsx | 6 + .../fusion-next-component/src/radio/main.scss | 325 +++++ .../src/radio/radio-group.jsx | 305 +++++ .../fusion-next-component/src/radio/radio.jsx | 312 +++++ .../fusion-next-component/src/radio/rtl.scss | 81 ++ .../src/radio/scss/variable.scss | 197 +++ .../fusion-next-component/src/radio/style.js | 2 + .../fusion-next-component/src/range/index.jsx | 22 + .../fusion-next-component/src/range/main.scss | 68 + .../src/range/scss/mixin.scss | 326 +++++ .../src/range/scss/variable.scss | 174 +++ .../fusion-next-component/src/range/style.js | 2 + .../fusion-next-component/src/range/utils.jsx | 44 + .../src/range/view/fixedSlider.jsx | 195 +++ .../src/range/view/mark.jsx | 75 ++ .../src/range/view/range.jsx | 874 ++++++++++++ .../src/range/view/scale.jsx | 67 + .../src/range/view/selected.jsx | 129 ++ .../src/range/view/slider.jsx | 57 + .../src/range/view/track.jsx | 20 + .../src/rating/index.jsx | 18 + .../src/rating/main.scss | 159 +++ .../src/rating/rating.jsx | 531 ++++++++ .../fusion-next-component/src/rating/rtl.scss | 18 + .../src/rating/scss/mixin.scss | 23 + .../src/rating/scss/variable.scss | 78 ++ .../fusion-next-component/src/rating/style.js | 2 + .../src/responsive-grid/cell.jsx | 42 + .../src/responsive-grid/create-style.js | 347 +++++ .../src/responsive-grid/index.jsx | 130 ++ .../src/responsive-grid/main.scss | 13 + .../src/responsive-grid/scss/mixin.scss | 4 + .../src/responsive-grid/scss/variable.scss | 18 + .../src/responsive-grid/style.js | 1 + .../src/responsive-grid/util.js | 43 + .../src/search/Search.jsx | 365 +++++ .../src/search/index.jsx | 25 + .../src/search/main.scss | 325 +++++ .../fusion-next-component/src/search/rtl.scss | 110 ++ .../src/search/scss/mixin.scss | 140 ++ .../src/search/scss/variable.scss | 333 +++++ .../fusion-next-component/src/search/style.js | 5 + .../src/select/auto-complete.jsx | 401 ++++++ .../fusion-next-component/src/select/base.jsx | 714 ++++++++++ .../src/select/data-store.js | 97 ++ .../src/select/index.jsx | 83 ++ .../src/select/main.scss | 462 +++++++ .../src/select/option-group.jsx | 23 + .../src/select/option.jsx | 27 + .../fusion-next-component/src/select/rtl.scss | 10 + .../src/select/scss/mixin.scss | 33 + .../src/select/scss/variable.scss | 55 + .../src/select/select.jsx | 1187 +++++++++++++++++ .../fusion-next-component/src/select/style.js | 6 + .../fusion-next-component/src/select/util.js | 363 +++++ .../fusion-next-component/src/shell/base.jsx | 106 ++ .../fusion-next-component/src/shell/index.jsx | 46 + .../fusion-next-component/src/shell/main.scss | 597 +++++++++ .../fusion-next-component/src/shell/rtl.scss | 1 + .../src/shell/scss/mixin.scss | 194 +++ .../src/shell/scss/variable.scss | 745 +++++++++++ .../fusion-next-component/src/shell/shell.jsx | 575 ++++++++ .../fusion-next-component/src/shell/style.js | 2 + .../fusion-next-component/src/shell/util.js | 42 + .../src/slider/index.jsx | 77 ++ .../src/slider/main.scss | 275 ++++ .../src/slider/scss/mixin.scss | 87 ++ .../src/slider/scss/variable.scss | 255 ++++ .../src/slider/slick/arrow.jsx | 143 ++ .../src/slider/slick/dots.jsx | 101 ++ .../src/slider/slick/inner-slider.jsx | 412 ++++++ .../src/slider/slick/mixins/event-handlers.js | 348 +++++ .../src/slider/slick/mixins/helpers.js | 472 +++++++ .../src/slider/slick/mixins/trackHelper.js | 222 +++ .../src/slider/slick/track.jsx | 221 +++ .../src/slider/slider.jsx | 271 ++++ .../fusion-next-component/src/slider/style.js | 3 + .../src/split-button/index.jsx | 309 +++++ .../src/split-button/main.scss | 32 + .../src/split-button/scss/mixin.scss | 2 + .../src/split-button/scss/variable.scss | 18 + .../src/split-button/style.js | 4 + .../fusion-next-component/src/step/index.jsx | 30 + .../fusion-next-component/src/step/main.scss | 12 + .../fusion-next-component/src/step/rtl.scss | 325 +++++ .../src/step/scss/arrow.scss | 115 ++ .../src/step/scss/basic.scss | 41 + .../src/step/scss/circle.scss | 178 +++ .../src/step/scss/dot.scss | 164 +++ .../src/step/scss/mixin.scss | 324 +++++ .../src/step/scss/normalize.scss | 13 + .../src/step/scss/variable.scss | 447 +++++++ .../fusion-next-component/src/step/style.js | 4 + .../src/step/view/step-item.jsx | 433 ++++++ .../src/step/view/step.jsx | 269 ++++ .../src/switch/index.jsx | 214 +++ .../src/switch/main.scss | 114 ++ .../fusion-next-component/src/switch/rtl.scss | 65 + .../src/switch/scss/mixin.scss | 38 + .../src/switch/scss/variable.scss | 196 +++ .../fusion-next-component/src/switch/style.js | 1 + .../fusion-next-component/src/tab/index.jsx | 52 + .../fusion-next-component/src/tab/main.scss | 478 +++++++ .../fusion-next-component/src/tab/rtl.scss | 94 ++ .../src/tab/scss/mixin.scss | 181 +++ .../src/tab/scss/placeholder.scss | 17 + .../src/tab/scss/variable.scss | 397 ++++++ .../fusion-next-component/src/tab/style.js | 4 + .../fusion-next-component/src/tab/tab.jsx | 324 +++++ .../src/tab/tabs/content.jsx | 52 + .../src/tab/tabs/nav.jsx | 678 ++++++++++ .../src/tab/tabs/tab-item.jsx | 67 + .../src/tab/tabs/utils.js | 45 + .../fusion-next-component/src/table/base.jsx | 785 +++++++++++ .../src/table/base/body.jsx | 192 +++ .../src/table/base/cell.jsx | 135 ++ .../src/table/base/filter.jsx | 212 +++ .../src/table/base/header.jsx | 195 +++ .../src/table/base/resize.jsx | 68 + .../src/table/base/row.jsx | 242 ++++ .../src/table/base/sort.jsx | 97 ++ .../src/table/base/wrapper.jsx | 26 + .../src/table/column-group.jsx | 39 + .../src/table/column.jsx | 105 ++ .../src/table/expanded.jsx | 244 ++++ .../src/table/expanded/row.jsx | 139 ++ .../fusion-next-component/src/table/fixed.jsx | 178 +++ .../src/table/fixed/body.jsx | 67 + .../src/table/fixed/header.jsx | 44 + .../src/table/fixed/wrapper.jsx | 21 + .../fusion-next-component/src/table/index.jsx | 109 ++ .../src/table/list-footer.jsx | 30 + .../src/table/list-header.jsx | 44 + .../fusion-next-component/src/table/list.jsx | 107 ++ .../src/table/list/body.jsx | 6 + .../src/table/list/row.jsx | 169 +++ .../fusion-next-component/src/table/lock.jsx | 773 +++++++++++ .../src/table/lock/body.jsx | 37 + .../src/table/lock/header.jsx | 22 + .../src/table/lock/row.jsx | 43 + .../fusion-next-component/src/table/main.scss | 435 ++++++ .../fusion-next-component/src/table/rtl.scss | 156 +++ .../src/table/scss/mixin.scss | 27 + .../src/table/scss/variable.scss | 162 +++ .../src/table/selection.jsx | 341 +++++ .../src/table/selection/row.jsx | 30 + .../src/table/sticky.jsx | 74 + .../src/table/sticky/header.jsx | 43 + .../fusion-next-component/src/table/style.js | 8 + .../fusion-next-component/src/table/tree.jsx | 198 +++ .../src/table/tree/cell.jsx | 110 ++ .../src/table/tree/row.jsx | 43 + .../fusion-next-component/src/table/util.js | 45 + .../src/table/virtual.jsx | 322 +++++ .../src/table/virtual/body.jsx | 93 ++ .../src/tag/closeable.jsx | 79 ++ .../fusion-next-component/src/tag/index.jsx | 71 + .../fusion-next-component/src/tag/main.scss | 239 ++++ .../fusion-next-component/src/tag/rtl.scss | 0 .../src/tag/scss/animation.scss | 15 + .../src/tag/scss/mixin.scss | 222 +++ .../src/tag/scss/placeholder.scss | 200 +++ .../src/tag/scss/variable.scss | 558 ++++++++ .../src/tag/selectable.jsx | 111 ++ .../fusion-next-component/src/tag/style.js | 3 + .../src/tag/tag-group.jsx | 30 + .../fusion-next-component/src/tag/tag.jsx | 285 ++++ .../src/time-picker/index.jsx | 24 + .../src/time-picker/main.scss | 26 + .../src/time-picker/module/time-menu.jsx | 146 ++ .../src/time-picker/panel.jsx | 197 +++ .../src/time-picker/rtl.scss | 9 + .../src/time-picker/scss/menu.scss | 55 + .../src/time-picker/scss/panel.scss | 33 + .../src/time-picker/scss/variable.scss | 102 ++ .../src/time-picker/style.js | 3 + .../src/time-picker/time-picker.jsx | 501 +++++++ .../src/time-picker/utils/index.js | 31 + .../src/timeline/index.jsx | 6 + .../src/timeline/locale/index.js | 6 + .../src/timeline/main.scss | 81 ++ .../src/timeline/rtl.scss | 38 + .../src/timeline/scss/mixin.scss | 199 +++ .../src/timeline/scss/normalize.scss | 23 + .../src/timeline/scss/util.scss | 3 + .../src/timeline/scss/variable.scss | 165 +++ .../src/timeline/style.js | 4 + .../src/timeline/view/timeline-item.jsx | 199 +++ .../src/timeline/view/timeline.jsx | 154 +++ .../src/transfer/.eslintrc | 5 + .../src/transfer/index.jsx | 3 + .../src/transfer/main.scss | 133 ++ .../src/transfer/scss/variable.scss | 125 ++ .../src/transfer/style.js | 4 + .../src/transfer/view/transfer-item.jsx | 181 +++ .../src/transfer/view/transfer-panel.jsx | 337 +++++ .../src/transfer/view/transfer.jsx | 613 +++++++++ .../src/tree-select/index.jsx | 20 + .../src/tree-select/main.scss | 22 + .../src/tree-select/scss/variable.scss | 31 + .../src/tree-select/style.js | 4 + .../src/tree-select/tree-select.jsx | 850 ++++++++++++ .../fusion-next-component/src/tree/index.jsx | 9 + .../fusion-next-component/src/tree/main.scss | 276 ++++ .../fusion-next-component/src/tree/rtl.scss | 34 + .../src/tree/scss/mixin.scss | 7 + .../src/tree/scss/variable.scss | 152 +++ .../fusion-next-component/src/tree/style.js | 4 + .../src/tree/view/tree-node-input.jsx | 27 + .../src/tree/view/tree-node.jsx | 595 +++++++++ .../src/tree/view/tree.jsx | 1132 ++++++++++++++++ .../src/tree/view/util.js | 215 +++ .../src/typography/index.js | 15 + .../src/typography/main.scss | 97 ++ .../src/typography/paragraph.jsx | 37 + .../src/typography/scss/mixin.scss | 2 + .../src/typography/scss/variable.scss | 84 ++ .../src/typography/style.js | 1 + .../src/typography/text.jsx | 102 ++ .../src/typography/title.jsx | 35 + .../src/typography/typography.jsx | 27 + .../fusion-next-component/src/upload/base.jsx | 29 + .../fusion-next-component/src/upload/card.jsx | 166 +++ .../src/upload/dragger.jsx | 115 ++ .../src/upload/index.jsx | 132 ++ .../fusion-next-component/src/upload/list.jsx | 518 +++++++ .../src/upload/main.scss | 499 +++++++ .../fusion-next-component/src/upload/rtl.scss | 38 + .../src/upload/runtime/html5-uploader.jsx | 150 +++ .../src/upload/runtime/iframe-uploader.jsx | 266 ++++ .../src/upload/runtime/index.jsx | 35 + .../src/upload/runtime/request.jsx | 116 ++ .../src/upload/runtime/selecter.jsx | 177 +++ .../src/upload/runtime/uploader.js | 154 +++ .../src/upload/scss/variable.scss | 295 ++++ .../fusion-next-component/src/upload/style.js | 4 + .../src/upload/transform.js | 30 + .../src/upload/upload.jsx | 582 ++++++++ .../fusion-next-component/src/upload/util.js | 54 + .../fusion-next-component/src/util/dom.js | 367 +++++ .../fusion-next-component/src/util/env.js | 40 + .../fusion-next-component/src/util/events.js | 61 + .../fusion-next-component/src/util/focus.js | 130 ++ .../fusion-next-component/src/util/func.js | 79 ++ .../fusion-next-component/src/util/guid.js | 16 + .../fusion-next-component/src/util/htmlId.js | 32 + .../fusion-next-component/src/util/index.js | 25 + .../fusion-next-component/src/util/keycode.js | 32 + .../fusion-next-component/src/util/log.js | 35 + .../fusion-next-component/src/util/object.js | 295 ++++ .../fusion-next-component/src/util/string.js | 55 + .../fusion-next-component/src/util/support.js | 94 ++ .../src/validate/index.js | 3 + .../src/virtual-list/index.jsx | 4 + .../src/virtual-list/main.scss | 4 + .../src/virtual-list/scss/mixin.scss | 2 + .../src/virtual-list/scss/variable.scss | 14 + .../src/virtual-list/style.js | 1 + .../src/virtual-list/virtual-list.jsx | 445 ++++++ .../es/basic/AIMakeBlank/amContainer.js | 4 +- .../es/basic/AIMakeBlank/amManifest.js | 60 +- .../es/basic/AIMakeBlank/container.js | 1 + .../es/basic/AIMakeBlank/index.js | 34 +- .../es/basic/AIMakeBlank/manifest.json | 2 +- .../es/basic/AIMakeIcon/IconFont.js | 30 +- .../es/basic/AIMakeIcon/amContainer.js | 4 +- .../es/basic/AIMakeIcon/amManifest.js | 18 +- .../es/basic/AIMakeIcon/container.js | 1 + .../es/basic/AIMakeIcon/index.js | 34 +- .../es/basic/AIMakeIcon/manifest.json | 2 +- .../es/basic/AIMakeImage/amContainer.js | 4 +- .../es/basic/AIMakeImage/amManifest.js | 18 +- .../es/basic/AIMakeImage/container.js | 1 + .../es/basic/AIMakeImage/index.js | 24 +- .../es/basic/AIMakeImage/manifest.json | 2 +- .../es/basic/AIMakeLink/amContainer.js | 4 +- .../es/basic/AIMakeLink/amManifest.js | 24 +- .../es/basic/AIMakeLink/container.js | 1 + .../es/basic/AIMakeLink/index.js | 32 +- .../es/basic/AIMakeLink/manifest.json | 2 +- .../es/basic/AIMakePlaceholder/amContainer.js | 4 +- .../es/basic/AIMakePlaceholder/amManifest.js | 24 +- .../es/basic/AIMakePlaceholder/container.js | 1 + .../es/basic/AIMakePlaceholder/index.js | 30 +- .../es/basic/AIMakePlaceholder/manifest.json | 2 +- .../es/basic/AIMakeText/amContainer.js | 4 +- .../es/basic/AIMakeText/amManifest.js | 34 +- .../es/basic/AIMakeText/container.js | 1 + .../es/basic/AIMakeText/index.js | 44 +- .../es/basic/AIMakeText/manifest.json | 2 +- .../es/basic/Root/amContainer.js | 4 +- .../es/basic/Root/amManifest.js | 10 +- .../es/basic/Root/container.js | 1 + .../es/basic/Root/index.js | 22 +- .../es/basic/Root/manifest.json | 2 +- .../es/basic/utils/HOCBackgroundProps.js | 28 +- .../es/basic/utils/HOCBoxModelProps.js | 42 +- .../es/basic/utils/HOCFlexLayoutProps.js | 34 +- .../es/basic/utils/HOCLayoutProps.js | 32 +- .../es/basic/utils/HOCTextProps.js | 32 +- .../multiple-exported-component/es/index.js | 1 + .../src/basic/AIMakeBlank/container.js | 3 +- .../src/basic/AIMakeBlank/index.js | 2 +- .../src/basic/AIMakeBlank/manifest.json | 2 +- .../src/basic/AIMakeIcon/container.js | 3 +- .../src/basic/AIMakeIcon/manifest.json | 2 +- .../src/basic/AIMakeImage/container.js | 3 +- .../src/basic/AIMakeImage/manifest.json | 2 +- .../src/basic/AIMakeLink/container.js | 3 +- .../src/basic/AIMakeLink/index.js | 2 +- .../src/basic/AIMakeLink/manifest.json | 2 +- .../src/basic/AIMakePlaceholder/container.js | 3 +- .../src/basic/AIMakePlaceholder/manifest.json | 2 +- .../src/basic/AIMakeText/container.js | 3 +- .../src/basic/AIMakeText/index.js | 2 +- .../src/basic/AIMakeText/manifest.json | 2 +- .../src/basic/Root/container.js | 3 +- .../src/basic/Root/manifest.json | 2 +- .../single-exported-component/es/container.js | 1 + .../single-exported-component/es/index.js | 16 +- .../es/manifest.json | 2 +- .../src/container.js | 3 +- .../src/manifest.json | 2 +- .../test/fixtures/ts-component/package.json | 29 + .../test/fixtures/ts-component/src/index.tsx | 32 + .../test/generator/Generator.ts | 188 --- packages/material-parser/test/index.ts | 79 ++ .../test/parser/ReactParser.ts | 40 - .../test/parser/snapshots/ReactParser.ts.md | 1039 --------------- .../test/parser/snapshots/ReactParser.ts.snap | Bin 6584 -> 0 bytes .../test/{scanner/Scanner.ts => scan.ts} | 21 +- .../test/scanner/snapshots/Scanner.ts.md | 633 --------- .../test/scanner/snapshots/Scanner.ts.snap | Bin 3708 -> 0 bytes .../material-parser/test/validate/index.ts | 1 + 913 files changed, 89678 insertions(+), 7991 deletions(-) delete mode 100644 packages/material-parser/src/Materialize.ts delete mode 100644 packages/material-parser/src/accesser/BaseAccesser.ts delete mode 100644 packages/material-parser/src/accesser/LocalAccesser.ts delete mode 100644 packages/material-parser/src/accesser/OnlineAccesser.ts delete mode 100644 packages/material-parser/src/extensions/MatConfigManifest.ts delete mode 100644 packages/material-parser/src/extensions/index.ts create mode 100644 packages/material-parser/src/generate.ts delete mode 100644 packages/material-parser/src/generator/Generator.ts create mode 100644 packages/material-parser/src/localize.ts create mode 100644 packages/material-parser/src/parse/handlers/defaultPropsHandler.ts rename packages/material-parser/src/{parser => parse}/handlers/index.ts (86%) rename packages/material-parser/src/{parser => parse}/handlers/propTypeHandler.ts (96%) create mode 100644 packages/material-parser/src/parse/index.ts rename packages/material-parser/src/{parser => parse}/resolver/checkIsIIFE.ts (100%) rename packages/material-parser/src/{parser => parse}/resolver/index.ts (73%) rename packages/material-parser/src/{parser => parse}/resolver/resolveHOC.ts (99%) rename packages/material-parser/src/{parser => parse}/resolver/resolveIIFE.ts (62%) create mode 100644 packages/material-parser/src/parse/resolver/resolveImport.ts rename packages/material-parser/src/{parser => parse}/resolver/resolveTranspiledClass.ts (80%) create mode 100644 packages/material-parser/src/parse/transform.ts delete mode 100644 packages/material-parser/src/parser/BaseParser.ts delete mode 100644 packages/material-parser/src/parser/ReactParser.ts create mode 100644 packages/material-parser/src/scan.ts delete mode 100644 packages/material-parser/src/scanner/Scanner.ts delete mode 100644 packages/material-parser/src/types/IGenerator.ts delete mode 100644 packages/material-parser/src/types/IParser.ts delete mode 100644 packages/material-parser/src/types/IScanner.ts delete mode 100644 packages/material-parser/test/Materialize.ts delete mode 100644 packages/material-parser/test/accesser/LocalAccesser.ts delete mode 100644 packages/material-parser/test/accesser/OnlineAccesser.ts delete mode 100644 packages/material-parser/test/accesser/snapshots/LocalAccesser.ts.md delete mode 100644 packages/material-parser/test/accesser/snapshots/LocalAccesser.ts.snap delete mode 100644 packages/material-parser/test/accesser/snapshots/OnlineAccesser.ts.md delete mode 100644 packages/material-parser/test/accesser/snapshots/OnlineAccesser.ts.snap delete mode 100644 packages/material-parser/test/fixtures/__snapshots__/test/Materialize.ts.md delete mode 100644 packages/material-parser/test/fixtures/__snapshots__/test/Materialize.ts.snap delete mode 100644 packages/material-parser/test/fixtures/__snapshots__/test/accesser/LocalAccesser.ts.md delete mode 100644 packages/material-parser/test/fixtures/__snapshots__/test/accesser/LocalAccesser.ts.snap delete mode 100644 packages/material-parser/test/fixtures/__snapshots__/test/generator/Generator.ts.md delete mode 100644 packages/material-parser/test/fixtures/__snapshots__/test/generator/Generator.ts.snap create mode 100644 packages/material-parser/test/fixtures/__snapshots__/test/index.ts.md create mode 100644 packages/material-parser/test/fixtures/__snapshots__/test/index.ts.snap delete mode 100644 packages/material-parser/test/fixtures/__snapshots__/test/parser/ReactParser.ts.md delete mode 100644 packages/material-parser/test/fixtures/__snapshots__/test/parser/ReactParser.ts.snap create mode 100644 packages/material-parser/test/fixtures/__snapshots__/test/scan.ts.md create mode 100644 packages/material-parser/test/fixtures/__snapshots__/test/scan.ts.snap delete mode 100644 packages/material-parser/test/fixtures/__snapshots__/test/scanner/Scanner.ts.md delete mode 100644 packages/material-parser/test/fixtures/__snapshots__/test/scanner/Scanner.ts.snap create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/.editorconfig create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/.eslintrc create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/.stylelintrc delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/affix/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/affix/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/animate/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/animate/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/badge/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/badge/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/balloon/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/balloon/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/breadcrumb/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/breadcrumb/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/button/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/button/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/calendar/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/calendar/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/card/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/card/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/cascader-select/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/cascader-select/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/cascader/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/cascader/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/checkbox/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/checkbox/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/collapse/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/collapse/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/config-provider/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/config-provider/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/date-picker/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/date-picker/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/dialog/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/dialog/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/drawer/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/drawer/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/dropdown/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/dropdown/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/field/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/field/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/form/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/form/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/grid/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/grid/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/icon/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/icon/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/input/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/input/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/loading/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/loading/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/menu-button/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/menu-button/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/menu/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/menu/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/message/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/message/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/nav/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/nav/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/number-picker/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/number-picker/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/overlay/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/overlay/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/pagination/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/pagination/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/paragraph/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/paragraph/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/progress/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/progress/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/radio/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/radio/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/range/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/range/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/rating/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/rating/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/search/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/search/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/select/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/select/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/slider/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/slider/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/split-button/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/split-button/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/step/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/step/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/switch/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/switch/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/tab/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/tab/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/table/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/table/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/tag/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/tag/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/time-picker/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/time-picker/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/timeline/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/timeline/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/transfer/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/transfer/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/tree-select/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/tree-select/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/tree/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/tree/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/upload/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/upload/manifest.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/virtual-list/container.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/virtual-list/manifest.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/affix/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/affix/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/affix/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/affix/util.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/.stylelintrc create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/animate.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/child.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/expand.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_attention-seekers/_buttonClick.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_attention-seekers/_press.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_attention-seekers/_pulse.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_attention-seekers/_shake.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_attention-seekers/_unpress.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_attention-seekers/attention-seekers.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_bounce-entrances/_bounceIn.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_bounce-entrances/bounce-entrances.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_bounce-exits/_bounceOut.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_bounce-exits/bounce-exits.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_expand-entrances/_expandInDown.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_expand-entrances/_expandInUp.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_expand-entrances/_withFade.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_expand-exits/_expandOutDown.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_expand-exits/_expandOutUp.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_expand-exits/_withFade.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeIn.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeInDown.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeInDownBig.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeInLeft.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeInLeftBig.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeInRight.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeInRightBig.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeInUp.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeInUpBig.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/fading-entrances.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOut.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOutDown.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOutDownBig.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOutLeft.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOutLeftBig.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOutRight.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOutRightBig.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOutUp.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOutUpBig.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/fading-exits.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_other-entrances/_pressIn.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_other-entrances/_pressInSmall.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_other-entrances/_waterIn.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_other-entrances/other-entrances.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_other-exits/_pressOut.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_other-exits/_pressOutSmall.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_other-exits/_waterOut.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_other-exits/other-exits.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-entrances/_slideInDown.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-entrances/_slideInLeft.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-entrances/_slideInRight.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-entrances/_slideInUp.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-entrances/sliding-entrances.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-exits/_slideOutDown.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-exits/_slideOutLeft.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-exits/_slideOutRight.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-exits/_slideOutUp.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-exits/sliding-exits.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-entrances/_zoomIn.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-entrances/_zoomInDown.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-entrances/_zoomInLeft.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-entrances/_zoomInPulse.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-entrances/_zoomInQuick.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-entrances/_zoomInRight.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-entrances/_zoomInUp.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-entrances/zooming-entrances.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-exits/_zoomOut.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-exits/_zoomOutDown.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-exits/_zoomOutLeft.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-exits/_zoomOutPulse.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-exits/_zoomOutQuick.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-exits/_zoomOutRight.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-exits/_zoomOutUp.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-exits/zooming-exits.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/animate/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/avatar/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/avatar/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/avatar/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/avatar/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/avatar/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/badge/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/badge/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/badge/rtl.scss create mode 100755 packages/material-parser/test/fixtures/fusion-next-component/src/badge/scss/function.scss create mode 100755 packages/material-parser/test/fixtures/fusion-next-component/src/badge/scss/mixin.scss create mode 100755 packages/material-parser/test/fixtures/fusion-next-component/src/badge/scss/placeholder.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/badge/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/badge/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/badge/sup.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/balloon/alignMap.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/balloon/balloon.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/balloon/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/balloon/inner.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/balloon/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/balloon/rtl.scss create mode 100755 packages/material-parser/test/fixtures/fusion-next-component/src/balloon/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/balloon/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/balloon/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/balloon/tooltip.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/balloon/util.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/box/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/box/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/box/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/box/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/box/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/breadcrumb/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/breadcrumb/item.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/breadcrumb/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/breadcrumb/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/breadcrumb/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/breadcrumb/style.js delete mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/build.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/button/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/button/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/button/rtl.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/button/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/button/scss/normalize.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/button/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/button/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/button/view/button.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/button/view/group.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/calendar/.eslintrc create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/calendar/calendar.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/calendar/head/card-header.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/calendar/head/date-panel-header.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/calendar/head/menu.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/calendar/head/month-panel-header.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/calendar/head/range-panel-header.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/calendar/head/year-panel-header.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/calendar/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/calendar/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/calendar/range-calendar.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/calendar/rtl.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/calendar/scss/animation.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/calendar/scss/header.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/calendar/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/calendar/scss/normalize.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/calendar/scss/table.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/calendar/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/calendar/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/calendar/table/date-table-head.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/calendar/table/date-table.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/calendar/table/month-table.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/calendar/table/year-table.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/calendar/utils/index.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/card/actions.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/card/bullet-header.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/card/card.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/card/collapse-content.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/card/content.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/card/divider.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/card/header.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/card/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/card/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/card/media.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/card/rtl.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/card/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/card/scss/normalize.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/card/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/card/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/cascader-select/cascader-select.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/cascader-select/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/cascader-select/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/cascader-select/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/cascader-select/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/cascader/cascader.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/cascader/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/cascader/item.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/cascader/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/cascader/menu.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/cascader/rtl.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/cascader/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/cascader/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/cascader/utils.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/checkbox/checkbox-group.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/checkbox/checkbox.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/checkbox/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/checkbox/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/checkbox/rtl.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/checkbox/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/checkbox/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/collapse/collapse.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/collapse/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/collapse/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/collapse/panel.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/collapse/rtl.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/collapse/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/collapse/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/collapse/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/config-provider/cache.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/config-provider/config.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/config-provider/consumer.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/config-provider/error-boundary.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/config-provider/get-context-props.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/config-provider/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/config-provider/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/config-provider/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/core/base/_accessibility.scss create mode 100755 packages/material-parser/test/fixtures/fusion-next-component/src/core/base/_normalize.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/core/base/_reset.scss create mode 100755 packages/material-parser/test/fixtures/fusion-next-component/src/core/base/_typography.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/core/form-element.scss create mode 100755 packages/material-parser/test/fixtures/fusion-next-component/src/core/index-noreset.scss create mode 100755 packages/material-parser/test/fixtures/fusion-next-component/src/core/index.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/core/mask.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/core/popup.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/core/reset.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_color.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_corner.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_font.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_global.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_icon.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_line.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_motion.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_shadow.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_size.scss create mode 100755 packages/material-parser/test/fixtures/fusion-next-component/src/core/util/_function.scss create mode 100755 packages/material-parser/test/fixtures/fusion-next-component/src/core/util/_mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/core/utility/_form-element.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/core/utility/_mask.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/core/utility/_popup.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/date-picker.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/module/panel-footer.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/month-picker.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/range-picker.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/rtl.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/scss/date-picker.scss create mode 100755 packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/scss/range-picker.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/util/index.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/week-picker.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/year-picker.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/demo-helper/.stylelintrc create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/demo-helper/icon.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/demo-helper/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/demo-helper/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/demo-helper/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/dialog/dialog.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/dialog/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/dialog/inner.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/dialog/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/dialog/rtl.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/dialog/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/dialog/show.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/dialog/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/divider/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/divider/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/divider/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/divider/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/divider/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/drawer/drawer.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/drawer/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/drawer/inner.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/drawer/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/drawer/rtl.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/drawer/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/drawer/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/drawer/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/dropdown/dropdown.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/dropdown/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/dropdown/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/dropdown/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/field/index.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/field/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/field/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/field/utils.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/form/enhance.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/form/error.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/form/form.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/form/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/form/item.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/form/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/form/reset.jsx create mode 100755 packages/material-parser/test/fixtures/fusion-next-component/src/form/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/form/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/form/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/form/submit.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/grid/col.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/grid/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/grid/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/grid/row.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/grid/rtl.scss create mode 100755 packages/material-parser/test/fixtures/fusion-next-component/src/grid/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/grid/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/grid/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/icon/icon-font.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/icon/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/icon/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/icon/rtl.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/icon/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/index.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/input/base.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/input/group.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/input/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/input/input.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/input/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/input/password.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/input/rtl.scss create mode 100755 packages/material-parser/test/fixtures/fusion-next-component/src/input/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/input/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/input/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/input/textarea.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/list/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/list/item.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/list/list.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/list/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/list/rtl.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/list/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/list/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/list/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/loading/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/loading/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/loading/rtl.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/loading/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/loading/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/loading/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/locale/en-us.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/locale/ja-jp.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/locale/zh-cn.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/locale/zh-tw.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/menu-button/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/menu-button/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/menu-button/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/menu-button/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/menu-button/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/menu/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/menu/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/menu/rtl.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/menu/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/menu/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/menu/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/menu/view/checkable-item.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/menu/view/checkbox-item.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/menu/view/create.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/menu/view/divider.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/menu/view/group.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/menu/view/item.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/menu/view/menu.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/menu/view/popup-item.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/menu/view/radio-item.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/menu/view/selectable-item.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/menu/view/sub-menu.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/menu/view/util.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/message/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/message/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/message/message.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/message/rtl.scss create mode 100755 packages/material-parser/test/fixtures/fusion-next-component/src/message/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/message/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/message/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/message/toast.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/mixin-ui-state/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/nav/group.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/nav/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/nav/item.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/nav/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/nav/nav.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/nav/popup-item.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/nav/rtl.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/nav/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/nav/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/nav/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/nav/sub-nav.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/notification/config.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/notification/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/notification/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/notification/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/number-picker/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/number-picker/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/number-picker/number-picker.jsx create mode 100755 packages/material-parser/test/fixtures/fusion-next-component/src/number-picker/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/number-picker/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/number-picker/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/overlay/gateway.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/overlay/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/overlay/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/overlay/manager.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/overlay/overlay.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/overlay/popup.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/overlay/position.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/overlay/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/overlay/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/overlay/utils/find-node.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/overlay/utils/position.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/pagination/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/pagination/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/pagination/pagination.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/pagination/rtl.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/pagination/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/pagination/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/pagination/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/paragraph/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/paragraph/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/paragraph/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/paragraph/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/paragraph/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/progress/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/progress/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/progress/rtl.scss create mode 100755 packages/material-parser/test/fixtures/fusion-next-component/src/progress/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/progress/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/progress/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/progress/view/progress-circle.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/progress/view/progress-line.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/progress/view/progress.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/radio/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/radio/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/radio/radio-group.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/radio/radio.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/radio/rtl.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/radio/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/radio/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/range/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/range/main.scss create mode 100755 packages/material-parser/test/fixtures/fusion-next-component/src/range/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/range/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/range/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/range/utils.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/range/view/fixedSlider.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/range/view/mark.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/range/view/range.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/range/view/scale.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/range/view/selected.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/range/view/slider.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/range/view/track.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/rating/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/rating/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/rating/rating.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/rating/rtl.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/rating/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/rating/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/rating/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/responsive-grid/cell.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/responsive-grid/create-style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/responsive-grid/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/responsive-grid/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/responsive-grid/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/responsive-grid/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/responsive-grid/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/responsive-grid/util.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/search/Search.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/search/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/search/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/search/rtl.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/search/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/search/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/search/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/select/auto-complete.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/select/base.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/select/data-store.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/select/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/select/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/select/option-group.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/select/option.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/select/rtl.scss create mode 100755 packages/material-parser/test/fixtures/fusion-next-component/src/select/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/select/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/select/select.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/select/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/select/util.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/shell/base.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/shell/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/shell/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/shell/rtl.scss create mode 100755 packages/material-parser/test/fixtures/fusion-next-component/src/shell/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/shell/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/shell/shell.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/shell/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/shell/util.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/slider/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/slider/main.scss create mode 100755 packages/material-parser/test/fixtures/fusion-next-component/src/slider/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/slider/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/slider/slick/arrow.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/slider/slick/dots.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/slider/slick/inner-slider.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/slider/slick/mixins/event-handlers.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/slider/slick/mixins/helpers.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/slider/slick/mixins/trackHelper.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/slider/slick/track.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/slider/slider.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/slider/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/split-button/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/split-button/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/split-button/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/split-button/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/split-button/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/step/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/step/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/step/rtl.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/step/scss/arrow.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/step/scss/basic.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/step/scss/circle.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/step/scss/dot.scss create mode 100755 packages/material-parser/test/fixtures/fusion-next-component/src/step/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/step/scss/normalize.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/step/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/step/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/step/view/step-item.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/step/view/step.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/switch/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/switch/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/switch/rtl.scss create mode 100755 packages/material-parser/test/fixtures/fusion-next-component/src/switch/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/switch/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/switch/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tab/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tab/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tab/rtl.scss create mode 100755 packages/material-parser/test/fixtures/fusion-next-component/src/tab/scss/mixin.scss create mode 100755 packages/material-parser/test/fixtures/fusion-next-component/src/tab/scss/placeholder.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tab/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tab/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tab/tab.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tab/tabs/content.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tab/tabs/nav.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tab/tabs/tab-item.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tab/tabs/utils.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/base.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/base/body.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/base/cell.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/base/filter.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/base/header.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/base/resize.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/base/row.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/base/sort.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/base/wrapper.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/column-group.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/column.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/expanded.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/expanded/row.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/fixed.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/fixed/body.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/fixed/header.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/fixed/wrapper.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/list-footer.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/list-header.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/list.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/list/body.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/list/row.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/lock.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/lock/body.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/lock/header.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/lock/row.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/rtl.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/selection.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/selection/row.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/sticky.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/sticky/header.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/tree.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/tree/cell.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/tree/row.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/util.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/virtual.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/table/virtual/body.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tag/closeable.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tag/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tag/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tag/rtl.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tag/scss/animation.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tag/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tag/scss/placeholder.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tag/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tag/selectable.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tag/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tag/tag-group.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tag/tag.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/time-picker/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/time-picker/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/time-picker/module/time-menu.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/time-picker/panel.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/time-picker/rtl.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/time-picker/scss/menu.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/time-picker/scss/panel.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/time-picker/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/time-picker/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/time-picker/time-picker.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/time-picker/utils/index.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/timeline/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/timeline/locale/index.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/timeline/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/timeline/rtl.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/timeline/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/timeline/scss/normalize.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/timeline/scss/util.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/timeline/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/timeline/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/timeline/view/timeline-item.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/timeline/view/timeline.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/transfer/.eslintrc create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/transfer/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/transfer/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/transfer/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/transfer/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/transfer/view/transfer-item.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/transfer/view/transfer-panel.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/transfer/view/transfer.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tree-select/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tree-select/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tree-select/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tree-select/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tree-select/tree-select.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tree/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tree/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tree/rtl.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tree/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tree/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tree/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tree/view/tree-node-input.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tree/view/tree-node.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tree/view/tree.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/tree/view/util.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/typography/index.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/typography/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/typography/paragraph.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/typography/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/typography/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/typography/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/typography/text.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/typography/title.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/typography/typography.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/upload/base.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/upload/card.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/upload/dragger.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/upload/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/upload/list.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/upload/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/upload/rtl.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/upload/runtime/html5-uploader.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/upload/runtime/iframe-uploader.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/upload/runtime/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/upload/runtime/request.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/upload/runtime/selecter.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/upload/runtime/uploader.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/upload/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/upload/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/upload/transform.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/upload/upload.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/upload/util.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/util/dom.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/util/env.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/util/events.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/util/focus.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/util/func.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/util/guid.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/util/htmlId.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/util/index.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/util/keycode.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/util/log.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/util/object.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/util/string.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/util/support.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/validate/index.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/virtual-list/index.jsx create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/virtual-list/main.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/virtual-list/scss/mixin.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/virtual-list/scss/variable.scss create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/virtual-list/style.js create mode 100644 packages/material-parser/test/fixtures/fusion-next-component/src/virtual-list/virtual-list.jsx create mode 100644 packages/material-parser/test/fixtures/ts-component/package.json create mode 100644 packages/material-parser/test/fixtures/ts-component/src/index.tsx delete mode 100644 packages/material-parser/test/generator/Generator.ts create mode 100644 packages/material-parser/test/index.ts delete mode 100644 packages/material-parser/test/parser/ReactParser.ts delete mode 100644 packages/material-parser/test/parser/snapshots/ReactParser.ts.md delete mode 100644 packages/material-parser/test/parser/snapshots/ReactParser.ts.snap rename packages/material-parser/test/{scanner/Scanner.ts => scan.ts} (56%) delete mode 100644 packages/material-parser/test/scanner/snapshots/Scanner.ts.md delete mode 100644 packages/material-parser/test/scanner/snapshots/Scanner.ts.snap diff --git a/packages/material-parser/src/Materialize.ts b/packages/material-parser/src/Materialize.ts deleted file mode 100644 index 06928f804..000000000 --- a/packages/material-parser/src/Materialize.ts +++ /dev/null @@ -1,48 +0,0 @@ -import LocalAccesser from './accesser/LocalAccesser'; -import OnlineAccesser from './accesser/OnlineAccesser'; -import { IComponentMaterial } from './otter-core'; -import { IAccesser, IMaterializeOptions } from './types'; - -/** - * 物料化(将普通组件包装为可接入和可流通的物料组件的过程,称为物料化)运行于 node 端 - * @class Materialize - */ -class Materialize { - /** - * 物料化配置项 - * @private - * @type {IMaterializeOptions} - * @memberof Materialize - */ - private options: IMaterializeOptions; - - /** - * 接入器 - * @private - * @type {IAccesser} - * @memberof Materialize - */ - private accesser?: IAccesser; - - constructor(options: IMaterializeOptions) { - this.options = options; - } - - /** - * 开始物料化 - * - * @returns {Promise} - * @memberof Materialize - */ - public async start(): Promise { - // 分发请求到对应接入器 - if (this.options.accesser === 'local') { - this.accesser = new LocalAccesser(this.options); - } else { - this.accesser = new OnlineAccesser(this.options); - } - return this.accesser.access(); - } -} - -export default Materialize; diff --git a/packages/material-parser/src/accesser/BaseAccesser.ts b/packages/material-parser/src/accesser/BaseAccesser.ts deleted file mode 100644 index 40269a88d..000000000 --- a/packages/material-parser/src/accesser/BaseAccesser.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { IComponentMaterial } from '../otter-core'; -import { IAccesser, IMaterializeOptions } from '../types'; - -/** - * 接入器模板基类 - * @abstract - * @class BaseAccesser - * @implements {IAccesser} - */ -abstract class BaseAccesser implements IAccesser { - /** - * 物料化配置项 - * @protected - * @type {IMaterializeOptions} - * @memberof BaseAccesser - */ - protected options: IMaterializeOptions; - - constructor(options: IMaterializeOptions) { - this.options = options; - } - - public abstract access(): Promise; -} - -export default BaseAccesser; diff --git a/packages/material-parser/src/accesser/LocalAccesser.ts b/packages/material-parser/src/accesser/LocalAccesser.ts deleted file mode 100644 index e3bc885ce..000000000 --- a/packages/material-parser/src/accesser/LocalAccesser.ts +++ /dev/null @@ -1,78 +0,0 @@ -import Generator from '../generator/Generator'; -import { debug, IComponentMaterial } from '../otter-core'; -import BaseParser from '../parser/BaseParser'; -import ReactParser from '../parser/ReactParser'; -import Scanner from '../scanner/Scanner'; -import { IMaterialParsedModel, IMaterialScanModel, IParser } from '../types'; -import BaseAccesser from './BaseAccesser'; - -const log = debug.extend('mat'); - -/** - * 本地接入器 - * @class LocalAccesser - * @extends {BaseAccesser} - */ -class LocalAccesser extends BaseAccesser { - /** - * 扫描器实例 - * @private - * @type {Scanner} - * @memberof LocalAccesser - */ - private scanner!: Scanner; - - /** - * 解析器实例 - * @private - * @type {IParser} - * @memberof LocalAccesser - */ - private parser!: IParser; - - /** - * 生成器实例 - * @private - * @type {Generator} - * @memberof LocalAccesser - */ - private generator!: Generator; - - public async access(): Promise { - await this.init(); - // 开始扫描 - const matScanModel: IMaterialScanModel = await this.scanner.scan(); - log('matScanModel', matScanModel); - // 开始解析 - const matParsedModels: IMaterialParsedModel[] = await this.parser.parse( - matScanModel, - ); - log('matParsedModels', matParsedModels); - // 开始生产 - const material: IComponentMaterial = await this.generator.generate( - matScanModel, - matParsedModels, - ); - log('material', material); - return material; - } - - /** - * 初始化 - * @private - * @returns {Promise} - * @memberof LocalAccesser - */ - private async init(): Promise { - const options = this.options; - this.scanner = new Scanner(options); - const ecology = await BaseParser.recognizeEcology(options); - if (ecology === 'react') { - // debugger; - this.parser = new ReactParser(options); - this.generator = new Generator(options); - } - } -} - -export default LocalAccesser; diff --git a/packages/material-parser/src/accesser/OnlineAccesser.ts b/packages/material-parser/src/accesser/OnlineAccesser.ts deleted file mode 100644 index 160f4d20b..000000000 --- a/packages/material-parser/src/accesser/OnlineAccesser.ts +++ /dev/null @@ -1,121 +0,0 @@ -import spawn from 'cross-spawn-promise'; -import { ensureDir, ensureFile, writeFile } from 'fs-extra'; -import { join } from 'path'; -import semver from 'semver'; -import uuid from 'short-uuid'; -import { debug, IComponentMaterial, OtterError } from '../otter-core'; -import { IMaterializeOptions } from '../types'; -import BaseAccesser from './BaseAccesser'; -import LocalAccesser from './LocalAccesser'; - -const log = debug.extend('mat'); - -/** - * 在线接入 - * @class OnlineAccesser - * @extends {BaseAccesser} - */ -class OnlineAccesser extends BaseAccesser { - /** - * 临时目录 - * - * @private - * @type {string} - * @memberof OnlineAccesser - */ - private tempDir: string = ''; - - public async access(): Promise { - // 创建临时目录 - this.tempDir = await this.createTempDir(); - // 创建组件包 - const { name, version } = this.getPkgNameAndVersion(this.options.entry); - await this.createFakePackage({ - pkgName: name, - pkgVersion: version, - }); - // 将问题转化为本地物料化场景 - const options: IMaterializeOptions = { - cwd: this.tempDir, - entry: join(this.tempDir, 'node_modules', name), - accesser: 'local', - isExportedAsMultiple: this.options.isExportedAsMultiple, - }; - const localAccesser = new LocalAccesser(options); - return localAccesser.access(); - } - - /** - * 创建组件包 - * - * @private - * @param {{ - * pkgName: string; - * pkgVersion: string; - * }} params - * @returns {Promise} - * @memberof OnlineAccesser - */ - private async createFakePackage(params: { - pkgName: string; - pkgVersion: string; - }): Promise { - // 创建临时组件包 - const tempDir = this.tempDir; - const pkgJsonFilePath = join(tempDir, 'package.json'); - await ensureFile(pkgJsonFilePath); - await writeFile( - pkgJsonFilePath, - JSON.stringify({ - name: params.pkgName, - version: params.pkgVersion, - dependencies: { - [params.pkgName]: params.pkgVersion, - }, - }), - ); - // 安装依赖 - const npmClient = this.options.npmClient || 'tnpm'; - await spawn(npmClient, ['i'], { stdio: 'inherit', cwd: tempDir } as any); - } - - /** - * 创建临时目录 - * - * @private - * @returns {Promise} 返回临时文件夹路径 - * @memberof LocalGenerator - */ - private async createTempDir(): Promise { - const tempDirName = uuid.generate(); - const tempDir = join(__dirname, '../../node_modules/.temp/', tempDirName); - await ensureDir(tempDir); - log('create temp dir successfully', tempDir); - return tempDir; - } - - /** - * 分离物料组件名称和版本号 - * - * @private - * @param {string} pkgNameWithVersion - * @returns {{ [key: string]: any }} - * @memberof OnlineAccesser - */ - private getPkgNameAndVersion( - pkgNameWithVersion: string, - ): { [key: string]: any } { - const matches = pkgNameWithVersion.match(/(@\d+\.\d+\.\d+)$/); - if (!matches) { - throw new OtterError(`Illegal semver version: ${pkgNameWithVersion}`); - } - const semverObj = semver.coerce(matches[0]); - const name = pkgNameWithVersion.replace(matches[0], ''); - return { - version: semverObj && semverObj.version, - name, - }; - } -} - -export default OnlineAccesser; diff --git a/packages/material-parser/src/extensions/MatConfigManifest.ts b/packages/material-parser/src/extensions/MatConfigManifest.ts deleted file mode 100644 index 491fdce8f..000000000 --- a/packages/material-parser/src/extensions/MatConfigManifest.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { writeFile } from 'fs-extra'; -import { IComponentMaterial } from '../otter-core'; - -/** - * 配置 manifest(物料化场景下可以使用此扩展点) - * - 扩展点名称:mat:config:manifest - * - 对应 Studio 所处状态:进入 就绪态 前 - * - * @export - * @param {{ - * manifestObj: IComponentMaterial, - * manifestFilePath: string, - * }} params - * @returns {Promise<{ - * manifestJS: string, - * manifestFilePath: string, - * manifestObj: IComponentMaterial, - * }>} - */ -export default async function matConfigManifest(params: { - manifestObj: IComponentMaterial; - manifestFilePath: string; -}): Promise<{ - manifestJSON: string; - manifestFilePath: string; - manifestObj: IComponentMaterial; -}> { - const manifestJSON = JSON.stringify(params.manifestObj); - - await writeFile(params.manifestFilePath, manifestJSON); - - return Promise.resolve({ - manifestJSON, - manifestObj: params.manifestObj, - manifestFilePath: params.manifestFilePath, - }); -} diff --git a/packages/material-parser/src/extensions/index.ts b/packages/material-parser/src/extensions/index.ts deleted file mode 100644 index d35c1b720..000000000 --- a/packages/material-parser/src/extensions/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { ExtensionName } from '../types'; -import MatConfigManifest from './MatConfigManifest'; - -export default { - [ExtensionName.CONFIGMANIFEST]: MatConfigManifest, -}; diff --git a/packages/material-parser/src/generate.ts b/packages/material-parser/src/generate.ts new file mode 100644 index 000000000..115e79b6f --- /dev/null +++ b/packages/material-parser/src/generate.ts @@ -0,0 +1,59 @@ +import { debug, ComponentMeta } from './otter-core'; +import { IMaterialParsedModel, IMaterialScanModel } from './types'; + +const log = debug.extend('mat'); + +export default async function( + matScanModel: IMaterialScanModel, + matParsedModels: IMaterialParsedModel[], +): Promise { + const containerList = []; + for (const matParsedModel of matParsedModels) { + // TODO 可以开放扩展点让上层使用者指定导出哪些组件或者不导出哪些组件 + // 默认排除掉 defaultExportName 为空的组件 + if (!matParsedModel.componentName) { + log('skip'); + continue; + } + // 组装 manifest + const manifest: any = await genManifest(matScanModel, matParsedModel); + + containerList.push(manifest); + } + + return containerList; +} + +/** + * 生成 manifest + * + * @param {IMaterialParsedModel} matParsedModel + * @returns {Promise< + * manifestObj: ComponentMeta, // 组件描述 + * >} + * @memberof LocalGenerator + */ +export async function genManifest( + matScanModel: IMaterialScanModel, + matParsedModel: IMaterialParsedModel, +): Promise { + const manifestObj: Partial = { + componentName: matParsedModel.componentName, + title: matScanModel.pkgName, + docUrl: '', + screenshot: '', + npm: { + package: matScanModel.pkgName, + version: matScanModel.pkgVersion, + exportName: matParsedModel.componentName, + main: matScanModel.mainEntry, + destructuring: false, + subName: '', + }, + }; + + // 填充 props + manifestObj.props = matParsedModel.props; + // 执行扩展点 + return manifestObj as ComponentMeta; +} diff --git a/packages/material-parser/src/generator/Generator.ts b/packages/material-parser/src/generator/Generator.ts deleted file mode 100644 index bec97c827..000000000 --- a/packages/material-parser/src/generator/Generator.ts +++ /dev/null @@ -1,175 +0,0 @@ -import { dirname, join } from 'path'; -import defaultExtension from '../extensions'; -import { debug, IComponentMaterial, PropsSection } from '../otter-core'; -import { - IGenerator, - IMaterializeOptions, - IMaterialParsedModel, - IMaterialScanModel, -} from '../types'; - -const log = debug.extend('mat'); - -/** - * 用于物料工作台 - */ -class Generator implements IGenerator { - /** - * 物料化配置项 - * @protected - * @type {IMaterializeOptions} - * @memberof BaseGenerator - */ - /** - * 物料化配置项 - * @protected - * @type {IMaterializeOptions} - * @memberof BaseGenerator - */ - protected options!: IMaterializeOptions; - - constructor(options: IMaterializeOptions) { - this.options = options; - } - - public async generate( - matScanModel: IMaterialScanModel, - matParsedModels: IMaterialParsedModel[], - ): Promise { - // const model: IMaterialinSchema = {} as any; - // 标记协议版本号 - // model.version = '1.0.0'; - // 组装 pkgInfo - // model.pkgInfo = pkgInfo; - const containerList = []; - for (const matParsedModel of matParsedModels) { - // TODO 可以开放扩展点让上层使用者指定导出哪些组件或者不导出哪些组件 - // 默认排除掉 defaultExportName 为空的组件 - if ( - !matParsedModel.defaultExportName || - !matParsedModel.defaultExportName.length - ) { - log('skip', matParsedModel.filePath); - continue; - } - // 组装 manifest - const manifest: any = await this.genManifest( - matScanModel, - matParsedModel, - ); - - containerList.push(manifest); - } - - // const components: IMaterialinComponent[] = bundle.bundleObj.components; - // Object.keys(bundle.bundleObj.Modules).forEach(key => { - // const { origin, manifest } = bundle.bundleObj.Modules[key]; - // const component: IMaterialinComponent = { - // componentName: key, - // origin, - // manifest, - // }; - // components.push(component); - // }); - // model.components = components; - // log('materialsModel', JSON.stringify(bundle.bundleObj)); - - return containerList; - } - - /** - * 生成 manifest - * - * @param {IMaterialParsedModel} matParsedModel - * @returns {Promise<{ - * manifestFilePath: string, // manifest 文件路径 - * manifestJS: string, // manifest 文件内容 - * manifestObj: IMaterialinManifest, // manifest 文件对象 - * }>} - * @memberof LocalGenerator - */ - public async genManifest( - matScanModel: IMaterialScanModel, - matParsedModel: IMaterialParsedModel, - ): Promise<{ - manifestFilePath: string; // manifest 文件路径 - manifestObj: IComponentMaterial; // manifest 文件对象 - }> { - const manifestObj: Partial = { - // componentName: matParsedModel.defaultExportName, - title: matScanModel.pkgName, - docUrl: '', - screenshot: '', - npm: { - package: matScanModel.pkgName, - version: matScanModel.pkgVersion, - exportName: '', // matParsedModel.defaultExportName, - main: matScanModel.mainEntry, - destructuring: false, - subName: '', - }, - }; - - const defaultManifestFilePath = join( - dirname(matParsedModel.filePath), - './manifest.json', - ); - - // 填充 props - manifestObj.props = matParsedModel.props; - // 执行扩展点 - const manifest: any = await this.executeExtensionPoint( - 'mat:config:manifest', - { - manifestObj, - manifestFilePath: defaultManifestFilePath, - }, - ); - return { - manifestObj: manifest.manifestObj, - manifestFilePath: manifest.manifestFilePath, - }; - } - - /** - * 填充 props - * - * @public - * @param {IMaterialParsedModel} matParsedModel - * @returns {IMaterialinProp[]} - * @memberof BaseGenerator - */ - public populateProps( - matParsedModel: IMaterialParsedModel, - ): PropsSection['props'] { - // @ts-ignore - return matParsedModel.props; - } - - /** - * 执行扩展点 - * @param {string} extName 扩展点名称 - * @param {...any[]} args 参数 - * @returns {Promise} - * @memberof BaseGenerator - */ - public async executeExtensionPoint( - extName: string, - ...args: any[] - ): Promise { - const options = this.options; - const optionsExtensions: any = options.extensions; - const defaultExtensions: any = defaultExtension; - - const ext: any = - optionsExtensions && optionsExtensions[extName] - ? optionsExtensions[extName] - : defaultExtensions[extName]; - if (!ext) { - throw new Error(`Unsupported extension point: ${extName}`); - } - return ext(...args); - } -} - -export default Generator; diff --git a/packages/material-parser/src/index.ts b/packages/material-parser/src/index.ts index d38da4098..8d3b3118c 100644 --- a/packages/material-parser/src/index.ts +++ b/packages/material-parser/src/index.ts @@ -1,8 +1,26 @@ -import Materialize from './Materialize'; - export { default as validate } from './validate'; export { default as schema } from './validate/schema.json'; export * from './types'; -export default Materialize; +import { IMaterializeOptions } from './types'; +import { ComponentMeta } from './otter-core'; +import scan from './scan'; +import generate from './generate'; +import parse from './parse'; +import localize from './localize'; + +export default async function( + options: IMaterializeOptions, +): Promise { + const { accesser = 'local' } = options; + if (accesser === 'online') { + const { entry, cwd } = await localize(options); + options.entry = entry; + options.cwd = cwd; + } + const scanedModel = await scan(options); + const parsedModel = await parse(scanedModel.modules[0]); + const result = await generate(scanedModel, parsedModel); + return result; +} diff --git a/packages/material-parser/src/localize.ts b/packages/material-parser/src/localize.ts new file mode 100644 index 000000000..dfdbcbbad --- /dev/null +++ b/packages/material-parser/src/localize.ts @@ -0,0 +1,108 @@ +import spawn from 'cross-spawn-promise'; +import { ensureDir, ensureFile, writeFile } from 'fs-extra'; +import { join } from 'path'; +import semver from 'semver'; +import uuid from 'short-uuid'; +import { debug, OtterError } from './otter-core'; +import { IMaterializeOptions } from './types'; + +const log = debug.extend('mat'); + +/** + * 创建组件包 + * + * @private + * @param {{ + * pkgName: string; + * pkgVersion: string; + * }} params + * @returns {Promise} + * @memberof OnlineAccesser + */ +export async function createFakePackage(params: { + tempDir: string; + pkgName: string; + pkgVersion: string; + npmClient?: string; +}): Promise { + // 创建临时组件包 + const tempDir = params.tempDir; + const pkgJsonFilePath = join(tempDir, 'package.json'); + await ensureFile(pkgJsonFilePath); + await writeFile( + pkgJsonFilePath, + JSON.stringify({ + name: params.pkgName, + version: params.pkgVersion, + dependencies: { + [params.pkgName]: params.pkgVersion, + }, + }), + ); + debugger; + // 安装依赖 + const npmClient = params.npmClient || 'tnpm'; + await spawn(npmClient, ['i'], { stdio: 'inherit', cwd: tempDir } as any); +} + +/** + * 创建临时目录 + * + * @private + * @returns {Promise} 返回临时文件夹路径 + * @memberof LocalGenerator + */ +export async function createTempDir(): Promise { + const tempDirName = uuid.generate(); + const tempDir = join(__dirname, '../../node_modules/.temp/', tempDirName); + await ensureDir(tempDir); + log('create temp dir successfully', tempDir); + return tempDir; +} + +/** + * 分离物料组件名称和版本号 + * + * @private + * @param {string} pkgNameWithVersion + * @returns {{ [key: string]: any }} + * @memberof OnlineAccesser + */ +export function getPkgNameAndVersion( + pkgNameWithVersion: string, +): { [key: string]: any } { + const matches = pkgNameWithVersion.match(/(@\d+\.\d+\.\d+)$/); + if (!matches) { + throw new OtterError(`Illegal semver version: ${pkgNameWithVersion}`); + } + const semverObj = semver.coerce(matches[0]); + const name = pkgNameWithVersion.replace(matches[0], ''); + return { + version: semverObj && semverObj.version, + name, + }; +} + +// 将问题转化为本地物料化场景 +export default async function localize( + options: IMaterializeOptions, +): Promise<{ + cwd: string; + entry: string; +}> { + // 创建临时目录 + const tempDir = await createTempDir(); + // 创建组件包 + const { name, version } = getPkgNameAndVersion(options.entry); + await createFakePackage({ + pkgName: name, + pkgVersion: version, + tempDir, + npmClient: options.npmClient, + }); + + return { + cwd: tempDir, + entry: join(tempDir, 'node_modules', name), + }; +} diff --git a/packages/material-parser/src/otter-core/schema/types.ts b/packages/material-parser/src/otter-core/schema/types.ts index 5fe064355..04b9cb533 100644 --- a/packages/material-parser/src/otter-core/schema/types.ts +++ b/packages/material-parser/src/otter-core/schema/types.ts @@ -8,10 +8,25 @@ /** * json schema for low code component protocol */ -export type IComponentMaterial = BasicSection & PropsSection & ConfigureSection; +export type ComponentMeta = BasicSection & PropsSection & ConfigureSection; export type PropType = BasicType | RequiredType | ComplexType; -export type BasicType = "array" | "bool" | "func" | "number" | "object" | "string" | "node" | "element" | "any"; -export type ComplexType = OneOf | OneOfType | ArrayOf | ObjectOf | Shape | Exact; +export type BasicType = + | 'array' + | 'bool' + | 'func' + | 'number' + | 'object' + | 'string' + | 'node' + | 'element' + | 'any'; +export type ComplexType = + | OneOf + | OneOfType + | ArrayOf + | ObjectOf + | Shape + | Exact; export type ConfigureProp = { title?: string; extraProps?: { @@ -28,7 +43,7 @@ export interface BasicSection { screenshot?: string; icon?: string; tags?: string[]; - devMode?: "proCode" | "lowCode"; + devMode?: 'proCode' | 'lowCode'; npm: Npm; [k: string]: any; } @@ -56,31 +71,31 @@ export interface RequiredType { isRequired?: boolean; } export interface OneOf { - type: "oneOf"; + type: 'oneOf'; value: (string | number | boolean)[]; isRequired?: boolean; [k: string]: any; } export interface OneOfType { - type: "oneOfType"; + type: 'oneOfType'; value: PropType[]; isRequired?: boolean; [k: string]: any; } export interface ArrayOf { - type: "arrayOf"; + type: 'arrayOf'; value: PropType; isRequired?: boolean; [k: string]: any; } export interface ObjectOf { - type: "objectOf"; + type: 'objectOf'; value: PropType; isRequired?: boolean; [k: string]: any; } export interface Shape { - type: "shape"; + type: 'shape'; value: { name?: string; propType?: PropType; @@ -89,7 +104,7 @@ export interface Shape { [k: string]: any; } export interface Exact { - type: "exact"; + type: 'exact'; value: { name?: string; propType?: PropType; @@ -112,38 +127,38 @@ export interface ConfigureSection { [k: string]: any; } export interface ConfigureFieldProp { - type: "field"; + type: 'field'; name?: string; setter?: ConfigureFieldSetter; [k: string]: any; } export interface ConfigureFieldSetter { componentName: - | "List" - | "Object" - | "Function" - | "Node" - | "Mixin" - | "Expression" - | "Switch" - | "Number" - | "Input" - | "TextArea" - | "Date" - | "DateYear" - | "DateMonth" - | "DateRange" - | "ColorPicker" - | "CodeEditor" - | "Select" - | "RadioGroup"; + | 'List' + | 'Object' + | 'Function' + | 'Node' + | 'Mixin' + | 'Expression' + | 'Switch' + | 'Number' + | 'Input' + | 'TextArea' + | 'Date' + | 'DateYear' + | 'DateMonth' + | 'DateRange' + | 'ColorPicker' + | 'CodeEditor' + | 'Select' + | 'RadioGroup'; props?: { [k: string]: any; }; [k: string]: any; } export interface ConfigureGroupProp { - type: "group"; + type: 'group'; items: ConfigureProp[]; [k: string]: any; } diff --git a/packages/material-parser/src/parse/handlers/defaultPropsHandler.ts b/packages/material-parser/src/parse/handlers/defaultPropsHandler.ts new file mode 100644 index 000000000..74782c162 --- /dev/null +++ b/packages/material-parser/src/parse/handlers/defaultPropsHandler.ts @@ -0,0 +1,150 @@ +const { namedTypes: t, NodePath } = require('ast-types'); +type NodePathType = typeof NodePath; +const { + getPropertyName, + isReactComponentClass, + getMemberValuePath, + isReactForwardRefCall, + printValue, + resolveExportDeclaration, + resolveToValue, +} = require('react-docgen').utils; +const resolveFunctionDefinitionToReturnValue = require('react-docgen/dist/utils/resolveFunctionDefinitionToReturnValue'); + +function getDefaultValue(path: NodePathType) { + let node = path.node; + let defaultValue; + if (t.Literal.check(node)) { + defaultValue = node.raw; + } else { + if (t.AssignmentPattern.check(path.node)) { + path = resolveToValue(path.get('right')); + } else { + path = resolveToValue(path); + } + if (t.ImportDeclaration.check(path.node)) { + defaultValue = node.name; + } else { + node = path.node; + try { + defaultValue = printValue(path); + } catch (e) {} + } + } + if (typeof defaultValue !== 'undefined') { + return { + value: defaultValue, + computed: + t.CallExpression.check(node) || + t.MemberExpression.check(node) || + t.Identifier.check(node), + }; + } + + return null; +} + +function getStatelessPropsPath(componentDefinition: any) { + const value = resolveToValue(componentDefinition); + if (isReactForwardRefCall(value)) { + const inner = resolveToValue(value.get('arguments', 0)); + return inner.get('params', 0); + } + return value.get('params', 0); +} + +function getDefaultPropsPath(componentDefinition: any) { + let defaultPropsPath = getMemberValuePath( + componentDefinition, + 'defaultProps', + ); + if (!defaultPropsPath) { + return null; + } + + defaultPropsPath = resolveToValue(defaultPropsPath); + if (!defaultPropsPath) { + return null; + } + + if (t.FunctionExpression.check(defaultPropsPath.node)) { + // Find the value that is returned from the function and process it if it is + // an object literal. + const returnValue = resolveFunctionDefinitionToReturnValue( + defaultPropsPath, + ); + if (returnValue && t.ObjectExpression.check(returnValue.node)) { + defaultPropsPath = returnValue; + } + } + return defaultPropsPath; +} + +function getDefaultValuesFromProps( + properties: any[], + documentation: any, + isStateless: boolean, +) { + properties + // Don't evaluate property if component is functional and the node is not an AssignmentPattern + .filter( + propertyPath => + !isStateless || + t.AssignmentPattern.check(propertyPath.get('value').node), + ) + .forEach(propertyPath => { + if (t.Property.check(propertyPath.node)) { + const propName = getPropertyName(propertyPath); + if (!propName) return; + + const propDescriptor = documentation.getPropDescriptor(propName); + const defaultValue = getDefaultValue( + isStateless + ? propertyPath.get('value', 'right') + : propertyPath.get('value'), + ); + if (defaultValue) { + propDescriptor.defaultValue = defaultValue; + } + } else if (t.SpreadElement.check(propertyPath.node)) { + const resolvedValuePath = resolveToValue(propertyPath.get('argument')); + if (t.ObjectExpression.check(resolvedValuePath.node)) { + getDefaultValuesFromProps( + resolvedValuePath.get('properties'), + documentation, + isStateless, + ); + } + } + }); +} + +export default function defaultPropsHandler( + documentation: any, + componentDefinition: any, +) { + let statelessProps = null; + const defaultPropsPath = getDefaultPropsPath(componentDefinition); + /** + * function, lazy, memo, forwardRef etc components can resolve default props as well + */ + if (!isReactComponentClass(componentDefinition)) { + statelessProps = getStatelessPropsPath(componentDefinition); + } + + // Do both statelessProps and defaultProps if both are available so defaultProps can override + if (statelessProps && t.ObjectPattern.check(statelessProps.node)) { + getDefaultValuesFromProps( + statelessProps.get('properties'), + documentation, + true, + ); + } + if (defaultPropsPath && t.ObjectExpression.check(defaultPropsPath.node)) { + getDefaultValuesFromProps( + defaultPropsPath.get('properties'), + documentation, + false, + ); + } +} diff --git a/packages/material-parser/src/parser/handlers/index.ts b/packages/material-parser/src/parse/handlers/index.ts similarity index 86% rename from packages/material-parser/src/parser/handlers/index.ts rename to packages/material-parser/src/parse/handlers/index.ts index a4ff85a6c..d7fae8bdd 100644 --- a/packages/material-parser/src/parser/handlers/index.ts +++ b/packages/material-parser/src/parse/handlers/index.ts @@ -1,9 +1,11 @@ -const { handlers } = require('react-docgen'); import { propTypeHandler, contextTypeHandler, childContextTypeHandler, } from './propTypeHandler'; +import defaultPropsHandler from './defaultPropsHandler'; + +const { handlers } = require('react-docgen'); const defaultHandlers = [ propTypeHandler, @@ -12,7 +14,7 @@ const defaultHandlers = [ handlers.propTypeCompositionHandler, handlers.propDocBlockHandler, handlers.flowTypeHandler, - handlers.defaultPropsHandler, + defaultPropsHandler, handlers.componentDocblockHandler, handlers.displayNameHandler, handlers.componentMethodsHandler, diff --git a/packages/material-parser/src/parser/handlers/propTypeHandler.ts b/packages/material-parser/src/parse/handlers/propTypeHandler.ts similarity index 96% rename from packages/material-parser/src/parser/handlers/propTypeHandler.ts rename to packages/material-parser/src/parse/handlers/propTypeHandler.ts index 619a88eb4..74fb883b2 100644 --- a/packages/material-parser/src/parser/handlers/propTypeHandler.ts +++ b/packages/material-parser/src/parse/handlers/propTypeHandler.ts @@ -8,7 +8,7 @@ */ import { namedTypes as t, visit } from 'ast-types'; -import { throwStatement } from '@babel/types'; + const { resolveToValue, getPropType, @@ -29,7 +29,6 @@ function getRoot(node: any) { } return root; } -// import type Documentation from '../Documentation'; function isPropTypesExpression(path: any) { const moduleName = resolveToModule(path); @@ -81,11 +80,12 @@ function amendPropTypes(getDescriptor: any, path: any) { function getDefinePropertyValuePath(nodePath: any, propName: string) { const program = getRoot(nodePath); - const componentName = nodePath.node.id.name; let resultPath = nodePath; + if (!nodePath.node.id) return; + const componentName = nodePath.node.id.name; visit(program, { - visitCallExpression: function(path) { + visitCallExpression(path) { const args = path.get('arguments'); const argsNodeList = args.value; if ( diff --git a/packages/material-parser/src/parse/index.ts b/packages/material-parser/src/parse/index.ts new file mode 100644 index 000000000..ccfe3212e --- /dev/null +++ b/packages/material-parser/src/parse/index.ts @@ -0,0 +1,39 @@ +const reactDocs = require('react-docgen'); +import { transformItem } from './transform'; +import { debug } from '../otter-core'; +import { IMaterialParsedModel, IMaterialScanModel } from '../types'; +import resolver from './resolver'; +import handlers from './handlers'; + +export default function parse(params: { + fileContent: string; + filePath: string; +}): Promise { + const { fileContent, filePath } = params; + const result = reactDocs.parse( + fileContent, + (ast: any) => { + ast.__path = filePath; + return resolver(ast); + }, + handlers, + ); + const coms = result.reduce((res: any[], info: any) => { + if (!info || !info.props) return res; + const props = Object.keys(info.props).reduce((acc: any[], name) => { + try { + const item: any = transformItem(name, info.props[name]); + acc.push(item); + } catch (e) { + } finally { + return acc; + } + }, []); + res.push({ + componentName: info.displayName, + props, + }); + return res; + }, []); + return coms; +} diff --git a/packages/material-parser/src/parser/resolver/checkIsIIFE.ts b/packages/material-parser/src/parse/resolver/checkIsIIFE.ts similarity index 100% rename from packages/material-parser/src/parser/resolver/checkIsIIFE.ts rename to packages/material-parser/src/parse/resolver/checkIsIIFE.ts diff --git a/packages/material-parser/src/parser/resolver/index.ts b/packages/material-parser/src/parse/resolver/index.ts similarity index 73% rename from packages/material-parser/src/parser/resolver/index.ts rename to packages/material-parser/src/parse/resolver/index.ts index b16a99fd4..f0d67adbb 100644 --- a/packages/material-parser/src/parser/resolver/index.ts +++ b/packages/material-parser/src/parse/resolver/index.ts @@ -7,6 +7,12 @@ */ import { namedTypes as t, visit } from 'ast-types'; +import checkIsIIFE from './checkIsIIFE'; +import resolveHOC from './resolveHOC'; +import resolveIIFE from './resolveIIFE'; +import resolveImport from './resolveImport'; +import resolveTranspiledClass from './resolveTranspiledClass'; + const { isExportsOrModuleAssignment, isReactComponentClass, @@ -17,13 +23,6 @@ const { resolveExportDeclaration, resolveToValue, } = require('react-docgen').utils; -import checkIsIIFE from './checkIsIIFE'; -import resolveHOC from './resolveHOC'; -import resolveIIFE from './resolveIIFE'; -import resolveTranspiledClass from './resolveTranspiledClass'; - -const ERROR_MULTIPLE_DEFINITIONS = - 'Multiple exported component definitions found.'; function ignore() { return false; @@ -57,7 +56,7 @@ function resolveDefinition(definition: any) { return null; } -function getDefinition(definition: any) { +function getDefinition(definition: any): any { if (checkIsIIFE(definition)) { definition = resolveToValue(resolveIIFE(definition)); if (!isComponentDefinition(definition)) { @@ -70,14 +69,17 @@ function getDefinition(definition: any) { if (!isComponentDefinition(definition)) { definition = resolveTranspiledClass(definition); } + } else if (t.SequenceExpression.check(definition.node)) { + return getDefinition( + resolveToValue(definition.get('expressions').get(0)), + ); + } else { + definition = resolveImport( + definition, + findAllExportedComponentDefinition, + ); } } - // definition = resolveToValue(resolveIIFE(definition)); - // if (!isComponentDefinition(definition)) { - // definition = resolveTranspiledClass(definition); - // } - // definition = resolveToValue(resolveHOC(definition)); - return definition; } /** @@ -95,33 +97,37 @@ function getDefinition(definition: any) { * export default Definition; * export var Definition = ...; */ -export default function findExportedComponentDefinition(ast: any) { - let foundDefinition: any; +export default function findAllExportedComponentDefinition(ast: any) { + const components: any[] = []; function exportDeclaration(path: any) { - const definitions = resolveExportDeclaration(path).reduce( - (acc: any, definition: any) => { + const definitions = resolveExportDeclaration(path) + .reduce((acc: any[], definition: any) => { if (isComponentDefinition(definition)) { acc.push(definition); } else { definition = getDefinition(definition); - if (isComponentDefinition(definition)) { - acc.push(definition); + if (!Array.isArray(definition)) { + definition = [definition]; } + definition.forEach((def: any) => { + if (isComponentDefinition(def)) { + acc.push(def); + } + }); } return acc; - }, - [], - ); + }, []) + .map((definition: any) => resolveDefinition(definition)); if (definitions.length === 0) { return false; } - if (definitions.length > 1 || foundDefinition) { - // If a file exports multiple components, ... complain! - throw new Error(ERROR_MULTIPLE_DEFINITIONS); - } - foundDefinition = resolveDefinition(definitions[0]); + definitions.forEach((definition: any) => { + if (definition && components.indexOf(definition) === -1) { + components.push(definition); + } + }); return false; } @@ -142,6 +148,12 @@ export default function findExportedComponentDefinition(ast: any) { visitExportNamedDeclaration: exportDeclaration, visitExportDefaultDeclaration: exportDeclaration, + visitExportAllDeclaration: function(path) { + components.push( + ...resolveImport(path, findAllExportedComponentDefinition), + ); + return false; + }, visitAssignmentExpression(path: any) { // Ignore anything that is not `exports.X = ...;` or @@ -155,14 +167,14 @@ export default function findExportedComponentDefinition(ast: any) { if (!isComponentDefinition(path)) { path = getDefinition(path); } - if (foundDefinition) { - // If a file exports multiple components, ... complain! - throw new Error(ERROR_MULTIPLE_DEFINITIONS); + + const definition = resolveDefinition(path); + if (definition && components.indexOf(definition) === -1) { + components.push(definition); } - foundDefinition = resolveDefinition(path); return false; }, }); - return foundDefinition; + return components; } diff --git a/packages/material-parser/src/parser/resolver/resolveHOC.ts b/packages/material-parser/src/parse/resolver/resolveHOC.ts similarity index 99% rename from packages/material-parser/src/parser/resolver/resolveHOC.ts rename to packages/material-parser/src/parse/resolver/resolveHOC.ts index a5538a91f..426dc1e84 100644 --- a/packages/material-parser/src/parser/resolver/resolveHOC.ts +++ b/packages/material-parser/src/parse/resolver/resolveHOC.ts @@ -6,6 +6,7 @@ */ import { namedTypes as t, visit } from 'ast-types'; + const { isReactCreateClassCall, isReactForwardRefCall, diff --git a/packages/material-parser/src/parser/resolver/resolveIIFE.ts b/packages/material-parser/src/parse/resolver/resolveIIFE.ts similarity index 62% rename from packages/material-parser/src/parser/resolver/resolveIIFE.ts rename to packages/material-parser/src/parse/resolver/resolveIIFE.ts index 011328600..371cde5fb 100644 --- a/packages/material-parser/src/parser/resolver/resolveIIFE.ts +++ b/packages/material-parser/src/parse/resolver/resolveIIFE.ts @@ -1,20 +1,7 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - */ +import checkIsIIFE from './checkIsIIFE'; -// const { namedTypes: t, visit } = require("ast-types"); const resolveFunctionDefinitionToReturnValue = require('react-docgen/dist/utils/resolveFunctionDefinitionToReturnValue') .default; -// isReactCreateClassCall, -// isReactForwardRefCall, -// resolveToValue, -// resolveHOC - -import checkIsIIFE from './checkIsIIFE'; /** * If the path is a call expression, it recursively resolves to the * rightmost argument, stopping if it finds a React.createClass call expression diff --git a/packages/material-parser/src/parse/resolver/resolveImport.ts b/packages/material-parser/src/parse/resolver/resolveImport.ts new file mode 100644 index 000000000..86c87f279 --- /dev/null +++ b/packages/material-parser/src/parse/resolver/resolveImport.ts @@ -0,0 +1,60 @@ +import { namedTypes as t } from 'ast-types'; +import fs from 'fs'; +import p from 'path'; + +function getRoot(node: any) { + let root = node.parent; + while (root.parent) { + root = root.parent; + } + return root.node; +} + +function isImportLike(node: any) { + return ( + t.ImportDeclaration.check(node) || + t.ExportAllDeclaration.check(node) || + t.ExportNamedDeclaration.check(node) + ); +} + +function getPath(path: any, name: any) { + const root = getRoot(path); + if (!root) return; + let { __path } = root; + __path = p.dirname(__path); + // is directory + if (fs.existsSync(p.resolve(__path, name))) { + name = name + '/index'; + } + const suffix = suffixes.find(suf => { + return fs.existsSync(p.resolve(__path, name + suf)); + }); + if (!suffix) return; + return p.resolve(__path, name + suffix); +} + +const buildParser = require('react-docgen/dist/babelParser').default; +const parser = buildParser(); +const suffixes = ['.js', '.jsx', '.ts', '.tsx']; + +export default function resolveImport(path: any, callback: any) { + let name; + if (path.name === 'local') { + name = path.parentPath.parentPath.parentPath.node.source.value; + } else if (!isImportLike(path.node)) { + return path; + } else { + name = path.node.source.value; + } + if (name) { + const __path = getPath(path, name); + if (!__path) return path; + const fileContent = fs.readFileSync(__path, 'utf8'); + const ast = parser.parse(fileContent); + ast.__src = fileContent; + ast.__path = __path; + return callback(ast); + } + return path; +} diff --git a/packages/material-parser/src/parser/resolver/resolveTranspiledClass.ts b/packages/material-parser/src/parse/resolver/resolveTranspiledClass.ts similarity index 80% rename from packages/material-parser/src/parser/resolver/resolveTranspiledClass.ts rename to packages/material-parser/src/parse/resolver/resolveTranspiledClass.ts index c4bfc6e72..0357966ab 100644 --- a/packages/material-parser/src/parser/resolver/resolveTranspiledClass.ts +++ b/packages/material-parser/src/parse/resolver/resolveTranspiledClass.ts @@ -1,11 +1,3 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - */ - import { builders, namedTypes as t, NodePath, visit } from 'ast-types'; /** * If the path is a call expression, it recursively resolves to the @@ -19,7 +11,7 @@ export default function resolveTranspiledClass(path: any) { visitFunctionDeclaration(arg) { classPath = new NodePath( builders.functionDeclaration( - arg.node.id, + arg.node.id || 'Default', [], builders.blockStatement([ builders.returnStatement( diff --git a/packages/material-parser/src/parse/transform.ts b/packages/material-parser/src/parse/transform.ts new file mode 100644 index 000000000..e2fe3f1cb --- /dev/null +++ b/packages/material-parser/src/parse/transform.ts @@ -0,0 +1,138 @@ +export function transformType(type: any) { + if (typeof type === 'string') return type; + const { name, elements, value = elements, computed, required } = type; + if (!value && !required) { + return name; + } + if (computed !== undefined && value) { + return eval(value); + } + const result: any = { + type: name, + }; + if (required) { + result.isRequired = required; + } + switch (name) { + case 'number': + case 'string': + case 'bool': + case 'any': + case 'func': + case 'symbol': + case 'object': + break; + case 'literal': + return eval(value); + case 'enum': + case 'tuple': + result.type = 'oneOf'; + result.value = value.map(transformType); + break; + case 'union': + result.type = 'oneOfType'; + result.value = value.map(transformType); + break; + case 'boolean': + result.type = 'bool'; + break; + case 'Array': { + result.type = 'arrayOf'; + const v = transformType(value[0]); + if (typeof v.type === 'string') result.value = v.type; + break; + } + case 'signature': { + result.type = 'shape'; + const { + signature: { properties }, + } = type; + if (properties.length === 0) { + result.type = 'object'; + } else if ( + properties.length === 1 && + typeof properties[0].key === 'object' + ) { + result.type = 'objectOf'; + const v = transformType(properties[0].value); + if (typeof v.type === 'string') result.value = v.type; + } else { + result.value = properties + .filter((item: any) => typeof item.key !== 'object') + .map((prop: any) => { + const { + key, + value: { name, ...others }, + } = prop; + return transformItem(key, { + ...others, + type: { + name, + }, + }); + }); + } + break; + } + case 'objectOf': + case 'arrayOf': + case 'instanceOf': + result.value = transformType(value); + break; + case 'exact': + case 'shape': + result.value = Object.keys(value).map(n => { + // tslint:disable-next-line:variable-name + const { name: _name, ...others } = value[n]; + return transformItem(n, { + ...others, + type: { + name: _name, + }, + }); + }); + break; + case (name.match('ReactNode$') || {}).input: + result.type = 'node'; + break; + case (name.match('Element$') || {}).input: + result.type = 'element'; + break; + case (name.match('ElementType$') || {}).input: + result.type = 'elementType'; + break; + default: + result.type = 'instanceOf'; + result.value = name; + break; + } + return result; +} + +export function transformItem(name: string, item: any) { + const { + description, + flowType, + type = flowType, + required, + defaultValue, + } = item; + const result: any = { + name, + propType: transformType({ + ...type, + required: !!required, + }), + }; + if (description) { + result.description = description; + } + if (defaultValue) { + try { + const value = eval(defaultValue.value); + result.defaultValue = value; + } catch (e) {} + } + + return result; +} diff --git a/packages/material-parser/src/parser/BaseParser.ts b/packages/material-parser/src/parser/BaseParser.ts deleted file mode 100644 index baf292875..000000000 --- a/packages/material-parser/src/parser/BaseParser.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { OtterError } from '../otter-core'; -import { - EcologyType, - IMaterializeOptions, - IMaterialParsedModel, - IMaterialScanModel, - IParser, - SourceType, -} from '../types'; - -/** - * 解析器基类 - * @abstract - * @class BaseParser - * @implements {IParser} - */ -abstract class BaseParser implements IParser { - /** - * 识别语法生态,判断是 react、vue、rax - * @static - * @param {IMaterializeOptions} options - * @returns {Promise} - * @memberof BaseParser - */ - public static recognizeEcology( - options: IMaterializeOptions, - ): Promise { - // TODO 识别物料组件生态 - return Promise.resolve(EcologyType.REACT); - } - - private options: IMaterializeOptions; - - constructor(options: IMaterializeOptions) { - this.options = options; - } - - public async parse( - model: IMaterialScanModel, - ): Promise { - const results: IMaterialParsedModel[] = []; - switch (model.sourceType) { - case SourceType.MODULE: { - for (const item of model.modules) { - const parsedModel: IMaterialParsedModel = await this.parseES6({ - model, - filePath: item.filePath, - fileContent: item.fileContent, - }); - results.push(parsedModel); - } - break; - } - case SourceType.MAIN: { - this.parseES5(model); - break; - } - default: { - throw new OtterError(`Unsupported SourceType [${model.sourceType}]`); - } - } - return results; - } - - public abstract parseES5( - model: IMaterialScanModel, - ): Promise; - - public abstract parseES6(params: { - model: IMaterialScanModel; - filePath: string; - fileContent: string; - }): Promise; -} - -export default BaseParser; diff --git a/packages/material-parser/src/parser/ReactParser.ts b/packages/material-parser/src/parser/ReactParser.ts deleted file mode 100644 index 5ececea15..000000000 --- a/packages/material-parser/src/parser/ReactParser.ts +++ /dev/null @@ -1,704 +0,0 @@ -import { CodeGenerator } from '@babel/generator'; -// import { parse } from '@babel/parser'; -const buildParser = require('react-docgen/dist/babelParser').default; -const reactDocs = require('react-docgen'); -import traverse from '@babel/traverse'; -import * as t from '@babel/types'; -const { utils: ReactDocUtils } = require('react-docgen'); -import { debug } from '../otter-core'; -import { - IMaterialParsedModel, - IMaterialScanModel, - IPropType, - IPropTypes, - SourceType, -} from '../types'; -import BaseParser from './BaseParser'; -import resolver from './resolver'; -import handlers from './handlers'; - -const log = debug.extend('mat'); -const parser = buildParser(); - -function transformType(type: any): any { - const { name, value, computed, required } = type; - if (!value && !required) { - return name; - } - if (computed !== undefined && value) { - // tslint:disable-next-line:no-eval - return eval(value); - } - const result: any = { - type: name, - }; - if (required) { - result.isRequired = required; - } - if (Array.isArray(value)) { - if (name === 'enum') { - result.type = 'oneOf'; - } else if (name === 'union') { - result.type = 'oneOfType'; - } - result.value = value.map(transformType); - } else if (typeof value === 'object') { - if (name === 'objectOf' || name === 'arrayOf' || name === 'instanceOf') { - result.value = transformType(value); - } else { - result.value = Object.keys(value).map((n: string) => { - // tslint:disable-next-line:variable-name - const { name: _name, ...others } = value[n]; - return transformItem(n, { - ...others, - type: { - name: _name, - }, - }); - }); - } - } else if (value !== undefined) { - result.value = value; - } - return result; -} - -function transformItem(name: string, item: any): any { - const { description, type, required, defaultValue } = item; - const result: any = { - name, - propType: transformType({ - ...type, - required: !!required, - }), - }; - if (description) { - result.description = description; - } - if (defaultValue) { - try { - const value = eval(defaultValue.value); - result.defaultValue = value; - } catch (e) {} - } - - return result; -} -/** - * 解析 react 生态下的组件 - * - * @class ReactParser - * @extends {BaseParser} - */ -class ReactParser extends BaseParser { - /** - * 解析 ExportStatement - * @static - * @returns {Promise} - * @memberof ReactParser - */ - public static async parseExportedStatement( - fileContent: string, - sourceType: string, - ): Promise< - Array<{ - localName: string; - exportedName: string; - source: string; - }> - > { - const ast = parser.parse(fileContent); - - // @ts-ignore - ast.__src = fileContent; - - const specifiers: any = []; - - // 组装 localName 和 exportedName - traverse(ast, { - enter(path) { - if (t.isExportNamedDeclaration(path.node)) { - path.node.specifiers.forEach(spec => { - if (t.isExportSpecifier(spec)) { - const source = (path.node as t.ExportNamedDeclaration).source; - specifiers.push({ - localName: spec.local.name, - exportedName: spec.exported.name, - source: t.isLiteral(source) ? (source as any).value : '', - }); - } - }); - } - }, - }); - // 组装 source - traverse(ast, { - enter(path) { - if (t.isImportDeclaration(path.node)) { - const source = path.node.source; - path.node.specifiers.forEach(spec => { - if (t.isImportDefaultSpecifier(spec)) { - const target = specifiers.find( - (inner: any) => inner.localName === spec.local.name, - ); - if (target) { - target.source = source.value; - } - } - }); - } - }, - }); - debug('specifiers', specifiers); - return specifiers; - } - public static parseProperties(objectPath: any): IPropTypes { - const results: IPropTypes = objectPath - .get('properties') - .map((p: any) => - transformItem( - p.get('key').node.name, - ReactDocUtils.getPropType(p.get('value')), - ), - ); - - return results; - } - - public async parseES5( - model: IMaterialScanModel, - ): Promise { - const parsedModel: IMaterialParsedModel = { - filePath: '', - defaultExportName: '', - componentNames: [], - importModules: [], - exportModules: [], - subModules: [], - propsTypes: [], - propsDefaults: [], - }; - - const mainEntryItem: any = model.modules.find( - item => item.filePath === model.mainEntry, - ); - - const result = reactDocs.parse( - mainEntryItem.fileContent, - resolver, - handlers, - ); - const props = Object.keys(result.props || {}).map(name => { - return transformItem(name, result.props[name]); - }); - - return { - filePath: mainEntryItem.filePath, - // defaultExportName, - // subModules, - // propsTypes, - props, - } as any; - - // log('mainEntryItem', mainEntryItem); - // const ast = parser.parse(mainEntryItem.file); - - // @ts-ignore - // ast.__src = mainEntryItem.file; - - // // 获取 defaultExportName - // traverse(ast, { - // enter(path) { - // if (t.isExpressionStatement(path.node)) { - // if ( - // t.isAssignmentExpression(path.node.expression) && - // t.isMemberExpression(path.node.expression.left) && - // t.isIdentifier(path.node.expression.left.object) && - // t.isIdentifier(path.node.expression.right) && - // path.node.expression.left.object.name === 'exports' && - // (path.node.expression.left.property.name === 'default' || - // path.node.expression.left.property.value === 'default') - // ) { - // // 支持 export default Demo 写法 - // const tempVarName = path.node.expression.right.name; - // let defaultExportName = ''; - // traverse(ast, { - // enter(innerPath) { - // if ( - // t.isVariableDeclaration(innerPath.node) && - // Array.isArray(innerPath.node.declarations) && - // innerPath.node.declarations.length && - // t.isVariableDeclarator(innerPath.node.declarations[0]) && - // t.isIdentifier(innerPath.node.declarations[0].id) && - // innerPath.node.declarations[0].id.name === tempVarName && - // t.isIdentifier(innerPath.node.declarations[0].init) - // ) { - // defaultExportName = innerPath.node.declarations[0].init.name; - // } - // }, - // }); - // parsedModel.defaultExportName = defaultExportName; - // log('isIdentifier defaultExportName', defaultExportName); - // } - // } - // }, - // }); - - // traverse(ast, { - // enter(path) { - // // 获取 componentNames - // if (t.isVariableDeclaration(path.node)) { - // if ( - // t.isVariableDeclarator(path.node.declarations) && - // t.isIdentifier(path.node.declarations.init) && - // t.isIdentifier(path.node.declarations.id) - // ) { - // const exportedName = path.node.declarations.init.name; - // const localName = path.node.declarations.id.name; - // log('isIdentifier componentNames', exportedName); - // parsedModel.componentNames.push({ - // exportedName, - // localName, - // }); - // } - // } - // // 获取 exportModules - // if (t.isExpressionStatement(path.node)) { - // // 对应 export function DemoFunc() {} 或 export { DemoFunc } 写法 - // if ( - // t.isAssignmentExpression(path.node.expression) && - // t.isMemberExpression(path.node.expression.left) && - // t.isIdentifier(path.node.expression.left.object) && - // t.isIdentifier(path.node.expression.left.property) && - // t.isIdentifier(path.node.expression.right) && - // path.node.expression.left.object.name === 'exports' - // ) { - // const exportedName = path.node.expression.left.property.name; - // const localName = path.node.expression.right.name; - // parsedModel.exportModules.push({ - // exportedName: - // exportedName === 'default' - // ? parsedModel.defaultExportName - // : exportedName, - // localName: - // exportedName === 'default' - // ? parsedModel.defaultExportName - // : localName, - // }); - // } - // // 支持 export { default as DemoFunc } from './DemoFunc' 写法 - // if ( - // t.isCallExpression(path.node.expression) && - // t.isMemberExpression(path.node.expression.callee) && - // t.isIdentifier(path.node.expression.callee.object) && - // t.isIdentifier(path.node.expression.callee.property) && - // path.node.expression.callee.object.name === 'Object' && - // path.node.expression.callee.property.name === 'defineProperty' && - // Array.isArray(path.node.expression.arguments) && - // t.isIdentifier(path.node.expression.arguments[0]) && - // (path.node.expression.arguments[0] as t.Identifier).name === - // 'exports' && - // t.isLiteral(path.node.expression.arguments[1]) - // ) { - // // 对应 export function DemoFunc() {} 或 export { DemoFunc } 写法 - // const args = path.node.expression.arguments as any; - // const funcName = args[1].value; - // if (funcName !== '__esModule') { - // parsedModel.exportModules.push({ - // exportedName: funcName, - // localName: funcName, - // }); - // } - // } - // } - // // 获取 importModules - // if ( - // t.isVariableDeclaration(path.node) && - // Array.isArray(path.node.declarations) && - // path.node.declarations.length - // ) { - // path.node.declarations.forEach(dec => { - // // 支持 import Demo from './demo' 写法 - // if ( - // t.isVariableDeclarator(dec) && - // t.isIdentifier(dec.id) && - // t.isCallExpression(dec.init) && - // t.isIdentifier(dec.init.callee) && - // ['_interopRequireWildcard', '_interopRequireDefault'].includes( - // dec.init.callee.name, - // ) && - // // dec.init.callee.name === '_interopRequireWildcard' && - // Array.isArray(dec.init.arguments) && - // t.isCallExpression(dec.init.arguments[0]) && - // t.isIdentifier( - // (dec.init.arguments[0] as t.CallExpression).callee, - // ) && - // ((dec.init.arguments[0] as t.CallExpression) - // .callee as t.Identifier).name === 'require' - // ) { - // const localName = dec.id.name; - // const args = (dec.init.arguments[0] as t.CallExpression) - // .arguments as any; - // const source = args[0].value; - // parsedModel.importModules.push({ - // importDefaultName: localName, - // localName, - // source, - // }); - // } - - // // 支持 import { Demo as Demo2 } from './demo' 写法 - // if ( - // t.isVariableDeclarator(dec) && - // t.isIdentifier(dec.id) && - // t.isCallExpression(dec.init) && - // t.isIdentifier(dec.init.callee) && - // dec.init.callee.name === 'require' && - // Array.isArray(dec.init.arguments) && - // t.isLiteral(dec.init.arguments[0]) - // ) { - // const args = dec.init.arguments as any; - // const source = args[0].value; - // const importName = dec.id.name; - // const localName = dec.id.name; - // // 遍历查找出 importName 和 localName - // // ES5 本身并不支持按需加载,故 import 都是全量导入 - // // 但如果使用了诸如:babel-plugin-import 等插件,会自动更改编译之后的 ES5 代码 - // parsedModel.importModules.push({ - // importName, - // localName, - // source, - // }); - // } - // }); - // } - - // // 获取 subModules - // if ( - // t.isExpressionStatement(path.node) && - // t.isAssignmentExpression(path.node.expression) && - // t.isMemberExpression(path.node.expression.left) - // ) { - // if ( - // t.isIdentifier(path.node.expression.left.object) && - // path.node.expression.left.object.name === - // parsedModel.defaultExportName - // ) { - // // 支持 SFC.SubDemo1 = SubDemo1; 写法 - // if (t.isIdentifier(path.node.expression.right)) { - // parsedModel.subModules.push({ - // objectName: [path.node.expression.left.object.name], - // propertyName: path.node.expression.left.property.name, - // isValueAnonymousFunc: false, - // value: path.node.expression.right.name, - // }); - // } - - // // 支持 SFC.SubDemo2 = function() {}; 写法 - // if (t.isFunctionExpression(path.node.expression.right)) { - // const rightID = path.node.expression.right.id as any; - // parsedModel.subModules.push({ - // objectName: [path.node.expression.left.object.name], - // propertyName: path.node.expression.left.property.name, - // isValueAnonymousFunc: !rightID, - // value: rightID ? rightID.name : undefined, - // }); - // } - // } - - // if (t.isMemberExpression(path.node.expression.left.object)) { - // if (t.isIdentifier(path.node.expression.right)) { - // // 支持 DemoFunc4.Test.Obj2 = Obj3; 写法 - // const tempLeftObject = path.node.expression.left.object as any; - // parsedModel.subModules.push({ - // objectName: [ - // tempLeftObject.object.name, - // tempLeftObject.property.name, - // ], - // propertyName: path.node.expression.left.property.name, - // isValueAnonymousFunc: false, - // value: path.node.expression.right.name, - // }); - // } - // if (t.isFunctionExpression(path.node.expression.right)) { - // // 支持 DemoFunc4.Test.Obj2 = function() {}; 写法 - // const rightID = path.node.expression.right.id as any; - // const tempLeftObject = path.node.expression.left.object as any; - // parsedModel.subModules.push({ - // objectName: [ - // tempLeftObject.object.name, - // tempLeftObject.property.name, - // ], - // propertyName: path.node.expression.left.property.name, - // isValueAnonymousFunc: !rightID, - // value: rightID ? rightID.name : undefined, - // }); - // } - // } - // } - - // // 获取 propsTypes 和 defaultProps - // if ( - // t.isExpressionStatement(path.node) && - // t.isAssignmentExpression(path.node.expression) && - // t.isMemberExpression(path.node.expression.left) && - // t.isObjectExpression(path.node.expression.right) && - // t.isIdentifier(path.node.expression.left.object) && - // t.isIdentifier(path.node.expression.left.property) && - // path.node.expression.left.object.name === - // parsedModel.defaultExportName && - // ['propTypes', 'defaultProps'].includes( - // path.node.expression.left.property.name, - // ) - // ) { - // // 处理 propTypes - // if (path.node.expression.left.property.name === 'propTypes') { - // path.node.expression.right.properties.forEach(prop => { - // if (t.isProperty(prop)) { - // if (t.isMemberExpression(prop.value)) { - // if (t.isIdentifier(prop.value.object)) { - // // 支持 optionalArray: PropTypes.array 写法 - // parsedModel.propsTypes.push({ - // name: prop.key.name, - // type: prop.value.property.name, - // required: false, - // }); - // } - // if (t.isMemberExpression(prop.value.object)) { - // // 支持 optionalArray: PropTypes.array.isRequired 写法 - // parsedModel.propsTypes.push({ - // name: prop.key.name, - // type: prop.value.object.property.name, - // required: - // prop.value.object.property.name === 'isRequired', - // }); - // } - // if ( - // t.isCallExpression(prop.value.object) && - // t.isMemberExpression(prop.value.object.callee) - // ) { - // // 支持 optionalArray: PropTypes.shape().isRequired 写法 - // parsedModel.propsTypes.push({ - // name: prop.key.name, - // type: prop.value.object.callee.property.name, - // required: prop.value.property.name === 'isRequired', - // }); - // } - // } - // if ( - // t.isCallExpression(prop.value) && - // t.isMemberExpression(prop.value.callee) - // ) { - // // 支持 optionalArray: PropTypes.shape() 写法 - // parsedModel.propsTypes.push({ - // name: prop.key.name, - // type: prop.value.callee.property.name, - // required: false, - // }); - // } - // } - // }); - // } - // // 处理 defaultProps - // if (path.node.expression.left.property.name === 'defaultProps') { - // path.node.expression.right.properties.forEach(prop => { - // if (t.isProperty(prop)) { - // if (t.isObjectExpression(prop.value)) { - // const defaultValue = new CodeGenerator( - // t.objectExpression(prop.value.properties), - // ).generate().code; - // parsedModel.propsDefaults.push({ - // name: prop.key.name, - // defaultValue, - // }); - // } - // } - // }); - // } - // } - // }, - // }); - - // log('traverse done.'); - // log('parsedModel.defaultExportName', parsedModel.defaultExportName); - // log('parsedModel.componentNames', parsedModel.componentNames); - // log('parsedModel.importModules', parsedModel.importModules); - // log('parsedModel.exportModules', parsedModel.exportModules); - // log('parsedModel.subModules', parsedModel.subModules); - // log('parsedModel.propsTypes', parsedModel.propsTypes); - // log('parsedModel.propsDefaults', parsedModel.propsDefaults); - // log('parsedModel', parsedModel); - // return parsedModel; - } - - public async parseES6(params: { - model: IMaterialScanModel; - filePath: string; - fileContent: string; - }): Promise { - const ast = parser.parse(params.fileContent); - const result = reactDocs.parse(params.fileContent, resolver, handlers); - const props = Object.keys(result.props || {}).map(name => { - return transformItem(name, result.props[name]); - }); - const defaultExportName = await this.parseDefaultExportNameES6(ast); - // const subModules = await this.parseSubModulesES6(ast); - - return { - filePath: params.filePath, - defaultExportName, - // subModules, - props, - } as any; - } - - /** - * 解析 AST 获取 defaultExportName - * 支持的写法: - * - export default Demo - * - export default function Demo() {} - * - export default class Demo {} - * - * @private - * @param {*} ast - * @memberof ReactParser - */ - private async parseDefaultExportNameES6(ast: any): Promise { - let defaultExportName = ''; - traverse(ast, { - enter(path) { - // 获取 defaultExportName - if (t.isExportDefaultDeclaration(path.node)) { - if (t.isIdentifier(path.node.declaration)) { - // 支持 export default Demo 写法 - defaultExportName = path.node.declaration.name; - log('isIdentifier defaultExportName', defaultExportName); - } - if (t.isFunctionDeclaration(path.node.declaration)) { - if (t.isIdentifier(path.node.declaration.id)) { - // 支持 export default function Demo() {} 写法 - defaultExportName = path.node.declaration.id.name; - log('isFunctionDeclaration defaultExportName', defaultExportName); - } - } - if (t.isClassDeclaration(path.node.declaration)) { - if (t.isIdentifier(path.node.declaration.id)) { - // 支持 export default class Demo {} 写法 - defaultExportName = path.node.declaration.id.name; - log('isClassDeclaration defaultExportName', defaultExportName); - } - } - if (t.isCallExpression(path.node.declaration)) { - const traverseCallExp: any = (args: any[]) => { - const arg = args[0]; - if (t.isIdentifier(arg)) { - return arg.name; - } - return traverseCallExp(arg.arguments); - }; - defaultExportName = traverseCallExp( - path.node.declaration.arguments, - ); - } - } - }, - }); - return defaultExportName; - } - - /** - * 解析 AST 获取 subModules - * 支持的写法: - * - DemoFunc4.Test = Test; - * - DemoFunc4.Test = function() {}; - * - DemoFunc4.Test.Obj2 = Obj3; - * - DemoFunc4.Test.Obj2 = function() {}; - * - * @private - * @param {*} ast - * @returns {Promise>} - * @memberof ReactParser - */ - private async parseSubModulesES6( - ast: any, - ): Promise< - Array<{ - objectName: string[]; - propertyName: string; - value?: string; - isValueAnonymousFunc: boolean; - }> - > { - const results: any[] = []; - traverse(ast, { - enter(path) { - if (t.isExpressionStatement(path.node)) { - if (t.isAssignmentExpression(path.node.expression)) { - if (t.isMemberExpression(path.node.expression.left)) { - if (t.isIdentifier(path.node.expression.left.object)) { - if (t.isIdentifier(path.node.expression.right)) { - // 支持 DemoFunc4.Test = Test; 写法 - results.push({ - objectName: [path.node.expression.left.object.name], - propertyName: path.node.expression.left.property.name, - isValueAnonymousFunc: false, - value: path.node.expression.right.name, - }); - } - if (t.isFunctionExpression(path.node.expression.right)) { - // 支持 DemoFunc4.Test = function() {}; 写法 - const rightID = !path.node.expression.right.id as any; - results.push({ - objectName: [path.node.expression.left.object.name], - propertyName: path.node.expression.left.property.name, - isValueAnonymousFunc: !!rightID, - value: rightID ? rightID.name : undefined, - }); - } - } - if (t.isMemberExpression(path.node.expression.left.object)) { - if (t.isIdentifier(path.node.expression.right)) { - // 支持 DemoFunc4.Test.Obj2 = Obj3; 写法 - const tempLeftObject = path.node.expression.left - .object as any; - results.push({ - objectName: [ - tempLeftObject.object.name, - tempLeftObject.property.name, - ], - propertyName: path.node.expression.left.property.name, - isValueAnonymousFunc: false, - value: path.node.expression.right.name, - }); - } - if (t.isFunctionExpression(path.node.expression.right)) { - // 支持 DemoFunc4.Test.Obj2 = function() {}; 写法 - const rightID = !path.node.expression.right.id as any; - const tempLeftObject = path.node.expression.left - .object as any; - results.push({ - objectName: [ - tempLeftObject.object.name, - tempLeftObject.property.name, - ], - propertyName: path.node.expression.left.property.name, - isValueAnonymousFunc: !!rightID, - value: rightID ? rightID.name : undefined, - }); - } - } - } - } - } - }, - }); - return results; - } -} - -export default ReactParser; diff --git a/packages/material-parser/src/scan.ts b/packages/material-parser/src/scan.ts new file mode 100644 index 000000000..45fc361ca --- /dev/null +++ b/packages/material-parser/src/scan.ts @@ -0,0 +1,74 @@ +import { IMaterializeOptions, IMaterialScanModel, SourceType } from './types'; +import { pathExists, readFile } from 'fs-extra'; +import { join } from 'path'; +import { debug } from './otter-core'; +const log = debug.extend('mat'); + +export default async function scan( + options: IMaterializeOptions, +): Promise { + const model: IMaterialScanModel = { + pkgName: '', + pkgVersion: '', + mainEntry: '', + sourceType: SourceType.MODULE, + modules: [], + }; + log('options', options); + // 入口文件路径 + let entryFilePath = null; + const cwd = options.cwd ? options.cwd : ''; + const entry = options.entry; + const isDepsMode = cwd !== entry; + const pkgJsonPath = join(cwd, 'package.json'); + // 判断是否存在 package.json + if (!(await pathExists(pkgJsonPath))) { + throw new Error(`Cannot find package.json. ${pkgJsonPath}`); + } + // 读取 package.json + let pkgJson = await resolvePkgJson(pkgJsonPath); + model.pkgName = pkgJson.name; + model.pkgVersion = pkgJson.version; + if (isDepsMode) { + pkgJson = await resolvePkgJson(join(entry, 'package.json')); + } + if (pkgJson.module) { + // 支持 es module + model.sourceType = SourceType.MODULE; + entryFilePath = pkgJson.module; + } else if (pkgJson.main) { + // 支持 commonjs + model.sourceType = SourceType.MAIN; + entryFilePath = pkgJson.main; + } else { + entryFilePath = './index.js'; + } + entryFilePath = join(isDepsMode ? entry : cwd, entryFilePath); + log('entryFilePath', entryFilePath); + const entryFile = await loadFile(entryFilePath); + log('entryFile', entryFile); + model.mainEntry = entryFilePath; + // 记录入口文件 + model.modules.push({ + filePath: entryFilePath, + fileContent: entryFile, + }); + log('model', model); + return model; +} + +export async function loadFile(filePath: string): Promise { + const content: string | Buffer = await readFile(filePath); + if (typeof content === 'string') { + return content; + } + return content.toString(); +} + +export async function resolvePkgJson( + pkgJsonPath: string, +): Promise<{ [k: string]: any }> { + const content = await loadFile(pkgJsonPath); + const json = JSON.parse(content); + return json; +} diff --git a/packages/material-parser/src/scanner/Scanner.ts b/packages/material-parser/src/scanner/Scanner.ts deleted file mode 100644 index 880678e13..000000000 --- a/packages/material-parser/src/scanner/Scanner.ts +++ /dev/null @@ -1,170 +0,0 @@ -import { pathExists, readFile, statSync } from 'fs-extra'; -import { dirname, join } from 'path'; -import { debug } from '../otter-core'; -import BaseParser from '../parser/BaseParser'; -import ReactParser from '../parser/ReactParser'; -import { - IMaterializeOptions, - IMaterialScanModel, - IScanner, - SourceType, -} from '../types'; - -const log = debug.extend('mat'); - -/** - * 文件扫描器 - * - * @class Scanner - * @implements {IScanner} - */ -class Scanner implements IScanner { - public options: IMaterializeOptions; - - constructor(options: IMaterializeOptions) { - this.options = options; - } - - public async scan(): Promise { - const model: IMaterialScanModel = { - pkgName: '', - pkgVersion: '', - mainEntry: '', - sourceType: SourceType.MODULE, - modules: [], - }; - const options = this.options; - log('options', options); - // 入口文件路径 - let entryFilePath = null; - const cwd = options.cwd ? options.cwd : ''; - const entry = options.entry; - const isDepsMode = cwd !== entry; - const pkgJsonPath = join(cwd, 'package.json'); - // 判断是否存在 package.json - // if (!(await pathExists(pkgJsonPath))) { - // throw new Error(`Cannot find package.json. ${pkgJsonPath}`); - // } - // 读取 package.json - let pkgJson = await this.resolvePkgJson(pkgJsonPath); - model.pkgName = pkgJson.name; - model.pkgVersion = pkgJson.version; - if (isDepsMode) { - pkgJson = await this.resolvePkgJson(join(entry, 'package.json')); - } - if (pkgJson.module) { - // 支持 es module - model.sourceType = SourceType.MODULE; - entryFilePath = pkgJson.module; - } else if (pkgJson.main) { - // 支持 commonjs - model.sourceType = SourceType.MAIN; - entryFilePath = pkgJson.main; - } else { - entryFilePath = './index.js'; - } - entryFilePath = join(isDepsMode ? entry : cwd, entryFilePath); - log('entryFilePath', entryFilePath); - const entryFile = await this.loadFile(entryFilePath); - log('entryFile', entryFile); - model.mainEntry = entryFilePath; - // 记录入口文件 - model.modules.push({ - filePath: entryFilePath, - fileContent: entryFile, - }); - log('model', model); - // debugger; - if (options.isExportedAsMultiple) { - // 解析 entryFile,提取出 export 语句 - const modules = await this.parseEntryFile({ - entryFile, - entryFilePath, - sourceType: model.sourceType, - }); - model.modules = [...modules]; - } - log('model', model); - return model; - } - - /** - * 判断是否为文件夹 - * @param {string} filePath 文件路径 - * @returns {Promise} - * @memberof LocalScanner - */ - public async isDirectory(filePath: string): Promise { - log('materialIn', 'isDirectory - filePath', filePath); - const stats = statSync(filePath); - return stats.isDirectory(); - } - - public async loadFile(filePath: string): Promise { - const content: string | Buffer = await readFile(filePath); - if (typeof content === 'string') { - return content; - } - return content.toString(); - } - - public async resolvePkgJson( - pkgJsonPath: string, - ): Promise<{ [k: string]: any }> { - const content = await this.loadFile(pkgJsonPath); - const json = JSON.parse(content); - return json; - } - - /** - * 解析入口文件,获取要导出的模块内容 - * @private - * @param {{ - * entryFile: string; - * entryFilePath: string; - * sourceType: string; - * }} params - * @returns {Promise} - * @memberof LocalScanner - */ - private async parseEntryFile(params: { - entryFile: string; - entryFilePath: string; - sourceType: string; - }): Promise { - const modules: any = []; - const entryFileDirName = dirname(params.entryFilePath); - const ecology = await BaseParser.recognizeEcology(this.options); - if (ecology === 'react') { - const exportedList = await ReactParser.parseExportedStatement( - params.entryFile, - params.sourceType, - ); - if (Array.isArray(exportedList)) { - for (const item of exportedList) { - if (item.source && item.source.length) { - try { - let filePath = join(entryFileDirName, item.source); - if (await this.isDirectory(filePath)) { - filePath = join(filePath, 'index.js'); - } else { - filePath = join(filePath, '.js'); - } - debug('filePath', filePath); - modules.push({ - filePath, - fileContent: await this.loadFile(filePath), - }); - } catch (e) { - debug('error', 'parseEntryFile', e.message); - } - } - } - } - } - debug('modules', modules); - return modules; - } -} - -export default Scanner; diff --git a/packages/material-parser/src/types/IAccesser.ts b/packages/material-parser/src/types/IAccesser.ts index 45cfd2dd3..3b3506118 100644 --- a/packages/material-parser/src/types/IAccesser.ts +++ b/packages/material-parser/src/types/IAccesser.ts @@ -1,4 +1,4 @@ -import { IComponentMaterial } from '../otter-core'; +import { ComponentMeta } from '../otter-core'; /** * 接入器接口(用于定义物料化组件的接入渠道) @@ -10,7 +10,7 @@ interface IAccesser { * @returns {Promise} * @memberof IAccesser */ - access(): Promise; + access(): Promise; } export default IAccesser; diff --git a/packages/material-parser/src/types/IExtensionConfigManifest.ts b/packages/material-parser/src/types/IExtensionConfigManifest.ts index 5971341f3..40dba966f 100644 --- a/packages/material-parser/src/types/IExtensionConfigManifest.ts +++ b/packages/material-parser/src/types/IExtensionConfigManifest.ts @@ -1,15 +1,15 @@ -import { IComponentMaterial } from '../otter-core'; +import { ComponentMeta } from '../otter-core'; /** * 扩展点:配置 manifest * (物料化场景) */ type IExtensionConfigManifest = (params: { - manifestObj: IComponentMaterial; // manifest 配置对象 + manifestObj: ComponentMeta; // manifest 配置对象 manifestFilePath: string; // manifest 文件默认路径 }) => Promise<{ manifestJSON: string; // manifest 文件内容 manifestFilePath: string; // manifest 文件路径 - manifestObj: IComponentMaterial; // manifest 文件对象 + manifestObj: ComponentMeta; // manifest 文件对象 }>; export default IExtensionConfigManifest; diff --git a/packages/material-parser/src/types/IGenerator.ts b/packages/material-parser/src/types/IGenerator.ts deleted file mode 100644 index bd16d9ead..000000000 --- a/packages/material-parser/src/types/IGenerator.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { IComponentMaterial } from '../otter-core'; -import { IMaterialParsedModel } from './IMaterialParsedModel'; -import IMaterialScanModel from './IMaterialScanModel'; - -/** - * 生成器 - */ -export default interface IGenerator { - /** - * 根据前面两阶段的产物生成最终编排引擎需要的物料 - * @param {IMaterialScanModel} matScanModel 对应扫描阶段产物 - * @param {IMaterialParsedModel[]} matParsedModels 对应解析阶段产物 - * @returns {Promise} - * @memberof IGenerator - */ - generate( - matScanModel: IMaterialScanModel, - matParsedModels: IMaterialParsedModel[], - ): Promise; -} diff --git a/packages/material-parser/src/types/IMaterialParsedModel.ts b/packages/material-parser/src/types/IMaterialParsedModel.ts index e86046674..94cce6f75 100644 --- a/packages/material-parser/src/types/IMaterialParsedModel.ts +++ b/packages/material-parser/src/types/IMaterialParsedModel.ts @@ -12,38 +12,38 @@ export interface IPropType { export type IPropTypes = IPropType[]; export interface IMaterialParsedModel { - filePath: string; - defaultExportName: string; + // filePath: string; + componentName: string; props?: PropsSection['props']; - componentNames: Array<{ - exportedName: string; - localName: string; - source?: string; - }>; - importModules: Array<{ - importDefaultName?: string; - importName?: string; - localName?: string; - source: string; - }>; - exportModules: Array<{ - exportedName: string; - localName: string; - source?: string; - }>; - /** - * 子模块,形如:Demo.SubModule = value; 或者 Demo.SubModule.Sub = subValue; - */ - subModules: Array<{ - objectName: string[]; - propertyName: string; - value?: string; - // value 是否对应匿名函数 - isValueAnonymousFunc: boolean; - }>; - propsTypes: IPropTypes; - propsDefaults: Array<{ - name: string; - defaultValue: any; - }>; + // componentNames: { + // exportedName: string; + // localName: string; + // source?: string; + // }[]; + // importModules: { + // importDefaultName?: string; + // importName?: string; + // localName?: string; + // source: string; + // }[]; + // exportModules: { + // exportedName: string; + // localName: string; + // source?: string; + // }[]; + // /** + // * 子模块,形如:Demo.SubModule = value; 或者 Demo.SubModule.Sub = subValue; + // */ + // subModules: { + // objectName: string[]; + // propertyName: string; + // value?: string; + // // value 是否对应匿名函数 + // isValueAnonymousFunc: boolean; + // }[]; + // propsTypes: IPropTypes; + // propsDefaults: { + // name: string; + // defaultValue: any; + // }[]; } diff --git a/packages/material-parser/src/types/IMaterialScanModel.ts b/packages/material-parser/src/types/IMaterialScanModel.ts index 5e9b1551c..c87bdc6d7 100644 --- a/packages/material-parser/src/types/IMaterialScanModel.ts +++ b/packages/material-parser/src/types/IMaterialScanModel.ts @@ -7,10 +7,10 @@ interface IMaterialScanModel { /** 标记物料组件包所使用的模块规范 */ sourceType: 'module' | 'main'; /** 每个文件对应的文件内容 */ - modules: Array<{ + modules: { filePath: string; fileContent: string; - }>; + }[]; /** 当前包名 */ pkgName: string; /** 当前包版本 */ diff --git a/packages/material-parser/src/types/IMaterializeOptions.ts b/packages/material-parser/src/types/IMaterializeOptions.ts index 9896f3916..f1fdb82a0 100644 --- a/packages/material-parser/src/types/IMaterializeOptions.ts +++ b/packages/material-parser/src/types/IMaterializeOptions.ts @@ -22,14 +22,6 @@ interface IMaterializeOptions { */ accesser: 'local' | 'online'; - /** - * 是否为多组件透出场景 - * (true:表示多组件透出场景,false:表示单组件透出场景) - * @type {boolean} - * @memberof IMaterializeOptions - */ - isExportedAsMultiple: boolean; - /** * 当 accesser=local 时,需要通过此配置项指定当前工作目录,形如:/usr/.../demo-project * @type {string} diff --git a/packages/material-parser/src/types/IParser.ts b/packages/material-parser/src/types/IParser.ts deleted file mode 100644 index 3906b5ec9..000000000 --- a/packages/material-parser/src/types/IParser.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { IMaterialParsedModel } from './IMaterialParsedModel'; -import IMaterialScanModel from './IMaterialScanModel'; - -/** - * 解析器 - * @interface IParser - */ -interface IParser { - /** - * 根据 IScanner 阶段的产出结果,解析对文件内容进行 AST 解析 - * @param {IMaterialScanModel} model IScanner 阶段的产出结果 - * @returns {Promise} - * @memberof IParser - */ - parse(model: IMaterialScanModel): Promise; - - /** - * 解析 ES5 语法 - * @param {IMaterialScanModel} model - * @returns {Promise} - * @memberof IParser - */ - parseES5(model: IMaterialScanModel): Promise; - - /** - * 解析 ESM 语法 - * @param {{ - * model: IMaterialScanModel, - * filePath: string, // 要解析的文件路径 - * fileContent: string // 要解析的文件内容 - * }} params - * @returns {Promise} - * @memberof IParser - */ - parseES6(params: { - model: IMaterialScanModel; - filePath: string; - fileContent: string; - }): Promise; -} - -export default IParser; diff --git a/packages/material-parser/src/types/IScanner.ts b/packages/material-parser/src/types/IScanner.ts deleted file mode 100644 index 2c10eda17..000000000 --- a/packages/material-parser/src/types/IScanner.ts +++ /dev/null @@ -1,32 +0,0 @@ -import IMaterialScanModel from './IMaterialScanModel'; - -/** - * 扫描器接口 - * @interface IScanner - */ -interface IScanner { - /** - * 扫描 - * @returns {Promise} 扫描产物 - * @memberof IScanner - */ - scan(): Promise; - - /** - * 加载文件 - * @param {string} filePath 文件地址 - * @returns {Promise} 返回文件内容 - * @memberof IScanner - */ - loadFile(filePath: string): Promise; - - /** - * 解析 package.json 文件 - * @param {string} pkgJsonPath 文件路径 - * @returns {Promise<{ [k: string]: any }>} package 文件信息 - * @memberof IScanner - */ - resolvePkgJson(pkgJsonPath: string): Promise<{ [k: string]: any }>; -} - -export default IScanner; diff --git a/packages/material-parser/src/types/index.ts b/packages/material-parser/src/types/index.ts index 06f5ae80e..9ec13a7d3 100644 --- a/packages/material-parser/src/types/index.ts +++ b/packages/material-parser/src/types/index.ts @@ -6,12 +6,13 @@ import ICompiler from './ICompiler'; import IExtensionConfigManifest from './IExtensionConfigManifest'; import IGenerator from './IGenerator'; import IMaterializeOptions from './IMaterializeOptions'; -export * from './IMaterialParsedModel'; import IMaterialScanModel from './IMaterialScanModel'; import IParser from './IParser'; import IScanner from './IScanner'; import SourceType from './SourceType'; +export * from './IMaterialParsedModel'; + export { IGenerator, IParser, diff --git a/packages/material-parser/test/Materialize.ts b/packages/material-parser/test/Materialize.ts deleted file mode 100644 index c4c81bd2a..000000000 --- a/packages/material-parser/test/Materialize.ts +++ /dev/null @@ -1,63 +0,0 @@ -import test from 'ava'; -import Materialize from '../src/Materialize'; -import { IMaterializeOptions } from '../src/types'; -import { getFromFixtures } from './helpers'; - -const multiExportedComptPath = getFromFixtures('multiple-exported-component'); -const singleExportedComptPath = getFromFixtures('single-exported-component'); -const singleExportedComponent = '@ali/demo-biz-test090702@0.0.2'; -const multipleExportedComponent = '@ali/aimake-basic@0.1.0'; - -test('materialize single exported component by local', async t => { - const options: IMaterializeOptions = { - cwd: singleExportedComptPath, - entry: singleExportedComptPath, - accesser: 'local', - isExportedAsMultiple: false, - }; - - const instance = new Materialize(options); - const actual = await instance.start(); - - t.snapshot(actual); -}); - -// test('materialize multiple exported component by local', async t => { -// const options: IMaterializeOptions = { -// cwd: multiExportedComptPath, -// entry: multiExportedComptPath, -// accesser: 'local', -// isExportedAsMultiple: true, -// }; - -// const instance = new Materialize(options); -// const actual = await instance.start(); - -// t.snapshot(actual); -// }); - -// test('materialize single exported component by online', async t => { -// const options: IMaterializeOptions = { -// entry: singleExportedComponent, -// accesser: 'online', -// isExportedAsMultiple: false, -// }; - -// const instance = new Materialize(options); -// const actual = await instance.start(); - -// t.snapshot(actual); -// }); - -// test('materialize multiple exported component by online', async t => { -// const options: IMaterializeOptions = { -// entry: multipleExportedComponent, -// accesser: 'online', -// isExportedAsMultiple: false, -// }; - -// const instance = new Materialize(options); -// const actual = await instance.start(); - -// t.snapshot(actual); -// }); diff --git a/packages/material-parser/test/accesser/LocalAccesser.ts b/packages/material-parser/test/accesser/LocalAccesser.ts deleted file mode 100644 index d09786416..000000000 --- a/packages/material-parser/test/accesser/LocalAccesser.ts +++ /dev/null @@ -1,29 +0,0 @@ -import test from 'ava'; -import LocalAccesser from '../../src/accesser/LocalAccesser'; -import { IMaterializeOptions } from '../../src/types'; -import { getFromFixtures } from '../helpers'; - -const multiExportedComptPath = getFromFixtures('multiple-exported-component'); -const singleExportedComptPath = getFromFixtures('single-exported-component'); - -test.serial('access single exported component by local', async t => { - const options: IMaterializeOptions = { - entry: singleExportedComptPath, - accesser: 'local', - isExportedAsMultiple: false, - }; - const accesser = new LocalAccesser(options); - const actual = await accesser.access(); - t.snapshot(actual); -}); - -// test.serial('access multiple exported component by local', async t => { -// const options: IMaterializeOptions = { -// entry: multiExportedComptPath, -// accesser: 'local', -// isExportedAsMultiple: true, -// }; -// const accesser = new LocalAccesser(options); -// const actual = await accesser.access(); -// t.snapshot(actual); -// }); diff --git a/packages/material-parser/test/accesser/OnlineAccesser.ts b/packages/material-parser/test/accesser/OnlineAccesser.ts deleted file mode 100644 index 83aa50963..000000000 --- a/packages/material-parser/test/accesser/OnlineAccesser.ts +++ /dev/null @@ -1,42 +0,0 @@ -import test from 'ava'; -import OnlineAccesser from '../../src/accesser/OnlineAccesser'; -import { IMaterializeOptions } from '../../src/types'; - -const singleExportedComponent = '@ali/demo-biz-test090702@0.0.2'; -const multipleExportedComponent = '@ali/aimake-basic@0.1.0'; - -test.serial('online accesser', t => { - t.pass(); -}) -// test.serial('access single exported component by online', async t => { -// const options: IMaterializeOptions = { -// entry: singleExportedComponent, -// accesser: 'online', -// isExportedAsMultiple: false, -// }; -// const accesser = new OnlineAccesser(options); -// const actual = await accesser.access(); -// t.snapshot(actual); -// }); - -// test.serial('access multiple exported component by online', async t => { -// const options: IMaterializeOptions = { -// entry: multipleExportedComponent, -// accesser: 'online', -// isExportedAsMultiple: true, -// }; -// const accesser = new OnlineAccesser(options); -// const actual = await accesser.access(); -// t.snapshot(actual); -// }); - -// test.serial('access @alifd/next@1.17.12 by online', async t => { -// const options: IMaterializeOptions = { -// entry: '@alifd/next@1.17.12', -// accesser: 'online', -// isExportedAsMultiple: true, -// }; -// const accesser = new OnlineAccesser(options); -// const actual = await accesser.access(); -// t.snapshot(actual); -// }); diff --git a/packages/material-parser/test/accesser/snapshots/LocalAccesser.ts.md b/packages/material-parser/test/accesser/snapshots/LocalAccesser.ts.md deleted file mode 100644 index b6d56ecd5..000000000 --- a/packages/material-parser/test/accesser/snapshots/LocalAccesser.ts.md +++ /dev/null @@ -1,529 +0,0 @@ -# Snapshot report for `test/accesser/LocalAccesser.ts` - -The actual snapshot is saved in `LocalAccesser.ts.snap`. - -Generated by [AVA](https://ava.li). - -## access multiple exported component by local - -> Snapshot 1 - - [ - { - manifestFilePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeBlank/manifest.js', - manifestJS: 'export default {"name":"AIMakeBlank","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[{"name":"children","label":"children","renderer":""},{"name":"styleBoxModel","label":"styleBoxModel","renderer":""},{"name":"styleLayout","label":"styleLayout","renderer":""},{"name":"styleBackground","label":"styleBackground","renderer":""},{"name":"styleFlexLayout","label":"styleFlexLayout","renderer":""},{"name":"style","label":"style","renderer":"","defaultValue":"{}"},{"name":"id","label":"id","renderer":""}]}}', - manifestObj: { - name: 'AIMakeBlank', - settings: { - handles: [ - 'cut', - 'copy', - 'duplicate', - 'delete', - 'paste', - ], - insertionModes: 'tbrl', - props: [ - { - defaultValue: undefined, - label: 'children', - name: 'children', - renderer: '', - }, - { - defaultValue: undefined, - label: 'styleBoxModel', - name: 'styleBoxModel', - renderer: '', - }, - { - defaultValue: undefined, - label: 'styleLayout', - name: 'styleLayout', - renderer: '', - }, - { - defaultValue: undefined, - label: 'styleBackground', - name: 'styleBackground', - renderer: '', - }, - { - defaultValue: undefined, - label: 'styleFlexLayout', - name: 'styleFlexLayout', - renderer: '', - }, - { - defaultValue: '{}', - label: 'style', - name: 'style', - renderer: '', - }, - { - defaultValue: undefined, - label: 'id', - name: 'id', - renderer: '', - }, - ], - shouldActive: true, - shouldDrag: true, - type: 'element_inline', - }, - }, - }, - { - manifestFilePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/manifest.js', - manifestJS: 'export default {"name":"AIMakeIcon","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[{"name":"className","label":"className","renderer":""},{"name":"iconClassName","label":"iconClassName","renderer":""},{"name":"children","label":"children","renderer":""},{"name":"styleBoxModel","label":"styleBoxModel","renderer":""},{"name":"styleText","label":"styleText","renderer":""},{"name":"styleBackground","label":"styleBackground","renderer":""},{"name":"style","label":"style","renderer":"","defaultValue":"{}"}]}}', - manifestObj: { - name: 'AIMakeIcon', - settings: { - handles: [ - 'cut', - 'copy', - 'duplicate', - 'delete', - 'paste', - ], - insertionModes: 'tbrl', - props: [ - { - defaultValue: undefined, - label: 'className', - name: 'className', - renderer: '', - }, - { - defaultValue: undefined, - label: 'iconClassName', - name: 'iconClassName', - renderer: '', - }, - { - defaultValue: undefined, - label: 'children', - name: 'children', - renderer: '', - }, - { - defaultValue: undefined, - label: 'styleBoxModel', - name: 'styleBoxModel', - renderer: '', - }, - { - defaultValue: undefined, - label: 'styleText', - name: 'styleText', - renderer: '', - }, - { - defaultValue: undefined, - label: 'styleBackground', - name: 'styleBackground', - renderer: '', - }, - { - defaultValue: '{}', - label: 'style', - name: 'style', - renderer: '', - }, - ], - shouldActive: true, - shouldDrag: true, - type: 'element_inline', - }, - }, - }, - { - manifestFilePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeImage/manifest.js', - manifestJS: 'export default {"name":"AIMakeImage","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[{"name":"styleBoxModel","label":"styleBoxModel","renderer":""},{"name":"style","label":"style","renderer":"","defaultValue":"{}"}]}}', - manifestObj: { - name: 'AIMakeImage', - settings: { - handles: [ - 'cut', - 'copy', - 'duplicate', - 'delete', - 'paste', - ], - insertionModes: 'tbrl', - props: [ - { - defaultValue: undefined, - label: 'styleBoxModel', - name: 'styleBoxModel', - renderer: '', - }, - { - defaultValue: '{}', - label: 'style', - name: 'style', - renderer: '', - }, - ], - shouldActive: true, - shouldDrag: true, - type: 'element_inline', - }, - }, - }, - { - manifestFilePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeLink/manifest.js', - manifestJS: 'export default {"name":"AIMakeLink","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[{"name":"children","label":"children","renderer":""},{"name":"styleBoxModel","label":"styleBoxModel","renderer":""},{"name":"styleText","label":"styleText","renderer":""},{"name":"styleLayout","label":"styleLayout","renderer":""},{"name":"styleBackground","label":"styleBackground","renderer":""},{"name":"style","label":"style","renderer":"","defaultValue":"{}"}]}}', - manifestObj: { - name: 'AIMakeLink', - settings: { - handles: [ - 'cut', - 'copy', - 'duplicate', - 'delete', - 'paste', - ], - insertionModes: 'tbrl', - props: [ - { - defaultValue: undefined, - label: 'children', - name: 'children', - renderer: '', - }, - { - defaultValue: undefined, - label: 'styleBoxModel', - name: 'styleBoxModel', - renderer: '', - }, - { - defaultValue: undefined, - label: 'styleText', - name: 'styleText', - renderer: '', - }, - { - defaultValue: undefined, - label: 'styleLayout', - name: 'styleLayout', - renderer: '', - }, - { - defaultValue: undefined, - label: 'styleBackground', - name: 'styleBackground', - renderer: '', - }, - { - defaultValue: '{}', - label: 'style', - name: 'style', - renderer: '', - }, - ], - shouldActive: true, - shouldDrag: true, - type: 'element_inline', - }, - }, - }, - { - manifestFilePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakePlaceholder/manifest.js', - manifestJS: 'export default {"name":"AIMakePlaceholder","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[{"name":"children","label":"children","renderer":""},{"name":"styleBoxModel","label":"styleBoxModel","renderer":""},{"name":"styleLayout","label":"styleLayout","renderer":""},{"name":"style","label":"style","renderer":"","defaultValue":"{}"}]}}', - manifestObj: { - name: 'AIMakePlaceholder', - settings: { - handles: [ - 'cut', - 'copy', - 'duplicate', - 'delete', - 'paste', - ], - insertionModes: 'tbrl', - props: [ - { - defaultValue: undefined, - label: 'children', - name: 'children', - renderer: '', - }, - { - defaultValue: undefined, - label: 'styleBoxModel', - name: 'styleBoxModel', - renderer: '', - }, - { - defaultValue: undefined, - label: 'styleLayout', - name: 'styleLayout', - renderer: '', - }, - { - defaultValue: '{}', - label: 'style', - name: 'style', - renderer: '', - }, - ], - shouldActive: true, - shouldDrag: true, - type: 'element_inline', - }, - }, - }, - { - manifestFilePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeText/manifest.js', - manifestJS: 'export default {"name":"AIMakeText","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[{"name":"children","label":"children","renderer":""},{"name":"type","label":"type","renderer":""},{"name":"styleBoxModel","label":"styleBoxModel","renderer":""},{"name":"styleText","label":"styleText","renderer":""},{"name":"styleLayout","label":"styleLayout","renderer":""},{"name":"styleBackground","label":"styleBackground","renderer":""},{"name":"style","label":"style","renderer":"","defaultValue":"{}"}]}}', - manifestObj: { - name: 'AIMakeText', - settings: { - handles: [ - 'cut', - 'copy', - 'duplicate', - 'delete', - 'paste', - ], - insertionModes: 'tbrl', - props: [ - { - defaultValue: undefined, - label: 'children', - name: 'children', - renderer: '', - }, - { - defaultValue: undefined, - label: 'type', - name: 'type', - renderer: '', - }, - { - defaultValue: undefined, - label: 'styleBoxModel', - name: 'styleBoxModel', - renderer: '', - }, - { - defaultValue: undefined, - label: 'styleText', - name: 'styleText', - renderer: '', - }, - { - defaultValue: undefined, - label: 'styleLayout', - name: 'styleLayout', - renderer: '', - }, - { - defaultValue: undefined, - label: 'styleBackground', - name: 'styleBackground', - renderer: '', - }, - { - defaultValue: '{}', - label: 'style', - name: 'style', - renderer: '', - }, - ], - shouldActive: true, - shouldDrag: true, - type: 'element_inline', - }, - }, - }, - { - manifestFilePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/Root/manifest.js', - manifestJS: 'export default {"name":"Root","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[{"name":"style","label":"style","renderer":"","defaultValue":"{\\n padding: 0,\\n backgroundColor: \'#f0f2f5\',\\n minHeight: \'100%\'\\n}"},{"name":"children","label":"children","renderer":""}]}}', - manifestObj: { - name: 'Root', - settings: { - handles: [ - 'cut', - 'copy', - 'duplicate', - 'delete', - 'paste', - ], - insertionModes: 'tbrl', - props: [ - { - defaultValue: `{␊ - padding: 0,␊ - backgroundColor: '#f0f2f5',␊ - minHeight: '100%'␊ - }`, - label: 'style', - name: 'style', - renderer: '', - }, - { - defaultValue: undefined, - label: 'children', - name: 'children', - renderer: '', - }, - ], - shouldActive: true, - shouldDrag: true, - type: 'element_inline', - }, - }, - }, - ] - -## access single exported component by local - -> Snapshot 1 - - [ - { - manifestFilePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/single-exported-component/es/manifest.js', - manifestJS: 'export default {"name":"Demo","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[{"name":"optionalArray","label":"optionalArray","renderer":""},{"name":"optionalBool","label":"optionalBool","renderer":""},{"name":"optionalFunc","label":"optionalFunc","renderer":""},{"name":"optionalNumber","label":"optionalNumber","renderer":""},{"name":"optionalObject","label":"optionalObject","renderer":""},{"name":"optionalString","label":"optionalString","renderer":""},{"name":"optionalSymbol","label":"optionalSymbol","renderer":""},{"name":"optionalNode","label":"optionalNode","renderer":""},{"name":"optionalElement","label":"optionalElement","renderer":""},{"name":"optionalElementType","label":"optionalElementType","renderer":""},{"name":"optionalMessage","label":"optionalMessage","renderer":""},{"name":"optionalEnum","label":"optionalEnum","renderer":""},{"name":"optionalUnion","label":"optionalUnion","renderer":""},{"name":"optionalArrayOf","label":"optionalArrayOf","renderer":""},{"name":"optionalObjectOf","label":"optionalObjectOf","renderer":""},{"name":"optionalObjectWithShape","label":"optionalObjectWithShape","renderer":""},{"name":"optionalObjectWithShape2","label":"optionalObjectWithShape2","renderer":""},{"name":"optionalObjectWithStrictShape","label":"optionalObjectWithStrictShape","renderer":""},{"name":"requiredFunc","label":"requiredFunc","renderer":""},{"name":"requiredAny","label":"requiredAny","renderer":""}]}}', - manifestObj: { - name: 'Demo', - settings: { - handles: [ - 'cut', - 'copy', - 'duplicate', - 'delete', - 'paste', - ], - insertionModes: 'tbrl', - props: [ - { - defaultValue: undefined, - label: 'optionalArray', - name: 'optionalArray', - renderer: '', - }, - { - defaultValue: undefined, - label: 'optionalBool', - name: 'optionalBool', - renderer: '', - }, - { - defaultValue: undefined, - label: 'optionalFunc', - name: 'optionalFunc', - renderer: '', - }, - { - defaultValue: undefined, - label: 'optionalNumber', - name: 'optionalNumber', - renderer: '', - }, - { - defaultValue: undefined, - label: 'optionalObject', - name: 'optionalObject', - renderer: '', - }, - { - defaultValue: undefined, - label: 'optionalString', - name: 'optionalString', - renderer: '', - }, - { - defaultValue: undefined, - label: 'optionalSymbol', - name: 'optionalSymbol', - renderer: '', - }, - { - defaultValue: undefined, - label: 'optionalNode', - name: 'optionalNode', - renderer: '', - }, - { - defaultValue: undefined, - label: 'optionalElement', - name: 'optionalElement', - renderer: '', - }, - { - defaultValue: undefined, - label: 'optionalElementType', - name: 'optionalElementType', - renderer: '', - }, - { - defaultValue: undefined, - label: 'optionalMessage', - name: 'optionalMessage', - renderer: '', - }, - { - defaultValue: undefined, - label: 'optionalEnum', - name: 'optionalEnum', - renderer: '', - }, - { - defaultValue: undefined, - label: 'optionalUnion', - name: 'optionalUnion', - renderer: '', - }, - { - defaultValue: undefined, - label: 'optionalArrayOf', - name: 'optionalArrayOf', - renderer: '', - }, - { - defaultValue: undefined, - label: 'optionalObjectOf', - name: 'optionalObjectOf', - renderer: '', - }, - { - defaultValue: undefined, - label: 'optionalObjectWithShape', - name: 'optionalObjectWithShape', - renderer: '', - }, - { - defaultValue: undefined, - label: 'optionalObjectWithShape2', - name: 'optionalObjectWithShape2', - renderer: '', - }, - { - defaultValue: undefined, - label: 'optionalObjectWithStrictShape', - name: 'optionalObjectWithStrictShape', - renderer: '', - }, - { - defaultValue: undefined, - label: 'requiredFunc', - name: 'requiredFunc', - renderer: '', - }, - { - defaultValue: undefined, - label: 'requiredAny', - name: 'requiredAny', - renderer: '', - }, - ], - shouldActive: true, - shouldDrag: true, - type: 'element_inline', - }, - }, - }, - ] diff --git a/packages/material-parser/test/accesser/snapshots/LocalAccesser.ts.snap b/packages/material-parser/test/accesser/snapshots/LocalAccesser.ts.snap deleted file mode 100644 index 0d3c837c208a03585e1ac98bdab8e967ff82b8cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3727 zcmV;A4sh{7RzV2V|V2aUH;!o2}i_#59AWEVXRC;2@JzXq;|@C^$Xt1*i&?7NN=OLcYW1w!6fP<(6i@fQ)8Odk6m5 z{p~JiGioTNQJR!!xB2jQCC=#Z_+9q8X2E$C&L(*Md@!%kYikYWw0k}6V##v6o^~+; zn@jr5QJ%}z#Jd#oz4#4yFYm=6%f?d1Uhna^6x^NJ8s=Gkce8@IGh4&F(BIaCgREUX zpiw}ey($zSAJ8aZso=#=tx$k`K&ya`wkE~PCm+zd253M^S0IqBVV)UimkR!_BheMH zOl;^8i|IV7QPcw7=R;RkD5mR(Ry1yZn^G8oYz^~8Zv0Vj2lF-TQg>O@5~(9eN1|$v zie-cximH%HoPuMi!>0JFu!`;#S*2ZORksR7XK5Cqh&D_Yp?EL9#_#m(?AVCabjTdf5Z_+ zI^FS*)0u(;j(D!bToWOMpa$?@1K0_kGg0S`W6qr*6@AjwRdizKcti!27CwB*;faHo zR7OEkR~hlrxI>kY5;|l_nTB+F=A}@c*qz$ln{7K2>GAG! zv-Eg})aYaqeCAssCJj>Z1~F-rk_W|PoRmB%CgY`KehQJ=4w4s&$wVo+MNFEcROq!+Ss8sQ+QgX4FOp%h;i^)_e`IMMUlail`$#f~1mxg49lw2exGo|EaF_|SL zpA?fr#NRUh1d?BX%yj&Qpe3E^1Bu~%0G1mexfMJP-U5aU%3@+H7Dy(53xFToPg{~0 z%OOaf2Y(Z#nS@Nwq%3B}aycY+@I!C_yiZ$_8OwhliOV8nJXi`gWl@$C#&SO-4}zD# zS0H}~Wl3c$(;;aDt>AX>8`_e_Sl))@I51`tQUO+EQx*Z_9XmQ2R-G9-t=DUdr1^%_Q5vKWgUl2za~a1eY*TZS+e!*D`OU?R8_Y#B~j zvKh;Rkn9Gpf^Wfu5tL;pW0?cVLa+ur4Bnqn}u3c<%`2(Xy zVk#wxm&W_x|5C%A-qeO=Ri!ETxX_tF`X;)R(AO-r;M9bA$0j~&MHQQZP^Z|^!e0^9 zqEnaZ9bcd|M-`u~rzq7uKI#2Ay7-i&diM?S1wE?1p&-;Lwsh*PT`fEf ztxgdRQJ7ayi!utm-q*5o>LRLZsjStzC5n?HQME(`p-!>MBdRp@64ltNq}2Pj?VQ(% z>bF(a>J(uHJ!_;EqLx^v7>7rgIZ_KXN{>zvkBBtar519uCY@p)r8{@0&SLa zRnLr;(CYR0-FD{Op-0q;nC0TvDMt`?M6C$gNXfFob?++i*Sa;?scQ*H15tJ z1rPQnecwuY)281!3&#ZUCe*#ge5J;i(0N-syIZjkzUov^U1mBsfb^iVC5-5c&bB>9 zI@=PDr<>huQ^YYtENdWju%0!A74Cw9cAMRfD%KQKl#2gtlG|N_$K~X==DuTdZyO+ASAoN zYqXSEZ)Q9R$tf_BUILZNNUI^43a+H37DjqCB-esHw6u(oz6{A>@HH)+%t+I72pI|{ z(+jEUySKbJIb>Q^y6%f}6jvE*m1FLjXp)NA+OuMkL*ALCa$f9JIO0o^R1BBfqhd0d zheWBg+MbnW?i!_~V%GMom^kq+Bo(kMO!weFl<0 zfOkRSC_?f<9cUV*wfZvgHb{N~9s_TJFFkBLjT9#Py3?gIzFVerWq^*u$V?;tRaB_tJ$07al2 zOa+Z&)%FMBjEf++2sptt;2yA_GG)?dd@Dg|(yhoX*(q}vY!56?#j3x!D!3D+PrbhZVYJ$K4yp(We?CePkEL_@H z99+1xw^&}d^w(l};nJ`YdEwIB5_#d$h7x(<(&Ht8g-bC|mk&#Vbs0KQuFIT>a$VL> zl%9wfz;5M*UX_RFmW7!VL4)84aShP>4ER~F<1d?$)cJ%o0LS^1rG~NG1j#nA54-_R)0XoXOLiUV0Hy&4 zxTB7;)H0U+kQ@Z>07E??6Y43;G~1mo^2z;;7A6 zM-u6^k1XuluIfHAHKkrVNJ72>t9}THtkY|U8})%%b%&d}R@Vr-)}L!f7*X5P2$5-6 zzfm>HcJP~t)+vr8dHJ?lI1yEP-7CUYhO6Ey)Ra0!H+XmLb}N$? z=cu-_NUF2<&N|@kTm9V52Hf=;yjPqZ_lm*i!@*wpeeRY0*!~AwS0BVAeN0!2M@jI# tZ0UpJ&*1pe7ZEkAH-|0PHmk1IHY+UFHpf(z{;xN^{{auUNs3uv003L%4B-F( diff --git a/packages/material-parser/test/accesser/snapshots/OnlineAccesser.ts.md b/packages/material-parser/test/accesser/snapshots/OnlineAccesser.ts.md deleted file mode 100644 index fc1e99f97..000000000 --- a/packages/material-parser/test/accesser/snapshots/OnlineAccesser.ts.md +++ /dev/null @@ -1,408 +0,0 @@ -# Snapshot report for `test/accesser/OnlineAccesser.ts` - -The actual snapshot is saved in `OnlineAccesser.ts.snap`. - -Generated by [AVA](https://ava.li). - -## access multiple exported component by online - -> Snapshot 1 - - [ - { - manifestFilePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/node_modules/.temp/kDKCQ3wGKzpHh6KU5ExdE1/node_modules/@ali/aimake-basic/es/basic/AIMakeBlank/manifest.js', - manifestJS: 'export default {"name":"AIMakeBlank","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[{"name":"children","label":"children","renderer":""},{"name":"styleBoxModel","label":"styleBoxModel","renderer":""},{"name":"styleLayout","label":"styleLayout","renderer":""},{"name":"styleBackground","label":"styleBackground","renderer":""},{"name":"styleFlexLayout","label":"styleFlexLayout","renderer":""},{"name":"style","label":"style","renderer":"","defaultValue":"{}"},{"name":"id","label":"id","renderer":""}]}}', - manifestObj: { - name: 'AIMakeBlank', - settings: { - handles: [ - 'cut', - 'copy', - 'duplicate', - 'delete', - 'paste', - ], - insertionModes: 'tbrl', - props: [ - { - defaultValue: undefined, - label: 'children', - name: 'children', - renderer: '', - }, - { - defaultValue: undefined, - label: 'styleBoxModel', - name: 'styleBoxModel', - renderer: '', - }, - { - defaultValue: undefined, - label: 'styleLayout', - name: 'styleLayout', - renderer: '', - }, - { - defaultValue: undefined, - label: 'styleBackground', - name: 'styleBackground', - renderer: '', - }, - { - defaultValue: undefined, - label: 'styleFlexLayout', - name: 'styleFlexLayout', - renderer: '', - }, - { - defaultValue: '{}', - label: 'style', - name: 'style', - renderer: '', - }, - { - defaultValue: undefined, - label: 'id', - name: 'id', - renderer: '', - }, - ], - shouldActive: true, - shouldDrag: true, - type: 'element_inline', - }, - }, - }, - { - manifestFilePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/node_modules/.temp/kDKCQ3wGKzpHh6KU5ExdE1/node_modules/@ali/aimake-basic/es/basic/AIMakeIcon/manifest.js', - manifestJS: 'export default {"name":"AIMakeIcon","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[{"name":"className","label":"className","renderer":""},{"name":"iconClassName","label":"iconClassName","renderer":""},{"name":"children","label":"children","renderer":""},{"name":"styleBoxModel","label":"styleBoxModel","renderer":""},{"name":"styleText","label":"styleText","renderer":""},{"name":"styleBackground","label":"styleBackground","renderer":""},{"name":"style","label":"style","renderer":"","defaultValue":"{}"}]}}', - manifestObj: { - name: 'AIMakeIcon', - settings: { - handles: [ - 'cut', - 'copy', - 'duplicate', - 'delete', - 'paste', - ], - insertionModes: 'tbrl', - props: [ - { - defaultValue: undefined, - label: 'className', - name: 'className', - renderer: '', - }, - { - defaultValue: undefined, - label: 'iconClassName', - name: 'iconClassName', - renderer: '', - }, - { - defaultValue: undefined, - label: 'children', - name: 'children', - renderer: '', - }, - { - defaultValue: undefined, - label: 'styleBoxModel', - name: 'styleBoxModel', - renderer: '', - }, - { - defaultValue: undefined, - label: 'styleText', - name: 'styleText', - renderer: '', - }, - { - defaultValue: undefined, - label: 'styleBackground', - name: 'styleBackground', - renderer: '', - }, - { - defaultValue: '{}', - label: 'style', - name: 'style', - renderer: '', - }, - ], - shouldActive: true, - shouldDrag: true, - type: 'element_inline', - }, - }, - }, - { - manifestFilePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/node_modules/.temp/kDKCQ3wGKzpHh6KU5ExdE1/node_modules/@ali/aimake-basic/es/basic/AIMakeImage/manifest.js', - manifestJS: 'export default {"name":"AIMakeImage","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[{"name":"styleBoxModel","label":"styleBoxModel","renderer":""},{"name":"style","label":"style","renderer":"","defaultValue":"{}"}]}}', - manifestObj: { - name: 'AIMakeImage', - settings: { - handles: [ - 'cut', - 'copy', - 'duplicate', - 'delete', - 'paste', - ], - insertionModes: 'tbrl', - props: [ - { - defaultValue: undefined, - label: 'styleBoxModel', - name: 'styleBoxModel', - renderer: '', - }, - { - defaultValue: '{}', - label: 'style', - name: 'style', - renderer: '', - }, - ], - shouldActive: true, - shouldDrag: true, - type: 'element_inline', - }, - }, - }, - { - manifestFilePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/node_modules/.temp/kDKCQ3wGKzpHh6KU5ExdE1/node_modules/@ali/aimake-basic/es/basic/AIMakeLink/manifest.js', - manifestJS: 'export default {"name":"AIMakeLink","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[{"name":"children","label":"children","renderer":""},{"name":"styleBoxModel","label":"styleBoxModel","renderer":""},{"name":"styleText","label":"styleText","renderer":""},{"name":"styleLayout","label":"styleLayout","renderer":""},{"name":"styleBackground","label":"styleBackground","renderer":""},{"name":"style","label":"style","renderer":"","defaultValue":"{}"}]}}', - manifestObj: { - name: 'AIMakeLink', - settings: { - handles: [ - 'cut', - 'copy', - 'duplicate', - 'delete', - 'paste', - ], - insertionModes: 'tbrl', - props: [ - { - defaultValue: undefined, - label: 'children', - name: 'children', - renderer: '', - }, - { - defaultValue: undefined, - label: 'styleBoxModel', - name: 'styleBoxModel', - renderer: '', - }, - { - defaultValue: undefined, - label: 'styleText', - name: 'styleText', - renderer: '', - }, - { - defaultValue: undefined, - label: 'styleLayout', - name: 'styleLayout', - renderer: '', - }, - { - defaultValue: undefined, - label: 'styleBackground', - name: 'styleBackground', - renderer: '', - }, - { - defaultValue: '{}', - label: 'style', - name: 'style', - renderer: '', - }, - ], - shouldActive: true, - shouldDrag: true, - type: 'element_inline', - }, - }, - }, - { - manifestFilePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/node_modules/.temp/kDKCQ3wGKzpHh6KU5ExdE1/node_modules/@ali/aimake-basic/es/basic/AIMakePlaceholder/manifest.js', - manifestJS: 'export default {"name":"AIMakePlaceholder","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[{"name":"children","label":"children","renderer":""},{"name":"styleBoxModel","label":"styleBoxModel","renderer":""},{"name":"styleLayout","label":"styleLayout","renderer":""},{"name":"style","label":"style","renderer":"","defaultValue":"{}"}]}}', - manifestObj: { - name: 'AIMakePlaceholder', - settings: { - handles: [ - 'cut', - 'copy', - 'duplicate', - 'delete', - 'paste', - ], - insertionModes: 'tbrl', - props: [ - { - defaultValue: undefined, - label: 'children', - name: 'children', - renderer: '', - }, - { - defaultValue: undefined, - label: 'styleBoxModel', - name: 'styleBoxModel', - renderer: '', - }, - { - defaultValue: undefined, - label: 'styleLayout', - name: 'styleLayout', - renderer: '', - }, - { - defaultValue: '{}', - label: 'style', - name: 'style', - renderer: '', - }, - ], - shouldActive: true, - shouldDrag: true, - type: 'element_inline', - }, - }, - }, - { - manifestFilePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/node_modules/.temp/kDKCQ3wGKzpHh6KU5ExdE1/node_modules/@ali/aimake-basic/es/basic/AIMakeText/manifest.js', - manifestJS: 'export default {"name":"AIMakeText","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[{"name":"children","label":"children","renderer":""},{"name":"type","label":"type","renderer":""},{"name":"styleBoxModel","label":"styleBoxModel","renderer":""},{"name":"styleText","label":"styleText","renderer":""},{"name":"styleLayout","label":"styleLayout","renderer":""},{"name":"styleBackground","label":"styleBackground","renderer":""},{"name":"style","label":"style","renderer":"","defaultValue":"{}"}]}}', - manifestObj: { - name: 'AIMakeText', - settings: { - handles: [ - 'cut', - 'copy', - 'duplicate', - 'delete', - 'paste', - ], - insertionModes: 'tbrl', - props: [ - { - defaultValue: undefined, - label: 'children', - name: 'children', - renderer: '', - }, - { - defaultValue: undefined, - label: 'type', - name: 'type', - renderer: '', - }, - { - defaultValue: undefined, - label: 'styleBoxModel', - name: 'styleBoxModel', - renderer: '', - }, - { - defaultValue: undefined, - label: 'styleText', - name: 'styleText', - renderer: '', - }, - { - defaultValue: undefined, - label: 'styleLayout', - name: 'styleLayout', - renderer: '', - }, - { - defaultValue: undefined, - label: 'styleBackground', - name: 'styleBackground', - renderer: '', - }, - { - defaultValue: '{}', - label: 'style', - name: 'style', - renderer: '', - }, - ], - shouldActive: true, - shouldDrag: true, - type: 'element_inline', - }, - }, - }, - { - manifestFilePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/node_modules/.temp/kDKCQ3wGKzpHh6KU5ExdE1/node_modules/@ali/aimake-basic/es/basic/Root/manifest.js', - manifestJS: 'export default {"name":"Root","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[{"name":"style","label":"style","renderer":"","defaultValue":"{\\n padding: 0,\\n backgroundColor: \'#f0f2f5\',\\n minHeight: \'100%\'\\n}"},{"name":"children","label":"children","renderer":""}]}}', - manifestObj: { - name: 'Root', - settings: { - handles: [ - 'cut', - 'copy', - 'duplicate', - 'delete', - 'paste', - ], - insertionModes: 'tbrl', - props: [ - { - defaultValue: `{␊ - padding: 0,␊ - backgroundColor: '#f0f2f5',␊ - minHeight: '100%'␊ - }`, - label: 'style', - name: 'style', - renderer: '', - }, - { - defaultValue: undefined, - label: 'children', - name: 'children', - renderer: '', - }, - ], - shouldActive: true, - shouldDrag: true, - type: 'element_inline', - }, - }, - }, - ] - -## access single exported component by online - -> Snapshot 1 - - [ - { - manifestFilePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/node_modules/.temp/todtaTTK9KxDGepu5Kbb9G/node_modules/@ali/demo-biz-test090702/es/manifest.js', - manifestJS: 'export default {"name":"Demo","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}', - manifestObj: { - name: 'Demo', - settings: { - handles: [ - 'cut', - 'copy', - 'duplicate', - 'delete', - 'paste', - ], - insertionModes: 'tbrl', - props: [], - shouldActive: true, - shouldDrag: true, - type: 'element_inline', - }, - }, - }, - ] diff --git a/packages/material-parser/test/accesser/snapshots/OnlineAccesser.ts.snap b/packages/material-parser/test/accesser/snapshots/OnlineAccesser.ts.snap deleted file mode 100644 index e8ea50d9451e4f315e76225efbfde5cab1ea5b7e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2896 zcmV-W3$OG+RzVY2;e>+GVGf93P7a00000000B+ znhQ`=*B!>s-DMX9bU~v=5ry@E0?RHSAmEFK53?TW%mLLm)&(A24sjjd053x z>P$7Au}!O;sZETNw9U&9o2q$O)3no?+J|ZEj5UoKW7QaEs_pcBSMEbWof{>?F*?%g_+w#4Z zQ}Z=>`|9gCx%OY>gs4fRtm2|LRXSd?z!**&&uNOBPQIDrd?lSuN4RLhafFNExVb)4 zL<3$of~Dv!OVwf4F0ZZ^%x+Gl6yxIJ2se^&YQpKDQQaq%H1S+qBX6_T2rlHiN=gJh}JjSEglgUGu%R>!|1kK-2BRw75NoSrDcM{lT%S$ zonIEHT!=o57NOB@sJ3o4xDl->-;`&{GRj?efO~&5%qPv%_2$_YxHK18x>}|qZuz2k3+PYF%nW4t;q!k@51Xk^jK&2h?XL= z+qwz8xt$)tS6AxfYkf5ir`;j7ysovCaHBYGIo@eso-w{W@lH!qLcJLmw}SojbWk(X zK}C&Ogftw=AJU-6-L?C57v&oxsjtYdapevet0rV2SOqqNeQK)j2&QkX-1PhE&ZZ+f zhL8$sRN#m!;Ys5zw{hFA4UIfhR12~Gqbygdbo6ZL9Q3XQ5z>56LJFJ}(okr}V@W51 zOi%`@!RCm-<*W%<&QSr^wDeNf5H41VK*>#wdDT(JaY|g$H1pLe(T-4No$r#`cS-A= zgueQS&XJSmq~C@VRf<>aQDh}p59)yjYz1vSZB&u+Mzz=57)tL+uioA3E2*fGi&L>} zN&TbvkW`G2i`%54MlQZ06}9qKcMio1;6u!})tca29poNJTEGS^A=jfQ`6x!N8-ZC2 zZUbu!C7;O1pMhi-*ceO5$x)O%nUPD*SH|oPraz z`qp&C{cdR-?1Hae|N`rZ&qb{IIYShX1lF-i_+G^ zqLf+;t2HU|F4woDvfrZgtLtV~T9IZ+7goBy8~dQ`1S^FmW)*hS4e&0|mnH05nb{#( znPGKaE@?z}y<3{)Tn|fAYBHSGW+*0nf2Q4I_uhf9)Y{umY1us-2vUpTH0i=^YaZOs zcKumiJ3_L&j)&9osuX#%P-ho0K)qXKzwTjg_iK1~u?_4uqW(b zzBw8_A;_Ji99%2}<_W>?BthB=$&=tkTB>8D??Q44T&JZ8j5Ky4A)`V5L`te>q$?nK z1Z=0J21dFcl7rxPv^1BIeh$f(K$k#Ci+gu3EynK$WqI6ZC3Ja9t*3UPJAVU{o3Zq* znHazC>vB6k>Q^|@H!!)GzxAz|c;+Lf+}hYl{Rv7sTI6Ob`_@c^v zoy1skA(;!Rz*g`acnh4Rty3ARHi?i}FdbBaTCfuwN}{Y8jP(p8pMaYnDVdNw@F-|W zrmT64^{0@$1l|Mx29bI~QbC2DvX*pngL#v_|2LQq=?DD=vy#u}A;>3j>d?vO(W(8< z=h-2Y&zm90=gJVuXU4St=d)(o(8*_42=X~Lg!1`c2=d9EKIr*GaoV+rq8e-hyTC#4 z&h(%U&~Q;_Aov7)2CjiSAaVviHG;$$fo3gb*3N_=0~CYRzy;bUQ#{?{0SJBuegTex zli)P?6kMdtqv;;Mg5W=3R0<)}zyh!;CD4>enbbB2+~5gHIGJvJ2L#W8pMWFaWAFuK znnsx-)iVhh0mgvIU>2AS7R(GZPN#b-hoBNzz-F)q9HvZ0%A|Q0f>YpQa1LCe3?{ml zn-JUvx>@+>0TzPQvjRJHa0CV{iz(PMP!R9*;rr0XPe;f!I{MSE+%f zQu;kAgrEpiP{Kt+;;AmbC$b(+^*xcbBUO1K>+MwKiL9%s$`e`oH06n`sx;+^tZ%1z zpU4^lxwNPGa``e%$t5{m$z^4_lFRmVC6~9-m0Yf*4}n~~u_hUOxvVgFa~ag2v~noV zC_x=DCk2C~s!?61be9Brw^iB=Dfoo4^p5%ugA8 zp}t{MLcP=(YNAOQ>q?U{)=!$0$^5!$$V}#oCSNX-GQGKA>tBvy6=(v_gAXKt0$4-k~ky7|S_GE`X>xgcw29 z9Lh4Dv3MY90ndXE!7bWyKVuo6k57uA6x4zp`IKb>V|f9Rm%$&we?dwCWtqZQ${<+= z+~7HIgtjCxmcK%B4yXzVnF*E^QkEHvr4bSr*b9z<%d{nhvBbG!5)b%3_!T%$ zTQV7odI3KDf^@J7Y+FECve@(?IS5XH8z5mJWyxmKholJ9fi`fMw#;TMA3<^&d<`ZQ z!CpjJ3K$CyNiEn3UIHJ{mO{pI1(F+JTrqk84aJmYE@NqfWH)#foCRD7WtqoVk|9X} z<-i5@(U$p)r5%!E;GZDAl#qF)lw|>9SqF(3>;#9w?`g|I#&Q*sn_%4{Lbiefizv%t z#&R5zli)IlUrb2uV#-p+{16#If1CEd6C_tgj-(_S`TmXaqqFZWPO#sryAwtE?)!99 zkkG_5GT_#4u)u;U2PnE2znjECZ-jKO8=%N^)cxmR(ep;A#!O`m`bM&s2Plpa%9G{6!s%8uPHQzj37#<_O8@}%bAPe` diff --git a/packages/material-parser/test/fixtures/__snapshots__/test/Materialize.ts.md b/packages/material-parser/test/fixtures/__snapshots__/test/Materialize.ts.md deleted file mode 100644 index 7a2d6f6db..000000000 --- a/packages/material-parser/test/fixtures/__snapshots__/test/Materialize.ts.md +++ /dev/null @@ -1,188 +0,0 @@ -# Snapshot report for `test/Materialize.ts` - -The actual snapshot is saved in `Materialize.ts.snap`. - -Generated by [AVA](https://avajs.dev). - -## materialize single exported component by local - -> Snapshot 1 - - [ - { - manifestFilePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/single-exported-component/es/manifest.json', - manifestObj: { - docUrl: '', - npm: { - destructuring: false, - exportName: '', - main: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/single-exported-component/es/index.js', - package: 'single-exported-component', - subName: '', - version: '1.0.0', - }, - props: [ - { - name: 'optionalArray', - propType: 'array', - }, - { - name: 'optionalBool', - propType: 'bool', - }, - { - name: 'optionalFunc', - propType: 'func', - }, - { - defaultValue: 123, - name: 'optionalNumber', - propType: 'number', - }, - { - name: 'optionalObject', - propType: 'object', - }, - { - name: 'optionalString', - propType: 'string', - }, - { - name: 'optionalSymbol', - propType: 'symbol', - }, - { - name: 'optionalNode', - propType: 'node', - }, - { - name: 'optionalElement', - propType: 'element', - }, - { - name: 'optionalElementType', - propType: 'elementType', - }, - { - name: 'optionalMessage', - propType: { - type: 'instanceOf', - value: 'Demo', - }, - }, - { - name: 'optionalEnum', - propType: { - type: 'oneOf', - value: [ - 'News', - 'Photos', - ], - }, - }, - { - name: 'optionalUnion', - propType: { - type: 'oneOfType', - value: [ - 'string', - 'number', - { - type: 'instanceOf', - value: 'Demo', - }, - ], - }, - }, - { - name: 'optionalArrayOf', - propType: { - type: 'arrayOf', - value: 'number', - }, - }, - { - name: 'optionalObjectOf', - propType: { - type: 'objectOf', - value: 'number', - }, - }, - { - name: 'optionalObjectWithShape', - propType: { - type: 'shape', - value: [ - { - name: 'optionalProperty', - propType: 'string', - }, - { - name: 'requiredProperty', - propType: { - isRequired: true, - type: 'number', - }, - }, - ], - }, - }, - { - name: 'optionalObjectWithShape2', - propType: { - isRequired: true, - type: 'shape', - value: [ - { - name: 'optionalProperty', - propType: 'string', - }, - { - name: 'requiredProperty', - propType: { - isRequired: true, - type: 'number', - }, - }, - ], - }, - }, - { - name: 'optionalObjectWithStrictShape', - propType: { - type: 'exact', - value: [ - { - name: 'optionalProperty', - propType: 'string', - }, - { - name: 'requiredProperty', - propType: { - isRequired: true, - type: 'number', - }, - }, - ], - }, - }, - { - name: 'requiredFunc', - propType: { - isRequired: true, - type: 'func', - }, - }, - { - name: 'requiredAny', - propType: { - isRequired: true, - type: 'any', - }, - }, - ], - screenshot: '', - title: 'single-exported-component', - }, - }, - ] diff --git a/packages/material-parser/test/fixtures/__snapshots__/test/Materialize.ts.snap b/packages/material-parser/test/fixtures/__snapshots__/test/Materialize.ts.snap deleted file mode 100644 index c49d07908fa8d5917ba96be85f294b28514c43ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1723 zcmV;s21NNmRzV9y!@LH89~R9h_&_aBQ000000000Bk zm}_hlRTzfP?7iE|ZoA!HxI^*6rCsO`)CdX)geVpSD~SSTx;t$LcW2g_*iU|RNCL(_%CM23_A~698Y9zjMc4yoDPTSco24a&p{dUfC z-kEdz&Y79V7?aqQb368_^PUP_IVm?bRSDAB79SvdoxrmFR&QE4cv z8^60cNp+I+AX?`vxc5EiBs528j7Ns{kk>gRzmnK)k-VQ zuhvO>!){;jH178;^as@JW$ZX~6^i*t8-1m13`y~Ofjj_hgtkGuAQiHpeb7tL>(B`F zF?0<20y+a-fG$D5LDwO#pRqcB>GbrMOiy%bfHbr=g@H11NsKz$$gg^$w7c@{?vgXg zB;Do9$g1Yd&I7l3cB)!R8N$>g&loItmouoP70q1F6m1Uvcp;)4%%TI58n;)X4&CcJB;%1x*gW@uq}kJfrnjo7~{!p z7~wwXaEQ$G0G;XHb3o2RHz*nu(6%bZ7C~F92pXcOZxG0H&^yo>idPBFSAhHpEesPh zETE47c?{Z1(P{yG56EHYJBro_=-**JCTwvvL2CtcGmviRd5YEv=wTp7pdTq35zy)y z#_FL}H3W?c=yo7Gp#v0c5YQ1IA3)zwG%ldO0{I=9RZGxT0bK!PC8Sbxrhx7T@*?y( zMQ01>1t1rphB|__3FuNFolu&hiv;ulkXN9i6itXL0mymiABrw_JrVe{u{RAhU zM^5tuPsotH?>#=8Ez*8DPr13)IIe4TJ?&=d>)}w@o*Qyn($%wj5%&doVSoNX63_iAN4TlTX*s+cB@ z8vHcc92q-}7X7Eux9c%0xzXCnjEZTZTT=_C^-N_>k&=Y7xtDvrQJGh?bO{yAzO2lw zxzudCYV~jHm$Ui)zg(GT%Oswi+_W`Xk?HISOtFTO*4X22tjxK_P@c`HhLXysSQwd= z8C5$*YqVkR^Y+9(*vL+y{;!GKMvp&X)!bTGoB8+j zNSXd^jnnTtzcM7-M;27yR9^MzJ>J+U@8*2GvYn=|3UYYLJ|)>hx|Bh) za8Z(q6K+etZs{hk;-yuJCq!DwnWcE0zb~Hu5)pR3N2KD;_lkq@{P&7t(Wk|tpJ-9E z$tk+ODPM%f_99F}uQid>)FNcDqd<;BqZFMdppjY_EkVh0XlpB(ZVQB&nFF#1dXu7e3+M?TC!wDy+Tl8hr Snapshot 1 - - [ - { - manifestFilePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/single-exported-component/es/manifest.json', - manifestObj: { - docUrl: '', - npm: { - destructuring: false, - exportName: '', - main: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/single-exported-component/es/index.js', - package: '@ali/lowcode-engine-material-parser', - subName: '', - version: '0.1.0', - }, - props: [ - { - name: 'optionalArray', - propType: 'array', - }, - { - name: 'optionalBool', - propType: 'bool', - }, - { - name: 'optionalFunc', - propType: 'func', - }, - { - defaultValue: 123, - name: 'optionalNumber', - propType: 'number', - }, - { - name: 'optionalObject', - propType: 'object', - }, - { - name: 'optionalString', - propType: 'string', - }, - { - name: 'optionalSymbol', - propType: 'symbol', - }, - { - name: 'optionalNode', - propType: 'node', - }, - { - name: 'optionalElement', - propType: 'element', - }, - { - name: 'optionalElementType', - propType: 'elementType', - }, - { - name: 'optionalMessage', - propType: { - type: 'instanceOf', - value: 'Demo', - }, - }, - { - name: 'optionalEnum', - propType: { - type: 'oneOf', - value: [ - 'News', - 'Photos', - ], - }, - }, - { - name: 'optionalUnion', - propType: { - type: 'oneOfType', - value: [ - 'string', - 'number', - { - type: 'instanceOf', - value: 'Demo', - }, - ], - }, - }, - { - name: 'optionalArrayOf', - propType: { - type: 'arrayOf', - value: 'number', - }, - }, - { - name: 'optionalObjectOf', - propType: { - type: 'objectOf', - value: 'number', - }, - }, - { - name: 'optionalObjectWithShape', - propType: { - type: 'shape', - value: [ - { - name: 'optionalProperty', - propType: 'string', - }, - { - name: 'requiredProperty', - propType: { - isRequired: true, - type: 'number', - }, - }, - ], - }, - }, - { - name: 'optionalObjectWithShape2', - propType: { - isRequired: true, - type: 'shape', - value: [ - { - name: 'optionalProperty', - propType: 'string', - }, - { - name: 'requiredProperty', - propType: { - isRequired: true, - type: 'number', - }, - }, - ], - }, - }, - { - name: 'optionalObjectWithStrictShape', - propType: { - type: 'exact', - value: [ - { - name: 'optionalProperty', - propType: 'string', - }, - { - name: 'requiredProperty', - propType: { - isRequired: true, - type: 'number', - }, - }, - ], - }, - }, - { - name: 'requiredFunc', - propType: { - isRequired: true, - type: 'func', - }, - }, - { - name: 'requiredAny', - propType: { - isRequired: true, - type: 'any', - }, - }, - ], - screenshot: '', - title: '@ali/lowcode-engine-material-parser', - }, - }, - ] diff --git a/packages/material-parser/test/fixtures/__snapshots__/test/accesser/LocalAccesser.ts.snap b/packages/material-parser/test/fixtures/__snapshots__/test/accesser/LocalAccesser.ts.snap deleted file mode 100644 index 368768b7c6ce4235eff0ad965cdd48424a87082a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1734 zcmV;%208gbRzVU6g8;~$F%00000000Bk zm|JWVRT#(5?7iFF?)I{60g*dcq1{qr;6ddQ;Q^(Tt0WR-x;xtr?9Oa=rZ<%YW1=Ea zFoa-8G$xQ36N8u3ON?Nm(F7j6gb*c$0Ko^47l{dp2F3rJ-Pv}(Q##wlKy30)zn$|t z|2en$&Y79X7?W7$wZ+R$?7!|me{fpt$(vho#rm5*l`%K-^H>TMrH%~Z5xJgpD5 z@+)#$ZN(2OZUw4pN<1qkcFH}95zok`l2he$YgW#|ENo< z&Qy}H%Vc#;(abonnr~Oz4nxOmzJUTB#uj);Z#|{G4M?%afoy=bK|N3o+6BD~ z9f00~-i1b>FQHS=8R!CZ6}k>#$XEz!f@XV57pk{pp<;M_q|4zXrYzT=!2DzG`Bhhx z4qSdcbjlg!76a$W$f{}4En9R^6)_`4DoQg6^41Z*9vQR_=%r)%L*@AVU&lV0K!@xF0sNo z9(G${Jx_SAB0K;c50EwQqif!M3CI07X4}fxHfV3|*jjmEi0T zG8TrG1_>Gz(5HbY(0+NG$Z4MH2^p~V!cD{3BJGv)l#^@7c3r9KX(v-pH;2mhT-~oF96eJU3iF&; zf`*bxO72gaTjX?q9`{JkPITWI`@Wt1nQkGk3wQQu1ZoGlk8_iAM< zTXx&mDu#hW2S1@MjEtU8i~f@s+f`VV+-OT>M#VI-SyKxq_~$Egij*Xrbt&%kUS(d< z(nqLZ_ETkMO{Hc}sAliRUOAf|e;jNp@oc_@X9qWJt;}@#IHq`p6Xs}hw^imG$|-&Q zYEDV!Q!I>Ls?4a`Hd>(#bDxjK_rXSX4keeMU@h6mYK1*-5s(gO6GiLAV+W8v=nzF4 z1@st@5$I=%P8HA_KwNcrJF6q;Jp%d|koAy3(R+pC=PN+=Lmxt?DLz+l{td|QP+dJi z?-$S(AaSURqU{3O2V@X>gQ6YI=LvI6t_!M~Vai%Uu^z_KH{^lhj%!tVRLSVhc3!-i z6&~x)>c_mKb1&!WRlItBt-<1A1r~nU&QlZgX2MN>tXn`YW~%?f&TAAO`I?4t`$msH zLDkq$csBEI?2$74myGW}ar2ZR**dbI`u6gwPp)~Rr@Y(qam!Yk!c(vZt=tD4Z7BT~ z(opg(1kdaj0KS6GLe~h~L}2#~0InEgp;#$6gMv)}rb7z|IFEuI0G2{43Am7cTy$A) z?C5rJ>^+^zpi#IeNyP=%)vKGj!K=7wmEsAJRk))<(A&Z>^@;!8eqB8|_P7`A-(3U2G&Jxfp zkOAljMdu6XDIh;Ue^YdUfHpN_vY|E21YIO1XCQ;nQHr+S@#H-2@v93Px{@;;UmweU z*NEEZhf!zbkQ2?fcS^iN&AjseXlBEdTOG-kp=1@5nnIS_Y++^Y0kRMJfTH&a=xHEl cp}#2F=D3I_m(3^IJ@2y9zxtj!h&>tr00+cGkN^Mx diff --git a/packages/material-parser/test/fixtures/__snapshots__/test/generator/Generator.ts.md b/packages/material-parser/test/fixtures/__snapshots__/test/generator/Generator.ts.md deleted file mode 100644 index d01bf610e..000000000 --- a/packages/material-parser/test/fixtures/__snapshots__/test/generator/Generator.ts.md +++ /dev/null @@ -1,1135 +0,0 @@ -# Snapshot report for `test/generator/Generator.ts` - -The actual snapshot is saved in `Generator.ts.snap`. - -Generated by [AVA](https://avajs.dev). - -## generate multiple exported components - -> Snapshot 1 - - [ - { - manifestFilePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeBlank/manifest.json', - manifestObj: { - docUrl: '', - npm: { - destructuring: false, - exportName: '', - main: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js', - package: 'multiple-exported-component', - subName: '', - version: '1.0.0', - }, - props: [ - { - name: 'children', - propType: { - type: 'oneOfType', - value: [ - { - type: 'arrayOf', - value: 'node', - }, - 'node', - ], - }, - }, - { - name: 'styleBoxModel', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleLayout', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleBackground', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleFlexLayout', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'style', - propType: 'object', - }, - { - name: 'id', - propType: 'string', - }, - ], - screenshot: '', - title: 'multiple-exported-component', - }, - }, - { - manifestFilePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/manifest.json', - manifestObj: { - docUrl: '', - npm: { - destructuring: false, - exportName: '', - main: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js', - package: 'multiple-exported-component', - subName: '', - version: '1.0.0', - }, - props: [ - { - name: 'className', - propType: 'string', - }, - { - name: 'iconClassName', - propType: 'string', - }, - { - name: 'children', - propType: { - type: 'oneOfType', - value: [ - { - type: 'arrayOf', - value: 'node', - }, - 'node', - ], - }, - }, - { - name: 'styleBoxModel', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleText', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleBackground', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'style', - propType: 'object', - }, - ], - screenshot: '', - title: 'multiple-exported-component', - }, - }, - { - manifestFilePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeImage/manifest.json', - manifestObj: { - docUrl: '', - npm: { - destructuring: false, - exportName: '', - main: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js', - package: 'multiple-exported-component', - subName: '', - version: '1.0.0', - }, - props: [ - { - name: 'styleBoxModel', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'style', - propType: 'object', - }, - ], - screenshot: '', - title: 'multiple-exported-component', - }, - }, - { - manifestFilePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeLink/manifest.json', - manifestObj: { - docUrl: '', - npm: { - destructuring: false, - exportName: '', - main: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js', - package: 'multiple-exported-component', - subName: '', - version: '1.0.0', - }, - props: [ - { - name: 'children', - propType: { - type: 'oneOfType', - value: [ - { - type: 'arrayOf', - value: 'node', - }, - 'node', - ], - }, - }, - { - name: 'styleBoxModel', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleText', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleLayout', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleBackground', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'style', - propType: 'object', - }, - ], - screenshot: '', - title: 'multiple-exported-component', - }, - }, - { - manifestFilePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakePlaceholder/manifest.json', - manifestObj: { - docUrl: '', - npm: { - destructuring: false, - exportName: '', - main: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js', - package: 'multiple-exported-component', - subName: '', - version: '1.0.0', - }, - props: [ - { - name: 'children', - propType: { - type: 'oneOfType', - value: [ - { - type: 'arrayOf', - value: 'node', - }, - 'node', - ], - }, - }, - { - name: 'styleBoxModel', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleLayout', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'style', - propType: 'object', - }, - ], - screenshot: '', - title: 'multiple-exported-component', - }, - }, - { - manifestFilePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeText/manifest.json', - manifestObj: { - docUrl: '', - npm: { - destructuring: false, - exportName: '', - main: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js', - package: 'multiple-exported-component', - subName: '', - version: '1.0.0', - }, - props: [ - { - name: 'children', - propType: { - type: 'oneOfType', - value: [ - { - type: 'arrayOf', - value: 'node', - }, - 'node', - 'string', - ], - }, - }, - { - name: 'type', - propType: 'string', - }, - { - name: 'styleBoxModel', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleText', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleLayout', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleBackground', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'style', - propType: 'object', - }, - ], - screenshot: '', - title: 'multiple-exported-component', - }, - }, - { - manifestFilePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/Root/manifest.json', - manifestObj: { - docUrl: '', - npm: { - destructuring: false, - exportName: '', - main: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js', - package: 'multiple-exported-component', - subName: '', - version: '1.0.0', - }, - props: [ - { - name: 'style', - propType: 'object', - }, - { - name: 'children', - propType: { - type: 'oneOfType', - value: [ - 'element', - { - type: 'arrayOf', - value: 'element', - }, - ], - }, - }, - ], - screenshot: '', - title: 'multiple-exported-component', - }, - }, - ] - -## generate multiple exported components with extensions - -> Snapshot 1 - - [ - { - manifestFilePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeBlank/manifest.json', - manifestObj: { - docUrl: '', - npm: { - destructuring: false, - exportName: '', - main: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js', - package: 'multiple-exported-component', - subName: '', - version: '1.0.0', - }, - props: [ - { - name: 'children', - propType: { - type: 'oneOfType', - value: [ - { - type: 'arrayOf', - value: 'node', - }, - 'node', - ], - }, - }, - { - name: 'styleBoxModel', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleLayout', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleBackground', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleFlexLayout', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'style', - propType: 'object', - }, - { - name: 'id', - propType: 'string', - }, - ], - screenshot: '', - title: 'multiple-exported-component', - }, - }, - { - manifestFilePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeIcon/manifest.json', - manifestObj: { - docUrl: '', - npm: { - destructuring: false, - exportName: '', - main: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js', - package: 'multiple-exported-component', - subName: '', - version: '1.0.0', - }, - props: [ - { - name: 'className', - propType: 'string', - }, - { - name: 'iconClassName', - propType: 'string', - }, - { - name: 'children', - propType: { - type: 'oneOfType', - value: [ - { - type: 'arrayOf', - value: 'node', - }, - 'node', - ], - }, - }, - { - name: 'styleBoxModel', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleText', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleBackground', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'style', - propType: 'object', - }, - ], - screenshot: '', - title: 'multiple-exported-component', - }, - }, - { - manifestFilePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeImage/manifest.json', - manifestObj: { - docUrl: '', - npm: { - destructuring: false, - exportName: '', - main: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js', - package: 'multiple-exported-component', - subName: '', - version: '1.0.0', - }, - props: [ - { - name: 'styleBoxModel', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'style', - propType: 'object', - }, - ], - screenshot: '', - title: 'multiple-exported-component', - }, - }, - { - manifestFilePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeLink/manifest.json', - manifestObj: { - docUrl: '', - npm: { - destructuring: false, - exportName: '', - main: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js', - package: 'multiple-exported-component', - subName: '', - version: '1.0.0', - }, - props: [ - { - name: 'children', - propType: { - type: 'oneOfType', - value: [ - { - type: 'arrayOf', - value: 'node', - }, - 'node', - ], - }, - }, - { - name: 'styleBoxModel', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleText', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleLayout', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleBackground', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'style', - propType: 'object', - }, - ], - screenshot: '', - title: 'multiple-exported-component', - }, - }, - { - manifestFilePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakePlaceholder/manifest.json', - manifestObj: { - docUrl: '', - npm: { - destructuring: false, - exportName: '', - main: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js', - package: 'multiple-exported-component', - subName: '', - version: '1.0.0', - }, - props: [ - { - name: 'children', - propType: { - type: 'oneOfType', - value: [ - { - type: 'arrayOf', - value: 'node', - }, - 'node', - ], - }, - }, - { - name: 'styleBoxModel', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleLayout', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'style', - propType: 'object', - }, - ], - screenshot: '', - title: 'multiple-exported-component', - }, - }, - { - manifestFilePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/AIMakeText/manifest.json', - manifestObj: { - docUrl: '', - npm: { - destructuring: false, - exportName: '', - main: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js', - package: 'multiple-exported-component', - subName: '', - version: '1.0.0', - }, - props: [ - { - name: 'children', - propType: { - type: 'oneOfType', - value: [ - { - type: 'arrayOf', - value: 'node', - }, - 'node', - 'string', - ], - }, - }, - { - name: 'type', - propType: 'string', - }, - { - name: 'styleBoxModel', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleText', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleLayout', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleBackground', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'style', - propType: 'object', - }, - ], - screenshot: '', - title: 'multiple-exported-component', - }, - }, - { - manifestFilePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/src/basic/Root/manifest.json', - manifestObj: { - docUrl: '', - npm: { - destructuring: false, - exportName: '', - main: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js', - package: 'multiple-exported-component', - subName: '', - version: '1.0.0', - }, - props: [ - { - name: 'style', - propType: 'object', - }, - { - name: 'children', - propType: { - type: 'oneOfType', - value: [ - 'element', - { - type: 'arrayOf', - value: 'element', - }, - ], - }, - }, - ], - screenshot: '', - title: 'multiple-exported-component', - }, - }, - ] - -## generate single exported components - -> Snapshot 1 - - [ - { - manifestFilePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/single-exported-component/es/manifest.json', - manifestObj: { - docUrl: '', - npm: { - destructuring: false, - exportName: '', - main: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/single-exported-component/es/index.js', - package: 'single-exported-component', - subName: '', - version: '1.0.0', - }, - props: [ - { - name: 'optionalArray', - propType: 'array', - }, - { - name: 'optionalBool', - propType: 'bool', - }, - { - name: 'optionalFunc', - propType: 'func', - }, - { - defaultValue: 123, - name: 'optionalNumber', - propType: 'number', - }, - { - name: 'optionalObject', - propType: 'object', - }, - { - name: 'optionalString', - propType: 'string', - }, - { - name: 'optionalSymbol', - propType: 'symbol', - }, - { - name: 'optionalNode', - propType: 'node', - }, - { - name: 'optionalElement', - propType: 'element', - }, - { - name: 'optionalElementType', - propType: 'elementType', - }, - { - name: 'optionalMessage', - propType: { - type: 'instanceOf', - value: 'Demo', - }, - }, - { - name: 'optionalEnum', - propType: { - type: 'oneOf', - value: [ - 'News', - 'Photos', - ], - }, - }, - { - name: 'optionalUnion', - propType: { - type: 'oneOfType', - value: [ - 'string', - 'number', - { - type: 'instanceOf', - value: 'Demo', - }, - ], - }, - }, - { - name: 'optionalArrayOf', - propType: { - type: 'arrayOf', - value: 'number', - }, - }, - { - name: 'optionalObjectOf', - propType: { - type: 'objectOf', - value: 'number', - }, - }, - { - name: 'optionalObjectWithShape', - propType: { - type: 'shape', - value: [ - { - name: 'optionalProperty', - propType: 'string', - }, - { - name: 'requiredProperty', - propType: { - isRequired: true, - type: 'number', - }, - }, - ], - }, - }, - { - name: 'optionalObjectWithShape2', - propType: { - isRequired: true, - type: 'shape', - value: [ - { - name: 'optionalProperty', - propType: 'string', - }, - { - name: 'requiredProperty', - propType: { - isRequired: true, - type: 'number', - }, - }, - ], - }, - }, - { - name: 'optionalObjectWithStrictShape', - propType: { - type: 'exact', - value: [ - { - name: 'optionalProperty', - propType: 'string', - }, - { - name: 'requiredProperty', - propType: { - isRequired: true, - type: 'number', - }, - }, - ], - }, - }, - { - name: 'requiredFunc', - propType: { - isRequired: true, - type: 'func', - }, - }, - { - name: 'requiredAny', - propType: { - isRequired: true, - type: 'any', - }, - }, - ], - screenshot: '', - title: 'single-exported-component', - }, - }, - ] - -## generate single exported components with extensions - -> Snapshot 1 - - [ - { - manifestFilePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/single-exported-component/src/manifest.json', - manifestObj: { - docUrl: '', - npm: { - destructuring: false, - exportName: '', - main: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/single-exported-component/es/index.js', - package: 'single-exported-component', - subName: '', - version: '1.0.0', - }, - props: [ - { - name: 'optionalArray', - propType: 'array', - }, - { - name: 'optionalBool', - propType: 'bool', - }, - { - name: 'optionalFunc', - propType: 'func', - }, - { - defaultValue: 123, - name: 'optionalNumber', - propType: 'number', - }, - { - name: 'optionalObject', - propType: 'object', - }, - { - name: 'optionalString', - propType: 'string', - }, - { - name: 'optionalSymbol', - propType: 'symbol', - }, - { - name: 'optionalNode', - propType: 'node', - }, - { - name: 'optionalElement', - propType: 'element', - }, - { - name: 'optionalElementType', - propType: 'elementType', - }, - { - name: 'optionalMessage', - propType: { - type: 'instanceOf', - value: 'Demo', - }, - }, - { - name: 'optionalEnum', - propType: { - type: 'oneOf', - value: [ - 'News', - 'Photos', - ], - }, - }, - { - name: 'optionalUnion', - propType: { - type: 'oneOfType', - value: [ - 'string', - 'number', - { - type: 'instanceOf', - value: 'Demo', - }, - ], - }, - }, - { - name: 'optionalArrayOf', - propType: { - type: 'arrayOf', - value: 'number', - }, - }, - { - name: 'optionalObjectOf', - propType: { - type: 'objectOf', - value: 'number', - }, - }, - { - name: 'optionalObjectWithShape', - propType: { - type: 'shape', - value: [ - { - name: 'optionalProperty', - propType: 'string', - }, - { - name: 'requiredProperty', - propType: { - isRequired: true, - type: 'number', - }, - }, - ], - }, - }, - { - name: 'optionalObjectWithShape2', - propType: { - isRequired: true, - type: 'shape', - value: [ - { - name: 'optionalProperty', - propType: 'string', - }, - { - name: 'requiredProperty', - propType: { - isRequired: true, - type: 'number', - }, - }, - ], - }, - }, - { - name: 'optionalObjectWithStrictShape', - propType: { - type: 'exact', - value: [ - { - name: 'optionalProperty', - propType: 'string', - }, - { - name: 'requiredProperty', - propType: { - isRequired: true, - type: 'number', - }, - }, - ], - }, - }, - { - name: 'requiredFunc', - propType: { - isRequired: true, - type: 'func', - }, - }, - { - name: 'requiredAny', - propType: { - isRequired: true, - type: 'any', - }, - }, - ], - screenshot: '', - title: 'single-exported-component', - }, - }, - ] diff --git a/packages/material-parser/test/fixtures/__snapshots__/test/generator/Generator.ts.snap b/packages/material-parser/test/fixtures/__snapshots__/test/generator/Generator.ts.snap deleted file mode 100644 index 6da53d5f152c86f2701007e5968f40882d74f2c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6077 zcmW+)c|6nqA9oC!W8@}tB+M=6a*te7%zY%+H@S}#axtNaoCy zQ0~YX`hEKCkJsz5_v`g~zh1BB^ZojKwl~rqDQXks5pu^T_^xQUGBX{Gx4!-uvKuwB z@Ufv-dxn2nBn?dS{}25}A>eU}q1pa&hxZW#pQikX_cA-@ir&>6opO2Hg zADT#{tCcM{2EVL*;DG+X5JKA~BlB?G0Qsibjp0o~pQOy;>8+6g)s<2m3D&^*w4q&H zp#lx>T$N|f2I3|4xWqoBT-mr$U9wih@b{}4{?6FLO59Ju3ug|qIhpb+wR*yVN3nAh zH_JGYb~$;Z_~{<;TvAMn^c~B?Hi3<4rbn(L%X^D=R7cz_dAN4If7Y;Ihy0!W+tt~= zakhEWFF51(IJ*Ydw`(V*FVxNi|IQvZiSRRqQm&wxH<{A(OS?4;N;a&lUlzRjJaOH_ z!{Z8C_``T`Y8~^2glhs}3b-!!yj<(+ zmsW4WZIB{vs6kI#9d3G`MH9j)e;5bOL$tfddMnJ+gdN+t-ZQnXZ*zEJvqaMGb56ez^VO;2I-4g5iMbddd@+E}oGv$%Gk;Zv5 zUcfviu>Tl$UEbfVZSwm~E2)aw*PCjUv1!9a*Hee)E%XIdn^?`@%If$!C;gOinK-*W4sqMNgw z2H7KeoMJ~OD~0d&JF%sPC=(~oHE0sg1lxOmxXaw5BQyNo14lBG?H*4J9Sygd{0%OC z4r))7?a<>4rcIsSH|Ju8ENWb z>7aYQ=qXk9`5Agj_d52jkpYhgs^~%?<)+@-=WZ)fPZ@3Ap_9Lu`6-;rM7^2()cK2) zJ3{u$oeO5p9d}pn)gq|-lD;@Qv}jUgC~;waH!(3`e)j*w9YCz!14N&e)jQ3cT%T6W zC4u)Xg72d_Hw+O{R>JS)Q+GJxUclLl)y;(8kD2XoJTlv1^|--S9Qa^aax!Im>Ebj; zRQJpMp7#!diHhHAw#{?(ECREa9)Fp*d9%MbX2i0mfq_YA7jxk*m<$cq{Y zH|{3?7m;A$*v+v^>aHBp&);3ZYx_y(I7Y{HO8Nk7)X73p8)La}*` zj-i$Hg-OXOtE}+44wZW6$5wiYq2Ln(Vph7~G%gb~Oq4F`zO;G;-sR3i>Q-58MTcXH zd>eF2j@894^50Y~8NFf*WAy^%A&I@|$NV_zyts4Vhu3okmmze)C8Lt*Q;aCd;m@lZ z>6)-UdUqXCvWia% z75p$~K`0bxfZ;6MSxMnuqfY2$>|p&A)+)kql1bt7YTUd5t$6QBBqAzDQeLcuPts6eZe z%vk2l03*VIlAi)M?LZ0jQu^@)90~v2zDH%12R=(kQnf6zg&kNhi)4p_KOe5Kuyvns zQtZXno>jP*?(r#>LJREWwzVKNj^zUPUo6)qA|42qy?E%dCT+Uvn-G-$c2s6>x7q(R zX>u8CG6j)XwzhdUI$pK*lla&QPE>XCc3Cr*-7^x{`Lo0_cgvUNXeLr%=WXo52j&&q zlXrB#jSIUjyl{Oz=Jfy>tiEU6cD*N1UH2L(u(8Qshrv`Q^?n$Eug<>>G2`j*cI;{2 z^=H|3dx_Tv@)nb~)BMgGVDGA_C+Sx0y5-NBulgDmx*cCCf60z?qHP@U<0uivhSIr|Q8|pS`I>(W6m69+OTM&v5uQy6b)h2&ZxGK!cX&>+;uH_uFJbRYe`pQK7p zKV{>0-k555DdB$oRHBuJVI+@GG4-l(8)%8ybX}iN$lt((Ytq?*eHx@n zHd8`DE_kYLy5Q5qBhZX8T&=)r7tf7J@l{K)($J3-UN571q(|}gF>qv?5ybf$xNt%4 z+N4LGqmyXfglqMh`Bn$WBW~b;XrDbb@h@w$NSM6%oqJ+mV4@%?qVn$fPuztyqervK z!|nnXt}3YEz(*rRrM80nLk!D7^Moj)uLWm+9|DmxSLH}N^I*&8j z>gA9ocqq}K!vv?Dx4GvJ)=MDbUY8en*7KavX`0_}cfYOXr`pFyACpGB+3+SS=eoGR zSkF$Q-4kM6KzvThjk70y1Ri6Et{RwvehlB&`~q>ecxY@O zz#@#Nf{bsldx=k&5H}|7=)n2(V;oQ$gS={Z;4x2{9ellu*9N)1qMrC`CGLJnokm&E zE=}lO9u2v7T!DSJJ{?w8p5NxYFxN;fe;U~2eYc^#H=6EDo-RX`suvw2|2SH{9qc~y8OzScez;Xyf2SaMIo4hLw2p3F z{wfn*h{3@(r>$xdk&rn}$)rK;mD?2&&>zap$1!d7pI-Pq$A${17K?CuZI!IDF9j)K z?I+WSYsCQ|6Q7*6rPU#Q->ar9$5}S}ngLMU!aS|B*Vd;guouhWL;FedMkEEHNbmI9 z=Jk4pi+FK5!yO=3mOmTLn}T%q67JYLgY+rl#ZI+lqa*AYaaA4q#C5gBe?!pZlcSTO z&A0@5ZK5a8?+OlLD3ezjk%<&Y>dx1^^&sd+7}lZ&Lu=(ZXR3@19b!+%xu#1cxdrn+A&(bdw>bP|=^_~lp znbhp_+oa?5uf-R9wstN4@b#~@+PzEIiF#BTC2WtS3(Q1Ml75ldx#f7D`OEsdVbv&!WE^bLC7qIepuNhVCaW7YQo@>`nJxF~!=Fq%o^7>`njjAx-wTVen zY(t1oan-lJQGxN}bmGgQ#>VKP_cvBmDQ4w|tZSsc^;@lDcS6j%)O4p6?8$l^4UaJE zusx+~bu(h~WD%i{y4|u&9bF+oM;g%b!Bl)S=)htt3*C*Gtnbry+Gu0$6WrD%)iwne zC50M~{#f~NUfE9)CzokX94MUCwZRY2SYqP8Xhyq*U&bkR*g1Q#^ncDuQl+^eE}hdh z870T9lV?Z_e6x{ni>KVIS-l#S81byE34L=pqC7`|!@OWvB}=UZ>Nc~t6svI8s)R*{ zD*RjaU^zJVz}D|>dBaDMBfaN}=VOoW1oG|3?#&@qr^XBI;a`3RHtn;%o}7LYxR0wN zudVf5m)d-_Ee-E-v0ySMxY<5GaXd`g&;zLd(_Rsw<0WPN_* zY2$pAJHCUq)XLLbiUHJPzM+dvBJeKfw{6WE)KLR!+@>R9(qfWL+k4;Td|Qht_nFQC zzr|#V1h%`@T$~DTGl=_n?WpYUh~oX83Aa^FaR*xFVO0#z?>BbUmKy=UulnbucKgN8 zsvQkpA}x;(q$gVAHt#=S${qGoF`j{XNg<4g>x%yOdOWI;#zJMadMgOthr)7Y)KTZT z%UU|8g6Z@vXwRj%*velK86kg;up=t_Vg=u-w&ZGZZ|(jVyi{=UU4>0;?!7WLeuKa1 z%zw0(^mg2W-Jkj`4O6qOm7VJ8QYuj)77$mMLyMxhT@ zWso+%zFpl0-Gi(%mX8uZ5?Vx124M*`?0R)esTur@d|R8APoKM;a}$=AOwS ziLnmRa|8*~`%_rv)wYEvm>yxbIs`%l4t*eyU0cl8Do$IsD$oqU7V|I%HOz&Q@Of+v zX~ElKp5&m=@nxKhsme!4Tvp488qFR^5iTDz!!xyWsxtQ>lv3Ovobk|m@`njPUWTR0!`3dKpnva=UqD7%xQc9C z+93?6l^@479}GlGKFLfLP5T%193i6pqcI21Htq(Qie~{3AX5M!#~mPo_iSu2uiO>9 z6THZ%VPo+1j+A+GSBW3oNpcv}`ZUAzt|Kg_{zI~sWED*{LYW9|rW(8jnVzs=RodGTyB zQuHH0MmMsTssAh)4|O<;Bmtqz!}Hu>HVnYcnG<G74r##YS z&Lsq?lkGmhptfF44lVt)_E`~#@)mL@?B1^%+dLe^Ok`qG>CP^c1ZbODJKA1ae9W<84QI4FBT&ms;R>YM`Sb9-Y-p5F&oh4eek{0y*H ze7jWH7|weE(JOBVa?mQE{ugwaX!U6addE*^tC|&d!c|GUH{j)|W1yaJ08~pYJAQby!>ky>Xxv>JOK&EcJgRUr5%hEEiS=a?~A%3 z1EI%>Zu>*5eT6^e$fO^ zCD;H%e}^C7&@LLln9^~%x>iigq~mhjtcMGoSStRl)YkAIT|fXIVX8MWWf4d2WI)X> z*h_3}%Svo1p?kH~=X+$MIMBWNutrM$f`)nB6 zJ-haT+^Knl zfc}d-;<>oJ3sot;NlOo$33VL9d}Q40f(N_@nDPzG*}90!K9VtD&l=D`4Ithim#XGIYc0;q`0o*^w48ZXF1-;mZ< z_9bvLpws;mw~q1bK#kfsI;Enbh-Tm-aQh$I+BiLZdZ1QI_#{3FSm*Bx-PQ!wm2is* z!?&>kvmUYVUUwS3t!kQw=d^*8Um3la5R@UU-)0gQIZBE75fcs#WJ4k_ZGSDsI^=!)7xa zj4{suU`_CqbXowgZU#rfK0lk0`{O+MhGz7a0TUHG;<{ zf&iQ&;ISQmUNC^0Q~H5GakMT|sd$;I+pI^W)Hty*w5=uDJ}i*rhxN7_AFFVU+pSt% z<@N6wY<1k6un8j`m+q1~A6O)Pz;L_HdPpY8h43kEg~)+);NO;DpOUL-D(9DAK}ppN zWLoI<4m3U~M9@b|>!ICuSn@c$q}n{A5+mr;?}v+M-c9}vJA3^dHnwJ9D)a-WRftJK zWME|l7KGX1M7#&O1urRP0*tRiB+l~#J+m7|g2 Snapshot 1 + + [ + { + componentName: 'AIMakeBlank', + docUrl: '', + npm: { + destructuring: false, + exportName: 'AIMakeBlank', + main: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js', + package: 'multiple-exported-component', + subName: '', + version: '1.0.0', + }, + props: [ + { + name: 'children', + propType: { + type: 'oneOfType', + value: [ + { + type: 'arrayOf', + value: 'node', + }, + 'node', + ], + }, + }, + { + name: 'styleBoxModel', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'styleLayout', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'styleBackground', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'styleFlexLayout', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'style', + propType: 'object', + }, + { + name: 'id', + propType: 'string', + }, + ], + screenshot: '', + title: 'multiple-exported-component', + }, + { + componentName: 'AIMakeIcon', + docUrl: '', + npm: { + destructuring: false, + exportName: 'AIMakeIcon', + main: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js', + package: 'multiple-exported-component', + subName: '', + version: '1.0.0', + }, + props: [ + { + name: 'className', + propType: 'string', + }, + { + name: 'iconClassName', + propType: 'string', + }, + { + name: 'children', + propType: { + type: 'oneOfType', + value: [ + { + type: 'arrayOf', + value: 'node', + }, + 'node', + ], + }, + }, + { + name: 'styleBoxModel', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'styleText', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'styleBackground', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'style', + propType: 'object', + }, + ], + screenshot: '', + title: 'multiple-exported-component', + }, + { + componentName: 'AIMakeImage', + docUrl: '', + npm: { + destructuring: false, + exportName: 'AIMakeImage', + main: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js', + package: 'multiple-exported-component', + subName: '', + version: '1.0.0', + }, + props: [ + { + name: 'styleBoxModel', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'style', + propType: 'object', + }, + ], + screenshot: '', + title: 'multiple-exported-component', + }, + { + componentName: 'AIMakeLink', + docUrl: '', + npm: { + destructuring: false, + exportName: 'AIMakeLink', + main: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js', + package: 'multiple-exported-component', + subName: '', + version: '1.0.0', + }, + props: [ + { + name: 'children', + propType: { + type: 'oneOfType', + value: [ + { + type: 'arrayOf', + value: 'node', + }, + 'node', + ], + }, + }, + { + name: 'styleBoxModel', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'styleText', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'styleLayout', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'styleBackground', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'style', + propType: 'object', + }, + ], + screenshot: '', + title: 'multiple-exported-component', + }, + { + componentName: 'AIMakePlaceholder', + docUrl: '', + npm: { + destructuring: false, + exportName: 'AIMakePlaceholder', + main: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js', + package: 'multiple-exported-component', + subName: '', + version: '1.0.0', + }, + props: [ + { + name: 'children', + propType: { + type: 'oneOfType', + value: [ + { + type: 'arrayOf', + value: 'node', + }, + 'node', + ], + }, + }, + { + name: 'styleBoxModel', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'styleLayout', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'style', + propType: 'object', + }, + ], + screenshot: '', + title: 'multiple-exported-component', + }, + { + componentName: 'AIMakeText', + docUrl: '', + npm: { + destructuring: false, + exportName: 'AIMakeText', + main: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js', + package: 'multiple-exported-component', + subName: '', + version: '1.0.0', + }, + props: [ + { + name: 'children', + propType: { + type: 'oneOfType', + value: [ + { + type: 'arrayOf', + value: 'node', + }, + 'node', + 'string', + ], + }, + }, + { + name: 'type', + propType: 'string', + }, + { + name: 'styleBoxModel', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'styleText', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'styleLayout', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'styleBackground', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'style', + propType: 'object', + }, + ], + screenshot: '', + title: 'multiple-exported-component', + }, + { + componentName: 'Root', + docUrl: '', + npm: { + destructuring: false, + exportName: 'Root', + main: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js', + package: 'multiple-exported-component', + subName: '', + version: '1.0.0', + }, + props: [ + { + name: 'style', + propType: 'object', + }, + { + name: 'children', + propType: { + type: 'oneOfType', + value: [ + 'element', + { + type: 'arrayOf', + value: 'element', + }, + ], + }, + }, + ], + screenshot: '', + title: 'multiple-exported-component', + }, + ] + +## materialize multiple exported component by online + +> Snapshot 1 + + [ + { + componentName: 'AIMakeBlank', + docUrl: '', + npm: { + destructuring: false, + exportName: 'AIMakeBlank', + main: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/node_modules/.temp/2pkTyFCp5tZHW8cKqMH71Z/node_modules/@ali/aimake-basic/es/index.js', + package: '@ali/aimake-basic', + subName: '', + version: '0.1.0', + }, + props: [ + { + name: 'children', + propType: { + type: 'oneOfType', + value: [ + { + type: 'arrayOf', + value: 'node', + }, + 'node', + ], + }, + }, + { + name: 'styleBoxModel', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'styleLayout', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'styleBackground', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'styleFlexLayout', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'style', + propType: 'object', + }, + { + name: 'id', + propType: 'string', + }, + ], + screenshot: '', + title: '@ali/aimake-basic', + }, + { + componentName: 'AIMakeIcon', + docUrl: '', + npm: { + destructuring: false, + exportName: 'AIMakeIcon', + main: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/node_modules/.temp/2pkTyFCp5tZHW8cKqMH71Z/node_modules/@ali/aimake-basic/es/index.js', + package: '@ali/aimake-basic', + subName: '', + version: '0.1.0', + }, + props: [ + { + name: 'className', + propType: 'string', + }, + { + name: 'iconClassName', + propType: 'string', + }, + { + name: 'children', + propType: { + type: 'oneOfType', + value: [ + { + type: 'arrayOf', + value: 'node', + }, + 'node', + ], + }, + }, + { + name: 'styleBoxModel', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'styleText', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'styleBackground', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'style', + propType: 'object', + }, + ], + screenshot: '', + title: '@ali/aimake-basic', + }, + { + componentName: 'AIMakeImage', + docUrl: '', + npm: { + destructuring: false, + exportName: 'AIMakeImage', + main: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/node_modules/.temp/2pkTyFCp5tZHW8cKqMH71Z/node_modules/@ali/aimake-basic/es/index.js', + package: '@ali/aimake-basic', + subName: '', + version: '0.1.0', + }, + props: [ + { + name: 'styleBoxModel', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'style', + propType: 'object', + }, + ], + screenshot: '', + title: '@ali/aimake-basic', + }, + { + componentName: 'AIMakeLink', + docUrl: '', + npm: { + destructuring: false, + exportName: 'AIMakeLink', + main: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/node_modules/.temp/2pkTyFCp5tZHW8cKqMH71Z/node_modules/@ali/aimake-basic/es/index.js', + package: '@ali/aimake-basic', + subName: '', + version: '0.1.0', + }, + props: [ + { + name: 'children', + propType: { + type: 'oneOfType', + value: [ + { + type: 'arrayOf', + value: 'node', + }, + 'node', + ], + }, + }, + { + name: 'styleBoxModel', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'styleText', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'styleLayout', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'styleBackground', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'style', + propType: 'object', + }, + ], + screenshot: '', + title: '@ali/aimake-basic', + }, + { + componentName: 'AIMakePlaceholder', + docUrl: '', + npm: { + destructuring: false, + exportName: 'AIMakePlaceholder', + main: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/node_modules/.temp/2pkTyFCp5tZHW8cKqMH71Z/node_modules/@ali/aimake-basic/es/index.js', + package: '@ali/aimake-basic', + subName: '', + version: '0.1.0', + }, + props: [ + { + name: 'children', + propType: { + type: 'oneOfType', + value: [ + { + type: 'arrayOf', + value: 'node', + }, + 'node', + ], + }, + }, + { + name: 'styleBoxModel', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'styleLayout', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'style', + propType: 'object', + }, + ], + screenshot: '', + title: '@ali/aimake-basic', + }, + { + componentName: 'AIMakeText', + docUrl: '', + npm: { + destructuring: false, + exportName: 'AIMakeText', + main: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/node_modules/.temp/2pkTyFCp5tZHW8cKqMH71Z/node_modules/@ali/aimake-basic/es/index.js', + package: '@ali/aimake-basic', + subName: '', + version: '0.1.0', + }, + props: [ + { + name: 'children', + propType: { + type: 'oneOfType', + value: [ + { + type: 'arrayOf', + value: 'node', + }, + 'node', + 'string', + ], + }, + }, + { + name: 'type', + propType: 'string', + }, + { + name: 'styleBoxModel', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'styleText', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'styleLayout', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'styleBackground', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'style', + propType: 'object', + }, + ], + screenshot: '', + title: '@ali/aimake-basic', + }, + { + componentName: 'Root', + docUrl: '', + npm: { + destructuring: false, + exportName: 'Root', + main: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/node_modules/.temp/2pkTyFCp5tZHW8cKqMH71Z/node_modules/@ali/aimake-basic/es/index.js', + package: '@ali/aimake-basic', + subName: '', + version: '0.1.0', + }, + props: [ + { + name: 'style', + propType: 'object', + }, + { + name: 'children', + propType: { + type: 'oneOfType', + value: [ + 'element', + { + type: 'arrayOf', + value: 'element', + }, + ], + }, + }, + ], + screenshot: '', + title: '@ali/aimake-basic', + }, + ] + +## materialize single exported component by local + +> Snapshot 1 + + [ + { + componentName: 'Demo', + docUrl: '', + npm: { + destructuring: false, + exportName: 'Demo', + main: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/single-exported-component/es/index.js', + package: 'single-exported-component', + subName: '', + version: '1.0.0', + }, + props: [ + { + name: 'optionalArray', + propType: 'array', + }, + { + name: 'optionalBool', + propType: 'bool', + }, + { + name: 'optionalFunc', + propType: 'func', + }, + { + defaultValue: 123, + name: 'optionalNumber', + propType: 'number', + }, + { + name: 'optionalObject', + propType: 'object', + }, + { + name: 'optionalString', + propType: 'string', + }, + { + name: 'optionalSymbol', + propType: 'symbol', + }, + { + name: 'optionalNode', + propType: 'node', + }, + { + name: 'optionalElement', + propType: 'element', + }, + { + name: 'optionalElementType', + propType: 'elementType', + }, + { + name: 'optionalMessage', + propType: { + type: 'instanceOf', + value: 'Demo', + }, + }, + { + name: 'optionalEnum', + propType: { + type: 'oneOf', + value: [ + 'News', + 'Photos', + ], + }, + }, + { + name: 'optionalUnion', + propType: { + type: 'oneOfType', + value: [ + 'string', + 'number', + { + type: 'instanceOf', + value: 'Demo', + }, + ], + }, + }, + { + name: 'optionalArrayOf', + propType: { + type: 'arrayOf', + value: 'number', + }, + }, + { + name: 'optionalObjectOf', + propType: { + type: 'objectOf', + value: 'number', + }, + }, + { + name: 'optionalObjectWithShape', + propType: { + type: 'shape', + value: [ + { + name: 'optionalProperty', + propType: 'string', + }, + { + name: 'requiredProperty', + propType: { + isRequired: true, + type: 'number', + }, + }, + ], + }, + }, + { + name: 'optionalObjectWithShape2', + propType: { + isRequired: true, + type: 'shape', + value: [ + { + name: 'optionalProperty', + propType: 'string', + }, + { + name: 'requiredProperty', + propType: { + isRequired: true, + type: 'number', + }, + }, + ], + }, + }, + { + name: 'optionalObjectWithStrictShape', + propType: { + type: 'exact', + value: [ + { + name: 'optionalProperty', + propType: 'string', + }, + { + name: 'requiredProperty', + propType: { + isRequired: true, + type: 'number', + }, + }, + ], + }, + }, + { + name: 'requiredFunc', + propType: { + isRequired: true, + type: 'func', + }, + }, + { + name: 'requiredAny', + propType: { + isRequired: true, + type: 'any', + }, + }, + ], + screenshot: '', + title: 'single-exported-component', + }, + ] + +## materialize single exported component by online + +> Snapshot 1 + + [] + +## ts component by local + +> Snapshot 1 + + [ + { + componentName: 'App', + docUrl: '', + npm: { + destructuring: false, + exportName: 'App', + main: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/ts-component/src/index.tsx', + package: '@ali/lowcode-engine-material-parser', + subName: '', + version: '0.1.0', + }, + props: [ + { + name: 'str', + propType: 'string', + }, + { + name: 'num', + propType: { + isRequired: true, + type: 'number', + }, + }, + { + name: 'any', + propType: { + isRequired: true, + type: 'any', + }, + }, + { + name: 'bool', + propType: { + isRequired: true, + type: 'bool', + }, + }, + { + name: 'tuple', + propType: { + isRequired: true, + type: 'oneOf', + value: [ + 1, + 'str', + true, + ], + }, + }, + { + name: 'enum', + propType: { + isRequired: true, + type: 'oneOfType', + value: [ + 'red', + 'yellow', + 'green', + ], + }, + }, + { + name: 'arr', + propType: { + isRequired: true, + type: 'arrayOf', + }, + }, + { + name: 'obj', + propType: { + isRequired: true, + type: 'shape', + value: [ + { + name: 'a', + propType: { + isRequired: true, + type: 'number', + }, + }, + ], + }, + }, + { + name: 'objOf', + propType: { + isRequired: true, + type: 'objectOf', + value: 'number', + }, + }, + { + name: 'exact', + propType: { + isRequired: true, + type: 'shape', + value: [ + { + name: 'a', + propType: { + isRequired: true, + type: 'number', + }, + }, + ], + }, + }, + { + name: 'empty', + propType: { + isRequired: true, + type: 'object', + }, + }, + { + name: 'node', + propType: 'ReactReactNode', + }, + { + name: 'element', + propType: 'JSX.Element', + }, + { + name: 'elementType', + propType: 'ReactElementType', + }, + { + name: 'instance', + propType: { + isRequired: true, + type: 'instanceOf', + value: 'Props', + }, + }, + ], + screenshot: '', + title: '@ali/lowcode-engine-material-parser', + }, + ] diff --git a/packages/material-parser/test/fixtures/__snapshots__/test/index.ts.snap b/packages/material-parser/test/fixtures/__snapshots__/test/index.ts.snap new file mode 100644 index 0000000000000000000000000000000000000000..d32172df21e4b6ae8aa72a6bdfdf72b1a51c8d38 GIT binary patch literal 6148 zcmYLNby$<#`==)j(kV(f6eLH7NT&lfO27e9qq}49B2o&n0d9apasvq|5d?;UG9+b$ zq{^fuq)~+5-uL^*@42q~e4gjrea?Md=RS{~ot~I&pj&X5Pf)m6q#_dyRkR98vhT&- zm&Kh3j?6ZcMPy6jJ`mG za)#-fwikEk4fIwHT@7Z)m#sPI3K9+@(mXj)hPSP`Io%@q`Six=6SOnCd!9+;|G21# znUGK0s7}xKLQ@Hk>|@R>Ob1@U+B&{9zX~EY#Dru4(>Nt3=r?> z9?j(5OK*^FSRbp8|M*Ewnk)G(fU%@xgqBMu;lXRlEXg+8*AaP!LHk%5@SV-F zDt|Vp@;T^dOD{7k|HURLDXCy7^Vz3J%Bs9$T+?P!Vkp;p?p^t%{e z#W%{FL|AC3;%5nYONq}Cgbbhham5@R!+cl^YA(Pop9J~@4%|z`cMd`V#l0TjhSdh# zex31fJ*^pMA+X2xOgn9n_tKf+2{rAS{*l*l+?&c87E-lg4~NOMKfKpmyb2AUp)IOs zoxBvtMK`uo(uW}Ea*O6JG0RsQ zS?cI9grQ|n@Fii|>RweWgTXq#IsHq$>tL$iYiIXtR;QmLc$090>!A>S7aq1xgQo?vFDdVt_%r%S5_~M@s#p&L=l_{yjxJ{y(&$AyTU;yw0F}&o_Lab zV^P>HpRXDKKMN-|3uQO6cuIM@b`U&6i&zVUI|&H)m|GTpi{W9CQoKu3v%r{>34d7- z^v6hr>=iOj#BAvIleM}cJ3s2NL&**HBKziHe4XxThf7!|an33%W=^0kzg>i-Lw;oz zdoICh^fC2Mh2Bf8lT_uJe8AkgLQNqc-8?mKZ@FXwhSYj(C74|RU^h)w*jv6k0jtxR zxoYzp8nbKXEAJ}WWiDuu3z#-f&DdMk%-i!fP35a3Jcw!JI^scd#{?sli*B$linFTZ zPq}R|ummy~mw()-udeMp;sgHn83--U5FEsnV=btTZ9tj$H-}&qM7tgG?7TmcbdSttRX;D-c^QbhHS6_8UW$aI z3~%=(et_j2@4e41U`s5o{h9ev^|h=uDLROhsDd$sKvXRY?$oPe`{3MD#kb5E_jJbZ z=E#98RUr<}9;^jS?e(8Ou^n}0EG~)IS?dh1aQqFeAeCqQFve{L%DTB=jF~&Ofra5F zyi*aeEn}N@sJmS4@QTmnY4i2(f-mv4)j|slK>1yuKld!iXN01gLY{lEFNnh?p191K z*kW9p&|V8WNWDajlzZ0{AobhI6!rViq3v&z9WhP#E00Yimq*=+etpZeE;G|a&El`0 z$xcE4*x#H@;@acZyyDsve&PQ8Q@udB7yr*~^79gIyWwmNcw~MS8(V|VCY50mtB_0g z;7gW<(5`pkacQ$|HzIc2t$i$`)4p}3Wxj-lme3+Lmv0}@cAwIRn@9m(J=iW%y+o9U zRl{#2eWCVboG~IPTP*;{9ItPaEUbomW8zeRrdQ$SR^|kq&7;B zd|>67-&60{8&h7b+vK%sGTOG@?QoZ=>Aa@*F!gRJZbGc&73`q%j?ml0{8i1N&K3=) z)D}#iT_c&jF)cmuEGhggz|CWJq||<^;MzpYwjvM%wh*Lk_P_9 z{capasnP~rj~An}a_eUl=7_JRS(O&P9>mv-18>eh5>P1|mVWZ0vK;9BC|qL4DRU?$ zEbO@Ck;Bg4M<38}JN7^Qx4Z9`#UG~aL7fCo@xb9fB$-kBqS@>6C(0+rg0rB?u(+mC zY%#Tf?4vIaZU5X^XBUP94B^=C#L)e$fX7*B)01UBT3m+%tYniXm@TT|-ifO$Wb4K( zyvwaWBkIfR)0c$DEZGWo_Y_wAavtoQrZy-ZUA7xY^Ex*S7JM{QcK9~IFRny8r*7Te+B8X?p ziH$V=0OM;Zx=#r;rcMJBx07H8TGTy#yOu2}@V9j8aU>#TX z695u3A9WDrr}A1eT)t{rmPNZFy+|^NIZtNceAveV6?uS8a!3XuIyJWxLy~74hZguZ#Gs7n)nU~T&#MpJQB07JSY1j zcj{vr!Yd$3yrh-;xGtxWKf6jm#auedPi;*2oZE*j?!C&0`hoJIkFDfegrLt9(Vh0w zmklEgzc+a*_kcPpArizkcj0pbYjhrbAltm>H+x}zYE@Wciw4Q$g5q4Soy5a(6rP+(jybujlCX8y&R zWzuHx>XCuet#&|iGgiDl2QW6YM(sRj%D2>>I=ig1+qlXUuRVkQanVV;zH>ethC5d` zd0)938O$azku@C>;d;5S;?Kpv3ByL(<&}R18C7J$BgfSl!*$kI5-4@?ksZ`5@S7 ze~YCO(+~^QwZpONQ42>%EoU4#%i{UMR)~c~V=gW6+f& zULjFke;j=a{F;$3{lg1hp@s)-+Fq@`LcaX@R_55Q%9V>r&IRrCYNQ~%ozZVSU~ohh zRUkZP<2$%fuw4L2Xl4#pn3{A*Nu4vQY+5`9*%{odYzlRf#w?uJ5xrC!P@%zbWvDNJ z_S@6XEw_Mbc#!~dfU%1oc^xLoz)W~Q)wlTW7BDKM6++hB?q>32S2Krps|G$$@%V-H zZfnfiG68-k#N+q=dfDG`WInP%?Wq2dMDB~V<}}{3kOL+lGVrn|>7`&%>IN_>Y2&vv z^0Qde%SP3}>%b0}7WDL18ygS>lY};_ANG`WF?C~aT*%l*@pv?0hoF6rJO4e{_iKo{ zLoU>wtkF66_$y1z;B(rE2DWn8vWqZ&j4(CkTp)!+$Vd1)oZhANdznWOC z>h09fOY!C;y<+raX_N9;xwduC*Bxs;g%nAM2obkg=1-H3(;}J;HXZrWNhzL7t<}aL${} z<~UHVJH8I&GFZ}wuPpRq)RcOy*^x11SY!^}T;cF&;V-sYKe*HSl+mkv*y%;A<3&VU zRJ1H7tfWNLwUWQ%>7O?=P*Ju9vtG~<%BZP;-U0GlHIs4wKBr9s)X(t5B^vcHQ(nC5 z#{8|_@!btN=Q3B;2D{X@IbYJ3m!}aMGQYaNl6=Q1m6f`DpK4m;+VxipPrrY)sP^hD4ePhD|C^am;@3fmkd)CyvYxs2-d`|P2QUu1w0ANpYo6A3P ziv_m@SiEddNtj4Rq%k29zZcZo#ZFcm`*CRrI+!xS%WaE_qc*(9?EUcLAY716yh4}V%5%R!7=*2MD$!@WeSxVXujt+}>2 z;7>44Xv6BHCAbYy4*4rmoybbo%w0s)^cTm{BCk;@fU$Zc{naJ^vJIG3f(Y^6@=ZM3 z_eo^D#r3skcPBZEH5fCg=gmoZ#c$Y%`!HRoaoC1Ba4Dr=;gN=E{4f5MEo|U|;4%*i z7T2~ESqaOEwfX#_+c_&X@qh5SA<7znc`4qrI1A54rO3hqsC#NcdN)&^bRvY9&;Ilq zjvvz)-{EJk;#A1WL~(3WA9E=bX5PG7M=!_G#GW7?%KlHnvdb=gUiuiGb3q`BA)xb5 zRz7W44^Z1<=a%k?_|BEsS7O|L{w8)2CR0X;$_QO6Hm?p{DB7jNg!RC#N-pV6tfEVe z*8C>|jGEuxWF-6q^5ObR`-H$<-V>^LrfwQtpTC%fG8-CNWwR|SMf5D|qVWK^jwC&>E*~4)|GF5J5~xrH z`YIXmWF3v!Sr`32GXGhc6A{z>s5gT`^c0e%kcUPk#D?XT?7mAoot&`hgUOTm^D?iWr>kW8hGLn!0T;jNej3Kv zg69#@h{Eefz}ns6*jcy%2RrVX0c48u%=3rl`L#x)%VQj@_5G# zbb$`oj_81aNT-Qqa(c6jlm&{TtNbjb#7kRG+dg4$ta<4Pv;7U3_iv|r4#H(5?V)j| z5pd7Oj;BIm53=WJ@9~_d-U@I$skbA2GSD33$SObQ48aeNo<4LqXx&M3{epZbc)#+> z*KURnqP>`zqI;UH<6$JUNs!y)6nR4a-0S3z(gu&C1^eLF##h=eNl%5`%yar2C*su8 ziO^W@%bB+hf1W?pUB=Jp0~vh(bS3o*-h$UTBeY%O&~w5i!|C{*t7%??7^)|!^jpWp z3rkB+8QKHvuiUdaDsgN!{VlxL^p1hENAQxfDeGqZ2c;u(#D{?g=R!;I)Zf->kI&4R zJHT&J6(9kheb}!$FG5P%=Mph_kXTtK-U9|MtqY?8nnqV)(+EnXis^lD@CMTjAZ~<6 zkeb1+R9E8MaW)6p5j6Vm^B_?0k7SW$mtet0lYx3(V;j?pTkq5wIqGQTQrihJ8gNRh zT04F;(K9N4d4@o#u~~@=V+d2PlJQ0pd{tB&I8f4H4$^ZW z5(`NwaU&Y5P6TU~o90L{DTL$Iz!INba^Mg9GSR=yv8TV^SP$F(rKzfCLiQ^=ZYAT) z(Pdzd$^v>cDoXA{9jrQuv!^`AqfVTk*8O`(F&$UGn@t#2hRU2^3lo{4Isd?=2tC%n zdbT~su?WybSTSac05TBgj9fYva0%oum>>{Y$bNmpI*l{b3};O)b$bVUkPJmSDS)|QuMs*M}K{GC{spCblT^6;KXPJ7;H zUyW!U6?6e%-@C4%)qI@qejjdU7YR=|H%Q8#yE^&Z@ZxqH7pnCB8#xh;n;AA92^lt| zZUbBng^nrjoD?j+i2{-)Ds^dzo7D1I)H1Pxrlg7Z((^vZy|d?ZxQgekJ{F9co0Gs$= z2BY+a&l$38{tO*jX;X!Es(VbkNNYAZ8F@deWVh9!P7aPA;{$<6e4y5oJ!4A{$VHsw+MFUUfT=&m_FY*v zbu$H@=sU8xQhfYnCa#JZ6|0hX%-H3j#i|k4ksYvBwV(}4Ab>!R-;1%$uveNAKHyxn z%t=?I|3p!F`OhofpA;-f3FUq8Xus->-a4aH=6)5vOomQ~V*1}Z-;y#bs@9mI9B)6$2fIaI!Rw2O@zt@2Jdj**#cCT1f($I#LPU(G&t&Iff z9jsO@$Sku$g8^PcT(zWVZxMzmhJC?a$$ULKPvy5!OIrFV9<(Mtf_ZukN9?^!SuZExC?binDU{%t#Vr4`aY)_%zi9su82*d# zkd4x77Z#|ZCXuzF9ih-z71@oU)*4pJtly!s8-_iLh9drLZGU6EYZdI6+G_4HI83T7 z_jAh^&?y?m*v4=$>D{+poaDchpKOX$1qs~&Imi$(PV{ct(VShkh!_p(uS&srk0Mqq z4bzdFP>!b{Nr_EF?p{@!s>$MH#y0WY@XVcor+QJ8aQ|%%oGAzgj;8#jWZHmrrV^l_ j5SANZLzzzii_+br{HjfyYwg-Ryr6a5QOc3VP*MFK3lGkT literal 0 HcmV?d00001 diff --git a/packages/material-parser/test/fixtures/__snapshots__/test/parser/ReactParser.ts.md b/packages/material-parser/test/fixtures/__snapshots__/test/parser/ReactParser.ts.md deleted file mode 100644 index 6a6806c56..000000000 --- a/packages/material-parser/test/fixtures/__snapshots__/test/parser/ReactParser.ts.md +++ /dev/null @@ -1,474 +0,0 @@ -# Snapshot report for `test/parser/ReactParser.ts` - -The actual snapshot is saved in `ReactParser.ts.snap`. - -Generated by [AVA](https://avajs.dev). - -## parse es6 multiple exported component by local - -> Snapshot 1 - - [ - { - defaultExportName: 'AIMakeBlank', - filePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeBlank/index.js', - props: [ - { - name: 'children', - propType: { - type: 'oneOfType', - value: [ - { - type: 'arrayOf', - value: 'node', - }, - 'node', - ], - }, - }, - { - name: 'styleBoxModel', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleLayout', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleBackground', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleFlexLayout', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'style', - propType: 'object', - }, - { - name: 'id', - propType: 'string', - }, - ], - }, - { - defaultExportName: 'AIMakeIcon', - filePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/index.js', - props: [ - { - name: 'className', - propType: 'string', - }, - { - name: 'iconClassName', - propType: 'string', - }, - { - name: 'children', - propType: { - type: 'oneOfType', - value: [ - { - type: 'arrayOf', - value: 'node', - }, - 'node', - ], - }, - }, - { - name: 'styleBoxModel', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleText', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleBackground', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'style', - propType: 'object', - }, - ], - }, - { - defaultExportName: 'AIMakeImage', - filePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeImage/index.js', - props: [ - { - name: 'styleBoxModel', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'style', - propType: 'object', - }, - ], - }, - { - defaultExportName: 'AIMakeLink', - filePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeLink/index.js', - props: [ - { - name: 'children', - propType: { - type: 'oneOfType', - value: [ - { - type: 'arrayOf', - value: 'node', - }, - 'node', - ], - }, - }, - { - name: 'styleBoxModel', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleText', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleLayout', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleBackground', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'style', - propType: 'object', - }, - ], - }, - { - defaultExportName: 'AIMakePlaceholder', - filePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakePlaceholder/index.js', - props: [ - { - name: 'children', - propType: { - type: 'oneOfType', - value: [ - { - type: 'arrayOf', - value: 'node', - }, - 'node', - ], - }, - }, - { - name: 'styleBoxModel', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleLayout', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'style', - propType: 'object', - }, - ], - }, - { - defaultExportName: 'AIMakeText', - filePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeText/index.js', - props: [ - { - name: 'children', - propType: { - type: 'oneOfType', - value: [ - { - type: 'arrayOf', - value: 'node', - }, - 'node', - 'string', - ], - }, - }, - { - name: 'type', - propType: 'string', - }, - { - name: 'styleBoxModel', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleText', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleLayout', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'styleBackground', - propType: { - isRequired: true, - type: 'object', - }, - }, - { - name: 'style', - propType: 'object', - }, - ], - }, - { - defaultExportName: 'Root', - filePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/Root/index.js', - props: [ - { - name: 'style', - propType: 'object', - }, - { - name: 'children', - propType: { - type: 'oneOfType', - value: [ - 'element', - { - type: 'arrayOf', - value: 'element', - }, - ], - }, - }, - ], - }, - ] - -## parse es6 single exported component by local - -> Snapshot 1 - - [ - { - defaultExportName: 'Demo', - filePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/single-exported-component/es/index.js', - props: [ - { - name: 'optionalArray', - propType: 'array', - }, - { - name: 'optionalBool', - propType: 'bool', - }, - { - name: 'optionalFunc', - propType: 'func', - }, - { - defaultValue: 123, - name: 'optionalNumber', - propType: 'number', - }, - { - name: 'optionalObject', - propType: 'object', - }, - { - name: 'optionalString', - propType: 'string', - }, - { - name: 'optionalSymbol', - propType: 'symbol', - }, - { - name: 'optionalNode', - propType: 'node', - }, - { - name: 'optionalElement', - propType: 'element', - }, - { - name: 'optionalElementType', - propType: 'elementType', - }, - { - name: 'optionalMessage', - propType: { - type: 'instanceOf', - value: 'Demo', - }, - }, - { - name: 'optionalEnum', - propType: { - type: 'oneOf', - value: [ - 'News', - 'Photos', - ], - }, - }, - { - name: 'optionalUnion', - propType: { - type: 'oneOfType', - value: [ - 'string', - 'number', - { - type: 'instanceOf', - value: 'Demo', - }, - ], - }, - }, - { - name: 'optionalArrayOf', - propType: { - type: 'arrayOf', - value: 'number', - }, - }, - { - name: 'optionalObjectOf', - propType: { - type: 'objectOf', - value: 'number', - }, - }, - { - name: 'optionalObjectWithShape', - propType: { - type: 'shape', - value: [ - { - name: 'optionalProperty', - propType: 'string', - }, - { - name: 'requiredProperty', - propType: { - isRequired: true, - type: 'number', - }, - }, - ], - }, - }, - { - name: 'optionalObjectWithShape2', - propType: { - isRequired: true, - type: 'shape', - value: [ - { - name: 'optionalProperty', - propType: 'string', - }, - { - name: 'requiredProperty', - propType: { - isRequired: true, - type: 'number', - }, - }, - ], - }, - }, - { - name: 'optionalObjectWithStrictShape', - propType: { - type: 'exact', - value: [ - { - name: 'optionalProperty', - propType: 'string', - }, - { - name: 'requiredProperty', - propType: { - isRequired: true, - type: 'number', - }, - }, - ], - }, - }, - { - name: 'requiredFunc', - propType: { - isRequired: true, - type: 'func', - }, - }, - { - name: 'requiredAny', - propType: { - isRequired: true, - type: 'any', - }, - }, - ], - }, - ] diff --git a/packages/material-parser/test/fixtures/__snapshots__/test/parser/ReactParser.ts.snap b/packages/material-parser/test/fixtures/__snapshots__/test/parser/ReactParser.ts.snap deleted file mode 100644 index 452d8b7a87c6c1603e145d177b393e9a6085bdff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3287 zcmV;|3@GzKRzVF00000000B+ zn-6dl)g8xo?_ZM3{mq3C0ucyEBp6QqH3A|e5G=}{2mvW-^|;$4M=rbZZi9*FAcNre zhoV)q(oRKZKv4>a)jH@nR7cSn(TXB4w&PUCD*mBTuqs;H@9y4ia=&-phD*TEk(tlr zar@ctzJ0s5_xA1ENgT&nxWcUu{Qkv1&b(@2;-j$-?EUS1Jg59SIf~;3KX=!Tu=|sT z7MBGcDjDJHMTb%y+j}T} z2uds*_l_mGdB?n^%Y?AZTa2R5=Tr61p&SS0R*rk$O7sFo{|3r`!FU_TePJW|P)5(O zbDSGggYWD_AHnDW2geNn^`Iz+=o1*d63RHx2+DGaK8?{QLYWF$Kv^Eq>r!>M+TLC` zmO`au_w)XU&=6{i$+hjRQe2)JY7z7$`PH-Lgqnq#SV(LpE9EvsV?td>Zc2V&*~kSK zCWLq**eHmN9U-wX7?vVJupusqvLHr+G3okB^^;I6T8aNCFH3N|hvz4vW%SzHTjNq|;uKrMsYTBUOQKn0JkX~aL#c6UTP*KsTO`knSuLpP z*>z^9RZeYo6$n)IzRL#c6UTl}@BZQ<9F>tdm>&?LnoLfouLHub3{=~D63 zmg(p0owKA~XqV5fvqY(JYFo_gX%|2FIPLJtk{Pj|nS(55bntaUL)L3NW96dCqC*n65nzg ziQl`8#E~8&vEE}OuJjm*+8U2}^uz-mEzzk8_<-~3i$-~kjVZ^+)sA$UB8~_ zD9{pdFvp-+1+FR}eN!9l%37C0xe;ukYA&Phf$}mqN>wML<_7S!0+Rwnbunr^lqFy- zRXvQl3Cb4m3RQiK`cEidg2FMqLQyO0b5i!x;5JD4W4v zs-DZJN1>bm1Nsy7JVqS{Wg-Yu^?XLX3Ce1)m8zo|^+hPJf@4&@fKl^{InEEJ6ccqU zqh0~!YOs>3;~8}elx^Tms#Y=Tr%;Z8fdhy-nNcS|nGC{Iox(O2l+|D}Ri`rQYf$!s zuc%tXsQwa;>klq0A?i#HKoM%@Z!2RK00S?qNH%9o&YAW<)4)G8=bK$NO; z7N{Em^ALAJ?uZFBQu`eA@nUMy-PtAOt4Xs%9a5XD<~)~Oj#sM@x|xk} zsZETiSs(QzYi3Mn?^3UV(yX%VY8LHU>+9~+SSXQD zZUcHP(j5&;;`CmRO+9C)WOpReoU={YCFQ9}+KnSp?#V7C?HT)gpE%3XG}VzlQL)q$ zq41pEIuWL3mqbp4W!a@Lm%t6#<)l5K_GFiJT94bOy>{G+2KP>jS7(=VT3acWU7c*Q zs`b_doo(~`v#S^RuDsAoNAC0Na?*ZRiih-tv*5IzRMXS%BKnsimdIe^5YoT2GhNXq zp!^9OqG}$aehY;k%5h~wiJH%-wNNetF{-*5bv={~;AyIQ8TBxf_kg{OsQnpr5R@`7 zovH&FwE;>DtfOivqwa+AG&o4r!Hjwm3O9`7h7Kd@a7LX0aa@EO`L}6ZocFn-mWPEv-arfn+SX=t5r8AnCFI?9ajSCU= zBa1iFHZon={=btlHTBg$HT9Wl>a{;L^_gnw9cOP-XWFepXYX$H#iUG4Z9k7~YW(1h z#>eBq#pk6yuyoKToAnTufCv$bsdxi~o5Afwtf1m12wT8TB2FZt?PUnBfp@@XM4mxY zZ6i6(3Cc#MiVNuzSna`I*p6|Rdz+GGyYjL-%)!nkTn^;!u!Dc2)`_wq> z#!afW4Rxt;taF5z&?1Pk_KdW`c(@rvaRT^71?lPJFrA_mP*#D>R2{&md!g(D$EZ4r z?dy#~Uk^+fMbt^`Lk%bbxQ(i{jQTi~C%^%!E;_XiTuw+iSLQVkNBicG!|_wrkC3IG z*Ij1*TF%Gcv1T)Twb=p}=_}cq@%K9LAh?9jJU{o;<_gUaS|qc%LTgX|T%iQ64L>+j zC}n!kFZp!SgZjOJj}HK4Ci5rYOJ1F)&ENQv?exMZHYSCjy(W4e8Dn+kaj3`B)T3oLb{c3Ty zQY=u5A1cLwdX@4i^Qpl!hw03c1}HJGfvW6q({3nxz!9oCsA}`zOH&9g1YtU{oBaj2 z9m-wcS*o(rTi%EAv7*uW-|U#zBq-BBGgaA{Fu#WK8}MhUvcqHlfbtnArZdXfNi)-+ z%mmA+%8sNx4CPVqHdWdAHAkVG0Hsc%vh!=IpiBXcR1GldDk!&tC#lMg&+UWq7U1$t zf3HiR3<332Wry-aC^FbeRpu=N>x)oc1y&bP%Ney4$}ljSs_dX!1C$uJm#SpY&2*?< zYL%ms7>cRa9JBFbdq}g)QeAp#jU>g)LTyV`soR+|+r+SGW`ioF`H6BRf1(x{zn?aK zMW*d~^zF`VYgx)pgl2}=#iVAoKSu7nYEwpjBIyh z^^nPE+ghBJYS7{Af{e?=LNO|74~1;*?4F^eTyT_rEwX~yW%*LSLdmct*@g8_4Z9*L zH!WxiB?k=FWS3d|1DRvh(4EyKTB~t|Ca)7B*GZj{kA|KuNV<9UX;-mT^`UE z-AETbVl3JpFa~G;gQB&N<0|MI66|Xav!TofE2+x9ps)qXHgK4#>9SixeDB5@|I1{ V9|~sp_56{O{s$bzH~!Q^007=MT^|4d diff --git a/packages/material-parser/test/fixtures/__snapshots__/test/scan.ts.md b/packages/material-parser/test/fixtures/__snapshots__/test/scan.ts.md new file mode 100644 index 000000000..4625015dd --- /dev/null +++ b/packages/material-parser/test/fixtures/__snapshots__/test/scan.ts.md @@ -0,0 +1,132 @@ +# Snapshot report for `test/scan.ts` + +The actual snapshot is saved in `scan.ts.snap`. + +Generated by [AVA](https://avajs.dev). + +## scan multiple exported component + +> Snapshot 1 + + { + mainEntry: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js', + modules: [ + { + fileContent: `import AIMakeBlank from './basic/AIMakeBlank';␊ + import AIMakeIcon from './basic/AIMakeIcon';␊ + import AIMakeImage from './basic/AIMakeImage';␊ + import AIMakeLink from './basic/AIMakeLink';␊ + import AIMakePlaceholder from './basic/AIMakePlaceholder';␊ + import AIMakeText from './basic/AIMakeText';␊ + import Root from './basic/Root';␊ + ␊ + export { AIMakeBlank, AIMakeIcon, AIMakeImage, AIMakeLink, AIMakePlaceholder, AIMakeText, Root };␊ + `, + filePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js', + }, + ], + pkgName: 'multiple-exported-component', + pkgVersion: '1.0.0', + sourceType: 'module', + } + +## scan single exported component + +> Snapshot 1 + + { + mainEntry: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/single-exported-component/es/index.js', + modules: [ + { + fileContent: `import _classCallCheck from "@babel/runtime/helpers/classCallCheck";␊ + import _createClass from "@babel/runtime/helpers/createClass";␊ + import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";␊ + import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";␊ + import _inherits from "@babel/runtime/helpers/inherits";␊ + ␊ + /* eslint-disable react/no-unused-prop-types */␊ + ␊ + /* eslint-disable react/require-default-props */␊ + import React from 'react';␊ + import PropTypes from 'prop-types';␊ + import "./main.css";␊ + ␊ + const Demo =␊ + /* #__PURE__ */␊ + function (_React$Component) {␊ + _inherits(Demo, _React$Component);␊ + ␊ + function Demo() {␊ + _classCallCheck(this, Demo);␊ + ␊ + return _possibleConstructorReturn(this, _getPrototypeOf(Demo).apply(this, arguments));␊ + }␊ + ␊ + _createClass(Demo, [{␊ + key: "render",␊ + value: function render() {␊ + return React.createElement("div", null, " Test ");␊ + },␊ + }]);␊ + ␊ + return Demo;␊ + }(React.Component);␊ + ␊ + Demo.propTypes = {␊ + optionalArray: PropTypes.array,␊ + optionalBool: PropTypes.bool,␊ + optionalFunc: PropTypes.func,␊ + optionalNumber: PropTypes.number,␊ + optionalObject: PropTypes.object,␊ + optionalString: PropTypes.string,␊ + optionalSymbol: PropTypes.symbol,␊ + // Anything that can be rendered: numbers, strings, elements or an array␊ + // (or fragment) containing these types.␊ + optionalNode: PropTypes.node,␊ + // A React element (ie. ).␊ + optionalElement: PropTypes.element,␊ + // A React element type (ie. MyComponent).␊ + optionalElementType: PropTypes.elementType,␊ + // You can also declare that a prop is an instance of a class. This uses␊ + // JS's instanceof operator.␊ + optionalMessage: PropTypes.instanceOf(Demo),␊ + // You can ensure that your prop is limited to specific values by treating␊ + // it as an enum.␊ + optionalEnum: PropTypes.oneOf(['News', 'Photos']),␊ + // An object that could be one of many types␊ + optionalUnion: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.instanceOf(Demo)]),␊ + // An array of a certain type␊ + optionalArrayOf: PropTypes.arrayOf(PropTypes.number),␊ + // An object with property values of a certain type␊ + optionalObjectOf: PropTypes.objectOf(PropTypes.number),␊ + // You can chain any of the above with `isRequired` to make sure a warning␊ + // is shown if the prop isn't provided.␊ + // An object taking on a particular shape␊ + optionalObjectWithShape: PropTypes.shape({␊ + optionalProperty: PropTypes.string,␊ + requiredProperty: PropTypes.number.isRequired,␊ + }),␊ + optionalObjectWithShape2: PropTypes.shape({␊ + optionalProperty: PropTypes.string,␊ + requiredProperty: PropTypes.number.isRequired,␊ + }).isRequired,␊ + // An object with warnings on extra properties␊ + optionalObjectWithStrictShape: PropTypes.exact({␊ + optionalProperty: PropTypes.string,␊ + requiredProperty: PropTypes.number.isRequired,␊ + }),␊ + requiredFunc: PropTypes.func.isRequired,␊ + // A value of any data type␊ + requiredAny: PropTypes.any.isRequired,␊ + };␊ + Demo.defaultProps = {␊ + optionalNumber: 123,␊ + };␊ + export default Demo;`, + filePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/single-exported-component/es/index.js', + }, + ], + pkgName: 'single-exported-component', + pkgVersion: '1.0.0', + sourceType: 'module', + } diff --git a/packages/material-parser/test/fixtures/__snapshots__/test/scan.ts.snap b/packages/material-parser/test/fixtures/__snapshots__/test/scan.ts.snap new file mode 100644 index 0000000000000000000000000000000000000000..51d3eebf4eabdfd4d6f16f039c02f3d051f29918 GIT binary patch literal 1656 zcmV-;28a1URzVvy>JgYY6;>u??Q=Z^SuS37q|qyU3In6e}~Idf|0RgbaIx^#+*r!idKt>TPhcNH%}DJ5)j+UxKJbp!ZhQIFcrc!Wii@KO4ep4 zvNlsO=RlVxWYHuXW9ox5}yuaol$X6p#DmZC-wcCe&T=zyk6eY%4sdZP+nN^nH_Jc)^zD&y=|MOVm{nku6=M&M=6t1!I;fSRor zbk~hx%ZX6S4M59ruQh3X%dx6um2RJ^RT8;hCvpj^{`1#;(}vA&aLqxil!v&lO)p#9>>;)-MAJB0{L6i+mB%w0Uhy-OG!J%NU1~~ zDK3@?WS;F#wxgIs-6LvAaK#lQ<7#(zzHzKWLRlY*Q$5DF5(R>_@E9U8p-i=7DlyoI z!0||hjJI=^ODM8T@T{#hNpvjSSwN7Fb1FzXCS43YZ^Vp5IS4hXn1n`RG$X;6Y{e+B z+arx5Og#v7KL?S?M=jEkL>EZP(P?ecYinyu*OxD@t!a(joJ9(1A2rvE*4G!yKAA^% zYiJavrY2~i2^1(mXvm^LO)H72W!O}GDq99(r4WR}6vWQ8Qpi*?ZfuzkaF!*50)a&@ zPr)8J58McCYks$a3-ed4W$R?Hfa(GU84>lCS=zu!P8LR<*v+9YLtBmifn~m!5UsOW zkLgCeg;<^>EmTJI**a4Pk`t4iRxGtsIL~?F0y^;Q?!OD}x%=8(cmGPBc8G8h%&fQ=JD6MyH!CjYni4R7U5qp< zW0*nO8MjuN6^#i)bdC)mwXBC!A1f4LhB~Ck3W*nxwF@$DiQ$IWY)Hff0x&M=^nR6vT!TBVA*NN*yT*O@~=T5bwfo`D_pijNd(8$ zSo5*L7!7=3nxnmV Snapshot 1 - - { - mainEntry: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/index.js', - modules: [ - { - fileContent: `import _extends from "@babel/runtime/helpers/extends";␊ - import _classCallCheck from "@babel/runtime/helpers/classCallCheck";␊ - import _createClass from "@babel/runtime/helpers/createClass";␊ - import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";␊ - import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";␊ - import _inherits from "@babel/runtime/helpers/inherits";␊ - import _defineProperty from "@babel/runtime/helpers/defineProperty";␊ - import React, { Component } from 'react';␊ - import PropTypes from 'prop-types';␊ - import HOCBoxModelProps from '../utils/HOCBoxModelProps';␊ - import HOCLayoutProps from '../utils/HOCLayoutProps';␊ - import HOCBackgroundProps from '../utils/HOCBackgroundProps';␊ - import HOCFlexLayoutProps from '../utils/HOCFlexLayoutProps';␊ - ␊ - var AIMakeBlank =␊ - /*#__PURE__*/␊ - function (_Component) {␊ - _inherits(AIMakeBlank, _Component);␊ - ␊ - function AIMakeBlank() {␊ - _classCallCheck(this, AIMakeBlank);␊ - ␊ - return _possibleConstructorReturn(this, _getPrototypeOf(AIMakeBlank).apply(this, arguments));␊ - }␊ - ␊ - _createClass(AIMakeBlank, [{␊ - key: "render",␊ - value: function render() {␊ - var merged = {};␊ - var _this$props = this.props,␊ - children = _this$props.children,␊ - styleBoxModel = _this$props.styleBoxModel,␊ - styleLayout = _this$props.styleLayout,␊ - styleBackground = _this$props.styleBackground,␊ - styleFlexLayout = _this$props.styleFlexLayout,␊ - style = _this$props.style,␊ - id = _this$props.id;␊ - var styles = { ...styleBoxModel,␊ - ...styleLayout,␊ - ...styleBackground,␊ - ...styleFlexLayout,␊ - ...style␊ - };␊ - ␊ - if (id) {␊ - merged.id = id;␊ - }␊ - ␊ - return React.createElement("div", _extends({␊ - style: styles␊ - }, merged), children);␊ - }␊ - }]);␊ - ␊ - return AIMakeBlank;␊ - }(Component);␊ - ␊ - _defineProperty(AIMakeBlank, "propTypes", {␊ - children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]),␊ - styleBoxModel: PropTypes.object.isRequired,␊ - styleLayout: PropTypes.object.isRequired,␊ - styleBackground: PropTypes.object.isRequired,␊ - styleFlexLayout: PropTypes.object.isRequired,␊ - style: PropTypes.object,␊ - id: PropTypes.string␊ - });␊ - ␊ - _defineProperty(AIMakeBlank, "defaultProps", {␊ - children: [],␊ - style: {},␊ - id: ''␊ - });␊ - ␊ - export default HOCBoxModelProps(HOCLayoutProps(HOCBackgroundProps(HOCFlexLayoutProps(AIMakeBlank))));`, - filePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeBlank/index.js', - }, - { - fileContent: `import _extends from "@babel/runtime/helpers/extends";␊ - import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";␊ - import _classCallCheck from "@babel/runtime/helpers/classCallCheck";␊ - import _createClass from "@babel/runtime/helpers/createClass";␊ - import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";␊ - import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";␊ - import _inherits from "@babel/runtime/helpers/inherits";␊ - import _defineProperty from "@babel/runtime/helpers/defineProperty";␊ - import React, { Component } from 'react';␊ - import PropTypes from 'prop-types';␊ - import classNames from 'classnames';␊ - import createFromIconfont from './IconFont';␊ - ␊ - var AIMakeIcon =␊ - /*#__PURE__*/␊ - function (_Component) {␊ - _inherits(AIMakeIcon, _Component);␊ - ␊ - function AIMakeIcon() {␊ - _classCallCheck(this, AIMakeIcon);␊ - ␊ - return _possibleConstructorReturn(this, _getPrototypeOf(AIMakeIcon).apply(this, arguments));␊ - }␊ - ␊ - _createClass(AIMakeIcon, [{␊ - key: "render",␊ - value: function render() {␊ - var _this$props = this.props,␊ - className = _this$props.className,␊ - iconClassName = _this$props.iconClassName,␊ - children = _this$props.children,␊ - styleBoxModel = _this$props.styleBoxModel,␊ - styleText = _this$props.styleText,␊ - styleBackground = _this$props.styleBackground,␊ - style = _this$props.style,␊ - otherProps = _objectWithoutProperties(_this$props, ["className", "iconClassName", "children", "styleBoxModel", "styleText", "styleBackground", "style"]);␊ - ␊ - var styles = { ...styleBoxModel,␊ - ...styleText,␊ - ...styleBackground,␊ - ...style␊ - };␊ - return React.createElement("i", _extends({}, otherProps, {␊ - className: classNames(className, iconClassName),␊ - style: styles␊ - }), children);␊ - }␊ - }]);␊ - ␊ - return AIMakeIcon;␊ - }(Component);␊ - ␊ - _defineProperty(AIMakeIcon, "propTypes", {␊ - className: PropTypes.string,␊ - iconClassName: PropTypes.string,␊ - children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]),␊ - styleBoxModel: PropTypes.object.isRequired,␊ - styleText: PropTypes.object.isRequired,␊ - styleBackground: PropTypes.object.isRequired,␊ - style: PropTypes.object␊ - });␊ - ␊ - _defineProperty(AIMakeIcon, "defaultProps", {␊ - className: '',␊ - iconClassName: 'iconfont',␊ - children: '',␊ - style: {}␊ - });␊ - ␊ - AIMakeIcon.createFromIconfont = createFromIconfont;␊ - export default AIMakeIcon;`, - filePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeIcon/index.js', - }, - { - fileContent: `import _extends from "@babel/runtime/helpers/extends";␊ - import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";␊ - import _classCallCheck from "@babel/runtime/helpers/classCallCheck";␊ - import _createClass from "@babel/runtime/helpers/createClass";␊ - import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";␊ - import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";␊ - import _inherits from "@babel/runtime/helpers/inherits";␊ - import _defineProperty from "@babel/runtime/helpers/defineProperty";␊ - import React, { Component } from 'react';␊ - import PropTypes from 'prop-types';␊ - import HOCBoxModelProps from '../utils/HOCBoxModelProps';␊ - ␊ - var AIMakeImage =␊ - /*#__PURE__*/␊ - function (_Component) {␊ - _inherits(AIMakeImage, _Component);␊ - ␊ - function AIMakeImage() {␊ - _classCallCheck(this, AIMakeImage);␊ - ␊ - return _possibleConstructorReturn(this, _getPrototypeOf(AIMakeImage).apply(this, arguments));␊ - }␊ - ␊ - _createClass(AIMakeImage, [{␊ - key: "render",␊ - value: function render() {␊ - var _this$props = this.props,␊ - styleBoxModel = _this$props.styleBoxModel,␊ - style = _this$props.style,␊ - otherProps = _objectWithoutProperties(_this$props, ["styleBoxModel", "style"]);␊ - ␊ - var styles = { ...styleBoxModel,␊ - ...style␊ - };␊ - return React.createElement("img", _extends({}, otherProps, {␊ - style: styles,␊ - alt: "AIMakeImage"␊ - }));␊ - }␊ - }]);␊ - ␊ - return AIMakeImage;␊ - }(Component);␊ - ␊ - _defineProperty(AIMakeImage, "propTypes", {␊ - styleBoxModel: PropTypes.object.isRequired,␊ - style: PropTypes.object␊ - });␊ - ␊ - _defineProperty(AIMakeImage, "defaultProps", {␊ - style: {}␊ - });␊ - ␊ - export default HOCBoxModelProps(AIMakeImage);`, - filePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeImage/index.js', - }, - { - fileContent: `import _extends from "@babel/runtime/helpers/extends";␊ - import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";␊ - import _classCallCheck from "@babel/runtime/helpers/classCallCheck";␊ - import _createClass from "@babel/runtime/helpers/createClass";␊ - import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";␊ - import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";␊ - import _inherits from "@babel/runtime/helpers/inherits";␊ - import _defineProperty from "@babel/runtime/helpers/defineProperty";␊ - import React, { Component } from 'react';␊ - import PropTypes from 'prop-types';␊ - import HOCBoxModelProps from '../utils/HOCBoxModelProps';␊ - import HOCTextProps from '../utils/HOCTextProps';␊ - import HOCLayoutProps from '../utils/HOCLayoutProps';␊ - import HOCBackgroundProps from '../utils/HOCBackgroundProps';␊ - ␊ - var AIMakeLink =␊ - /*#__PURE__*/␊ - function (_Component) {␊ - _inherits(AIMakeLink, _Component);␊ - ␊ - function AIMakeLink() {␊ - _classCallCheck(this, AIMakeLink);␊ - ␊ - return _possibleConstructorReturn(this, _getPrototypeOf(AIMakeLink).apply(this, arguments));␊ - }␊ - ␊ - _createClass(AIMakeLink, [{␊ - key: "render",␊ - value: function render() {␊ - var _this$props = this.props,␊ - children = _this$props.children,␊ - styleBoxModel = _this$props.styleBoxModel,␊ - styleText = _this$props.styleText,␊ - styleLayout = _this$props.styleLayout,␊ - styleBackground = _this$props.styleBackground,␊ - style = _this$props.style,␊ - otherProps = _objectWithoutProperties(_this$props, ["children", "styleBoxModel", "styleText", "styleLayout", "styleBackground", "style"]);␊ - ␊ - var styles = { ...styleBoxModel,␊ - ...styleText,␊ - ...styleLayout,␊ - ...styleBackground,␊ - ...style␊ - };␊ - ␊ - if (typeof children !== 'string') {␊ - styles.display = 'inline-block';␊ - }␊ - ␊ - return React.createElement("a", _extends({}, otherProps, {␊ - style: styles␊ - }), [children]);␊ - }␊ - }]);␊ - ␊ - return AIMakeLink;␊ - }(Component);␊ - ␊ - _defineProperty(AIMakeLink, "propTypes", {␊ - children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]),␊ - styleBoxModel: PropTypes.object.isRequired,␊ - styleText: PropTypes.object.isRequired,␊ - styleLayout: PropTypes.object.isRequired,␊ - styleBackground: PropTypes.object.isRequired,␊ - style: PropTypes.object␊ - });␊ - ␊ - _defineProperty(AIMakeLink, "defaultProps", {␊ - children: '',␊ - style: {}␊ - });␊ - ␊ - export default HOCBoxModelProps(HOCTextProps(HOCLayoutProps(HOCBackgroundProps(AIMakeLink))));`, - filePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeLink/index.js', - }, - { - fileContent: `import _classCallCheck from "@babel/runtime/helpers/classCallCheck";␊ - import _createClass from "@babel/runtime/helpers/createClass";␊ - import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";␊ - import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";␊ - import _inherits from "@babel/runtime/helpers/inherits";␊ - import _defineProperty from "@babel/runtime/helpers/defineProperty";␊ - import React, { Component } from 'react';␊ - import PropTypes from 'prop-types';␊ - import HOCBoxModelProps from '../utils/HOCBoxModelProps';␊ - import HOCLayoutProps from '../utils/HOCLayoutProps';␊ - ␊ - var AIMakePlaceholder =␊ - /*#__PURE__*/␊ - function (_Component) {␊ - _inherits(AIMakePlaceholder, _Component);␊ - ␊ - function AIMakePlaceholder() {␊ - _classCallCheck(this, AIMakePlaceholder);␊ - ␊ - return _possibleConstructorReturn(this, _getPrototypeOf(AIMakePlaceholder).apply(this, arguments));␊ - }␊ - ␊ - _createClass(AIMakePlaceholder, [{␊ - key: "render",␊ - value: function render() {␊ - var _this$props = this.props,␊ - children = _this$props.children,␊ - styleBoxModel = _this$props.styleBoxModel,␊ - styleLayout = _this$props.styleLayout,␊ - style = _this$props.style;␊ - var styles = { ...styleBoxModel,␊ - ...styleLayout,␊ - ...style␊ - };␊ - var placeholderStyle = {␊ - display: 'inline-block',␊ - border: '1px dashed #aaa',␊ - lineHeight: styles.height,␊ - backgroundColor: '#F5E075',␊ - overflow: 'hidden',␊ - textAlign: 'center',␊ - ...styles␊ - };␊ - return React.createElement("div", {␊ - style: placeholderStyle␊ - }, children);␊ - }␊ - }]);␊ - ␊ - return AIMakePlaceholder;␊ - }(Component);␊ - ␊ - _defineProperty(AIMakePlaceholder, "propTypes", {␊ - children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]),␊ - styleBoxModel: PropTypes.object.isRequired,␊ - styleLayout: PropTypes.object.isRequired,␊ - style: PropTypes.object␊ - });␊ - ␊ - _defineProperty(AIMakePlaceholder, "defaultProps", {␊ - children: '',␊ - style: {}␊ - });␊ - ␊ - export default HOCBoxModelProps(HOCLayoutProps(AIMakePlaceholder));`, - filePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakePlaceholder/index.js', - }, - { - fileContent: `import _classCallCheck from "@babel/runtime/helpers/classCallCheck";␊ - import _createClass from "@babel/runtime/helpers/createClass";␊ - import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";␊ - import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";␊ - import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized";␊ - import _inherits from "@babel/runtime/helpers/inherits";␊ - import _defineProperty from "@babel/runtime/helpers/defineProperty";␊ - import React, { Component } from 'react';␊ - import PropTypes from 'prop-types';␊ - import HOCBoxModelProps from '../utils/HOCBoxModelProps';␊ - import HOCTextProps from '../utils/HOCTextProps';␊ - import HOCLayoutProps from '../utils/HOCLayoutProps';␊ - import HOCBackgroundProps from '../utils/HOCBackgroundProps';␊ - ␊ - var AIMakeText =␊ - /*#__PURE__*/␊ - function (_Component) {␊ - _inherits(AIMakeText, _Component);␊ - ␊ - function AIMakeText() {␊ - var _this;␊ - ␊ - _classCallCheck(this, AIMakeText);␊ - ␊ - for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {␊ - args[_key] = arguments[_key];␊ - }␊ - ␊ - _this = _possibleConstructorReturn(this, _getPrototypeOf(AIMakeText).call(this, ...args));␊ - ␊ - _defineProperty(_assertThisInitialized(_this), "generateComponentType", function (componentType) {␊ - var componentNameMap = {␊ - h1: 'h1',␊ - h2: 'h2',␊ - h3: 'h3',␊ - h4: 'h4',␊ - h5: 'h5',␊ - paragraph: 'p',␊ - label: 'label'␊ - };␊ - return componentNameMap[componentType] || 'div';␊ - });␊ - ␊ - return _this;␊ - }␊ - ␊ - _createClass(AIMakeText, [{␊ - key: "render",␊ - value: function render() {␊ - var _this$props = this.props,␊ - children = _this$props.children,␊ - type = _this$props.type,␊ - styleBoxModel = _this$props.styleBoxModel,␊ - styleText = _this$props.styleText,␊ - styleLayout = _this$props.styleLayout,␊ - styleBackground = _this$props.styleBackground,␊ - style = _this$props.style;␊ - var styles = { ...styleBoxModel,␊ - ...styleText,␊ - ...styleLayout,␊ - ...styleBackground,␊ - ...style␊ - };␊ - var Comp = this.generateComponentType(type);␊ - var labelStyle = Comp === 'label' ? {␊ - display: 'inline-block'␊ - } : {};␊ - return React.createElement(Comp, {␊ - className: "AIMakeText",␊ - style: Object.assign(labelStyle, styles)␊ - }, [children]);␊ - }␊ - }]);␊ - ␊ - return AIMakeText;␊ - }(Component);␊ - ␊ - _defineProperty(AIMakeText, "propTypes", {␊ - children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node, PropTypes.string]),␊ - type: PropTypes.string,␊ - styleBoxModel: PropTypes.object.isRequired,␊ - styleText: PropTypes.object.isRequired,␊ - styleLayout: PropTypes.object.isRequired,␊ - styleBackground: PropTypes.object.isRequired,␊ - style: PropTypes.object␊ - });␊ - ␊ - _defineProperty(AIMakeText, "defaultProps", {␊ - children: '',␊ - type: '',␊ - // paragraph || label␊ - style: {}␊ - });␊ - ␊ - export default HOCBoxModelProps(HOCTextProps(HOCLayoutProps(HOCBackgroundProps(AIMakeText))));`, - filePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/AIMakeText/index.js', - }, - { - fileContent: `import _classCallCheck from "@babel/runtime/helpers/classCallCheck";␊ - import _createClass from "@babel/runtime/helpers/createClass";␊ - import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";␊ - import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";␊ - import _inherits from "@babel/runtime/helpers/inherits";␊ - import _defineProperty from "@babel/runtime/helpers/defineProperty";␊ - import React from 'react';␊ - import PropTypes from 'prop-types';␊ - ␊ - var Root =␊ - /*#__PURE__*/␊ - function (_React$Component) {␊ - _inherits(Root, _React$Component);␊ - ␊ - function Root() {␊ - _classCallCheck(this, Root);␊ - ␊ - return _possibleConstructorReturn(this, _getPrototypeOf(Root).apply(this, arguments));␊ - }␊ - ␊ - _createClass(Root, [{␊ - key: "render",␊ - value: function render() {␊ - var _this$props = this.props,␊ - style = _this$props.style,␊ - children = _this$props.children;␊ - var newStyle = Object.assign({}, Root.defaultProps.style, style);␊ - return React.createElement("div", {␊ - style: newStyle␊ - }, children);␊ - }␊ - }]);␊ - ␊ - return Root;␊ - }(React.Component);␊ - ␊ - _defineProperty(Root, "propTypes", {␊ - style: PropTypes.object,␊ - children: PropTypes.oneOfType([PropTypes.element, PropTypes.arrayOf(PropTypes.element)])␊ - });␊ - ␊ - _defineProperty(Root, "defaultProps", {␊ - style: {␊ - padding: 0,␊ - backgroundColor: '#f0f2f5',␊ - minHeight: '100%'␊ - },␊ - children: null␊ - });␊ - ␊ - export default Root;`, - filePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/multiple-exported-component/es/basic/Root/index.js', - }, - ], - pkgName: 'multiple-exported-component', - pkgVersion: '1.0.0', - sourceType: 'module', - } - -## scan single exported component - -> Snapshot 1 - - { - mainEntry: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/single-exported-component/es/index.js', - modules: [ - { - fileContent: `import _classCallCheck from "@babel/runtime/helpers/classCallCheck";␊ - import _createClass from "@babel/runtime/helpers/createClass";␊ - import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";␊ - import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";␊ - import _inherits from "@babel/runtime/helpers/inherits";␊ - ␊ - /* eslint-disable react/no-unused-prop-types */␊ - ␊ - /* eslint-disable react/require-default-props */␊ - import React from 'react';␊ - import PropTypes from 'prop-types';␊ - import "./main.css";␊ - ␊ - var Demo =␊ - /*#__PURE__*/␊ - function (_React$Component) {␊ - _inherits(Demo, _React$Component);␊ - ␊ - function Demo() {␊ - _classCallCheck(this, Demo);␊ - ␊ - return _possibleConstructorReturn(this, _getPrototypeOf(Demo).apply(this, arguments));␊ - }␊ - ␊ - _createClass(Demo, [{␊ - key: "render",␊ - value: function render() {␊ - return React.createElement("div", null, " Test ");␊ - }␊ - }]);␊ - ␊ - return Demo;␊ - }(React.Component);␊ - ␊ - Demo.propTypes = {␊ - optionalArray: PropTypes.array,␊ - optionalBool: PropTypes.bool,␊ - optionalFunc: PropTypes.func,␊ - optionalNumber: PropTypes.number,␊ - optionalObject: PropTypes.object,␊ - optionalString: PropTypes.string,␊ - optionalSymbol: PropTypes.symbol,␊ - // Anything that can be rendered: numbers, strings, elements or an array␊ - // (or fragment) containing these types.␊ - optionalNode: PropTypes.node,␊ - // A React element (ie. ).␊ - optionalElement: PropTypes.element,␊ - // A React element type (ie. MyComponent).␊ - optionalElementType: PropTypes.elementType,␊ - // You can also declare that a prop is an instance of a class. This uses␊ - // JS's instanceof operator.␊ - optionalMessage: PropTypes.instanceOf(Demo),␊ - // You can ensure that your prop is limited to specific values by treating␊ - // it as an enum.␊ - optionalEnum: PropTypes.oneOf(['News', 'Photos']),␊ - // An object that could be one of many types␊ - optionalUnion: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.instanceOf(Demo)]),␊ - // An array of a certain type␊ - optionalArrayOf: PropTypes.arrayOf(PropTypes.number),␊ - // An object with property values of a certain type␊ - optionalObjectOf: PropTypes.objectOf(PropTypes.number),␊ - // You can chain any of the above with `isRequired` to make sure a warning␊ - // is shown if the prop isn't provided.␊ - // An object taking on a particular shape␊ - optionalObjectWithShape: PropTypes.shape({␊ - optionalProperty: PropTypes.string,␊ - requiredProperty: PropTypes.number.isRequired␊ - }),␊ - optionalObjectWithShape2: PropTypes.shape({␊ - optionalProperty: PropTypes.string,␊ - requiredProperty: PropTypes.number.isRequired␊ - }).isRequired,␊ - // An object with warnings on extra properties␊ - optionalObjectWithStrictShape: PropTypes.exact({␊ - optionalProperty: PropTypes.string,␊ - requiredProperty: PropTypes.number.isRequired␊ - }),␊ - requiredFunc: PropTypes.func.isRequired,␊ - // A value of any data type␊ - requiredAny: PropTypes.any.isRequired␊ - };␊ - Demo.defaultProps = {␊ - optionalNumber: 123␊ - };␊ - export default Demo;`, - filePath: '/Users/gengyang/code/frontend/low-code/ali-lowcode-engine/packages/material-parser/test/fixtures/single-exported-component/es/index.js', - }, - ], - pkgName: 'single-exported-component', - pkgVersion: '1.0.0', - sourceType: 'module', - } diff --git a/packages/material-parser/test/fixtures/__snapshots__/test/scanner/Scanner.ts.snap b/packages/material-parser/test/fixtures/__snapshots__/test/scanner/Scanner.ts.snap deleted file mode 100644 index fb0e88c0411cd649a47e7527283069ba7c944cd4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3591 zcmV+i4*2mwRzVb(k#g|2+U%b(9b9v_Pc00000000B+ zTup2wM-}e2*WQgc%O(m^f{>t?O_-VNxX1ewA=%j^yUs3Il-)J^lPI!`Q`1v3({WGt z(B0$pu(7xyjz~lxA`Tq5AjFYe!Zku15aN{MiX##Tgb+v(LcCYiKh-}o-7{l5USdlv zS699F>Q&Wy^}c%D)60sY%qYgi-9+v(Yk$C@Cp+p{fZd39(utR~yh-f$r2Gl4 zzrgixxMpS)P3T*H52LkRD5s zzWI!zY`}H>%L&rC6zLpMl#_6+KA#|+Pm%r?NRFKa+r5w=J)R<6yr?J_;L=}7ke*19 ze(AEJJPX%9uO&zyOL@dhVyREI43n*LWA_4|`0isy7cGfwvK@2+mw-ETN$HgaZ7{R$ z^exZmvU-P^J@g!(sI;;Wu<0gs-BoIus~x6qjpmNi%0e6lZncWdIT9j5iM?mLuF>FQ zb3Lc8d$x0%fkRrOg$-qsM7No@=GdO?fq&d;jg}Xum4p~p2lfmvXKVqL#Mopl*nB`J z5O{;p>~Y#i$ZbY-uSOn_)nKO}yFyag!KQLZiM+TE_( zA(yY;pj+&UNv$n%X`%l7na$0$d$+G{Za!aMX!R}KgPoOBHp5x1k_QVUTI-6$Un3G3 zh$kczAW>C>1d{Zriq|pRnoKEV5aI|UA8!9XYr=|U)v6lp^~`}!NS$`S3rf0G=z@@4 z>_&FZ_@LH>x?60pOiB*y3(P6ic-1yF`)oNHrDzNXhy)JlGN;X&_7SWRKB{aj#e!|ui zV`PC@j8SWfF^gO#GLo7YO?j$0JF5&Md*N>-fzeJN zMq8s^Cje;gf9i*p26YX+F6k{DV+x|o52r<$!VumxypBJSu+#?25i^A82)uq)!7E=v zJWmHiyu!i?iHNV#HE6%C+g1w!1}$zn0Zjq_P{FF{P`ZX-&Q0M zu*9WsrXjSJVzY=9!8BnxHU(h?4l!yCl@F^*8`TgVjtyAj^H&6}MvycgU>Y%a2?#Qp zz?uYM!x>tZcArXQp>eycMmlBU)G_cWdSO9$DjYVAP9xQm$crN-S@CR=LxXS86!r(* zrm04uQh%niKxs6S<#NXKmJL4`mE#jDh(ib~I*&TjGNRd~j1aey1iO+E;B!P>%rWrw&jj$gavjvGYs zB%*m<8Y<>&k5)Q~D?NU+ern+;S|3I0M=@GQoOmP|#uc`GN>5KEO!2xg)#FcO&qWkS zR0vQY;ojg0E@=`tAqI31$*n_|dOEo0q5G4o8ZR3q#&p2RsY#x(W>7q{P;GpzKB-zC#}@2=9cu z9^MD9#S>He`G|HrRA(LA1pG1u0+giW0zrwk5FV81_XZZq0w+O-vBCbofW)zJUl!?}zjl_) zMWNtcH2rscMIzkcW1Qs##EB#~YzG*j{akN{G^yKRO>%}(Dv==HYs_eOya2#x9eyiG z38U1iZQ3aA%(WM;E`99uRI0Q+xvU1wy4?Hj{U?e4O;NLxqzh-N%PZ zCm%n8OU2<5XbYBl7dGzemf^wT8Q*~&aHOnEmLmlAs3!YFI%s03$8#Ea7!Qd;q!Z#C zAH9tNd&n4|yq4{d3THMs_zB^e2KQ~R!vPy242#_-{3mG@q=X2u32+SRmsUjSMJ_?y zoIM)>Fl1lH$_-h%s0pH?&=^%jz%v=(Ib3plF9$_E7{4lCL{(MUrU~uUy7>xmKb6LA}wJ_b@sKxXEE2 zP9s5(j|WnGT8g96o$)bqXlAGr%lUFdpQgO8w}0kNJi z7fyWMA{+rJ=twwfs9W}8-|D+yWD!gtfCh##IN}7b=WD_+i&)}4Se=09m9EzOe6NB zY(x>z+~EiE>?3+eGw3$r+Pb{PKdD}}2C%YL8!#dDh)yliVE&@8CdPEs%SBj*f}!B! z50}^u0ct)sLR1B6T5#^=@Pz2FVS;A}(adH1i0o?eEI=GvPNpJ!t$e@qJ0lf?Y2?Kl zgXq~t{iUib%Qq2OT!5ysCGxBy7b{845_va~1YuFNFZwOJ&nJ$Wt__$6ywPD|Iw?UL zBZiAJWq{97OJ~GxK?C<$jbLV*z<%ZmQQx>zc0)p-Lrh1(OJ%)oFxQ2UFY6R=1TLFU zj9G3!P-y_6HPp&9x&{Pn;@QOQG2Lhxx^PgJGzP>&=fe+=aA5`vhmV7SO~mF2?o-gV zvR=N)?z`n0DX(>4LvhO+)zIRIuw>ul?7rDVqXRyinl7~l!d9d{?pg3J7eD*PpLVMe zQzfg#ZP{NQz|vs7T#@9~aI2Nt9O5}P-f4Qc_YJSZr=B09{dpeMo7e*4-PwNK(Efr& z*E=W?Clk5=42qpKaV?~SZ61QXDx9}}nl;InWRravB zZ8TX^ORXy1LZ^qlonju$GxWZRDeDf+7#zOGd?+~xWM1R9j?szgV!dJtV|n@zb-CLEZgxM8kmw1^Au?$ppWjQCYSBNHh3VD8*pVs z!;IkykKhggM%$zw4g4Vx1hFdSdDcMgc6UXDb@}9*i0nb!J$L>Bk|&O-953V@QxD5w N?SHSwmi>KJ006FB%(nml diff --git a/packages/material-parser/test/fixtures/fusion-next-component/package.json b/packages/material-parser/test/fixtures/fusion-next-component/package.json index 417b601bb..aaacb18ee 100644 --- a/packages/material-parser/test/fixtures/fusion-next-component/package.json +++ b/packages/material-parser/test/fixtures/fusion-next-component/package.json @@ -1,14 +1,11 @@ { - "name": "fusion-next-component", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "", - "license": "ISC", - "dependencies": { - "@alife/next": "^1.17.12" + "name": "@alifd/next", + "version": "1.19.18", + "description": "A configurable component library for web built on React.", + "main": "src/index.js", + "typings": "types/index.d.ts", + "repository": { + "type": "git", + "url": "https://github.com/alibaba-fusion/next.git" } } diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/.editorconfig b/packages/material-parser/test/fixtures/fusion-next-component/src/.editorconfig new file mode 100644 index 000000000..992ed3118 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/.editorconfig @@ -0,0 +1,22 @@ +# EditorConfig helps developers define and maintain consistent +# coding styles between different editors and IDEs +# editorconfig.org + +root = true + +# Apply for all files +[*] + +charset = utf-8 + +indent_style = space +indent_size = 4 + +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +# package.json +[package.json] +indent_size = 2 +indent_style = space diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/.eslintrc b/packages/material-parser/test/fixtures/fusion-next-component/src/.eslintrc new file mode 100644 index 000000000..41c30708c --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/.eslintrc @@ -0,0 +1,5 @@ +{ + "rules": { + "react/prefer-stateless-function": "off" + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/.stylelintrc b/packages/material-parser/test/fixtures/fusion-next-component/src/.stylelintrc new file mode 100644 index 000000000..71e5dbaf4 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/.stylelintrc @@ -0,0 +1,17 @@ +{ + "extends": [ + "@alifd/stylelint-config-next" + ], + "ignoreFiles": [ + "**/*.js", + "**/*.jsx" + ], + "rules": { + "max-nesting-depth": 4, + "max-empty-lines": 3, + "no-duplicate-selectors": null, + "no-descending-specificity": null, + "font-family-no-missing-generic-family-keyword": null, + "no-empty-source": null + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/affix/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/affix/container.js deleted file mode 100644 index 13a930414..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/affix/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Affix from './../../../../node_modules/@alife/next/es/affix/index.js'; - import manifest from './manifest.js'; - export default { origin: Affix, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/affix/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/affix/manifest.js deleted file mode 100644 index 751985edd..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/affix/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Affix","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/animate/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/animate/container.js deleted file mode 100644 index 16517b960..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/animate/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Animate from './../../../../node_modules/@alife/next/es/animate/index.js'; - import manifest from './manifest.js'; - export default { origin: Animate, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/animate/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/animate/manifest.js deleted file mode 100644 index 25911eb09..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/animate/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Animate","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/badge/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/badge/container.js deleted file mode 100644 index b7876c7bf..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/badge/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Badge from './../../../../node_modules/@alife/next/es/badge/index.js'; - import manifest from './manifest.js'; - export default { origin: Badge, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/badge/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/badge/manifest.js deleted file mode 100644 index 4ada9a631..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/badge/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Badge","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/balloon/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/balloon/container.js deleted file mode 100644 index 47b7966c7..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/balloon/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Balloon from './../../../../node_modules/@alife/next/es/balloon/index.js'; - import manifest from './manifest.js'; - export default { origin: Balloon, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/balloon/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/balloon/manifest.js deleted file mode 100644 index 5fcfc0d20..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/balloon/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Balloon","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/breadcrumb/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/breadcrumb/container.js deleted file mode 100644 index 74264a70e..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/breadcrumb/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Breadcrumb from './../../../../node_modules/@alife/next/es/breadcrumb/index.js'; - import manifest from './manifest.js'; - export default { origin: Breadcrumb, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/breadcrumb/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/breadcrumb/manifest.js deleted file mode 100644 index a07e03570..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/breadcrumb/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Breadcrumb","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/button/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/button/container.js deleted file mode 100644 index d7fc3dbfc..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/button/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Button from './../../../../node_modules/@alife/next/es/button/index.js'; - import manifest from './manifest.js'; - export default { origin: Button, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/button/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/button/manifest.js deleted file mode 100644 index fd75d2704..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/button/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Button","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/calendar/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/calendar/container.js deleted file mode 100644 index 14dcbf75d..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/calendar/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Calendar from './../../../../node_modules/@alife/next/es/calendar/index.js'; - import manifest from './manifest.js'; - export default { origin: Calendar, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/calendar/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/calendar/manifest.js deleted file mode 100644 index 5dce9f12c..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/calendar/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Calendar","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/card/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/card/container.js deleted file mode 100644 index db95955dc..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/card/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Card from './../../../../node_modules/@alife/next/es/card/index.js'; - import manifest from './manifest.js'; - export default { origin: Card, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/card/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/card/manifest.js deleted file mode 100644 index 55f71864d..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/card/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Card","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/cascader-select/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/cascader-select/container.js deleted file mode 100644 index 6a2830156..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/cascader-select/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import CascaderSelect from './../../../../node_modules/@alife/next/es/cascader-select/index.js'; - import manifest from './manifest.js'; - export default { origin: CascaderSelect, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/cascader-select/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/cascader-select/manifest.js deleted file mode 100644 index 5feab3aba..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/cascader-select/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"CascaderSelect","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/cascader/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/cascader/container.js deleted file mode 100644 index 4fbf15b03..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/cascader/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Cascader from './../../../../node_modules/@alife/next/es/cascader/index.js'; - import manifest from './manifest.js'; - export default { origin: Cascader, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/cascader/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/cascader/manifest.js deleted file mode 100644 index 64d37a979..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/cascader/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Cascader","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/checkbox/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/checkbox/container.js deleted file mode 100644 index 2652db1f6..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/checkbox/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Checkbox from './../../../../node_modules/@alife/next/es/checkbox/index.js'; - import manifest from './manifest.js'; - export default { origin: Checkbox, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/checkbox/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/checkbox/manifest.js deleted file mode 100644 index 70693a4fa..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/checkbox/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Checkbox","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/collapse/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/collapse/container.js deleted file mode 100644 index ff841a57d..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/collapse/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Collapse from './../../../../node_modules/@alife/next/es/collapse/index.js'; - import manifest from './manifest.js'; - export default { origin: Collapse, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/collapse/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/collapse/manifest.js deleted file mode 100644 index 1405b1121..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/collapse/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Collapse","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/config-provider/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/config-provider/container.js deleted file mode 100644 index d9af8c127..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/config-provider/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import ConfigProvider from './../../../../node_modules/@alife/next/es/config-provider/index.js'; - import manifest from './manifest.js'; - export default { origin: ConfigProvider, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/config-provider/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/config-provider/manifest.js deleted file mode 100644 index 85fa49736..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/config-provider/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"ConfigProvider","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/date-picker/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/date-picker/container.js deleted file mode 100644 index 68147708e..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/date-picker/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import DatePicker from './../../../../node_modules/@alife/next/es/date-picker/index.js'; - import manifest from './manifest.js'; - export default { origin: DatePicker, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/date-picker/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/date-picker/manifest.js deleted file mode 100644 index e22f21a35..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/date-picker/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"DatePicker","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/dialog/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/dialog/container.js deleted file mode 100644 index af202aab6..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/dialog/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Dialog from './../../../../node_modules/@alife/next/es/dialog/index.js'; - import manifest from './manifest.js'; - export default { origin: Dialog, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/dialog/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/dialog/manifest.js deleted file mode 100644 index a39a549b6..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/dialog/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Dialog","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/drawer/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/drawer/container.js deleted file mode 100644 index 16b254479..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/drawer/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Drawer from './../../../../node_modules/@alife/next/es/drawer/index.js'; - import manifest from './manifest.js'; - export default { origin: Drawer, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/drawer/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/drawer/manifest.js deleted file mode 100644 index a9e76e428..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/drawer/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Drawer","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/dropdown/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/dropdown/container.js deleted file mode 100644 index f789fde88..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/dropdown/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Dropdown from './../../../../node_modules/@alife/next/es/dropdown/index.js'; - import manifest from './manifest.js'; - export default { origin: Dropdown, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/dropdown/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/dropdown/manifest.js deleted file mode 100644 index 4cf365f09..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/dropdown/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Dropdown","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/field/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/field/container.js deleted file mode 100644 index 67e11c4a4..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/field/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Field from './../../../../node_modules/@alife/next/es/field/index.js'; - import manifest from './manifest.js'; - export default { origin: Field, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/field/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/field/manifest.js deleted file mode 100644 index 9b35e62d4..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/field/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Field","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/form/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/form/container.js deleted file mode 100644 index 821ca7a0d..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/form/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Form from './../../../../node_modules/@alife/next/es/form/index.js'; - import manifest from './manifest.js'; - export default { origin: Form, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/form/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/form/manifest.js deleted file mode 100644 index a855da347..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/form/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Form","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/grid/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/grid/container.js deleted file mode 100644 index 347bff542..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/grid/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Grid from './../../../../node_modules/@alife/next/es/grid/index.js'; - import manifest from './manifest.js'; - export default { origin: Grid, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/grid/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/grid/manifest.js deleted file mode 100644 index 740bf24ec..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/grid/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Grid","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/icon/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/icon/container.js deleted file mode 100644 index fb846969a..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/icon/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Icon from './../../../../node_modules/@alife/next/es/icon/index.js'; - import manifest from './manifest.js'; - export default { origin: Icon, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/icon/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/icon/manifest.js deleted file mode 100644 index a43b02674..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/icon/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Icon","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/input/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/input/container.js deleted file mode 100644 index d76c65b3e..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/input/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Input from './../../../../node_modules/@alife/next/es/input/index.js'; - import manifest from './manifest.js'; - export default { origin: Input, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/input/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/input/manifest.js deleted file mode 100644 index bc304458a..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/input/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Input","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/loading/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/loading/container.js deleted file mode 100644 index 0f2a50195..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/loading/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Loading from './../../../../node_modules/@alife/next/es/loading/index.js'; - import manifest from './manifest.js'; - export default { origin: Loading, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/loading/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/loading/manifest.js deleted file mode 100644 index fbabd53fb..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/loading/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Loading","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/menu-button/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/menu-button/container.js deleted file mode 100644 index 0ced35241..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/menu-button/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import MenuButton from './../../../../node_modules/@alife/next/es/menu-button/index.js'; - import manifest from './manifest.js'; - export default { origin: MenuButton, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/menu-button/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/menu-button/manifest.js deleted file mode 100644 index 275424364..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/menu-button/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"MenuButton","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/menu/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/menu/container.js deleted file mode 100644 index 27ca1f129..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/menu/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Menu from './../../../../node_modules/@alife/next/es/menu/index.js'; - import manifest from './manifest.js'; - export default { origin: Menu, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/menu/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/menu/manifest.js deleted file mode 100644 index 437244640..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/menu/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Menu","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/message/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/message/container.js deleted file mode 100644 index 8ff60abe5..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/message/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Message from './../../../../node_modules/@alife/next/es/message/index.js'; - import manifest from './manifest.js'; - export default { origin: Message, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/message/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/message/manifest.js deleted file mode 100644 index 1c6447d74..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/message/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Message","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/nav/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/nav/container.js deleted file mode 100644 index 14c714668..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/nav/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Nav from './../../../../node_modules/@alife/next/es/nav/index.js'; - import manifest from './manifest.js'; - export default { origin: Nav, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/nav/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/nav/manifest.js deleted file mode 100644 index ce358a0ce..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/nav/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Nav","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/number-picker/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/number-picker/container.js deleted file mode 100644 index 968721f57..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/number-picker/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import NumberPicker from './../../../../node_modules/@alife/next/es/number-picker/index.js'; - import manifest from './manifest.js'; - export default { origin: NumberPicker, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/number-picker/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/number-picker/manifest.js deleted file mode 100644 index 62315f984..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/number-picker/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"NumberPicker","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/overlay/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/overlay/container.js deleted file mode 100644 index 990cca3b2..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/overlay/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Overlay from './../../../../node_modules/@alife/next/es/overlay/index.js'; - import manifest from './manifest.js'; - export default { origin: Overlay, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/overlay/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/overlay/manifest.js deleted file mode 100644 index 76377394a..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/overlay/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Overlay","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/pagination/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/pagination/container.js deleted file mode 100644 index cbe654f0f..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/pagination/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Pagination from './../../../../node_modules/@alife/next/es/pagination/index.js'; - import manifest from './manifest.js'; - export default { origin: Pagination, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/pagination/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/pagination/manifest.js deleted file mode 100644 index 1429fc61c..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/pagination/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Pagination","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/paragraph/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/paragraph/container.js deleted file mode 100644 index 54a9aa717..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/paragraph/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Paragraph from './../../../../node_modules/@alife/next/es/paragraph/index.js'; - import manifest from './manifest.js'; - export default { origin: Paragraph, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/paragraph/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/paragraph/manifest.js deleted file mode 100644 index 1ccb54b91..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/paragraph/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Paragraph","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/progress/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/progress/container.js deleted file mode 100644 index 89ac33303..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/progress/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Progress from './../../../../node_modules/@alife/next/es/progress/index.js'; - import manifest from './manifest.js'; - export default { origin: Progress, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/progress/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/progress/manifest.js deleted file mode 100644 index fc3545779..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/progress/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Progress","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/radio/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/radio/container.js deleted file mode 100644 index 55d9817f4..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/radio/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Radio from './../../../../node_modules/@alife/next/es/radio/index.js'; - import manifest from './manifest.js'; - export default { origin: Radio, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/radio/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/radio/manifest.js deleted file mode 100644 index 5f9f0db17..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/radio/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Radio","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/range/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/range/container.js deleted file mode 100644 index 651475782..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/range/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Range from './../../../../node_modules/@alife/next/es/range/index.js'; - import manifest from './manifest.js'; - export default { origin: Range, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/range/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/range/manifest.js deleted file mode 100644 index ca54d4334..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/range/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Range","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/rating/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/rating/container.js deleted file mode 100644 index cecf9c9a1..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/rating/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Rating from './../../../../node_modules/@alife/next/es/rating/index.js'; - import manifest from './manifest.js'; - export default { origin: Rating, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/rating/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/rating/manifest.js deleted file mode 100644 index ec43231f1..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/rating/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Rating","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/search/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/search/container.js deleted file mode 100644 index 3155aa955..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/search/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Search from './../../../../node_modules/@alife/next/es/search/index.js'; - import manifest from './manifest.js'; - export default { origin: Search, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/search/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/search/manifest.js deleted file mode 100644 index 1bcd6fb68..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/search/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Search","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/select/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/select/container.js deleted file mode 100644 index cdce4e83f..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/select/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Select from './../../../../node_modules/@alife/next/es/select/index.js'; - import manifest from './manifest.js'; - export default { origin: Select, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/select/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/select/manifest.js deleted file mode 100644 index a8b4cd1da..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/select/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Select","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/slider/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/slider/container.js deleted file mode 100644 index 6d78d11f7..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/slider/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Slider from './../../../../node_modules/@alife/next/es/slider/index.js'; - import manifest from './manifest.js'; - export default { origin: Slider, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/slider/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/slider/manifest.js deleted file mode 100644 index e584440fe..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/slider/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Slider","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/split-button/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/split-button/container.js deleted file mode 100644 index fa7fc2ede..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/split-button/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import SplitButton from './../../../../node_modules/@alife/next/es/split-button/index.js'; - import manifest from './manifest.js'; - export default { origin: SplitButton, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/split-button/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/split-button/manifest.js deleted file mode 100644 index 1ad543cd9..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/split-button/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"SplitButton","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/step/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/step/container.js deleted file mode 100644 index 3ed16a4d6..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/step/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Step from './../../../../node_modules/@alife/next/es/step/index.js'; - import manifest from './manifest.js'; - export default { origin: Step, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/step/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/step/manifest.js deleted file mode 100644 index 3589863c8..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/step/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Step","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/switch/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/switch/container.js deleted file mode 100644 index f2b18420b..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/switch/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Switch from './../../../../node_modules/@alife/next/es/switch/index.js'; - import manifest from './manifest.js'; - export default { origin: Switch, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/switch/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/switch/manifest.js deleted file mode 100644 index 374b84938..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/switch/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Switch","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/tab/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/tab/container.js deleted file mode 100644 index f926d23c7..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/tab/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Tab from './../../../../node_modules/@alife/next/es/tab/index.js'; - import manifest from './manifest.js'; - export default { origin: Tab, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/tab/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/tab/manifest.js deleted file mode 100644 index 163f3b630..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/tab/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Tab","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/table/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/table/container.js deleted file mode 100644 index 9e939eef5..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/table/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Table from './../../../../node_modules/@alife/next/es/table/index.js'; - import manifest from './manifest.js'; - export default { origin: Table, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/table/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/table/manifest.js deleted file mode 100644 index 88898f698..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/table/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Table","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/tag/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/tag/container.js deleted file mode 100644 index 2255f4d53..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/tag/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import ConfigTag from './../../../../node_modules/@alife/next/es/tag/index.js'; - import manifest from './manifest.js'; - export default { origin: ConfigTag, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/tag/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/tag/manifest.js deleted file mode 100644 index 0fb0a2cfe..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/tag/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"ConfigTag","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/time-picker/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/time-picker/container.js deleted file mode 100644 index 4cbec7206..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/time-picker/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import TimePicker from './../../../../node_modules/@alife/next/es/time-picker/index.js'; - import manifest from './manifest.js'; - export default { origin: TimePicker, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/time-picker/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/time-picker/manifest.js deleted file mode 100644 index 545dcb01c..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/time-picker/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"TimePicker","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/timeline/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/timeline/container.js deleted file mode 100644 index 2fd586c95..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/timeline/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Timeline from './../../../../node_modules/@alife/next/es/timeline/index.js'; - import manifest from './manifest.js'; - export default { origin: Timeline, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/timeline/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/timeline/manifest.js deleted file mode 100644 index f83c63788..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/timeline/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Timeline","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/transfer/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/transfer/container.js deleted file mode 100644 index 8079114ff..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/transfer/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Transfer from './../../../../node_modules/@alife/next/es/transfer/index.js'; - import manifest from './manifest.js'; - export default { origin: Transfer, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/transfer/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/transfer/manifest.js deleted file mode 100644 index 087080712..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/transfer/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Transfer","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/tree-select/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/tree-select/container.js deleted file mode 100644 index ea7cab05a..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/tree-select/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import TreeSelect from './../../../../node_modules/@alife/next/es/tree-select/index.js'; - import manifest from './manifest.js'; - export default { origin: TreeSelect, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/tree-select/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/tree-select/manifest.js deleted file mode 100644 index b87595af2..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/tree-select/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"TreeSelect","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/tree/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/tree/container.js deleted file mode 100644 index c474b1396..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/tree/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Tree from './../../../../node_modules/@alife/next/es/tree/index.js'; - import manifest from './manifest.js'; - export default { origin: Tree, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/tree/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/tree/manifest.js deleted file mode 100644 index 8a59f7b3e..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/tree/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Tree","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/upload/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/upload/container.js deleted file mode 100644 index 5acf79fab..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/upload/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import Upload from './../../../../node_modules/@alife/next/es/upload/index.js'; - import manifest from './manifest.js'; - export default { origin: Upload, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/upload/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/upload/manifest.js deleted file mode 100644 index f7fbe355a..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/upload/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"Upload","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/virtual-list/container.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/virtual-list/container.js deleted file mode 100644 index 9de0aae6a..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/virtual-list/container.js +++ /dev/null @@ -1,5 +0,0 @@ - - import VirtualList from './../../../../node_modules/@alife/next/es/virtual-list/index.js'; - import manifest from './manifest.js'; - export default { origin: VirtualList, manifest }; - \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/virtual-list/manifest.js b/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/virtual-list/manifest.js deleted file mode 100644 index c9b1776ad..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/@alife/next/virtual-list/manifest.js +++ /dev/null @@ -1 +0,0 @@ -const manifest = {"name":"VirtualList","settings":{"type":"element_inline","insertionModes":"tbrl","handles":["cut","copy","duplicate","delete","paste"],"shouldActive":true,"shouldDrag":true,"props":[]}}; export default manifest; \ No newline at end of file diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/affix/index.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/affix/index.jsx new file mode 100644 index 000000000..dd15c28d0 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/affix/index.jsx @@ -0,0 +1,280 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import { findDOMNode } from 'react-dom'; +import { polyfill } from 'react-lifecycles-compat'; + +import { obj, events, func } from '../util'; +import ConfigProvider from '../config-provider'; +import { getScroll, getRect, getNodeHeight } from './util'; + +/** Affix */ +class Affix extends React.Component { + static propTypes = { + prefix: PropTypes.string, + /** + * 设置 Affix 需要监听滚动事件的容器元素 + * @return {ReactElement} 目标容器元素的实例 + */ + container: PropTypes.func, + /** + * 距离窗口顶部达到指定偏移量后触发 + */ + offsetTop: PropTypes.number, + /** + * 距离窗口底部达到制定偏移量后触发 + */ + offsetBottom: PropTypes.number, + /** + * 当元素的样式发生固钉样式变化时触发的回调函数 + * @param {Boolean} affixed 元素是否被固钉 + */ + onAffix: PropTypes.func, + /** + * 是否启用绝对布局实现 affix + * @param {Boolean} 是否启用绝对布局 + */ + useAbsolute: PropTypes.bool, + className: PropTypes.string, + style: PropTypes.object, + children: PropTypes.any, + }; + + static defaultProps = { + prefix: 'next-', + container: () => window, + onAffix: func.noop, + }; + + static _getAffixMode(nextProps) { + const affixMode = { + top: false, + bottom: false, + offset: 0, + }; + if (!nextProps) { + return affixMode; + } + const { offsetTop, offsetBottom } = nextProps; + + if (typeof offsetTop !== 'number' && typeof offsetBottom !== 'number') { + // set default + affixMode.top = true; + } else if (typeof offsetTop === 'number') { + affixMode.top = true; + affixMode.bottom = false; + affixMode.offset = offsetTop; + } else if (typeof offsetBottom === 'number') { + affixMode.bottom = true; + affixMode.top = false; + affixMode.offset = offsetBottom; + } + + return affixMode; + } + + constructor(props, context) { + super(props, context); + this.state = { + style: null, + containerStyle: null, + affixMode: Affix._getAffixMode(props), + }; + } + + static getDerivedStateFromProps(nextProps, prevState) { + if ('offsetTop' in nextProps || 'offsetBottom' in nextProps) { + return { + affixMode: Affix._getAffixMode(nextProps), + }; + } + return null; + } + + componentDidMount() { + const { container } = this.props; + this._updateNodePosition(); + // wait for parent rendered + this.timeout = setTimeout(() => { + this._setEventHandlerForContainer(container); + }); + } + + componentDidUpdate(prevProps, prevState, snapshot) { + setTimeout(this._updateNodePosition); + } + + componentWillUnmount() { + if (this.timeout) { + clearTimeout(this.timeout); + this.timeout = null; + } + const { container } = this.props; + this._removeEventHandlerForContainer(container); + } + + _setEventHandlerForContainer(getContainer) { + const container = getContainer(); + if (!container) { + return; + } + events.on(container, 'scroll', this._updateNodePosition, false); + events.on(container, 'resize', this._updateNodePosition, false); + } + + _removeEventHandlerForContainer(getContainer) { + const container = getContainer(); + if (container) { + events.off(container, 'scroll', this._updateNodePosition); + events.off(container, 'resize', this._updateNodePosition); + } + } + + updatePosition = () => { + this._updateNodePosition(); + }; + + _updateNodePosition = () => { + const { affixMode } = this.state; + const { container, useAbsolute } = this.props; + const affixContainer = container(); + + if (!affixContainer || !this.affixNode) { + return false; + } + const containerScrollTop = getScroll(affixContainer, true); // 容器在垂直位置上的滚动 offset + const affixOffset = this._getOffset(this.affixNode, affixContainer); // 目标节点当前相对于容器的 offset + const containerHeight = getNodeHeight(affixContainer); // 容器的高度 + const affixHeight = this.affixNode.offsetHeight; + const containerRect = getRect(affixContainer); + + const affixChildHeight = this.affixChildNode.offsetHeight; + + const affixStyle = { + width: affixOffset.width, + }; + const containerStyle = { + width: affixOffset.width, + height: affixChildHeight, + }; + if ( + affixMode.top && + containerScrollTop > affixOffset.top - affixMode.offset + ) { + // affix top + if (useAbsolute) { + affixStyle.position = 'absolute'; + affixStyle.top = + containerScrollTop - (affixOffset.top - affixMode.offset); + containerStyle.position = 'relative'; + } else { + affixStyle.position = 'fixed'; + affixStyle.top = affixMode.offset + containerRect.top; + } + this._setAffixStyle(affixStyle, true); + this._setContainerStyle(containerStyle); + } else if ( + affixMode.bottom && + containerScrollTop < + affixOffset.top + + affixHeight + + affixMode.offset - + containerHeight + ) { + // affix bottom + affixStyle.height = affixHeight; + if (useAbsolute) { + affixStyle.position = 'absolute'; + affixStyle.top = + containerScrollTop - + (affixOffset.top + + affixHeight + + affixMode.offset - + containerHeight); + containerStyle.position = 'relative'; + } else { + affixStyle.position = 'fixed'; + affixStyle.bottom = affixMode.offset; + } + this._setAffixStyle(affixStyle, true); + this._setContainerStyle(containerStyle); + } else { + this._setAffixStyle(null); + this._setContainerStyle(null); + } + }; + + _setAffixStyle(affixStyle, affixed = false) { + if (obj.shallowEqual(affixStyle, this.state.style)) { + return; + } + + this.setState({ + style: affixStyle, + }); + + const { onAffix } = this.props; + + if (affixed) { + setTimeout(() => onAffix(true)); + } else if (!affixStyle) { + setTimeout(() => onAffix(false)); + } + } + + _setContainerStyle(containerStyle) { + if (obj.shallowEqual(containerStyle, this.state.containerStyle)) { + return; + } + this.setState({ containerStyle }); + } + + _getOffset(affixNode, affixContainer) { + const affixRect = affixNode.getBoundingClientRect(); // affix 元素 相对浏览器窗口的位置 + const containerRect = getRect(affixContainer); // affix 容器 相对浏览器窗口的位置 + const containerScrollTop = getScroll(affixContainer, true); + const containerScrollLeft = getScroll(affixContainer, false); + + return { + top: affixRect.top - containerRect.top + containerScrollTop, + left: affixRect.left - containerRect.left + containerScrollLeft, + width: affixRect.width, + height: affixRect.height, + }; + } + + _affixNodeRefHandler = ref => { + this.affixNode = findDOMNode(ref); + }; + + _affixChildNodeRefHandler = ref => { + this.affixChildNode = findDOMNode(ref); + }; + + render() { + const { affixMode } = this.state; + const { prefix, className, style, children } = this.props; + const state = this.state; + const classNames = classnames({ + [`${prefix}affix`]: state.style, + [`${prefix}affix-top`]: !state.style && affixMode.top, + [`${prefix}affix-bottom`]: !state.style && affixMode.bottom, + [className]: className, + }); + const combinedStyle = { ...state.containerStyle, ...style }; + + return ( +
+
+ {children} +
+
+ ); + } +} + +export default ConfigProvider.config(polyfill(Affix)); diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/affix/main.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/affix/main.scss new file mode 100644 index 000000000..ce3cb5e76 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/affix/main.scss @@ -0,0 +1 @@ +/* stylelint-disable-next-line */ diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/affix/style.js b/packages/material-parser/test/fixtures/fusion-next-component/src/affix/style.js new file mode 100644 index 000000000..f1ad40f46 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/affix/style.js @@ -0,0 +1 @@ +import './main.scss'; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/affix/util.js b/packages/material-parser/test/fixtures/fusion-next-component/src/affix/util.js new file mode 100644 index 000000000..6a7e82b98 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/affix/util.js @@ -0,0 +1,24 @@ +export function getScroll(node, isVertical) { + if (typeof window === 'undefined') { + return 0; + } + const windowProp = isVertical ? 'pageYOffset' : 'pageXOffset'; + const elementProp = isVertical ? 'scrollTop' : 'scrollLeft'; + return node === window ? node[windowProp] : node[elementProp]; +} + +export function getRect(node) { + return node !== window + ? node.getBoundingClientRect() + : { top: 0, left: 0, bottom: 0 }; +} + +export function getNodeHeight(node) { + if (!node) { + return 0; + } + if (node === window) { + return window.innerHeight; + } + return node.clientHeight; +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/.stylelintrc b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/.stylelintrc new file mode 100644 index 000000000..3e4c91025 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/.stylelintrc @@ -0,0 +1,9 @@ +{ + "extends": [ + "@alifd/stylelint-config-next" + ], + "rules": { + "selector-class-pattern": null, + "scss/at-mixin-pattern": null + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/animate.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/animate.jsx new file mode 100644 index 000000000..28c239ef3 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/animate.jsx @@ -0,0 +1,178 @@ +import React, { Component, Children } from 'react'; +import PropTypes from 'prop-types'; +import { TransitionGroup } from 'react-transition-group'; +import AnimateChild from './child'; + +const noop = () => {}; +const FirstChild = props => { + const childrenArray = React.Children.toArray(props.children); + return childrenArray[0] || null; +}; + +/** + * Animate + */ +class Animate extends Component { + static propTypes = { + /** + * 动画 className + */ + animation: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), + /** + * 子元素第一次挂载时是否执行动画 + */ + animationAppear: PropTypes.bool, + /** + * 包裹子元素的标签 + */ + component: PropTypes.any, + /** + * 是否只有单个子元素,如果有多个子元素,请设置为 false + */ + singleMode: PropTypes.bool, + /** + * 子元素 + */ + children: PropTypes.oneOfType([ + PropTypes.element, + PropTypes.arrayOf(PropTypes.element), + ]), + /** + * 执行第一次挂载动画前触发的回调函数 + * @param {HTMLElement} node 执行动画的 dom 元素 + */ + beforeAppear: PropTypes.func, + /** + * 执行第一次挂载动画,添加 xxx-appear-active 类名后触发的回调函数 + * @param {HTMLElement} node 执行动画的 dom 元素 + */ + onAppear: PropTypes.func, + /** + * 执行完第一次挂载动画后触发的函数 + * @param {HTMLElement} node 执行动画的 dom 元素 + */ + afterAppear: PropTypes.func, + /** + * 执行进场动画前触发的回调函数 + * @param {HTMLElement} node 执行动画的 dom 元素 + */ + beforeEnter: PropTypes.func, + /** + * 执行进场动画,添加 xxx-enter-active 类名后触发的回调函数 + * @param {HTMLElement} node 执行动画的 dom 元素 + */ + onEnter: PropTypes.func, + /** + * 执行完进场动画后触发的回调函数 + * @param {HTMLElement} node 执行动画的 dom 元素 + */ + afterEnter: PropTypes.func, + /** + * 执行离场动画前触发的回调函数 + * @param {HTMLElement} node 执行动画的 dom 元素 + */ + beforeLeave: PropTypes.func, + /** + * 执行离场动画,添加 xxx-leave-active 类名后触发的回调函数 + * @param {HTMLElement} node 执行动画的 dom 元素 + */ + onLeave: PropTypes.func, + /** + * 执行完离场动画后触发的回调函数 + * @param {HTMLElement} node 执行动画的 dom 元素 + */ + afterLeave: PropTypes.func, + }; + + static defaultProps = { + animationAppear: true, + component: 'div', + singleMode: true, + beforeAppear: noop, + onAppear: noop, + afterAppear: noop, + beforeEnter: noop, + onEnter: noop, + afterEnter: noop, + beforeLeave: noop, + onLeave: noop, + afterLeave: noop, + }; + + normalizeNames(names) { + if (typeof names === 'string') { + return { + appear: `${names}-appear`, + appearActive: `${names}-appear-active`, + enter: `${names}-enter`, + enterActive: `${names}-enter-active`, + leave: `${names}-leave`, + leaveActive: `${names}-leave-active`, + }; + } + if (typeof names === 'object') { + return { + appear: names.appear, + appearActive: `${names.appear}-active`, + enter: `${names.enter}`, + enterActive: `${names.enter}-active`, + leave: `${names.leave}`, + leaveActive: `${names.leave}-active`, + }; + } + } + + render() { + /* eslint-disable no-unused-vars */ + const { + animation, + children, + animationAppear, + singleMode, + component, + beforeAppear, + onAppear, + afterAppear, + beforeEnter, + onEnter, + afterEnter, + beforeLeave, + onLeave, + afterLeave, + ...others + } = this.props; + /* eslint-enable no-unused-vars */ + + const animateChildren = Children.map(children, child => { + return ( + + {child} + + ); + }); + + return ( + + {animateChildren} + + ); + } +} + +export default Animate; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/child.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/child.jsx new file mode 100644 index 000000000..1210b2f82 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/child.jsx @@ -0,0 +1,263 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { Transition } from 'react-transition-group'; +import { func, support, events, dom, guid } from '../util'; + +const noop = () => {}; +const { on, off } = events; +const { addClass, removeClass } = dom; +const prefixes = ['-webkit-', '-moz-', '-o-', 'ms-', '']; + +function getStyleProperty(node, name) { + const style = window.getComputedStyle(node); + let ret = ''; + for (let i = 0; i < prefixes.length; i++) { + ret = style.getPropertyValue(prefixes[i] + name); + if (ret) { + break; + } + } + return ret; +} + +export default class AnimateChild extends Component { + static propTypes = { + names: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), + onAppear: PropTypes.func, + onAppearing: PropTypes.func, + onAppeared: PropTypes.func, + onEnter: PropTypes.func, + onEntering: PropTypes.func, + onEntered: PropTypes.func, + onExit: PropTypes.func, + onExiting: PropTypes.func, + onExited: PropTypes.func, + }; + + static defaultProps = { + onAppear: noop, + onAppearing: noop, + onAppeared: noop, + onEnter: noop, + onEntering: noop, + onEntered: noop, + onExit: noop, + onExiting: noop, + onExited: noop, + }; + + constructor(props) { + super(props); + func.bindCtx(this, [ + 'handleEnter', + 'handleEntering', + 'handleEntered', + 'handleExit', + 'handleExiting', + 'handleExited', + 'addEndListener', + ]); + this.endListeners = { + transitionend: [], + animationend: [], + }; + this.timeoutMap = {}; + } + + componentWillUnmount() { + Object.keys(this.endListeners).forEach(eventName => { + this.endListeners[eventName].forEach(listener => { + off(this.node, eventName, listener); + }); + }); + this.endListeners = { + transitionend: [], + animationend: [], + }; + } + + generateEndListener(node, done, eventName, id) { + const _this = this; + return function endListener(e) { + if (e && e.target === node) { + if (_this.timeoutMap[id]) { + clearTimeout(_this.timeoutMap[id]); + delete _this.timeoutMap[id]; + } + + done(); + off(node, eventName, endListener); + const listeners = _this.endListeners[eventName]; + const index = listeners.indexOf(endListener); + index > -1 && listeners.splice(index, 1); + } + }; + } + + addEndListener(node, done) { + if (support.transition || support.animation) { + const id = guid(); + + this.node = node; + if (support.transition) { + const transitionEndListener = this.generateEndListener( + node, + done, + 'transitionend', + id + ); + on(node, 'transitionend', transitionEndListener); + this.endListeners.transitionend.push(transitionEndListener); + } + if (support.animation) { + const animationEndListener = this.generateEndListener( + node, + done, + 'animationend', + id + ); + on(node, 'animationend', animationEndListener); + this.endListeners.animationend.push(animationEndListener); + } + + setTimeout(() => { + const transitionDelay = + parseFloat(getStyleProperty(node, 'transition-delay')) || 0; + const transitionDuration = + parseFloat(getStyleProperty(node, 'transition-duration')) || + 0; + const animationDelay = + parseFloat(getStyleProperty(node, 'animation-delay')) || 0; + const animationDuration = + parseFloat(getStyleProperty(node, 'animation-duration')) || + 0; + const time = Math.max( + transitionDuration + transitionDelay, + animationDuration + animationDelay + ); + if (time) { + this.timeoutMap[id] = setTimeout(() => { + done(); + }, time * 1000 + 200); + } + }, 15); + } else { + done(); + } + } + + removeEndtListener() { + this.transitionOff && this.transitionOff(); + this.animationOff && this.animationOff(); + } + + removeClassNames(node, names) { + Object.keys(names).forEach(key => { + removeClass(node, names[key]); + }); + } + + handleEnter(node, isAppearing) { + const { names } = this.props; + if (names) { + this.removeClassNames(node, names); + const className = isAppearing ? 'appear' : 'enter'; + addClass(node, names[className]); + } + + const hook = isAppearing ? this.props.onAppear : this.props.onEnter; + hook(node); + } + + handleEntering(node, isAppearing) { + setTimeout(() => { + const { names } = this.props; + if (names) { + const className = isAppearing ? 'appearActive' : 'enterActive'; + addClass(node, names[className]); + } + + const hook = isAppearing + ? this.props.onAppearing + : this.props.onEntering; + hook(node); + }, 10); + } + + handleEntered(node, isAppearing) { + const { names } = this.props; + if (names) { + const classNames = isAppearing + ? [names.appear, names.appearActive] + : [names.enter, names.enterActive]; + classNames.forEach(className => { + removeClass(node, className); + }); + } + + const hook = isAppearing ? this.props.onAppeared : this.props.onEntered; + hook(node); + } + + handleExit(node) { + const { names } = this.props; + if (names) { + this.removeClassNames(node, names); + addClass(node, names.leave); + } + + this.props.onExit(node); + } + + handleExiting(node) { + setTimeout(() => { + const { names } = this.props; + if (names) { + addClass(node, names.leaveActive); + } + this.props.onExiting(node); + }, 10); + } + + handleExited(node) { + const { names } = this.props; + if (names) { + [names.leave, names.leaveActive].forEach(className => { + removeClass(node, className); + }); + } + + this.props.onExited(node); + } + + render() { + /* eslint-disable no-unused-vars */ + const { + names, + onAppear, + onAppeared, + onAppearing, + onEnter, + onEntering, + onEntered, + onExit, + onExiting, + onExited, + ...others + } = this.props; + /* eslint-enable no-unused-vars */ + + return ( + + ); + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/expand.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/expand.jsx new file mode 100644 index 000000000..6bc06fa16 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/expand.jsx @@ -0,0 +1,146 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { func, dom } from '../util'; +import Animate from './animate'; + +const noop = () => {}; +const { getStyle } = dom; + +export default class Expand extends Component { + static propTypes = { + animation: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), + beforeEnter: PropTypes.func, + onEnter: PropTypes.func, + afterEnter: PropTypes.func, + beforeLeave: PropTypes.func, + onLeave: PropTypes.func, + afterLeave: PropTypes.func, + }; + + static defaultProps = { + beforeEnter: noop, + onEnter: noop, + afterEnter: noop, + beforeLeave: noop, + onLeave: noop, + afterLeave: noop, + }; + + constructor(props) { + super(props); + func.bindCtx(this, [ + 'beforeEnter', + 'onEnter', + 'afterEnter', + 'beforeLeave', + 'onLeave', + 'afterLeave', + ]); + } + + beforeEnter(node) { + if (this.leaving) { + this.afterLeave(node); + } + + this.cacheCurrentStyle(node); + this.cacheComputedStyle(node); + this.setCurrentStyleToZero(node); + + this.props.beforeEnter(node); + } + + onEnter(node) { + this.setCurrentStyleToComputedStyle(node); + + this.props.onEnter(node); + } + + afterEnter(node) { + this.restoreCurrentStyle(node); + + this.props.afterEnter(node); + } + + beforeLeave(node) { + this.leaving = true; + + this.cacheCurrentStyle(node); + this.cacheComputedStyle(node); + this.setCurrentStyleToComputedStyle(node); + + this.props.beforeLeave(node); + } + + onLeave(node) { + this.setCurrentStyleToZero(node); + + this.props.onLeave(node); + } + + afterLeave(node) { + this.leaving = false; + + this.restoreCurrentStyle(node); + + this.props.afterLeave(node); + } + + cacheCurrentStyle(node) { + this.styleBorderTopWidth = node.style.borderTopWidth; + this.stylePaddingTop = node.style.paddingTop; + this.styleHeight = node.style.height; + this.stylePaddingBottom = node.style.paddingBottom; + this.styleBorderBottomWidth = node.style.borderBottomWidth; + } + + cacheComputedStyle(node) { + this.borderTopWidth = getStyle(node, 'borderTopWidth'); + this.paddingTop = getStyle(node, 'paddingTop'); + this.height = node.offsetHeight; + this.paddingBottom = getStyle(node, 'paddingBottom'); + this.borderBottomWidth = getStyle(node, 'borderBottomWidth'); + } + + setCurrentStyleToZero(node) { + node.style.borderTopWidth = '0px'; + node.style.paddingTop = '0px'; + node.style.height = '0px'; + node.style.paddingBottom = '0px'; + node.style.borderBottomWidth = '0px'; + } + + setCurrentStyleToComputedStyle(node) { + node.style.borderTopWidth = `${this.borderTopWidth}px`; + node.style.paddingTop = `${this.paddingTop}px`; + node.style.height = `${this.height}px`; + node.style.paddingBottom = `${this.paddingBottom}px`; + node.style.borderBottomWidth = `${this.borderBottomWidth}px`; + } + + restoreCurrentStyle(node) { + node.style.borderTopWidth = this.styleBorderTopWidth; + node.style.paddingTop = this.stylePaddingTop; + node.style.height = this.styleHeight; + node.style.paddingBottom = this.stylePaddingBottom; + node.style.borderBottomWidth = this.styleBorderBottomWidth; + } + + render() { + const { animation, ...others } = this.props; + const newAnimation = animation || 'expand'; + + return ( + + ); + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/index.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/index.jsx new file mode 100644 index 000000000..3666fddb5 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/index.jsx @@ -0,0 +1,6 @@ +import Animate from './animate'; +import Expand from './expand'; + +Animate.Expand = Expand; + +export default Animate; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/main.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/main.scss new file mode 100644 index 000000000..18b9d2c3f --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/main.scss @@ -0,0 +1,145 @@ +@import "scss/mixin"; +@import "scss/variable"; +@import "scss/_fading-entrances/_fadeIn.scss"; +@import "scss/_fading-entrances/_fadeInDown.scss"; +@import "scss/_fading-entrances/_fadeInLeft.scss"; +@import "scss/_fading-entrances/_fadeInRight.scss"; +@import "scss/_fading-entrances/_fadeInUp.scss"; +@import "scss/_fading-exits/_fadeOut.scss"; +@import "scss/_fading-exits/_fadeOutDown.scss"; +@import "scss/_fading-exits/_fadeOutLeft.scss"; +@import "scss/_fading-exits/_fadeOutRight.scss"; +@import "scss/_fading-exits/_fadeOutUp.scss"; +@import "scss/_sliding-exits/sliding-exits.scss"; +@import "scss/_sliding-entrances/sliding-entrances.scss"; +@import "scss/_zooming-entrances/_zoomIn.scss"; +@import "scss/_zooming-exits/_zoomOut.scss"; +@import "scss/_expand-entrances/_expandInDown.scss"; +@import "scss/_expand-entrances/_expandInUp.scss"; +@import "scss/_expand-entrances/_withFade.scss"; +@import "scss/_expand-exits/_expandOutUp.scss"; +@import "scss/_expand-exits/_expandOutDown.scss"; +@import "scss/_expand-exits/_withFade.scss"; +@import "scss/_attention-seekers/_pulse.scss"; + +.fadeIn { + @include fadeIn(); +} + +.fadeInDown { + @include fadeInDown(); +} + +.fadeInLeft { + @include fadeInLeft(); +} + +.fadeInRight { + @include fadeInRight(); +} + +.fadeInUp { + @include fadeInUp(); +} + +.fadeOut { + @include fadeOut(); +} + +.fadeOutDown { + @include fadeOutDown(); +} + +.fadeOutLeft { + @include fadeOutLeft(); +} + +.fadeOutRight { + @include fadeOutRight(); +} + +.fadeOutUp { + @include fadeOutUp(); +} + +.slideInUp { + @include slideInUp(); +} + +.slideInDown { + @include slideInDown(); +} + +.slideInLeft { + @include slideInLeft(); +} + +.slideInRight { + @include slideInRight(); +} + +.slideOutUp { + @include slideOutUp(); +} + +.slideOutRight { + @include slideOutRight(); +} + +.slideOutLeft { + @include slideOutLeft(); +} + +.slideOutDown { + @include slideOutDown(); +} + +.zoomIn { + @include zoomIn(); +} + +.zoomOut { + @include zoomOut(); +} + +.expandInDown { + @include expandInDown(); +} + +.expandOutUp { + @include expandOutUp(); +} + +.expandInUp { + @include expandInUp(); +} + +.expandOutDown { + @include expandOutDown(); +} + +.pulse { + @include pulse(); +} + +.expand-enter { + overflow: hidden; +} + +.expand-enter-active { + transition: all .3s ease-out; + & > * { + @include expandInWithFade(); + } +} + +.expand-leave { + overflow: hidden; +} + +.expand-leave-active { + transition: all .2s ease-out; + & > * { + @include expandOutWithFade(); + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_attention-seekers/_buttonClick.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_attention-seekers/_buttonClick.scss new file mode 100644 index 000000000..481ce9998 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_attention-seekers/_buttonClick.scss @@ -0,0 +1,14 @@ +@include keyframes(buttonClick) { + 50% { + @include transform(scale3d(.95, .95, .95)); + } +} +@mixin buttonClick($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $functionDefault, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(buttonClick); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_attention-seekers/_press.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_attention-seekers/_press.scss new file mode 100644 index 000000000..a52df20bf --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_attention-seekers/_press.scss @@ -0,0 +1,14 @@ +@include keyframes(press) { + 50% { + @include transform(scale3d(.7, .7, .7)); + } +} +@mixin press($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $functionDefault, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(press); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_attention-seekers/_pulse.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_attention-seekers/_pulse.scss new file mode 100644 index 000000000..efeb3439d --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_attention-seekers/_pulse.scss @@ -0,0 +1,21 @@ +@include keyframes(pulse) { + from { + @include transform(scale(1)); + } + 20% { + @include transform(scale(1.2)); + } + to { + @include transform(scale(1)); + } +} + +@mixin pulse($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $functionDefault, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(pulse); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_attention-seekers/_shake.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_attention-seekers/_shake.scss new file mode 100644 index 000000000..944281412 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_attention-seekers/_shake.scss @@ -0,0 +1,32 @@ +@include keyframes(shake) { + from, + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + 10%, + 30%, + 50%, + 70%, + 90% { + -webkit-transform: translate3d(-10px, 0, 0); + transform: translate3d(-10px, 0, 0); + } + 20%, + 40%, + 60%, + 80% { + -webkit-transform: translate3d(10px, 0, 0); + transform: translate3d(10px, 0, 0); + } +} + +@mixin shake($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $functionDefault, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(shake); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_attention-seekers/_unpress.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_attention-seekers/_unpress.scss new file mode 100644 index 000000000..9d9b0089b --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_attention-seekers/_unpress.scss @@ -0,0 +1,14 @@ +@include keyframes(unpress) { + 50% { + @include transform(scale3d(.7, .7, .7)); + } +} +@mixin unpress($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $functionDefault, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(unpress); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_attention-seekers/attention-seekers.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_attention-seekers/attention-seekers.scss new file mode 100644 index 000000000..42dbe936a --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_attention-seekers/attention-seekers.scss @@ -0,0 +1,7 @@ +// INDEX OF FADING EXITS + +@import "_pulse"; +@import "_shake"; +@import "_press"; +@import "_unpress"; +@import "_buttonClick"; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_bounce-entrances/_bounceIn.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_bounce-entrances/_bounceIn.scss new file mode 100644 index 000000000..e185d6c74 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_bounce-entrances/_bounceIn.scss @@ -0,0 +1,48 @@ +@include keyframes(bounceIn) { + from, + 20%, + 40%, + 60%, + 80%, + to { + -webkit-animation-timing-function: cubic-bezier(.215, .610, .355, 1.000); + animation-timing-function: cubic-bezier(.215, .610, .355, 1.000); + } + 0% { + opacity: 0; + -webkit-transform: scale3d(.3, .3, .3); + transform: scale3d(.3, .3, .3); + } + 20% { + -webkit-transform: scale3d(1.1, 1.1, 1.1); + transform: scale3d(1.1, 1.1, 1.1); + } + 40% { + -webkit-transform: scale3d(.9, .9, .9); + transform: scale3d(.9, .9, .9); + } + 60% { + opacity: 1; + -webkit-transform: scale3d(1.03, 1.03, 1.03); + transform: scale3d(1.03, 1.03, 1.03); + } + 80% { + -webkit-transform: scale3d(.97, .97, .97); + transform: scale3d(.97, .97, .97); + } + to { + opacity: 1; + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +@mixin bounceIn($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $ease-out-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(bounceIn); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_bounce-entrances/bounce-entrances.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_bounce-entrances/bounce-entrances.scss new file mode 100644 index 000000000..3a7e70557 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_bounce-entrances/bounce-entrances.scss @@ -0,0 +1,3 @@ +// INDEX OF FADING ENTRANCES + +@import "_bounceIn"; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_bounce-exits/_bounceOut.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_bounce-exits/_bounceOut.scss new file mode 100644 index 000000000..befe972ab --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_bounce-exits/_bounceOut.scss @@ -0,0 +1,27 @@ +@include keyframes(bounceOut) { + 20% { + -webkit-transform: scale3d(.9, .9, .9); + transform: scale3d(.9, .9, .9); + } + 50%, + 55% { + opacity: 1; + -webkit-transform: scale3d(1.1, 1.1, 1.1); + transform: scale3d(1.1, 1.1, 1.1); + } + to { + opacity: 0; + -webkit-transform: scale3d(.3, .3, .3); + transform: scale3d(.3, .3, .3); + } +} + +@mixin bounceOut($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $ease-in-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(bounceOut); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_bounce-exits/bounce-exits.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_bounce-exits/bounce-exits.scss new file mode 100644 index 000000000..c9c681c5f --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_bounce-exits/bounce-exits.scss @@ -0,0 +1,3 @@ +// INDEX OF FADING EXITS + +@import "_bounceOut"; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_expand-entrances/_expandInDown.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_expand-entrances/_expandInDown.scss new file mode 100644 index 000000000..ce8cd2a17 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_expand-entrances/_expandInDown.scss @@ -0,0 +1,22 @@ +@include keyframes(expandInDown) { + 0% { + opacity: 0; + @include transform(scaleY(.6)); + @include transform-origin(left top 0); + } + 100% { + opacity: 1; + @include transform(scaleY(1)); + @include transform-origin(left top 0); + } +} + +@mixin expandInDown($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $functionDefault, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(expandInDown); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_expand-entrances/_expandInUp.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_expand-entrances/_expandInUp.scss new file mode 100644 index 000000000..82db15d8f --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_expand-entrances/_expandInUp.scss @@ -0,0 +1,22 @@ +@include keyframes(expandInUp) { + 0% { + opacity: 0; + @include transform(scaleY(.6)); + @include transform-origin(left bottom 0); + } + 100% { + opacity: 1; + @include transform(scaleY(1)); + @include transform-origin(left bottom 0); + } +} + +@mixin expandInUp($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $functionDefault, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(expandInUp); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_expand-entrances/_withFade.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_expand-entrances/_withFade.scss new file mode 100644 index 000000000..b349946c4 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_expand-entrances/_withFade.scss @@ -0,0 +1,24 @@ +@include keyframes(expandInWithFade) { + 0% { + opacity: 0; + } + 40% { + opacity: .1; + } + 50% { + opacity: .9; + } + 100% { + opacity: 1; + } +} + +@mixin expandInWithFade($count: $countDefault, $duration: .2s, $delay: $delayDefault, $function: $functionDefault, $fill: 'forwards', $visibility: $visibilityDefault) { + @include animation-name(expandInWithFade); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_expand-exits/_expandOutDown.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_expand-exits/_expandOutDown.scss new file mode 100644 index 000000000..ad5d5d772 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_expand-exits/_expandOutDown.scss @@ -0,0 +1,22 @@ +@include keyframes(expandOutDown) { + 0% { + opacity: 1; + @include transform(scaleY(1)); + @include transform-origin(left bottom 0); + } + 100% { + opacity: 0; + @include transform(scaleY(.6)); + @include transform-origin(left bottom 0); + } +} + +@mixin expandOutDown($count: $countDefault, $duration: .15s, $delay: $delayDefault, $function: $functionDefault, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(expandOutDown); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_expand-exits/_expandOutUp.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_expand-exits/_expandOutUp.scss new file mode 100644 index 000000000..b151f9d57 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_expand-exits/_expandOutUp.scss @@ -0,0 +1,22 @@ +@include keyframes(expandOutUp) { + 0% { + opacity: 1; + @include transform(scaleY(1)); + @include transform-origin(left top 0); + } + 100% { + opacity: 0; + @include transform(scaleY(.6)); + @include transform-origin(left top 0); + } +} + +@mixin expandOutUp($count: $countDefault, $duration: .15s, $delay: $delayDefault, $function: $functionDefault, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(expandOutUp); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_expand-exits/_withFade.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_expand-exits/_withFade.scss new file mode 100644 index 000000000..ca57e03fc --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_expand-exits/_withFade.scss @@ -0,0 +1,21 @@ +@include keyframes(expandOutWithFade) { + 0% { + opacity: 1; + } + 70% { + opacity: 0; + } + 100% { + opacity: 0; + } +} + +@mixin expandOutWithFade($count: $countDefault, $duration: .2s, $delay: $delayDefault, $function: $functionDefault, $fill: 'forwards', $visibility: $visibilityDefault) { + @include animation-name(expandOutWithFade); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeIn.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeIn.scss new file mode 100644 index 000000000..0687e7a3a --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeIn.scss @@ -0,0 +1,18 @@ +@include keyframes(fadeIn) { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } +} + +@mixin fadeIn($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $ease-out-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(fadeIn); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeInDown.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeInDown.scss new file mode 100644 index 000000000..9cde74899 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeInDown.scss @@ -0,0 +1,20 @@ +@include keyframes(fadeInDown) { + 0% { + opacity: 0; + @include transform(translateY(-100px)); + } + 100% { + opacity: 1; + @include transform(translateY(0)); + } +} + +@mixin fadeInDown($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $ease-out-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(fadeInDown); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeInDownBig.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeInDownBig.scss new file mode 100644 index 000000000..4b9b6aef1 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeInDownBig.scss @@ -0,0 +1,20 @@ +@include keyframes(fadeInDownBig) { + 0% { + opacity: 0; + @include transform(translateY(-2000px)); + } + 100% { + opacity: 1; + @include transform(translateY(0)); + } +} + +@mixin fadeInDownBig($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $ease-out-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(fadeInDownBig); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeInLeft.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeInLeft.scss new file mode 100644 index 000000000..50ff06a0a --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeInLeft.scss @@ -0,0 +1,20 @@ +@include keyframes(fadeInLeft) { + 0% { + opacity: 0; + @include transform(translateX(-20px)); + } + 100% { + opacity: 1; + @include transform(translateX(0)); + } +} + +@mixin fadeInLeft($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $ease-out-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(fadeInLeft); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeInLeftBig.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeInLeftBig.scss new file mode 100644 index 000000000..72ae7b595 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeInLeftBig.scss @@ -0,0 +1,20 @@ +@include keyframes(fadeInLeftBig) { + 0% { + opacity: 0; + @include transform(translateX(-2000px)); + } + 100% { + opacity: 1; + @include transform(translateX(0)); + } +} + +@mixin fadeInLeftBig($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $ease-out-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(fadeInLeftBig); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeInRight.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeInRight.scss new file mode 100644 index 000000000..620e328b5 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeInRight.scss @@ -0,0 +1,20 @@ +@include keyframes(fadeInRight) { + 0% { + opacity: 0; + @include transform(translateX(20px)); + } + 100% { + opacity: 1; + @include transform(translateX(0)); + } +} + +@mixin fadeInRight($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $ease-out-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(fadeInRight); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeInRightBig.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeInRightBig.scss new file mode 100644 index 000000000..8f9a03360 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeInRightBig.scss @@ -0,0 +1,20 @@ +@include keyframes(fadeInRightBig) { + 0% { + opacity: 0; + @include transform(translateX(2000px)); + } + 100% { + opacity: 1; + @include transform(translateX(0)); + } +} + +@mixin fadeInRightBig($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $ease-out-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(fadeInRightBig); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeInUp.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeInUp.scss new file mode 100644 index 000000000..99d55e3ae --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeInUp.scss @@ -0,0 +1,19 @@ +@include keyframes(fadeInUp) { + 0% { + opacity: 0; + @include transform(translateY(20px));} + 100% { + opacity: 1; + @include transform(translateY(0)); + } +} + +@mixin fadeInUp($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $ease-out-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(fadeInUp); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeInUpBig.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeInUpBig.scss new file mode 100644 index 000000000..e8ad26edf --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/_fadeInUpBig.scss @@ -0,0 +1,20 @@ +@include keyframes(fadeInUpBig) { + 0% { + opacity: 0; + @include transform(translateY(2000px)); + } + 100% { + opacity: 1; + @include transform(translateY(0)); + } +} + +@mixin fadeInUpBig($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $ease-out-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(fadeInUpBig); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/fading-entrances.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/fading-entrances.scss new file mode 100644 index 000000000..8bc4d929a --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-entrances/fading-entrances.scss @@ -0,0 +1,11 @@ +// INDEX OF FADING ENTRANCES + +@import "_fadeIn"; +@import "_fadeInDown"; +@import "_fadeInDownBig"; +@import "_fadeInLeft"; +@import "_fadeInLeftBig"; +@import "_fadeInRight"; +@import "_fadeInRightBig"; +@import "_fadeInUp"; +@import "_fadeInUpBig"; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOut.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOut.scss new file mode 100644 index 000000000..677c7ca9f --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOut.scss @@ -0,0 +1,18 @@ +@include keyframes(fadeOut) { + 0% { + opacity: 1; + } + 100% { + opacity: 0; + } +} + +@mixin fadeOut($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $ease-in-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(fadeOut); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOutDown.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOutDown.scss new file mode 100644 index 000000000..f8a510ac3 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOutDown.scss @@ -0,0 +1,20 @@ +@include keyframes(fadeOutDown) { + 0% { + opacity: 1; + @include transform(translateY(0)); + } + 100% { + opacity: 0; + @include transform(translateY(20px)); + } +} + +@mixin fadeOutDown($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $ease-in-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(fadeOutDown); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOutDownBig.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOutDownBig.scss new file mode 100644 index 000000000..70a16990d --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOutDownBig.scss @@ -0,0 +1,20 @@ +@include keyframes(fadeOutDownBig) { + 0% { + opacity: 1; + @include transform(translateY(0)); + } + 100% { + opacity: 0; + @include transform(translateY(2000px)); + } +} + +@mixin fadeOutDownBig($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $ease-in-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(fadeOutDownBig); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOutLeft.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOutLeft.scss new file mode 100644 index 000000000..2e3635961 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOutLeft.scss @@ -0,0 +1,20 @@ +@include keyframes(fadeOutLeft) { + 0% { + opacity: 1; + @include transform(translateX(0)); + } + 100% { + opacity: 0; + @include transform(translateX(-20px)); + } +} + +@mixin fadeOutLeft($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $ease-in-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(fadeOutLeft); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOutLeftBig.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOutLeftBig.scss new file mode 100644 index 000000000..d449649ae --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOutLeftBig.scss @@ -0,0 +1,20 @@ +@include keyframes(fadeOutLeftBig) { + 0% { + opacity: 1; + @include transform(translateX(0)); + } + 100% { + opacity: 0; + @include transform(translateX(-2000px)); + } +} + +@mixin fadeOutLeftBig($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $ease-in-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(fadeOutLeftBig); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOutRight.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOutRight.scss new file mode 100644 index 000000000..3893b7e4c --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOutRight.scss @@ -0,0 +1,20 @@ +@include keyframes(fadeOutRight) { + 0% { + opacity: 1; + @include transform(translateX(0)); + } + 100% { + opacity: 0; + @include transform(translateX(20px)); + } +} + +@mixin fadeOutRight($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $ease-in-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(fadeOutRight); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOutRightBig.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOutRightBig.scss new file mode 100644 index 000000000..708841d55 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOutRightBig.scss @@ -0,0 +1,20 @@ +@include keyframes(fadeOutRightBig) { + 0% { + opacity: 1; + @include transform(translateX(0)); + } + 100% { + opacity: 0; + @include transform(translateX(2000px)); + } +} + +@mixin fadeOutRightBig($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $ease-in-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(fadeOutRightBig); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOutUp.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOutUp.scss new file mode 100644 index 000000000..304d27a2a --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOutUp.scss @@ -0,0 +1,20 @@ +@include keyframes(fadeOutUp) { + 0% { + opacity: 1; + @include transform(translateY(0)); + } + 100% { + opacity: 0; + @include transform(translateY(-100px)); + } +} + +@mixin fadeOutUp($count: $countDefault, $duration: .2s, $delay: $delayDefault, $function: $ease-in-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(fadeOutUp); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOutUpBig.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOutUpBig.scss new file mode 100644 index 000000000..bf4601451 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/_fadeOutUpBig.scss @@ -0,0 +1,20 @@ +@include keyframes(fadeOutUpBig) { + 0% { + opacity: 1; + @include transform(translateY(0)); + } + 100% { + opacity: 0; + @include transform(translateY(-2000px)); + } +} + +@mixin fadeOutUpBig($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $ease-in-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(fadeOutUpBig); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/fading-exits.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/fading-exits.scss new file mode 100644 index 000000000..96b75d74d --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_fading-exits/fading-exits.scss @@ -0,0 +1,11 @@ +// INDEX OF FADING EXITS + +@import "_fadeOut"; +@import "_fadeOutDown"; +@import "_fadeOutDownBig"; +@import "_fadeOutLeft"; +@import "_fadeOutLeftBig"; +@import "_fadeOutRight"; +@import "_fadeOutRightBig"; +@import "_fadeOutUp"; +@import "_fadeOutUpBig"; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_other-entrances/_pressIn.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_other-entrances/_pressIn.scss new file mode 100644 index 000000000..b22e5ba6d --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_other-entrances/_pressIn.scss @@ -0,0 +1,14 @@ +@include keyframes(pressIn) { + 100% { + @include transform(scale(.7)); + } +} +@mixin pressIn($count: $countDefault, $duration: $durationSmallDefault, $delay: $delayDefault, $function: $functionDefault, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(pressIn); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_other-entrances/_pressInSmall.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_other-entrances/_pressInSmall.scss new file mode 100644 index 000000000..2c293b9f4 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_other-entrances/_pressInSmall.scss @@ -0,0 +1,14 @@ +@include keyframes(pressInSmall) { + 100% { + @include transform(scale(.5)); + } +} +@mixin pressInSmall($count: $countDefault, $duration: $durationSmallDefault, $delay: $delayDefault, $function: $functionDefault, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(pressInSmall); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_other-entrances/_waterIn.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_other-entrances/_waterIn.scss new file mode 100644 index 000000000..90dd6f9ea --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_other-entrances/_waterIn.scss @@ -0,0 +1,17 @@ +@include keyframes(waterIn) { + 0% { + @include transform(translate(-45%) scaleX(2)); + } + 100% { + @include transform(translate(0%) scaleX(1)); + } +} +@mixin waterIn($count: $countDefault, $duration: $durationSmallDefault, $delay: $delayDefault, $function: $functionDefault, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(waterIn); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_other-entrances/other-entrances.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_other-entrances/other-entrances.scss new file mode 100644 index 000000000..3e08a0978 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_other-entrances/other-entrances.scss @@ -0,0 +1,5 @@ +// INDEX OF FADING ENTRANCES + +@import "_pressIn"; +@import "_waterIn"; +@import "_pressInSmall"; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_other-exits/_pressOut.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_other-exits/_pressOut.scss new file mode 100644 index 000000000..7ef356f10 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_other-exits/_pressOut.scss @@ -0,0 +1,14 @@ +@include keyframes(pressOut) { + 0% { + @include transform(scale3d(.7, .7, .7)); + } +} +@mixin pressOut($count: $countDefault, $duration: $durationSmallDefault, $delay: $delayDefault, $function: $functionDefault, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(pressOut); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_other-exits/_pressOutSmall.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_other-exits/_pressOutSmall.scss new file mode 100644 index 000000000..a8b2b716a --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_other-exits/_pressOutSmall.scss @@ -0,0 +1,14 @@ +@include keyframes(pressOutSmall) { + 0% { + @include transform(scale(.5)); + } +} +@mixin pressOutSmall($count: $countDefault, $duration: $durationSmallDefault, $delay: $delayDefault, $function: $functionDefault, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(pressOutSmall); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_other-exits/_waterOut.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_other-exits/_waterOut.scss new file mode 100644 index 000000000..4600cde92 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_other-exits/_waterOut.scss @@ -0,0 +1,17 @@ +@include keyframes(waterOut) { + 0% { + @include transform(translate(-45%) scaleX(2)); + } + 100% { + @include transform(translate(0%) scaleX(1)); + } +} +@mixin waterOut($count: $countDefault, $duration: $durationSmallDefault, $delay: $delayDefault, $function: $functionDefault, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(waterOut); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_other-exits/other-exits.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_other-exits/other-exits.scss new file mode 100644 index 000000000..b93b3d0c1 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_other-exits/other-exits.scss @@ -0,0 +1,5 @@ +// INDEX OF PRESS EXITS + +@import "_pressOut"; +@import "_waterOut"; +@import "_pressOutSmall"; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-entrances/_slideInDown.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-entrances/_slideInDown.scss new file mode 100644 index 000000000..3afbf0a23 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-entrances/_slideInDown.scss @@ -0,0 +1,20 @@ +@include keyframes(slideInDown) { + 0% { + opacity: 0; + @include transform(translateY(-2000px)); + } + 100% { + opacity: 1; + @include transform(translateY(0)); + } +} + +@mixin slideInDown($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $ease-in-out-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(slideInDown); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-entrances/_slideInLeft.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-entrances/_slideInLeft.scss new file mode 100644 index 000000000..8bce57947 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-entrances/_slideInLeft.scss @@ -0,0 +1,20 @@ +@include keyframes(slideInLeft) { + 0% { + opacity: 0; + @include transform(translateX(-2000px)); + } + 100% { + opacity: 1; + @include transform(translateX(0)); + } +} + +@mixin slideInLeft($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $ease-in-out-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(slideInLeft); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-entrances/_slideInRight.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-entrances/_slideInRight.scss new file mode 100644 index 000000000..6e718aefb --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-entrances/_slideInRight.scss @@ -0,0 +1,20 @@ +@include keyframes(slideInRight) { + 0% { + opacity: 0; + @include transform(translateX(2000px)); + } + 100% { + opacity: 1; + @include transform(translateX(0)); + } +} + +@mixin slideInRight($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $ease-in-out-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(slideInRight); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-entrances/_slideInUp.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-entrances/_slideInUp.scss new file mode 100644 index 000000000..7ab856749 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-entrances/_slideInUp.scss @@ -0,0 +1,20 @@ +@include keyframes(slideInUp) { + 0% { + opacity: 0; + @include transform(translateY(2000px)); + } + 100% { + opacity: 1; + @include transform(translateY(0)); + } +} + +@mixin slideInUp($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $ease-in-out-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(slideInUp); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-entrances/sliding-entrances.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-entrances/sliding-entrances.scss new file mode 100644 index 000000000..2572eeec3 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-entrances/sliding-entrances.scss @@ -0,0 +1,6 @@ +// INDEX OF SLIDING ENTRANCES + +@import "_slideInDown"; +@import "_slideInLeft"; +@import "_slideInRight"; +@import "_slideInUp"; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-exits/_slideOutDown.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-exits/_slideOutDown.scss new file mode 100644 index 000000000..9b2f895b0 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-exits/_slideOutDown.scss @@ -0,0 +1,19 @@ +@include keyframes(slideOutDown) { + 0% { + @include transform(translateY(0)); + } + 100% { + opacity: 0; + @include transform(translateY(2000px)); + } +} + +@mixin slideOutDown($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $functionDefault, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(slideOutDown); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-exits/_slideOutLeft.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-exits/_slideOutLeft.scss new file mode 100644 index 000000000..a896debbe --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-exits/_slideOutLeft.scss @@ -0,0 +1,19 @@ +@include keyframes(slideOutLeft) { + 0% { + @include transform(translateX(0)); + } + 100% { + opacity: 0; + @include transform(translateX(-2000px)); + } +} + +@mixin slideOutLeft($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $functionDefault, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(slideOutLeft); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-exits/_slideOutRight.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-exits/_slideOutRight.scss new file mode 100644 index 000000000..8cf70ff99 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-exits/_slideOutRight.scss @@ -0,0 +1,19 @@ +@include keyframes(slideOutRight) { + 0% { + @include transform(translateX(0)); + } + 100% { + opacity: 0; + @include transform(translateX(2000px)); + } +} + +@mixin slideOutRight($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $functionDefault, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(slideOutRight); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-exits/_slideOutUp.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-exits/_slideOutUp.scss new file mode 100644 index 000000000..62ceb9133 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-exits/_slideOutUp.scss @@ -0,0 +1,19 @@ +@include keyframes(slideOutUp) { + 0% { + @include transform(translateY(0)); + } + 100% { + opacity: 0; + @include transform(translateY(-2000px)); + } +} + +@mixin slideOutUp($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $functionDefault, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(slideOutUp); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-exits/sliding-exits.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-exits/sliding-exits.scss new file mode 100644 index 000000000..c16647ebe --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_sliding-exits/sliding-exits.scss @@ -0,0 +1,6 @@ +// INDEX OF SLIDING EXITS + +@import "_slideOutDown"; +@import "_slideOutLeft"; +@import "_slideOutRight"; +@import "_slideOutUp"; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-entrances/_zoomIn.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-entrances/_zoomIn.scss new file mode 100644 index 000000000..73bab09f8 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-entrances/_zoomIn.scss @@ -0,0 +1,19 @@ +@include keyframes(zoomIn) { + 0% { + opacity: 0; + @include transform(scale3d(.3, .3, .3)); + } + 50% { + opacity: 1; + } +} + +@mixin zoomIn($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $ease-out-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(zoomIn); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-entrances/_zoomInDown.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-entrances/_zoomInDown.scss new file mode 100644 index 000000000..1d2858ae7 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-entrances/_zoomInDown.scss @@ -0,0 +1,22 @@ +@include keyframes(zoomInDown) { + 0% { + animation-timing-function: cubic-bezier(.550, .055, .675, .190); + opacity: 0; + @include transform(scale3d(.1, .1, .1) translate3d(0, -1000px, 0)); + } + 60% { + animation-timing-function: cubic-bezier(.175, .885, .320, 1); + opacity: 1; + @include transform(scale3d(.475, .475, .475) translate3d(0, 60px, 0)); + } +} + +@mixin zoomInDown($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $ease-out-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(zoomInDown); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-entrances/_zoomInLeft.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-entrances/_zoomInLeft.scss new file mode 100644 index 000000000..188da94cf --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-entrances/_zoomInLeft.scss @@ -0,0 +1,22 @@ +@include keyframes(zoomInLeft) { + 0% { + animation-timing-function: cubic-bezier(.550, .055, .675, .190); + opacity: 0; + @include transform(scale3d(.1, .1, .1) translate3d(-1000px, 0, 0)); + } + 60% { + animation-timing-function: cubic-bezier(.175, .885, .320, 1); + opacity: 1; + @include transform(scale3d(.475, .475, .475) translate3d(10px, 0, 0)); + } +} + +@mixin zoomInLeft($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $ease-out-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(zoomInLeft); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-entrances/_zoomInPulse.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-entrances/_zoomInPulse.scss new file mode 100644 index 000000000..b836e6f7c --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-entrances/_zoomInPulse.scss @@ -0,0 +1,24 @@ +@include keyframes(zoomInPulse) { + from { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } + 50% { + -webkit-transform: scale3d(1.8, 1.8, 1.8); + transform: scale3d(1.8, 1.8, 1.8); + } + to { + -webkit-transform: scale3d(1.4, 1.4, 1.4); + transform: scale3d(1.4, 1.4, 1.4); + } +} +// 用在icon放大再缩小效果 +@mixin zoomInPulse($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $functionDefault, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(zoomInPulse); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-entrances/_zoomInQuick.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-entrances/_zoomInQuick.scss new file mode 100644 index 000000000..9e596ef66 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-entrances/_zoomInQuick.scss @@ -0,0 +1,19 @@ +@include keyframes(zoomInQuick) { + 0% { + opacity: 0; + @include transform(scale(.8)); + } + to { + @include transform(scale(1)); + } +} + +@mixin zoomInQuick($count: $countDefault, $duration: $durationSmallDefault, $delay: $delayDefault, $function: $ease-out-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(zoomInQuick); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-entrances/_zoomInRight.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-entrances/_zoomInRight.scss new file mode 100644 index 000000000..18fdcb285 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-entrances/_zoomInRight.scss @@ -0,0 +1,22 @@ +@include keyframes(zoomInRight) { + 0% { + animation-timing-function: cubic-bezier(.550, .055, .675, .190); + opacity: 0; + @include transform(scale3d(.1, .1, .1) translate3d(1000px, 0, 0)); + } + 60% { + animation-timing-function: cubic-bezier(.175, .885, .320, 1); + opacity: 1; + @include transform(scale3d(.475, .475, .475) translate3d(-10px, 0, 0)); + } +} + +@mixin zoomInRight($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $ease-out-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(zoomInRight); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-entrances/_zoomInUp.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-entrances/_zoomInUp.scss new file mode 100644 index 000000000..7f4528486 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-entrances/_zoomInUp.scss @@ -0,0 +1,22 @@ +@include keyframes(zoomInUp) { + 0% { + animation-timing-function: cubic-bezier(.550, .055, .675, .190); + opacity: 0; + @include transform(scale3d(.1, .1, .1) translate3d(0, 1000px, 0)); + } + 60% { + animation-timing-function: cubic-bezier(.175, .885, .320, 1); + opacity: 1; + @include transform(scale3d(.475, .475, .475) translate3d(0, -60px, 0)); + } +} + +@mixin zoomInUp($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $ease-out-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(zoomInUp); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-entrances/zooming-entrances.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-entrances/zooming-entrances.scss new file mode 100644 index 000000000..e9c7a5a6c --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-entrances/zooming-entrances.scss @@ -0,0 +1,9 @@ +// INDEX OF ZOOMING ENTRANCES + +@import "_zoomIn"; +@import "_zoomInPulse"; +@import "_zoomInQuick"; +@import "_zoomInDown"; +@import "_zoomInLeft"; +@import "_zoomInRight"; +@import "_zoomInUp"; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-exits/_zoomOut.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-exits/_zoomOut.scss new file mode 100644 index 000000000..47c56785c --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-exits/_zoomOut.scss @@ -0,0 +1,22 @@ +@include keyframes(zoomOut) { + 0% { + opacity: 1; + } + 50% { + opacity: 0; + @include transform(scale3d(.3, .3, .3)); + } + 100% { + opacity: 0; + } +} + +@mixin zoomOut($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $ease-in-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(zoomOut); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-exits/_zoomOutDown.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-exits/_zoomOutDown.scss new file mode 100644 index 000000000..25c7faaa8 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-exits/_zoomOutDown.scss @@ -0,0 +1,23 @@ +@include keyframes(zoomOutDown) { + 40% { + animation-timing-function: cubic-bezier(.550, .055, .675, .190); + opacity: 1; + @include transform(scale3d(.475, .475, .475) translate3d(0, -60px, 0)); + } + 100% { + animation-timing-function: cubic-bezier(.175, .885, .320, 1); + opacity: 0; + @include transform(scale3d(.1, .1, .1) translate3d(0, 2000px, 0)); + @include transform-origin(center bottom); + } +} + +@mixin zoomOutDown($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $ease-in-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(zoomOutDown); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-exits/_zoomOutLeft.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-exits/_zoomOutLeft.scss new file mode 100644 index 000000000..3f2d7a53e --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-exits/_zoomOutLeft.scss @@ -0,0 +1,21 @@ +@include keyframes(zoomOutLeft) { + 40% { + opacity: 1; + @include transform(scale3d(.475, .475, .475) translate3d(42px, 0, 0)); + } + 100% { + opacity: 0; + @include transform(scale(.1) translate3d(-2000px, 0, 0)); + @include transform-origin(left center); + } +} + +@mixin zoomOutLeft($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $ease-in-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(zoomOutLeft); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-exits/_zoomOutPulse.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-exits/_zoomOutPulse.scss new file mode 100644 index 000000000..6a9882d77 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-exits/_zoomOutPulse.scss @@ -0,0 +1,20 @@ +@include keyframes(zoomOutPulse) { + from { + -webkit-transform: scale3d(1.4, 1.4, 1.4); + transform: scale3d(1.4, 1.4, 1.4); + } + to { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +@mixin zoomOutPulse($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $functionDefault, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(zoomOutPulse); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-exits/_zoomOutQuick.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-exits/_zoomOutQuick.scss new file mode 100644 index 000000000..9265242e3 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-exits/_zoomOutQuick.scss @@ -0,0 +1,19 @@ +@include keyframes(zoomOutQuick) { + 0% { + @include transform(scale(1)); + } + to { + opacity: 0; + @include transform(scale(.8)); + } +} + +@mixin zoomOutQuick($count: $countDefault, $duration: $durationSmallDefault, $delay: $delayDefault, $function: $ease-in-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(zoomOutQuick); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-exits/_zoomOutRight.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-exits/_zoomOutRight.scss new file mode 100644 index 000000000..9e3aed35d --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-exits/_zoomOutRight.scss @@ -0,0 +1,21 @@ +@include keyframes(zoomOutRight) { + 40% { + opacity: 1; + @include transform(scale3d(.475, .475, .475) translate3d(-42px, 0, 0)); + } + 100% { + opacity: 0; + @include transform(scale(.1) translate3d(2000px, 0, 0)); + @include transform-origin(right center); + } +} + +@mixin zoomOutRight($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $ease-in-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(zoomOutRight); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-exits/_zoomOutUp.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-exits/_zoomOutUp.scss new file mode 100644 index 000000000..c5c14d2dc --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-exits/_zoomOutUp.scss @@ -0,0 +1,23 @@ +@include keyframes(zoomOutUp) { + 40% { + animation-timing-function: cubic-bezier(.550, .055, .675, .190); + opacity: 1; + @include transform(scale3d(.475, .475, .475) translate3d(0, 60px, 0)); + } + 100% { + animation-timing-function: cubic-bezier(.175, .885, .320, 1); + opacity: 0; + @include transform(scale3d(.1, .1, .1) translate3d(0, -2000px, 0)); + @include transform-origin(center bottom); + } +} + +@mixin zoomOutUp($count: $countDefault, $duration: $durationDefault, $delay: $delayDefault, $function: $ease-in-quint, $fill: $fillDefault, $visibility: $visibilityDefault) { + @include animation-name(zoomOutUp); + @include count($count); + @include duration($duration); + @include delay($delay); + @include function($function); + @include fill-mode($fill); + @include visibility($visibility); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-exits/zooming-exits.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-exits/zooming-exits.scss new file mode 100644 index 000000000..9e75c9fea --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/_zooming-exits/zooming-exits.scss @@ -0,0 +1,9 @@ +// INDEX OF ZOOMING EXITS + +@import "_zoomOut"; +@import "_zoomOutPulse"; +@import "_zoomOutQuick"; +@import "_zoomOutDown"; +@import "_zoomOutLeft"; +@import "_zoomOutRight"; +@import "_zoomOutUp"; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/mixin.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/mixin.scss new file mode 100644 index 000000000..62ea7749f --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/mixin.scss @@ -0,0 +1,105 @@ +@charset "UTF-8"; + +// animate mixins +// -------------------------------------------------- + +@mixin count($count: 1) { + -webkit-animation-iteration-count: $count; + -moz-animation-iteration-count: $count; + -ms-animation-iteration-count: $count; + -o-animation-iteration-count: $count; + animation-iteration-count: $count; +} + +@mixin duration($duration: 1s) { + -webkit-animation-duration: $duration; + -moz-animation-duration: $duration; + -ms-animation-duration: $duration; + -o-animation-duration: $duration; + animation-duration: $duration; +} + +@mixin delay($delay: .2s) { + -webkit-animation-delay: $delay; + -moz-animation-delay: $delay; + -ms-animation-delay: $delay; + -o-animation-delay: $delay; + animation-delay: $delay; +} + +@mixin function($function: ease) { + -webkit-animation-timing-function: $function; + -moz-animation-timing-function: $function; + -ms-animation-timing-function: $function; + -o-animation-timing-function: $function; + animation-timing-function: $function; +} + +@mixin fill-mode($fill: both) { + -webkit-animation-fill-mode: $fill; + -moz-animation-fill-mode: $fill; + -ms-animation-fill-mode: $fill; + -o-animation-fill-mode: $fill; + animation-fill-mode: $fill; +} + +@mixin visibility($visibility: hidden) { + -webkit-backface-visibility: $visibility; + -moz-backface-visibility: $visibility; + -ms-backface-visibility: $visibility; + -o-backface-visibility: $visibility; + backface-visibility: $visibility; +} + +@mixin transform($property) { + -webkit-transform: $property; + -moz-transform: $property; + -ms-transform: $property; + -o-transform: $property; + transform: $property; +} + +@mixin transform-origin($transform-origin: center center) { + -webkit-transform-origin: $transform-origin; + -moz-transform-origin: $transform-origin; + -ms-transform-origin: $transform-origin; + -o-transform-origin: $transform-origin; + transform-origin: $transform-origin; +} + +@mixin transform-style($transform-style: flat) { + -webkit-transform-style: $transform-style; + -moz-transform-style: $transform-style; + -o-transform-style: $transform-style; + transform-style: $transform-style; +} + +@mixin animation-name($animation-name) { + -webkit-animation-name: $animation-name; + -moz-animation-name: $animation-name; + -ms-animation-name: $animation-name; + -o-animation-name: $animation-name; + animation-name: $animation-name; +} + +@mixin keyframes($animation-name) { + @-webkit-keyframes #{$animation-name} { + @content; + } + + @-moz-keyframes #{$animation-name} { + @content; + } + + @-ms-keyframes #{$animation-name} { + @content; + } + + @-o-keyframes #{$animation-name} { + @content; + } + + @keyframes #{$animation-name} { + @content; + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/variable.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/variable.scss new file mode 100644 index 000000000..b2018ba5d --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/scss/variable.scss @@ -0,0 +1,19 @@ +@charset "UTF-8"; + +// animate variables +// -------------------------------------------------- + +$countDefault: 1 !default; + +$durationSmallDefault: .2s !default; +$durationDefault: .3s !default; +$durationBigDefault: .35s !default; + +$delayDefault: 0s !default; +$functionDefault: cubic-bezier(.23, 1, .32, 1) !default; +$fillDefault: both; +$visibilityDefault: hidden !default; + +$ease-in-quint: cubic-bezier(.755, .05, .855, .06); +$ease-out-quint: cubic-bezier(.23, 1, .32, 1); +$ease-in-out-quint: cubic-bezier(.86, 0, .07, 1); diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/animate/style.js b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/style.js new file mode 100644 index 000000000..f1ad40f46 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/animate/style.js @@ -0,0 +1 @@ +import './main.scss'; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/avatar/index.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/avatar/index.jsx new file mode 100644 index 000000000..929d7aefa --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/avatar/index.jsx @@ -0,0 +1,149 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; +import ConfigProvider from '../config-provider'; +import Icon from '../icon'; +import { obj } from '../util'; + +/** + * Avatar + */ +class Avatar extends Component { + static propTypes = { + prefix: PropTypes.string, + children: PropTypes.any, + className: PropTypes.string, + /** + * 头像的大小 + */ + size: PropTypes.oneOfType([ + PropTypes.oneOf(['small', 'medium', 'large']), + PropTypes.number, + ]), + /** + * 头像的形状 + */ + shape: PropTypes.oneOf(['circle', 'square']), + /** + * icon 类头像的图标类型,可设为 Icon 的 `type` 或 `ReactNode` + */ + icon: PropTypes.oneOfType([PropTypes.node, PropTypes.string]), + /** + * 图片类头像的资源地址 + */ + src: PropTypes.string, + /** + * 图片加载失败的事件,返回 false 会关闭组件默认的 fallback 行为 + */ + onError: PropTypes.func, + /** + * 图像无法显示时的 alt 替代文本 + */ + alt: PropTypes.string, + /** + * 图片类头像响应式资源地址 + */ + srcSet: PropTypes.string, + }; + + static defaultProps = { + prefix: 'next-', + size: 'medium', + shape: 'circle', + }; + + state = { + isImgExist: true, + }; + + componentDidUpdate(prevProps) { + if (prevProps.src !== this.props.src) { + // eslint-disable-next-line react/no-did-update-set-state + this.setState({ isImgExist: true }); + } + } + + handleImgLoadError = () => { + const { onError } = this.props; + const errorFlag = onError ? onError() : undefined; + if (errorFlag !== false) { + this.setState({ isImgExist: false }); + } + }; + + getIconSize = avatarSize => { + return typeof avatarSize === 'number' ? avatarSize / 2 : avatarSize; + }; + + render() { + const { + prefix, + className, + style, + size, + icon, + alt, + srcSet, + shape, + src, + } = this.props; + const { isImgExist } = this.state; + let { children } = this.props; + + const others = obj.pickOthers(Avatar.propTypes, this.props); + + const cls = classNames( + { + [`${prefix}avatar`]: true, + [`${prefix}avatar-${shape}`]: !!shape, + [`${prefix}avatar-image`]: src && isImgExist, + [`${prefix}avatar-${size}`]: typeof size === 'string', + }, + className + ); + + const sizeStyle = + typeof size === 'number' + ? { + width: size, + height: size, + lineHeight: `${size}px`, + fontSize: icon ? size / 2 : 18, + } + : {}; + + const iconSize = this.getIconSize(size); + if (src) { + if (isImgExist) { + children = ( + {alt} + ); + } else { + children = ; + } + } else if (typeof icon === 'string') { + children = ; + } else if (icon) { + const newIconSize = + 'size' in icon.props ? icon.props.size : iconSize; + children = React.cloneElement(icon, { size: newIconSize }); + } + + return ( + + {children} + + ); + } +} + +export default ConfigProvider.config(Avatar); diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/avatar/main.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/avatar/main.scss new file mode 100644 index 000000000..952b037e0 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/avatar/main.scss @@ -0,0 +1,44 @@ +@charset "UTF-8"; + +@import "../core/index-noreset.scss"; + +@import "scss/mixin"; +@import "scss/variable"; + +/* put your code here */ + +#{$avatar-prefix} { + position: relative; + display: inline-block; + overflow: hidden; + color: $avatar-color; + white-space: nowrap; + text-align: center; + vertical-align: middle; + background: $avatar-default-bg; + + &-image { + background: transparent; + } + + @include avatar-size($avatar-size-medium); + + &-large { + @include avatar-size($avatar-size-large); + } + + &-small { + @include avatar-size($avatar-size-small); + } + + &-square { + border-radius: $avatar-border-radius; + } + + & > img { + display: block; + width: 100%; + height: 100%; + object-fit: cover; + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/avatar/scss/mixin.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/avatar/scss/mixin.scss new file mode 100644 index 000000000..49c33721d --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/avatar/scss/mixin.scss @@ -0,0 +1,17 @@ +@charset "UTF-8"; + +// avatar mixins +// -------------------------------------------------- + +@mixin avatar-size($size) { + width: $size; + height: $size; + line-height: $size; + border-radius: 50%; + + &-string { + position: absolute; + left: 50%; + transform-origin: 0 center; + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/avatar/scss/variable.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/avatar/scss/variable.scss new file mode 100644 index 000000000..a48e2f978 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/avatar/scss/variable.scss @@ -0,0 +1,42 @@ +@charset "UTF-8"; + +// avatar variables +// -------------------------------------------------- + +//// +/// @module avatar: 头像 +/// @tag Avatar +/// @category component +/// @family data-display +/// @varPrefix $avatar- +/// @classPrefix {prefix}-avatar +/// @order {} +//// + +// Unconfigurable +// ---------------------------------------- +$avatar-prefix: ".#{$css-prefix}avatar"; + +// Size +// ---------------------------------------- + +/// size +/// @namespace size/bounding +$avatar-size-large: $s-13 !default; +/// size +/// @namespace size/bounding +$avatar-size-medium: $s-10 !default; +/// size +/// @namespace size/bounding +$avatar-size-small: $s-7 !default; + + +// Statement +// ---------------------------------------- + +/// corner +/// @namespace statement/normal +$avatar-border-radius: $corner-1 !default; + +$avatar-color: $color-white !default; +$avatar-default-bg: $color-fill1-4 !default; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/avatar/style.js b/packages/material-parser/test/fixtures/fusion-next-component/src/avatar/style.js new file mode 100644 index 000000000..65cfc7e39 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/avatar/style.js @@ -0,0 +1,2 @@ +import '../icon/style.js'; +import './main.scss'; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/badge/index.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/badge/index.jsx new file mode 100644 index 000000000..5c14a88ff --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/badge/index.jsx @@ -0,0 +1,106 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; +import ConfigProvider from '../config-provider'; +import { obj } from '../util'; +import Sup from './sup'; + +/** + * Badge + */ +class Badge extends Component { + static propTypes = { + // 样式类名的品牌前缀 + prefix: PropTypes.string, + rtl: PropTypes.bool, + // 自定义类名 + className: PropTypes.string, + // 自定义内联样式 + style: PropTypes.object, + /** + * 徽章依托的内容 + */ + children: PropTypes.node, + /** + * 展示的数字,大于 overflowCount 时显示为 ${overflowCount}+,为 0 时默认隐藏 + */ + count: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), + /** + * 当count为0时,是否显示count + */ + showZero: PropTypes.bool, + /** + * 自定义节点内容 + */ + content: PropTypes.node, + /** + * 展示的封顶的数字 + */ + overflowCount: PropTypes.oneOfType([ + PropTypes.number, + PropTypes.string, + ]), + /** + * 不展示数字,只展示一个小红点 + */ + dot: PropTypes.bool, + }; + + static defaultProps = { + prefix: 'next-', + count: 0, + showZero: false, + overflowCount: 99, + dot: false, + }; + + render() { + const { + prefix, + dot, + className, + children, + content, + style, + rtl, + count: originCount, + showZero, + overflowCount: originOverflowCount, + } = this.props; + const count = parseInt(originCount, 10); + const overflowCount = parseInt(originOverflowCount, 10); + const others = obj.pickOthers(Badge.propTypes, this.props); + + // 如果是数字,则添加默认的 title + if (count || (count === 0 && showZero)) { + others.title = others.title || `${count}`; + } + + const classes = classNames( + `${prefix}badge`, + { + [`${prefix}badge-not-a-wrapper`]: !children, + }, + className + ); + + return ( + + {children} + + + ); + } +} + +export default ConfigProvider.config(Badge); diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/badge/main.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/badge/main.scss new file mode 100644 index 000000000..c3bd8f161 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/badge/main.scss @@ -0,0 +1,120 @@ +@charset "UTF-8"; + +@import "../core/index-noreset.scss"; +@import "scss/function"; +@import "scss/mixin"; +@import "scss/placeholder"; +@import "scss/variable"; + +.#{$css-prefix} { + &badge { + @include box-sizing; + /* @include global-font; */ + + @include badge-bounding(); + + .#{$css-prefix}badge-count { + @include badge-state( + $color: $badge-color, + $bgColor: $badge-color-bg, + $borderRadius: $badge-size-count-border-radius + ); + @include badge-size( + $width: $badge-size-count-width, + $minWidth: $badge-size-dot-min-width, + $height: $badge-size-count-height, + $padding: $badge-size-count-padding, + $fontSize: $badge-size-count-font, + $lineHeight: $badge-size-count-lineheight + ); + top: -.5em; + } + + .#{$css-prefix}badge-dot { + @include badge-state( + $color: $badge-dot-color, + $bgColor: $badge-dot-color-bg, + $borderRadius: $badge-size-dot-border-radius + ); + @include badge-size( + $width: $badge-size-dot-width, + $minWidth: $badge-size-dot-min-width, + $height: $badge-size-dot-height, + $padding: $badge-size-dot-padding, + $fontSize: 1px, + $lineHeight: 1 + ); + top: -.5em; + } + + .#{$css-prefix}badge-custom { + line-height: 1.166667; + white-space: nowrap; + font-size: $font-size-caption; + padding-left: $badge-size-custom-padding-lr; + padding-right: $badge-size-custom-padding-lr; + border-radius: $badge-size-custom-border-radius; + transform: translateX(-50%); + + > * { + line-height: 1; + } + + > i, + > .#{$css-prefix}icon { + &:before { + font-size: inherit; + width: auto; + vertical-align: top; + } + } + } + + .#{$css-prefix}badge-scroll-number { + position: absolute; + top: -4px; + z-index: 10; + overflow: hidden; + transform-origin: left center; + } + + &-scroll-number-only { + position: relative; + display: inline-block; + transition: transform $motion-duration-immediately $motion-linear, -webkit-transform $motion-duration-immediately $motion-linear; + min-width: $badge-size-dot-min-width; + + span { + display: block; + height: $badge-size-count-height; + line-height: $badge-size-count-height; + font-size: $badge-size-count-font; + } + } + + &-not-a-wrapper &-count, + &-not-a-wrapper &-custom { + position: relative; + display: block; + top: auto; + transform: translateX(0); + } + + &-not-a-wrapper &-dot { + position: relative; + display: block; + top: auto; + transform: translateX(0); + } + + &-list-wrapper { + margin-left: 0; + li { + margin-bottom: $badge-size-list-margin; + list-style: none; + } + } + } +} + +@import './rtl.scss'; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/badge/rtl.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/badge/rtl.scss new file mode 100644 index 000000000..a26579f83 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/badge/rtl.scss @@ -0,0 +1,12 @@ + +.#{$css-prefix}badge[dir="rtl"] { + .#{$css-prefix}badge-custom { + padding-right: $badge-size-custom-padding-lr; + padding-left: $badge-size-custom-padding-lr; + } + + .#{$css-prefix}badge-scroll-number { + left: 0; + transform-origin: right center; + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/badge/scss/function.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/badge/scss/function.scss new file mode 100755 index 000000000..954b506da --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/badge/scss/function.scss @@ -0,0 +1,4 @@ +@charset "UTF-8"; + +// badge functions +// -------------------------------------------------- diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/badge/scss/mixin.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/badge/scss/mixin.scss new file mode 100755 index 000000000..91ff9d7f7 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/badge/scss/mixin.scss @@ -0,0 +1,44 @@ +@charset "UTF-8"; + +// badge mixins +// -------------------------------------------------- +@mixin badge-bounding { + position: relative; + display: inline-block; + vertical-align: middle; + line-height: 1; +} + +@mixin badge-state( + $color, + $bgColor, + $borderRadius +) { + color: $color; + background: $bgColor; + text-align: center; + white-space: nowrap; + border-radius: $borderRadius; + a, + a:hover { + color: $color; + } +} + +@mixin badge-size( + $width, + $minWidth, + $height, + $padding, + $fontSize, + $lineHeight +) { + position: absolute; + width: $width; + height: $height; + min-width: $minWidth; + padding: $padding; + font-size: $fontSize; + line-height: $lineHeight; + transform: translateX(-50%); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/badge/scss/placeholder.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/badge/scss/placeholder.scss new file mode 100755 index 000000000..0f0fc5521 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/badge/scss/placeholder.scss @@ -0,0 +1,4 @@ +@charset "UTF-8"; + +// badge placeholders +// -------------------------------------------------- diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/badge/scss/variable.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/badge/scss/variable.scss new file mode 100644 index 000000000..63719e6a3 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/badge/scss/variable.scss @@ -0,0 +1,67 @@ +@charset "UTF-8"; + +// badge variables +// -------------------------------------------------- + +//// +/// @module badge: 徽标数 +/// @tag badge +/// @category component +/// @family data-display +/// @varPrefix $badge- +/// @classPrefix {prefix}-badge +/// @order {"size/bounding":10,"size/list":11,"size/text":12,"statement/normal":10} +//// + +// Size +// ---------------------------------------- + +/// size +/// @namespace size/bounding +$badge-size-dot-width: $s-2 !default; +/// margin (b) +/// @namespace size/list +$badge-size-list-margin: $s-zero !default; +/// height +/// @namespace size/bounding +$badge-size-count-config-height: $s-4 !default; +/// padding (lr) +/// @namespace size/bounding +$badge-size-count-padding-lr: $s-1 !default; +/// padding (lr) +/// @namespace size/bounding +$badge-size-custom-padding-lr: $s-1 !default; +/// size +/// @namespace size/text +$badge-size-count-font: $font-size-caption !default; + +// unconfigurable +$badge-size-count-width: auto !default; +$badge-size-count-height: $badge-size-count-config-height !default; +$badge-size-count-padding: 0 $badge-size-count-padding-lr 0 $badge-size-count-padding-lr !default; +$badge-size-count-lineheight: $badge-size-count-config-height !default; +$badge-size-dot-min-width: $badge-size-dot-width !default; +$badge-size-dot-height: $badge-size-dot-width !default; +$badge-size-dot-padding: $s-zero !default; + +// Statement +// ---------------------------------------- + +/// background +/// @namespace statement/normal +$badge-color-bg: $color-error-3 !default; +/// corner +/// @namespace statement/normal +$badge-size-count-border-radius: $s-2 !default; +/// background +/// @namespace statement/normal +$badge-dot-color-bg: $color-error-3 !default; +/// corner +/// @namespace statement/normal +$badge-size-dot-border-radius: $s-2 !default; +/// corner +/// @namespace statement/normal +$badge-size-custom-border-radius: $corner-1 !default; +// unconfigurable +$badge-color: $color-white !default; +$badge-dot-color: $color-white !default; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/badge/style.js b/packages/material-parser/test/fixtures/fusion-next-component/src/badge/style.js new file mode 100644 index 000000000..8a22efcc3 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/badge/style.js @@ -0,0 +1,2 @@ +import '../animate/style.js'; +import './main.scss'; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/badge/sup.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/badge/sup.jsx new file mode 100644 index 000000000..c979b3bcc --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/badge/sup.jsx @@ -0,0 +1,221 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { polyfill } from 'react-lifecycles-compat'; +import classNames from 'classnames'; +import Animate from '../animate'; +import { support, dom } from '../util'; + +/** + * badge sup component + */ + +// util::getDigitArray +const getDigitArray = num => + num + .toString() + .split('') + .reverse() + .map(i => parseInt(i, 10)); + +class Sup extends Component { + static propTypes = { + prefix: PropTypes.string, + count: PropTypes.number, + showZero: PropTypes.bool, + overflowCount: PropTypes.number, + content: PropTypes.node, + dot: PropTypes.bool, + style: PropTypes.object, + }; + + static defaultProps = { + prefix: 'next-', + count: 0, + showZero: false, + overflowCount: 99, + dot: false, + }; + + // 单排可滚动的数字列表 + static renderDigit(prefix, digit, key) { + const children = []; + for (let i = 0; i < 30; i++) { + children.push({i % 10}); + } + + return ( + + {children} + + ); + } + + // 可滚动数字组 + static renderNumber(prefix, count) { + return getDigitArray(count) + .map((digit, i) => Sup.renderDigit(prefix, digit, i)) + .reverse(); + } + + constructor(props) { + super(props); + + // render 时, 上一次的渲染数字 和 当前渲染的数字 + this.state = { + lastCount: 0, + currentCount: props.count, + }; + } + + static getDerivedStateFromProps(nextProps, prevState) { + if ('count' in nextProps) { + return { + lastCount: prevState.currentCount, + currentCount: nextProps.count, + }; + } + + return null; + } + + componentDidMount() { + this.computeStyle(true); + } + + componentDidUpdate(prevProps) { + if (prevProps.count !== this.props.count) { + this.computeStyle(false); + + // NOTE why called `computeStyle` again after 300ms ? + setTimeout(() => { + this.computeStyle(true, true); + }, 300); + } + } + + computeStyle(removeTransition, revert) { + const { prefix, count, overflowCount } = this.props; + const { lastCount } = this.state; + + if (count < 0) { + return; + } + const supNode = this.refs.sup; + + if (supNode && dom.hasClass(supNode, `${prefix}badge-count`)) { + let scrollNums = supNode.querySelectorAll( + `.${prefix}badge-scroll-number-only` + ); + + if (scrollNums.length) { + const height = window.getComputedStyle(supNode).height; + + scrollNums = [].slice.call(scrollNums, 0).reverse(); + + getDigitArray(count).forEach((digit, i) => { + const position = this.getPositionByDigit(digit, i, revert); + const transformTo = -position * parseInt(height, 10); + + removeTransition = + removeTransition || + typeof getDigitArray(lastCount)[i] === 'undefined' || + lastCount > overflowCount || + lastCount <= 0; + + const scrollStyle = support.animation + ? { + transition: removeTransition + ? 'none' + : 'transform .3s cubic-bezier(.645, .045, .355, 1), -webkit-transform .3s cubic-bezier(.645, .045, .355, 1)', + WebkitTransform: `translateY(${transformTo}px)`, + transform: `translateY(${transformTo}px)`, + height, + lineHeight: height, + } + : { + top: `${transformTo}px`, + height, + lineHeight: height, + }; + + Object.keys(scrollStyle).forEach(key => { + scrollNums[i].style[key] = scrollStyle[key]; + }); + }); + } + } + } + + getPositionByDigit(digit, i, revert) { + const { lastCount } = this.state; + if (revert) { + return 10 + digit; + } + const lastDigit = getDigitArray(lastCount)[i] || 0; + + if (this.props.count > lastCount) { + return (digit >= lastDigit ? 10 : 20) + digit; + } + + if (digit <= lastDigit) { + return 10 + digit; + } + + return digit; + } + + render() { + const { + prefix, + count, + showZero, + overflowCount, + dot, + style, + content, + } = this.props; + + const supClasses = classNames(`${prefix}badge-scroll-number`, { + [`${prefix}badge-count`]: !!count || (count === 0 && showZero), + [`${prefix}badge-dot`]: dot, + [`${prefix}badge-custom`]: !!content, + }); + + let children = null; + const show = dot || count > 0 || (count === 0 && showZero) || content; + + if (count > 0 || (count === 0 && showZero)) { + const realCount = + overflowCount > 0 && count > overflowCount + ? `${overflowCount}+` + : count; + + children = isNaN(realCount) + ? realCount + : Sup.renderNumber(prefix, count); + } else if (content) { + children = content; + } + + const animation = { + appear: 'zoomIn', + enter: 'zoomIn', + leave: 'zoomOut', + }; + + const wrapper = support.animation ? ( + + ) : ( + + ); + const element = show ? ( + + {children} + + ) : null; + + return React.cloneElement(wrapper, {}, element); + } +} + +export default polyfill(Sup); diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/balloon/alignMap.js b/packages/material-parser/test/fixtures/fusion-next-component/src/balloon/alignMap.js new file mode 100644 index 000000000..26ecc073c --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/balloon/alignMap.js @@ -0,0 +1,202 @@ +/** + * Created by xiachi on 17/1/17. + */ + +const normalMap = { + t: { + align: 'bc tc', + rtlAlign: 'bc tc', + arrow: 'bottom', + trOrigin: 'bottom', + rtlTrOrigin: 'bottom', + offset: [0, -12], + }, + r: { + align: 'cl cr', + rtlAlign: 'cr cl', + arrow: 'left', + trOrigin: 'left', + rtlTrOrigin: 'right', + offset: [12, 0], + }, + b: { + align: 'tc bc', + rtlAlign: 'tc bc', + arrow: 'top', + trOrigin: 'top', + rtlTrOrigin: 'top', + offset: [0, 12], + }, + l: { + align: 'cr cl', + rtlAlign: 'cl cr', + arrow: 'right', + trOrigin: 'right', + rtlTrOrigin: 'left', + offset: [-12, 0], + }, + tl: { + align: 'br tc', + rtlAlign: 'bl tc', + arrow: 'bottom-right', + trOrigin: 'bottom right', + rtlTrOrigin: 'bottom left', + offset: [20, -12], + }, + tr: { + align: 'bl tc', + rtlAlign: 'br tc', + arrow: 'bottom-left', + trOrigin: 'bottom left', + rtlTrOrigin: 'bottom right', + offset: [-20, -12], + }, + rt: { + align: 'bl cr', + rtlAlign: 'br cl', + arrow: 'left-bottom', + trOrigin: 'bottom left', + rtlTrOrigin: 'bottom right', + offset: [12, 20], + }, + rb: { + align: 'tl cr', + rtlAlign: 'tr cl', + arrow: 'left-top', + trOrigin: 'top left', + rtlTrOrigin: 'top right', + offset: [12, -20], + }, + bl: { + align: 'tr bc', + rtlAlign: 'tl bc', + arrow: 'top-right', + trOrigin: 'top right', + rtlTrOrigin: 'top left', + offset: [20, 12], + }, + br: { + align: 'tl bc', + rtlAlign: 'tr bc', + arrow: 'top-left', + trOrigin: 'top left', + rtlTrOrigin: 'top right', + offset: [-20, 12], + }, + lt: { + align: 'br cl', + rtlAlign: 'bl cr', + arrow: 'right-bottom', + trOrigin: 'bottom right', + rtlTrOrigin: 'bottom left', + offset: [-12, 20], + }, + lb: { + align: 'tr cl', + rtlAlign: 'tl cr', + arrow: 'right-top', + trOrigin: 'top right', + rtlTrOrigin: 'top left', + offset: [-12, -20], + }, +}; +const edgeMap = { + t: { + align: 'bc tc', + rtlAlign: 'bc tc', + arrow: 'bottom', + trOrigin: 'bottom', + rtlTrOrigin: 'bottom', + offset: [0, -12], + }, + r: { + align: 'cl cr', + rtlAlign: 'cr cl', + arrow: 'left', + trOrigin: 'left', + rtlTrOrigin: 'right', + offset: [12, 0], + }, + b: { + align: 'tc bc', + rtlAlign: 'tc bc', + arrow: 'top', + trOrigin: 'top', + rtlTrOrigin: 'top', + offset: [0, 12], + }, + l: { + align: 'cr cl', + rtlAlign: 'cl cr', + arrow: 'right', + trOrigin: 'right', + rtlTrOrigin: 'left', + offset: [-12, 0], + }, + tl: { + align: 'bl tl', + rtlAlign: 'br tr', + arrow: 'bottom-left', + trOrigin: 'bottom left', + rtlTrOrigin: 'bottom right', + offset: [0, -12], + }, + tr: { + align: 'br tr', + rtlAlign: 'bl tl', + arrow: 'bottom-right', + trOrigin: 'bottom right', + rtlTrOrigin: 'bottom left', + offset: [0, -12], + }, + rt: { + align: 'tl tr', + rtlAlign: 'tr tl', + arrow: 'left-top', + trOrigin: 'top left', + rtlTrOrigin: 'top right', + offset: [12, 0], + }, + rb: { + align: 'bl br', + rtlAlign: 'br bl', + arrow: 'left-bottom', + trOrigin: 'bottom left', + rtlTrOrigin: 'bottom right', + offset: [12, 0], + }, + bl: { + align: 'tl bl', + rtlAlign: 'tr br', + arrow: 'top-left', + trOrigin: 'top left', + rtlTrOrigin: 'top right', + offset: [0, 12], + }, + br: { + align: 'tr br', + rtlAlign: 'tl bl', + arrow: 'top-right', + trOrigin: 'top right', + rtlTrOrigin: 'top left', + offset: [0, 12], + }, + lt: { + align: 'tr tl', + rtlAlign: 'tl tr', + arrow: 'right-top', + trOrigin: 'top right', + rtlTrOrigin: 'top left', + offset: [-12, 0], + }, + lb: { + align: 'br bl', + rtlAlign: 'bl br', + arrow: 'right-bottom', + trOrigin: 'bottom right', + rtlTrOrigin: 'bottom left', + offset: [-12, 0], + }, +}; + +export { normalMap, edgeMap }; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/balloon/balloon.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/balloon/balloon.jsx new file mode 100644 index 000000000..5fa8c4869 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/balloon/balloon.jsx @@ -0,0 +1,398 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { polyfill } from 'react-lifecycles-compat'; +import Overlay from '../overlay'; +import { func, obj, log } from '../util'; +import BalloonInner from './inner'; +import { normalMap, edgeMap } from './alignMap'; +import { getDisabledCompatibleTrigger } from './util'; + +const { noop } = func; +const { Popup } = Overlay; + +const alignList = [ + 't', + 'r', + 'b', + 'l', + 'tl', + 'tr', + 'bl', + 'br', + 'lt', + 'lb', + 'rt', + 'rb', +]; + +let alignMap = normalMap; + +/** Balloon */ +class Balloon extends React.Component { + static contextTypes = { + prefix: PropTypes.string, + }; + static propTypes = { + prefix: PropTypes.string, + pure: PropTypes.bool, + rtl: PropTypes.bool, + /** + * 自定义类名 + */ + className: PropTypes.string, + /** + * 自定义内敛样式 + */ + style: PropTypes.object, + /** + * 浮层的内容 + */ + children: PropTypes.any, + size: PropTypes.string, + /** + * 样式类型 + */ + type: PropTypes.oneOf(['normal', 'primary']), + /** + * 弹层当前显示的状态 + */ + visible: PropTypes.bool, + /** + * 弹层默认显示的状态 + */ + defaultVisible: PropTypes.bool, + /** + * 弹层在显示和隐藏触发的事件 + * @param {Boolean} visible 弹层是否隐藏和显示 + * @param {String} type 触发弹层显示或隐藏的来源, closeClick 表示由自带的关闭按钮触发; fromTrigger 表示由trigger的点击触发; docClick 表示由document的点击触发 + */ + onVisibleChange: PropTypes.func, + /** + * 弹出层对齐方式, 是否为边缘对齐 + */ + alignEdge: PropTypes.bool, + /** + * 是否显示关闭按钮 + */ + closable: PropTypes.bool, + /** + * 弹出层位置 + * @enumdesc 上, 右, 下, 左, 上左, 上右, 下左, 下右, 左上, 左下, 右上, 右下 及其 两两组合 + */ + align: PropTypes.oneOf(alignList), + /** + * 弹层相对于trigger的定位的微调, 接收数组[hoz, ver], 表示弹层在 left / top 上的增量 + * e.g. [100, 100] 表示往右(RTL 模式下是往左) 、下分布偏移100px + */ + offset: PropTypes.array, + /** + * 触发元素 + */ + trigger: PropTypes.any, + /** + * 触发行为 + * 鼠标悬浮, 鼠标点击('hover','click')或者它们组成的数组,如 ['hover', 'click'], 强烈不建议使用'focus',若弹窗内容有复杂交互请使用click + */ + triggerType: PropTypes.oneOfType([PropTypes.string, PropTypes.array]), + + onClick: PropTypes.func, + /** + * 任何visible为false时会触发的事件 + */ + onClose: PropTypes.func, + onHover: PropTypes.func, + /** + * 是否进行自动位置调整 + */ + needAdjust: PropTypes.bool, + /** + * 弹层在触发以后的延时显示, 单位毫秒 ms + */ + delay: PropTypes.number, + /** + * 浮层关闭后触发的事件, 如果有动画,则在动画结束后触发 + */ + afterClose: PropTypes.func, + /** + * 强制更新定位信息 + */ + shouldUpdatePosition: PropTypes.bool, + /** + * 弹层出现后是否自动focus到内部第一个元素 + */ + autoFocus: PropTypes.bool, + /** + * 安全节点:对于triggetType为click的浮层,会在点击除了浮层外的其它区域时关闭浮层.safeNode用于添加不触发关闭的节点, 值可以是dom节点的id或者是节点的dom对象 + */ + safeNode: PropTypes.string, + /** + * 用来指定safeNode节点的id,和safeNode配合使用 + */ + safeId: PropTypes.string, + /** + * 配置动画的播放方式 + * @param {String} in 进场动画 + * @param {String} out 出场动画 + */ + animation: PropTypes.oneOfType([PropTypes.object, PropTypes.bool]), + + /** + * 弹层的dom节点关闭时是否删除 + */ + cache: PropTypes.bool, + /** + * 指定浮层渲染的父节点, 可以为节点id的字符串,也可以返回节点的函数。 + */ + popupContainer: PropTypes.any, + container: PropTypes.any, + /** + * 弹层组件style,透传给Popup + */ + popupStyle: PropTypes.object, + /** + * 弹层组件className,透传给Popup + */ + popupClassName: PropTypes.string, + /** + * 弹层组件属性,透传给Popup + */ + popupProps: PropTypes.object, + /** + * 是否跟随滚动 + */ + followTrigger: PropTypes.bool, + /** + * 弹层id, 传入值才会支持无障碍 + */ + id: PropTypes.string, + }; + static defaultProps = { + prefix: 'next-', + pure: false, + type: 'normal', + closable: true, + defaultVisible: false, + size: 'medium', + alignEdge: false, + align: 'b', + offset: [0, 0], + trigger: , + onClose: noop, + afterClose: noop, + onVisibleChange: noop, + needAdjust: false, + triggerType: 'hover', + safeNode: undefined, + safeId: null, + autoFocus: true, + animation: { + in: 'zoomIn', + out: 'zoomOut', + }, + cache: false, + popupStyle: {}, + popupClassName: '', + popupProps: {}, + }; + + constructor(props, context) { + super(props, context); + this.state = { + align: alignList.includes(props.align) ? props.align : 'b', + visible: 'visible' in props ? props.visible : props.defaultVisible, + }; + this._onClose = this._onClose.bind(this); + this._onPosition = this._onPosition.bind(this); + this._onVisibleChange = this._onVisibleChange.bind(this); + } + + static getDerivedStateFromProps(nextProps, prevState) { + const nextState = {}; + if ('visible' in nextProps) { + nextState.visible = nextProps.visible; + } + + if ( + !prevState.innerAlign && + 'align' in nextProps && + alignList.includes(nextProps.align) + ) { + nextState.align = nextProps.align; + nextState.innerAlign = false; + } + + return nextState; + } + + _onVisibleChange(visible, trigger) { + // Not Controlled + if (!('visible' in this.props)) { + this.setState({ + visible: visible, + }); + } + + this.props.onVisibleChange(visible, trigger); + + if (!visible) { + this.props.onClose(); + } + } + + _onClose(e) { + this._onVisibleChange(false, 'closeClick'); + + //必须加上preventDefault,否则单测IE下报错,出现full page reload 异常 + e.preventDefault(); + } + + _onPosition(res) { + const { rtl } = this.props; + alignMap = this.props.alignEdge ? edgeMap : normalMap; + const newAlign = res.align.join(' '); + let resAlign; + + let alignKey = 'align'; + if (rtl) { + alignKey = 'rtlAlign'; + } + + for (const key in alignMap) { + if (alignMap[key][alignKey] === newAlign) { + resAlign = key; + + break; + } + } + + resAlign = resAlign || this.state.align; + if (resAlign !== this.state.align) { + this.setState({ + align: resAlign, + innerAlign: true, + }); + } + } + + render() { + const { + id, + type, + prefix, + className, + alignEdge, + trigger, + triggerType, + children, + closable, + shouldUpdatePosition, + delay, + needAdjust, + safeId, + autoFocus, + safeNode, + onClick, + onHover, + animation, + offset, + style, + container, + popupContainer, + cache, + popupStyle, + popupClassName, + popupProps, + followTrigger, + rtl, + ...others + } = this.props; + + if (container) { + log.deprecated('container', 'popupContainer', 'Balloon'); + } + + const { align } = this.state; + + alignMap = alignEdge ? edgeMap : normalMap; + const _prefix = this.context.prefix || prefix; + + let trOrigin = 'trOrigin'; + if (rtl) { + trOrigin = 'rtlTrOrigin'; + } + + const _offset = [ + alignMap[align].offset[0] + offset[0], + alignMap[align].offset[1] + offset[1], + ]; + const transformOrigin = alignMap[align][trOrigin]; + const _style = { ...{ transformOrigin }, ...style }; + + const content = ( + + {children} + + ); + + const triggerProps = {}; + triggerProps['aria-describedby'] = id; + triggerProps.tabIndex = '0'; + + const ariaTrigger = id + ? React.cloneElement(trigger, triggerProps) + : trigger; + + const newTrigger = getDisabledCompatibleTrigger( + React.isValidElement(ariaTrigger) ? ( + ariaTrigger + ) : ( + {ariaTrigger} + ) + ); + + return ( + + {content} + + ); + } +} + +export default polyfill(Balloon); diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/balloon/index.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/balloon/index.jsx new file mode 100644 index 000000000..06b0afd9f --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/balloon/index.jsx @@ -0,0 +1,46 @@ +import ConfigProvider from '../config-provider'; +import Balloon from './balloon'; +import Tooltip from './tooltip'; +import Inner from './inner'; + +Balloon.Tooltip = ConfigProvider.config(Tooltip, { + transform: /* istanbul ignore next */ (props, deprecated) => { + if ('text' in props) { + deprecated('text', 'children', 'Tooltip'); + const { text, ...others } = props; + props = { children: text, ...others }; + } + + return props; + }, +}); +Balloon.Inner = Inner; + +export default ConfigProvider.config(Balloon, { + transform: /* istanbul ignore next */ (props, deprecated) => { + if (props.alignment) { + deprecated('alignment', 'alignEdge', 'Balloon'); + const { alignment, ...others } = props; + props = { alignEdge: alignment === 'edge', ...others }; + } + if (props.onCloseClick) { + deprecated( + 'onCloseClick', + 'onVisibleChange(visible, [type = "closeClick"])', + 'Balloon' + ); + const { onCloseClick, onVisibleChange, ...others } = props; + const newOnVisibleChange = (visible, type) => { + if (type === 'closeClick') { + onCloseClick(); + } + if (onVisibleChange) { + onVisibleChange(visible, type); + } + }; + props = { onVisibleChange: newOnVisibleChange, ...others }; + } + + return props; + }, +}); diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/balloon/inner.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/balloon/inner.jsx new file mode 100644 index 000000000..d62b3c543 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/balloon/inner.jsx @@ -0,0 +1,106 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; +import { func, obj } from '../util'; +import Icon from '../icon'; +import zhCN from '../locale/zh-cn'; +import { normalMap, edgeMap } from './alignMap'; + +/** + * Created by xiachi on 17/2/10. + */ + +const { noop } = func; + +class BalloonInner extends React.Component { + static contextTypes = { + prefix: PropTypes.string, + }; + static propTypes = { + prefix: PropTypes.string, + rtl: PropTypes.bool, + closable: PropTypes.bool, + children: PropTypes.any, + className: PropTypes.string, + alignEdge: PropTypes.bool, + onClose: PropTypes.func, + style: PropTypes.any, + align: PropTypes.string, + type: PropTypes.string, + isTooltip: PropTypes.bool, + locale: PropTypes.object, + pure: PropTypes.bool, + }; + static defaultProps = { + prefix: 'next-', + closable: true, + onClose: noop, + locale: zhCN.Balloon, + align: 'b', + type: 'normal', + alignEdge: false, + pure: false, + }; + + render() { + const { + prefix, + closable, + className, + style, + isTooltip, + align, + type, + onClose, + alignEdge, + children, + rtl, + locale, + ...others + } = this.props; + + const alignMap = alignEdge ? edgeMap : normalMap; + let _prefix = prefix; + + if (isTooltip) { + _prefix = `${_prefix}balloon-tooltip`; + } else { + _prefix = `${_prefix}balloon`; + } + + const classes = classNames({ + [`${_prefix}`]: true, + [`${_prefix}-${type}`]: type, + [`${_prefix}-medium`]: true, + [`${_prefix}-${alignMap[align].arrow}`]: alignMap[align], + [`${_prefix}-closable`]: closable, + [className]: className, + }); + + return ( +
+ {children} + {closable ? ( + + + + ) : null} +
+ ); + } +} + +export default BalloonInner; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/balloon/main.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/balloon/main.scss new file mode 100644 index 000000000..c91b02e31 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/balloon/main.scss @@ -0,0 +1,120 @@ +@charset "UTF-8"; + +@import "../core/index-noreset.scss"; +@import "scss/variable"; +@import "scss/mixin"; + +.#{$css-prefix}balloon { + @include box-sizing; + @include balloon-bounding($balloon-border-style); + + font-size: $balloon-content-font-size; + font-weight: $balloon-content-font-weight; + animation-duration: $motion-duration-standard; + animation-timing-function: $motion-ease-in-out; + word-wrap: break-all; + word-wrap: break-word; + z-index: 0; + &:focus, + & *:focus { + outline: 0; + } + + &-primary { + @include balloon-state( + $balloon-primary-color, + $balloon-primary-color-border, + $balloon-primary-color-bg, + $balloon-primary-shadow, + $balloon-primary-border-width + ); + @include balloon-close( + $balloon-size-close-margin-top, + $balloon-size-close-margin-right, + $balloon-size-close, + $balloon-primary-color-close, + $balloon-primary-color-close-hover + ); + @include balloon-arrow( + $balloon-size-arrow-size, + $balloon-size-arrow-size, + $balloon-primary-color-border, + $balloon-primary-color-bg, + $balloon-primary-shadow, + $balloon-primary-border-width, + $balloon-size-arrow-expose-primary + ); + } + + &-normal { + @include balloon-state( + $balloon-normal-color, + $balloon-normal-color-border, + $balloon-normal-color-bg, + $balloon-normal-shadow, + $balloon-normal-border-width + ); + @include balloon-close( + $balloon-size-close-margin-top, + $balloon-size-close-margin-right, + $balloon-size-close, + $balloon-normal-color-close, + $balloon-normal-color-close-hover + ); + @include balloon-arrow( + $balloon-size-arrow-size, + $balloon-size-arrow-size, + $balloon-normal-color-border, + $balloon-normal-color-bg, + $balloon-normal-shadow, + $balloon-normal-border-width, + $balloon-size-arrow-expose + ); + } + + @include show-hidden(); + + /* size */ + &-medium { + @include balloon-size($balloon-size-padding-top, $balloon-size-padding-right, $balloon-size-padding-top, $balloon-size-padding-right); + } + /* 带关闭按钮的右侧padding变大 */ + &-closable { + @include balloon-size($balloon-size-padding-top, $balloon-size-padding-closable-right, $balloon-size-padding-top, $balloon-size-padding-right); + } +} + +.#{$css-prefix}balloon-tooltip { + @include box-sizing; + @include balloon-bounding($balloon-tooltip-border-style); + + font-size: $balloon-tooltip-content-font-size; + font-weight: $balloon-tooltip-content-font-weight; + z-index: 0; + word-wrap: break-all; + word-wrap: break-word; + + @include tooltip-state( + $balloon-tooltip-color, + $balloon-tooltip-color-border, + $balloon-tooltip-color-bg, + $balloon-tooltip-shadow, + $balloon-tooltip-border-width + ); + + @include tooltip-arrow( + $balloon-size-arrow-size, + $balloon-size-arrow-size, + $balloon-tooltip-color-border, + $balloon-tooltip-color-bg + ); + + @include show-hidden(); + + /* size */ + &-medium { + @include balloon-size($balloon-tooltip-size-padding-top, $balloon-tooltip-size-padding-right, $balloon-tooltip-size-padding-bottom, $balloon-tooltip-size-padding-left); + } +} + +@import "./rtl.scss"; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/balloon/rtl.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/balloon/rtl.scss new file mode 100644 index 000000000..e7dc45d68 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/balloon/rtl.scss @@ -0,0 +1,206 @@ +@import "../core/index-noreset.scss"; + +@mixin tooltip-arrow-rtl() { + + &.#{$css-prefix}balloon-tooltip-right:after { + left: $balloon-size-arrow-expose; + right: auto; + border-top: none; + border-right: none; + border-left: inherit; + border-bottom: inherit; + } + + &.#{$css-prefix}balloon-tooltip-left:after { + right: $balloon-size-arrow-expose; + left: auto; + border-top: inherit; + border-right: inherit; + border-left: none; + border-bottom: none; + } + &.#{$css-prefix}balloon-tooltip-left-top:after { + right: $balloon-size-arrow-expose; + left: auto; + border-top: inherit; + border-right: inherit; + border-left: none; + border-bottom: none; + } + &.#{$css-prefix}balloon-tooltip-left-bottom:after { + right: $balloon-size-arrow-expose; + left: auto; + border-top: inherit; + border-right: inherit; + border-left: none; + border-bottom: none; + } + + &.#{$css-prefix}balloon-tooltip-right-top:after { + left: $balloon-size-arrow-expose; + right: auto; + border-top: none; + border-right: none; + border-left: inherit; + border-bottom: inherit; + } + + &.#{$css-prefix}balloon-tooltip-right-bottom:after { + left: $balloon-size-arrow-expose; + right: auto; + border-top: none; + border-right: none; + border-left: inherit; + border-bottom: inherit; + } + + &.#{$css-prefix}balloon-tooltip-top-left:after { + right: $balloon-size-arrow-margin; + left: auto; + } + + &.#{$css-prefix}balloon-tooltip-top-right:after { + left: $balloon-size-arrow-margin; + right: auto; + } + + &.#{$css-prefix}balloon-tooltip-bottom-left:after { + right: $balloon-size-arrow-margin; + left: auto; + } + + &.#{$css-prefix}balloon-tooltip-bottom-right:after { + left: $balloon-size-arrow-margin; + right: auto; + } +} + +@mixin balloon-close-rtl( + $left +) { + .#{$css-prefix}balloon-close { + left: $left; + right: auto; + } +} + +@mixin balloon-arrow-rtl( + $arrorExpose +) { + $shadow-top: $balloon-shadow-top; + $shadow-right: $balloon-shadow-right; + $shadow-bottom: $balloon-shadow-bottom; + $shadow-left: $balloon-shadow-left; + + &.#{$css-prefix}balloon-right:after { + left: $arrorExpose; + right: auto; + border-right: none; + border-top: none; + border-left: inherit; + border-bottom: inherit; + box-shadow: $shadow-left; + } + &.#{$css-prefix}balloon-left:after { + right: $arrorExpose; + left: auto; + border-left: none; + border-bottom: none; + border-right: inherit; + border-top: inherit; + box-shadow: $shadow-right; + } + &.#{$css-prefix}balloon-left-top:after { + right: $arrorExpose; + left: auto; + border-left: none; + border-bottom: none; + border-top: inherit; + border-right: inherit; + box-shadow: $shadow-right; + } + &.#{$css-prefix}balloon-left-bottom:after { + right: $arrorExpose; + left: auto; + border-left: none; + border-bottom: none; + border-top: inherit; + border-right: inherit; + box-shadow: $shadow-right; + } + + &.#{$css-prefix}balloon-right-top:after { + left: $arrorExpose; + right: auto; + border-right: none; + border-top: none; + border-bottom: inherit; + border-left: inherit; + box-shadow: $shadow-left; + } + + &.#{$css-prefix}balloon-right-bottom:after { + left: $arrorExpose; + right: auto; + border-right: none; + border-top: none; + border-bottom: inherit; + border-left: inherit; + box-shadow: $shadow-left; + } + + &.#{$css-prefix}balloon-top-left:after { + right: $balloon-size-arrow-margin; + left: auto; + } + + &.#{$css-prefix}balloon-top-right:after { + right: auto; + left: $balloon-size-arrow-margin; + } + + &.#{$css-prefix}balloon-bottom-left:after { + right: $balloon-size-arrow-margin; + left: auto; + } + + &.#{$css-prefix}balloon-bottom-right:after { + left: $balloon-size-arrow-margin; + right: auto; + } +} + +.#{$css-prefix}balloon[dir="rtl"] { + &.#{$css-prefix}balloon-primary { + @include balloon-close-rtl( + $balloon-size-close-margin-right + ); + @include balloon-arrow-rtl( + $balloon-size-arrow-expose-primary + ); + } + + &.#{$css-prefix}balloon-normal { + @include balloon-close-rtl( + $balloon-size-close-margin-right + ); + @include balloon-arrow-rtl( + $balloon-size-arrow-expose + ); + } + + /* 带关闭按钮的右侧padding变大 */ + &.#{$css-prefix}balloon-closable { + @include balloon-size($balloon-size-padding-top, $balloon-size-padding-right, $balloon-size-padding-top, $balloon-size-padding-closable-right); + } +} + +.#{$css-prefix}balloon-tooltip[dir="rtl"] { + + @include tooltip-arrow-rtl(); + + /* size */ + &.#{$css-prefix}balloon-tooltip-medium { + @include balloon-size($balloon-tooltip-size-padding-top, $balloon-tooltip-size-padding-left, $balloon-tooltip-size-padding-bottom, $balloon-tooltip-size-padding-right); + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/balloon/scss/mixin.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/balloon/scss/mixin.scss new file mode 100755 index 000000000..ec48db6fd --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/balloon/scss/mixin.scss @@ -0,0 +1,318 @@ +@charset "UTF-8"; + +// balloon mixins +// -------------------------------------------------- + +@mixin balloon-bounding($border-style) { + position: absolute; + max-width: $balloon-size-max-width; + border-style: $border-style; + border-radius: $balloon-corner; +} + +@mixin balloon-state( + $contentColor, + $colorBorder, + $colorBg, + $shadow, + $widthBorder +) { + color: $contentColor; + border-color: $colorBorder; + background-color: $colorBg; + box-shadow: $shadow; + border-width: $widthBorder; +} + +@mixin balloon-size( + $padding-top, + $padding-right, + $padding-bottom, + $padding-left +) { + padding: $padding-top $padding-right $padding-bottom $padding-left; +} + +@mixin balloon-arrow( + $width, + $height, + $colorBorder, + $colorBg, + $shadow, + $widthBorder, + $arrorExpose +) { + $shadow-top: $balloon-shadow-top; + $shadow-right: $balloon-shadow-right; + $shadow-bottom: $balloon-shadow-bottom; + $shadow-left: $balloon-shadow-left; + + @if $shadow == $shadow-zero { + $shadow-top: null; + $shadow-right: null; + $shadow-bottom: null; + $shadow-left: null; + } + &:after { + position: absolute; + width: $height; + height: $height; + content: ''; + transform: rotate(45deg); + box-sizing: content-box !important; + border: $widthBorder $balloon-border-style $colorBorder; + background-color: $colorBg; + z-index: -1; + } + &.#{$css-prefix}balloon-top:after { + top: $arrorExpose; + left: calc(50% + #{$arrorExpose}); + border-right: none; + border-bottom: none; + box-shadow: $shadow-top; + } + &.#{$css-prefix}balloon-right:after { + top: calc(50% + #{$arrorExpose}); + right: $arrorExpose; + border-left: none; + border-bottom: none; + box-shadow: $shadow-right; + } + &.#{$css-prefix}balloon-bottom:after { + bottom: $arrorExpose; + left: calc(50% + #{$arrorExpose}); + border-top: none; + border-left: none; + box-shadow: $shadow-bottom; + } + &.#{$css-prefix}balloon-left:after { + top: calc(50% + #{$arrorExpose}); + left: $arrorExpose; + border-top: none; + border-right: none; + box-shadow: $shadow-left; + } + &.#{$css-prefix}balloon-left-top:after { + top: $balloon-size-arrow-margin; + left: $arrorExpose; + border-top: none; + border-right: none; + box-shadow: $shadow-left; + } + &.#{$css-prefix}balloon-left-bottom:after { + bottom: $balloon-size-arrow-margin; + left: $arrorExpose; + border-top: none; + border-right: none; + box-shadow: $shadow-left; + } + + &.#{$css-prefix}balloon-right-top:after { + top: $balloon-size-arrow-margin; + right: $arrorExpose; + border-bottom: none; + border-left: none; + box-shadow: $shadow-right; + } + + &.#{$css-prefix}balloon-right-bottom:after { + right: $arrorExpose; + bottom: $balloon-size-arrow-margin; + border-bottom: none; + border-left: none; + box-shadow: $shadow-right; + } + + &.#{$css-prefix}balloon-top-left:after { + top: $arrorExpose; + left: $balloon-size-arrow-margin; + border-right: none; + border-bottom: none; + box-shadow: $shadow-top; + } + + &.#{$css-prefix}balloon-top-right:after { + top: $arrorExpose; + right: $balloon-size-arrow-margin; + border-right: none; + border-bottom: none; + box-shadow: $shadow-top; + } + + &.#{$css-prefix}balloon-bottom-left:after { + bottom: $arrorExpose; + left: $balloon-size-arrow-margin; + border-top: none; + border-left: none; + box-shadow: $shadow-bottom; + } + + &.#{$css-prefix}balloon-bottom-right:after { + right: $balloon-size-arrow-margin; + bottom: $arrorExpose; + border-top: none; + border-left: none; + box-shadow: $shadow-bottom; + } +} + +@mixin balloon-close( + $top, + $right, + $iconSize, + $colorClose, + $colorCloseHover +) { + .#{$css-prefix}balloon-close { + position: absolute; + top: $top; + right: $right; + font-size: $iconSize; + cursor: pointer; + + .#{$css-prefix}icon { + @include icon-square-size($iconSize); + } + color: $colorClose; + :hover { + color: $colorCloseHover; + } + } +} + +@mixin show-hidden() { + &.visible { + display: block; + } + &.hidden { + display: none; + } +} + +@mixin tooltip-state( + $contentColor, + $colorBorder, + $colorBg, + $shadow, + $widthBorder +) { + color: $contentColor; + border-color: $colorBorder; + background-color: $colorBg; + box-shadow: $shadow; + border-width: $widthBorder; +} + +@mixin tooltip-arrow( + $width, + $height, + $colorBorder, + $colorBg +) { + + $shadow-top: null; + $shadow-right: null; + $shadow-bottom: null; + $shadow-left: null; + &:after { + position: absolute; + width: $width; + height: $height; + content: ''; + transform: rotate(45deg); + box-sizing: content-box !important; + border: $balloon-tooltip-border-width $balloon-tooltip-border-style $colorBorder; + background-color: $colorBg; + z-index: -1; + } + &-top:after { + top: $balloon-size-arrow-expose; + left: calc(50% + #{$balloon-size-arrow-expose}); + border-right: none; + border-bottom: none; + box-shadow: $shadow-top; + } + &-right:after { + top: calc(50% + #{$balloon-size-arrow-expose}); + right: $balloon-size-arrow-expose; + border-left: none; + border-bottom: none; + box-shadow: $shadow-right; + } + &-bottom:after { + bottom: $balloon-size-arrow-expose; + left: calc(50% + #{$balloon-size-arrow-expose}); + border-top: none; + border-left: none; + box-shadow: $shadow-bottom; + } + &-left:after { + top: calc(50% + #{$balloon-size-arrow-expose}); + left: $balloon-size-arrow-expose; + border-top: none; + border-right: none; + box-shadow: $shadow-left; + } + &-left-top:after { + top: $balloon-size-arrow-margin; + left: $balloon-size-arrow-expose; + border-top: none; + border-right: none; + box-shadow: $shadow-left; + } + &-left-bottom:after { + bottom: $balloon-size-arrow-margin; + left: $balloon-size-arrow-expose; + border-top: none; + border-right: none; + box-shadow: $shadow-left; + } + + &-right-top:after { + top: $balloon-size-arrow-margin; + right: $balloon-size-arrow-expose; + border-bottom: none; + border-left: none; + box-shadow: $shadow-right; + } + + &-right-bottom:after { + right: $balloon-size-arrow-expose; + bottom: $balloon-size-arrow-margin; + border-bottom: none; + border-left: none; + box-shadow: $shadow-right; + } + + &-top-left:after { + top: $balloon-size-arrow-expose; + left: $balloon-size-arrow-margin; + border-right: none; + border-bottom: none; + box-shadow: $shadow-top; + } + + &-top-right:after { + top: $balloon-size-arrow-expose; + right: $balloon-size-arrow-margin; + border-right: none; + border-bottom: none; + box-shadow: $shadow-top; + } + + &-bottom-left:after { + bottom: $balloon-size-arrow-expose; + left: $balloon-size-arrow-margin; + border-top: none; + border-left: none; + box-shadow: $shadow-bottom; + } + + &-bottom-right:after { + right: $balloon-size-arrow-margin; + bottom: $balloon-size-arrow-expose; + border-top: none; + border-left: none; + box-shadow: $shadow-bottom; + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/balloon/scss/variable.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/balloon/scss/variable.scss new file mode 100644 index 000000000..746030e24 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/balloon/scss/variable.scss @@ -0,0 +1,186 @@ +@charset "UTF-8"; + +//// +/// @module balloon: 气泡 +/// @tag Balloon +/// @category component +/// @family feedback +/// @varPrefix $balloon- +/// @classPrefix {prefix}-balloon +/// @order {"size/bounding":10,"size/content":11,"size/close icon":12,"size/arrow":13,"statement/normal":10,"statement/normal/bounding":100,"statement/normal/content":101,"statement/normal/close icon":102,"statement/hover":11,"statement/hover/close icon":110} +//// + + +// balloon variables +// -------------------------------------------------- + +// Size +/// max width +/// @type length +/// @namespace size/bounding +$balloon-size-max-width: 300px !default; + +/// padding (t, b) +/// @namespace size/content +$balloon-size-padding-top: $s-4 !default; + +/// padding (r) +/// @namespace size/content +$balloon-size-padding-right: $s-4 !default; + +/// padding (l) +/// @namespace size/content +$balloon-size-padding-closable-right: $s-10 !default; + +/// text +/// @namespace size/content +$balloon-content-font-size: $font-size-body-1 !default; + +/// text weight +/// @namespace size/content +$balloon-content-font-weight: $font-weight-2 !default; + +/// border width +/// @namespace size/bounding +$balloon-normal-border-width: $line-1 !default; + +/// border width +/// @namespace size/bounding +$balloon-primary-border-width: $line-1 !default; + +/// border width +/// @namespace size/bounding +$balloon-tooltip-border-width: $line-1 !default; + +/// text +/// @namespace size/content +$balloon-tooltip-content-font-size: $font-size-body-1 !default; + +/// text weight +/// @namespace size/content +$balloon-tooltip-content-font-weight: $font-weight-2 !default; + +/// size +/// @namespace size/close icon +$balloon-size-close: $icon-xs !default; + +/// margin (t) +/// @namespace size/close icon +$balloon-size-close-margin-top: $s-3 !default; + +/// margin (r) +/// @namespace size/close icon +$balloon-size-close-margin-right: $s-3 !default; + +/// size +/// @namespace size/arrow +$balloon-size-arrow-size: $s-3 !default; + +/// margin +/// @namespace size/arrow +$balloon-size-arrow-margin: $s-3 !default; + +/// padding (t) +/// @namespace size/bounding +$balloon-tooltip-size-padding-top: $s-2 !default; + +/// padding (r) +/// @namespace size/bounding +$balloon-tooltip-size-padding-right: $s-2 !default; + +/// padding (b) +/// @namespace size/bounding +$balloon-tooltip-size-padding-bottom: $s-2 !default; + +/// padding (l) +/// @namespace size/bounding +$balloon-tooltip-size-padding-left: $s-2 !default; + +$balloon-size-padding: $balloon-size-padding-top $balloon-size-padding-right; +$balloon-size-closable-padding: $balloon-size-padding-top $balloon-size-padding-closable-right $balloon-size-padding-top $balloon-size-padding-right; +$balloon-size-arrow-expose: -$balloon-size-arrow-size / 2 - 1; +$balloon-size-arrow-expose-primary: -$balloon-size-arrow-size / 2 - $balloon-primary-border-width; + +// Common +/// border style +/// @namespace statement/normal/bounding +$balloon-border-style: $line-solid !default; +/// corner +/// @namespace statement/normal/bounding +$balloon-corner: $corner-1 !default; + +// Normal +/// background +/// @namespace statement/normal/bounding +$balloon-normal-color-bg: $color-white !default; + +/// border +/// @namespace statement/normal/bounding +$balloon-normal-color-border: $color-line1-2 !default; + +/// shadow +/// @namespace statement/normal/bounding +$balloon-normal-shadow: $shadow-2-down !default; + +/// text +/// @namespace statement/normal/content +$balloon-normal-color: $color-text1-4 !default; + +/// color +/// @namespace statement/normal/close icon +$balloon-normal-color-close: $color-text1-2 !default; + +/// color +/// @namespace statement/hover/close icon +$balloon-normal-color-close-hover: $color-text1-3 !default; + +// Primary +/// background +/// @namespace statement/normal/bounding +$balloon-primary-color-bg: $color-notice-1 !default; + +/// border +/// @namespace statement/normal/bounding +$balloon-primary-color-border: $color-notice-3 !default; + +/// shadow +/// @namespace statement/normal/bounding +$balloon-primary-shadow: $shadow-1-down !default; + +/// text +/// @namespace statement/normal/content +$balloon-primary-color: $color-text1-4 !default; + +/// color +/// @namespace statement/normal/close icon +$balloon-primary-color-close: $color-text1-2 !default; + +/// color +/// @namespace statement/hover/close icon +$balloon-primary-color-close-hover: $color-text1-4 !default; + +// Tooltip +/// background +/// @namespace statement/normal/bounding +$balloon-tooltip-color-bg: $color-fill1-2 !default; + +/// shadow +/// @namespace statement/normal/bounding +$balloon-tooltip-shadow: $shadow-zero !default; + +/// border +/// @namespace statement/normal/bounding +$balloon-tooltip-color-border: $color-line1-2 !default; + +/// border style +/// @namespace statement/normal/bounding +$balloon-tooltip-border-style: $line-solid !default; + +/// text +/// @namespace statement/normal/content +$balloon-tooltip-color: $color-text1-4 !default; + +$balloon-shadow-top: shadow-maker($shadow-sides-base, 1, rgba($shadow-color-sd1, .1), -1, -1); +$balloon-shadow-right: shadow-maker($shadow-sides-base, 1, rgba($shadow-color-sd1, .1), 1, -1); +$balloon-shadow-bottom: shadow-maker($shadow-sides-base, 1, rgba($shadow-color-sd1, .1), 1, 1); +$balloon-shadow-left: shadow-maker($shadow-sides-base, 1, rgba($shadow-color-sd1, .1), -1, 1); diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/balloon/style.js b/packages/material-parser/test/fixtures/fusion-next-component/src/balloon/style.js new file mode 100644 index 000000000..cd58ce291 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/balloon/style.js @@ -0,0 +1,4 @@ +import '../animate/style.js'; +import '../overlay/style.js'; +import '../icon/style.js'; +import './main.scss'; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/balloon/tooltip.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/balloon/tooltip.jsx new file mode 100644 index 000000000..7607fdea5 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/balloon/tooltip.jsx @@ -0,0 +1,193 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import Overlay from '../overlay'; +import BalloonInner from './inner'; +import { normalMap, edgeMap } from './alignMap'; +import { getDisabledCompatibleTrigger } from './util'; + +const { Popup } = Overlay; + +let alignMap = normalMap; +/** Balloon.Tooltip */ +export default class Tooltip extends React.Component { + static propTypes = { + /** + * 样式类名的品牌前缀 + */ + prefix: PropTypes.string, + /** + * 自定义类名 + */ + className: PropTypes.string, + /** + * 自定义内联样式 + */ + style: PropTypes.object, + /** + * tooltip的内容 + */ + children: PropTypes.any, + /** + * 弹出层位置 + * @enumdesc 上, 右, 下, 左, 上左, 上右, 下左, 下右, 左上, 左下, 右上, 右下 及其 两两组合 + */ + align: PropTypes.oneOf([ + 't', + 'r', + 'b', + 'l', + 'tl', + 'tr', + 'bl', + 'br', + 'lt', + 'lb', + 'rt', + 'rb', + ]), + /** + * 触发元素 + */ + trigger: PropTypes.any, + /** + * 触发行为 + * 鼠标悬浮, 鼠标点击('hover', 'click')或者它们组成的数组,如 ['hover', 'click'], 强烈不建议使用'focus',若有复杂交互,推荐使用triggerType为click的Balloon组件 + */ + triggerType: PropTypes.oneOfType([PropTypes.string, PropTypes.array]), + /** + * 弹层组件style,透传给Popup + */ + popupStyle: PropTypes.object, + /** + * 弹层组件className,透传给Popup + */ + popupClassName: PropTypes.string, + /** + * 弹层组件属性,透传给Popup + */ + popupProps: PropTypes.object, + /** + * 是否pure render + */ + pure: PropTypes.bool, + /** + * 指定浮层渲染的父节点, 可以为节点id的字符串,也可以返回节点的函数。 + */ + popupContainer: PropTypes.any, + /** + * 是否跟随滚动 + */ + followTrigger: PropTypes.bool, + /** + * 弹层id, 传入值才会支持无障碍 + */ + id: PropTypes.string, + /** + * 如果需要让 Tooltip 内容可被点击,可以设置这个参数,例如 100 + */ + delay: PropTypes.number, + }; + static defaultProps = { + triggerType: 'hover', + prefix: 'next-', + align: 'b', + delay: 0, + trigger: , + }; + + render() { + const { + id, + className, + align, + style, + prefix, + trigger, + children, + popupContainer, + popupProps, + popupClassName, + popupStyle, + followTrigger, + triggerType, + autoFocus, + alignEdge, + rtl, + delay, + ...others + } = this.props; + + let trOrigin = 'trOrigin'; + if (rtl) { + others.rtl = true; + trOrigin = 'rtlTrOrigin'; + } + + alignMap = alignEdge ? edgeMap : normalMap; + + const transformOrigin = alignMap[align][trOrigin]; + const _offset = alignMap[align].offset; + const _style = { transformOrigin, ...style }; + + const content = ( + + {children} + + ); + + const triggerProps = {}; + triggerProps['aria-describedby'] = id; + triggerProps.tabIndex = '0'; + + let newTriggerType = triggerType; + + if (triggerType === 'hover' && id) { + newTriggerType = ['focus', 'hover']; + } + + const ariaTrigger = id + ? React.cloneElement(trigger, triggerProps) + : trigger; + + const newTrigger = getDisabledCompatibleTrigger( + React.isValidElement(ariaTrigger) ? ( + ariaTrigger + ) : ( + {ariaTrigger} + ) + ); + + return ( + + {content} + + ); + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/balloon/util.js b/packages/material-parser/test/fixtures/fusion-next-component/src/balloon/util.js new file mode 100644 index 000000000..ecac5dc62 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/balloon/util.js @@ -0,0 +1,26 @@ +import React from 'react'; + +export function getDisabledCompatibleTrigger(element) { + if ( + element.type.displayName === 'Config(Button)' && + element.props.disabled + ) { + const displayStyle = + element.props.style && element.props.style.display + ? element.props.style.display + : 'inline-block'; + const child = React.cloneElement(element, { + style: { + ...element.props.style, + pointerEvents: 'none', + }, + }); + return ( + // eslint-disable-next-line + + {child} + + ); + } + return element; +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/box/index.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/box/index.jsx new file mode 100644 index 000000000..ed9307158 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/box/index.jsx @@ -0,0 +1,252 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import cx from 'classnames'; +import ConfigProvider from '../config-provider'; +import { obj } from '../util'; +import createStyle, { + getMargin, + getChildMargin, + getSpacingHelperMargin, + filterInnerStyle, + filterHelperStyle, + filterOuterStyle, + getGridChildProps, + // getBoxChildProps, +} from '../responsive-grid/create-style'; + +const { pickOthers } = obj; + +const createChildren = (children, { spacing, direction, wrap, device }) => { + const array = React.Children.toArray(children); + if (!children) { + return null; + } + + return array.map((child, index) => { + let spacingMargin = {}; + + spacingMargin = getChildMargin(spacing); + + if (!wrap) { + // 不折行 + const isNone = [index === 0, index === array.length - 1]; + const props = + direction === 'row' + ? ['marginLeft', 'marginRight'] + : ['marginTop', 'marginBottom']; + + ['marginTop', 'marginRight', 'marginBottom', 'marginLeft'].forEach( + prop => { + if (prop in spacingMargin && props.indexOf(prop) === -1) { + spacingMargin[prop] = 0; + } + + props.forEach((key, i) => { + if (key in spacingMargin && isNone[i]) { + spacingMargin[key] = 0; + } + }); + } + ); + } + + if (React.isValidElement(child)) { + const { margin: propsMargin } = child.props; + const childPropsMargin = getMargin(propsMargin); + let gridProps = {}; + + if ( + typeof child.type === 'function' && + child.type._typeMark === 'responsive_grid' + ) { + gridProps = createStyle({ display: 'grid', ...child.props }); + } + + return React.cloneElement(child, { + style: { + ...spacingMargin, + // ...getBoxChildProps(child.props), + ...childPropsMargin, + ...gridProps, + ...(child.props.style || {}), + }, + }); + } + + return child; + }); +}; + +const getStyle = (style = {}, props) => { + return { + ...createStyle({ display: 'flex', ...props }), + ...style, + }; +}; + +const getOuterStyle = (style, styleProps) => { + const sheet = getStyle(style, styleProps); + + return filterOuterStyle(sheet); +}; + +const getHelperStyle = (style, styleProps) => { + const sheet = getStyle(style, styleProps); + + return filterHelperStyle({ + ...sheet, + ...getSpacingHelperMargin(styleProps.spacing), + }); +}; + +const getInnerStyle = (style, styleProps) => { + const sheet = getStyle(style, styleProps); + + return filterInnerStyle(sheet); +}; + +/** + * Box + */ +class Box extends Component { + static propTypes = { + prefix: PropTypes.string, + style: PropTypes.object, + className: PropTypes.any, + /** + * 布局属性 + */ + flex: PropTypes.oneOfType([ + PropTypes.arrayOf( + PropTypes.oneOfType([PropTypes.number, PropTypes.string]) + ), + PropTypes.number, + ]), + /** + * 布局方向,默认为 column ,一个元素占据一整行 + * @default column + */ + direction: PropTypes.oneOf(['row', 'column']), + /** + * 是否折行 + */ + wrap: PropTypes.bool, + /** + * 元素之间的间距 [bottom&top, right&left] + */ + spacing: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.number), + PropTypes.number, + ]), + /** + * 设置 margin [bottom&top, right&left] + */ + margin: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.number), + PropTypes.number, + ]), + /** + * 设置 padding [bottom&top, right&left] + */ + padding: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.number), + PropTypes.number, + ]), + /** + * 沿着主轴方向,子元素们的排布关系 (兼容性同 justify-content ) + */ + justify: PropTypes.oneOf([ + 'flex-start', + 'center', + 'flex-end', + 'space-between', + 'space-around', + ]), + /** + * 垂直主轴方向,子元素们的排布关系 (兼容性同 align-items ) + */ + align: PropTypes.oneOf([ + 'flex-start', + 'center', + 'flex-end', + 'baseline', + 'stretch', + ]), + device: PropTypes.oneOf(['phone', 'tablet', 'desktop']), + }; + + static defaultProps = { + prefix: 'next-', + direction: 'column', + wrap: false, + }; + + render() { + const { + prefix, + direction, + justify, + align, + wrap, + flex, + spacing, + padding, + margin, + style, + className, + children, + device, + } = this.props; + + const styleProps = { + direction, + justify, + align, + wrap, + flex, + spacing, + padding, + margin, + }; + const View = 'Component' in this.props ? Component : 'div'; + const others = pickOthers(Object.keys(Box.propTypes), this.props); + const styleSheet = getStyle(style, styleProps); + + const boxs = createChildren(children, { + spacing, + direction, + wrap, + device, + }); + + const cls = cx( + { + [`${prefix}box`]: true, + }, + className + ); + if (wrap && spacing) { + const outerStyle = getOuterStyle(style, styleProps); + const helperStyle = getHelperStyle(style, styleProps); + const innerStyle = getInnerStyle(style, styleProps); + + return ( + + + + {boxs} + + + + ); + } + + return ( + + {boxs} + + ); + } +} + +export default ConfigProvider.config(Box); diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/box/main.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/box/main.scss new file mode 100644 index 000000000..4f6f9a86e --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/box/main.scss @@ -0,0 +1,13 @@ +@charset "UTF-8"; + +@import "../core/index-noreset.scss"; + +@import "scss/mixin"; +@import "scss/variable"; + +/* put your code here */ + +#{$box-prefix} { + @include box-sizing; + display: flex; +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/box/scss/mixin.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/box/scss/mixin.scss new file mode 100644 index 000000000..64dae2675 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/box/scss/mixin.scss @@ -0,0 +1,4 @@ +@charset "UTF-8"; + +// box mixins +// -------------------------------------------------- diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/box/scss/variable.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/box/scss/variable.scss new file mode 100644 index 000000000..992cb35bc --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/box/scss/variable.scss @@ -0,0 +1,18 @@ +@charset "UTF-8"; + +// box variables +// -------------------------------------------------- + +//// +/// @module box: 弹性布局 +/// @tag Box +/// @category component +/// @family general +/// @varPrefix $box- +/// @classPrefix {prefix}-box +/// @order {} +//// + +// Unconfigurable +// ---------------------------------------- +$box-prefix: ".#{$css-prefix}box"; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/box/style.js b/packages/material-parser/test/fixtures/fusion-next-component/src/box/style.js new file mode 100644 index 000000000..f1ad40f46 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/box/style.js @@ -0,0 +1 @@ +import './main.scss'; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/breadcrumb/index.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/breadcrumb/index.jsx new file mode 100644 index 000000000..3abeb26a1 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/breadcrumb/index.jsx @@ -0,0 +1,247 @@ +import React, { Component, Children } from 'react'; +import PropTypes from 'prop-types'; +import { polyfill } from 'react-lifecycles-compat'; +import Icon from '../icon'; +import ConfigProvider from '../config-provider'; +import Item from './item'; +import { events } from '../util'; + +/** + * Breadcrumb + */ +class Breadcrumb extends Component { + static Item = Item; + + static propTypes = { + /** + * 样式类名的品牌前缀 + */ + prefix: PropTypes.string, + rtl: PropTypes.bool, + /*eslint-disable*/ + /** + * 面包屑子节点,需传入 Breadcrumb.Item + */ + children: (props, propName) => { + Children.forEach(props[propName], child => { + if ( + !( + child && + typeof child.type === 'function' && + child.type._typeMark === 'breadcrumb_item' + ) + ) { + throw new Error( + "Breadcrumb's children must be Breadcrumb.Item!" + ); + } + }); + }, + /*eslint-enable*/ + /** + * 面包屑最多显示个数,超出部分会被隐藏, 设置为 auto 会自动根据父元素的宽度适配。 + */ + maxNode: PropTypes.oneOfType([ + PropTypes.number, + PropTypes.oneOf(['auto']), + ]), + /** + * 分隔符,可以是文本或 Icon + */ + separator: PropTypes.node, + /** + * 设置标签类型 + */ + component: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), + className: PropTypes.any, + }; + + static defaultProps = { + prefix: 'next-', + maxNode: 100, + separator: , + component: 'nav', + }; + + constructor(props) { + super(props); + this.state = { + maxNode: props.maxNode === 'auto' ? 100 : props.maxNode, + }; + } + + static getDerivedStateFromProps(props, state) { + if (state.prevMaxNode === props.maxNode) { + return {}; + } + + return { + prevMaxNode: props.maxNode, + maxNode: props.maxNode === 'auto' ? 100 : props.maxNode, + }; + } + + componentDidMount() { + this.computeMaxNode(); + events.on(window, 'resize', this.computeMaxNode); + } + + componentDidUpdate() { + this.computeMaxNode(); + } + + componentWillUnmount() { + events.off(window, 'resize', this.computeMaxNode); + } + + computeMaxNode = () => { + // 计算最大node节点,无法获取到 ... 节点的宽度,目前会有 nodeWidth - ellipsisNodeWidth 的误差 + if (this.props.maxNode !== 'auto' || !this.breadcrumbEl) return; + const scrollWidth = this.breadcrumbEl.scrollWidth; + const rect = this.breadcrumbEl.getBoundingClientRect(); + + if (scrollWidth <= rect.width) return; + let maxNode = this.breadcrumbEl.children.length; + let index = 1; + let fullWidth = scrollWidth; + + while (index < this.breadcrumbEl.children.length - 1) { + const el = this.breadcrumbEl.children[index]; + maxNode--; + fullWidth -= el.getBoundingClientRect().width; + if (fullWidth <= rect.width) { + break; + } + index++; + } + + maxNode = Math.max(3, maxNode); + + if (maxNode !== this.state.maxNode) { + this.setState({ + maxNode, + }); + } + }; + + saveBreadcrumbRef = ref => { + this.breadcrumbEl = ref; + }; + + render() { + const { + prefix, + rtl, + className, + children, + separator, + component, + maxNode: maxNodeProp, + ...others + } = this.props; + + const { maxNode } = this.state; + + let items; + const length = Children.count(children); + + if (maxNode > 1 && length > maxNode) { + const breakpointer = length - maxNode + 1; + items = []; + + Children.forEach(children, (item, i) => { + const ariaProps = {}; + + if (i === length - 1) { + ariaProps['aria-current'] = 'page'; + } + + if (i && i === breakpointer) { + items.push( + React.cloneElement( + item, + { + separator, + prefix, + key: i, + activated: i === length - 1, + ...ariaProps, + className: `${prefix}breadcrumb-text-ellipsis`, + }, + '...' + ) + ); + } else if (!i || i > breakpointer) { + items.push( + React.cloneElement(item, { + separator, + prefix, + key: i, + ...ariaProps, + activated: i === length - 1, + }) + ); + } + }); + } else { + items = Children.map(children, (item, i) => { + const ariaProps = {}; + + if (i === length - 1) { + ariaProps['aria-current'] = 'page'; + } + + return React.cloneElement(item, { + separator, + prefix, + activated: i === length - 1, + ...ariaProps, + key: i, + }); + }); + } + + if (rtl) { + others.dir = 'rtl'; + } + + const BreadcrumbComponent = component; + + delete others.maxNode; + + return ( + +
    {items}
+ {maxNodeProp === 'auto' ? ( +
    + {Children.map(children, (item, i) => { + return React.cloneElement(item, { + separator, + prefix, + activated: i === length - 1, + key: i, + }); + })} +
+ ) : null} +
+ ); + } +} + +export default ConfigProvider.config(polyfill(Breadcrumb)); diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/breadcrumb/item.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/breadcrumb/item.jsx new file mode 100644 index 000000000..eef81e067 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/breadcrumb/item.jsx @@ -0,0 +1,70 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; +import ConfigProvider from '../config-provider'; + +/** + * Breadcrumb.Item + */ +class Item extends Component { + static propTypes = { + prefix: PropTypes.string, + rtl: PropTypes.bool, + /** + * 面包屑节点链接,如果设置这个属性,则该节点为`` ,否则是`` + */ + link: PropTypes.string, + activated: PropTypes.bool, + separator: PropTypes.node, + className: PropTypes.any, + children: PropTypes.node, + }; + + static defaultProps = { + prefix: 'next-', + }; + + static _typeMark = 'breadcrumb_item'; + + // stateless separator component + static Separator({ prefix, children }) { + return ( + {children} + ); + } + + render() { + const { + prefix, + rtl, + className, + children, + link, + activated, + separator, + ...others + } = this.props; + const clazz = classNames(`${prefix}breadcrumb-text`, className, { + activated, + }); + + return ( +
  • + {link ? ( + + {children} + + ) : ( + + {children} + + )} + {activated + ? null + : Item.Separator({ prefix, children: separator })} +
  • + ); + } +} + +export default ConfigProvider.config(Item); diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/breadcrumb/main.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/breadcrumb/main.scss new file mode 100644 index 000000000..2a6826ce8 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/breadcrumb/main.scss @@ -0,0 +1,35 @@ +@charset "UTF-8"; + +@import "../core/index-noreset.scss"; + +@import "scss/mixin"; +@import "scss/variable"; + +/* put your code here */ + +.#{$css-prefix} { + &breadcrumb { + @include breadcrumb-bounding(); + + @include breadcrumb-size( + $breadcrumb-height, + $breadcrumb-text-min-width, + $breadcrumb-size-m-font-size, + $breadcrumb-size-ellipsis-font-size, + $breadcrumb-size-m-icon-size, + $breadcrumb-size-m-icon-margin + ); + + @include breadcrumb-state( + $breadcrumb-text-color, + $breadcrumb-text-ellipsis-color, + $breadcrumb-text-current-color, + $breadcrumb-text-current-weight, + $breadcrumb-text-keyword-color, + $breadcrumb-icon-color, + $breadcrumb-text-color-hover, + $breadcrumb-text-current-color-hover, + $breadcrumb-text-keyword-color-hover + ); + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/breadcrumb/scss/mixin.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/breadcrumb/scss/mixin.scss new file mode 100644 index 000000000..22e3a45b6 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/breadcrumb/scss/mixin.scss @@ -0,0 +1,131 @@ +@charset "UTF-8"; + +// breadcrumb mixins +// -------------------------------------------------- + +@mixin breadcrumb-bounding() { + display: block; + margin: 0; + padding: 0; + white-space: nowrap; + + .#{$css-prefix}breadcrumb-item { + display: inline-block; + + .#{$css-prefix}breadcrumb-text { + display: inline-block; + text-decoration: none; + text-align: center; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + transition: all $motion-duration-immediately $motion-linear; + + > b { + font-weight: normal; + } + } + + .#{$css-prefix}breadcrumb-separator { + display: inline-block; + vertical-align: top; + } + } +} + +@mixin breadcrumb-size( + $height, + $minWidth, + $fontSize, + $ellipsisFontSize, + $separatorSize, + $separatorMargin +) { + height: $height; + line-height: $height; + + .#{$css-prefix}breadcrumb-text { + height: $height; + min-width: $minWidth; + font-size: $fontSize; + line-height: $height; + } + + .#{$css-prefix}breadcrumb-separator { + height: $height; + margin: 0 $separatorMargin; + font-size: $separatorSize; + line-height: $height; + + .#{$css-prefix}icon { + @include icon-size($separatorSize); + } + } + + .#{$css-prefix}breadcrumb-text-ellipsis { + font-size: $ellipsisFontSize; + } +} + +@mixin breadcrumb-state( + $textColor, + $ellipsisTextColor, + $currentTextColor, + $currentTextWeight, + $keywordTextColor, + $iconColor, + $textColorHover, + $currentTextColorHover, + $keywordTextColorHover +) { + .#{$css-prefix}breadcrumb-text { + color: $textColor; + > b { + color: $keywordTextColor; + } + > a { + color: $textColor; + text-decoration: none; + text-align: center; + } + } + + .#{$css-prefix}breadcrumb-text.activated { + color: $currentTextColor; + font-weight: $currentTextWeight; + > a { + color: $currentTextColor; + font-weight: $currentTextWeight; + } + } + + .#{$css-prefix}breadcrumb-text-ellipsis { + color: $ellipsisTextColor; + cursor: default; + } + + .#{$css-prefix}breadcrumb-separator { + color: $iconColor; + } + + .#{$css-prefix}breadcrumb-text:not(.#{$css-prefix}breadcrumb-text-ellipsis):hover > a { + color: $textColorHover; + } + + a.#{$css-prefix}breadcrumb-text.activated:hover > a { + color: $currentTextColorHover; + } + + a.#{$css-prefix}breadcrumb-text:not(.#{$css-prefix}breadcrumb-text-ellipsis):hover { + color: $textColorHover; + + > b { + color: $keywordTextColorHover; + } + } + + a.#{$css-prefix}breadcrumb-text.activated:hover { + color: $currentTextColorHover; + font-weight: $currentTextWeight; + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/breadcrumb/scss/variable.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/breadcrumb/scss/variable.scss new file mode 100644 index 000000000..7ca2e96e3 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/breadcrumb/scss/variable.scss @@ -0,0 +1,82 @@ +@charset "UTF-8"; + +// breadcrumb variables +// -------------------------------------------------- + +//// +/// @module breadcrumb: 面包屑 +/// @tag Breadcrumb +/// @category component +/// @family navigation +/// @varPrefix $breadcrumb- +/// @classPrefix {prefix}-breadcrumb +/// @order {"size/item":10,"size/ellipsis":11,"size/number":12,"size/keyword":13,"size/seperator":14,"statement/normal":10,"statement/normal/item":100,"statement/normal/item current":101,"statement/normal/ellipsis":102,"statement/normal/number":103,"statement/normal/keyword":104,"statement/normal/seperator":105,"statement/hover":11,"statement/hover/item":110,"statement/hover/item current":111,"statement/hover/number":112,"statement/hover/keyword":113} +//// + +// Unconfigurable +// ---------------------------------------- + +// 整体高度,不可配 +$breadcrumb-height: $s-4 !default; +// text 最小宽度,不可配 +$breadcrumb-text-min-width: $s-4 !default; + +// Size +// ---------------------------------------- + +/// text +/// @namespace size/item +$breadcrumb-size-m-font-size: $font-size-caption !default; + +/// text +/// @namespace size/ellipsis +$breadcrumb-size-ellipsis-font-size: $font-size-caption !default; + +/// size +/// @namespace size/seperator +$breadcrumb-size-m-icon-size: $icon-xxs !default; + +/// margin (l, r) +/// @namespace size/seperator +$breadcrumb-size-m-icon-margin: $s-2 !default; + +// Statement:Normal +// ---------------------------------------- + +/// text +/// @namespace statement/normal/item +$breadcrumb-text-color: $color-text1-3 !default; + +/// text +/// @namespace statement/normal/item current +$breadcrumb-text-current-color: $color-text1-4 !default; +/// weight +/// @namespace statement/normal/item current +$breadcrumb-text-current-weight: $font-weight-2 !default; + +/// text +/// @namespace statement/normal/ellipsis +$breadcrumb-text-ellipsis-color: $color-text1-3 !default; + +/// text +/// @namespace statement/normal/keyword +$breadcrumb-text-keyword-color: $color-brand1-6 !default; + +/// text +/// @namespace statement/normal/seperator +$breadcrumb-icon-color: $color-line1-4 !default; + +// Statement:Hover +// ---------------------------------------- + +/// text +/// @namespace statement/hover/item +$breadcrumb-text-color-hover: $color-brand1-6 !default; + +/// text +/// @namespace statement/hover/item current +$breadcrumb-text-current-color-hover: $color-brand1-6 !default; + +/// text +/// @namespace statement/hover/keyword +$breadcrumb-text-keyword-color-hover: $color-brand1-6 !default; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/breadcrumb/style.js b/packages/material-parser/test/fixtures/fusion-next-component/src/breadcrumb/style.js new file mode 100644 index 000000000..65cfc7e39 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/breadcrumb/style.js @@ -0,0 +1,2 @@ +import '../icon/style.js'; +import './main.scss'; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/build.js b/packages/material-parser/test/fixtures/fusion-next-component/src/build.js deleted file mode 100644 index a89aa0f98..000000000 --- a/packages/material-parser/test/fixtures/fusion-next-component/src/build.js +++ /dev/null @@ -1,51 +0,0 @@ -export { default as Affix } from './@alife/next/affix/container.js'; -export { default as Animate } from './@alife/next/animate/container.js'; -export { default as Badge } from './@alife/next/badge/container.js'; -export { default as Balloon } from './@alife/next/balloon/container.js'; -export { default as Breadcrumb } from './@alife/next/breadcrumb/container.js'; -export { default as Button } from './@alife/next/button/container.js'; -export { default as Calendar } from './@alife/next/calendar/container.js'; -export { default as Card } from './@alife/next/card/container.js'; -export { default as Cascader } from './@alife/next/cascader/container.js'; -export { default as CascaderSelect } from './@alife/next/cascader-select/container.js'; -export { default as Checkbox } from './@alife/next/checkbox/container.js'; -export { default as Collapse } from './@alife/next/collapse/container.js'; -export { default as ConfigProvider } from './@alife/next/config-provider/container.js'; -export { default as DatePicker } from './@alife/next/date-picker/container.js'; -export { default as Dialog } from './@alife/next/dialog/container.js'; -export { default as Dropdown } from './@alife/next/dropdown/container.js'; -export { default as Drawer } from './@alife/next/drawer/container.js'; -export { default as Field } from './@alife/next/field/container.js'; -export { default as Form } from './@alife/next/form/container.js'; -export { default as Grid } from './@alife/next/grid/container.js'; -export { default as Icon } from './@alife/next/icon/container.js'; -export { default as Input } from './@alife/next/input/container.js'; -export { default as Loading } from './@alife/next/loading/container.js'; -export { default as Menu } from './@alife/next/menu/container.js'; -export { default as MenuButton } from './@alife/next/menu-button/container.js'; -export { default as Message } from './@alife/next/message/container.js'; -export { default as Nav } from './@alife/next/nav/container.js'; -export { default as NumberPicker } from './@alife/next/number-picker/container.js'; -export { default as Overlay } from './@alife/next/overlay/container.js'; -export { default as Pagination } from './@alife/next/pagination/container.js'; -export { default as Paragraph } from './@alife/next/paragraph/container.js'; -export { default as Progress } from './@alife/next/progress/container.js'; -export { default as Radio } from './@alife/next/radio/container.js'; -export { default as Range } from './@alife/next/range/container.js'; -export { default as Rating } from './@alife/next/rating/container.js'; -export { default as Search } from './@alife/next/search/container.js'; -export { default as Select } from './@alife/next/select/container.js'; -export { default as Slider } from './@alife/next/slider/container.js'; -export { default as SplitButton } from './@alife/next/split-button/container.js'; -export { default as Step } from './@alife/next/step/container.js'; -export { default as Switch } from './@alife/next/switch/container.js'; -export { default as Tab } from './@alife/next/tab/container.js'; -export { default as Table } from './@alife/next/table/container.js'; -export { default as ConfigTag } from './@alife/next/tag/container.js'; -export { default as TimePicker } from './@alife/next/time-picker/container.js'; -export { default as Timeline } from './@alife/next/timeline/container.js'; -export { default as Transfer } from './@alife/next/transfer/container.js'; -export { default as Tree } from './@alife/next/tree/container.js'; -export { default as TreeSelect } from './@alife/next/tree-select/container.js'; -export { default as Upload } from './@alife/next/upload/container.js'; -export { default as VirtualList } from './@alife/next/virtual-list/container.js'; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/button/index.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/button/index.jsx new file mode 100644 index 000000000..c18fca4c5 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/button/index.jsx @@ -0,0 +1,42 @@ +import ConfigProvider from '../config-provider'; +import Button from './view/button'; +import ButtonGroup from './view/group'; + +Button.Group = ButtonGroup; + +export default ConfigProvider.config(Button, { + transform: /* istanbul ignore next */ (props, deprecated) => { + if ('shape' in props) { + deprecated('shape', 'text | warning | ghost', 'Button'); + + const { shape, type, ...others } = props; + + let newType = type; + if ( + type === 'light' || + type === 'dark' || + (type === 'secondary' && shape === 'warning') + ) { + newType = 'normal'; + } + + let ghost; + if (shape === 'ghost') { + ghost = { + primary: 'dark', + secondary: 'dark', + normal: 'light', + dark: 'dark', + light: 'light', + }[type || Button.defaultProps.type]; + } + + const text = shape === 'text'; + const warning = shape === 'warning'; + + props = { type: newType, ghost, text, warning, ...others }; + } + + return props; + }, +}); diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/button/main.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/button/main.scss new file mode 100644 index 000000000..01d9f5abe --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/button/main.scss @@ -0,0 +1,396 @@ +@import '../core/index-noreset'; + +@import './scss/variable'; +@import './scss/normalize'; +@import './scss/mixin'; + +#{$btn-prefix} { + & { + position: relative; + display: inline-block; + box-shadow: $btn-shadow; + text-decoration: none; + text-align: center; + text-transform: none; + white-space: nowrap; + vertical-align: middle; + user-select: none; + transition: all $motion-duration-immediately $motion-linear; + line-height: 1; + cursor: pointer; + + &:after { + text-align: center; + position: absolute; + opacity: 0; + visibility: hidden; + transition: opacity $motion-duration-immediately $motion-linear; + } + + &::before { + content: ''; + display: inline-block; + height: 100%; + width: 0; + vertical-align: middle; + } + + .#{$css-prefix}icon { + display: inline-block; + font-size: 0; + vertical-align: middle; + } + + > span, + > div { + display: inline-block; + vertical-align: middle; + } + + &.hover, + &:hover { + box-shadow: $btn-shadow-hover; + } + } + + /* 尺寸维度 */ + /* ---------------------------------------- */ + &.#{$css-prefix} { + &small { + @include next-button-size( + $btn-size-s-padding, + $btn-size-s-height, + $btn-size-s-font, + $btn-size-s-border-width, + $btn-size-s-corner, + $btn-size-s-icon-margin, + $btn-size-s-icon-size, + $btn-size-s-icon-split-size + ); + } + &medium { + @include next-button-size( + $btn-size-m-padding, + $btn-size-m-height, + $btn-size-m-font, + $btn-size-m-border-width, + $btn-size-m-corner, + $btn-size-m-icon-margin, + $btn-size-m-icon-size, + $btn-size-m-icon-split-size + ); + } + &large { + @include next-button-size( + $btn-size-l-padding, + $btn-size-l-height, + $btn-size-l-font, + $btn-size-l-border-width, + $btn-size-l-corner, + $btn-size-l-icon-margin, + $btn-size-l-icon-size, + $btn-size-l-icon-split-size + ); + } + } + + /* 普通按钮 */ + &#{$btn-prefix} { + &-normal { + border-style: $btn-pure-normal-border-style; + + @include button-color( + $btn-pure-normal-color, + $btn-pure-normal-color-hover, + $btn-pure-normal-bg, + $btn-pure-normal-bg-hover, + $btn-pure-normal-border-color, + $btn-pure-normal-border-color-hover + ); + } + + &-primary { + border-style: $btn-pure-primary-border-style; + + @include button-color( + $btn-pure-primary-color, + $btn-pure-primary-color-hover, + $btn-pure-primary-bg, + $btn-pure-primary-bg-hover, + $btn-pure-primary-border-color, + $btn-pure-primary-border-color-hover + ); + } + + &-secondary { + border-style: $btn-pure-secondary-border-style; + + @include button-color( + $btn-pure-secondary-color, + $btn-pure-secondary-color-hover, + $btn-pure-secondary-bg, + $btn-pure-secondary-bg-hover, + $btn-pure-secondary-border-color, + $btn-pure-secondary-border-color-hover + ); + } + } + + /* 普通态禁用样式 */ + &.disabled, + &[disabled] { + cursor: not-allowed; + + @include button-color( + $btn-pure-color-disabled, + $btn-pure-color-disabled, + $btn-pure-bg-disabled, + $btn-pure-bg-disabled, + $btn-pure-border-color-disabled, + $btn-pure-border-color-disabled + ); + } + + /* 警告按钮 */ + &-warning { + border-style: $btn-warning-border-style; + + &#{$btn-prefix}-primary { + @include button-color( + $btn-warning-primary-color, + $btn-warning-primary-color-hover, + $btn-warning-primary-bg, + $btn-warning-primary-bg-hover, + $btn-warning-primary-border-color, + $btn-warning-primary-border-color-hover + ); + &.disabled, + &[disabled] { + @include button-color( + $btn-warning-primary-color-disabled, + $btn-warning-primary-color-disabled, + $btn-warning-primary-bg-disabled, + $btn-warning-primary-bg-disabled, + $btn-warning-primary-border-color-disabled, + $btn-warning-primary-border-color-disabled + ); + } + } + + &#{$btn-prefix}-normal { + @include button-color( + $btn-warning-normal-color, + $btn-warning-normal-color-hover, + $btn-warning-normal-bg, + $btn-warning-normal-bg-hover, + $btn-warning-normal-border-color, + $btn-warning-normal-border-color-hover + ); + + &.disabled, + &[disabled] { + @include button-color( + $btn-warning-normal-color-disabled, + $btn-warning-normal-color-disabled, + $btn-warning-normal-bg-disabled, + $btn-warning-normal-bg-disabled, + $btn-warning-normal-border-color-disabled, + $btn-warning-normal-border-color-disabled + ); + } + } + } + + /* 文本按钮 */ + &-text { + box-shadow: none; + border-radius: 0; + + &.hover, + &:hover { + box-shadow: none; + } + + &#{$btn-prefix}-primary { + @include button-color( + $btn-text-primary-color, + $btn-text-primary-color-hover, + transparent, + transparent, + transparent, + transparent + ); + } + &#{$btn-prefix}-secondary { + @include button-color( + $btn-text-secondary-color, + $btn-text-secondary-color-hover, + transparent, + transparent, + transparent, + transparent + ); + } + &#{$btn-prefix}-normal { + @include button-color( + $btn-text-normal-color, + $btn-text-normal-color-hover, + transparent, + transparent, + transparent, + transparent + ); + } + &.#{$css-prefix}large { + @include next-button-size( + 0, + $btn-text-size-l-height, + $btn-text-size-l-font, + 0, + 0, + $btn-text-icon-l-margin, + $btn-size-l-icon-size, + $btn-size-l-icon-split-size + ); + } + &.#{$css-prefix}medium { + @include next-button-size( + 0, + $btn-text-size-m-height, + $btn-text-size-m-font, + 0, + 0, + $btn-text-icon-m-margin, + $btn-size-m-icon-size, + $btn-size-m-icon-split-size + ); + } + &.#{$css-prefix}small { + @include next-button-size( + 0, + $btn-text-size-s-height, + $btn-text-size-s-font, + 0, + 0, + $btn-text-icon-s-margin, + $btn-size-s-icon-size, + $btn-size-s-icon-split-size + ); + } + &.disabled, + &[disabled] { + @include button-color( + $btn-text-disabled-color, + $btn-text-disabled-color, + transparent, + transparent, + transparent, + transparent + ); + } + &#{$btn-prefix}-loading { + @include button-color( + $btn-text-loading-color, + $btn-text-loading-color, + transparent, + transparent, + transparent, + transparent + ); + } + } + + /* loading */ + /* ---------------------------------------- */ + &-loading { + pointer-events: none; + &:after { + font-family: $icon-font-family; + content: $icon-content-loading; + opacity: 1; + visibility: visible; + animation: loadingCircle 2s infinite linear; + } + } + + /* 幽灵按钮 */ + &-ghost { + box-shadow: none; + border-style: $btn-ghost-border-style; + &#{$btn-prefix}-dark { + @include button-color( $btn-ghost-dark-color, $btn-ghost-dark-color-hover, $btn-ghost-dark-bg-normal, $btn-ghost-dark-bg-hover, $btn-ghost-dark-border-color, $btn-ghost-dark-border-color-hover); + &.disabled, + &[disabled] { + @include button-color( $btn-ghost-dark-color-disabled, $btn-ghost-dark-color-disabled, $btn-ghost-dark-bg-disabled, $btn-ghost-dark-bg-disabled, $btn-ghost-dark-border-color-disabled, $btn-ghost-dark-border-color-disabled); + } + } + &#{$btn-prefix}-light { + @include button-color( $btn-ghost-light-color, $btn-ghost-light-color-hover, $btn-ghost-light-bg-normal, $btn-ghost-light-bg-hover, $btn-ghost-light-border-color, $btn-ghost-light-border-color-hover); + &.disabled, + &[disabled] { + @include button-color( $btn-ghost-light-color-disabled, $btn-ghost-light-color-disabled, $btn-ghost-light-bg-disabled, $btn-ghost-light-bg-disabled, $btn-ghost-light-border-color-disabled, $btn-ghost-light-border-color-disabled); + } + } + } + + /* 组合 */ + /* ---------------------------------------- */ + &-group { + position: relative; + display: inline-block; + vertical-align: middle; + + > #{$btn-prefix} { + position: relative; + float: left; + box-shadow: none; + + &:hover, + &:focus, + &:active, + &.active { + z-index: 1; + } + &.disabled, + &[disabled] { + z-index: 0; + } + } + + #{$btn-prefix}#{$btn-prefix} { + margin: 0 0 0 -1px; + } + + #{$btn-prefix}:not(:first-child):not(:last-child) { + border-radius: 0; + } + + > #{$btn-prefix}:first-child { + margin: 0; + } + + > #{$btn-prefix}:first-child:not(:last-child) { + border-bottom-right-radius: 0; + border-top-right-radius: 0; + } + + > #{$btn-prefix}:last-child:not(:first-child) { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + } + + > #{$btn-prefix}-primary:not(:first-child) { + border-left-color: transparentize($color-white, .8); + + &:hover { + border-left-color: transparent; + } + &.disabled, + &[disabled] { + border-left-color: $color-line1-1; + } + } + } +} + +@import './rtl.scss'; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/button/rtl.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/button/rtl.scss new file mode 100644 index 000000000..8fd003a01 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/button/rtl.scss @@ -0,0 +1,119 @@ +@mixin next-button-size-rtl( + $padding, + $icon-margin, + $icon-size, + $corner +) { + border-radius: $corner; + & > #{$btn-prefix}-icon#{$btn-icon-prefix}-first { + @include icon-size($icon-size, $icon-margin, 0); + } + & > #{$btn-prefix}-icon#{$btn-icon-prefix}-last { + @include icon-size($icon-size, 0, $icon-margin); + } + + &#{$btn-prefix}-loading { + padding-left: $padding; + padding-right: $padding + $icon-size + $icon-margin; + + &:after { + right: $padding; + top: 50%; + margin-right: 0; + margin-left: $icon-margin; + } + } +} + +/* 组合 */ +/* ---------------------------------------- */ +#{$btn-prefix}-group[dir="rtl"] { + > #{$btn-prefix} { + float: right; + } + + #{$btn-prefix}#{$btn-prefix} { + margin: 0 -1px 0 0; + } + + > #{$btn-prefix}:first-child:not(:last-child) { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + } + + > #{$btn-prefix}:last-child:not(:first-child) { + border-bottom-right-radius: 0; + border-top-right-radius: 0; + } + + > #{$btn-prefix}-primary:not(:first-child) { + border-right-color: transparentize($color-white, .8); + + &:hover { + border-right-color: transparent; + } + &.disabled, + &[disabled] { + border-right-color: $color-line1-1; + } + } +} + + +/* 尺寸维度 */ +/* ---------------------------------------- */ +#{$btn-prefix}.#{$css-prefix} { + &small[dir="rtl"] { + @include next-button-size-rtl( + $btn-size-s-padding, + $btn-size-s-icon-margin, + $btn-size-s-icon-size, + $btn-size-s-corner + ); + } + &medium[dir="rtl"] { + @include next-button-size-rtl( + $btn-size-m-padding, + $btn-size-m-icon-margin, + $btn-size-m-icon-size, + $btn-size-m-corner + ); + } + &large[dir="rtl"] { + @include next-button-size-rtl( + $btn-size-l-padding, + $btn-size-l-icon-margin, + $btn-size-l-icon-size, + $btn-size-l-corner + ); + } +} + +/* 文本按钮 */ +#{$btn-prefix}-text[dir="rtl"] { + &.#{$css-prefix}large { + @include next-button-size-rtl( + 0, + $btn-text-icon-l-margin, + $btn-size-l-icon-size, + 0 + ); + } + &.#{$css-prefix}medium { + @include next-button-size-rtl( + 0, + $btn-text-icon-m-margin, + $btn-size-m-icon-size, + 0 + ); + } + &.#{$css-prefix}small { + @include next-button-size-rtl( + 0, + $btn-text-icon-s-margin, + $btn-size-s-icon-size, + 0 + ); + } +} + diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/button/scss/mixin.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/button/scss/mixin.scss new file mode 100644 index 000000000..e41bee4f1 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/button/scss/mixin.scss @@ -0,0 +1,54 @@ +@mixin next-button-size( + $padding, + $height, + $font-size, + $border-width, + $corner, + $icon-margin, + $icon-size, + $icon-split-size +) { + border-radius: $corner; + + @include button-size($padding, $height, $font-size, $border-width); + + & > #{$btn-prefix}-icon#{$btn-icon-prefix}-first { + @include icon-size($icon-size, 0, $icon-margin); + } + & > #{$btn-prefix}-icon#{$btn-icon-prefix}-last { + @include icon-size($icon-size, $icon-margin, 0); + } + & > #{$btn-prefix}-icon#{$btn-icon-prefix}-alone { + @include icon-size($icon-size); + } + + &#{$btn-prefix}-loading { + padding-left: $padding + $icon-size + $icon-margin; + + &:after { + width: $icon-size; + height: $icon-size; + font-size: $icon-size; + line-height: $icon-size; + left: $padding; + top: 50%; + text-align: center; + margin-top: -$icon-size/2; + margin-right: $icon-margin; + } + > #{$btn-icon-prefix} { + display: none; + } + } +} + +@keyframes loadingCircle { + 0% { + transform-origin: 50% 50%; + transform: rotate(0deg); + } + 100% { + transform-origin: 50% 50%; + transform: rotate(360deg); + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/button/scss/normalize.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/button/scss/normalize.scss new file mode 100644 index 000000000..a4abdeee9 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/button/scss/normalize.scss @@ -0,0 +1,15 @@ +#{$btn-prefix} { + @include box-sizing; + + &::-moz-focus-inner { + border: 0; + padding: 0; + } + + &, + &:active, + &:focus, + &:hover { + outline: 0; + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/button/scss/variable.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/button/scss/variable.scss new file mode 100644 index 000000000..325260495 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/button/scss/variable.scss @@ -0,0 +1,522 @@ +//// +/// @module button: 按钮 +/// @tag Button +/// @category component +/// @family general +/// @varPrefix $btn- +/// @classPrefix {prefix}-btn +/// @order {"statement/normal":10,"statement/hover":11,"statement/disabled":12,"statement/loading":13,"size/bounding":10,"size/text":11,"size/icon":12,"size/normal":13} +//// + +$btn-prefix: '.' + $css-prefix + 'btn'; + +$btn-icon-prefix: '.' + $css-prefix + 'icon'; + +// Global +// ---------------------------------------- + +/// shadow +/// @namespace statement/normal +$btn-shadow: $shadow-zero !default; + +/// shadow +/// @namespace statement/hover +$btn-shadow-hover: $shadow-zero !default; + +// Small +// ---------------------------------------- + +/// height +/// @namespace size/bounding +$btn-size-s-height: $s-5 !default; + +/// padding +/// @namespace size/bounding +$btn-size-s-padding: $s-2 !default; + +/// border width +/// @namespace size/bounding +$btn-size-s-border-width: $line-1 !default; + +/// size +/// @namespace size/text +$btn-size-s-font: $font-size-caption !default; + +/// size +/// @namespace size/icon +$btn-size-s-icon-size: $icon-xs !default; + +/// margin +/// @namespace size/icon +$btn-size-s-icon-margin: $s-1 !default; + +/// split icon +/// @namespace size/icon +$btn-size-s-icon-split-size: $icon-xs !default; + +/// corner +/// @namespace size/normal +$btn-size-s-corner: $corner-1 !default; + +// Medium +// ---------------------------------------- + +/// height +/// @namespace size/bounding +$btn-size-m-height: $s-7 !default; + +/// padding +/// @namespace size/bounding +$btn-size-m-padding: $s-3 !default; + +/// border width +/// @namespace size/bounding +$btn-size-m-border-width: $line-1 !default; + +/// size +/// @namespace size/text +$btn-size-m-font: $font-size-body-1 !default; + +/// size +/// @namespace size/icon +$btn-size-m-icon-size: $icon-xs !default; + +/// margin +/// @namespace size/icon +$btn-size-m-icon-margin: $s-1 !default; + +/// split icon +/// @namespace size/icon +$btn-size-m-icon-split-size: $icon-xs !default; + +/// corner +/// @namespace size/normal +$btn-size-m-corner: $corner-1 !default; + +// Large +// ---------------------------------------- + +/// height +/// @namespace size/bounding +$btn-size-l-height: $s-10 !default; + +/// padding +/// @namespace size/bounding +$btn-size-l-padding: $s-4 !default; + +/// border width +/// @namespace size/bounding +$btn-size-l-border-width: $line-1 !default; + +/// size +/// @namespace size/text +$btn-size-l-font: $font-size-subhead !default; + +/// size +/// @namespace size/icon +$btn-size-l-icon-size: $icon-s !default; + +/// margin +/// @namespace size/icon +$btn-size-l-icon-margin: $s-1 !default; + +/// split icon +/// @namespace size/icon +$btn-size-l-icon-split-size: $icon-s !default; + +/// corner +/// @namespace size/normal +$btn-size-l-corner: $corner-1 !default; + +// Pure +// ---------------------------------------- + +/// text +/// @namespace statement/disabled +$btn-pure-color-disabled: $color-text1-1 !default; +/// background +/// @namespace statement/disabled +$btn-pure-bg-disabled: $color-fill1-1 !default; +/// border color +/// @namespace statement/disabled +$btn-pure-border-color-disabled: $color-line1-1 !default; + +/// text +/// @namespace statement/normal +$btn-pure-normal-color: $color-text1-4 !default; +/// text +/// @namespace statement/hover +$btn-pure-normal-color-hover: $color-text1-4 !default; +/// background +/// @namespace statement/normal +$btn-pure-normal-bg: $color-white !default; +/// background +/// @namespace statement/hover +$btn-pure-normal-bg-hover: $color-fill1-2 !default; +/// border color +/// @namespace statement/normal +$btn-pure-normal-border-color: $color-line1-3 !default; +/// border color +/// @namespace statement/hover +$btn-pure-normal-border-color-hover: $color-line1-4 !default; +/// border style +/// @namespace statement/normal +$btn-pure-normal-border-style: $line-solid !default; + +// Secondary +// ---------------------------------------- +/// text +/// @namespace statement/normal +$btn-pure-secondary-color: $color-brand1-6 !default; +/// text +/// @namespace statement/hover +$btn-pure-secondary-color-hover: $color-white !default; +/// background +/// @namespace statement/normal +$btn-pure-secondary-bg: $color-white !default; +/// background +/// @namespace statement/hover +$btn-pure-secondary-bg-hover: $color-brand1-9 !default; +/// border color +/// @namespace statement/normal +$btn-pure-secondary-border-color: $color-brand1-6 !default; +/// border color +/// @namespace statement/hover +$btn-pure-secondary-border-color-hover: $color-brand1-9 !default; +/// border style +/// @namespace statement/normal +$btn-pure-secondary-border-style: $line-solid !default; + +// Primary +// ---------------------------------------- +/// text +/// @namespace statement/normal +$btn-pure-primary-color: $color-white !default; +/// text +/// @namespace statement/hover +$btn-pure-primary-color-hover: $color-white !default; +/// background +/// @namespace statement/normal +$btn-pure-primary-bg: $color-brand1-6 !default; +/// background +/// @namespace statement/hover +$btn-pure-primary-bg-hover: $color-brand1-9 !default; +/// border color +/// @namespace statement/normal +$btn-pure-primary-border-color: $color-transparent !default; +/// border color +/// @namespace statement/hover +$btn-pure-primary-border-color-hover: $color-transparent !default; +/// border style +/// @namespace statement/normal +$btn-pure-primary-border-style: $line-solid !default; + +// Ghost Dark +// ---------------------------------------- + +/// border style +/// @namespace statement/normal +$btn-ghost-border-style: $line-solid !default; + +/// text +/// @namespace statement/normal +$btn-ghost-dark-color: $color-white !default; + +/// border color +/// @namespace statement/normal +$btn-ghost-dark-border-color: $color-white !default; + +/// text +/// @namespace statement/hover +$btn-ghost-dark-color-hover: $color-white !default; + +/// background +/// @namespace statement/normal +$btn-ghost-dark-bg: $color-transparent !default; + +/// bg opacity +/// @namespace statement/normal +/// @type alpha +$btn-ghost-dark-bg-opacity: 0 !default; +$btn-ghost-dark-bg-normal: rgba($btn-ghost-dark-bg, $btn-ghost-dark-bg-opacity); + +/// background +/// @namespace statement/hover +$btn-ghost-dark-bg-hover-rgb: $color-white !default; + +/// bg opacity +/// @namespace statement/hover +/// @type alpha +$btn-ghost-dark-bg-hover-opacity: .8 !default; +$btn-ghost-dark-bg-hover: rgba($btn-ghost-dark-bg-hover-rgb, $btn-ghost-dark-bg-hover-opacity); + +/// border +/// @namespace statement/hover +$btn-ghost-dark-border-color-hover: $color-white !default; + +/// color +/// @namespace statement/disabled +$btn-ghost-dark-color-disabled-rgb: $color-white !default; + +/// color opacity +/// @namespace statement/disabled +/// @type alpha +$btn-ghost-dark-color-disabled-opacity: .4 !default; +$btn-ghost-dark-color-disabled: rgba($btn-ghost-dark-color-disabled-rgb, $btn-ghost-dark-color-disabled-opacity); + +/// background +/// @namespace statement/disabled +$btn-ghost-dark-bg-disabled: $color-transparent !default; + +/// border +/// @namespace statement/disabled +$btn-ghost-dark-border-color-disabled-rgb: $color-white !default; + +/// border opacity +/// @namespace statement/disabled +/// @type alpha +$btn-ghost-dark-border-color-disabled-opacity: .4 !default; +$btn-ghost-dark-border-color-disabled: rgba($btn-ghost-dark-border-color-disabled-rgb, $btn-ghost-dark-border-color-disabled-opacity); + +// Ghost Light +// ---------------------------------------- + +/// text +/// @namespace statement/normal +$btn-ghost-light-color: $color-text1-4 !default; + +/// border +/// @namespace statement/normal +$btn-ghost-light-border-color: $color-text1-4 !default; + +/// background +/// @namespace statement/normal +$btn-ghost-light-bg: $color-transparent !default; + +/// bg opacity +/// @namespace statement/normal +/// @type alpha +$btn-ghost-light-bg-opacity: 0 !default; +$btn-ghost-light-bg-normal: rgba($btn-ghost-light-bg, $btn-ghost-light-bg-opacity); + +/// text +/// @namespace statement/hover +$btn-ghost-light-color-hover: $color-text1-2 !default; + +/// border +/// @namespace statement/hover +$btn-ghost-light-border-color-hover: $color-text1-4 !default; + +/// background +/// @namespace statement/hover +$btn-ghost-light-bg-hover-rgb: $color-black !default; + +/// bg opacity +/// @namespace statement/hover +/// @type alpha +$btn-ghost-light-bg-hover-opacity: .92 !default; +$btn-ghost-light-bg-hover: rgba($btn-ghost-light-bg-hover-rgb, $btn-ghost-light-bg-hover-opacity); + +/// text +/// @namespace statement/disabled +$btn-ghost-light-color-disabled-rgb: $color-black !default; + +/// text opacity +/// @namespace statement/disabled +/// @type alpha +$btn-ghost-light-color-disabled-opacity: .1 !default; +$btn-ghost-light-color-disabled: rgba($btn-ghost-light-color-disabled-rgb, $btn-ghost-light-color-disabled-opacity); + +/// background +/// @namespace statement/disabled +$btn-ghost-light-bg-disabled: $color-transparent !default; + +/// border +/// @namespace statement/disabled +$btn-ghost-light-border-color-disabled-rgb: $color-black !default; + +/// border opacity +/// @namespace statement/disabled +/// @type alpha +$btn-ghost-light-border-color-disabled-opacity: .1 !default; +$btn-ghost-light-border-color-disabled: rgba($btn-ghost-light-border-color-disabled-rgb, $btn-ghost-light-border-color-disabled-opacity); + +// Warning Primary +// ---------------------------------------- + +/// border style +/// @namespace statement/normal +$btn-warning-border-style: $line-solid !default; + +/// text +/// @namespace statement/normal +$btn-warning-primary-color: $color-white !default; + +/// text +/// @namespace statement/hover +$btn-warning-primary-color-hover: $color-white !default; + +/// border color +/// @namespace statement/normal +$btn-warning-primary-border-color: $color-error-3 !default; + +/// border color +/// @namespace statement/hover +$btn-warning-primary-border-color-hover: $color-error-4 !default; + +/// background +/// @namespace statement/normal +$btn-warning-primary-bg: $color-error-3 !default; + +/// background +/// @namespace statement/hover +$btn-warning-primary-bg-hover: $color-error-4 !default; + +/// text +/// @namespace statement/disabled +$btn-warning-primary-color-disabled: $color-text1-1 !default; + +/// border +/// @namespace statement/disabled +$btn-warning-primary-border-color-disabled: $color-line1-2 !default; + +/// background +/// @namespace statement/disabled +$btn-warning-primary-bg-disabled: $color-fill1-1 !default; + +// Warning Normal +// ---------------------------------------- + +/// text +/// @namespace statement/normal +$btn-warning-normal-color: $color-error-3 !default; + +/// text +/// @namespace statement/hover +$btn-warning-normal-color-hover: $color-white !default; + +/// border +/// @namespace statement/normal +$btn-warning-normal-border-color: $color-error-3 !default; + +/// border +/// @namespace statement/hover +$btn-warning-normal-border-color-hover: $color-error-4 !default; + +/// background +/// @namespace statement/normal +$btn-warning-normal-bg: $color-white !default; + +/// background +/// @namespace statement/hover +$btn-warning-normal-bg-hover: $color-error-4 !default; + +/// text +/// @namespace statement/disabled +$btn-warning-normal-color-disabled: $color-text1-1 !default; + +/// border +/// @namespace statement/disabled +$btn-warning-normal-border-color-disabled: $color-line1-1 !default; + +/// background +/// @namespace statement/disabled +$btn-warning-normal-bg-disabled: $color-fill1-1 !default; + +// Text primary & disabled & loading +// ---------------------------------------- + +/// text +/// @namespace statement/normal +$btn-text-primary-color: $color-link-1 !default; + +/// text +/// @namespace statement/hover +$btn-text-primary-color-hover: $color-brand1-9 !default; + +/// text +/// @namespace statement/disabled +$btn-text-disabled-color: $color-text1-1 !default; + +/// text +/// @namespace statement/loading +$btn-text-loading-color: $color-text1-4 !default; + +// Text secondary +// ---------------------------------------- + +/// text +/// @namespace statement/normal +$btn-text-secondary-color: $color-text1-3 !default; + +/// text +/// @namespace statement/hover +$btn-text-secondary-color-hover: $color-brand1-6 !default; + +// Text normal +// ---------------------------------------- + +/// text +/// @namespace statement/normal +$btn-text-normal-color: $color-text1-4 !default; + +/// text +/// @namespace statement/hover +$btn-text-normal-color-hover: $color-brand1-6 !default; + +// Text small +// ---------------------------------------- + +/// height +/// @namespace size/bounding +$btn-text-size-s-height: $s-4 !default; + +/// text +/// @namespace size/text +$btn-text-size-s-font: $font-size-caption !default; + +/// icon +/// @namespace size/icon +$btn-text-icon-size-s: $icon-s !default; + +/// margin +/// @namespace size/icon +$btn-text-icon-s-margin: $s-1 !default; + +// Text medium +// ---------------------------------------- + +/// height +/// @namespace size/bounding +$btn-text-size-m-height: $s-5 !default; + +/// text +/// @namespace size/text +$btn-text-size-m-font: $font-size-body-1 !default; + +/// icon +/// @namespace size/icon +$btn-text-icon-size-m: $icon-m !default; + +/// margin +/// @namespace size/icon +$btn-text-icon-m-margin: $s-1 !default; + +// Text large +// ---------------------------------------- + +/// height +/// @namespace size/bounding +$btn-text-size-l-height: $s-6 !default; + +/// text +/// @namespace size/text +$btn-text-size-l-font: $font-size-body-2 !default; + +/// icon +/// @namespace size/icon +$btn-text-icon-size-l: $icon-l !default; + +/// margin +/// @namespace size/icon +$btn-text-icon-l-margin: $s-1 !default; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/button/style.js b/packages/material-parser/test/fixtures/fusion-next-component/src/button/style.js new file mode 100644 index 000000000..65cfc7e39 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/button/style.js @@ -0,0 +1,2 @@ +import '../icon/style.js'; +import './main.scss'; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/button/view/button.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/button/view/button.jsx new file mode 100644 index 000000000..37594c25b --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/button/view/button.jsx @@ -0,0 +1,208 @@ +import React, { Component, Children, isValidElement } from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; +import ConfigProvider from '../../config-provider'; +import { obj, log } from '../../util'; + +function mapIconSize(size) { + return { + large: 'small', + medium: 'xs', + small: 'xs', + }[size]; +} + +/** Button */ +export default class Button extends Component { + static propTypes = { + ...ConfigProvider.propTypes, + prefix: PropTypes.string, + rtl: PropTypes.bool, + /** + * 按钮的类型 + */ + type: PropTypes.oneOf(['primary', 'secondary', 'normal']), + /** + * 按钮的尺寸 + */ + size: PropTypes.oneOf(['small', 'medium', 'large']), + /** + * 按钮中 Icon 的尺寸,用于替代 Icon 的默认大小 + */ + iconSize: PropTypes.oneOf([ + 'xxs', + 'xs', + 'small', + 'medium', + 'large', + 'xl', + 'xxl', + 'xxxl', + ]), + /** + * 当 component = 'button' 时,设置 button 标签的 type 值 + */ + htmlType: PropTypes.oneOf(['submit', 'reset', 'button']), + /** + * 设置标签类型 + */ + component: PropTypes.oneOf(['button', 'a', 'div', 'span']), + /** + * 设置按钮的载入状态 + */ + loading: PropTypes.bool, + /** + * 是否为幽灵按钮 + */ + ghost: PropTypes.oneOf([true, false, 'light', 'dark']), + /** + * 是否为文本按钮 + */ + text: PropTypes.bool, + /** + * 是否为警告按钮 + */ + warning: PropTypes.bool, + /** + * 是否禁用 + */ + disabled: PropTypes.bool, + /** + * 点击按钮的回调 + * @param {Object} e Event Object + */ + onClick: PropTypes.func, + className: PropTypes.string, + onMouseUp: PropTypes.func, + children: PropTypes.node, + }; + + static defaultProps = { + prefix: 'next-', + type: 'normal', + size: 'medium', + htmlType: 'button', + component: 'button', + loading: false, + ghost: false, + text: false, + warning: false, + disabled: false, + onClick: () => {}, + }; + + onMouseUp = e => { + this.button.blur(); + + if (this.props.onMouseUp) { + this.props.onMouseUp(e); + } + }; + + buttonRefHandler = button => { + this.button = button; + }; + + render() { + const { + prefix, + className, + type, + size, + htmlType, + loading, + text, + warning, + ghost, + component, + iconSize, + disabled, + onClick, + children, + rtl, + ...others + } = this.props; + const ghostType = + ['light', 'dark'].indexOf(ghost) >= 0 ? ghost : 'dark'; + + const btnCls = classNames({ + [`${prefix}btn`]: true, + [`${prefix}${size}`]: size, + [`${prefix}btn-${type}`]: type && !ghost, + [`${prefix}btn-text`]: text, + [`${prefix}btn-warning`]: warning, + [`${prefix}btn-loading`]: loading, + [`${prefix}btn-ghost`]: ghost, + [`${prefix}btn-${ghostType}`]: ghost, + [className]: className, + }); + + const count = Children.count(children); + const clonedChildren = Children.map(children, (child, index) => { + if ( + child && + typeof child.type === 'function' && + child.type._typeMark === 'icon' + ) { + const iconCls = classNames({ + [`${prefix}btn-icon`]: !iconSize, // 如果用户没有传 iconSize,则使用该样式标记 icon 为 button 预设尺寸 + [`${prefix}icon-first`]: count > 1 && index === 0, + [`${prefix}icon-last`]: count > 1 && index === count - 1, + [`${prefix}icon-alone`]: count === 1, + [child.props.className]: !!child.props.className, + }); + + if ('size' in child.props) { + log.warning( + `The size of Icon will not take effect, when Icon is the [direct child element] of Button(), use instead of.` + ); + } + return React.cloneElement(child, { + className: iconCls, + size: iconSize || mapIconSize(size), + }); + } + + if (!isValidElement(child)) { + return {child}; + } + + return child; + }); + + const TagName = component; + const tagAttrs = { + ...obj.pickOthers(Object.keys(Button.propTypes), others), + type: htmlType, + disabled: disabled, + onClick: onClick, + className: btnCls, + }; + + if (TagName !== 'button') { + delete tagAttrs.type; + + if (tagAttrs.disabled) { + delete tagAttrs.onClick; // a 标签的 onClick 浏览器默认不会禁用 + tagAttrs.href && delete tagAttrs.href; // a 标签在禁用状态下无跳转 + } + } + + return ( + + {clonedChildren} + + ); + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/button/view/group.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/button/view/group.jsx new file mode 100644 index 000000000..842cd8aa8 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/button/view/group.jsx @@ -0,0 +1,62 @@ +import React, { Component, Children } from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; +import ConfigProvider from '../../config-provider'; + +/** + * Button.Group + */ +class ButtonGroup extends Component { + static propTypes = { + ...ConfigProvider.propTypes, + rtl: PropTypes.bool, + prefix: PropTypes.string, + /** + * 统一设置 Button 组件的按钮大小 + */ + size: PropTypes.string, + className: PropTypes.string, + children: PropTypes.node, + }; + + static defaultProps = { + prefix: 'next-', + size: 'medium', + }; + + render() { + const { + prefix, + className, + size, + children, + rtl, + ...others + } = this.props; + + const groupCls = classNames({ + [`${prefix}btn-group`]: true, + [className]: className, + }); + + const cloneChildren = Children.map(children, child => { + if (child) { + return React.cloneElement(child, { + size: size, + }); + } + }); + + if (rtl) { + others.dir = 'rtl'; + } + + return ( +
    + {cloneChildren} +
    + ); + } +} + +export default ConfigProvider.config(ButtonGroup); diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/.eslintrc b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/.eslintrc new file mode 100644 index 000000000..d5855dc78 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/.eslintrc @@ -0,0 +1,5 @@ +{ + "rules": { + "react/prop-types": 1 + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/calendar.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/calendar.jsx new file mode 100644 index 000000000..5f3923042 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/calendar.jsx @@ -0,0 +1,354 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import moment from 'moment'; +import classnames from 'classnames'; +import ConfigProvider from '../config-provider'; +import nextLocale from '../locale/zh-cn'; +import { func, obj } from '../util'; +import CardHeader from './head/card-header'; +import DatePanelHeader from './head/date-panel-header'; +import MonthPanelHeader from './head/month-panel-header'; +import YearPanelHeader from './head/year-panel-header'; +import DateTable from './table/date-table'; +import MonthTable from './table/month-table'; +import YearTable from './table/year-table'; +import { + checkMomentObj, + formatDateValue, + getVisibleMonth, + isSameYearMonth, + CALENDAR_MODES, + CALENDAR_MODE_DATE, + CALENDAR_MODE_MONTH, + CALENDAR_MODE_YEAR, + getLocaleData, +} from './utils'; + +/** Calendar */ +class Calendar extends Component { + static propTypes = { + ...ConfigProvider.propTypes, + prefix: PropTypes.string, + rtl: PropTypes.bool, + /** + * 默认选中的日期(moment 对象) + */ + defaultValue: checkMomentObj, + /** + * 选中的日期值 (moment 对象) + */ + value: checkMomentObj, + /** + * 面板模式 + */ + mode: PropTypes.oneOf(CALENDAR_MODES), // 生成 API 文档需要手动改回 ['date', 'month', 'year'] + // 面板可变化的模式列表,仅初始化时接收一次 + modes: PropTypes.array, + // 禁用更改面板模式,采用 dropdown 的方式切换显示日期 (暂不正式对外透出) + disableChangeMode: PropTypes.bool, + // 日期值的格式(用于日期title显示的格式) + format: PropTypes.string, + /** + * 是否展示非本月的日期 + */ + showOtherMonth: PropTypes.bool, + /** + * 默认展示的月份 + */ + defaultVisibleMonth: PropTypes.func, + /** + * 展现形态 + */ + shape: PropTypes.oneOf(['card', 'fullscreen', 'panel']), + /** + * 选择日期单元格时的回调 + * @param {Object} value 对应的日期值 (moment 对象) + */ + onSelect: PropTypes.func, + /** + * 面板模式变化时的回调 + * @param {String} mode 对应面板模式 date month year + */ + onModeChange: PropTypes.func, + /** + * 展现的月份变化时的回调 + * @param {Object} value 显示的月份 (moment 对象) + * @param {String} reason 触发月份改变原因 + */ + onVisibleMonthChange: PropTypes.func, + /** + * 自定义样式类 + */ + className: PropTypes.string, + /** + * 自定义日期渲染函数 + * @param {Object} value 日期值(moment对象) + * @returns {ReactNode} + */ + dateCellRender: PropTypes.func, + /** + * 自定义月份渲染函数 + * @param {Object} calendarDate 对应 Calendar 返回的自定义日期对象 + * @returns {ReactNode} + */ + monthCellRender: PropTypes.func, + yearCellRender: PropTypes.func, // 兼容 0.x yearCellRender + /** + * 年份范围,[START_YEAR, END_YEAR] (只在shape 为 ‘card’, 'fullscreen' 下生效) + */ + yearRange: PropTypes.arrayOf(PropTypes.number), + /** + * 不可选择的日期 + * @param {Object} calendarDate 对应 Calendar 返回的自定义日期对象 + * @param {String} view 当前视图类型,year: 年, month: 月, date: 日 + * @returns {Boolean} + */ + disabledDate: PropTypes.func, + /** + * 国际化配置 + */ + locale: PropTypes.object, + }; + + static defaultProps = { + prefix: 'next-', + rtl: false, + shape: 'fullscreen', + modes: CALENDAR_MODES, + disableChangeMode: false, + format: 'YYYY-MM-DD', + onSelect: func.noop, + onVisibleMonthChange: func.noop, + onModeChange: func.noop, + dateCellRender: value => value.date(), + locale: nextLocale.Calendar, + showOtherMonth: true, + }; + + constructor(props, context) { + super(props, context); + const value = formatDateValue(props.value || props.defaultValue); + const visibleMonth = getVisibleMonth(props.defaultVisibleMonth, value); + + this.MODES = props.modes; + this.today = moment(); + this.state = { + value, + mode: props.mode || this.MODES[0], + visibleMonth, + }; + } + + componentWillReceiveProps(nextProps) { + if ('value' in nextProps) { + const value = formatDateValue(nextProps.value); + this.setState({ + value, + }); + + if (value) { + this.setState({ + visibleMonth: value, + }); + } + } + + if (nextProps.mode && this.MODES.indexOf(nextProps.mode) > -1) { + this.setState({ + mode: nextProps.mode, + }); + } + } + + onSelectCell = (date, nextMode) => { + const { shape } = this.props; + + this.changeVisibleMonth(date, 'cellClick'); + + // 当用户所在的面板为初始化面板时,则选择动作为触发 onSelect 回调 + if (this.state.mode === this.MODES[0]) { + this.props.onSelect(date); + } + + if (shape === 'panel') { + this.changeMode(nextMode); + } + }; + + changeMode = nextMode => { + if ( + nextMode && + this.MODES.indexOf(nextMode) > -1 && + nextMode !== this.state.mode + ) { + this.setState({ mode: nextMode }); + this.props.onModeChange(nextMode); + } + }; + + changeVisibleMonth = (date, reason) => { + if (!isSameYearMonth(date, this.state.visibleMonth)) { + this.setState({ visibleMonth: date }); + this.props.onVisibleMonthChange(date, reason); + } + }; + + /** + * 根据日期偏移量设置当前展示的月份 + * @param {Number} offset 日期偏移的数量 + * @param {String} type 日期偏移的类型 days, months, years + */ + changeVisibleMonthByOffset(offset, type) { + const cloneValue = this.state.visibleMonth.clone(); + cloneValue.add(offset, type); + this.changeVisibleMonth(cloneValue, 'buttonClick'); + } + + goPrevDecade = () => { + this.changeVisibleMonthByOffset(-10, 'years'); + }; + + goNextDecade = () => { + this.changeVisibleMonthByOffset(10, 'years'); + }; + + goPrevYear = () => { + this.changeVisibleMonthByOffset(-1, 'years'); + }; + + goNextYear = () => { + this.changeVisibleMonthByOffset(1, 'years'); + }; + + goPrevMonth = () => { + this.changeVisibleMonthByOffset(-1, 'months'); + }; + + goNextMonth = () => { + this.changeVisibleMonthByOffset(1, 'months'); + }; + + render() { + const { + prefix, + rtl, + className, + shape, + showOtherMonth, + format, + locale, + dateCellRender, + monthCellRender, + yearCellRender, + disabledDate, + yearRange, + disableChangeMode, + ...others + } = this.props; + const state = this.state; + + const classNames = classnames( + { + [`${prefix}calendar`]: true, + [`${prefix}calendar-${shape}`]: shape, + }, + className + ); + + if (rtl) { + others.dir = 'rtl'; + } + + const visibleMonth = state.visibleMonth; + + // reset moment locale + if (locale.momentLocale) { + state.value && state.value.locale(locale.momentLocale); + visibleMonth.locale(locale.momentLocale); + } + + const localeData = getLocaleData( + locale.format || {}, + visibleMonth.localeData() + ); + + const headerProps = { + prefix, + value: state.value, + mode: state.mode, + disableChangeMode, + yearRange, + locale, + rtl, + visibleMonth, + momentLocale: localeData, + changeMode: this.changeMode, + changeVisibleMonth: this.changeVisibleMonth, + goNextDecade: this.goNextDecade, + goNextYear: this.goNextYear, + goNextMonth: this.goNextMonth, + goPrevDecade: this.goPrevDecade, + goPrevYear: this.goPrevYear, + goPrevMonth: this.goPrevMonth, + }; + + const tableProps = { + prefix, + visibleMonth, + showOtherMonth, + value: state.value, + mode: state.mode, + locale, + dateCellRender, + monthCellRender, + yearCellRender, + disabledDate, + momentLocale: localeData, + today: this.today, + goPrevDecade: this.goPrevDecade, + goNextDecade: this.goNextDecade, + }; + + const tables = { + [CALENDAR_MODE_DATE]: ( + + ), + [CALENDAR_MODE_MONTH]: ( + + ), + [CALENDAR_MODE_YEAR]: ( + + ), + }; + + const panelHeaders = { + [CALENDAR_MODE_DATE]: , + [CALENDAR_MODE_MONTH]: , + [CALENDAR_MODE_YEAR]: , + }; + + return ( +
    + {shape === 'panel' ? ( + panelHeaders[state.mode] + ) : ( + + )} + {tables[state.mode]} +
    + ); + } +} + +export default Calendar; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/head/card-header.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/head/card-header.jsx new file mode 100644 index 000000000..2562b5895 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/head/card-header.jsx @@ -0,0 +1,118 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import Select from '../../select'; +import Radio from '../../radio'; + +class CardHeader extends React.PureComponent { + static propTypes = { + yearRange: PropTypes.arrayOf(PropTypes.number), + yearRangeOffset: PropTypes.number, + locale: PropTypes.object, + }; + + static defaultProps = { + yearRangeOffset: 10, + }; + + selectContainerHandler = target => { + return target.parentNode; + }; + + getYearSelect(year) { + const { prefix, yearRangeOffset, yearRange = [], locale } = this.props; + + let [startYear, endYear] = yearRange; + if (!startYear || !endYear) { + startYear = year - yearRangeOffset; + endYear = year + yearRangeOffset; + } + + const options = []; + for (let i = startYear; i <= endYear; i++) { + options.push( + + {i} + + ); + } + + return ( + + ); + } + + getMonthSelect(month) { + const { prefix, momentLocale, locale } = this.props; + const localeMonths = momentLocale.monthsShort(); + const options = []; + for (let i = 0; i < 12; i++) { + options.push( + + {localeMonths[i]} + + ); + } + return ( + + ); + } + + onYearChange = year => { + const { visibleMonth, changeVisibleMonth } = this.props; + changeVisibleMonth(visibleMonth.clone().year(year), 'yearSelect'); + }; + + changeVisibleMonth = month => { + const { visibleMonth, changeVisibleMonth } = this.props; + changeVisibleMonth(visibleMonth.clone().month(month), 'monthSelect'); + }; + + onModePanelChange = mode => { + this.props.changeMode(mode); + }; + + render() { + const { prefix, mode, locale, visibleMonth } = this.props; + + const yearSelect = this.getYearSelect(visibleMonth.year()); + const monthSelect = + mode === 'month' ? null : this.getMonthSelect(visibleMonth.month()); + const panelSelect = ( + + {locale.month} + {locale.year} + + ); + + return ( +
    + {yearSelect} + {monthSelect} + {panelSelect} +
    + ); + } +} + +export default CardHeader; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/head/date-panel-header.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/head/date-panel-header.jsx new file mode 100644 index 000000000..0b122fdde --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/head/date-panel-header.jsx @@ -0,0 +1,173 @@ +/* istanbul ignore file */ +import React from 'react'; +import Icon from '../../icon'; +import Dropdown from '../../dropdown'; +import SelectMenu from './menu'; +import { getMonths, getYears } from '../utils'; + +/* eslint-disable */ +class DatePanelHeader extends React.PureComponent { + static defaultProps = { + yearRangeOffset: 10, + }; + + selectContainerHandler = target => { + return target.parentNode; + }; + + onYearChange = year => { + const { visibleMonth, changeVisibleMonth } = this.props; + changeVisibleMonth(visibleMonth.clone().year(year), 'yearSelect'); + }; + + changeVisibleMonth = month => { + const { visibleMonth, changeVisibleMonth } = this.props; + changeVisibleMonth(visibleMonth.clone().month(month), 'monthSelect'); + }; + + render() { + const { + prefix, + visibleMonth, + momentLocale, + locale, + changeMode, + goNextMonth, + goNextYear, + goPrevMonth, + goPrevYear, + disableChangeMode, + yearRangeOffset, + yearRange = [], + } = this.props; + + const localedMonths = momentLocale.months(); + const monthLabel = localedMonths[visibleMonth.month()]; + const yearLabel = visibleMonth.year(); + const btnCls = `${prefix}calendar-btn`; + + let monthButton = ( + + ); + + let yearButton = ( + + ); + + if (disableChangeMode) { + const months = getMonths(momentLocale); + const years = getYears( + yearRange, + yearRangeOffset, + visibleMonth.year() + ); + + monthButton = ( + + {monthLabel} + + + } + triggerType="click" + > + this.changeVisibleMonth(value)} + /> + + ); + + yearButton = ( + + {yearLabel} + + + } + triggerType="click" + > + + + ); + } + + return ( +
    + + +
    + {monthButton} + {yearButton} +
    + + +
    + ); + } +} + +export default DatePanelHeader; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/head/menu.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/head/menu.jsx new file mode 100644 index 000000000..dec7f7a09 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/head/menu.jsx @@ -0,0 +1,70 @@ +/* istanbul ignore file */ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { findDOMNode } from 'react-dom'; +import Menu from '../../menu'; + +export default class SelectMenu extends Component { + static isNextMenu = true; + static propTypes = { + dataSource: PropTypes.arrayOf(PropTypes.object), + value: PropTypes.number, + prefix: PropTypes.string, + onChange: PropTypes.func, + children: PropTypes.node, + }; + + componentDidMount() { + this.scrollToSelectedItem(); + } + + scrollToSelectedItem() { + const { prefix, dataSource, value } = this.props; + + const selectedIndex = dataSource.findIndex( + item => item.value === value + ); + + if (selectedIndex === -1) { + return; + } + + const itemSelector = `.${prefix}menu-item`; + const menu = findDOMNode(this.refs.menu); + const targetItem = menu.querySelectorAll(itemSelector)[selectedIndex]; + if (targetItem) { + menu.scrollTop = + targetItem.offsetTop - + Math.floor( + (menu.clientHeight / targetItem.clientHeight - 1) / 2 + ) * + targetItem.clientHeight; + } + } + + render() { + const { + prefix, + dataSource, + onChange, + value, + className, + ...others + } = this.props; + return ( + onChange(Number(selectKeys[0]))} + role="listbox" + className={`${prefix}calendar-panel-menu ${className}`} + > + {dataSource.map(({ label, value }) => ( + {label} + ))} + + ); + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/head/month-panel-header.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/head/month-panel-header.jsx new file mode 100644 index 000000000..7d534c10c --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/head/month-panel-header.jsx @@ -0,0 +1,50 @@ +import React from 'react'; +import Icon from '../../icon'; + +class MonthPanelHeader extends React.PureComponent { + render() { + const { + prefix, + visibleMonth, + locale, + changeMode, + goPrevYear, + goNextYear, + } = this.props; + const yearLabel = visibleMonth.year(); + const btnCls = `${prefix}calendar-btn`; + + return ( +
    + +
    + +
    + +
    + ); + } +} + +export default MonthPanelHeader; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/head/range-panel-header.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/head/range-panel-header.jsx new file mode 100644 index 000000000..5077d7d74 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/head/range-panel-header.jsx @@ -0,0 +1,253 @@ +/* istanbul ignore file */ +import React from 'react'; +import Icon from '../../icon'; +import Dropdown from '../../dropdown'; +import SelectMenu from './menu'; +import { getMonths, getYears } from '../utils'; + +/* eslint-disable */ +class RangePanelHeader extends React.PureComponent { + static defaultProps = { + yearRangeOffset: 10, + }; + + selectContainerHandler = target => { + return target.parentNode; + }; + + onYearChange = (visibleMonth, year) => { + const { changeVisibleMonth } = this.props; + changeVisibleMonth(visibleMonth.clone().year(year), 'yearSelect'); + }; + + changeVisibleMonth = (visibleMonth, month) => { + const { changeVisibleMonth } = this.props; + changeVisibleMonth(visibleMonth.clone().month(month), 'monthSelect'); + }; + + render() { + const { + prefix, + startVisibleMonth, + endVisibleMonth, + yearRange = [], + yearRangeOffset, + momentLocale, + locale, + changeMode, + goNextMonth, + goNextYear, + goPrevMonth, + goPrevYear, + disableChangeMode, + } = this.props; + + const localedMonths = momentLocale.months(); + const startMonthLabel = localedMonths[startVisibleMonth.month()]; + const endMonthLabel = localedMonths[endVisibleMonth.month()]; + const startYearLabel = startVisibleMonth.year(); + const endYearLabel = endVisibleMonth.year(); + const btnCls = `${prefix}calendar-btn`; + + const months = getMonths(momentLocale); + const startYears = getYears( + yearRange, + yearRangeOffset, + startVisibleMonth.year() + ); + const endYears = getYears( + yearRange, + yearRangeOffset, + endVisibleMonth.year() + ); + + return ( +
    + + +
    + {disableChangeMode ? ( + + {startMonthLabel} + + + } + triggerType="click" + > + + this.changeVisibleMonth( + startVisibleMonth, + value + ) + } + /> + + ) : ( + + )} + {disableChangeMode ? ( + + {startYearLabel} + + + } + triggerType="click" + > + + this.onYearChange(startVisibleMonth, v) + } + /> + + ) : ( + + )} +
    +
    + {disableChangeMode ? ( + + {endMonthLabel} + + + } + triggerType="click" + > + + this.changeVisibleMonth( + endVisibleMonth, + value + ) + } + /> + + ) : ( + + )} + {disableChangeMode ? ( + + {endYearLabel} + + + } + triggerType="click" + > + + this.onYearChange(endVisibleMonth, v) + } + /> + + ) : ( + + )} +
    + + +
    + ); + } +} + +export default RangePanelHeader; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/head/year-panel-header.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/head/year-panel-header.jsx new file mode 100644 index 000000000..7ece4016b --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/head/year-panel-header.jsx @@ -0,0 +1,55 @@ +import React from 'react'; +import Icon from '../../icon'; + +class YearPanelHeader extends React.PureComponent { + getDecadeLabel = date => { + const year = date.year(); + const start = parseInt(year / 10, 10) * 10; + const end = start + 9; + return `${start}-${end}`; + }; + + render() { + const { + prefix, + visibleMonth, + locale, + goPrevDecade, + goNextDecade, + } = this.props; + const decadeLable = this.getDecadeLabel(visibleMonth); + const btnCls = `${prefix}calendar-btn`; + + return ( +
    + +
    + +
    + +
    + ); + } +} + +export default YearPanelHeader; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/index.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/index.jsx new file mode 100644 index 000000000..1e55b5084 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/index.jsx @@ -0,0 +1,82 @@ +import ConfigProvider from '../config-provider'; +import { preFormatDateValue } from './utils'; +import Calendar from './calendar'; +import RangeCalendar from './range-calendar'; + +/* istanbul ignore next */ +const transform = (props, deprecated) => { + const { + type, + onChange, + base, + disabledMonth, + disabledYear, + ...others + } = props; + const newProps = others; + + if ('type' in props) { + deprecated('type', 'shape', 'Calendar'); + + newProps.shape = type; + + if ('shape' in props) { + newProps.shape = props.shape; + } + } + + if ('base' in props) { + deprecated('base', 'defaultVisibleMonth', 'Calendar'); + + let newDefaultVisibleMonth = () => { + preFormatDateValue(base, 'YYYY-MM-DD'); + }; + + if ('defaultVisibleMonth' in props) { + newDefaultVisibleMonth = props.defaultVisibleMonth; + } + + newProps.defaultVisibleMonth = newDefaultVisibleMonth; + } + + if ('onChange' in props && typeof onChange === 'function') { + deprecated('onChange', 'onSelect', 'Calendar'); + + const newOnSelect = date => { + onChange({ mode: others.mode, value: date }); + + if ('onSelect' in props) { + props.onSelect(date); + } + }; + + newProps.onSelect = newOnSelect; + } + + if ('disabledMonth' in props && typeof disabledMonth === 'function') { + deprecated('disabledMonth', 'disabledDate', 'Calendar'); + } + + if ('disabledYear' in props && typeof disabledYear === 'function') { + deprecated('disabledYear', 'disabledDate', 'Calendar'); + } + + if ('yearCellRender' in props && typeof yearCellRender === 'function') { + deprecated( + 'yearCellRender', + 'monthCellRender/dateCellRender', + 'Calendar' + ); + } + + if ('language' in props) { + deprecated('language', 'moment.locale', 'Calendar'); + } + + return newProps; +}; + +Calendar.RangeCalendar = RangeCalendar; +export default ConfigProvider.config(Calendar, { + transform, +}); diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/main.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/main.scss new file mode 100644 index 000000000..688ed83dd --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/main.scss @@ -0,0 +1,38 @@ +@import '../core/index-noreset'; + +@import "scss/variable"; +@import "scss/normalize"; +@import "scss/mixin"; +@import "scss/animation"; + +@import "scss/header"; +@import "scss/table"; +@import "./rtl.scss"; + +#{$calendar-prefix} { + &-table { + width: 100%; + table-layout: fixed; + } + + /* range calendar */ + /* --------------- */ + &-range { + #{$calendar-prefix}-body { + &-left, &-right { + float: left; + width: 50%; + } + + &-left { + padding-right: $s-2; + } + + &-right { + padding-left: $s-2; + } + + @include clearfix; + } + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/range-calendar.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/range-calendar.jsx new file mode 100644 index 000000000..6bbe8fa64 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/range-calendar.jsx @@ -0,0 +1,411 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import moment from 'moment'; +import ConfigProvider from '../config-provider'; +import nextLocale from '../locale/zh-cn'; +import { obj, func } from '../util'; +import RangePanelHeader from './head/range-panel-header'; +import MonthPanelHeader from './head/month-panel-header'; +import YearPanelHeader from './head/year-panel-header'; +import DateTable from './table/date-table'; +import MonthTable from './table/month-table'; +import YearTable from './table/year-table'; +import { + checkMomentObj, + formatDateValue, + getVisibleMonth, + isSameYearMonth, + CALENDAR_MODES, + CALENDAR_MODE_DATE, + CALENDAR_MODE_MONTH, + CALENDAR_MODE_YEAR, + getLocaleData, +} from './utils'; + +class RangeCalendar extends React.Component { + static propTypes = { + ...ConfigProvider.propTypes, + /** + * 样式前缀 + */ + prefix: PropTypes.string, + rtl: PropTypes.bool, + /** + * 默认的开始日期 + */ + defaultStartValue: checkMomentObj, + /** + * 默认的结束日期 + */ + defaultEndValue: checkMomentObj, + /** + * 开始日期(moment 对象) + */ + startValue: checkMomentObj, + /** + * 结束日期(moment 对象) + */ + endValue: checkMomentObj, + // 面板模式 + mode: PropTypes.oneOf(CALENDAR_MODES), + // 禁用更改面板模式,采用 dropdown 的方式切换显示日期 (暂不正式对外透出) + disableChangeMode: PropTypes.bool, + // 日期值的格式(用于日期title显示的格式) + format: PropTypes.string, + yearRange: PropTypes.arrayOf(PropTypes.number), + /** + * 是否显示非本月的日期 + */ + showOtherMonth: PropTypes.bool, + /** + * 模板展示的月份(起始月份) + */ + defaultVisibleMonth: PropTypes.func, + /** + * 展现的月份变化时的回调 + * @param {Object} value 显示的月份 (moment 对象) + * @param {String} reason 触发月份改变原因 + */ + onVisibleMonthChange: PropTypes.func, + /** + * 不可选择的日期 + * @param {Object} calendarDate 对应 Calendar 返回的自定义日期对象 + * @param {String} view 当前视图类型,year: 年, month: 月, date: 日 + * @returns {Boolean} + */ + disabledDate: PropTypes.func, + /** + * 选择日期单元格时的回调 + * @param {Object} value 对应的日期值 (moment 对象) + */ + onSelect: PropTypes.func, + /** + * 自定义日期单元格渲染 + */ + dateCellRender: PropTypes.func, + /** + * 自定义月份渲染函数 + * @param {Object} calendarDate 对应 Calendar 返回的自定义日期对象 + * @returns {ReactNode} + */ + monthCellRender: PropTypes.func, + yearCellRender: PropTypes.func, // 兼容 0.x yearCellRender + locale: PropTypes.object, + className: PropTypes.string, + }; + + static defaultProps = { + prefix: 'next-', + rtl: false, + mode: CALENDAR_MODE_DATE, + disableChangeMode: false, + format: 'YYYY-MM-DD', + dateCellRender: value => value.date(), + onSelect: func.noop, + onVisibleMonthChange: func.noop, + locale: nextLocale.Calendar, + showOtherMonth: false, + }; + + constructor(props, context) { + super(props, context); + + const startValue = formatDateValue( + props.startValue || props.defaultStartValue + ); + const endValue = formatDateValue( + props.endValue || props.defaultEndValue + ); + const visibleMonth = getVisibleMonth( + props.defaultVisibleMonth, + startValue + ); + + this.state = { + startValue, + endValue, + mode: props.mode, + startVisibleMonth: visibleMonth, + activePanel: undefined, + }; + this.today = moment(); + } + + componentWillReceiveProps(nextProps) { + if ('startValue' in nextProps) { + const startValue = formatDateValue(nextProps.startValue); + this.setState({ + startValue, + }); + + if ( + startValue && + !startValue.isSame(this.state.startValue, 'day') + ) { + this.setState({ + startVisibleMonth: startValue, + }); + } + } + + if ('endValue' in nextProps) { + const endValue = formatDateValue(nextProps.endValue); + this.setState({ + endValue, + }); + } + + if ('mode' in nextProps) { + this.setState({ + mode: nextProps.mode, + }); + } + } + + onSelectCell = (date, nextMode) => { + if (this.state.mode === CALENDAR_MODE_DATE) { + this.props.onSelect(date); + } else { + this.changeVisibleMonth(date, 'cellClick'); + } + + this.changeMode(nextMode); + }; + + changeMode = (mode, activePanel) => { + if (typeof mode === 'string' && mode !== this.state.mode) { + this.setState({ mode }); + } + if (activePanel && activePanel !== this.state.activePanel) { + this.setState({ activePanel }); + } + }; + + changeVisibleMonth = (date, reason) => { + if (!isSameYearMonth(date, this.state.startVisibleMonth)) { + this.setState({ startVisibleMonth: date }); + this.props.onVisibleMonthChange(date, reason); + } + }; + + /** + * 根据日期偏移量设置当前展示的月份 + * @param {Number} offset 日期偏移量 + * @param {String} type 日期偏移类型 days, months, years + */ + changeVisibleMonthByOffset = (offset, type) => { + const offsetDate = this.state.startVisibleMonth + .clone() + .add(offset, type); + this.changeVisibleMonth(offsetDate, 'buttonClick'); + }; + + goPrevDecade = () => { + this.changeVisibleMonthByOffset(-10, 'years'); + }; + + goNextDecade = () => { + this.changeVisibleMonthByOffset(10, 'years'); + }; + + goPrevYear = () => { + this.changeVisibleMonthByOffset(-1, 'years'); + }; + + goNextYear = () => { + this.changeVisibleMonthByOffset(1, 'years'); + }; + + goPrevMonth = () => { + this.changeVisibleMonthByOffset(-1, 'months'); + }; + + goNextMonth = () => { + this.changeVisibleMonthByOffset(1, 'months'); + }; + + render() { + const { + prefix, + rtl, + dateCellRender, + monthCellRender, + yearCellRender, + className, + format, + locale, + showOtherMonth, + disabledDate, + disableChangeMode, + yearRange, + ...others + } = this.props; + const { + startValue, + endValue, + mode, + startVisibleMonth, + activePanel, + } = this.state; + + // reset moment locale + if (locale.momentLocale) { + startValue && startValue.locale(locale.momentLocale); + endValue && endValue.locale(locale.momentLocale); + startVisibleMonth.locale(locale.momentLocale); + } + + if (rtl) { + others.dir = 'rtl'; + } + const localeData = getLocaleData( + locale.format || {}, + startVisibleMonth.localeData() + ); + + const endVisibleMonth = startVisibleMonth.clone().add(1, 'months'); + + const headerProps = { + prefix, + rtl, + mode, + locale, + momentLocale: localeData, + startVisibleMonth, + endVisibleMonth, + changeVisibleMonth: this.changeVisibleMonth, + changeMode: this.changeMode, + yearRange, + disableChangeMode, + }; + + const tableProps = { + prefix, + value: startValue, + startValue, + endValue, + mode, + locale, + momentLocale: localeData, + showOtherMonth, + today: this.today, + disabledDate, + dateCellRender, + monthCellRender, + yearCellRender, + changeMode: this.changeMode, + changeVisibleMonth: this.changeVisibleMonth, + }; + + const visibleMonths = { + start: startVisibleMonth, + end: endVisibleMonth, + }; + + const visibleMonth = visibleMonths[activePanel]; + + let header; + let table; + + switch (mode) { + case CALENDAR_MODE_DATE: { + table = [ +
    + +
    , +
    + +
    , + ]; + header = ( + + ); + break; + } + case CALENDAR_MODE_MONTH: { + table = ( + + ); + header = ( + + ); + break; + } + case CALENDAR_MODE_YEAR: { + table = ( + + ); + header = ( + + ); + break; + } + } + + const classNames = classnames( + { + [`${prefix}calendar`]: true, + [`${prefix}calendar-range`]: true, + }, + className + ); + + return ( +
    + {header} +
    {table}
    +
    + ); + } +} + +export default ConfigProvider.config(RangeCalendar, { + componentName: 'Calendar', +}); diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/rtl.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/rtl.scss new file mode 100644 index 000000000..6f007ce6e --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/rtl.scss @@ -0,0 +1,69 @@ +#{$calendar-prefix}[dir='rtl'] { + #{$calendar-prefix} { + &-header { + text-align: left; + + #{$calendar-select-prefix} { + margin-right: 0; + margin-left: $s-1; + } + + #{$calendar-menu-prefix} { + text-align: right; + } + } + &-btn-prev-decade, + &-btn-prev-year { + left: auto; + right: $calendar-btn-arrow-double-offset-lr; + } + + &-btn-prev-month { + left: auto; + right: $calendar-btn-arrow-single-offset-lr; + } + + &-btn-next-month { + right: auto; + left: $calendar-btn-arrow-single-offset-lr; + } + + &-btn-next-year, + &-btn-next-decade { + right: auto; + left: $calendar-btn-arrow-double-offset-lr; + } + } +} + +#{$calendar-prefix}-fullscreen[dir='rtl'] { + #{$calendar-prefix} { + &-th { + text-align: left; + padding-left: $calendar-fullscreen-table-head-padding-r; + padding-right: 0; + } + &-date, + &-month { + text-align: left; + } + } +} + +#{$calendar-prefix}-range[dir='rtl'] { + #{$calendar-prefix} { + &-body-left, &-body-right { + float: right; + } + + &-body-left { + padding-right: 0; + padding-left: $s-2; + } + + &-body-right { + padding-left: 0; + padding-right: $s-2; + } + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/scss/animation.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/scss/animation.scss new file mode 100644 index 000000000..976c58a80 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/scss/animation.scss @@ -0,0 +1,45 @@ +@keyframes cellZoomIn { + 0% { + transform: scale(.5); + } + 100% { + transform: scale(1); + } +} + +@keyframes cellHover { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } +} + +@keyframes enterToLeft { + 0% { + transform: translate(-40%); + opacity: 0; + } + 50% { + opacity: .6; + } + 100% { + opacity: 1; + transform: translate(0%); + } +} + +@keyframes enterToRight { + 0% { + transform: translate(40%); + opacity: 0; + } + 50% { + opacity: .6; + } + 100% { + opacity: 1; + transform: translate(0%); + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/scss/header.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/scss/header.scss new file mode 100644 index 000000000..af23c7d15 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/scss/header.scss @@ -0,0 +1,126 @@ +// shape +#{$calendar-prefix} { + + // shape: fullscreen, card + // ------------------------ + &-fullscreen, &-card { + + #{$calendar-prefix}-header { + text-align: right; + + #{$calendar-select-prefix} { + margin-right: $s-1; + vertical-align: top; + } + + #{$calendar-menu-prefix} { + text-align: left; + } + } + } + + // shape: fullscreen + &-fullscreen { + #{$calendar-prefix}-header { + margin-bottom: $calendar-fullscreen-header-margin-bottom; + } + } + + // shape: card + &-card { + #{$calendar-prefix}-header { + margin-bottom: $calendar-card-header-margin-bottom; + } + } + + // shape: panel + // ------------------------ + &-panel { + + &-header { + position: relative; + background: $calendar-panel-header-background; + margin-bottom: $calendar-panel-header-margin-bottom; + border-bottom: $calendar-panel-header-border-bottom-width solid $calendar-panel-header-border-bottom-color; + + &-left, + &-right, + &-full { + height: $calendar-panel-header-height; + line-height: $calendar-panel-header-height; + + #{$calendar-prefix}-btn { + vertical-align: top; + font-weight: $calendar-btn-date-font-weight; + margin: 0 $calendar-btn-date-margin-lr; + @include button-color($calendar-btn-date-color, $calendar-btn-date-color-hover); + } + } + + &-left, + &-right { + display: inline-block; + width: 50%; + text-align: center; + } + + &-full { + width: 100%; + text-align: center; + } + } + } + + &-panel-menu { + max-height: 210px; + overflow: auto; + text-align: left; + } + // panel components + // ------------------------ + &-btn { + cursor: pointer; + padding: 0; + margin: 0; + border: 0; + background: transparent; + outline: none; + height: 100%; + + & > #{$calendar-icon-prefix}#{$calendar-icon-prefix} { + @include icon-size($calendar-btn-arrow-size); + } + .#{$css-prefix}icon { + margin-left: $s-1; + } + } + + &-btn-prev-year, + &-btn-prev-month, + &-btn-prev-decade, + &-btn-next-month, + &-btn-next-year, + &-btn-next-decade { + position: absolute; + top: 0; + @include button-color($calendar-btn-arrow-color, $calendar-btn-arrow-color-hover); + } + + &-btn-prev-decade, + &-btn-prev-year { + left: $calendar-btn-arrow-double-offset-lr; + } + + &-btn-prev-month { + left: $calendar-btn-arrow-single-offset-lr; + } + + &-btn-next-month { + right: $calendar-btn-arrow-single-offset-lr; + } + + &-btn-next-year, + &-btn-next-decade { + right: $calendar-btn-arrow-double-offset-lr; + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/scss/mixin.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/scss/mixin.scss new file mode 100644 index 000000000..77579d01d --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/scss/mixin.scss @@ -0,0 +1,26 @@ +// 状态 +// ---------------------------------------- +@mixin calendar-cell-state( + $background, + $color, + $border-color +) { + background: $background; + color: $color; + border-color: $border-color; +} + +// 卡片模式单元尺寸 +// ---------------------------------------- +@mixin calendar-card-cell-size( + $width, + $height, + $corner: 0, + $margin-tb: 0 +) { + width: $width; + height: $height; + line-height: $height - 2; + margin: $margin-tb auto; + border-radius: $corner; +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/scss/normalize.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/scss/normalize.scss new file mode 100644 index 000000000..c2e7d0fb8 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/scss/normalize.scss @@ -0,0 +1,13 @@ +#{$calendar-prefix} { + @include box-sizing(); + + table { + border-collapse: collapse; + border-spacing: 0; + } + + td, + th { + padding: 0; + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/scss/table.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/scss/table.scss new file mode 100644 index 000000000..db38d847b --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/scss/table.scss @@ -0,0 +1,290 @@ +#{$calendar-prefix}-fullscreen { + + #{$calendar-prefix} { + &-th { + text-align: right; + color: $calendar-fullscreen-table-head-color; + font-size: $calendar-fullscreen-table-head-font-size; + font-weight: $calendar-fullscreen-table-head-font-weight; + padding-right: $calendar-fullscreen-table-head-padding-r; + padding-bottom: $calendar-fullscreen-table-head-padding-b; + } + + &-cell { + font-size: $calendar-fullscreen-table-cell-font-size; + + &.#{$css-prefix}selected { + #{$calendar-prefix}-date, + #{$calendar-prefix}-month { + font-weight: $calendar-fullscreen-table-cell-select-font-weight; + + @include calendar-cell-state ( + $calendar-fullscreen-table-cell-select-background, + $calendar-fullscreen-table-cell-select-color, + $calendar-fullscreen-table-cell-select-border-color + ); + } + } + + &.#{$css-prefix}disabled { + #{$calendar-prefix}-date, + #{$calendar-prefix}-month { + cursor: not-allowed; + @include calendar-cell-state ( + $calendar-fullscreen-table-cell-disabled-background, + $calendar-fullscreen-table-cell-disabled-color, + $calendar-fullscreen-table-cell-disabled-border-color + ); + } + } + } + + &-date, + &-month { + text-align: right; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + margin: $calendar-fullscreen-table-cell-margin-tb $calendar-fullscreen-table-cell-margin-lr; + padding: $calendar-fullscreen-table-cell-padding-tb $calendar-fullscreen-table-cell-padding-lr; + min-height: $calendar-fullscreen-table-cell-min-height; + border-top: $calendar-fullscreen-table-cell-boder-top-width $line-solid; + transition: background $motion-duration-immediately $motion-linear; + + @include calendar-cell-state ( + $calendar-fullscreen-table-cell-normal-background, + $calendar-fullscreen-table-cell-normal-color, + $calendar-fullscreen-table-cell-normal-border-color + ); + + &:hover { + @include calendar-cell-state ( + $calendar-fullscreen-table-cell-hover-background, + $calendar-fullscreen-table-cell-hover-color, + $calendar-fullscreen-table-cell-hover-border-color + ); + } + } + + &-cell-prev-month, + &-cell-next-month { + #{$calendar-prefix}-date { + @include calendar-cell-state ( + $calendar-fullscreen-table-cell-other-background, + $calendar-fullscreen-table-cell-other-color, + $calendar-fullscreen-table-cell-other-border-color + ); + } + } + + &-cell-current { + #{$calendar-prefix}-date, + #{$calendar-prefix}-month { + font-weight: $calendar-fullscreen-table-cell-current-font-weight; + + @include calendar-cell-state ( + $calendar-fullscreen-table-cell-current-background, + $calendar-fullscreen-table-cell-current-color, + $calendar-fullscreen-table-cell-current-border-color + ); + } + } + } +} + +#{$calendar-prefix}-card, +#{$calendar-prefix}-panel, +#{$calendar-prefix}-range { + + #{$calendar-prefix} { + &-th { + text-align: center; + color: $calendar-card-table-head-color; + font-size: $calendar-card-table-head-font-size; + font-weight: $calendar-card-table-head-font-weight; + } + + &-cell { + text-align: center; + font-size: $calendar-card-table-cell-font-size; + + &.#{$css-prefix}selected { + #{$calendar-prefix}-date, + #{$calendar-prefix}-month, + #{$calendar-prefix}-year { + animation: cellZoomIn .4s cubic-bezier(.23, 1, .32, 1); + font-weight: $calendar-card-table-cell-select-font-weight; + + @include calendar-cell-state ( + $calendar-card-table-cell-select-background, + $calendar-card-table-cell-select-color, + $calendar-card-table-cell-select-border-color + ); + } + } + + &.#{$css-prefix}disabled { + #{$calendar-prefix}-date, + #{$calendar-prefix}-month, + #{$calendar-prefix}-year { + cursor: not-allowed; + + @include calendar-cell-state ( + $calendar-card-table-cell-disabled-background, + $calendar-card-table-cell-disabled-color, + $calendar-card-table-cell-disabled-border-color + ); + } + } + + &.#{$css-prefix}inrange { + #{$calendar-prefix}-date { + @include calendar-cell-state ( + $calendar-card-table-cell-inrange-background, + $calendar-card-table-cell-inrange-color, + $calendar-card-table-cell-inrange-border-color); + } + } + } + + &-date, + &-month, + &-year { + text-align: center; + border: $line-1 $line-solid; + + &:hover { + cursor: pointer; + } + + @include calendar-cell-state ( + $calendar-card-table-cell-normal-background, + $calendar-card-table-cell-normal-color, + $calendar-card-table-cell-normal-border-color + ); + + &:hover { + @include calendar-cell-state ( + $calendar-card-table-cell-hover-background, + $calendar-card-table-cell-hover-color, + $calendar-card-table-cell-hover-border-color + ); + } + } + + &-date { + @include calendar-card-cell-size( + $calendar-card-table-cell-date-width, + $calendar-card-table-cell-date-height, + $calendar-card-table-cell-date-border-radius, + $s-1 + ); + } + + &-month { + @include calendar-card-cell-size( + $calendar-card-table-cell-month-width, + $calendar-card-table-cell-month-height, + $calendar-card-table-cell-month-border-radius, + $s-2 + ); + } + + &-year { + @include calendar-card-cell-size( + $calendar-card-table-cell-year-width, + $calendar-card-table-cell-year-height, + $calendar-card-table-cell-year-border-radius, + $s-2 + ); + } + + &-cell-prev-month { + #{$calendar-prefix}-date { + @include calendar-cell-state ( + $calendar-card-table-cell-other-background, + $calendar-card-table-cell-other-color, + $calendar-card-table-cell-other-border-color + ); + } + } + + &-cell-next-month { + #{$calendar-prefix}-date { + @include calendar-cell-state ( + $calendar-card-table-cell-other-background, + $calendar-card-table-cell-other-color, + $calendar-card-table-cell-other-border-color + ); + } + } + + &-cell-current { + #{$calendar-prefix}-date, + #{$calendar-prefix}-month, + #{$calendar-prefix}-year { + font-weight: $calendar-card-table-cell-current-font-weight; + + @include calendar-cell-state ( + $calendar-card-table-cell-current-background, + $calendar-card-table-cell-current-color, + $calendar-card-table-cell-current-border-color + ); + } + } + } +} + +#{$calendar-prefix}-panel#{$calendar-prefix}-week { + #{$calendar-prefix}-tbody { + tr { + cursor: pointer; + } + tr:hover { + #{$calendar-prefix}-cell #{$calendar-prefix}-date { + @include calendar-cell-state ( + $calendar-card-table-cell-hover-background, + $calendar-card-table-cell-hover-color, + $calendar-card-table-cell-hover-border-color + ); + } + } + + #{$calendar-prefix}-cell.#{$css-prefix}selected { + #{$calendar-prefix}-date { + font-weight: normal; + background: transparent; + border-color: transparent; + } + } + + #{$calendar-prefix}-week-active-date { + position: relative; + color: $calendar-card-table-cell-inrange-color; + &::before { + content: ''; + position: absolute; + left: -$line-1; + top: -$line-1; + bottom: -$line-1; + right: -$line-1; + border: $line-1 $line-solid; + background: $calendar-card-table-cell-inrange-background; + border-color: $calendar-card-table-cell-inrange-border-color; + border-radius: $calendar-card-table-cell-date-border-radius; + } + > span { + position: relative; + } + } + + #{$calendar-prefix}-week-active-start, + #{$calendar-prefix}-week-active-end { + color: $calendar-card-table-cell-select-color; + &::before { + background: $calendar-card-table-cell-select-background; + border-color: $calendar-card-table-cell-select-border-color; + } + } + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/scss/variable.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/scss/variable.scss new file mode 100644 index 000000000..d51892e20 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/scss/variable.scss @@ -0,0 +1,371 @@ +//// +/// @module calendar: 日历 +/// @tag Calendar +/// @category component +/// @family data-display +/// @varPrefix $calendar- +/// @classPrefix {prefix}-calendar +/// @order {"size/header":10,"size/table head":11,"size/table cell":12,"statement/normal":10,"statement/normal/table head":100,"statement/normal/table cell":101,"statement/normal/header":102,"statement/hover":11,"statement/hover/table cell":110,"statement/hover/header":111,"statement/selected":12,"statement/selected/table cell":120,"statement/current":13,"statement/current/table cell":130,"statement/other month":14,"statement/other month/table cell":140,"statement/disabled":15,"statement/disabled/table cell":150,"statement/last month":16,"statement/last month/table cell":160,"statement/in range":17,"statement/in range/table cell":170} +//// + +$calendar-prefix: '.' + $css-prefix + 'calendar'; + +$calendar-select-prefix: '.' + $css-prefix + 'select'; + +$calendar-radio-prefix: '.' + $css-prefix + 'radio'; + +$calendar-icon-prefix: '.' + $css-prefix + 'icon'; + +$calendar-menu-prefix: '.' + $css-prefix + 'menu'; + +// 全屏模式 +// ---------------------------------------- + +/// margin (b) +/// @namespace size/header +$calendar-fullscreen-header-margin-bottom: $s-2 !default; + +/// font weight +/// @namespace size/table head +$calendar-fullscreen-table-head-font-weight: $font-weight-3 !default; + +/// text +/// @namespace size/table head +$calendar-fullscreen-table-head-font-size: $font-size-subhead !default; + +/// padding (r) +/// @namespace size/table head +$calendar-fullscreen-table-head-padding-r: $s-3 !default; + +/// padding (b) +/// @namespace size/table head +$calendar-fullscreen-table-head-padding-b: $s-1 !default; + +/// text +/// @namespace size/table cell +$calendar-fullscreen-table-cell-font-size: $font-size-body-2 !default; + +/// border (t) +/// @namespace size/table cell +$calendar-fullscreen-table-cell-boder-top-width: $line-2 !default; + +/// margin (t, b) +/// @namespace size/table cell +$calendar-fullscreen-table-cell-margin-tb: $s-zero !default; + +/// margin (l, r) +/// @namespace size/table cell +$calendar-fullscreen-table-cell-margin-lr: $s-1 !default; + +/// padding (t, b) +/// @namespace size/table cell +$calendar-fullscreen-table-cell-padding-tb: $s-1 !default; + +/// padding (l, r) +/// @namespace size/table cell +$calendar-fullscreen-table-cell-padding-lr: $s-2 !default; + +/// min height +/// @namespace size/table cell +$calendar-fullscreen-table-cell-min-height: $s-20 !default; + +/// text +/// @namespace statement/normal/table head +$calendar-fullscreen-table-head-color: $color-text1-4 !default; + +/// background +/// @namespace statement/normal/table cell +$calendar-fullscreen-table-cell-normal-background: $color-white !default; + +/// text +/// @namespace statement/normal/table cell +$calendar-fullscreen-table-cell-normal-color: $color-text1-4 !default; + +/// border color +/// @namespace statement/normal/table cell +$calendar-fullscreen-table-cell-normal-border-color: $color-line1-2 !default; + +/// background +/// @namespace statement/hover/table cell +$calendar-fullscreen-table-cell-hover-background: $color-brand1-1 !default; + +/// text +/// @namespace statement/hover/table cell +$calendar-fullscreen-table-cell-hover-color: $color-brand1-6 !default; + +/// border color +/// @namespace statement/hover/table cell +$calendar-fullscreen-table-cell-hover-border-color: $color-brand1-6 !default; + +/// background +/// @namespace statement/selected/table cell +$calendar-fullscreen-table-cell-select-background: $color-brand1-1 !default; + +/// text +/// @namespace statement/selected/table cell +$calendar-fullscreen-table-cell-select-color: $color-brand1-6 !default; + +/// border color +/// @namespace statement/selected/table cell +$calendar-fullscreen-table-cell-select-border-color: $color-brand1-6 !default; + +/// font weight +/// @namespace statement/selected/table cell +$calendar-fullscreen-table-cell-select-font-weight: $font-weight-3 !default; + +/// background +/// @namespace statement/current/table cell +$calendar-fullscreen-table-cell-current-background: $color-white !default; + +/// text +/// @namespace statement/current/table cell +$calendar-fullscreen-table-cell-current-color: $color-brand1-6 !default; + +/// border color +/// @namespace statement/current/table cell +$calendar-fullscreen-table-cell-current-border-color: $color-brand1-6 !default; + +/// font weight +/// @namespace statement/current/table cell +$calendar-fullscreen-table-cell-current-font-weight: $font-weight-3 !default; + +/// background +/// @namespace statement/other month/table cell +$calendar-fullscreen-table-cell-other-background: $color-transparent !default; + +/// text +/// @namespace statement/other month/table cell +$calendar-fullscreen-table-cell-other-color: $color-text1-1 !default; + +/// border color +/// @namespace statement/other month/table cell +$calendar-fullscreen-table-cell-other-border-color: $color-transparent !default; + +/// background +/// @namespace statement/disabled/table cell +$calendar-fullscreen-table-cell-disabled-background: $color-fill1-1 !default; + +/// text +/// @namespace statement/disabled/table cell +$calendar-fullscreen-table-cell-disabled-color: $color-text1-1 !default; + +/// border color +/// @namespace statement/disabled/table cell +$calendar-fullscreen-table-cell-disabled-border-color: $color-line1-1 !default; + +// 卡片模式 cell +// ---------------------------------------- + +/// margin (b) +/// @namespace size/header +$calendar-card-header-margin-bottom: $s-2 !default; + +/// text +/// @namespace size/table head +$calendar-card-table-head-font-size: $font-size-caption !default; + +/// font weight +/// @namespace size/table head +$calendar-card-table-head-font-weight: $font-weight-2 !default; + +/// text +/// @namespace size/table cell +$calendar-card-table-cell-font-size: $font-size-caption !default; + +/// date corner +/// @namespace size/table cell +$calendar-card-table-cell-date-border-radius: $corner-1 !default; + +/// date width +/// @namespace size/table cell +$calendar-card-table-cell-date-width: $s-6 !default; + +/// date height +/// @namespace size/table cell +$calendar-card-table-cell-date-height: $s-6 !default; + +/// month corner +/// @namespace size/table cell +$calendar-card-table-cell-month-border-radius: $corner-1 !default; + +/// month width +/// @namespace size/table cell +$calendar-card-table-cell-month-width: $s-15 !default; + +/// month height +/// @namespace size/table cell +$calendar-card-table-cell-month-height: $s-6 !default; + +/// year corner +/// @namespace size/table cell +$calendar-card-table-cell-year-border-radius: $corner-1 !default; + +/// year width +/// @namespace size/table cell +$calendar-card-table-cell-year-width: $s-12 !default; + +/// year height +/// @namespace size/table cell +$calendar-card-table-cell-year-height: $s-6 !default; + +/// text +/// @namespace statement/normal/table head +$calendar-card-table-head-color: $color-text1-2 !default; + +/// cell corner +/// @namespace statement/normal/table cell +$calendar-card-table-cell-corner: $corner-zero !default; + +/// background +/// @namespace statement/normal/table cell +$calendar-card-table-cell-normal-background: $color-white !default; + +/// text +/// @namespace statement/normal/table cell +$calendar-card-table-cell-normal-color: $color-text1-3 !default; + +/// border color +/// @namespace statement/normal/table cell +$calendar-card-table-cell-normal-border-color: $color-white !default; + +/// background +/// @namespace statement/hover/table cell +$calendar-card-table-cell-hover-background: $color-brand1-1 !default; + +/// text +/// @namespace statement/hover/table cell +$calendar-card-table-cell-hover-color: $color-brand1-6 !default; + +/// border color +/// @namespace statement/hover/table cell +$calendar-card-table-cell-hover-border-color: $color-brand1-1 !default; + +/// background +/// @namespace statement/selected/table cell +$calendar-card-table-cell-select-background: $color-brand1-6 !default; + +/// text +/// @namespace statement/selected/table cell +$calendar-card-table-cell-select-color: $color-white !default; + +/// border color +/// @namespace statement/selected/table cell +$calendar-card-table-cell-select-border-color: $color-brand1-6 !default; + +/// font weight +/// @namespace statement/selected/table cell +$calendar-card-table-cell-select-font-weight: $font-weight-3 !default; + +/// background +/// @namespace statement/last month/table cell +$calendar-card-table-cell-other-background: $color-white !default; + +/// text +/// @namespace statement/last month/table cell +$calendar-card-table-cell-other-color: $color-text1-1 !default; + +/// border color +/// @namespace statement/last month/table cell +$calendar-card-table-cell-other-border-color: $color-white !default; + +/// background +/// @namespace statement/disabled/table cell +$calendar-card-table-cell-disabled-background: $color-fill1-1 !default; + +/// text +/// @namespace statement/disabled/table cell +$calendar-card-table-cell-disabled-color: $color-text1-1 !default; + +/// border color +/// @namespace statement/disabled/table cell +$calendar-card-table-cell-disabled-border-color: $color-fill1-1 !default; + +/// background +/// @namespace statement/current/table cell +$calendar-card-table-cell-current-background: $color-white !default; + +/// text +/// @namespace statement/current/table cell +$calendar-card-table-cell-current-color: $color-brand1-6 !default; + +/// border color +/// @namespace statement/current/table cell +$calendar-card-table-cell-current-border-color: $color-transparent !default; + +/// font weight +/// @namespace statement/current/table cell +$calendar-card-table-cell-current-font-weight: $font-weight-3 !default; + +/// background +/// @namespace statement/in range/table cell +$calendar-card-table-cell-inrange-background: $color-brand1-1 !default; + +/// text +/// @namespace statement/in range/table cell +$calendar-card-table-cell-inrange-color: $color-brand1-6 !default; + +/// border color +/// @namespace statement/in range/table cell +$calendar-card-table-cell-inrange-border-color: $color-brand1-1 !default; + +// 面板模式 Panel Header +// ---------------------------------------- + +/// margin (b) +/// @namespace size/header +$calendar-panel-header-margin-bottom: $s-2 !default; + +/// height +/// @namespace size/header +$calendar-panel-header-height: $s-8 !default; + +/// border (b) +/// @namespace size/header +$calendar-panel-header-border-bottom-width: $line-1 !default; + +/// background +/// @namespace statement/normal/header +$calendar-panel-header-background: $color-brand1-6 !default; + +/// border (b) +/// @namespace statement/normal/header +$calendar-panel-header-border-bottom-color: $color-transparent !default; + +// calendar btn +// -------------------- + +/// btn font weight +/// @namespace size/header +$calendar-btn-date-font-weight: $font-weight-3 !default; + +/// btn margin (lr) +/// @namespace size/header +$calendar-btn-date-margin-lr: $s-1 !default; + +/// sing arrow offset (l, r) +/// @namespace size/header +$calendar-btn-arrow-single-offset-lr: $s-7 !default; + +/// double arrow offset (l,r ) +/// @namespace size/header +$calendar-btn-arrow-double-offset-lr: $s-2 !default; + +/// icon +/// @namespace size/header +$calendar-btn-arrow-size: $icon-xs !default; + +/// arrow +/// @namespace statement/normal/header +$calendar-btn-arrow-color: $color-white !default; + +/// arrow +/// @namespace statement/hover/header +$calendar-btn-arrow-color-hover: $color-white !default; + +/// text +/// @namespace statement/normal/header +$calendar-btn-date-color: $color-white !default; + +/// text +/// @namespace statement/hover/header +$calendar-btn-date-color-hover: $color-white !default; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/style.js b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/style.js new file mode 100644 index 000000000..e5286b5dc --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/style.js @@ -0,0 +1,4 @@ +import '../icon/style.js'; +import '../radio/style.js'; +import '../select/style.js'; +import './main.scss'; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/table/date-table-head.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/table/date-table-head.jsx new file mode 100644 index 000000000..b3d1691b5 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/table/date-table-head.jsx @@ -0,0 +1,28 @@ +import React, { PureComponent } from 'react'; +import { DAYS_OF_WEEK } from '../utils'; + +class DateTableHead extends PureComponent { + render() { + const { prefix, momentLocale } = this.props; + const firstDayOfWeek = momentLocale.firstDayOfWeek(); + const weekdaysShort = momentLocale.weekdaysShort(); + + const elements = []; + for (let i = 0; i < DAYS_OF_WEEK; i++) { + const index = (firstDayOfWeek + i) % DAYS_OF_WEEK; + elements.push( + + {weekdaysShort[index]} + + ); + } + + return ( + + {elements} + + ); + } +} + +export default DateTableHead; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/table/date-table.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/table/date-table.jsx new file mode 100644 index 000000000..e10290fec --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/table/date-table.jsx @@ -0,0 +1,166 @@ +import React, { PureComponent } from 'react'; +import classNames from 'classnames'; +import DateTableHead from './date-table-head'; +import { + isDisabledDate, + DAYS_OF_WEEK, + CALENDAR_TABLE_COL_COUNT, + CALENDAR_TABLE_ROW_COUNT, +} from '../utils'; + +function isSameDay(a, b) { + return a && b && a.isSame(b, 'day'); +} + +function isRangeDate(date, startDate, endDate) { + return ( + date.format('L') !== startDate.format('L') && + date.format('L') !== endDate.format('L') && + date.valueOf() > startDate.valueOf() && + date.valueOf() < endDate.valueOf() + ); +} + +function isLastMonthDate(date, target) { + if (date.year() < target.year()) { + return 1; + } + return date.year() === target.year() && date.month() < target.month(); +} + +function isNextMonthDate(date, target) { + if (date.year() > target.year()) { + return 1; + } + return date.year() === target.year() && date.month() > target.month(); +} + +class DateTable extends PureComponent { + render() { + const { + prefix, + visibleMonth, + showOtherMonth, + endValue, + format, + today, + momentLocale, + dateCellRender, + disabledDate, + onSelectDate, + } = this.props; + const startValue = this.props.startValue || this.props.value; + + const firstDayOfMonth = visibleMonth.clone().startOf('month'); // 该月的 1 号 + const firstDayOfMonthInWeek = firstDayOfMonth.day(); // 星期几 + + const firstDayOfWeek = momentLocale.firstDayOfWeek(); + + const datesOfLastMonthCount = + (firstDayOfMonthInWeek + DAYS_OF_WEEK - firstDayOfWeek) % + DAYS_OF_WEEK; + + const lastMonthDate = firstDayOfMonth.clone(); + lastMonthDate.add(0 - datesOfLastMonthCount, 'days'); + + let counter = 0; + let currentDate; + const dateList = []; + for (let i = 0; i < CALENDAR_TABLE_ROW_COUNT; i++) { + for (let j = 0; j < CALENDAR_TABLE_COL_COUNT; j++) { + currentDate = lastMonthDate; + if (counter) { + currentDate = currentDate.clone(); + currentDate.add(counter, 'days'); + } + dateList.push(currentDate); + counter++; + } + } + + counter = 0; // reset counter + const monthElements = []; + for (let i = 0; i < CALENDAR_TABLE_ROW_COUNT; i++) { + const weekElements = []; + for (let j = 0; j < CALENDAR_TABLE_COL_COUNT; j++) { + currentDate = dateList[counter]; + const isLastMonth = isLastMonthDate(currentDate, visibleMonth); + const isNextMonth = isNextMonthDate(currentDate, visibleMonth); + const isCurrentMonth = !isLastMonth && !isNextMonth; + + const isDisabled = isDisabledDate( + currentDate, + disabledDate, + 'date' + ); + const isToday = + !isDisabled && + isSameDay(currentDate, today) && + isCurrentMonth; + const isSelected = + !isDisabled && + (isSameDay(currentDate, startValue) || + isSameDay(currentDate, endValue)) && + isCurrentMonth; + const isInRange = + !isDisabled && + startValue && + endValue && + isRangeDate(currentDate, startValue, endValue) && + isCurrentMonth; + + const cellContent = + !showOtherMonth && !isCurrentMonth + ? null + : dateCellRender(currentDate); + + const elementCls = classNames({ + [`${prefix}calendar-cell`]: true, + [`${prefix}calendar-cell-prev-month`]: isLastMonth, + [`${prefix}calendar-cell-next-month`]: isNextMonth, + [`${prefix}calendar-cell-current`]: isToday, + [`${prefix}inrange`]: isInRange, + [`${prefix}selected`]: isSelected, + [`${prefix}disabled`]: cellContent && isDisabled, + }); + + weekElements.push( + +
    + {cellContent} +
    + + ); + counter++; + } + monthElements.push( + + {weekElements} + + ); + } + + return ( + + + + {monthElements} + +
    + ); + } +} + +export default DateTable; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/table/month-table.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/table/month-table.jsx new file mode 100644 index 000000000..2f7d1c208 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/table/month-table.jsx @@ -0,0 +1,96 @@ +import React, { PureComponent } from 'react'; +import classnames from 'classnames'; +import { + isDisabledDate, + MONTH_TABLE_ROW_COUNT, + MONTH_TABLE_COL_COUNT, +} from '../utils'; + +function isSameMonth(currentDate, selectedDate) { + return ( + selectedDate && + currentDate.year() === selectedDate.year() && + currentDate.month() === selectedDate.month() + ); +} + +class MonthTable extends PureComponent { + onMonthCellClick(date) { + this.props.onSelectMonth(date, 'date'); + } + + render() { + const { + prefix, + value, + visibleMonth, + disabledDate, + today, + momentLocale, + monthCellRender, + } = this.props; + + const monthLocale = momentLocale.monthsShort(); + + let counter = 0; + const monthList = []; + for (let i = 0; i < MONTH_TABLE_ROW_COUNT; i++) { + const rowList = []; + for (let j = 0; j < MONTH_TABLE_COL_COUNT; j++) { + const monthDate = visibleMonth.clone().month(counter); + const isDisabled = isDisabledDate( + monthDate, + disabledDate, + 'month' + ); + const isSelected = isSameMonth(monthDate, value); + const isThisMonth = isSameMonth(monthDate, today); + const elementCls = classnames({ + [`${prefix}calendar-cell`]: true, + [`${prefix}calendar-cell-current`]: isThisMonth, + [`${prefix}selected`]: isSelected, + [`${prefix}disabled`]: isDisabled, + }); + const localedMonth = monthLocale[counter]; + const monthCellContent = monthCellRender + ? monthCellRender(monthDate) + : localedMonth; + rowList.push( + +
    + {monthCellContent} +
    + + ); + counter++; + } + monthList.push( + + {rowList} + + ); + } + + return ( + + + {monthList} + +
    + ); + } +} + +export default MonthTable; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/table/year-table.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/table/year-table.jsx new file mode 100644 index 000000000..ed9fa3e5a --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/table/year-table.jsx @@ -0,0 +1,106 @@ +import React from 'react'; +import classnames from 'classnames'; +import Icon from '../../icon'; +import { + isDisabledDate, + YEAR_TABLE_COL_COUNT, + YEAR_TABLE_ROW_COUNT, +} from '../utils'; + +class YearTable extends React.PureComponent { + onYearCellClick(date) { + this.props.onSelectYear(date, 'month'); + } + + render() { + const { + prefix, + value, + today, + visibleMonth, + locale, + disabledDate, + goPrevDecade, + goNextDecade, + yearCellRender, + } = this.props; + const currentYear = today.year(); + const selectedYear = value ? value.year() : null; + const visibleYear = visibleMonth.year(); + const startYear = Math.floor(visibleYear / 10) * 10; + + const yearElements = []; + let counter = 0; + + const lastRowIndex = YEAR_TABLE_ROW_COUNT - 1; + const lastColIndex = YEAR_TABLE_COL_COUNT - 1; + + for (let i = 0; i < YEAR_TABLE_ROW_COUNT; i++) { + const rowElements = []; + for (let j = 0; j < YEAR_TABLE_COL_COUNT; j++) { + let content; + let year; + let isDisabled = false; + let onClick; + let title; + + if (i === 0 && j === 0) { + title = locale.prevDecade; + onClick = goPrevDecade; + content = ; + } else if (i === lastRowIndex && j === lastColIndex) { + title = locale.nextDecade; + onClick = goNextDecade; + content = ; + } else { + year = startYear + counter++; + title = year; + const yearDate = visibleMonth.clone().year(year); + isDisabled = isDisabledDate(yearDate, disabledDate, 'year'); + + !isDisabled && + (onClick = this.onYearCellClick.bind(this, yearDate)); + + content = yearCellRender ? yearCellRender(yearDate) : year; + } + + const isSelected = year === selectedYear; + + const classNames = classnames({ + [`${prefix}calendar-cell`]: true, + [`${prefix}calendar-cell-current`]: year === currentYear, + [`${prefix}selected`]: isSelected, + [`${prefix}disabled`]: isDisabled, + }); + + rowElements.push( + +
    + {content} +
    + + ); + } + yearElements.push( + + {rowElements} + + ); + } + return ( + + + {yearElements} + +
    + ); + } +} + +export default YearTable; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/utils/index.js b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/utils/index.js new file mode 100644 index 000000000..f99eaf29b --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/calendar/utils/index.js @@ -0,0 +1,129 @@ +import moment from 'moment'; + +export const DAYS_OF_WEEK = 7; + +export const CALENDAR_TABLE_COL_COUNT = 7; + +export const CALENDAR_TABLE_ROW_COUNT = 6; + +export const MONTH_TABLE_ROW_COUNT = 4; + +export const MONTH_TABLE_COL_COUNT = 3; + +export const YEAR_TABLE_ROW_COUNT = 4; + +export const YEAR_TABLE_COL_COUNT = 3; + +export const CALENDAR_MODE_YEAR = 'year'; + +export const CALENDAR_MODE_MONTH = 'month'; + +export const CALENDAR_MODE_DATE = 'date'; + +export const CALENDAR_MODES = [ + CALENDAR_MODE_DATE, + CALENDAR_MODE_MONTH, + CALENDAR_MODE_YEAR, +]; + +export function isDisabledDate(date, fn, view) { + if (typeof fn === 'function' && fn(date, view)) { + return true; + } + return false; +} + +export function checkMomentObj(props, propName, componentName) { + if (props[propName] && !moment.isMoment(props[propName])) { + return new Error( + `Invalid prop ${propName} supplied to ${componentName}. Required a moment object` + ); + } +} + +export function formatDateValue(value, reservedValue = null) { + if (value && moment.isMoment(value)) { + return value; + } + return reservedValue; +} + +export function getVisibleMonth(defaultVisibleMonth, value) { + let getVM = defaultVisibleMonth; + if (typeof getVM !== 'function' || !moment.isMoment(getVM())) { + getVM = () => { + if (value) { + return value; + } + return moment(); + }; + } + return getVM(); +} + +export function isSameYearMonth(dateA, dateB) { + return dateA.month() === dateB.month() && dateA.year() === dateB.year(); +} + +export function preFormatDateValue(value, format) { + const val = + typeof value === 'string' ? moment(value, format, false) : value; + if (val && moment.isMoment(val) && val.isValid()) { + return val; + } + + return null; +} + +export function getLocaleData( + { + months, + shortMonths, + firstDayOfWeek, + weekdays, + shortWeekdays, + veryShortWeekdays, + }, + localeData +) { + return { + ...localeData, + monthsShort: () => shortMonths || localeData.monthsShort(), + months: () => months || localeData.months(), + firstDayOfWeek: () => firstDayOfWeek || localeData.firstDayOfWeek(), + weekdays: () => weekdays || localeData.weekdays, + weekdaysShort: () => shortWeekdays || localeData.weekdaysShort(), + weekdaysMin: () => veryShortWeekdays || localeData.weekdaysMin(), + }; +} + +/* istanbul ignore next */ +export function getYears(yearRange, yearRangeOffset, year) { + const options = []; + let [startYear, endYear] = yearRange; + if (!startYear || !endYear) { + startYear = year - yearRangeOffset; + endYear = year + yearRangeOffset; + } + + for (let i = startYear; i <= endYear; i++) { + options.push({ + label: i, + value: i, + }); + } + return options; +} + +/* istanbul ignore next */ +export function getMonths(momentLocale) { + const localeMonths = momentLocale.monthsShort(); + const options = []; + for (let i = 0; i < 12; i++) { + options.push({ + value: i, + label: localeMonths[i], + }); + } + return options; +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/card/actions.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/card/actions.jsx new file mode 100644 index 000000000..f9d538233 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/card/actions.jsx @@ -0,0 +1,41 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; +import ConfigProvider from '../config-provider'; + +/** + * Card.Actions + * @order 5 + */ +class CardActions extends Component { + static propTypes = { + prefix: PropTypes.string, + /** + * 设置标签类型 + */ + component: PropTypes.elementType, + className: PropTypes.string, + }; + + static defaultProps = { + prefix: 'next-', + component: 'div', + }; + + render() { + const { + prefix, + component: Component, + className, + ...others + } = this.props; + return ( + + ); + } +} + +export default ConfigProvider.config(CardActions); diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/card/bullet-header.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/card/bullet-header.jsx new file mode 100644 index 000000000..a592f8796 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/card/bullet-header.jsx @@ -0,0 +1,70 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; +import ConfigProvider from '../config-provider'; + +/** + * Card.BulletHeader + * @order 2 + */ +class CardBulletHeader extends Component { + static propTypes = { + prefix: PropTypes.string, + /** + * 卡片的标题 + */ + title: PropTypes.node, + /** + * 卡片的副标题 + */ + subTitle: PropTypes.node, + /** + * 是否显示标题的项目符号 + */ + showTitleBullet: PropTypes.bool, + /** + * 标题区域的用户自定义内容 + */ + extra: PropTypes.node, + }; + + static defaultProps = { + prefix: 'next-', + showTitleBullet: true, + }; + + render() { + const { prefix, title, subTitle, extra, showTitleBullet } = this.props; + + if (!title) return null; + + const headCls = classNames({ + [`${prefix}card-head`]: true, + [`${prefix}card-head-show-bullet`]: showTitleBullet, + }); + + const headExtra = extra ? ( +
    {extra}
    + ) : null; + + return ( +
    +
    +
    + {title} + {subTitle ? ( + + {subTitle} + + ) : null} +
    + {headExtra} +
    +
    + ); + } +} + +export default ConfigProvider.config(CardBulletHeader, { + componentName: 'Card', +}); diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/card/card.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/card/card.jsx new file mode 100644 index 000000000..63a174647 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/card/card.jsx @@ -0,0 +1,127 @@ +/* eslint-disable valid-jsdoc */ +import React from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; +import ConfigProvider from '../config-provider'; +import BulletHeader from './bullet-header'; +import CollapseContent from './collapse-content'; +import CardMedia from './media'; +import CardActions from './actions'; +import { obj } from '../util'; + +const { pickOthers } = obj; + +/** + * Card + * @order 0 + */ +export default class Card extends React.Component { + static displayName = 'Card'; + + static propTypes = { + ...ConfigProvider.propTypes, + prefix: PropTypes.string, + rtl: PropTypes.bool, + /** + * 卡片的上的图片 / 视频 + */ + media: PropTypes.node, + /** + * 卡片的标题 + */ + title: PropTypes.node, + /** + * 卡片的副标题 + */ + subTitle: PropTypes.node, + /** + * 卡片操作组,位置在卡片底部 + */ + actions: PropTypes.node, + /** + * 是否显示标题的项目符号 + */ + showTitleBullet: PropTypes.bool, + /** + * 是否展示头部的分隔线 + */ + showHeadDivider: PropTypes.bool, + /** + * 内容区域的固定高度 + */ + contentHeight: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.number, + ]), + /** + * 标题区域的用户自定义内容 + */ + extra: PropTypes.node, + /** + * 是否开启自由模式,开启后card 将使用子组件配合使用, 设置此项后 title, subtitle, 等等属性都将失效 + */ + free: PropTypes.bool, + className: PropTypes.string, + children: PropTypes.node, + }; + + static defaultProps = { + prefix: 'next-', + free: false, + showTitleBullet: true, + showHeadDivider: true, + contentHeight: 120, + }; + + render() { + const { + prefix, + className, + title, + subTitle, + extra, + showTitleBullet, + showHeadDivider, + children, + rtl, + contentHeight, + free, + actions, + media, + } = this.props; + + const cardCls = classNames( + { + [`${prefix}card`]: true, + [`${prefix}card-free`]: free, + [`${prefix}card-show-divider`]: showHeadDivider, + [`${prefix}card-hide-divider`]: !showHeadDivider, + }, + className + ); + + const others = pickOthers(Object.keys(Card.propTypes), this.props); + + others.dir = rtl ? 'rtl' : undefined; + + return ( +
    + {media && {media}} + + {free ? ( + children + ) : ( + + {children} + + )} + {actions && {actions}} +
    + ); + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/card/collapse-content.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/card/collapse-content.jsx new file mode 100644 index 000000000..4b4dce5f6 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/card/collapse-content.jsx @@ -0,0 +1,147 @@ +import React, { Component } from 'react'; +import ReactDOM from 'react-dom'; +import PropTypes from 'prop-types'; +import Icon from '../icon'; +import Button from '../button'; +import ConfigProvider from '../config-provider'; +import nextLocale from '../locale/zh-cn'; + +/** + * Card.CollaspeContent + * @order 3 + */ +class CardCollaspeContent extends Component { + static propTypes = { + prefix: PropTypes.string, + /** + * 内容区域的固定高度 + */ + contentHeight: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.number, + ]), + locale: PropTypes.object, + children: PropTypes.node, + }; + + static defaultProps = { + prefix: 'next-', + contentHeight: 120, + locale: nextLocale.Card, + }; + + constructor(props, context) { + super(props, context); + + this.state = { + needMore: false, + expand: false, + contentHeight: 'auto', + }; + } + + componentDidMount() { + this._setNeedMore(); + this._setContentHeight(); + } + + componentDidUpdate() { + this._setContentHeight(); + } + + handleToggle = () => { + this.setState(prevState => { + return { + expand: !prevState.expand, + }; + }); + }; + + // 是否展示 More 按钮 + _setNeedMore() { + const { contentHeight } = this.props; + const childrenHeight = this._getNodeChildrenHeight(this.content); + this.setState({ + needMore: + contentHeight !== 'auto' && childrenHeight > contentHeight, + }); + } + + // 设置 Body 的高度 + _setContentHeight() { + if (this.state.expand) { + const childrenHeight = this._getNodeChildrenHeight(this.content); + this.content.style.height = `${childrenHeight}px`; // get the real height + } else { + const el = ReactDOM.findDOMNode(this.footer); + let height = this.props.contentHeight; + + if (el) { + height = height - el.getBoundingClientRect().height; + } + + this.content.style.height = `${height}px`; + } + } + + _getNodeChildrenHeight(node) { + if (!node) { + return 0; + } + + const contentChildNodes = node.childNodes; + const length = contentChildNodes.length; + + if (!length) { + return 0; + } + + const lastNode = contentChildNodes[length - 1]; + + return lastNode.offsetTop + lastNode.offsetHeight; + } + + _contentRefHandler = ref => { + this.content = ref; + }; + + saveFooter = ref => { + this.footer = ref; + }; + + render() { + const { prefix, children, locale } = this.props; + const { needMore, expand } = this.state; + + return ( +
    +
    + {children} +
    + {needMore ? ( +
    + +
    + ) : null} +
    + ); + } +} + +export default ConfigProvider.config(CardCollaspeContent, { + componentName: 'Card', +}); diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/card/content.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/card/content.jsx new file mode 100644 index 000000000..eb1814a79 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/card/content.jsx @@ -0,0 +1,44 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; +import ConfigProvider from '../config-provider'; + +/** + * Card.Content + * @order 3 + */ +class CardContent extends Component { + static propTypes = { + prefix: PropTypes.string, + /** + * 设置标签类型 + */ + component: PropTypes.elementType, + className: PropTypes.string, + }; + + static defaultProps = { + prefix: 'next-', + component: 'div', + }; + + render() { + const { + prefix, + className, + component: Component, + ...others + } = this.props; + return ( + + ); + } +} + +export default ConfigProvider.config(CardContent); diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/card/divider.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/card/divider.jsx new file mode 100644 index 000000000..a868d1b4d --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/card/divider.jsx @@ -0,0 +1,50 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; +import ConfigProvider from '../config-provider'; + +/** + * Card.Divider + * @order 4 + */ +class CardDivider extends Component { + static propTypes = { + prefix: PropTypes.string, + /** + * 设置标签类型 + */ + component: PropTypes.elementType, + /** + * 分割线是否向内缩进 + */ + inset: PropTypes.bool, + className: PropTypes.string, + }; + + static defaultProps = { + prefix: 'next-', + component: 'hr', + }; + + render() { + const { + prefix, + component: Component, + inset, + className, + ...others + } = this.props; + + const dividerClassName = classNames( + `${prefix}card-divider`, + { + [`${prefix}card-divider--inset`]: inset, + }, + className + ); + + return ; + } +} + +export default ConfigProvider.config(CardDivider); diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/card/header.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/card/header.jsx new file mode 100644 index 000000000..75322ba87 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/card/header.jsx @@ -0,0 +1,73 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; +import ConfigProvider from '../config-provider'; + +/** + * Card.Header + * @order 2 + */ +class CardHeader extends Component { + static propTypes = { + prefix: PropTypes.string, + /** + * 卡片的标题 + */ + title: PropTypes.node, + /** + * 卡片的副标题 + */ + subTitle: PropTypes.node, + /** + * 标题区域的用户自定义内容 + */ + extra: PropTypes.node, + /** + * 设置标签类型 + */ + component: PropTypes.elementType, + className: PropTypes.string, + }; + + static defaultProps = { + prefix: 'next-', + component: 'div', + }; + + render() { + const { + prefix, + title, + subTitle, + extra, + className, + component: Component, + ...others + } = this.props; + + return ( + + {extra && ( +
    {extra}
    + )} +
    + {title && ( +
    + {title} +
    + )} + {subTitle && ( +
    + {subTitle} +
    + )} +
    +
    + ); + } +} + +export default ConfigProvider.config(CardHeader); diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/card/index.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/card/index.jsx new file mode 100644 index 000000000..8fb889eed --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/card/index.jsx @@ -0,0 +1,39 @@ +import ConfigProvider from '../config-provider'; +import Card from './card'; +import CardHeader from './header'; +import CardBulletHeader from './bullet-header'; +import CardMedia from './media'; +import CardDivider from './divider'; +import CardContent from './content'; +import CollaspeContent from './collapse-content'; +import CardActions from './actions'; + +Card.Header = CardHeader; +Card.Media = CardMedia; +Card.Divider = CardDivider; +Card.Content = CardContent; +Card.Actions = CardActions; +Card.BulletHeader = CardBulletHeader; +Card.CollaspeContent = CollaspeContent; + +export default ConfigProvider.config(Card, { + transform: /* istanbul ignore next */ (props, deprecated) => { + if ('titlePrefixLine' in props) { + deprecated('titlePrefixLine', 'showTitleBullet', 'Card'); + const { titlePrefixLine, ...others } = props; + props = { showTitleBullet: titlePrefixLine, ...others }; + } + if ('titleBottomLine' in props) { + deprecated('titleBottomLine', 'showHeadDivider', 'Card'); + const { titleBottomLine, ...others } = props; + props = { showHeadDivider: titleBottomLine, ...others }; + } + if ('bodyHeight' in props) { + deprecated('bodyHeight', 'contentHeight', 'Card'); + const { bodyHeight, ...others } = props; + props = { contentHeight: bodyHeight, ...others }; + } + + return props; + }, +}); diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/card/main.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/card/main.scss new file mode 100644 index 000000000..772272113 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/card/main.scss @@ -0,0 +1,197 @@ +@import "../core/index-noreset.scss"; +@import "scss/variable"; +@import "scss/normalize"; +@import "scss/mixin"; +@import "rtl.scss"; + +#{$card-prefix} { + @include box-sizing; + + & { + min-width: $s-25; + border: $card-border-width $card-border-style $card-border-color; + border-radius: $card-corner; + box-shadow: $card-shadow; + background: $card-background; + overflow: hidden; + } + + &-head { + background: $card-header-background; + padding-left: $card-padding-lr; + padding-right: $card-padding-lr; + &-show-bullet { + #{$card-prefix}-title { + padding-left: $card-title-padding-left; + } + + #{$card-prefix}-title:before { + content: ''; + display: inline-block; + height: $card-title-bullet-height; + width: $card-title-bullet-width; + background: $card-title-bullet-color; + position: absolute; + left: 0; + top: calc(50% - #{$card-title-bullet-height} / 2); + } + } + + &-main { + position: relative; + margin-top: $card-head-main-margin-top; + margin-bottom: $card-head-main-margin-bottom; + height: $card-head-main-height; + line-height: $card-head-main-height; + } + } + + &-title { + display: inline-block; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + max-width: 80%; + height: 100%; + color: $card-title-color; + font-size: $card-title-font-size; + font-weight: $card-title-font-weight; + } + + &-subtitle { + font-size: $card-sub-title-font-size; + color: $card-sub-title-color; + padding-left: $card-sub-title-padding-left; + } + + &-extra { + position: absolute; + right: 0; + top: 0; + height: 100%; + font-size: $card-title-extra-font-size; + color: $card-title-extra-color; + } + + &-body { + padding-bottom: $card-body-padding-bottom; + padding-left: $card-padding-lr; + padding-right: $card-padding-lr; + } + + &-show-divider { + #{$card-prefix}-head-main { + border-bottom: $card-head-bottom-border-width $card-border-style $card-head-bottom-border-color; + } + + #{$card-prefix}-body { + padding-top: $card-body-show-divider-padding-top; + } + } + + &-hide-divider { + #{$card-prefix}-body { + padding-top: $card-body-hide-divider-padding-top; + } + } + + &—free { + padding: 0; + } + &-content { + overflow: hidden; + transition: all $motion-duration-standard $motion-ease; + position: relative; + } + + &-footer { + .#{$css-prefix}icon { + transition: all $motion-duration-immediately $motion-linear; + + &.expand { + transform-origin: 50% 47%; + transform: rotate(180deg); + } + } + } + + &-header { + background: $card-header-background; + padding: 0 $card-padding-lr; + margin-bottom: $card-body-show-divider-padding-top; + margin-top: $card-body-padding-bottom; + } + + &-media, + &-media > * { + display: block; + background-size: cover; + background-repeat: no-repeat; + background-position: center; + object-fit: cover; + width: 100%; + } + + &-header-titles { + overflow: hidden; + } + + &-header-extra { + float: right; + text-align: right; + & .#{$css-prefix}-btn { + margin-left: $s-3; + vertical-align: middle; + } + } + + &-header-title { + color: $card-title-color; + font-size: $card-title-font-size; + font-weight: $card-title-font-weight; + line-height: 1.5; + } + + &-header-subtitle { + font-size: $card-sub-title-font-size; + color: $card-sub-title-color; + } + + &-actions { + display: block; + padding-left: $card-padding-lr; + padding-right: $card-padding-lr; + padding-top: $card-body-show-divider-padding-top; + padding-bottom: $card-body-padding-bottom; + .#{$css-prefix}btn:not(:last-child) { + margin-right: $s-3; + vertical-align: middle; + } + } + + &-divider { + border-style: none; + width: 100%; + margin: 0; + position: relative; + &::before { + content: ''; + display: block; + border-bottom: $card-head-bottom-border-width $card-border-style $card-head-bottom-border-color; + } + } + + &-divider--inset { + padding: 0 $card-padding-lr; + } + + &-content-container { + margin-top: $card-body-show-divider-padding-top; + padding-bottom: $card-body-padding-bottom; + padding-left: $card-padding-lr; + padding-right: $card-padding-lr; + font-size: $card-content-font-size; + line-height: $card-content-line-height; + color: $card-content-color; + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/card/media.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/card/media.jsx new file mode 100644 index 000000000..637c8325e --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/card/media.jsx @@ -0,0 +1,74 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; +import ConfigProvider from '../config-provider'; +import { log } from '../util'; + +const { warning } = log; + +const MEDIA_COMPONENTS = ['video', 'audio', 'picture', 'iframe', 'img']; + +/** + * Card.Media + * @order 1 + */ +class CardMedia extends Component { + static propTypes = { + prefix: PropTypes.string, + /** + * 设置标签类型 + */ + component: PropTypes.elementType, + /** + * 背景图片地址 + */ + image: PropTypes.string, + /** + * 媒体源文件地址 + */ + src: PropTypes.string, + style: PropTypes.object, + className: PropTypes.string, + }; + + static defaultProps = { + prefix: 'next-', + component: 'div', + style: {}, + }; + + render() { + const { + prefix, + style, + className, + component: Component, + image, + src, + ...others + } = this.props; + + if (!('children' in others || Boolean(image || src))) { + warning( + 'either `children`, `image` or `src` prop must be specified.' + ); + } + + const isMediaComponent = MEDIA_COMPONENTS.indexOf(Component) !== -1; + const composedStyle = + !isMediaComponent && image + ? { backgroundImage: `url("${image}")`, ...style } + : style; + + return ( + + ); + } +} + +export default ConfigProvider.config(CardMedia); diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/card/rtl.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/card/rtl.scss new file mode 100644 index 000000000..915508654 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/card/rtl.scss @@ -0,0 +1,26 @@ +#{$card-prefix}[dir="rtl"] { + #{$card-prefix}-extra { + left: 0; + right: auto; + } + + #{$card-prefix}-title { + &:before { + right: 0; + left: auto; + } + } + + #{$card-prefix}-subtitle { + float: left; + padding-right: $card-sub-title-padding-left; + padding-left: 0; + } + + #{$card-prefix}-head-show-bullet { + #{$card-prefix}-title { + padding-left: 0; + padding-right: $card-title-padding-left; + } + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/card/scss/mixin.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/card/scss/mixin.scss new file mode 100644 index 000000000..8b45a4d9c --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/card/scss/mixin.scss @@ -0,0 +1,2 @@ +// card mixins +// -------------------------------------------------- diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/card/scss/normalize.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/card/scss/normalize.scss new file mode 100644 index 000000000..0bc6cf3c2 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/card/scss/normalize.scss @@ -0,0 +1,13 @@ +#{$card-prefix} { + *, + *:before, + *:after { + box-sizing: border-box; + } + + &, + &:before, + &:after { + box-sizing: border-box; + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/card/scss/variable.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/card/scss/variable.scss new file mode 100644 index 000000000..568690c54 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/card/scss/variable.scss @@ -0,0 +1,163 @@ +//// +/// @module card: 卡片 +/// @tag Card +/// @category component +/// @family data-display +/// @varPrefix $card- +/// @classPrefix {prefix}-card +/// @order {"size/bounding":10,"size/divider":11,"size/header":12,"size/content":13,"size/footer":14,"statement/normal":10,"statement/normal/bounding":100,"statement/normal/header":101,"statement/normal/footer":102} +//// + +$card-prefix: '.' + $css-prefix + 'card'; + +// animation +$ease-out: cubic-bezier(.23, 1, .32, 1); +$ease-in: cubic-bezier(.755, .05, .855, .06); + +/// corner +/// @namespace size/bounding +$card-corner: $corner-1 !default; + +/// padding (l, r) +/// @namespace size/bounding +$card-padding-lr: $s-4 !default; + +/// border width +/// @namespace size/bounding +$card-border-width: $line-1 !default; + +/// padding (t) +/// @namespace size/divider +$card-head-padding-bottom: $s-3 !default; + +/// border width (b) +/// @namespace size/divider +$card-head-bottom-border-width: $line-1 !default; + +/// height +/// @namespace size/header +$card-head-main-height: $s-10 !default; + +/// margin (t) +/// @namespace size/header +$card-head-main-margin-top: $s-2 !default; + +/// margin (b) +/// @namespace size/header +$card-head-main-margin-bottom: $s-zero !default; + +/// title text +/// @namespace size/header +$card-title-font-size: $font-size-subhead !default; + +/// title text weight +/// @namespace size/header +$card-title-font-weight: $font-weight-2 !default; + +/// sub title text +/// @namespace size/header +$card-sub-title-font-size: $font-size-caption !default; + +/// extra text +/// @namespace size/header +$card-title-extra-font-size: $font-size-body-1 !default; + +/// line width +/// @namespace size/header +$card-title-bullet-width: $line-3 !default; + +/// line height +/// @namespace size/header +$card-title-bullet-height: $s-4 !default; + +/// title padding (l) +/// @namespace size/header +$card-title-padding-left: $s-2 !default; + +/// sub title padding (l) +/// @namespace size/header +$card-sub-title-padding-left: $s-2 !default; + +/// padding (t) +/// @namespace size/content +$card-body-show-divider-padding-top: $s-3 !default; + +/// padding (t) +/// @namespace size/content +$card-body-hide-divider-padding-top: $s-zero !default; + +/// font size +/// @namespace size/content +$card-content-font-size: $font-size-body-1 !default; + +/// line height +/// @namespace size/content +$card-content-line-height: $font-lineheight-2 !default; + +/// padding (b) +/// @namespace size/content +$card-body-padding-bottom: $s-3 !default; + +/// more button height +/// @namespace size/footer +$card-more-btn-height: $s-4 !default; + +/// padding (t) +/// @namespace size/footer +$card-more-btn-padding-top: $s-2 !default; + +/// expand button size +/// @namespace size/footer +$card-more-btn-font-size: $font-size-body-1 !default; + +/// shadow +/// @namespace statement/normal/bounding +$card-shadow: $shadow-zero !default; + +/// border style +/// @namespace statement/normal/bounding +$card-border-style: $line-solid !default; + +/// border color +/// @namespace statement/normal/bounding +$card-border-color: $color-line1-2 !default; + +/// background +/// @namespace statement/normal/bounding +$card-background: $color-white !default; + +/// background +/// @namespace statement/normal/header +$card-header-background: $color-white !default; + +/// title color +/// @namespace statement/normal/header +$card-title-color: $color-text1-4 !default; + +/// sub title color +/// @namespace statement/normal/header +$card-sub-title-color: $color-text1-3 !default; + +/// extra color +/// @namespace statement/normal/header +$card-title-extra-color: $color-link-1 !default; + +/// line color +/// @namespace statement/normal/header +$card-title-bullet-color: $color-brand1-6 !default; + +/// color +/// @namespace statement/normal/content +$card-content-color: $color-text1-3 !default; + +/// divider color +/// @namespace statement/normal/header +$card-head-bottom-border-color: $color-line1-1 !default; + +/// expand button color +/// @namespace statement/normal/footer +$card-more-btn-color: $color-link-1 !default; + +/// background +/// @namespace statement/normal/footer +$card-more-btn-background: $color-white !default; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/card/style.js b/packages/material-parser/test/fixtures/fusion-next-component/src/card/style.js new file mode 100644 index 000000000..5f66b4c70 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/card/style.js @@ -0,0 +1,3 @@ +import '../icon/style.js'; +import '../button/style.js'; +import './main.scss'; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/cascader-select/cascader-select.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/cascader-select/cascader-select.jsx new file mode 100644 index 000000000..e2d2d573e --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/cascader-select/cascader-select.jsx @@ -0,0 +1,919 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; +import Select from '../select'; +import Cascader from '../cascader'; +import Menu from '../menu'; +import { func, obj, dom, KEYCODE } from '../util'; + +const { bindCtx } = func; +const { pickOthers } = obj; +const { getStyle } = dom; + +/** + * CascaderSelect + */ +export default class CascaderSelect extends Component { + static propTypes = { + prefix: PropTypes.string, + pure: PropTypes.bool, + className: PropTypes.string, + /** + * 选择框大小 + */ + size: PropTypes.oneOf(['small', 'medium', 'large']), + /** + * 选择框占位符 + */ + placeholder: PropTypes.string, + /** + * 是否禁用 + */ + disabled: PropTypes.bool, + /** + * 是否有下拉箭头 + */ + hasArrow: PropTypes.bool, + /** + * 是否有边框 + */ + hasBorder: PropTypes.bool, + /** + * 是否有清除按钮 + */ + hasClear: PropTypes.bool, + /** + * 自定义内联 label + */ + label: PropTypes.node, + /** + * 是否只读,只读模式下可以展开弹层但不能选 + */ + readOnly: PropTypes.bool, + /** + * 数据源,结构可参考下方说明 + */ + dataSource: PropTypes.arrayOf(PropTypes.object), + /** + * (非受控)默认值 + */ + defaultValue: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.arrayOf(PropTypes.string), + ]), + /** + * (受控)当前值 + */ + value: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.arrayOf(PropTypes.string), + ]), + /** + * 选中值改变时触发的回调函数 + * @param {String|Array} value 选中的值,单选时返回单个值,多选时返回数组 + * @param {Object|Array} data 选中的数据,包括 value 和 label,单选时返回单个值,多选时返回数组,父子节点选中关联时,同时选中,只返回父节点 + * @param {Object} extra 额外参数 + * @param {Array} extra.selectedPath 单选时选中的数据的路径 + * @param {Boolean} extra.checked 多选时当前的操作是选中还是取消选中 + * @param {Object} extra.currentData 多选时当前操作的数据 + * @param {Array} extra.checkedData 多选时所有被选中的数据 + * @param {Array} extra.indeterminateData 多选时半选的数据 + */ + onChange: PropTypes.func, + /** + * 默认展开值,如果不设置,组件内部会根据 defaultValue/value 进行自动设置 + */ + defaultExpandedValue: PropTypes.arrayOf(PropTypes.string), + /** + * 展开触发的方式 + */ + expandTriggerType: PropTypes.oneOf(['click', 'hover']), + onExpand: PropTypes.func, + /** + * 是否开启虚拟滚动 + */ + useVirtual: PropTypes.bool, + /** + * 是否多选 + */ + multiple: PropTypes.bool, + /** + * 是否选中即发生改变, 该属性仅在单选模式下有效 + */ + changeOnSelect: PropTypes.bool, + /** + * 是否只能勾选叶子项的checkbox,该属性仅在多选模式下有效 + */ + canOnlyCheckLeaf: PropTypes.bool, + /** + * 父子节点是否选中不关联 + */ + checkStrictly: PropTypes.bool, + /** + * 每列列表样式对象 + */ + listStyle: PropTypes.object, + /** + * 每列列表类名 + */ + listClassName: PropTypes.string, + /** + * 选择框单选时展示结果的自定义渲染函数 + * @param {Array} label 选中路径的文本数组 + * @return {ReactNode} 渲染在选择框中的内容 + * @default 单选时:labelPath => labelPath.join(' / ');多选时:labelPath => labelPath[labelPath.length - 1] + */ + displayRender: PropTypes.func, + /** + * 渲染 item 内容的方法 + * @param {Object} item 渲染节点的item + * @return {ReactNode} item node + */ + itemRender: PropTypes.func, + /** + * 是否显示搜索框 + */ + showSearch: PropTypes.bool, + /** + * 自定义搜索函数 + * @param {String} searchValue 搜索的关键字 + * @param {Array} path 节点路径 + * @return {Boolean} 是否匹配 + * @default 根据路径所有节点的文本值模糊匹配 + */ + filter: PropTypes.func, + /** + * 搜索结果自定义渲染函数 + * @param {String} searchValue 搜索的关键字 + * @param {Array} path 匹配到的节点路径 + * @return {ReactNode} 渲染的内容 + * @default 按照节点文本 a / b / c 的模式渲染 + */ + resultRender: PropTypes.func, + /** + * 搜索结果列表是否和选择框等宽 + */ + resultAutoWidth: PropTypes.bool, + /** + * 无数据时显示内容 + */ + notFoundContent: PropTypes.node, + /** + * 异步加载数据函数 + * @param {Object} data 当前点击异步加载的数据 + */ + loadData: PropTypes.func, + /** + * 自定义下拉框头部 + */ + header: PropTypes.node, + /** + * 自定义下拉框底部 + */ + footer: PropTypes.node, + /** + * 初始下拉框是否显示 + */ + defaultVisible: PropTypes.bool, + /** + * 当前下拉框是否显示 + */ + visible: PropTypes.bool, + /** + * 下拉框显示或关闭时触发事件的回调函数 + * @param {Boolean} visible 是否显示 + * @param {String} type 触发显示关闭的操作类型, fromTrigger 表示由trigger的点击触发; docClick 表示由document的点击触发 + */ + onVisibleChange: PropTypes.func, + /** + * 下拉框自定义样式对象 + */ + popupStyle: PropTypes.object, + /** + * 下拉框样式自定义类名 + */ + popupClassName: PropTypes.string, + /** + * 下拉框挂载的容器节点 + */ + popupContainer: PropTypes.any, + /** + * 透传到 Popup 的属性对象 + */ + popupProps: PropTypes.object, + /** + * 是否跟随滚动 + */ + followTrigger: PropTypes.bool, + /** + * 是否为预览态 + */ + isPreview: PropTypes.bool, + /** + * 预览态模式下渲染的内容 + * @param {Array} value 选择值 { label: , value:} + */ + renderPreview: PropTypes.func, + }; + + static defaultProps = { + prefix: 'next-', + pure: false, + size: 'medium', + disabled: false, + hasArrow: true, + hasBorder: true, + hasClear: false, + dataSource: [], + defaultValue: null, + expandTriggerType: 'click', + onExpand: () => {}, + useVirtual: false, + multiple: false, + changeOnSelect: false, + canOnlyCheckLeaf: false, + checkStrictly: false, + showSearch: false, + filter: (searchValue, path) => { + return path.some(item => item.label.indexOf(searchValue) > -1); + }, + resultRender: (searchValue, path) => { + const parts = []; + path.forEach((item, i) => { + const others = item.label.split(searchValue); + others.forEach((other, j) => { + if (other) { + parts.push(other); + } + if (j < others.length - 1) { + parts.push({searchValue}); + } + }); + if (i < path.length - 1) { + parts.push(' / '); + } + }); + return {parts}; + }, + resultAutoWidth: true, + notFoundContent: 'Not Found', + defaultVisible: false, + onVisibleChange: () => {}, + popupProps: {}, + }; + + constructor(props, context) { + super(props, context); + + this.state = { + value: this.normalizeValue( + 'value' in props ? props.value : props.defaultValue + ), + searchValue: '', + visible: + typeof props.visible === 'undefined' + ? props.defaultVisible + : props.visible, + }; + + bindCtx(this, [ + 'handleVisibleChange', + 'handleAfterOpen', + 'handleSelect', + 'handleChange', + 'handleClear', + 'handleRemove', + 'handleSearch', + 'getPopup', + 'saveSelectRef', + 'saveCascaderRef', + 'handleKeyDown', + ]); + } + + componentWillReceiveProps(nextProps) { + const st = {}; + + if ('value' in nextProps) { + st.value = this.normalizeValue(nextProps.value); + } + if ('visible' in nextProps) { + st.visible = nextProps.visible; + } + + if (Object.keys(st).length) { + this.setState(st); + } + } + + normalizeValue(value) { + if (value) { + if (Array.isArray(value)) { + return value; + } + + return [value]; + } + + return []; + } + + updateCache(dataSource) { + this._v2n = {}; + this._p2n = {}; + const loop = (data, prefix = '0') => + data.forEach((item, index) => { + const { value, children } = item; + const pos = `${prefix}-${index}`; + this._v2n[value] = this._p2n[pos] = { ...item, pos }; + + if (children && children.length) { + loop(children, pos); + } + }); + + loop(dataSource); + } + + flatValue(value) { + const getDepth = v => { + const pos = this.getPos(v); + if (!pos) { + return 0; + } + return pos.split('-').length; + }; + const newValue = value.slice(0).sort((prev, next) => { + return getDepth(prev) - getDepth(next); + }); + + for (let i = 0; i < newValue.length; i++) { + for (let j = 0; j < newValue.length; j++) { + if ( + i !== j && + this.isDescendantOrSelf( + this.getPos(newValue[i]), + this.getPos(newValue[j]) + ) + ) { + newValue.splice(j, 1); + j--; + } + } + } + + return newValue; + } + + isDescendantOrSelf(currentPos, targetPos) { + if (!currentPos || !targetPos) { + return false; + } + + const currentNums = currentPos.split('-'); + const targetNums = targetPos.split('-'); + + return ( + currentNums.length <= targetNums.length && + currentNums.every((num, index) => { + return num === targetNums[index]; + }) + ); + } + + getValue(pos) { + return this._p2n[pos] ? this._p2n[pos].value : null; + } + + getPos(value) { + return this._v2n[value] ? this._v2n[value].pos : null; + } + + getData(value) { + return value.map(v => this._v2n[v]); + } + + getLabelPath(data) { + const nums = data.pos.split('-'); + return nums.slice(1).reduce((ret, num, index) => { + const p = nums.slice(0, index + 2).join('-'); + ret.push(this._p2n[p].label); + return ret; + }, []); + } + + getSignleData(value) { + if (!value.length) { + return null; + } + + if (Array.isArray(value)) value = value[0]; + + const data = this._v2n[value]; + if (!data) { + return { + value, + }; + } + + const labelPath = this.getLabelPath(data); + const displayRender = + this.props.displayRender || (labels => labels.join(' / ')); + + return { + ...data, + label: displayRender(labelPath, data), + }; + } + + getMultipleData(value) { + if (!value.length) { + return null; + } + + const { checkStrictly, canOnlyCheckLeaf, displayRender } = this.props; + let data = (checkStrictly || canOnlyCheckLeaf + ? value + : this.flatValue(value) + ).map(v => this._v2n[v] || { value: v }); + + if (displayRender) { + data = data.map(item => { + if (!item.pos) { + return item; + } + const labelPath = this.getLabelPath(item); + + return { + ...item, + label: displayRender(labelPath, item), + }; + }); + } + + return data; + } + + getIndeterminate(value) { + const indeterminate = []; + + const positions = value.map(this.getPos.bind(this)); + positions.forEach(pos => { + if (!pos) { + return false; + } + const nums = pos.split('-'); + for (let i = nums.length; i > 2; i--) { + const parentPos = nums.slice(0, i - 1).join('-'); + const parentValue = this.getValue(parentPos); + if (indeterminate.indexOf(parentValue) === -1) { + indeterminate.push(parentValue); + } + } + }); + + return indeterminate; + } + + saveSelectRef(ref) { + this.select = ref; + } + + saveCascaderRef(ref) { + this.cascader = ref; + } + + completeValue(value) { + const newValue = []; + + const flatValue = this.flatValue(value).reverse(); + const ps = Object.keys(this._p2n); + for (let i = 0; i < ps.length; i++) { + for (let j = 0; j < flatValue.length; j++) { + const v = flatValue[j]; + if (this.isDescendantOrSelf(this.getPos(v), ps[i])) { + newValue.push(this.getValue(ps[i])); + ps.splice(i, 1); + i--; + break; + } + } + } + + return newValue; + } + + isLeaf(data) { + return !( + (data.children && data.children.length) || + (!!this.props.loadData && !data.isLeaf) + ); + } + + handleVisibleChange(visible, type) { + const { searchValue } = this.state; + if (!('visible' in this.props)) { + this.setState({ + visible, + }); + } + + if (!visible && searchValue) { + this.setState({ + searchValue: '', + }); + } + + if (['fromCascader', 'keyboard'].indexOf(type) !== -1 && !visible) { + this.select.focusInput(); + } + + this.props.onVisibleChange(visible, type); + } + + handleKeyDown(e) { + const { onKeyDown } = this.props; + const { visible } = this.state; + + if (onKeyDown) { + onKeyDown(e); + } + + if (!visible) { + return; + } + + switch (e.keyCode) { + case KEYCODE.UP: + case KEYCODE.DOWN: + this.cascader.setFocusValue(); + e.preventDefault(); + break; + default: + break; + } + } + + getPopup(ref) { + this.popup = ref; + if (typeof this.props.popupProps.ref === 'function') { + this.props.popupProps.ref(ref); + } + } + + handleAfterOpen() { + if (!this.popup) { + return; + } + + const { prefix, popupProps } = this.props; + const dropDownNode = this.popup + .getInstance() + .overlay.getInstance() + .getContentNode(); + const cascaderNode = dropDownNode.querySelector(`.${prefix}cascader`); + if (cascaderNode) { + this.cascaderHeight = getStyle(cascaderNode, 'height'); + } + + if (typeof popupProps.afterOpen === 'function') { + popupProps.afterOpen(); + } + } + + handleSelect(value, data) { + const { multiple, changeOnSelect } = this.props; + const { visible, searchValue } = this.state; + + if ( + !multiple && + (!changeOnSelect || this.isLeaf(data) || !!searchValue) + ) { + this.handleVisibleChange(!visible, 'fromCascader'); + } + } + + handleChange(value, data, extra) { + const { multiple, onChange } = this.props; + const { searchValue, value: stateValue } = this.state; + + const st = {}; + + if (multiple && stateValue && Array.isArray(stateValue)) { + value = [...stateValue.filter(v => !this._v2n[v]), ...value]; + } + + if (!('value' in this.props)) { + st.value = value; + } + if (!multiple && searchValue) { + st.searchValue = ''; + } + if (Object.keys(st).length) { + this.setState(st); + } + + if (onChange) { + onChange(value, data, extra); + } + + if (searchValue && this.select) { + this.select.handleSearchClear(); + } + } + + handleClear() { + // 单选时点击清空按钮 + const { hasClear, multiple, treeCheckable } = this.props; + if (hasClear && (!multiple || !treeCheckable)) { + if (!('value' in this.props)) { + this.setState({ + value: [], + }); + } + + this.props.onChange(null, null); + } + } + + handleRemove(currentData) { + const { value: currentValue } = currentData; + let value; + + const { multiple, checkStrictly, onChange } = this.props; + if (multiple) { + value = [...this.state.value]; + value.splice(value.indexOf(currentValue), 1); + + if (this.props.onChange) { + const data = this.getData(value); + const checked = false; + + if (checkStrictly) { + this.props.onChange(value, data, { + checked, + currentData, + checkedData: data, + }); + } else { + const checkedValue = this.completeValue(value); + const checkedData = this.getData(checkedValue); + const indeterminateValue = this.getIndeterminate(value); + const indeterminateData = this.getData(indeterminateValue); + this.props.onChange(value, data, { + checked, + currentData, + checkedData, + indeterminateData, + }); + } + } + } else { + value = []; + onChange(null, null); + } + + if (!('value' in this.props)) { + this.setState({ + value, + }); + } + } + + handleSearch(searchValue) { + this.setState({ + searchValue, + }); + } + + getPath(pos) { + const items = []; + + const nums = pos.split('-'); + if (nums === 2) { + items.push(this._p2n[pos]); + } else { + for (let i = 1; i < nums.length; i++) { + const p = nums.slice(0, i + 1).join('-'); + items.push(this._p2n[p]); + } + } + + return items; + } + + filterItems() { + const { + multiple, + changeOnSelect, + canOnlyCheckLeaf, + filter, + } = this.props; + const { searchValue } = this.state; + let items = Object.keys(this._p2n).map(p => this._p2n[p]); + if ((!multiple && !changeOnSelect) || (multiple && canOnlyCheckLeaf)) { + items = items.filter( + item => !item.children || !item.children.length + ); + } + + return items + .map(item => this.getPath(item.pos)) + .filter(path => filter(searchValue, path)); + } + + renderNotFound() { + const { prefix, notFoundContent } = this.props; + + return ( + + {notFoundContent} + + ); + } + + renderCascader() { + const { dataSource } = this.props; + if (dataSource.length === 0) { + return this.renderNotFound(); + } + + const { searchValue } = this.state; + let filteredPaths = []; + if (searchValue) { + filteredPaths = this.filterItems(); + if (filteredPaths.length === 0) { + return this.renderNotFound(); + } + } + + const { + multiple, + useVirtual, + changeOnSelect, + checkStrictly, + canOnlyCheckLeaf, + defaultExpandedValue, + expandTriggerType, + onExpand, + listStyle, + listClassName, + loadData, + showSearch, + resultRender, + readOnly, + itemRender, + } = this.props; + const { value } = this.state; + + const props = { + dataSource, + value, + multiple, + useVirtual, + canOnlySelectLeaf: !changeOnSelect, + checkStrictly, + canOnlyCheckLeaf, + defaultExpandedValue, + expandTriggerType, + ref: this.saveCascaderRef, + onExpand, + listStyle, + listClassName, + loadData, + itemRender, + }; + if (!readOnly) { + props.onChange = this.handleChange; + props.onSelect = this.handleSelect; + } + if (showSearch) { + props.searchValue = searchValue; + props.filteredPaths = filteredPaths; + props.resultRender = resultRender; + props.filteredListStyle = { height: this.cascaderHeight }; + } + + return ; + } + + renderPopupContent() { + const { prefix, header, footer } = this.props; + return ( +
    + {header} + {this.renderCascader()} + {footer} +
    + ); + } + + renderPreview(others) { + const { prefix, multiple, className, renderPreview } = this.props; + const { value } = this.state; + const previewCls = classNames(className, `${prefix}form-preview`); + let items = + (multiple + ? this.getMultipleData(value) + : this.getSignleData(value)) || []; + + if (!Array.isArray(items)) { + items = [items]; + } + + if (typeof renderPreview === 'function') { + return ( +
    + {renderPreview(items, this.props)} +
    + ); + } + + return ( +

    + {items.map(({ label }) => label).join(', ')} +

    + ); + } + + render() { + const { + prefix, + size, + hasArrow, + hasBorder, + hasClear, + label, + readOnly, + placeholder, + dataSource, + disabled, + multiple, + className, + showSearch, + popupStyle, + popupClassName, + popupContainer, + popupProps, + followTrigger, + isPreview, + } = this.props; + const { value, searchValue, visible } = this.state; + const others = pickOthers( + Object.keys(CascaderSelect.propTypes), + this.props + ); + + this.updateCache(dataSource); + + if (isPreview) { + return this.renderPreview(others); + } + + const popupContent = this.renderPopupContent(); + + const props = { + prefix, + className, + size, + placeholder, + disabled, + hasArrow, + hasBorder, + hasClear, + label, + readOnly, + ref: this.saveSelectRef, + autoWidth: false, + mode: multiple ? 'multiple' : 'single', + value: multiple + ? this.getMultipleData(value) + : this.getSignleData(value), + onChange: this.handleClear, + onRemove: this.handleRemove, + visible, + onVisibleChange: this.handleVisibleChange, + showSearch, + // searchValue, + onSearch: this.handleSearch, + onKeyDown: this.handleKeyDown, + popupContent, + popupStyle, + popupClassName, + popupContainer, + popupProps, + followTrigger, + }; + + if (showSearch) { + props.popupProps = { + ...popupProps, + ref: this.getPopup, + afterOpen: this.handleAfterOpen, + }; + props.autoWidth = showSearch && !!searchValue; + } + + return + ); + + // disable 无状态操作 + if (!disabled) { + childInput = this.getStateElement(childInput); + } + const cls = classnames({ + [`${prefix}checkbox-wrapper`]: true, + [className]: !!className, + checked, + disabled, + indeterminate, + [this.getStateClassName()]: true, + }); + const labelCls = `${prefix}checkbox-label`; + const type = indeterminate ? 'semi-select' : 'select'; + + if (isPreview) { + const previewCls = classnames(className, `${prefix}form-preview`); + if ('renderPreview' in this.props) { + return ( +
    + {renderPreview(checked, this.props)} +
    + ); + } + + return ( +

    + {checked && (children || label || this.state.value)} +

    + ); + } + + return ( + + ); + } +} + +export default ConfigProvider.config(Checkbox); diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/checkbox/index.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/checkbox/index.jsx new file mode 100644 index 000000000..a4898acb2 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/checkbox/index.jsx @@ -0,0 +1,6 @@ +import Checkbox from './checkbox'; +import Group from './checkbox-group'; + +Checkbox.Group = Group; + +export default Checkbox; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/checkbox/main.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/checkbox/main.scss new file mode 100644 index 000000000..cb9b10f74 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/checkbox/main.scss @@ -0,0 +1,189 @@ +@charset "UTF-8"; + +@import '../core/index-noreset'; +@import 'scss/variable'; +@import './rtl.scss'; + +/* stylelint-disable max-nesting-depth */ + +#{$checkbox-prefix}-wrapper { + @include box-sizing; + + #{$checkbox-prefix} { + display: inline-block; + position: relative; + line-height: 1; + vertical-align: middle; + } + + input[type="checkbox"] { + opacity: 0; + position: absolute; + top: 0; + left: 0; + width: $checkbox-size; + height: $checkbox-size; + margin: 0; + cursor: pointer; + } + + #{$checkbox-prefix}-inner { + display: block; + width: $checkbox-size; + height: $checkbox-size; + background: $checkbox-bg-color; + border-radius: $checkbox-border-radius; + border: $checkbox-border-width solid $checkbox-border-color; + transition: all $motion-duration-immediately $motion-linear; + text-align: left; /* 防止继承父级 */ + box-shadow: $checkbox-shadow; + /* box-sizing: content-box; */ + + > .#{$css-prefix}icon { + transform: scale(0); + position: absolute; + top: 0; + opacity: 0; + line-height: $checkbox-size; + transition: all $motion-duration-immediately $motion-linear; + color: $checkbox-checked-circle-color; + left: ($checkbox-size - $checkbox-circle-size) / 2; + @if ($checkbox-circle-size == 12) { + margin-top: 1px; + } + @include icon-size($checkbox-circle-size, 0); + } + > .#{$css-prefix}icon::before { + vertical-align: top; + margin-top: 0; + } + } + + &.checked, + &.checked.focused { + > #{$checkbox-prefix} { + > #{$checkbox-prefix}-inner { + border-color: $checkbox-checked-border-color; + background-color: $checkbox-checked-bg-color; + + &:hover, + &.hovered { + border-color: $checkbox-checked-border-color; + } + > .#{$css-prefix}icon { + opacity: 1; + transform: scale(1); + @include icon-size($checkbox-circle-size, 0); /* font-size < 12px的时候进行覆盖。 */ + } + } + } + } + + &.indeterminate, + &.indeterminate.focused { + > #{$checkbox-prefix} { + > #{$checkbox-prefix}-inner { + border-color: $checkbox-checked-border-color; + background-color: $checkbox-checked-bg-color; + + &:hover, + &.hovered { + border-color: $checkbox-checked-border-color; + } + > .#{$css-prefix}icon { + opacity: 1; + transform: scale3d(1, 1, 1); + @include icon-size($checkbox-circle-size, 0); /* font-size < 12px的时候进行覆盖。 */ + } + } + } + } + + &:not(.disabled):hover, + &.hovered, + &.focused { + > #{$checkbox-prefix} { + > #{$checkbox-prefix}-inner { + border-color: $checkbox-hovered-border-color; + background-color: $checkbox-hovered-bg-color; + } + } + #{$checkbox-prefix}-label { + cursor: pointer; + } + } + + &.indeterminate:not(.disabled):hover, + &.indeterminate:not(.disabled).hovered, + &.checked:not(.disabled):hover, + &.checked:not(.disabled).hovered { + > #{$checkbox-prefix} { + #{$checkbox-prefix}-inner { + border-color: $checkbox-checked-hovered-border-color; + background-color: $checkbox-checked-hovered-bg-color; + + > .#{$css-prefix}icon { + color: $checkbox-checked-hovered-circle-color; + opacity: 1; + } + } + } + } + + &.disabled { + input[type="checkbox"] { + cursor: not-allowed; + } + #{$checkbox-prefix}-inner { + border-color: $checkbox-disabled-border-color; + background: $checkbox-disabled-bg-color; + } + &.checked, + &.indeterminate { + #{$checkbox-prefix}-inner { + border-color: $checkbox-disabled-border-color; + background: $checkbox-disabled-bg-color; + + &:hover, &.hovered { + border-color: $checkbox-disabled-border-color; + } + + > .#{$css-prefix}icon { + color: $checkbox-disabled-circle-color; + opacity: 1; + } + } + } + #{$checkbox-prefix}-label { + color: $checkbox-disabled-label-color; + } + } +} + +#{$checkbox-prefix}-group { + #{$checkbox-prefix}-wrapper { + display: inline-block; + margin-left: 8px; + &:first-child { + margin-left: 0; + } + } + + &-ver { + #{$checkbox-prefix}-wrapper { + display: block; + margin-left: 0; + margin-right: 0; + margin-bottom: 8px; + } + } +} + +#{$checkbox-prefix}-label { + font-size: $checkbox-font-size; + color: $checkbox-label-color; + vertical-align: middle; + margin: 0; + margin-left: $checkbox-margin-left; + line-height: 1; +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/checkbox/rtl.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/checkbox/rtl.scss new file mode 100644 index 000000000..5fc69b457 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/checkbox/rtl.scss @@ -0,0 +1,12 @@ +#{$checkbox-prefix}-wrapper[dir="rtl"] { + margin-right: 8px; + margin-left: 0; + &:first-child { + margin-right: 0; + } + + > #{$checkbox-prefix}-label { + margin-right: $checkbox-margin-left; + margin-left: 0; + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/checkbox/scss/variable.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/checkbox/scss/variable.scss new file mode 100644 index 000000000..ef899fd9f --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/checkbox/scss/variable.scss @@ -0,0 +1,86 @@ +//// +/// @module checkbox: 复选框 +/// @tag checkbox +/// @category component +/// @family data-entry +/// @varPrefix $checkbox- +/// @classPrefix {prefix}-checkbox +/// @order {"size/bounding":10,"size/icon":11,"size/label":12,"statement/normal":10,"statement/normal/bounding":100,"statement/hover":11,"statement/hover/bounding":110,"statement/checked":12,"statement/checked/bounding":120,"statement/checked/icon":121,"statement/disabled":13,"statement/disabled/bounding":130,"statement/disabled/icon":131,"statement/checked hover":14,"statement/checked hover/bounding":140,"statement/checked hover/icon":141} +//// + +@charset "UTF-8"; + +$checkbox-prefix: '.#{$css-prefix}checkbox'; + +/// size +/// @namespace size/bounding +$checkbox-size: $s-4 !default; +/// radius +/// @namespace size/bounding +$checkbox-border-radius: $corner-1 !default; +/// border-width +/// @namespace size/bounding +$checkbox-border-width: $line-1 !default; + +/// size +/// @namespace size/icon +$checkbox-circle-size: $icon-xxs !default; + +/// shadow +/// @namespace size/bounding +$checkbox-shadow: $shadow-zero !default; + +/// border +/// @namespace statement/normal/bounding +$checkbox-border-color: $color-line1-3 !default; +/// border +/// @namespace statement/hover/bounding +$checkbox-hovered-border-color: $color-brand1-6 !default; +/// border +/// @namespace statement/checked/bounding +$checkbox-checked-border-color: $color-transparent !default; +/// border +/// @namespace statement/disabled/bounding +$checkbox-disabled-border-color: $color-line1-1 !default; +/// border +/// @namespace statement/checked hover/bounding +$checkbox-checked-hovered-border-color: $color-transparent !default; + +/// text +/// @namespace statement/checked/icon +$checkbox-checked-circle-color: $color-white !default; +/// text +/// @namespace statement/normal/label +$checkbox-label-color: $color-text1-4 !default; +/// text +/// @namespace statement/disabled/label +$checkbox-disabled-label-color: $color-text1-4 !default; +/// text +/// @namespace statement/disabled/icon +$checkbox-disabled-circle-color: $color-text1-1 !default; +/// text +/// @namespace statement/checked hover/icon +$checkbox-checked-hovered-circle-color: $color-white !default; + +/// background +/// @namespace statement/normal/bounding +$checkbox-bg-color: $color-white !default; +/// background +/// @namespace statement/checked/bounding +$checkbox-checked-bg-color: $color-brand1-6 !default; +/// background +/// @namespace statement/hover/bounding +$checkbox-hovered-bg-color: $color-brand1-1 !default; +/// background +/// @namespace statement/checked hover/bounding +$checkbox-checked-hovered-bg-color: $color-brand1-9 !default; +/// background +/// @namespace statement/disabled/bounding +$checkbox-disabled-bg-color: $color-fill1-1 !default; + +/// size +/// @namespace size/label +$checkbox-font-size: $font-size-body-1 !default; +/// margin(L) +/// @namespace size/label +$checkbox-margin-left: $s-1 !default; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/checkbox/style.js b/packages/material-parser/test/fixtures/fusion-next-component/src/checkbox/style.js new file mode 100644 index 000000000..05935d150 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/checkbox/style.js @@ -0,0 +1,3 @@ +import '../icon/style.js'; +import '../animate/style.js'; +import './main.scss'; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/collapse/collapse.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/collapse/collapse.jsx new file mode 100644 index 000000000..de34d4c97 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/collapse/collapse.jsx @@ -0,0 +1,259 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; +import { polyfill } from 'react-lifecycles-compat'; +import ConfigProvider from '../config-provider'; +import { func, obj } from '../util'; +import Panel from './panel'; + +/** Collapse */ +class Collapse extends React.Component { + static propTypes = { + /** + * 样式前缀 + */ + prefix: PropTypes.string, + /** + * 组件接受行内样式 + */ + style: PropTypes.object, + /** + * 使用数据模型构建 + */ + dataSource: PropTypes.array, + /** + * 默认展开keys + */ + defaultExpandedKeys: PropTypes.array, + /** + * 受控展开keys + */ + expandedKeys: PropTypes.array, + /** + * 展开状态发升变化时候的回调 + */ + onExpand: PropTypes.func, + /** + * 所有禁用 + */ + disabled: PropTypes.bool, + /** + * 扩展class + */ + className: PropTypes.string, + /** + * 手风琴模式,一次只能打开一个 + */ + accordion: PropTypes.bool, + children: PropTypes.node, + id: PropTypes.string, + rtl: PropTypes.bool, + }; + + static defaultProps = { + accordion: false, + prefix: 'next-', + onExpand: func.noop, + }; + + static contextTypes = { + prefix: PropTypes.string, + }; + + constructor(props) { + super(props); + + let expandedKeys; + if ('expandedKeys' in props) { + expandedKeys = props.expandedKeys; + } else { + expandedKeys = props.defaultExpandedKeys; + } + + this.state = { + expandedKeys: + typeof expandedKeys === 'undefined' ? [] : expandedKeys, + }; + } + + static getDerivedStateFromProps(props) { + if ('expandedKeys' in props) { + return { + expandedKeys: + typeof props.expandedKeys === 'undefined' + ? [] + : props.expandedKeys, + }; + } + return null; + } + + onItemClick(key) { + let expandedKeys = this.state.expandedKeys; + if (this.props.accordion) { + expandedKeys = String(expandedKeys[0]) === String(key) ? [] : [key]; + } else { + expandedKeys = [...expandedKeys]; + const stringKey = String(key); + const index = expandedKeys.findIndex(k => String(k) === stringKey); + const isExpanded = index > -1; + if (isExpanded) { + expandedKeys.splice(index, 1); + } else { + expandedKeys.push(key); + } + } + this.setExpandedKey(expandedKeys); + } + + genratePanelId(itemId, index) { + const { id: collapseId } = this.props; + let id; + if (itemId) { + // 优先用 item自带的id + id = itemId; + } else if (collapseId) { + // 其次用 collapseId 和 index 生成id + id = `${collapseId}-panel-${index}`; + } + return id; + } + getProps(item, index, key) { + const expandedKeys = this.state.expandedKeys; + const { title } = item; + let disabled = this.props.disabled; + + if (!disabled) { + disabled = item.disabled; + } + + let isExpanded = false; + + if (this.props.accordion) { + isExpanded = String(expandedKeys[0]) === String(key); + } else { + isExpanded = expandedKeys.some(expandedKey => { + if ( + expandedKey === null || + expandedKey === undefined || + key === null || + key === undefined + ) { + return false; + } + + if ( + expandedKey === key || + expandedKey.toString() === key.toString() + ) { + return true; + } + return false; + }); + } + + const id = this.genratePanelId(item.id, index); + return { + key, + title, + isExpanded, + disabled, + id, + onClick: disabled + ? null + : () => { + this.onItemClick(key); + if ('onClick' in item) { + item.onClick(key); + } + }, + }; + } + + getItemsByDataSource() { + const { props } = this; + const { dataSource } = props; + // 是否有dataSource.item传入过key + const hasKeys = dataSource.some(item => 'key' in item); + + return dataSource.map((item, index) => { + // 传入过key就用item.key 没传入则统一使用index为key + const key = hasKeys ? item.key : `${index}`; + return ( + + {item.content} + + ); + }); + } + + getItemsByChildren() { + // 是否有child传入过key + const allKeys = React.Children.map( + this.props.children, + child => child && child.key + ); + const hasKeys = Boolean(allKeys.length); + + return React.Children.map(this.props.children, (child, index) => { + if ( + child && + typeof child.type === 'function' && + child.type.isNextPanel + ) { + // 传入过key就用child.key 没传入则统一使用index为key + const key = hasKeys ? child.key : `${index}`; + return React.cloneElement( + child, + this.getProps(child.props, index, key) + ); + } else { + return child; + } + }); + } + + setExpandedKey(expandedKeys) { + if (!('expandedKeys' in this.props)) { + this.setState({ expandedKeys }); + } + this.props.onExpand( + this.props.accordion ? expandedKeys[0] : expandedKeys + ); + } + + render() { + const { + prefix, + className, + style, + disabled, + dataSource, + id, + rtl, + } = this.props; + const collapseClassName = classNames({ + [`${prefix}collapse`]: true, + [`${prefix}collapse-disabled`]: disabled, + [className]: Boolean(className), + }); + + const others = obj.pickOthers(Collapse.propTypes, this.props); + return ( + + ); + } +} + +export default polyfill(ConfigProvider.config(Collapse)); diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/collapse/index.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/collapse/index.jsx new file mode 100644 index 000000000..3d9094b5e --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/collapse/index.jsx @@ -0,0 +1,6 @@ +import Collapse from './collapse'; +import Panel from './panel'; + +Collapse.Panel = Panel; + +export default Collapse; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/collapse/main.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/collapse/main.scss new file mode 100644 index 000000000..9c303cf87 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/collapse/main.scss @@ -0,0 +1,119 @@ +@charset "UTF-8"; +@import "../core/index-noreset.scss"; +@import "scss/mixin"; +@import "scss/variable"; +@import "./rtl.scss"; + +/* put your code here */ +#{$collapse-prefix} { + @include box-sizing; + + border: $collapse-border-width solid $collapse-border-color; + border-radius: $collapse-border-corner; + &:focus, + & *:focus { + outline: 0; + } + + &-panel { + &:not(:first-child) { + border-top: $collapse-title-border-width solid $collapse-panel-border-color; + } + } + + #{$collapse-prefix}-panel-icon { + position: absolute; + color: $collapse-icon-color; + transition: transform $motion-duration-immediately $motion-linear; + left: $collapse-icon-margin-l; + margin-top: -2px; + + @include icon-size($collapse-icon-size, 0, 0, rotate($collapse-icon-rotation-collapsed)); + } + + &-panel-title { + position: relative; + line-height: $collapse-title-height; + background: $collapse-title-bg-color; + font-size: $collapse-title-font-size; + font-weight: $collapse-title-font-weight; + color: $collapse-title-font-color; + cursor: pointer; + padding: $collapse-title-padding-tb 0 $collapse-title-padding-tb $collapse-icon-margin-r + $collapse-icon-margin-l + $collapse-icon-size; + transition: background $motion-duration-immediately $motion-linear; + + &:hover { + background: $collapse-title-hover-bg-color; + color: $collapse-title-hover-font-color; + font-weight: $collapse-title-hover-font-weight; + + #{$collapse-prefix}-panel-icon { + color: $collapse-icon-hover-color; + } + } + } + + &-panel-content { + height: 0; + padding: 0 $collapse-content-padding-x; + background: $collapse-content-bg-color; + font-size: $collapse-content-font-size; + color: $collapse-content-color; + transition: all $motion-duration-standard $motion-ease; + opacity: 0; + } + + &-panel-expanded { + > #{$collapse-prefix}-panel-content { + display: block; + padding: $collapse-content-padding-y $collapse-content-padding-x; + height: auto; + opacity: 1; + } + } + + &-panel-hidden { + > #{$collapse-prefix}-panel-content { + overflow: hidden; + } + } + + #{$collapse-prefix}-panel-icon { + &#{$collapse-prefix}-panel-icon-expanded { + @include icon-size($collapse-icon-size, 0, 0, rotate($collapse-icon-rotation-expanded)); + } + } + + &-disabled { + border-color: $collapse-disabled-border-color; + } + + &-panel-disabled { + &:not(:first-child) { + border-color: $collapse-disabled-border-color; + } + + > #{$collapse-prefix}-panel-title { + cursor: not-allowed; + color: $collapse-title-font-disabled-color; + background: $collapse-title-disabled-bg-color; + } + + #{$collapse-prefix}-panel-icon { + color: $collapse-title-font-disabled-color; + } + + #{$collapse-prefix}-panel-title:hover { + font-weight: $collapse-title-font-weight; + + #{$collapse-prefix}-panel-icon { + color: $collapse-title-font-disabled-color; + } + } + + &:hover { + color: $collapse-title-font-disabled-color; + background: $collapse-title-disabled-bg-color; + } + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/collapse/panel.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/collapse/panel.jsx new file mode 100644 index 000000000..52b927aa5 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/collapse/panel.jsx @@ -0,0 +1,115 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; +import ConfigProvider from '../config-provider'; +import Icon from '../icon'; +import { func, KEYCODE } from '../util'; + +/** Collapse.Panel */ +class Panel extends React.Component { + static propTypes = { + /** + * 样式类名的品牌前缀 + */ + prefix: PropTypes.string, + /** + * 子组件接受行内样式 + */ + style: PropTypes.object, + children: PropTypes.any, + isExpanded: PropTypes.bool, + /** + * 是否禁止用户操作 + */ + disabled: PropTypes.bool, + /** + * 标题 + */ + title: PropTypes.node, + /** + * 扩展class + */ + className: PropTypes.string, + onClick: PropTypes.func, + id: PropTypes.string, + }; + + static defaultProps = { + prefix: 'next-', + isExpanded: false, + onClick: func.noop, + }; + + static isNextPanel = true; // + + onKeyDown = e => { + const { keyCode } = e; + if (keyCode === KEYCODE.SPACE) { + const { onClick } = this.props; + e.preventDefault(); + onClick && onClick(e); + } + }; + render() { + const { + title, + children, + className, + isExpanded, + disabled, + style, + prefix, + onClick, + id, + ...others + } = this.props; + + const cls = classNames({ + [`${prefix}collapse-panel`]: true, + [`${prefix}collapse-panel-hidden`]: !isExpanded, + [`${prefix}collapse-panel-expanded`]: isExpanded, + [`${prefix}collapse-panel-disabled`]: disabled, + [className]: className, + }); + + const iconCls = classNames({ + [`${prefix}collapse-panel-icon`]: true, + [`${prefix}collapse-panel-icon-expanded`]: isExpanded, + }); + + // 为了无障碍 需要添加两个id + const headingId = id ? `${id}-heading` : undefined; + const regionId = id ? `${id}-region` : undefined; + return ( +
    +
    +
    +
    + {children} +
    +
    + ); + } +} + +export default ConfigProvider.config(Panel); diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/collapse/rtl.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/collapse/rtl.scss new file mode 100644 index 000000000..571f0fdd0 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/collapse/rtl.scss @@ -0,0 +1,12 @@ +#{$collapse-prefix}[dir=rtl] { + #{$collapse-prefix}-panel-title { + padding: $collapse-title-padding-tb $collapse-icon-margin-r + $collapse-icon-margin-l + $collapse-icon-size $collapse-title-padding-tb 0; + } + + #{$collapse-prefix}-panel-icon { + left: inherit; + right: $collapse-icon-margin-l; + + @include icon-size($collapse-icon-size, 0, 0, rotate($collapse-icon-rotation-collapsed-rtl)); + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/collapse/scss/mixin.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/collapse/scss/mixin.scss new file mode 100644 index 000000000..9f44090c9 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/collapse/scss/mixin.scss @@ -0,0 +1 @@ +@charset "UTF-8"; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/collapse/scss/variable.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/collapse/scss/variable.scss new file mode 100644 index 000000000..0ac19b014 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/collapse/scss/variable.scss @@ -0,0 +1,108 @@ +@charset "UTF-8"; + +//// +/// @module collapse: 折叠面板 +/// @tag Collapse +/// @category component +/// @family data-display +/// @varPrefix $collapse- +/// @classPrefix {prefix}-collapse +/// @order {"size/bounding":10,"size/divider":11,"size/title":12,"size/icon":13,"size/content":14,"statement/normal":10,"statement/normal/title":100,"statement/normal/icon":101,"statement/normal/content":102,"statement/divider":11,"statement/disabled":12,"statement/disabled/title":120,"statement/hover":13,"statement/hover/title":130} +//// + +$collapse-prefix: '.#{$css-prefix}collapse'; + +// collapse variables +// -------------------------------------------------- + +// Common + +/// border +/// @namespace size/bounding +$collapse-border-width: $line-1 !default; + +/// corner +/// @namespace size/bounding +$collapse-border-corner: $corner-1 !default; +/// border +/// @namespace statement/normal +$collapse-border-color: $color-line1-2 !default; +/// border +/// @namespace statement/divider +$collapse-panel-border-color: $color-line1-2 !default; +/// border +/// @namespace statement/disabled +$collapse-disabled-border-color: $color-line1-1 !default; + +/// border +/// @namespace size/divider +$collapse-title-border-width: $line-1 !default; +/// line height +/// @namespace size/title +$collapse-title-height: $s-5 !default; +/// background +/// @namespace statement/normal/title +$collapse-title-bg-color: $color-fill1-2 !default; +/// background +/// @namespace statement/hover/title +$collapse-title-hover-bg-color: $color-fill1-3 !default; +/// background +/// @namespace statement/disabled/title +$collapse-title-disabled-bg-color: $color-fill1-2 !default; +/// text +/// @namespace statement/normal/title +$collapse-title-font-color: $color-text1-4 !default; +/// text +/// @namespace statement/disabled/title +$collapse-title-font-disabled-color: $color-text1-1 !default; +/// text +/// @namespace statement/hover/title +$collapse-title-hover-font-color: $color-text1-4 !default; +/// text +/// @namespace size/title +$collapse-title-font-size: $font-size-body-2 !default; +/// weight +/// @namespace size/title +$collapse-title-font-weight: $font-weight-2 !default; +/// weight +/// @namespace statement/hover/title +$collapse-title-hover-font-weight: $font-weight-2 !default; +/// padding(t,b) +/// @namespace size/title +$collapse-title-padding-tb: $s-2 !default; + +/// size +/// @namespace size/icon +$collapse-icon-size: $icon-xxs !default; +/// color +/// @namespace statement/normal/icon +$collapse-icon-color: $color-text1-4 !default; +/// color +/// @namespace statement/hover/icon +$collapse-icon-hover-color: $color-text1-4 !default; +/// margin (r) +/// @namespace size/icon +$collapse-icon-margin-r: $s-2 !default; +/// margin (l) +/// @namespace size/icon +$collapse-icon-margin-l: $s-3 !default; + +$collapse-icon-rotation-collapsed: 90deg; +$collapse-icon-rotation-expanded: 180deg; +$collapse-icon-rotation-collapsed-rtl: $collapse-icon-rotation-collapsed * 3; + +/// background +/// @namespace statement/normal/content +$collapse-content-bg-color: $color-white !default; +/// padding (l,r) +/// @namespace size/content +$collapse-content-padding-x: $s-4 !default; +/// padding (t,b) +/// @namespace size/content +$collapse-content-padding-y: $s-3 !default; +/// text +/// @namespace size/content +$collapse-content-font-size: $font-size-body-1 !default; +/// text +/// @namespace statement/normal/content +$collapse-content-color: $color-text1-3 !default; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/collapse/style.js b/packages/material-parser/test/fixtures/fusion-next-component/src/collapse/style.js new file mode 100644 index 000000000..65cfc7e39 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/collapse/style.js @@ -0,0 +1,2 @@ +import '../icon/style.js'; +import './main.scss'; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/config-provider/cache.js b/packages/material-parser/test/fixtures/fusion-next-component/src/config-provider/cache.js new file mode 100644 index 000000000..c165bab91 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/config-provider/cache.js @@ -0,0 +1,42 @@ +class Cache { + constructor() { + this._root = null; + this._store = new Map(); + } + + empty() { + return this._store.size === 0; + } + + has(key) { + return this._store.has(key); + } + + get(key, defaultValue) { + const res = this.has(key) ? this._store.get(key) : this.root(); + return typeof res === 'undefined' || res === null ? defaultValue : res; + } + + add(key, value) { + if (this.empty()) { + this._root = key; + } + this._store.set(key, value); + } + + update(key, value) { + if (this.has(key)) { + this._store.set(key, value); + } + } + + remove(key) { + this._store.delete(key); + } + + root() { + return this._store.get(this._root); + } +} + +export default Cache; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/config-provider/config.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/config-provider/config.jsx new file mode 100644 index 000000000..af1cd1084 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/config-provider/config.jsx @@ -0,0 +1,254 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import hoistNonReactStatic from 'hoist-non-react-statics'; +import { obj, log } from '../util'; +import getContextProps from './get-context-props'; +import ErrorBoundary from './error-boundary'; + +const { shallowEqual } = obj; + +function getDisplayName(Component) { + return Component.displayName || Component.name || 'Component'; +} + +let globalLocales; +let currentGlobalLanguage = 'zh-cn'; +let currentGlobalLocale = {}; +let currentGlobalRtl; + +export function initLocales(locales) { + globalLocales = locales; + + if (locales) { + currentGlobalLocale = locales[currentGlobalLanguage]; + + if (typeof currentGlobalRtl !== 'boolean') { + currentGlobalRtl = currentGlobalLocale && currentGlobalLocale.rtl; + } + } +} + +export function setLanguage(language) { + if (globalLocales) { + currentGlobalLanguage = language; + currentGlobalLocale = globalLocales[language]; + + if (typeof currentGlobalRtl !== 'boolean') { + currentGlobalRtl = currentGlobalLocale && currentGlobalLocale.rtl; + } + } +} + +export function setLocale(locale) { + currentGlobalLocale = { + ...(globalLocales ? globalLocales[currentGlobalLanguage] : {}), + ...locale, + }; + + if (typeof currentGlobalRtl !== 'boolean') { + currentGlobalRtl = currentGlobalLocale && currentGlobalLocale.rtl; + } +} + +export function setDirection(dir) { + currentGlobalRtl = dir === 'rtl'; +} + +export function getLocale() { + return currentGlobalLocale; +} + +export function getLanguage() { + return currentGlobalLanguage; +} + +export function getDirection() { + return currentGlobalRtl; +} + +export function config(Component, options = {}) { + // 非 forwardRef 创建的 class component + if ( + obj.isClassComponent(Component) && + Component.prototype.shouldComponentUpdate === undefined + ) { + // class component: 通过定义 shouldComponentUpdate 改写成 pure component, 有refs + Component.prototype.shouldComponentUpdate = function shouldComponentUpdate( + nextProps, + nextState + ) { + if (this.props.pure) { + return ( + !shallowEqual(this.props, nextProps) || + !shallowEqual(this.state, nextState) + ); + } + + return true; + }; + } + + class ConfigedComponent extends React.Component { + static propTypes = { + ...(Component.propTypes || {}), + prefix: PropTypes.string, + locale: PropTypes.object, + pure: PropTypes.bool, + rtl: PropTypes.bool, + device: PropTypes.oneOf(['tablet', 'desktop', 'phone']), + popupContainer: PropTypes.any, + errorBoundary: PropTypes.oneOfType([ + PropTypes.bool, + PropTypes.object, + ]), + }; + static contextTypes = { + ...(Component.contextTypes || {}), + nextPrefix: PropTypes.string, + nextLocale: PropTypes.object, + nextPure: PropTypes.bool, + nextRtl: PropTypes.bool, + nextWarning: PropTypes.bool, + nextDevice: PropTypes.oneOf(['tablet', 'desktop', 'phone']), + nextPopupContainer: PropTypes.any, + nextErrorBoundary: PropTypes.oneOfType([ + PropTypes.bool, + PropTypes.object, + ]), + }; + + constructor(props, context) { + super(props, context); + + this._getInstance = this._getInstance.bind(this); + this._deprecated = this._deprecated.bind(this); + } + + _getInstance(ref) { + this._instance = ref; + + if (this._instance && options.exportNames) { + options.exportNames.forEach(name => { + const field = this._instance[name]; + if (typeof field === 'function') { + this[name] = field.bind(this._instance); + } else { + this[name] = field; + } + }); + } + } + + _deprecated(...args) { + if (this.context.nextWarning !== false) { + log.deprecated(...args); + } + } + + getInstance() { + return this._instance; + } + + render() { + const { + prefix, + locale, + pure, + rtl, + device, + popupContainer, + errorBoundary, + ...others + } = this.props; + const { + nextPrefix, + nextLocale = {}, + nextPure, + nextRtl, + nextDevice, + nextPopupContainer, + nextErrorBoundary, + } = this.context; + + const displayName = + options.componentName || getDisplayName(Component); + const contextProps = getContextProps( + { + prefix, + locale, + pure, + device, + popupContainer, + rtl, + errorBoundary, + }, + { + nextPrefix, + nextLocale: { ...currentGlobalLocale, ...nextLocale }, + nextPure, + nextDevice, + nextPopupContainer, + nextRtl: + typeof nextRtl === 'boolean' + ? nextRtl + : currentGlobalRtl === true + ? true + : undefined, + nextErrorBoundary, + }, + displayName + ); + + // errorBoundary is only for + const newContextProps = [ + 'prefix', + 'locale', + 'pure', + 'rtl', + 'device', + 'popupContainer', + ].reduce((ret, name) => { + if (typeof contextProps[name] !== 'undefined') { + ret[name] = contextProps[name]; + } + return ret; + }, {}); + + if ('pure' in newContextProps && newContextProps.pure) { + log.warning( + 'pure of ConfigProvider is deprecated, use Function Component or React.PureComponent' + ); + } + + const newOthers = options.transform + ? options.transform(others, this._deprecated) + : others; + + const content = ( + + ); + + const { open, ...othersBoundary } = contextProps.errorBoundary; + + return open ? ( + {content} + ) : ( + content + ); + } + } + + ConfigedComponent.displayName = `Config(${getDisplayName(Component)})`; + + hoistNonReactStatic(ConfigedComponent, Component); + + return ConfigedComponent; +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/config-provider/consumer.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/config-provider/consumer.jsx new file mode 100644 index 000000000..668a703b9 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/config-provider/consumer.jsx @@ -0,0 +1,73 @@ +import PropTypes from 'prop-types'; + +/** + * Creates an object with the same values as object and keys + * generated by running each own enumerable string keyed property + * of object thru iteratee. + * @param {Object} obj + * @param {Function} fn + * @return {Object} + */ +const mapKeys = (obj, fn) => { + const result = {}; + for (const key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key)) { + const value = obj[key]; + const newKey = fn(key, value); + result[newKey] = value; + } + } + + return result; +}; + +/** + * Replace specific key with prefix `next` + * and lowercase first character of the result. + * @param {String} key + * @return {String} + */ +const replaceKey = key => + key.replace(/^(next)([A-Z])/, (match, p1, p2) => p2.toLowerCase()); + +/** + * @param {Object} source + * @return {Object} + */ +const transformContext = source => mapKeys(source, replaceKey); + +/** + * Consumer + * @param {Object} prop + * @param {Object} context + */ +const Consumer = ({ children }, context) => + typeof children === 'function' ? children(transformContext(context)) : null; + +/** + * PropTypes + * @type {Object} + * @static + */ +Consumer.propTypes = { + // Render context as function + // Function(context: object): ReactElement + children: PropTypes.func, +}; + +/** + * ContextTypes (legacy context) + * @type {Object} + * @static + */ +Consumer.contextTypes = { + nextPrefix: PropTypes.string, + nextLocale: PropTypes.object, + nextPure: PropTypes.bool, + newRtl: PropTypes.bool, + nextWarning: PropTypes.bool, + nextDevice: PropTypes.oneOf(['tablet', 'desktop', 'phone']), + nextPopupContainer: PropTypes.any, +}; + +export default Consumer; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/config-provider/error-boundary.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/config-provider/error-boundary.jsx new file mode 100644 index 000000000..27041de87 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/config-provider/error-boundary.jsx @@ -0,0 +1,63 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +DefaultUI.propTypes = { + error: PropTypes.object, + errorInfo: PropTypes.object, +}; + +function DefaultUI() { + return ''; +} + +export default class ErrorBoundary extends React.Component { + static propTypes = { + children: PropTypes.element, + /** + * 捕获错误后的自定义处理, 比如埋点上传 + * @param {Object} error 错误 + * @param {Object} errorInfo 错误详细信息 + */ + afterCatch: PropTypes.func, + /** + * 捕获错误后的展现 自定义组件 + * @param {Object} error 错误 + * @param {Object} errorInfo 错误详细信息 + * @returns {Element} 捕获错误后的处理 + */ + fallbackUI: PropTypes.func, + }; + + constructor(props) { + super(props); + this.state = { error: null, errorInfo: null }; + } + + componentDidCatch(error, errorInfo) { + this.setState({ + error: error, + errorInfo: errorInfo, + }); + + const { afterCatch } = this.props; + + if ('afterCatch' in this.props && typeof afterCatch === 'function') { + this.props.afterCatch(error, errorInfo); + } + } + + render() { + const { fallbackUI: FallbackUI = DefaultUI } = this.props; + + if (this.state.errorInfo) { + return ( + + ); + } + // Normally, just render children + return this.props.children; + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/config-provider/get-context-props.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/config-provider/get-context-props.jsx new file mode 100644 index 000000000..4aca7dc10 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/config-provider/get-context-props.jsx @@ -0,0 +1,89 @@ +import zhCN from '../locale/zh-cn.js'; +import { obj } from '../util'; +/** + * + * @param {Object|Boolean} input + * @returns {Object} typeof obj.open === 'boolean' + */ +const parseBoundary = input => { + let obj; + if (input === undefined || input === null) { + return {}; + } else if (typeof input === 'boolean') { + obj = { open: input }; + } else { + obj = { open: true, ...input }; + } + + return obj; +}; + +export default function getContextProps(props, context, displayName) { + const { + prefix, + locale, + pure, + rtl, + device, + popupContainer, + errorBoundary, + } = props; + const { + nextPrefix, + nextLocale, + nextPure, + nextWarning, + nextRtl, + nextDevice, + nextPopupContainer, + nextErrorBoundary, + } = context; + + const newPrefix = prefix || nextPrefix; + + let localeFromContext; + if (nextLocale) { + localeFromContext = nextLocale[displayName]; + if (localeFromContext) { + localeFromContext.momentLocale = nextLocale.momentLocale; + } + } + + let newLocale; + if (locale) { + newLocale = obj.deepMerge( + {}, + zhCN[displayName], + localeFromContext, + locale + ); + } else if (localeFromContext) { + newLocale = obj.deepMerge({}, zhCN[displayName], localeFromContext); + } + + const newPure = typeof pure === 'boolean' ? pure : nextPure; + const newRtl = typeof rtl === 'boolean' ? rtl : nextRtl; + + // ProtoType of [nextE|e]rrorBoundary can be one of [boolean, object] + // but typeof newErrorBoundary === 'object' + // newErrorBoundary should always have the key 'open', which indicates ErrorBoundary on or off + const newErrorBoundary = { + ...parseBoundary(nextErrorBoundary), + ...parseBoundary(errorBoundary), + }; + + if (!('open' in newErrorBoundary)) { + newErrorBoundary.open = false; + } + + return { + prefix: newPrefix, + locale: newLocale, + pure: newPure, + rtl: newRtl, + warning: nextWarning, + device: device || nextDevice || undefined, + popupContainer: popupContainer || nextPopupContainer, + errorBoundary: newErrorBoundary, + }; +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/config-provider/index.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/config-provider/index.jsx new file mode 100644 index 000000000..523f91313 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/config-provider/index.jsx @@ -0,0 +1,230 @@ +import { Component, Children } from 'react'; +import PropTypes from 'prop-types'; +import { polyfill } from 'react-lifecycles-compat'; +import getContextProps from './get-context-props'; +import { + config, + initLocales, + setLanguage, + setLocale, + setDirection, + getLocale, + getLanguage, + getDirection, +} from './config'; +import Consumer from './consumer'; +import ErrorBoundary from './error-boundary'; +import Cache from './cache'; + +const childContextCache = new Cache(); + +const setMomentLocale = locale => { + let moment; + try { + moment = require('moment'); + } catch (e) { + // ignore + } + + if (moment && locale) { + moment.locale(locale.momentLocale); + } +}; +/** + * ConfigProvider + * @propsExtends false + */ +class ConfigProvider extends Component { + static propTypes = { + /** + * 样式类名的品牌前缀 + */ + prefix: PropTypes.string, + /** + * 国际化文案对象,属性为组件的 displayName + */ + locale: PropTypes.object, + /** + * 是否开启错误捕捉 errorBoundary + * 如需自定义参数,请传入对象 对象接受参数列表如下: + * + * fallbackUI `Function(error?: {}, errorInfo?: {}) => Element` 捕获错误后的展示 + * afterCatch `Function(error?: {}, errorInfo?: {})` 捕获错误后的行为, 比如埋点上传 + */ + errorBoundary: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]), + /** + * 是否开启 Pure Render 模式,会提高性能,但是也会带来副作用 + */ + pure: PropTypes.bool, + /** + * 是否在开发模式下显示组件属性被废弃的 warning 提示 + */ + warning: PropTypes.bool, + /** + * 是否开启 rtl 模式 + */ + rtl: PropTypes.bool, + /** + * 设备类型,针对不同的设备类型组件做出对应的响应式变化 + */ + device: PropTypes.oneOf(['tablet', 'desktop', 'phone']), + /** + * 组件树 + */ + children: PropTypes.any, + /** + * 指定浮层渲染的父节点, 可以为节点id的字符串,也可以返回节点的函数 + */ + popupContainer: PropTypes.any, + }; + + static defaultProps = { + warning: true, + errorBoundary: false, + }; + + static childContextTypes = { + nextPrefix: PropTypes.string, + nextLocale: PropTypes.object, + nextPure: PropTypes.bool, + nextRtl: PropTypes.bool, + nextWarning: PropTypes.bool, + nextDevice: PropTypes.oneOf(['tablet', 'desktop', 'phone']), + nextPopupContainer: PropTypes.any, + nextErrorBoundary: PropTypes.oneOfType([ + PropTypes.bool, + PropTypes.object, + ]), + }; + + /** + * 传入组件,生成受 ConfigProvider 控制的 HOC 组件 + * @param {Component} Component 组件类 + * @param {Object} options 可选项 + * @returns {Component} HOC + */ + static config = (Component, options) => { + return config(Component, options); + }; + + /** + * 传入组件的 props 和 displayName,得到和 childContext 计算过的包含有 preifx/locale/pure 的对象,一般用于通过静态方法生成脱离组件树的组件 + * @param {Object} props 组件的 props + * @param {String} displayName 组件的 displayName + * @returns {Object} 新的 context props + */ + static getContextProps = (props, displayName) => { + return getContextProps( + props, + childContextCache.root() || {}, + displayName + ); + }; + + static initLocales = initLocales; + static setLanguage = setLanguage; + static setLocale = setLocale; + static setDirection = setDirection; + static getLanguage = getLanguage; + static getLocale = getLocale; + static getDirection = getDirection; + static Consumer = Consumer; + static ErrorBoundary = ErrorBoundary; + + static getContext = () => { + const { + nextPrefix, + nextLocale, + nextPure, + nextRtl, + nextWarning, + nextDevice, + nextPopupContainer, + nextErrorBoundary, + } = childContextCache.root() || {}; + + return { + prefix: nextPrefix, + locale: nextLocale, + pure: nextPure, + rtl: nextRtl, + warning: nextWarning, + device: nextDevice, + popupContainer: nextPopupContainer, + errorBoundary: nextErrorBoundary, + }; + }; + + constructor(...args) { + super(...args); + childContextCache.add( + this, + Object.assign( + {}, + childContextCache.get(this, {}), + this.getChildContext() + ) + ); + + this.state = { + locale: this.props.locale, + }; + } + + getChildContext() { + const { + prefix, + locale, + pure, + warning, + rtl, + device, + popupContainer, + errorBoundary, + } = this.props; + + return { + nextPrefix: prefix, + nextLocale: locale, + nextPure: pure, + nextRtl: rtl, + nextWarning: warning, + nextDevice: device, + nextPopupContainer: popupContainer, + nextErrorBoundary: errorBoundary, + }; + } + + static getDerivedStateFromProps(nextProps, prevState) { + if (nextProps.locale !== prevState.locale) { + setMomentLocale(nextProps.locale); + + return { + locale: nextProps.locale, + }; + } + + return null; + } + + componentDidUpdate() { + childContextCache.add( + this, + Object.assign( + {}, + childContextCache.get(this, {}), + this.getChildContext() + ) + ); + } + + componentWillUnmount() { + childContextCache.remove(this); + } + + render() { + return Children.only(this.props.children); + } +} + +export default polyfill(ConfigProvider); diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/config-provider/main.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/config-provider/main.scss new file mode 100644 index 000000000..e69de29bb diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/config-provider/style.js b/packages/material-parser/test/fixtures/fusion-next-component/src/config-provider/style.js new file mode 100644 index 000000000..f1ad40f46 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/config-provider/style.js @@ -0,0 +1 @@ +import './main.scss'; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/core/base/_accessibility.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/core/base/_accessibility.scss new file mode 100644 index 000000000..a06264c30 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/core/base/_accessibility.scss @@ -0,0 +1,11 @@ +.#{$css-prefix}sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; + margin: -1px; +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/core/base/_normalize.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/core/base/_normalize.scss new file mode 100755 index 000000000..15748fdbe --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/core/base/_normalize.scss @@ -0,0 +1,449 @@ +/* stylelint-disable */ + +/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */ + +/* Document +========================================================================== */ + +/** +* 1. Correct the line height in all browsers. +* 2. Prevent adjustments of font size after orientation changes in +* IE on Windows Phone and in iOS. +*/ + +html { + line-height: 1.15; /* 1 */ + -ms-text-size-adjust: 100%; /* 2 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/* Sections + ========================================================================== */ + +/** +* Remove the margin in all browsers (opinionated). +*/ + +body { + margin: 0; +} + +/** +* Add the correct display in IE 9-. +*/ + +article, +aside, +footer, +header, +nav, +section { + display: block; +} + +/** +* Correct the font size and margin on `h1` elements within `section` and +* `article` contexts in Chrome, Firefox, and Safari. +*/ + +h1 { + font-size: 2em; + margin: .67em 0; +} + +/* Grouping content + ========================================================================== */ + +/** +* Add the correct display in IE 9-. +* 1. Add the correct display in IE. +*/ + +figcaption, +figure, +main { /* 1 */ + display: block; +} + +/** +* Add the correct margin in IE 8. +*/ + +figure { + margin: 1em 40px; +} + +/** +* 1. Add the correct box sizing in Firefox. +* 2. Show the overflow in Edge and IE. +*/ + +hr { + box-sizing: content-box; /* 1 */ + height: 0; /* 1 */ + overflow: visible; /* 2 */ +} + +/** +* 1. Correct the inheritance and scaling of font size in all browsers. +* 2. Correct the odd `em` font sizing in all browsers. +*/ + +pre { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/* Text-level semantics + ========================================================================== */ + +/** +* 1. Remove the gray background on active links in IE 10. +* 2. Remove gaps in links underline in iOS 8+ and Safari 8+. +*/ + +a { + background-color: transparent; /* 1 */ + -webkit-text-decoration-skip: objects; /* 2 */ +} + +/** +* 1. Remove the bottom border in Chrome 57- and Firefox 39-. +* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. +*/ + +abbr[title] { + border-bottom: none; /* 1 */ + text-decoration: underline; /* 2 */ + text-decoration: underline dotted; /* 2 */ +} + +/** +* Prevent the duplicate application of `bolder` by the next rule in Safari 6. +*/ + +b, +strong { + font-weight: inherit; +} + +/** +* Add the correct font weight in Chrome, Edge, and Safari. +*/ + +b, +strong { + font-weight: bolder; +} + +/** +* 1. Correct the inheritance and scaling of font size in all browsers. +* 2. Correct the odd `em` font sizing in all browsers. +*/ + +code, +kbd, +samp { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/** +* Add the correct font style in Android 4.3-. +*/ + +dfn { + font-style: italic; +} + +/** +* Add the correct background and color in IE 9-. +*/ + +mark { + background-color: #FF0; + color: #000; +} + +/** +* Add the correct font size in all browsers. +*/ + +small { + font-size: 80%; +} + +/** +* Prevent `sub` and `sup` elements from affecting the line height in +* all browsers. +*/ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -.25em; +} + +sup { + top: -.5em; +} + +/* Embedded content + ========================================================================== */ + +/** +* Add the correct display in IE 9-. +*/ + +audio, +video { + display: inline-block; +} + +/** +* Add the correct display in iOS 4-7. +*/ + +audio:not([controls]) { + display: none; + height: 0; +} + +/** +* Remove the border on images inside links in IE 10-. +*/ + +img { + border-style: none; +} + +/** +* Hide the overflow in IE. +*/ + +svg:not(:root) { + overflow: hidden; +} + +/* Forms + ========================================================================== */ + +/** +* 1. Change the font styles in all browsers (opinionated). +* 2. Remove the margin in Firefox and Safari. +*/ + +button, +input, +optgroup, +select, +textarea { + font-family: sans-serif; /* 1 */ + font-size: 100%; /* 1 */ + line-height: 1.15; /* 1 */ + margin: 0; /* 2 */ +} + +/** +* Show the overflow in IE. +* 1. Show the overflow in Edge. +*/ + +button, +input { /* 1 */ + overflow: visible; +} + +/** +* Remove the inheritance of text transform in Edge, Firefox, and IE. +* 1. Remove the inheritance of text transform in Firefox. +*/ + +button, +select { /* 1 */ + text-transform: none; +} + +/** +* 1. Prevent a WebKit bug where (2) destroys native `audio` and `video` +* controls in Android 4. +* 2. Correct the inability to style clickable types in iOS and Safari. +*/ + +button, +html [type="button"], /* 1 */ +[type="reset"], +[type="submit"] { + -webkit-appearance: button; /* 2 */ +} + +/** +* Remove the inner border and padding in Firefox. +*/ + +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + border-style: none; + padding: 0; +} + +/** +* Restore the focus styles unset by the previous rule. +*/ + +button:-moz-focusring, +[type="button"]:-moz-focusring, +[type="reset"]:-moz-focusring, +[type="submit"]:-moz-focusring { + outline: 1px dotted ButtonText; +} + +/** +* Correct the padding in Firefox. +*/ + +fieldset { + padding: .35em .75em .625em; +} + +/** +* 1. Correct the text wrapping in Edge and IE. +* 2. Correct the color inheritance from `fieldset` elements in IE. +* 3. Remove the padding so developers are not caught out when they zero out +* `fieldset` elements in all browsers. +*/ + +legend { + box-sizing: border-box; /* 1 */ + color: inherit; /* 2 */ + display: table; /* 1 */ + max-width: 100%; /* 1 */ + padding: 0; /* 3 */ + white-space: normal; /* 1 */ +} + +/** +* 1. Add the correct display in IE 9-. +* 2. Add the correct vertical alignment in Chrome, Firefox, and Opera. +*/ + +progress { + display: inline-block; /* 1 */ + vertical-align: baseline; /* 2 */ +} + +/** +* Remove the default vertical scrollbar in IE. +*/ + +textarea { + overflow: auto; +} + +/** +* 1. Add the correct box sizing in IE 10-. +* 2. Remove the padding in IE 10-. +*/ + +[type="checkbox"], +[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** +* Correct the cursor style of increment and decrement buttons in Chrome. +*/ + +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** +* 1. Correct the odd appearance in Chrome and Safari. +* 2. Correct the outline style in Safari. +*/ + +[type="search"] { + -webkit-appearance: textfield; /* 1 */ + outline-offset: -2px; /* 2 */ +} + +/** +* Remove the inner padding and cancel buttons in Chrome and Safari on macOS. +*/ + +[type="search"]::-webkit-search-cancel-button, +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** +* 1. Correct the inability to style clickable types in iOS and Safari. +* 2. Change font properties to `inherit` in Safari. +*/ + +::-webkit-file-upload-button { + -webkit-appearance: button; /* 1 */ + font: inherit; /* 2 */ +} + +/* Interactive + ========================================================================== */ + +/* +* Add the correct display in IE 9-. +* 1. Add the correct display in Edge, IE, and Firefox. +*/ + +details, /* 1 */ +menu { + display: block; +} + +/* +* Add the correct display in all browsers. +*/ + +summary { + display: list-item; +} + +/* Scripting + ========================================================================== */ + +/** +* Add the correct display in IE 9-. +*/ + +canvas { + display: inline-block; +} + +/** +* Add the correct display in IE. +*/ + +template { + display: none; +} + +/* Hidden + ========================================================================== */ + +/** +* Add the correct display in IE 10-. +*/ + +[hidden] { + display: none; +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/core/base/_reset.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/core/base/_reset.scss new file mode 100644 index 000000000..40cc843bd --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/core/base/_reset.scss @@ -0,0 +1,38 @@ +*, +*:before, +*:after { + box-sizing: border-box; +} + +ul, +ol { + list-style: none; + margin: 0; + padding: 0; +} + +li { + margin-left: 0; +} + +hr { + border: 0 $line-solid $color-line1-2; + border-top-width: $line-1; +} + +a { + text-decoration: none; + &:link { + color: $color-link-1; + } + &:visited { + color: $color-link-2; + } + &:hover { + color: $color-link-3; + } + &:active { + text-decoration: underline; + color: $color-link-3; + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/core/base/_typography.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/core/base/_typography.scss new file mode 100755 index 000000000..c79640440 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/core/base/_typography.scss @@ -0,0 +1,143 @@ +@if $font-custom-name != "" { + @font-face { + font-family: "#{$font-custom-name}"; + src: url("#{$font-custom-path}#{$font-name-thin}.eot"); + src: + url("#{$font-custom-path}#{$font-name-thin}.eot?#iefix") format("embedded-opentype"), + url("#{$font-custom-path}#{$font-name-thin}.woff2") format("woff2"), + url("#{$font-custom-path}#{$font-name-thin}.woff") format("woff"), + url("#{$font-custom-path}#{$font-name-thin}.ttf") format("truetype"); + font-weight: 200; + } + + @font-face { + font-family: "#{$font-custom-name}"; + src: url("#{$font-custom-path}#{$font-name-light}.eot"); + src: + url("#{$font-custom-path}#{$font-name-light}.eot?#iefix") format("embedded-opentype"), + url("#{$font-custom-path}#{$font-name-light}.woff2") format("woff2"), + url("#{$font-custom-path}#{$font-name-light}.woff") format("woff"), + url("#{$font-custom-path}#{$font-name-light}.ttf") format("truetype"); + font-weight: 300; + } + + @font-face { + font-family: "#{$font-custom-name}"; + src: url("#{$font-custom-path}#{$font-name-regular}.eot"); + src: + url("#{$font-custom-path}#{$font-name-regular}.eot?#iefix") format("embedded-opentype"), + url("#{$font-custom-path}#{$font-name-regular}.woff2") format("woff2"), + url("#{$font-custom-path}#{$font-name-regular}.woff") format("woff"), + url("#{$font-custom-path}#{$font-name-regular}.ttf") format("truetype"); + font-weight: 400; + } + + @font-face { + font-family: "#{$font-custom-name}"; + src: url("#{$font-custom-path}#{$font-name-medium}.eot"); + src: + url("#{$font-custom-path}#{$font-name-medium}.eot?#iefix") format("embedded-opentype"), + url("#{$font-custom-path}#{$font-name-medium}.woff2") format("woff2"), + url("#{$font-custom-path}#{$font-name-medium}.woff") format("woff"), + url("#{$font-custom-path}#{$font-name-medium}.ttf") format("truetype"); + font-weight: 500; + } + + @font-face { + font-family: "#{$font-custom-name}"; + src: url("#{$font-custom-path}#{$font-name-bold}.eot"); + src: + url("#{$font-custom-path}#{$font-name-bold}.eot?#iefix") format("embedded-opentype"), + url("#{$font-custom-path}#{$font-name-bold}.woff2") format("woff2"), + url("#{$font-custom-path}#{$font-name-bold}.woff") format("woff"), + url("#{$font-custom-path}#{$font-name-bold}.ttf") format("truetype"); + font-weight: 700; + } +} + +html { + font-size: 100%; + // font-smooth has been removed from this specification, Works only on Mac OS X platform. + // -webkit-font-smoothing: antialiased; +} + +body { + font-family: $font-family-base; + font-size: $font-size-body-1; + line-height: $font-lineheight-base; + color: $color-text1-4; +} + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; +} + +h1 a, +h2 a, +h3 a, +h4 a, +h5 a, +h6 a { + font-weight: inherit; +} + +h1 { + margin-bottom: $font-size-headline * $typo-margin-bottom; + font-size: $font-size-headline; + font-weight: $font-weight-medium; + line-height: 36px; +} + +h2 { + margin-bottom: $font-size-title * $typo-margin-bottom; + font-size: $font-size-title; + font-weight: $font-weight-medium; + line-height: 30px; +} + +h3 { + margin-bottom: $font-size-subhead * $typo-margin-bottom; + font-size: $font-size-subhead; + font-weight: $font-weight-2; + line-height: 24px; +} + +h4 { + margin-bottom: $font-size-subhead * $typo-margin-bottom; + font-size: $font-size-subhead; + font-weight: $font-weight-2; + line-height: 24px; +} + +h5 { + margin-bottom: $font-size-body-1 * $typo-margin-bottom; + font-size: $font-size-body-2; + font-weight: $font-weight-2; + line-height: 24px; +} + +h6 { + margin-bottom: $font-size-body-2 * $typo-margin-bottom; + font-size: $font-size-body-1; + font-weight: $font-weight-medium; + line-height: 20px; +} + +p { + margin-bottom: $font-size-body-1 * $typo-margin-bottom; + font-size: $font-size-body-1; + font-weight: $font-weight-2; + line-height: 20px; +} + +strong { + font-weight: 500; +} + +small { + font-size: 75%; +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/core/form-element.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/core/form-element.scss new file mode 100644 index 000000000..6c8942cf3 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/core/form-element.scss @@ -0,0 +1,48 @@ +@import "./index-noreset.scss"; +@import "../input/scss/variable.scss"; +@import "../input/scss/mixin.scss"; +@import "../form/scss/mixin.scss"; + +.demo-body table { + width: 100%; +} + +.next-form-element.next-input, +.next-form-element.next-select .next-input, +.next-form-element.next-time-picker .next-input { + &.next-small { + @include input-size($form-element-small-height, $input-s-padding, $form-element-small-font-size, $input-s-label-padding-left, $input-s-icon-padding-right); + @include input-icon-size($form-element-small-icon-size); + @include input-border-radius($form-element-small-corner); + } + + &.next-medium { + @include input-size($form-element-medium-height, $input-m-padding, $form-element-medium-font-size, $input-m-label-padding-left, $input-m-icon-padding-right); + @include input-icon-size($form-element-medium-icon-size); + @include input-border-radius($form-element-medium-corner); + } + + &.next-large { + @include input-size($form-element-large-height, $input-l-padding, $form-element-large-font-size, $input-l-label-padding-left, $input-l-icon-padding-right); + @include input-icon-size($form-element-large-icon-size); + @include input-border-radius($form-element-large-corner); + } + + // stylelint-disable-next-line + .next-select-values input { + padding-left: 0; + padding-right: 0; + } +} + +.next-form-element { + &.next-small { + @include form-preview($form-element-small-preview-font-size, $form-element-small-preview-height); + } + &.next-medium { + @include form-preview($form-element-medium-preview-font-size, $form-element-medium-preview-height); + } + &.next-large { + @include form-preview($form-element-large-preview-font-size, $form-element-large-preview-height); + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/core/index-noreset.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/core/index-noreset.scss new file mode 100755 index 000000000..5ab218151 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/core/index-noreset.scss @@ -0,0 +1,24 @@ +// Mixin & Function +@import "./util/_function.scss"; +@import "./util/_mixin.scss"; + +// Style +@import "./style/_global.scss"; +@import "./style/_size.scss"; +@import "./style/_color.scss"; +@import "./style/_corner.scss"; +@import "./style/_font.scss"; +@import "./style/_line.scss"; +@import "./style/_shadow.scss"; +@import "./style/_motion.scss"; + +// Icon +@import "./style/_icon.scss"; + +// Utility +@import "./utility/_form-element.scss"; +@import "./utility/_popup.scss"; +@import "./utility/_mask.scss"; + +// Accessibility +@import "./base/_accessibility.scss"; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/core/index.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/core/index.scss new file mode 100755 index 000000000..a3667cc75 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/core/index.scss @@ -0,0 +1 @@ +@import "./index-noreset.scss"; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/core/mask.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/core/mask.scss new file mode 100644 index 000000000..a66f28972 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/core/mask.scss @@ -0,0 +1,21 @@ +@import "./index-noreset.scss"; + +.demo-body table { + width: 100%; +} + +// stylelint-disable-next-line +.demo.pc .demo-group > .wrap > div.demo-item { + display: block; +} + +.next-overlay-wrapper .next-overlay-backdrop, +.next-dialog-container { + position: absolute; +} + +// stylelint-disable-next-line +.next-overlay-wrapper.opened .next-overlay-backdrop.next-mask { + background: $mask-background; + opacity: $mask-opacity; +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/core/popup.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/core/popup.scss new file mode 100644 index 000000000..90d624a33 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/core/popup.scss @@ -0,0 +1,13 @@ +@import "./index-noreset.scss"; + +.demo-body table { + width: 100%; +} + +.next-popup.next-menu, +.next-popup.next-time-picker-body, +.next-popup .next-tree-select-dropdown { + border: $popup-local-border-width $popup-local-border-style $popup-local-border-color; + border-radius: $popup-local-corner; + box-shadow: $popup-local-shadow; +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/core/reset.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/core/reset.scss new file mode 100644 index 000000000..87e2ca861 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/core/reset.scss @@ -0,0 +1,6 @@ +@import "./index-noreset.scss"; +// Base +@import "./base/_normalize.scss"; +@import "./base/_reset.scss"; +@import "./base/_typography.scss"; + diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_color.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_color.scss new file mode 100644 index 000000000..d6e4cb153 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_color.scss @@ -0,0 +1,300 @@ +//// +/// @module color: 颜色 +/// @type Color +/// @category style +//// + + +// ----------- 品牌主色 ----------- // + +/// brand1-1 +/// @group brand +/// @semantic 浅 +/// @export +$color-brand1-1: #DEE8FF !default; +/// brand1-6 +/// @group brand +/// @semantic 常规 +/// @export +$color-brand1-6: #5584FF !default; +/// brand1-9 +/// @group brand +/// @semantic 深 +/// @export +$color-brand1-9: #3E71F7 !default; + +// ----------- 功能色 ----------- // + +// 成功 + +/// success-1 +/// @group function +/// @semantic 浅 +/// @export +$color-success-1: #E4FDDA !default; +/// success-2 +/// @group function +/// @semantic 常规 +/// @export +$color-success-2: #CDF2BE !default; +/// success-3 +/// @group function +/// @semantic 深 +/// @export +$color-success-3: #46BC15 !default; +/// success-4 +/// @group function +/// @semantic 重 +/// @export +$color-success-4: #41A716 !default; + +// 提示 + +/// notice-1 +/// @group function +/// @semantic 浅 +/// @export +$color-notice-1: #E3F2FD !default; +/// notice-2 +/// @group function +/// @semantic 常规 +/// @export +$color-notice-2: #BAD9FF !default; +/// notice-3 +/// @group function +/// @semantic 深 +/// @export +$color-notice-3: #4494F9 !default; +/// notice-4 +/// @group function +/// @semantic 重 +/// @export +$color-notice-4: #2E7DE0 !default; + +// 警告 + +/// warning-1 +/// @group function +/// @semantic 浅 +/// @export +$color-warning-1: #FFF3E0 !default; +/// warning-2 +/// @group function +/// @semantic 常规 +/// @export +$color-warning-2: #FFE6BD !default; +/// warning-3 +/// @group function +/// @semantic 深 +/// @export +$color-warning-3: #FF9300 !default; +/// warning-4 +/// @group function +/// @semantic 重 +/// @export +$color-warning-4: #EB7E10 !default; + +// 错误 + +/// error-1 +/// @group function +/// @semantic 浅 +/// @export +$color-error-1: #FFECE4 !default; +/// error-2 +/// @group function +/// @semantic 常规 +/// @export +$color-error-2: #FFC8B2 !default; +/// error-3 +/// @group function +/// @semantic 深 +/// @export +$color-error-3: #FF3000 !default; +/// error-4 +/// @group function +/// @semantic 重 +/// @export +$color-error-4: #E72B00 !default; + +// 帮助 + +/// help-1 +/// @group function +/// @semantic 浅 +/// @export +$color-help-1: #E3FFF8 !default; +/// help-2 +/// @group function +/// @semantic 常规 +/// @export +$color-help-2: #C0ECE2 !default; +/// help-3 +/// @group function +/// @semantic 深 +/// @export +$color-help-3: #01C1B2 !default; +/// help-4 +/// @group function +/// @semantic 重 +/// @export +$color-help-4: #01A79A !default; + +// 链接 + +/// link-1 +/// @group function +/// @semantic 默认 +/// @export +$color-link-1: #5584FF !default; +/// link-2 +/// @group function +/// @semantic 已访问 +/// @export +$color-link-2: #5584FF !default; +/// link-3 +/// @group function +/// @semantic 鼠标滑过 +/// @export +$color-link-3: #3E71F7 !default; + +// 其它 + +/// other-1 +/// @group function +/// @export +$color-other-1: #FFEB3B !default; + +/// other-2 +/// @group function +/// @export +$color-other-2: #FCCC12 !default; + +/// other-3 +/// @group function +/// @export +$color-other-3: #EABB06 !default; + +// ----------- 中立色 ----------- // + +// 预设 + +/// white +/// @semantic 纯白 +/// @export +$color-white: #FFFFFF; +/// black +/// @semantic 纯黑 +/// @export +$color-black: #000000; +/// transparent +/// @export +$color-transparent: transparent; + +// 线条 + +/// line1-1 +/// @group neutural +/// @semantic 浅 +/// @export +$color-line1-1: #E6E7EB !default; +/// line1-2 +/// @group neutural +/// @semantic 常规 +/// @export +$color-line1-2: #DCDEE3 !default; +/// line1-3 +/// @group neutural +/// @semantic 深 +/// @export +$color-line1-3: #C4C6CF !default; +/// line1-4 +/// @group neutural +/// @semantic 重 +/// @export +$color-line1-4: #A0A2AD !default; + +// 填充 + +/// fill1-1 +/// @group neutural +/// @semantic 浅 +/// @export +$color-fill1-1: #F7F8FA !default; +/// fill1-2 +/// @group neutural +/// @semantic 常规 +/// @export +$color-fill1-2: #F2F3F7 !default; +/// fill1-3 +/// @group neutural +/// @semantic 深 +/// @export +$color-fill1-3: #EBECF0 !default; +/// fill1-4 +/// @group neutural +/// @semantic 重 +/// @export +$color-fill1-4: #E2E4E8 !default; + +// 文字 + +/// text1-1 +/// @group neutural +/// @semantic 禁用 +/// @export +$color-text1-1: #CCCCCC !default; +/// text1-2 +/// @group neutural +/// @semantic 水印/提示 +/// @export +$color-text1-2: #999999 !default; +/// text1-3 +/// @group neutural +/// @semantic 正文/标题 +/// @export +$color-text1-3: #666666 !default; +/// text1-4 +/// @group neutural +/// @semantic 正文/标题 +/// @export +$color-text1-4: #333333 !default; + + + +// ----------- 数据色 ----------- // + +// 数据序列 + +/// data1-1 +/// @group data +/// @export +$color-data1-1: #00DCCD !default; +/// data1-2 +/// @group data +/// @export +$color-data1-2: #506FED !default; +/// data1-3 +/// @group data +/// @export +$color-data1-3: #AE66FC !default; +/// data1-4 +/// @group data +/// @export +$color-data1-4: #FF445F !default; +/// data1-5 +/// @group data +/// @export +$color-data1-5: #FF934D !default; +/// data1-6 +/// @group data +/// @export +$color-data1-6: #FFD74D !default; +/// data1-7 +/// @group data +/// @export +$color-data1-7: #4DDE6D !default; +/// data1-8 +/// @group data +/// @export +$color-data1-8: #18B1F7 !default; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_corner.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_corner.scss new file mode 100644 index 000000000..5dcf34d74 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_corner.scss @@ -0,0 +1,51 @@ +//// +/// @module corner: 边角 +/// @category style +//// + + +// Corner 预定义圆角尺寸 +// 根据 Alibaba Base DPL(BASE DPL)设计规范实现 +// 圆角是用一段与角的两边相切的圆弧 +// 规则: x == y, 所有方向阴影的 blur 值, 透明度, 颜色都应该相同 +// 类型: Right Angle(直角), Rounded(圆角) +// ------------------------------- + +/// corner-1 +/// @semantic 常规圆角 +/// @export +/// @type Length +$corner-1: 3px !default; + +/// corner-2 +/// @semantic 大圆角 +/// @export +/// @type Length +$corner-2: 6px !default; + +/// corner-3 +/// @semantic 超大圆角 +/// @export +/// @type Length +$corner-3: 20px !default; + +/// corner-circle +/// @semantic 圆形 +/// @export +/// @unconfigurable +$corner-circle: 50% !default; + +/// corner-semicircle +/// @semantic 圆形 +/// @export +/// @unconfigurable +$corner-semicircle: 500px !default; + +/// corner-zero +/// @semantic 直角 +/// @export +/// @unconfigurable +$corner-zero: 0 !default; + +// ----------- patch ----------- // +$corner-right-angle: $corner-zero; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_font.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_font.scss new file mode 100644 index 000000000..d90e84df7 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_font.scss @@ -0,0 +1,177 @@ +@import "../util/_mixin.scss"; + +//// +/// @module font: 字体 +/// @type String +/// @category style +/// @export +//// + +// Font & Typography +// 根据 Alibaba Base DPL(BASE DPL) 设计规范实现 +// 字体主要解决的是内容可读性以及信息的层级表达,同时选择不同的字体来传达不同的设计风格的统一性和整体性,从而在阅读的舒适性上达到平衡。 +// ------------------------------- + +$font-custom-path: "//i.alicdn.com/artascope-font/20160419204543/font/" !default; +$font-custom-name: Roboto !default; +$font-name-thin: roboto-thin !default; +$font-name-light: roboto-light !default; +$font-name-regular: roboto-regular !default; +$font-name-medium: roboto-medium !default; +$font-name-bold: roboto-bold !default; +$font-name-bolder: roboto-bolder !default; +$font-lineheight-base: 1.2857142; + +$font-face-name-default: "#{$font-custom-name}"; +$font-face-url-default: "#{$font-custom-path}#{$font-name-thin}.eot"; + +// ------------------- font-face ------------------- // + +$font-face1-name: $font-face-name-default !default; +$font-face1-url: $font-face-url-default !default; +$font-face2-name: $font-face-name-default !default; +$font-face2-url: $font-face-url-default !default; +$font-face3-name: $font-face-name-default !default; +$font-face3-url: $font-face-url-default !default; +@include font-face-handler($font-face1-name, $font-face1-url); +@include font-face-handler($font-face2-name, $font-face2-url); +@include font-face-handler($font-face3-name, $font-face3-url); + +// ------------------- font-family ------------------- // + +/// family +/// @semantic 字体 +/// @export +$font-family-base: Roboto, "Helvetica Neue", Helvetica, Tahoma, Arial, "PingFang SC", "Microsoft YaHei" !default; + +$font-family-en: Roboto, "Helvetica Neue", Helvetica, Tahoma, Arial !default; +$font-family-zh: "Microsoft YaHei", SimSun, Arial !default !default; + +// ------------------- font-weight ------------------- // + +/// thin +/// @semantic Ultra light(Thin) +/// @group weight +/// @export weight +$font-weight-1: lighter !default; +/// extra light +/// @semantic Extra Light +/// @group weight +/// @export weight +$font-weight-thin: 200 !default; +/// light +/// @semantic Light +/// @group weight +/// @export weight +$font-weight-light: 300 !default; +/// normal +/// @semantic Regular(Normal) +/// @group weight +/// @export weight +$font-weight-2: normal !default; +/// medium +/// @semantic Medium +/// @group weight +/// @export weight +$font-weight-medium: 500 !default; +/// semi bold +/// @semantic Semi Bold +/// @group weight +/// @export weight +$font-weight-semi-bold: 600 !default; +/// bold +/// @semantic Bold +/// @group weight +/// @export weight +$font-weight-3: bold !default; +/// extra bold +/// @semantic Extra Bold +/// @group weight +/// @export weight +$font-weight-extra-bold: 800 !default; +/// heavy +/// @semantic Ultra Bold(Heavy) +/// @group weight +/// @export weight +$font-weight-ultra-bold: 900 !default; + +$font-weight-bolder: bolder !default; + +// ------------------- font-size ------------------- // + +/// display-3 +/// @semantic 运营标题-大 +/// @group size +/// @export size +$font-size-display-3: 56px !default; + +/// display-2 +/// @semantic 运营标题-中 +/// @group size +/// @export size +$font-size-display-2: 48px !default; + +/// display-1 +/// @semantic 运营标题-小 +/// @group size +/// @export size +$font-size-display-1: 36px !default; + +/// headline +/// @semantic 标题-大 +/// @group size +/// @export size +$font-size-headline: 24px !default; + +/// title +/// @semantic 标题-中 +/// @group size +/// @export size +$font-size-title: 20px !default; + +/// subhead +/// @semantic 标题-小 +/// @group size +/// @export size +$font-size-subhead: 16px !default; + +/// body-2 +/// @semantic 正文-强调 +/// @group size +/// @export size +$font-size-body-2: 14px !default; + +/// body-1 +/// @semantic 正文-常规 +/// @group size +/// @export size +$font-size-body-1: 12px !default; + +/// caption +/// @semantic 水印文本 +/// @group size +/// @export size +$font-size-caption: 12px !default; + +// ------------------- line-height ------------------- // + +/// lineheight-1 +/// @semantic 密集 +/// @group lineheight +/// @export lineheight +/// @type Number +$font-lineheight-1: 1.3 !default; + +/// lineheight-2 +/// @semantic 常规 +/// @group lineheight +/// @export lineheight +/// @type Number +$font-lineheight-2: 1.5 !default; + +/// lineheight-3 +/// @semantic 宽松 +/// @group lineheight +/// @export lineheight +/// @type Number +$font-lineheight-3: 1.7 !default; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_global.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_global.scss new file mode 100644 index 000000000..b5be48bb7 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_global.scss @@ -0,0 +1,38 @@ +//// +/// @module global: 全局基础样式 +/// @category style +//// + +/// 全局命名空间前缀 +/// @unconfigurable +$class-prefix: ".next" !default; +$css-prefix: "#{str-slice($class-prefix, 2)}-" !default; + +/// language +/// @semantic 语言变量 +/// @export +/// @unconfigurable +$language: "zh-cn" !default; + +// Typography +$typo-margin-bottom: .5; + +// Z-Indexes +// [...] +// ------------------------------- +$z-pane: 89 !default; +$z-menu: 99 !default; +$z-select: 109 !default; +$z-dialog: 199 !default; +$z-balloon: 299 !default; +$z-loading-panel: 399 !default; +$z-tour-user: 499 !default; +$z-tour-new: 599 !default; +$z-dialog-login: 699 !default; +$z-msg: 999 !default; + +$prefix-for-webkit: true !default; +$prefix-for-mozilla: true !default; +$prefix-for-microsoft: true !default; +$prefix-for-opera: true !default; +$prefix-for-spec: true !default; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_icon.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_icon.scss new file mode 100644 index 000000000..3781fec2e --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_icon.scss @@ -0,0 +1,373 @@ +//// +/// @module icon: 图标 +/// @type String +/// @category style +//// + +// Icon +// 根据 Alibaba Base DPL 设计实现 + +/// icon font path 字体路径 +$icon-font-path: "//at.alicdn.com/t/font_515771_7u6frotlpa6" !default; + +/// icon font name 自定义的icon font 名称 +$icon-font-name: "icon" !default; + +$icon-font-family: #{to-upper-case(str-slice($css-prefix, 1, 1))}#{str-slice($css-prefix, 2, str-length($css-prefix) - 1)}Icon !default; + +$icon-prefix: #{$css-prefix}icon !default; + +// ------------------- 图标尺寸 ---------------------- // + +/// icon-xxs +/// @group size +/// @export size +$icon-xxs: $s-2 !default; + +/// icon-xs +/// @group size +/// @export size +$icon-xs: $s-3 !default; + +/// icon-s +/// @group size +/// @export size +$icon-s: $s-4 !default; + +/// icon-m +/// @group size +/// @export size +$icon-m: $s-5 !default; + +/// icon-l +/// @group size +/// @export size +$icon-l: $s-6 !default; + +/// icon-xl +/// @group size +/// @export size +$icon-xl: $s-8 !default; + +/// icon-xxl +/// @group size +/// @export size +$icon-xxl: $s-12 !default; + +/// icon-xxxl +/// @group size +/// @export size +$icon-xxxl: $s-16 !default; + +// ------------------- 图标 unicode 值 ---------------------- // +/// icon-content-smile +/// @group type +/// @export type +/// @unconfigurable +$icon-content-smile: "\e65f" !default; + +/// icon-content-cry +/// @group type +/// @export type +/// @unconfigurable +$icon-content-cry: "\e65d" !default; + +/// icon-content-success +/// @group type +/// @export type +/// @unconfigurable +$icon-content-success: "\e60a" !default; + +/// icon-content-warning +/// @group type +/// @export type +/// @unconfigurable +$icon-content-warning: "\e60b" !default; + +/// icon-content-prompt +/// @group type +/// @export type +/// @unconfigurable +$icon-content-prompt: "\e60c" !default; + +/// icon-content-error +/// @group type +/// @export type +/// @unconfigurable +$icon-content-error: "\e60d" !default; + +/// icon-content-help +/// @group type +/// @export type +/// @unconfigurable +$icon-content-help: "\e673" !default; + +/// icon-content-clock +/// @group type +/// @export type +/// @unconfigurable +$icon-content-clock: "\e621" !default; + +/// icon-content-success-filling +/// @group type +/// @export type +/// @unconfigurable +$icon-content-success-filling: "\e63a" !default; + +/// icon-content-delete-filling +/// @group type +/// @export type +/// @unconfigurable +$icon-content-delete-filling: "\e623" !default; + +/// icon-content-favorites-filling +/// @group type +/// @export type +/// @unconfigurable +$icon-content-favorites-filling: "\e60e" !default; + +/// icon-content-add +/// @group type +/// @export type +/// @unconfigurable +$icon-content-add: "\e655" !default; + +/// icon-content-minus +/// @group type +/// @export type +/// @unconfigurable +$icon-content-minus: "\e601" !default; + +/// icon-content-arrow-up +/// @group type +/// @export type +/// @unconfigurable +$icon-content-arrow-up: "\e625" !default; + +/// icon-content-arrow-down +/// @group type +/// @export type +/// @unconfigurable +$icon-content-arrow-down: "\e63d" !default; + +/// icon-content-arrow-left +/// @group type +/// @export type +/// @unconfigurable +$icon-content-arrow-left: "\e61d" !default; + +/// icon-content-arrow-right +/// @group type +/// @export type +/// @unconfigurable +$icon-content-arrow-right: "\e619" !default; + +/// icon-content-arrow-double-left +/// @group type +/// @export type +/// @unconfigurable +$icon-content-arrow-double-left: "\e659" !default; + +/// icon-content-arrow-double-right +/// @group type +/// @export type +/// @unconfigurable +$icon-content-arrow-double-right: "\e65e" !default; + +/// icon-content-switch +/// @group type +/// @export type +/// @unconfigurable +$icon-content-switch: "\e6b3" !default; + +/// icon-content-sorting +/// @group type +/// @export type +/// @unconfigurable +$icon-content-sorting: "\e634" !default; + +/// icon-content-descending +/// @group type +/// @export type +/// @unconfigurable +$icon-content-descending: "\e61f" !default; + +/// icon-content-ascending +/// @group type +/// @export type +/// @unconfigurable +$icon-content-ascending: "\e61e" !default; + +/// icon-content-select +/// @group type +/// @export type +/// @unconfigurable +$icon-content-select: "\e632" !default; + +/// icon-content-semi-select +/// @group type +/// @export type +/// @unconfigurable +$icon-content-semi-select: "\e633" !default; + +/// icon-content-loading +/// @group type +/// @export type +/// @unconfigurable +$icon-content-loading: "\e646" !default; + +/// icon-content-search +/// @group type +/// @export type +/// @unconfigurable +$icon-content-search: "\e656" !default; + +/// icon-content-close +/// @group type +/// @export type +/// @unconfigurable +$icon-content-close: "\e626" !default; + +/// icon-content-ellipsis +/// @group type +/// @export type +/// @unconfigurable +$icon-content-ellipsis: "\e654" !default; + +/// icon-content-picture +/// @group type +/// @export type +/// @unconfigurable +$icon-content-picture: "\e631" !default; + +/// icon-content-calendar +/// @group type +/// @export type +/// @unconfigurable +$icon-content-calendar: "\e607" !default; + +/// icon-content-ashbin +/// @group type +/// @export type +/// @unconfigurable +$icon-content-ashbin: "\e639" !default; + +/// icon-content-upload +/// @group type +/// @export type +/// @unconfigurable +$icon-content-upload: "\e7ee" !default; + +/// icon-content-download +/// @group type +/// @export type +/// @unconfigurable +$icon-content-download: "\e628" !default; + +/// icon-content-set +/// @group type +/// @export type +/// @unconfigurable +$icon-content-set: "\e683" !default; + +/// icon-content-edit +/// @group type +/// @export type +/// @unconfigurable +$icon-content-edit: "\e63b" !default; + +/// icon-content-refresh +/// @group type +/// @export type +/// @unconfigurable +$icon-content-refresh: "\e677" !default; + +/// icon-content-filter +/// @group type +/// @export type +/// @unconfigurable +$icon-content-filter: "\e627" !default; + +/// icon-content-attachment +/// @group type +/// @export type +/// @unconfigurable +$icon-content-attachment: "\e665" !default; + +/// icon-content-account +/// @group type +/// @export type +/// @unconfigurable +$icon-content-account: "\e608" !default; + +/// icon-content-email +/// @group type +/// @export type +/// @unconfigurable +$icon-content-email: "\e605" !default; + +/// icon-content-atm +/// @group type +/// @export type +/// @unconfigurable +$icon-content-atm: "\e606" !default; + +/// icon-content-copy +/// @group type +/// @export type +/// @unconfigurable +$icon-content-copy: "\e60f" !default; + +/// icon-content-toggle-left +/// @group type +/// @export type +/// @unconfigurable +$icon-content-toggle-left: "\e602" !default; + +/// icon-content-toggle-right +/// @group type +/// @export type +/// @unconfigurable +$icon-content-toggle-right: "\e603" !default; + +/// icon-content-eye +/// @group type +/// @export type +/// @unconfigurable +$icon-content-eye: "\e611" !default; + +/// icon-content-eye-close +/// @group type +/// @export type +/// @unconfigurable +$icon-content-eye-close: "\e600" !default; + +/// icon-content-unlock +/// @group type +/// @export type +/// @unconfigurable +$icon-content-unlock: "\e615" !default; + +/// icon-content-lock +/// @group type +/// @export type +/// @unconfigurable +$icon-content-lock: "\e617" !default; + +/// icon-content-exit +/// @group type +/// @export type +/// @unconfigurable +$icon-content-exit: "\e616" !default; + +/// icon-content-chart-bar +/// @group type +/// @export type +/// @unconfigurable +$icon-content-chart-bar: "\e612" !default; + +/// icon-content-chart-pie +/// @group type +/// @export type +/// @unconfigurable +$icon-content-chart-pie: "\e613" !default; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_line.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_line.scss new file mode 100644 index 000000000..62ba31763 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_line.scss @@ -0,0 +1,61 @@ +//// +/// @module line: 线条 +/// @type String +/// @category style +//// + +// Line +// 根据 Alibaba Base DPL(BASE DPL) +// 边框主要用于呈现元素内容区域,显示元素的操作区域;线主要用于管理和分隔列表和页面布局内的内容。以便让内容生成更好的视觉效果及空间感。 + +// ************************** 公共变量, 供开发者和设计师引用 *********************** // + +/// line-zero +/// @semantic 无 +/// @export size +/// @group size +/// @type Length +/// @unconfigurable +$line-zero: 0 !default; + +/// line-1 +/// @semantic 细 +/// @export size +/// @group size +/// @type Length +$line-1: 1px !default; + +/// line-2 +/// @semantic 常规 +/// @export size +/// @group size +/// @type Length +$line-2: 2px !default; + +/// line-3 +/// @semantic 粗 +/// @export size +/// @group size +/// @type Length +$line-3: 3px !default; + +/// line-solid +/// @export style +/// @group style +/// @unconfigurable +$line-solid: solid !default; + +/// line-dashed +/// @export style +/// @group style +/// @unconfigurable +$line-dashed: dashed !default; + +/// line-dotted +/// @export style +/// @group style +/// @unconfigurable +$line-dotted: dotted !default; + +// ----------- patch ----------- // +$line-0: $line-zero; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_motion.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_motion.scss new file mode 100644 index 000000000..49ed1cc8d --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_motion.scss @@ -0,0 +1,10 @@ +$motion-ease: ease; +$motion-ease-in: ease-in; +$motion-ease-out: ease-out; +$motion-ease-in-out: ease-in-out; +$motion-linear: linear; + +$motion-duration-immediately: 100ms; +$motion-duration-standard: 300ms; +$motion-duration-complex: 450ms; +$motion-duration-continue: 600ms; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_shadow.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_shadow.scss new file mode 100644 index 000000000..b9315f42b --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_shadow.scss @@ -0,0 +1,207 @@ +@import "./_color"; +@import "../util/_function"; + +//// +/// @module shadow: 阴影 +/// @category style +//// + +// Elevation & Shadow +// 根据 Alibaba Base DPL(BASE DPL)设计规范实现 +// 在现实生活中,不同对象可以被堆积或粘贴起来,但是不能彼此交叉。对象自身塑造了自己的阴影并返回自己的光影。 +// 规则: x == y, 所有方向阴影的 blur 值, 透明度, 颜色都应该相同 +// ------------------------------- + +// 变量: x, y, color, opacity, elevation +// 常量: base(45度), top, right, bottom, left + +// ---------------- 阴影方向 ---------------- // + +/// Sides Base +/// @type String +$shadow-sides-base: "base" !default; +/// Sides Up +/// @type String +$shadow-sides-up: "up" !default; +/// Sides Right +/// @type String +$shadow-sides-right: "right" !default; +/// Sides Down +/// @type String +$shadow-sides-down: "down" !default; +/// Sides Left +/// @type String +$shadow-sides-left: "left" !default; + +// ---------------- 阴影距离 ----------------- // + +/// Distance 1x +/// @type Number +$shadow-distance-sd1: 1; +/// Distance 2x +/// @type Number +$shadow-distance-sd2: 2; +/// Distance 3x +/// @type Number +$shadow-distance-sd3: 3; + +/// Distance 1y +/// @type Number +$shadow-distance-sd1y: 1; +/// Distance 2y +/// @type Number +$shadow-distance-sd2y: 2; +/// Distance 3y +/// @type Number +$shadow-distance-sd3y: 3; + +// ---------------- 阴影透明度 ----------------- // + +/// Opacity 1 +/// @type Number +$shadow-opacity-sd1: .12 !default; +/// Opacity 2 +/// @type Number +$shadow-opacity-sd2: .12 !default; +/// Opacity 3 +/// @type Number +$shadow-opacity-sd3: .12 !default; + +// ---------------- 阴影颜色 ----------------- // + +/// Color 1 +/// @type Color +$shadow-color-sd1: $color-black !default; + +/// Color 2 +/// @type Color +$shadow-color-sd2: $color-black !default; + +/// Color 3 +/// @type Color +$shadow-color-sd3: $color-black !default; + +// 带透明度的颜色变量 +$shadow-color-opacity-sd1: rgba($shadow-color-sd1, $shadow-opacity-sd1) !default; +$shadow-color-opacity-sd2: rgba($shadow-color-sd2, $shadow-opacity-sd2) !default; +$shadow-color-opacity-sd3: rgba($shadow-color-sd3, $shadow-opacity-sd3) !default; + +// ------------------ 阴影羽化值 ---------------- // + +/// Blur 1 +/// @type Number +$shadow-blur-sd1: 3 !default; + +/// Blur 2 +/// @type Number +$shadow-blur-sd2: 4 !default; + +/// Blur 3 +/// @type Number +$shadow-blur-sd3: 5 !default; + +// ------------------ 阴影扩散值 ---------------- // + +/// Spread 1 +/// @type Number +$shadow-spread-sd1: 0 !default; + +/// Spread 2 +/// @type Number +$shadow-spread-sd2: 0 !default; + +/// Spread 3 +/// @type Number +$shadow-spread-sd3: 0 !default; + +// ------------------ Shadow Values ---------------- // + +/// shadow-zero +/// @export +/// @unconfigurable +$shadow-zero: none; + +/// shadow-1 +/// @semantic 阴影1-右下 +/// @export +/// @unconfigurable +$shadow-1: shadow-maker($shadow-sides-base, $shadow-blur-sd1, $shadow-color-opacity-sd1, $shadow-distance-sd1, $shadow-distance-sd1y, $shadow-spread-sd1); + +/// shadow-1-up +/// @semantic 阴影1-上 +/// @export +/// @unconfigurable +$shadow-1-up: shadow-maker($shadow-sides-up, $shadow-blur-sd1, $shadow-color-opacity-sd1, $shadow-distance-sd1, $shadow-distance-sd1y, $shadow-spread-sd1); + +/// shadow-1-right +/// @semantic 阴影1-右 +/// @export +/// @unconfigurable +$shadow-1-right: shadow-maker($shadow-sides-right, $shadow-blur-sd1, $shadow-color-opacity-sd1, $shadow-distance-sd1, $shadow-distance-sd1y, $shadow-spread-sd1); + +/// shadow-1-down +/// @semantic 阴影1-下 +/// @export +/// @unconfigurable +$shadow-1-down: shadow-maker($shadow-sides-down, $shadow-blur-sd1, $shadow-color-opacity-sd1, $shadow-distance-sd1, $shadow-distance-sd1y, $shadow-spread-sd1); + +/// shadow-1-left +/// @semantic 阴影1-左 +/// @export +/// @unconfigurable +$shadow-1-left: shadow-maker($shadow-sides-left, $shadow-blur-sd1, $shadow-color-opacity-sd1, $shadow-distance-sd1, $shadow-distance-sd1y, $shadow-spread-sd1); + +/// shadow-2 +/// @semantic 阴影2-右下 +/// @export +/// @unconfigurable +$shadow-2: shadow-maker($shadow-sides-base, $shadow-blur-sd2, $shadow-color-opacity-sd2, $shadow-distance-sd2, $shadow-distance-sd2y, $shadow-spread-sd2); +/// shadow-2-up +/// @semantic 阴影2-上 +/// @export +/// @unconfigurable +$shadow-2-up: shadow-maker($shadow-sides-up, $shadow-blur-sd2, $shadow-color-opacity-sd2, $shadow-distance-sd2, $shadow-distance-sd2y, $shadow-spread-sd2); +/// shadow-2-right +/// @semantic 阴影2-右 +/// @export +/// @unconfigurable +$shadow-2-right: shadow-maker($shadow-sides-right, $shadow-blur-sd2, $shadow-color-opacity-sd2, $shadow-distance-sd2, $shadow-distance-sd2y, $shadow-spread-sd2); +/// shadow-2-down +/// @semantic 阴影2-下 +/// @export +/// @unconfigurable +$shadow-2-down: shadow-maker($shadow-sides-down, $shadow-blur-sd2, $shadow-color-opacity-sd2, $shadow-distance-sd2, $shadow-distance-sd2y, $shadow-spread-sd2); +/// shadow-2-left +/// @semantic 阴影2-左 +/// @export +/// @unconfigurable +$shadow-2-left: shadow-maker($shadow-sides-left, $shadow-blur-sd2, $shadow-color-opacity-sd2, $shadow-distance-sd2, $shadow-distance-sd2y, $shadow-spread-sd2); + +/// shadow-3 +/// @semantic 阴影3-右下 +/// @export +/// @unconfigurable +$shadow-3: shadow-maker($shadow-sides-base, $shadow-blur-sd3, $shadow-color-opacity-sd3, $shadow-distance-sd3, $shadow-distance-sd3y, $shadow-spread-sd3); +/// shadow-3-up +/// @semantic 阴影3-上 +/// @export +/// @unconfigurable +$shadow-3-up: shadow-maker($shadow-sides-up, $shadow-blur-sd3, $shadow-color-opacity-sd3, $shadow-distance-sd3, $shadow-distance-sd3y, $shadow-spread-sd3); +/// shadow-3-right +/// @semantic 阴影3-右 +/// @export +/// @unconfigurable +$shadow-3-right: shadow-maker($shadow-sides-right, $shadow-blur-sd3, $shadow-color-opacity-sd3, $shadow-distance-sd3, $shadow-distance-sd3y, $shadow-spread-sd3); +/// shadow-3-down +/// @semantic 阴影3-下 +/// @export +/// @unconfigurable +$shadow-3-down: shadow-maker($shadow-sides-down, $shadow-blur-sd3, $shadow-color-opacity-sd3, $shadow-distance-sd3, $shadow-distance-sd3y, $shadow-spread-sd3); +/// shadow-3-left +/// @semantic 阴影3-左 +/// @export +/// @unconfigurable +$shadow-3-left: shadow-maker($shadow-sides-left, $shadow-blur-sd3, $shadow-color-opacity-sd3, $shadow-distance-sd3, $shadow-distance-sd3y, $shadow-spread-sd3); + +// ----------- patch ----------- // +$shadow-0: $shadow-zero; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_size.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_size.scss new file mode 100644 index 000000000..00f3abe36 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/core/style/_size.scss @@ -0,0 +1,285 @@ +//// +/// @module size: 尺寸 +/// @type String +/// @category style +//// + + +/** + * 尺寸 基础尺寸 + * 命名能在语义的前提下简单就尽量简单, 这里可以是 size-2x, space-2x, size-base ... + * 不过可以在语义的前提下做的更精简一些, 于是用了s2, s1等 + * 可用变量: `$s1 - $s8` + * @example scss - 使用 + * .element { + * padding: $s1 !default; + * } + * + * @example css - CSS 输出 + * .element { + * padding: 4px !default; + * } + */ + +/// size-base +/// @semantic 基础尺寸 +/// @type Length +$size-base: 4px !default; + +/// s-zero +/// @export +/// @unconfigurable +$s-zero: 0; + +/// s-1 +/// @unconfigurable +/// @export +$s-1: $size-base * 1; + +/// s-2 +/// @export +/// @unconfigurable +$s-2: $size-base * 2; + +/// s-3 +/// @export +/// @unconfigurable +$s-3: $size-base * 3; + +/// s-4 +/// @export +/// @unconfigurable +$s-4: $size-base * 4; + +/// s-5 +/// @export +/// @unconfigurable +$s-5: $size-base * 5; + +/// s-6 +/// @export +/// @unconfigurable +$s-6: $size-base * 6; + +/// s-7 +/// @export +/// @unconfigurable +$s-7: $size-base * 7; + +/// s-8 +/// @export +/// @unconfigurable +$s-8: $size-base * 8; + +/// s-9 +/// @export +/// @unconfigurable +$s-9: $size-base * 9; + +/// s-10 +/// @export +/// @unconfigurable +$s-10: $size-base * 10; + +/// s-11 +/// @export +/// @unconfigurable +$s-11: $size-base * 11; + +/// s-12 +/// @export +/// @unconfigurable +$s-12: $size-base * 12; + +/// s-13 +/// @export +/// @unconfigurable +$s-13: $size-base * 13; + +/// s-14 +/// @export +/// @unconfigurable +$s-14: $size-base * 14; + +/// s-15 +/// @export +/// @unconfigurable +$s-15: $size-base * 15; + +/// s-16 +/// @export +/// @unconfigurable +$s-16: $size-base * 16; + +/// s-17 +/// @export +/// @unconfigurable +$s-17: $size-base * 17; + +/// s-18 +/// @export +/// @unconfigurable +$s-18: $size-base * 18; + +/// s-19 +/// @export +/// @unconfigurable +$s-19: $size-base * 19; + +/// s-20 +/// @export +/// @unconfigurable +$s-20: $size-base * 20; + +/// s-21 +/// @export +/// @unconfigurable +$s-21: $size-base * 21; + +/// s-22 +/// @export +/// @unconfigurable +$s-22: $size-base * 22; + +/// s-23 +/// @export +/// @unconfigurable +$s-23: $size-base * 23; + +/// s-24 +/// @export +/// @unconfigurable +$s-24: $size-base * 24; + +/// s-25 +/// @export +/// @unconfigurable +$s-25: $size-base * 25; + +/// s-26 +/// @export +/// @unconfigurable +$s-26: $size-base * 26; + +/// s-27 +/// @export +/// @unconfigurable +$s-27: $size-base * 27; + +/// s-28 +/// @export +/// @unconfigurable +$s-28: $size-base * 28; + +/// s-29 +/// @export +/// @unconfigurable +$s-29: $size-base * 29; + +/// s-30 +/// @export +/// @unconfigurable +$s-30: $size-base * 30; + +/// s-31 +/// @export +/// @unconfigurable +$s-31: $size-base * 31; + +/// s-32 +/// @export +/// @unconfigurable +$s-32: $size-base * 32; + +/// s-33 +/// @export +/// @unconfigurable +$s-33: $size-base * 33; + +/// s-34 +/// @export +/// @unconfigurable +$s-34: $size-base * 34; + +/// s-35 +/// @export +/// @unconfigurable +$s-35: $size-base * 35; + +/// s-36 +/// @export +/// @unconfigurable +$s-36: $size-base * 36; + +/// s-37 +/// @export +/// @unconfigurable +$s-37: $size-base * 37; + +/// s-38 +/// @export +/// @unconfigurable +$s-38: $size-base * 38; + +/// s-39 +/// @export +/// @unconfigurable +$s-39: $size-base * 39; + +/// s-40 +/// @export +/// @unconfigurable +$s-40: $size-base * 40; + +/// s-41 +/// @export +/// @unconfigurable +$s-41: $size-base * 41; + +/// s-42 +/// @export +/// @unconfigurable +$s-42: $size-base * 42; + +/// s-43 +/// @export +/// @unconfigurable +$s-43: $size-base * 43; + +/// s-44 +/// @export +/// @unconfigurable +$s-44: $size-base * 44; + +/// s-45 +/// @export +/// @unconfigurable +$s-45: $size-base * 45; + +/// s-46 +/// @export +/// @unconfigurable +$s-46: $size-base * 46; + +/// s-47 +/// @export +/// @unconfigurable +$s-47: $size-base * 47; + +/// s-48 +/// @export +/// @unconfigurable +$s-48: $size-base * 48; + +/// s-49 +/// @export +/// @unconfigurable +$s-49: $size-base * 49; + +/// s-50 +/// @export +/// @unconfigurable +$s-50: $size-base * 50; + +// ----------- patch ----------- // +$s-0: $s-zero; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/core/util/_function.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/core/util/_function.scss new file mode 100755 index 000000000..8c99db9d3 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/core/util/_function.scss @@ -0,0 +1,183 @@ +//// +/// @group utils +//// + +// 去除数值单位的方法 +// +// @param {String} $value +// 带单位的数值 +// +// @example scss - SCSS 用法 +// $dimension: strip-units(10px); +// +// @example css - CSS 输出 +// $dimension: 10; +// +// @return {Number} +@function strip-units($value) { + @return ($value / ($value * 0 + 1)); +} + +// 检查一个值是否为合法的CSS长度 +// +// @param {String} $value +// @return {Number} +@function is-length($value) { + @return type-of($value) != "null" and (str-slice($value + "", 1, 4) == "calc" // 是calc函数来计算的长度 + or type-of(index(auto inherit initial 0, $value)) == 'number' + or (type-of($value) == "number" and not(unitless($value)))); +} + +// 将pixel单位转换为em单位 +// +// @param {Number} $pxval +// pixel单位下的数值 +// +// @param {Number} $base +// 全局基础pixel单位下的字号 +// +// @example scss - SCSS 用法 +// .element { +// font-size: em(12, 14); +// } +// +// @example css - CSS 输出 +// .element { +// font-size: 0.85714em; +// } +// @require {function} strip-units +// @require {variable} $font-size-body-1 +// +// @return {String} + +@function em($pxval, $base: $font-size-body-1) { + @if not unitless($pxval) { + $pxval: strip-units($pxval); + } + @if not unitless($base) { + $base: strip-units($base); + } + @return ($pxval / $base) * 1em; +} + +// 转化为四值属性的方法,该属性可以有 1 到 4 个值,如:margin, padding, position +// +// @param {List} $shorthand +// +// @example scss - SCSS 用法 +// .element { +// margin: unpack(1em 2em); +// padding: unpack(1em 2em 2em); +// } +// +// @example css - CSS 输出 +// .element { +// margin: 1em 2em 1em 2em; +// padding: 1em 2em 2em 2em; +// } +// +// @return {List} +@function unpack($shorthand) { + @if length($shorthand) == 1 { + @return nth($shorthand, 1) nth($shorthand, 1) nth($shorthand, 1) nth($shorthand, 1); + } @else if length($shorthand) == 2 { + @return nth($shorthand, 1) nth($shorthand, 2) nth($shorthand, 1) nth($shorthand, 2); + } @else if length($shorthand) == 3 { + @return nth($shorthand, 1) nth($shorthand, 2) nth($shorthand, 3) nth($shorthand, 2); + } @else { + @return $shorthand; + } +} + +// 圆角生成器 +// +// @access private +// +// @param {String} $side [$corner-sides-base] - 需要加圆角的面 +// @param {String} $radius [$corner-radius-base] - 圆角曲率 +// +// @example scss - SCSS 用法 +// .element { +// border-radius: corner-maker(); +// } +// +// @example css - CSS 输出 +// .element { +// border-radius: 3px 3px 3px 3px; +// } +// +// @return {List} + +@function corner-maker($side: $corner-sides-base, $radius: 3px) { + + $tl: $radius; + $tr: $radius; + $br: $radius; + $bl: $radius; + + @if ($side == top) { + $br: 0; + $bl: 0; + } @else if ($side == right) { + $tl: 0; + $bl: 0; + } @else if ($side == down) { + $tr: 0; + $tl: 0; + } @else if ($side == left) { + $tr: 0; + $br: 0; + } + + @return #{$tl} #{$tr} #{$br} #{$bl}; +} + +// shadow 生成器 +// +// +// @param {String} $direction [$shadow-sides-base] - 阴影方向 +// @param {String} $blur [$shadow-blur-sd1] - 阴影羽化值 +// @param {Color} $shadow-color [$shadow-color-opacity-sd1] - 阴影颜色 +// @param {String} $shadow-x [$shadow-distance-sd1] - 阴影x方向距离 +// @param {String} $shadow-y [$shadow-distance-sd1y] - 阴影y方向距离 +// @param {String} $shadow-spread [$shadow-spread-sd1] - 阴影扩散值 +// +// @example scss - SCSS 用法 +// $shadow-1: shadow-maker(); +// +// @return {List} + +@function shadow-maker( + $direction: $shadow-sides-base, + $blur: $shadow-blur-sd1, + $shadow-color: $shadow-color-opacity-sd1, + $shadow-x: $shadow-distance-sd1, + $shadow-y: $shadow-distance-sd1y, + $shadow-spread: $shadow-spread-sd1 + +) { + + $x: $shadow-x; + $y: $shadow-y; + $b: $blur; + $c: $shadow-color; + $s: $shadow-spread; + + @if ($b == 0) { + @return 0 0 0 #FFFFFF; + } + + @if ($direction == $shadow-sides-up) { + $x: 0; + $y: -$shadow-y; + } @else if ($direction == $shadow-sides-right) { + $y: 0; + } @else if ($direction == $shadow-sides-down) { + $x: 0; + } @else if ($direction == $shadow-sides-left) { + $x: -$shadow-x; + $y: 0; + } + + @return #{$x}px #{$y}px #{$b}px #{$s}px $c; +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/core/util/_mixin.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/core/util/_mixin.scss new file mode 100755 index 000000000..3c5f80a97 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/core/util/_mixin.scss @@ -0,0 +1,570 @@ +//// +/// @group utils +//// + +/// 清除浮动 +/// +/// @example scss +/// .wrapper { +/// @include clearfix; +/// } +/// +@mixin clearfix { + &:after { + visibility: hidden; + display: block; + height: 0; + font-size: 0; + content: '\0020'; + clear: both; + } +} + + + +/// 单行截取文字,添加『...』结尾 +/// +/// @param {Number | String} $width [100%] - 最大宽度,CSS长度,包括calc方法定义的表达式 +/// +/// @example scss - 使用 +/// .element { +/// @include ellipsis; +/// } +/// +/// @example css - 输出 +/// .element { +/// display: inline-block; +/// max-width: 100%; +/// overflow: hidden; +/// text-overflow: ellipsis; +/// white-space: nowrap; +/// word-wrap: normal; +/// } +/// +@mixin ellipsis($width: 100%) { + display: inline-block; + max-width: $width; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + word-wrap: normal; +} + +/// 多行截取文字,添加『...』结尾 +/// +/// @param {Number | String} $line-height [1.2em] - 行高 +/// @param {Number} $line-count [2] - 行数, 超出行数开始截取 +/// @param {Color} $bg-color [#fff] - 文本背景色 +/// +/// @example scss - 使用 +/// .element { +/// @include multi-line-ellipsis(1.2em, 3, #fff); +/// } +/// +/// @example css - 输出 +/// .element { +/// overflow: hidden; +/// position: relative; +/// line-height: 1.2em; +/// max-height: 3.6em; +/// text-align: justify; +/// padding-right: 0em; +/// } +/// +/// .element:before { +/// content: '...'; +/// position: absolute; +/// right: 0; +/// bottom: 0; +/// background: #fff; +/// } +/// +/// .element:after { +/// content: ''; +/// position: absolute; +/// right: 0; +/// width: 1em; +/// height: 1em; +/// margin-top: 0.2em; +/// background: #fff; +/// } +/// +@mixin multi-line-ellipsis( + $line-height: 1.2em, + $line-count: 2, + $bg-color: #fff +) { + overflow: hidden; + position: relative; + line-height: $line-height; + max-height: $line-height * $line-count; + text-align: justify; + padding-right: 0; + + &:before { + content: '...'; + position: absolute; + right: 0; + bottom: 0; + background: $bg-color; + } + + &:after { + content: ''; + position: absolute; + right: 0; + width: 1em; + height: 1em; + margin-top: .2em; + background: $bg-color; + } +} + +/// 隐藏文字 +/// +/// 『text-indent: -9999px』Hack 的替代版本 +/// +/// @link http://nicolasgallagher.com/another-css-image-replacement-technique +/// +/// @example scss +/// .element { +/// @include hide-text; +/// background: url(logo.png); +/// } +/// +@mixin hide-text { + font: 0/0 a; + text-shadow: none; + color: transparent; +} + +/// 将元素垂直(水平)居中 (transform 版本) +/// +/// @param {String} $inner-selector ['.inner'] - 直接子选择器名称 +/// @param {Bool} $horizontal [true] - 是否水平居中 +/// +/// @example scss - 使用 +/// .element { +/// @include center-tl; +/// } +/// +/// @example css - 输出 +/// .element { +/// position: relative; +/// } +/// +/// .element > .inner { +/// position: absolute; +/// top: 50%; +/// left: 50%; +/// transform: translate(-50%, -50%); +/// } +/// +@mixin center-tl( + $inner-selector: '.inner', + $horizontal: true +) { + + position: relative; + + & > #{$inner-selector} { + position: absolute; + top: 50%; + $translate-val: translateY(-50%); + + @if $horizontal { + left: 50%; + $translate-val: translate(-50%, -50%); + } + + transform: $translate-val; + } +} + +/// 将元素垂直(水平)居中 (table 版本) +/// +/// @param {String} $inner-selector ['.inner'] - 直接子选择器名称 +/// @param {Bool} $horizontal [true] - 是否水平居中 +/// +/// @example scss - 使用 +/// .element { +/// @include center-td; +/// } +/// +/// @example css - 输出 +/// .element { +/// text-align: center; +/// display: table; +/// } +/// +/// .element > .inner { +/// display: table-cell; +/// vertical-align: middle; +/// } +/// +@mixin center-td( + $inner-selector: '.inner', + $horizontal: true +) { + + @if $horizontal { + text-align: center; + } + + display: table; + + & > #{$inner-selector} { + display: table-cell; + vertical-align: middle; + } +} + +/// 快捷设置元素width,height的方法 +/// +/// @param {String | List} $size - CSS尺寸长度 +/// +/// @example scss - 使用 +/// .element { +/// @include size(2em 4em); +/// } +/// +/// @example css - 输出 +/// .element { +/// width: 2em; +/// height: 4em; +/// } +/// +@mixin size($size) { + + @if length($size) == 1 { + width: $size; + height: $size; + } @else if length($size) == 2 { + width: nth($size, 1); + height: nth($size, 2); + } +} + +// 快捷设置元素postion的方法 (传入null参数可略过一个方位) +// +// @param {String} $position [relative] +// CSS position属性值 +// +// @param {List} $coordinates [null null null null] +// 上、右、下、左 四个边值,可以传入1 ~ 4个值 +// +// @example scss - 使用 +// .element { +// @include position(absolute, 0 null null 10px); +// } +// +// @example css - 输出 +// .element { +// position: absolute; +// left: 10px; +// top: 0; +// } +// +// @require {function} is-length +// @require {function} unpack +@mixin position($position: relative, $coordinates: null null null null) { + + // 如果参数是数组 + @if type-of($position) == list { + $coordinates: $position; + $position: relative; + } + + $coordinates: unpack($coordinates); + + $offsets: ( + top: nth($coordinates, 1), + right: nth($coordinates, 2), + bottom: nth($coordinates, 3), + left: nth($coordinates, 4) + ); + + position: $position; + + @each $offset, $value in $offsets { + + // 如果是合法长度 + @if is-length($value) { + #{$offset}: $value; + } + } +} + +// 三角型生成器(8种形态) +// +// @param {Number | List} $size +// 三角形尺寸 +// 传入一个参数,生成等宽高三角形;传入数组且长度为2,第一个设置宽度,第二个设置高度 +// +// @param {String | List} $color +// 传入一个参数,设置三角形颜色;传入数组且长度为2,第一个设置三角形颜色,第二个设置背景色 +// +// @param {String} $direction +// 三角形朝向,可传参数:up | down | right | left | up-right | up-left | down-right | down-left | inset-up | inset-down | inset-left | inset-right +// +// @example scss - 使用 +// .element { +// &:before { +// content: " "; +// @include triangle(100px 200px, blue, up); +// } +// } +// +// @example css - 输出 +// .example:before { +// content: " "; +// height: 0; +// width: 0; +// border-bottom: 200px solid blue; +// border-left: 50px solid transparent; +// border-right: 50px solid transparent; +// } +// +@mixin triangle($size, $color, $direction) { + $width: nth($size, 1); + $height: nth($size, length($size)); + $foreground-color: nth($color, 1); + $background-color: if(length($color) == 2, nth($color, 2), transparent); + height: 0; + width: 0; + + @if ($direction == up) or ($direction == down) or ($direction == right) or ($direction == left) { + $width: $width / 2; + $height: if(length($size) > 1, $height, $height/2); + + @if $direction == up { + border-bottom: $height solid $foreground-color; + border-left: $width solid $background-color; + border-right: $width solid $background-color; + } @else if $direction == right { + border-bottom: $width solid $background-color; + border-left: $height solid $foreground-color; + border-top: $width solid $background-color; + } @else if $direction == down { + border-left: $width solid $background-color; + border-right: $width solid $background-color; + border-top: $height solid $foreground-color; + } @else if $direction == left { + border-bottom: $width solid $background-color; + border-right: $height solid $foreground-color; + border-top: $width solid $background-color; + } + } @else if ($direction == up-right) or ($direction == up-left) { + border-top: $height solid $foreground-color; + + @if $direction == up-right { + border-left: $width solid $background-color; + } @else if $direction == up-left { + border-right: $width solid $background-color; + } + } @else if ($direction == down-right) or ($direction == down-left) { + border-bottom: $height solid $foreground-color; + + @if $direction == down-right { + border-left: $width solid $background-color; + } @else if $direction == down-left { + border-right: $width solid $background-color; + } + } @else if ($direction == inset-up) { + border-color: $background-color $background-color $foreground-color; + border-style: solid; + border-width: $height $width; + } @else if ($direction == inset-down) { + border-color: $foreground-color $background-color $background-color; + border-style: solid; + border-width: $height $width; + } @else if ($direction == inset-right) { + border-color: $background-color $background-color $background-color $foreground-color; + border-style: solid; + border-width: $width $height; + } @else if ($direction == inset-left) { + border-color: $background-color $foreground-color $background-color $background-color; + border-style: solid; + border-width: $width $height; + } +} + +@mixin box-sizing { + box-sizing: border-box; + *, + *:before, + *:after { + box-sizing: border-box; + } +} + +@mixin icon-size($size, $marginLeft: false, $marginRight: false, $transform: false) { + @if ($transform) { + transform: $transform; + } + @if ($marginLeft) { + margin-left: $marginLeft; + } + @if ($marginRight) { + margin-right: $marginRight; + } + + &:before, + & .#{$css-prefix}icon-remote { + width: $size; + font-size: $size; + line-height: inherit; + } + + // Chrome不支持小于12px的字体,故采用缩放的方式缩小字体 + @if (type-of($size) == 'number') { + @if ($size < 12) { + @media all and (-webkit-min-device-pixel-ratio: 0) and (min-resolution: .001dpcm) { + @if ($transform) { + transform: scale($size / $icon-s) $transform; + } @else { + transform: scale($size / $icon-s); + } + @if ($marginLeft) { + margin-left: $marginLeft - ($icon-s - $size) / 2; + } @else { + margin-left: -($icon-s - $size) / 2; + } + @if ($marginRight) { + margin-right: $marginRight - ($icon-s - $size) / 2; + } @else { + margin-right: -($icon-s - $size) / 2; + } + + &:before { + width: $icon-s; + font-size: $icon-s; + } + } + } + } +} + +@mixin icon-square-size($size, $marginTop: false, $marginRight: false, $marginBottom: false, $marginLeft: false, $transform: false) { + @if ($transform) { + transform: $transform; + } + @if ($marginTop) { + margin-top: $marginTop; + } + @if ($marginRight) { + margin-right: $marginRight; + } + @if ($marginBottom) { + margin-bottom: $marginBottom; + } + @if ($marginLeft) { + margin-left: $marginLeft; + } + + width: $size; + height: $size; + line-height: $size; + + &:before { + width: $size; + height: $size; + font-size: $size; + line-height: $size; + } + + // Chrome不支持小于12px的字体,故采用缩放的方式缩小字体 + @if ($size < 12) { + @media all and (-webkit-min-device-pixel-ratio: 0) and (min-resolution: .001dpcm) { + @if ($transform) { + transform: scale($size / $icon-s) $transform; + } @else { + transform: scale($size / $icon-s); + } + @if ($marginTop) { + margin-top: $marginTop - ($icon-s - $size) / 2; + } @else { + margin-top: -($icon-s - $size) / 2; + } + @if ($marginRight) { + margin-right: $marginRight - ($icon-s - $size) / 2; + } @else { + margin-right: -($icon-s - $size) / 2; + } + @if ($marginBottom) { + margin-bottom: $marginBottom - ($icon-s - $size) / 2; + } @else { + margin-bottom: -($icon-s - $size) / 2; + } + @if ($marginLeft) { + margin-left: $marginLeft - ($icon-s - $size) / 2; + } @else { + margin-left: -($icon-s - $size) / 2; + } + + width: $icon-s; + height: $icon-s; + line-height: $icon-s; + + &:before { + width: $icon-s; + height: $icon-s; + font-size: $icon-s; + line-height: $icon-s; + } + } + } +} + +@mixin font-face-handler($name, $url) { + @if ($name != Roboto) and ($name != "") { + @font-face { + font-family: "#{$name}"; + src: url("#{$url}"); + } + } +} + +/// 设置 button 外观颜色 +/// +/// @param {String} $color 字体色 +/// @param {String} $color-hover 鼠标悬浮时的字体色 +/// @param {String} $bg-color 背景色 +/// @param {String} $bg-color-hover 鼠标悬浮时的背景色 +/// @param {String} $border-color 边框色 +/// @param {String} $border-color-hover 鼠标悬浮时的边框色 +@mixin button-color($color, $color-hover, $bg-color: transparent, $bg-color-hover: transparent, $border-color: transparent, $border-color-hover: transparent) { + background-color: $bg-color; + border-color: $border-color; + + &, + &:link, + &:visited, + &.visited { + color: $color; + } + + &:focus, + &:hover, + &.hover, + &:active, + &.active { + color: $color-hover; + background-color: $bg-color-hover; + border-color: $border-color-hover; + text-decoration: none; + } +} + +/// 设置 button 大小 +/// +/// @param {Number} $padding 内边距 +/// @param {Number} $height 高度 +/// @param {Number} $font-size 字体大小 +/// @param {Number} $border-width 边框宽度 +@mixin button-size($padding, $height, $font-size, $border-width) { + padding: 0 $padding; + height: $height; + font-size: $font-size; + border-width: $border-width; +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/core/utility/_form-element.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/core/utility/_form-element.scss new file mode 100644 index 000000000..1e9084446 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/core/utility/_form-element.scss @@ -0,0 +1,82 @@ +//// +/// @group form-element +/// @module form-element: 表单通用 +/// @type String +/// @tag form-element +/// @category utility +/// @family form-element +/// @varPrefix $form-element- +/// @classPrefix {prefix}-form-element +//// + +/// height +/// @semantic 小号组件高度 +$form-element-small-height: $s-5 !default; + +/// height +/// @semantic 中号组件高度 +$form-element-medium-height: $s-7 !default; + +/// height +/// @semantic 大号组件高度 +$form-element-large-height: $s-10 !default; + +/// text +/// @semantic 小号组件字体 +$form-element-small-font-size: $font-size-caption !default; + +/// text +/// @semantic 中号组件字体 +$form-element-medium-font-size: $font-size-body-1 !default; + +/// text +/// @semantic 大号组件字体 +$form-element-large-font-size: $font-size-subhead !default; + +/// preview height +/// @semantic 小号组件预览态高度 +$form-element-small-preview-height: $s-5 !default; + +/// preview height +/// @semantic 中号组件预览态高度 +$form-element-medium-preview-height: $s-7 !default; + +/// preview height +/// @semantic 大号组件预览态高度 +$form-element-large-preview-height: $s-10 !default; + +/// preview text +/// @semantic 小号组件预览态字体 +$form-element-small-preview-font-size: $font-size-caption !default; + +/// preview text +/// @semantic 中号组件预览态字体 +$form-element-medium-preview-font-size: $font-size-body-1 !default; + +/// preview text +/// @semantic 大号组件预览态字体 +$form-element-large-preview-font-size: $font-size-subhead !default; + +/// icon +/// @semantic 小号组件 icon +$form-element-small-icon-size: $icon-xs !default; + +/// icon +/// @semantic 中号组件 icon +$form-element-medium-icon-size: $icon-xs !default; + +/// icon +/// @semantic 大号组件 icon +$form-element-large-icon-size: $icon-s !default; + +/// corner +/// @semantic 小号组件圆角 +$form-element-small-corner: $corner-1 !default; + +/// corner +/// @semantic 中号组件圆角 +$form-element-medium-corner: $corner-1 !default; + +/// corner +/// @semantic 大号组件圆角 +$form-element-large-corner: $corner-1 !default; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/core/utility/_mask.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/core/utility/_mask.scss new file mode 100644 index 000000000..2e8734861 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/core/utility/_mask.scss @@ -0,0 +1,20 @@ +//// +/// @group mask +/// @module mask: 遮罩通用 +/// @type String +/// @tag mask +/// @category utility +/// @family mask +/// @varPrefix $mask- +/// @classPrefix {prefix}-mask +//// + + +/// background +/// @semantic 背景颜色 +$mask-background: $color-black !default; + +/// opacity +/// @type alpha +/// @semantic 透明度 +$mask-opacity: .2 !default; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/core/utility/_popup.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/core/utility/_popup.scss new file mode 100644 index 000000000..7f25f8d28 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/core/utility/_popup.scss @@ -0,0 +1,51 @@ +//// +/// @group popup +/// @module popup: 弹层通用 +/// @type String +/// @tag popup +/// @category utility +/// @family popup +/// @varPrefix $popup- +/// @classPrefix {prefix}-popup +//// + + +/// border width +/// @semantic 边框宽度 +$popup-local-border-width: $line-1 !default; + +/// border style +/// @semantic 边框样式 +$popup-local-border-style: $line-solid !default; + +/// border color +/// @semantic 边框颜色 +$popup-local-border-color: $color-line1-2 !default; + +/// corner +/// @semantic 圆角 +$popup-local-corner: $corner-1 !default; + +/// shadow +/// @semantic 阴影 +$popup-local-shadow: $shadow-zero !default; + +/// border width +/// @semantic 边框宽度 +$popup-global-border-width: $line-zero !default; + +/// border style +/// @semantic 边框样式 +$popup-global-border-style: $line-solid !default; + +/// border color +/// @semantic 边框颜色 +$popup-global-border-color: $color-line1-2 !default; + +/// corner +/// @semantic 圆角 +$popup-global-corner: $corner-1 !default; + +/// shadow +/// @semantic 阴影 +$popup-global-shadow: $shadow-2-down !default; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/date-picker.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/date-picker.jsx new file mode 100644 index 000000000..fa9819655 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/date-picker.jsx @@ -0,0 +1,748 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import moment from 'moment'; +import ConfigProvider from '../config-provider'; +import Overlay from '../overlay'; +import Input from '../input'; +import Calendar from '../calendar'; +import TimePickerPanel from '../time-picker/panel'; +import nextLocale from '../locale/zh-cn'; +import { func, obj } from '../util'; +import { + PANEL, + resetValueTime, + checkDateValue, + formatDateValue, + getDateTimeFormat, + extend, + onDateKeydown, + onTimeKeydown, +} from './util'; +import PanelFooter from './module/panel-footer'; + +const { Popup } = Overlay; + +/** + * DatePicker + */ +export default class DatePicker extends Component { + static propTypes = { + ...ConfigProvider.propTypes, + prefix: PropTypes.string, + rtl: PropTypes.bool, + /** + * 输入框内置标签 + */ + label: PropTypes.node, + /** + * 输入框状态 + */ + state: PropTypes.oneOf(['success', 'loading', 'error']), + /** + * 输入提示 + */ + placeholder: PropTypes.string, + /** + * 默认展现的月 + * @return {MomentObject} 返回包含指定月份的 moment 对象实例 + */ + defaultVisibleMonth: PropTypes.func, + onVisibleMonthChange: PropTypes.func, + /** + * 日期值(受控)moment 对象 + */ + value: checkDateValue, + /** + * 初始日期值,moment 对象 + */ + defaultValue: checkDateValue, + /** + * 日期值的格式(用于限定用户输入和展示) + */ + format: PropTypes.string, + /** + * 是否使用时间控件,传入 TimePicker 的属性 { defaultValue, format, ... } + */ + showTime: PropTypes.oneOfType([PropTypes.object, PropTypes.bool]), + /** + * 每次选择日期时是否重置时间(仅在 showTime 开启时有效) + */ + resetTime: PropTypes.bool, + /** + * 禁用日期函数 + * @param {MomentObject} 日期值 + * @param {String} view 当前视图类型,year: 年, month: 月, date: 日 + * @return {Boolean} 是否禁用 + */ + disabledDate: PropTypes.func, + /** + * 自定义面板页脚 + * @return {Node} 自定义的面板页脚组件 + */ + footerRender: PropTypes.func, + /** + * 日期值改变时的回调 + * @param {MomentObject|String} value 日期值 + */ + onChange: PropTypes.func, + /** + * 点击确认按钮时的回调 + * @return {MomentObject|String} 日期值 + */ + onOk: PropTypes.func, + /** + * 输入框尺寸 + */ + size: PropTypes.oneOf(['small', 'medium', 'large']), + /** + * 是否禁用 + */ + disabled: PropTypes.bool, + /** + * 是否显示清空按钮 + */ + hasClear: PropTypes.bool, + /** + * 弹层显示状态 + */ + visible: PropTypes.bool, + /** + * 弹层默认是否显示 + */ + defaultVisible: PropTypes.bool, + /** + * 弹层展示状态变化时的回调 + * @param {Boolean} visible 弹层是否显示 + * @param {String} type 触发弹层显示和隐藏的来源 calendarSelect 表示由日期表盘的选择触发; okBtnClick 表示由确认按钮触发; fromTrigger 表示由trigger的点击触发; docClick 表示由document的点击触发 + */ + onVisibleChange: PropTypes.func, + /** + * 弹层触发方式 + */ + popupTriggerType: PropTypes.oneOf(['click', 'hover']), + /** + * 弹层对齐方式,具体含义见 OverLay文档 + */ + popupAlign: PropTypes.string, + /** + * 弹层容器 + * @param {Element} target 目标元素 + * @return {Element} 弹层的容器元素 + */ + popupContainer: PropTypes.any, + /** + * 弹层自定义样式 + */ + popupStyle: PropTypes.object, + /** + * 弹层自定义样式类 + */ + popupClassName: PropTypes.string, + /** + * 弹层其他属性 + */ + popupProps: PropTypes.object, + /** + * 是否跟随滚动 + */ + followTrigger: PropTypes.bool, + /** + * 输入框其他属性 + */ + inputProps: PropTypes.object, + /** + * 自定义日期渲染函数 + * @param {Object} value 日期值(moment对象) + * @returns {ReactNode} + */ + dateCellRender: PropTypes.func, + /** + * 自定义月份渲染函数 + * @param {Object} calendarDate 对应 Calendar 返回的自定义日期对象 + * @returns {ReactNode} + */ + monthCellRender: PropTypes.func, + yearCellRender: PropTypes.func, // 兼容 0.x yearCellRender + /** + * 日期输入框的 aria-label 属性 + */ + dateInputAriaLabel: PropTypes.string, + /** + * 时间输入框的 aria-label 属性 + */ + timeInputAriaLabel: PropTypes.string, + /** + * 是否为预览态 + */ + isPreview: PropTypes.bool, + /** + * 预览态模式下渲染的内容 + * @param {MomentObject} value 日期 + */ + renderPreview: PropTypes.func, + locale: PropTypes.object, + className: PropTypes.string, + name: PropTypes.string, + popupComponent: PropTypes.elementType, + popupContent: PropTypes.node, + disableChangeMode: PropTypes.bool, + yearRange: PropTypes.arrayOf(PropTypes.number), + }; + + static defaultProps = { + prefix: 'next-', + rtl: false, + format: 'YYYY-MM-DD', + size: 'medium', + showTime: false, + resetTime: false, + disabledDate: () => false, + footerRender: () => null, + hasClear: true, + popupTriggerType: 'click', + popupAlign: 'tl tl', + locale: nextLocale.DatePicker, + defaultVisible: false, + onChange: func.noop, + onVisibleChange: func.noop, + onOk: func.noop, + }; + + constructor(props, context) { + super(props, context); + const dateTimeFormat = getDateTimeFormat(props.format, props.showTime); + extend(dateTimeFormat, this); + + const value = formatDateValue( + props.value || props.defaultValue, + this.dateTimeFormat + ); + this.inputAsString = + typeof (props.value || props.defaultValue) === 'string'; // 判断用户输入是否是字符串 + this.state = { + value, + dateInputStr: '', + timeInputStr: '', + inputing: false, // 当前是否处于输入状态 + visible: props.visible || props.defaultVisible, + panel: PANEL.DATE, + }; + } + + componentWillReceiveProps(nextProps) { + if ('showTime' in nextProps) { + const dateTimeFormat = getDateTimeFormat( + nextProps.format || this.props.format, + nextProps.showTime + ); + extend(dateTimeFormat, this); + } + + if ('value' in nextProps) { + const value = formatDateValue(nextProps.value, this.dateTimeFormat); + this.setState({ + value, + }); + this.inputAsString = typeof nextProps.value === 'string'; + } + + if ('visible' in nextProps) { + this.setState({ + visible: nextProps.visible, + }); + } + } + + onValueChange = (newValue, handler = 'onChange') => { + const ret = + this.inputAsString && newValue + ? newValue.format(this.dateTimeFormat) + : newValue; + this.props[handler](ret); + }; + + onSelectCalendarPanel = value => { + const { showTime, resetTime } = this.props; + + const prevValue = this.state.value; + let newValue = value; + if (showTime) { + if (!prevValue) { + // 第一次选择日期值时,如果设置了默认时间,则使用该默认时间 + if (showTime.defaultValue) { + const defaultTimeValue = formatDateValue( + showTime.defaultValue, + this.timeFormat + ); + newValue = resetValueTime(value, defaultTimeValue); + } + } else if (!resetTime) { + // 非第一选择日期,如果开启了 resetTime 属性,则记住之前选择的时间值 + newValue = resetValueTime(value, prevValue); + } + } + + this.handleChange(newValue, prevValue, { inputing: false }); + + if (!showTime) { + this.onVisibleChange(false, 'calendarSelect'); + } + }; + + onSelectTimePanel = value => { + this.handleChange(value, this.state.value, { inputing: false }); + }; + + clearValue = () => { + this.setState({ + dateInputStr: '', + timeInputStr: '', + }); + + this.handleChange(null, this.state.value, { inputing: false }); + }; + + onDateInputChange = (inputStr, e, eventType) => { + if (eventType === 'clear' || !inputStr) { + e.stopPropagation(); + this.clearValue(); + } else { + this.setState({ + dateInputStr: inputStr, + inputing: 'date', + }); + } + }; + + onTimeInputChange = inputStr => { + this.setState({ + timeInputStr: inputStr, + inputing: 'time', + }); + }; + + onDateInputBlur = () => { + const { dateInputStr } = this.state; + if (dateInputStr) { + const { disabledDate } = this.props; + const parsed = moment(dateInputStr, this.format, true); + + this.setState({ + dateInputStr: '', + inputing: false, + }); + + if (parsed.isValid() && !disabledDate(parsed, 'date')) { + this.handleChange(parsed, this.state.value); + } + } + }; + + onTimeInputBlur = () => { + const { value, timeInputStr } = this.state; + if (timeInputStr) { + const parsed = moment(timeInputStr, this.timeFormat, true); + + this.setState({ + timeInputStr: '', + inputing: false, + }); + + if (parsed.isValid()) { + const hour = parsed.hour(); + const minute = parsed.minute(); + const second = parsed.second(); + const newValue = value + .clone() + .hour(hour) + .minute(minute) + .second(second); + + this.handleChange(newValue, this.state.value); + } + } + }; + + onKeyDown = e => { + const { format } = this.props; + const { dateInputStr, value } = this.state; + const dateStr = onDateKeydown( + e, + { format, dateInputStr, value }, + 'day' + ); + if (!dateStr) return; + this.onDateInputChange(dateStr); + }; + + onTimeKeyDown = e => { + const { showTime } = this.props; + const { timeInputStr, value } = this.state; + const { + disabledMinutes, + disabledSeconds, + hourStep = 1, + minuteStep = 1, + secondStep = 1, + } = typeof showTime === 'object' ? showTime : {}; + let unit = 'second'; + + if (disabledSeconds) { + unit = disabledMinutes ? 'hour' : 'minute'; + } + + const timeStr = onTimeKeydown( + e, + { + format: this.timeFormat, + timeInputStr, + value, + steps: { + hour: hourStep, + minute: minuteStep, + second: secondStep, + }, + }, + unit + ); + + if (!timeStr) return; + + this.onTimeInputChange(timeStr); + }; + + handleChange = (newValue, prevValue, others = {}) => { + if (!('value' in this.props)) { + this.setState({ + value: newValue, + ...others, + }); + } else { + this.setState({ + ...others, + }); + } + + const newValueOf = newValue ? newValue.valueOf() : null; + const preValueOf = prevValue ? prevValue.valueOf() : null; + + if (newValueOf !== preValueOf) { + this.onValueChange(newValue); + } + }; + + onFoucsDateInput = () => { + if (this.state.panel !== PANEL.DATE) { + this.setState({ + panel: PANEL.DATE, + }); + } + }; + + onFoucsTimeInput = () => { + if (this.state.panel !== PANEL.TIME) { + this.setState({ + panel: PANEL.TIME, + }); + } + }; + + onVisibleChange = (visible, type) => { + if (!('visible' in this.props)) { + this.setState({ + visible, + }); + } + this.props.onVisibleChange(visible, type); + }; + + changePanel = panel => { + this.setState({ + panel, + }); + }; + + onOk = () => { + this.onVisibleChange(false, 'okBtnClick'); + this.onValueChange(this.state.value, 'onOk'); + }; + + renderPreview(others) { + const { prefix, format, className, renderPreview } = this.props; + const { value } = this.state; + const previewCls = classnames(className, `${prefix}form-preview`); + + const label = value ? value.format(format) : ''; + + if (typeof renderPreview === 'function') { + return ( +
    + {renderPreview(value, this.props)} +
    + ); + } + + return ( +

    + {label} +

    + ); + } + + render() { + const { + prefix, + rtl, + locale, + label, + state, + defaultVisibleMonth, + onVisibleMonthChange, + showTime, + disabledDate, + footerRender, + placeholder, + size, + disabled, + hasClear, + popupTriggerType, + popupAlign, + popupContainer, + popupStyle, + popupClassName, + popupProps, + popupComponent, + popupContent, + followTrigger, + className, + inputProps, + dateCellRender, + monthCellRender, + yearCellRender, + dateInputAriaLabel, + timeInputAriaLabel, + isPreview, + disableChangeMode, + yearRange, + ...others + } = this.props; + + const { + visible, + value, + dateInputStr, + timeInputStr, + panel, + inputing, + } = this.state; + + const datePickerCls = classnames( + { + [`${prefix}date-picker`]: true, + }, + className + ); + + const triggerInputCls = classnames({ + [`${prefix}date-picker-input`]: true, + [`${prefix}error`]: false, + }); + + const panelBodyClassName = classnames({ + [`${prefix}date-picker-body`]: true, + [`${prefix}date-picker-body-show-time`]: showTime, + }); + + const panelDateInputCls = classnames({ + [`${prefix}date-picker-panel-input`]: true, + [`${prefix}focus`]: panel === PANEL.DATE, + }); + + if (rtl) { + others.dir = 'rtl'; + } + + if (isPreview) { + return this.renderPreview( + obj.pickOthers(others, DatePicker.PropTypes) + ); + } + + const sharedInputProps = { + ...inputProps, + size, + disabled, + onChange: this.onDateInputChange, + onBlur: this.onDateInputBlur, + onPressEnter: this.onDateInputBlur, + onKeyDown: this.onKeyDown, + }; + + const dateInputValue = + inputing === 'date' + ? dateInputStr + : (value && value.format(this.format)) || ''; + let triggerInputValue = dateInputValue; + + const dateInput = ( + + ); + + const datePanel = ( + + ); + + let panelFooter = footerRender(); + + let timeInput = null; + let timePanel = null; + + if (showTime) { + const timeInputValue = + inputing === 'time' + ? timeInputStr + : (value && value.format(this.timeFormat)) || ''; + triggerInputValue = + (value && value.format(this.dateTimeFormat)) || ''; + + const timePanelProps = typeof showTime === 'object' ? showTime : {}; + + const showSecond = this.timeFormat.indexOf('s') > -1; + const showMinute = this.timeFormat.indexOf('m') > -1; + + const panelTimeInputCls = classnames({ + [`${prefix}date-picker-panel-input`]: true, + [`${prefix}focus`]: panel === PANEL.TIME, + }); + + timeInput = ( + + ); + + timePanel = ( + + ); + + panelFooter = panelFooter || ( + + ); + } + + const panelBody = { + [PANEL.DATE]: datePanel, + [PANEL.TIME]: timePanel, + }[panel]; + + const allowClear = value && hasClear; + const trigger = ( +
    + +
    + ); + const PopupComponent = popupComponent ? popupComponent : Popup; + + return ( +
    + + {popupContent ? ( + popupContent + ) : ( +
    +
    + {dateInput} + {timeInput} +
    + {panelBody} + {panelFooter} +
    + )} +
    +
    + ); + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/index.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/index.jsx new file mode 100644 index 000000000..7040f4c72 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/index.jsx @@ -0,0 +1,79 @@ +import ConfigProvider from '../config-provider'; +import DatePicker from './date-picker'; +import RangePicker from './range-picker'; +import MonthPicker from './month-picker'; +import YearPicker from './year-picker'; +import WeekPicker from './week-picker'; + +/* istanbul ignore next */ +const transform = (props, deprecated) => { + const { open, defaultOpen, onOpenChange, ...others } = props; + const newProps = others; + + delete newProps.formater; + + if ('open' in props) { + deprecated('open', 'visible', 'DatePicker'); + + newProps.visible = open; + + if ('visible' in props) { + newProps.visible = props.visible; + } + } + + if ('defaultOpen' in props) { + deprecated('defaultOpen', 'defaultVisible', 'DatePicker'); + + newProps.defaultVisible = defaultOpen; + + if ('defaultVisible' in props) { + newProps.defaultVisible = props.defaultVisible; + } + } + + if ('onOpenChange' in props && typeof onOpenChange === 'function') { + deprecated('onOpenChange', 'onVisibleChange', 'DatePicker'); + + newProps.onVisibleChange = onOpenChange; + + if ('onVisibleChange' in props) { + newProps.onVisibleChange = props.onVisibleChange; + } + } + + if ('formater' in props) { + deprecated('formater', 'format showTime.format', 'DatePicker'); + } + + if ('format' in props && typeof props.format !== 'string') { + deprecated('format', 'format: PropTypes.string,', 'DatePicker'); + } + + if ('ranges' in props) { + deprecated('ranges', 'footerRender: PropTypes.func', 'RangePicker'); + } + + return newProps; +}; + +DatePicker.RangePicker = ConfigProvider.config(RangePicker, { + componentName: 'DatePicker', + transform, +}); +DatePicker.MonthPicker = ConfigProvider.config(MonthPicker, { + componentName: 'DatePicker', + transform, +}); +DatePicker.YearPicker = ConfigProvider.config(YearPicker, { + componentName: 'DatePicker', + transform, +}); + +DatePicker.WeekPicker = ConfigProvider.config(WeekPicker, { + componentName: 'DatePicker', +}); + +export default ConfigProvider.config(DatePicker, { + transform, +}); diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/main.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/main.scss new file mode 100644 index 000000000..a12eb3feb --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/main.scss @@ -0,0 +1,68 @@ +@import "../core/index-noreset"; +@import "../input/scss/variable.scss"; +@import "../input/scss/mixin.scss"; +@import "../time-picker/scss/variable.scss"; + +@import "scss/variable"; +@import "scss/mixin"; + +@import "scss/date-picker"; +@import "scss/range-picker"; +@import "./rtl.scss"; + +#{$date-picker-prefix}, +#{$range-picker-prefix}, +#{$month-picker-prefix}, +#{$year-picker-prefix}, +#{$week-picker-prefix} { + @include box-sizing; + + &-body { + border: $popup-local-border-width $popup-local-border-style $popup-local-border-color; + border-radius: $popup-local-corner; + box-shadow: $popup-local-shadow; + background: $date-picker-panel-background; + } + + &-panel { + &-header { + padding: 6px; + text-align: center; + } + + &-time { + border-top: $popup-local-border-width $popup-local-border-style $popup-local-border-color; + } + + &-footer { + text-align: right; + padding: $date-picker-panel-footer-padding-tb $date-picker-panel-footer-padding-lr; + border-top: $popup-local-border-width $popup-local-border-style $popup-local-border-color; + } + + &-footer > #{$date-picker-btn-prefix}:not(:last-child), + &-tools > #{$date-picker-btn-prefix}:not(:last-child) { + margin-right: $s-4; + } + + &-tools { + float: left; + } + } + + .#{$css-prefix}calendar-panel-header { + margin-left: -$popup-local-border-width; + margin-right: -$popup-local-border-width; + } + + #{$date-picker-input-prefix} input { + vertical-align: baseline; + } +} + +#{$range-picker-prefix}-panel-body { + .#{$css-prefix}calendar { + display: inline-block; + width: 50%; + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/module/panel-footer.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/module/panel-footer.jsx new file mode 100644 index 000000000..a88ace0a9 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/module/panel-footer.jsx @@ -0,0 +1,90 @@ +import React from 'react'; +import moment from 'moment'; +import Button from '../../button'; +import { func } from '../../util'; +import { PANEL } from '../util'; + +class PanelFooter extends React.PureComponent { + static defaultProps = { + // onPanelChange: func.noop, + onOk: func.noop, + }; + + changePanel = () => { + const targetPanel = { + [PANEL.DATE]: PANEL.TIME, + [PANEL.TIME]: PANEL.DATE, + }[this.props.panel]; + this.props.onPanelChange(targetPanel); + }; + + createRanges = ranges => { + if (!ranges || ranges.length === 0) return null; + const { onOk, prefix } = this.props; + + return ( +
    + {ranges.map(({ label, value = [], onChange }) => { + const handleClick = () => { + onChange(value.map(v => moment(v))); + onOk(); + }; + return ( + + ); + })} +
    + ); + }; + + render() { + const { + prefix, + locale, + panel, + value, + ranges, // 兼容0.x range 属性 + disabledOk, + onPanelChange, + onOk, + } = this.props; + const panelBtnLabel = { + [PANEL.DATE]: locale.selectTime, + [PANEL.TIME]: locale.selectDate, + }[panel]; + + const sharedBtnProps = { + size: 'small', + type: 'primary', + disabled: !value, + }; + + return ( +
    + {this.createRanges(ranges)} + {onPanelChange ? ( + + ) : null} + +
    + ); + } +} + +export default PanelFooter; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/month-picker.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/month-picker.jsx new file mode 100644 index 000000000..14c237977 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/month-picker.jsx @@ -0,0 +1,505 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import moment from 'moment'; +import ConfigProvider from '../config-provider'; +import Overlay from '../overlay'; +import Input from '../input'; +import Calendar from '../calendar'; +import nextLocale from '../locale/zh-cn'; +import { func, obj } from '../util'; +import { checkDateValue, formatDateValue, onDateKeydown } from './util'; + +const { Popup } = Overlay; + +/** + * DatePicker.MonthPicker + */ +class MonthPicker extends Component { + static propTypes = { + ...ConfigProvider.propTypes, + prefix: PropTypes.string, + rtl: PropTypes.bool, + /** + * 输入框内置标签 + */ + label: PropTypes.node, + /** + * 输入框状态 + */ + state: PropTypes.oneOf(['success', 'loading', 'error']), + /** + * 输入提示 + */ + placeholder: PropTypes.string, + /** + * 默认展现的年 + * @return {MomentObject} 返回包含指定年份的 moment 对象实例 + */ + defaultVisibleYear: PropTypes.func, + /** + * 日期值(受控)moment 对象 + */ + value: checkDateValue, + /** + * 初始日期值,moment 对象 + */ + defaultValue: checkDateValue, + /** + * 日期值的格式(用于限定用户输入和展示) + */ + format: PropTypes.string, + /** + * 禁用日期函数 + * @param {MomentObject} 日期值 + * @param {String} view 当前视图类型,year: 年, month: 月, date: 日 + * @return {Boolean} 是否禁用 + */ + disabledDate: PropTypes.func, + /** + * 自定义面板页脚 + * @return {Node} 自定义的面板页脚组件 + */ + footerRender: PropTypes.func, + /** + * 日期值改变时的回调 + * @param {MomentObject|String} value 日期值 + */ + onChange: PropTypes.func, + /** + * 输入框尺寸 + */ + size: PropTypes.oneOf(['small', 'medium', 'large']), + /** + * 是否禁用 + */ + disabled: PropTypes.bool, + /** + * 是否显示清空按钮 + */ + hasClear: PropTypes.bool, + /** + * 弹层显示状态 + */ + visible: PropTypes.bool, + /** + * 弹层默认是否显示 + */ + defaultVisible: PropTypes.bool, + /** + * 弹层展示状态变化时的回调 + * @param {Boolean} visible 弹层是否显示 + * @param {String} type 触发弹层显示和隐藏的来源 calendarSelect 表示由日期表盘的选择触发; fromTrigger 表示由trigger的点击触发; docClick 表示由document的点击触发 + */ + onVisibleChange: PropTypes.func, + /** + * 弹层触发方式 + */ + popupTriggerType: PropTypes.oneOf(['click', 'hover']), + /** + * 弹层对齐方式, 具体含义见 OverLay文档 + */ + popupAlign: PropTypes.string, + /** + * 弹层容器 + * @param {Element} target 目标元素 + * @return {Element} 弹层的容器元素 + */ + popupContainer: PropTypes.any, + /** + * 弹层自定义样式 + */ + popupStyle: PropTypes.object, + /** + * 弹层自定义样式类 + */ + popupClassName: PropTypes.string, + /** + * 弹层其他属性 + */ + popupProps: PropTypes.object, + /** + * 是否跟随滚动 + */ + followTrigger: PropTypes.bool, + /** + * 输入框其他属性 + */ + inputProps: PropTypes.object, + /** + * 自定义月份渲染函数 + * @param {Object} calendarDate 对应 Calendar 返回的自定义日期对象 + * @returns {ReactNode} + */ + monthCellRender: PropTypes.func, + yearCellRender: PropTypes.func, // 兼容 0.x yearCellRender + /** + * 日期输入框的 aria-label 属性 + */ + dateInputAriaLabel: PropTypes.string, + /** + * 是否为预览态 + */ + isPreview: PropTypes.bool, + /** + * 预览态模式下渲染的内容 + * @param {MomentObject} value 月份 + */ + renderPreview: PropTypes.func, + locale: PropTypes.object, + className: PropTypes.string, + name: PropTypes.string, + popupComponent: PropTypes.elementType, + popupContent: PropTypes.node, + }; + + static defaultProps = { + prefix: 'next-', + rtl: false, + format: 'YYYY-MM', + size: 'medium', + disabledDate: () => false, + footerRender: () => null, + hasClear: true, + popupTriggerType: 'click', + popupAlign: 'tl tl', + locale: nextLocale.DatePicker, + onChange: func.noop, + onVisibleChange: func.noop, + }; + + constructor(props, context) { + super(props, context); + + const value = formatDateValue( + props.value || props.defaultValue, + props.format + ); + + this.inputAsString = + typeof (props.value || props.defaultValue) === 'string'; // 判断用户输入是否是字符串 + this.state = { + value, + dateInputStr: '', + inputing: false, + visible: props.visible || props.defaultVisible, + }; + } + + componentWillReceiveProps(nextProps) { + if ('value' in nextProps) { + const value = formatDateValue( + nextProps.value, + nextProps.format || this.props.format + ); + this.setState({ + value, + }); + this.inputAsString = typeof nextProps.value === 'string'; + } + + if ('visible' in nextProps) { + this.setState({ + visible: nextProps.visible, + }); + } + } + + onValueChange = newValue => { + const ret = + this.inputAsString && newValue + ? newValue.format(this.props.format) + : newValue; + this.props.onChange(ret); + }; + + onSelectCalendarPanel = value => { + // const { format } = this.props; + const prevSelectedMonth = this.state.value; + const selectedMonth = value + .clone() + .date(1) + .hour(0) + .minute(0) + .second(0); + + this.handleChange( + selectedMonth, + prevSelectedMonth, + { inputing: false }, + () => { + this.onVisibleChange(false, 'calendarSelect'); + } + ); + }; + + clearValue = () => { + this.setState({ + dateInputStr: '', + }); + + this.handleChange(null, this.state.value); + }; + + onDateInputChange = (inputStr, e, eventType) => { + if (eventType === 'clear' || !inputStr) { + e.stopPropagation(); + this.clearValue(); + } else { + this.setState({ + dateInputStr: inputStr, + inputing: true, + }); + } + }; + + onDateInputBlur = () => { + const { dateInputStr } = this.state; + if (dateInputStr) { + const { disabledDate, format } = this.props; + const parsed = moment(dateInputStr, format, true); + + this.setState({ + dateInputStr: '', + inputing: false, + }); + + if (parsed.isValid() && !disabledDate(parsed, 'month')) { + this.handleChange(parsed, this.state.value); + } + } + }; + + onKeyDown = e => { + const { format } = this.props; + const { dateInputStr, value } = this.state; + const dateStr = onDateKeydown( + e, + { format, dateInputStr, value }, + 'month' + ); + if (!dateStr) return; + this.onDateInputChange(dateStr); + }; + + handleChange = (newValue, prevValue, others = {}, callback) => { + if (!('value' in this.props)) { + this.setState({ + value: newValue, + ...others, + }); + } else { + this.setState({ + ...others, + }); + } + + const { format } = this.props; + + const newValueOf = newValue ? newValue.format(format) : null; + const preValueOf = prevValue ? prevValue.format(format) : null; + + if (newValueOf !== preValueOf) { + this.onValueChange(newValue); + if (typeof callback === 'function') { + return callback(); + } + } + }; + + onVisibleChange = (visible, type) => { + if (!('visible' in this.props)) { + this.setState({ + visible, + }); + } + this.props.onVisibleChange(visible, type); + }; + + renderPreview(others) { + const { prefix, format, className, renderPreview } = this.props; + const { value } = this.state; + const previewCls = classnames(className, `${prefix}form-preview`); + + const label = value ? value.format(format) : ''; + + if (typeof renderPreview === 'function') { + return ( +
    + {renderPreview(value, this.props)} +
    + ); + } + + return ( +

    + {label} +

    + ); + } + + render() { + const { + prefix, + rtl, + locale, + label, + state, + format, + defaultVisibleYear, + disabledDate, + footerRender, + placeholder, + size, + disabled, + hasClear, + popupTriggerType, + popupAlign, + popupContainer, + popupStyle, + popupClassName, + popupProps, + popupComponent, + popupContent, + followTrigger, + className, + inputProps, + monthCellRender, + yearCellRender, + dateInputAriaLabel, + isPreview, + ...others + } = this.props; + + const { visible, value, dateInputStr, inputing } = this.state; + + const monthPickerCls = classnames( + { + [`${prefix}month-picker`]: true, + }, + className + ); + + const triggerInputCls = classnames({ + [`${prefix}month-picker-input`]: true, + [`${prefix}error`]: false, + }); + + const panelBodyClassName = classnames({ + [`${prefix}month-picker-body`]: true, + }); + + if (rtl) { + others.dir = 'rtl'; + } + + if (isPreview) { + return this.renderPreview( + obj.pickOthers(others, MonthPicker.PropTypes) + ); + } + + const panelInputCls = `${prefix}month-picker-panel-input`; + + const sharedInputProps = { + ...inputProps, + size, + disabled, + onChange: this.onDateInputChange, + onBlur: this.onDateInputBlur, + onPressEnter: this.onDateInputBlur, + onKeyDown: this.onKeyDown, + }; + + const dateInputValue = inputing + ? dateInputStr + : (value && value.format(format)) || ''; + const triggerInputValue = dateInputValue; + + const dateInput = ( + + ); + + const datePanel = ( + + ); + + const panelBody = datePanel; + const panelFooter = footerRender(); + + const allowClear = value && hasClear; + const trigger = ( +
    + +
    + ); + + const PopupComponent = popupComponent ? popupComponent : Popup; + + return ( +
    + + {popupContent ? ( + popupContent + ) : ( +
    +
    + {dateInput} +
    + {panelBody} + {panelFooter} +
    + )} +
    +
    + ); + } +} + +export default MonthPicker; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/range-picker.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/range-picker.jsx new file mode 100644 index 000000000..169d9c007 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/range-picker.jsx @@ -0,0 +1,1182 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import moment from 'moment'; +import ConfigProvider from '../config-provider'; +import Overlay from '../overlay'; +import Input from '../input'; +import Calendar from '../calendar'; +import RangeCalendar from '../calendar/range-calendar'; +import TimePickerPanel from '../time-picker/panel'; +import nextLocale from '../locale/zh-cn'; +import { func, obj } from '../util'; +import { + PANEL, + resetValueTime, + formatDateValue, + extend, + getDateTimeFormat, + isFunction, + onDateKeydown, + onTimeKeydown, +} from './util'; +import PanelFooter from './module/panel-footer'; + +const { Popup } = Overlay; + +function mapInputStateName(name) { + return { + startValue: 'startDateInputStr', + endValue: 'endDateInputStr', + startTime: 'startTimeInputStr', + endTime: 'endTimeInputStr', + }[name]; +} + +function mapTimeToValue(name) { + return { + startTime: 'startValue', + endTime: 'endValue', + }[name]; +} + +function getFormatValues(values, format) { + if (!Array.isArray(values)) { + return [null, null]; + } + return [ + formatDateValue(values[0], format), + formatDateValue(values[1], format), + ]; +} + +/** + * DatePicker.RangePicker + */ +export default class RangePicker extends Component { + static propTypes = { + ...ConfigProvider.propTypes, + prefix: PropTypes.string, + rtl: PropTypes.bool, + /** + * 日期范围类型 + */ + type: PropTypes.oneOf(['date', 'month', 'year']), + /** + * 默认展示的起始月份 + * @return {MomentObject} 返回包含指定月份的 moment 对象实例 + */ + defaultVisibleMonth: PropTypes.func, + onVisibleMonthChange: PropTypes.func, + /** + * 日期范围值数组 [moment, moment] + */ + value: PropTypes.array, + /** + * 初始的日期范围值数组 [moment, moment] + */ + defaultValue: PropTypes.array, + /** + * 日期格式 + */ + format: PropTypes.string, + /** + * 是否使用时间控件,支持传入 TimePicker 的属性 + */ + showTime: PropTypes.oneOfType([PropTypes.object, PropTypes.bool]), + /** + * 每次选择是否重置时间(仅在 showTime 开启时有效) + */ + resetTime: PropTypes.bool, + /** + * 禁用日期函数 + * @param {MomentObject} 日期值 + * @param {String} view 当前视图类型,year: 年, month: 月, date: 日 + * @return {Boolean} 是否禁用 + */ + disabledDate: PropTypes.func, + /** + * 自定义面板页脚 + * @return {Node} 自定义的面板页脚组件 + */ + footerRender: PropTypes.func, + /** + * 日期范围值改变时的回调 [ MomentObject|String, MomentObject|String ] + * @param {Array} value 日期值 + */ + onChange: PropTypes.func, + /** + * 点击确认按钮时的回调 返回开始时间和结束时间`[ MomentObject|String, MomentObject|String ]` + * @return {Array} 日期范围 + */ + onOk: PropTypes.func, + /** + * 输入框内置标签 + */ + label: PropTypes.node, + /** + * 输入框状态 + */ + state: PropTypes.oneOf(['error', 'loading', 'success']), + /** + * 输入框尺寸 + */ + size: PropTypes.oneOf(['small', 'medium', 'large']), + /** + * 是否禁用 + */ + disabled: PropTypes.bool, + /** + * 是否显示清空按钮 + */ + hasClear: PropTypes.bool, + /** + * 弹层显示状态 + */ + visible: PropTypes.bool, + /** + * 弹层默认是否显示 + */ + defaultVisible: PropTypes.bool, + /** + * 弹层展示状态变化时的回调 + * @param {Boolean} visible 弹层是否显示 + * @param {String} type 触发弹层显示和隐藏的来源 okBtnClick 表示由确认按钮触发; fromTrigger 表示由trigger的点击触发; docClick 表示由document的点击触发 + */ + onVisibleChange: PropTypes.func, + /** + * 弹层触发方式 + */ + popupTriggerType: PropTypes.oneOf(['click', 'hover']), + /** + * 弹层对齐方式, 具体含义见 OverLay文档 + */ + popupAlign: PropTypes.string, + /** + * 弹层容器 + * @param {Element} target 目标元素 + * @return {Element} 弹层的容器元素 + */ + popupContainer: PropTypes.any, + /** + * 弹层自定义样式 + */ + popupStyle: PropTypes.object, + /** + * 弹层自定义样式类 + */ + popupClassName: PropTypes.string, + /** + * 弹层其他属性 + */ + popupProps: PropTypes.object, + /** + * 是否跟随滚动 + */ + followTrigger: PropTypes.bool, + /** + * 输入框其他属性 + */ + inputProps: PropTypes.object, + /** + * 自定义日期单元格渲染 + */ + dateCellRender: PropTypes.func, + /** + * 自定义月份渲染函数 + * @param {Object} calendarDate 对应 Calendar 返回的自定义日期对象 + * @returns {ReactNode} + */ + monthCellRender: PropTypes.func, + yearCellRender: PropTypes.func, // 兼容 0.x yearCellRender + /** + * 开始日期输入框的 aria-label 属性 + */ + startDateInputAriaLabel: PropTypes.string, + /** + * 开始时间输入框的 aria-label 属性 + */ + startTimeInputAriaLabel: PropTypes.string, + /** + * 结束日期输入框的 aria-label 属性 + */ + endDateInputAriaLabel: PropTypes.string, + /** + * 结束时间输入框的 aria-label 属性 + */ + endTimeInputAriaLabel: PropTypes.string, + /** + * 是否为预览态 + */ + isPreview: PropTypes.bool, + /** + * 预览态模式下渲染的内容 + * @param {Array} value 日期区间 + */ + renderPreview: PropTypes.func, + disableChangeMode: PropTypes.bool, + yearRange: PropTypes.arrayOf(PropTypes.number), + ranges: PropTypes.object, // 兼容0.x版本 + locale: PropTypes.object, + className: PropTypes.string, + name: PropTypes.string, + popupComponent: PropTypes.elementType, + popupContent: PropTypes.node, + placeholder: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.string), + PropTypes.string, + ]), + }; + + static defaultProps = { + prefix: 'next-', + rtl: false, + type: 'date', + size: 'medium', + showTime: false, + resetTime: false, + format: 'YYYY-MM-DD', + disabledDate: () => false, + footerRender: () => null, + hasClear: true, + defaultVisible: false, + popupTriggerType: 'click', + popupAlign: 'tl tl', + locale: nextLocale.DatePicker, + disableChangeMode: false, + onChange: func.noop, + onOk: func.noop, + onVisibleChange: func.noop, + }; + + constructor(props, context) { + super(props, context); + const dateTimeFormat = getDateTimeFormat( + props.format, + props.showTime, + props.type + ); + extend(dateTimeFormat, this); + + const val = props.value || props.defaultValue; + const values = getFormatValues(val, this.dateTimeFormat); + this.inputAsString = + val && (typeof val[0] === 'string' || typeof val[1] === 'string'); + this.state = { + visible: props.visible || props.defaultVisible, + startValue: values[0], + endValue: values[1], + startDateInputStr: '', + endDateInputStr: '', + activeDateInput: 'startValue', + startTimeInputStr: '', + endTimeInputStr: '', + inputing: false, // 当前是否处于输入状态 + panel: PANEL.DATE, + }; + } + + componentWillReceiveProps(nextProps) { + if ('showTime' in nextProps) { + const dateTimeFormat = getDateTimeFormat( + nextProps.format || this.props.format, + nextProps.showTime, + nextProps.type + ); + extend(dateTimeFormat, this); + } + + if ('value' in nextProps) { + const values = getFormatValues( + nextProps.value, + this.dateTimeFormat + ); + this.setState({ + startValue: values[0], + endValue: values[1], + }); + this.inputAsString = + nextProps.value && + (typeof nextProps.value[0] === 'string' || + typeof nextProps.value[1] === 'string'); + } + + if ('visible' in nextProps) { + this.setState({ + visible: nextProps.visible, + }); + } + } + + onValueChange = (values, handler = 'onChange') => { + let ret; + if (!values.length || !this.inputAsString) { + ret = values; + } else { + ret = [ + values[0] ? values[0].format(this.dateTimeFormat) : null, + values[1] ? values[1].format(this.dateTimeFormat) : null, + ]; + } + this.props[handler](ret); + }; + + onSelectCalendarPanel = (value, active) => { + const { showTime, resetTime } = this.props; + const { + activeDateInput: prevActiveDateInput, + startValue: prevStartValue, + endValue: prevEndValue, + } = this.state; + + const newState = { + activeDateInput: active || prevActiveDateInput, + inputing: false, + }; + + let newValue = value; + switch (active || prevActiveDateInput) { + case 'startValue': { + if ( + !prevEndValue || + value.valueOf() <= prevEndValue.valueOf() + ) { + newState.activeDateInput = 'endValue'; + } + + if (showTime) { + if (!prevStartValue) { + // 第一次选择,如果设置了时间默认值,则使用该默认时间 + if (showTime.defaultValue) { + const defaultTimeValue = formatDateValue( + Array.isArray(showTime.defaultValue) + ? showTime.defaultValue[0] + : showTime.defaultValue, + this.timeFormat + ); + newValue = resetValueTime(value, defaultTimeValue); + } + } else if (!resetTime) { + // 非第一次选择,如果开启了 resetTime ,则记住之前选择的时间值 + newValue = resetValueTime(value, prevStartValue); + } + } + + newState.startValue = newValue; + + if (prevEndValue && value.valueOf() > prevEndValue.valueOf()) { + newState.endValue = null; + newState.activeDateInput = 'endValue'; + } + break; + } + + case 'endValue': + if (!prevStartValue) { + newState.activeDateInput = 'startValue'; + } + + if (showTime) { + if (!prevEndValue) { + // 第一次选择,如果设置了时间默认值,则使用该默认时间 + if (showTime.defaultValue) { + const defaultTimeValue = formatDateValue( + Array.isArray(showTime.defaultValue) + ? showTime.defaultValue[1] || + showTime.defaultValue[0] + : showTime.defaultValue, + this.timeFormat + ); + newValue = resetValueTime(value, defaultTimeValue); + } + } else if (!resetTime) { + // 非第一次选择,如果开启了 resetTime ,则记住之前选择的时间值 + newValue = resetValueTime(value, prevEndValue); + } + } + + newState.endValue = newValue; + + // 选择了一个比开始日期更小的结束日期,此时表示用户重新选择了 + if ( + prevStartValue && + value.valueOf() < prevStartValue.valueOf() + ) { + newState.startValue = value; + newState.endValue = null; + } + break; + } + + const newStartValue = + 'startValue' in newState ? newState.startValue : prevStartValue; + const newEndValue = + 'endValue' in newState ? newState.endValue : prevEndValue; + + // 受控状态选择不更新值 + if ('value' in this.props) { + delete newState.startValue; + delete newState.endValue; + } + + this.setState(newState); + + this.onValueChange([newStartValue, newEndValue]); + }; + + clearRange = () => { + this.setState({ + startDateInputStr: '', + endDateInputStr: '', + startTimeInputStr: '', + endTimeInputStr: '', + }); + + if (!('value' in this.props)) { + this.setState({ + startValue: null, + endValue: null, + }); + } + + this.onValueChange([]); + }; + + onDateInputChange = (inputStr, e, eventType) => { + if (eventType === 'clear' || !inputStr) { + e.stopPropagation(); + this.clearRange(); + } else { + const stateName = mapInputStateName(this.state.activeDateInput); + this.setState({ + [stateName]: inputStr, + inputing: this.state.activeDateInput, + }); + } + }; + + onDateInputBlur = () => { + const stateName = mapInputStateName(this.state.activeDateInput); + const dateInputStr = this.state[stateName]; + if (dateInputStr) { + const { format, disabledDate } = this.props; + const parsed = moment(dateInputStr, format, true); + + this.setState({ + [stateName]: '', + inputing: false, + }); + + if (parsed.isValid() && !disabledDate(parsed, 'date')) { + const valueName = this.state.activeDateInput; + const newValue = parsed; + + this.handleChange(valueName, newValue); + } + } + }; + + onDateInputKeyDown = e => { + const { type } = this.props; + const { activeDateInput } = this.state; + const stateName = mapInputStateName(activeDateInput); + const dateInputStr = this.state[stateName]; + const dateStr = onDateKeydown( + e, + { + format: this.format, + value: this.state[activeDateInput], + dateInputStr, + }, + type === 'date' ? 'day' : type + ); + if (!dateStr) return; + + return this.onDateInputChange(dateStr); + }; + + onFocusDateInput = type => { + if (type !== this.state.activeDateInput) { + this.setState({ + activeDateInput: type, + }); + } + if (this.state.panel !== PANEL.DATE) { + this.setState({ + panel: PANEL.DATE, + }); + } + }; + + onFocusTimeInput = type => { + if (type !== this.state.activeDateInput) { + this.setState({ + activeDateInput: type, + }); + } + + if (this.state.panel !== PANEL.TIME) { + this.setState({ + panel: PANEL.TIME, + }); + } + }; + + onSelectStartTime = value => { + if (!('value' in this.props)) { + this.setState({ + startValue: value, + inputing: false, + activeDateInput: 'startTime', + }); + } + if (value.valueOf() !== this.state.startValue.valueOf()) { + this.onValueChange([value, this.state.endValue]); + } + }; + + onSelectEndTime = value => { + if (!('value' in this.props)) { + this.setState({ + endValue: value, + inputing: false, + activeDateInput: 'endTime', + }); + } + if (value.valueOf() !== this.state.endValue.valueOf()) { + this.onValueChange([this.state.startValue, value]); + } + }; + + onTimeInputChange = inputStr => { + const stateName = mapInputStateName(this.state.activeDateInput); + this.setState({ + [stateName]: inputStr, + inputing: this.state.activeDateInput, + }); + }; + + onTimeInputBlur = () => { + const stateName = mapInputStateName(this.state.activeDateInput); + const timeInputStr = this.state[stateName]; + if (timeInputStr) { + const parsed = moment(timeInputStr, this.timeFormat, true); + + this.setState({ + [stateName]: '', + inputing: false, + }); + + if (parsed.isValid()) { + const hour = parsed.hour(); + const minute = parsed.minute(); + const second = parsed.second(); + const valueName = mapTimeToValue(this.state.activeDateInput); + const newValue = this.state[valueName] + .clone() + .hour(hour) + .minute(minute) + .second(second); + + this.handleChange(valueName, newValue); + } + } + }; + + onTimeInputKeyDown = e => { + const { showTime } = this.props; + const { activeDateInput } = this.state; + const stateName = mapInputStateName(activeDateInput); + const timeInputStr = this.state[stateName]; + const { + disabledMinutes, + disabledSeconds, + hourStep = 1, + minuteStep = 1, + secondStep = 1, + } = typeof showTime === 'object' ? showTime : {}; + let unit = 'second'; + + if (disabledSeconds) { + unit = disabledMinutes ? 'hour' : 'minute'; + } + + const timeStr = onTimeKeydown( + e, + { + format: this.timeFormat, + timeInputStr, + value: this.state[ + activeDateInput.indexOf('start') ? 'startValue' : 'endValue' + ], + steps: { + hour: hourStep, + minute: minuteStep, + second: secondStep, + }, + }, + unit + ); + + if (!timeStr) return; + + this.onTimeInputChange(timeStr); + }; + + handleChange = (valueName, newValue) => { + if (!('value' in this.props)) { + this.setState({ + [valueName]: newValue, + }); + } + + const startValue = + valueName === 'startValue' ? newValue : this.state.startValue; + const endValue = + valueName === 'endValue' ? newValue : this.state.endValue; + + this.onValueChange([startValue, endValue]); + }; + + onVisibleChange = (visible, type) => { + if (!('visible' in this.props)) { + this.setState({ + visible, + }); + } + this.props.onVisibleChange(visible, type); + }; + + changePanel = panel => { + const { startValue, endValue } = this.state; + this.setState({ + panel, + activeDateInput: + panel === PANEL.DATE + ? !!startValue && !endValue + ? 'endValue' + : 'startValue' + : 'startTime', + }); + }; + + onOk = () => { + this.onVisibleChange(false, 'okBtnClick'); + this.onValueChange( + [this.state.startValue, this.state.endValue], + 'onOk' + ); + }; + + // 如果用户没有给定时间禁用逻辑,则给默认到禁用逻辑,即如果是同一天,则时间不能是同样的 + getDisabledTime = ({ startValue, endValue }) => { + const { disabledHours, disabledMinutes, disabledSeconds } = + this.props.showTime || {}; + + let disabledTime = {}; + + if (startValue && endValue) { + const isSameDay = startValue.format('L') === endValue.format('L'); + const newDisabledHours = isFunction(disabledHours) + ? disabledHours + : index => { + if (isSameDay && index < startValue.hour()) { + return true; + } + }; + + const newDisabledMinutes = isFunction(disabledMinutes) + ? disabledMinutes + : index => { + if ( + isSameDay && + startValue.hour() === endValue.hour() && + index < startValue.minute() + ) { + return true; + } + }; + + const newDisabledSeconds = isFunction(disabledSeconds) + ? disabledSeconds + : index => { + if ( + isSameDay && + startValue.hour() === endValue.hour() && + startValue.minute() === endValue.minute() && + index <= startValue.second() + ) { + return true; + } + }; + disabledTime = { + disabledHours: newDisabledHours, + disabledMinutes: newDisabledMinutes, + disabledSeconds: newDisabledSeconds, + }; + } + + return disabledTime; + }; + + renderPreview([startValue, endValue], others) { + const { prefix, format, className, renderPreview } = this.props; + + const previewCls = classnames(className, `${prefix}form-preview`); + const startLabel = startValue ? startValue.format(format) : ''; + const endLabel = endValue ? endValue.format(format) : ''; + + if (typeof renderPreview === 'function') { + return ( +
    + {renderPreview([startValue, endValue], this.props)} +
    + ); + } + + return ( +

    + {startLabel} - {endLabel} +

    + ); + } + + render() { + const { + prefix, + rtl, + type, + defaultVisibleMonth, + onVisibleMonthChange, + showTime, + disabledDate, + footerRender, + label, + ranges = {}, // 兼容0.x ranges 属性 + state: inputState, + size, + disabled, + hasClear, + popupTriggerType, + popupAlign, + popupContainer, + popupStyle, + popupClassName, + popupProps, + popupComponent, + popupContent, + followTrigger, + className, + locale, + inputProps, + dateCellRender, + monthCellRender, + yearCellRender, + startDateInputAriaLabel, + startTimeInputAriaLabel, + endDateInputAriaLabel, + endTimeInputAriaLabel, + isPreview, + disableChangeMode, + yearRange, + placeholder, + ...others + } = this.props; + + const state = this.state; + + const classNames = classnames( + { + [`${prefix}range-picker`]: true, + [`${prefix}${size}`]: size, + [`${prefix}disabled`]: disabled, + }, + className + ); + + const panelBodyClassName = classnames({ + [`${prefix}range-picker-body`]: true, + [`${prefix}range-picker-body-show-time`]: showTime, + }); + + const triggerCls = classnames({ + [`${prefix}range-picker-trigger`]: true, + [`${prefix}error`]: inputState === 'error', + }); + + const startDateInputCls = classnames({ + [`${prefix}range-picker-panel-input-start-date`]: true, + [`${prefix}focus`]: state.activeDateInput === 'startValue', + }); + + const endDateInputCls = classnames({ + [`${prefix}range-picker-panel-input-end-date`]: true, + [`${prefix}focus`]: state.activeDateInput === 'endValue', + }); + + if (rtl) { + others.dir = 'rtl'; + } + + if (isPreview) { + return this.renderPreview( + [state.startValue, state.endValue], + obj.pickOthers(others, RangePicker.PropTypes) + ); + } + + const startDateInputValue = + state.inputing === 'startValue' + ? state.startDateInputStr + : (state.startValue && state.startValue.format(this.format)) || + ''; + const endDateInputValue = + state.inputing === 'endValue' + ? state.endDateInputStr + : (state.endValue && state.endValue.format(this.format)) || ''; + + let startTriggerValue = startDateInputValue; + let endTriggerValue = endDateInputValue; + + const sharedInputProps = { + ...inputProps, + size, + disabled, + onChange: this.onDateInputChange, + onBlur: this.onDateInputBlur, + onPressEnter: this.onDateInputBlur, + onKeyDown: this.onDateInputKeyDown, + }; + + const startDateInput = ( + this.onFocusDateInput('startValue')} + className={startDateInputCls} + /> + ); + + const endDateInput = ( + this.onFocusDateInput('endValue')} + className={endDateInputCls} + /> + ); + + const shareCalendarProps = { + showOtherMonth: true, + dateCellRender: dateCellRender, + monthCellRender: monthCellRender, + yearCellRender: yearCellRender, + format: this.format, + defaultVisibleMonth: defaultVisibleMonth, + onVisibleMonthChange: onVisibleMonthChange, + }; + + const datePanel = + type === 'date' ? ( + + ) : ( +
    + { + return ( + state.endValue && + date.isAfter(state.endValue, type) + ); + }} + onSelect={value => { + const selectedValue = value + .clone() + .date(1) + .hour(0) + .minute(0) + .second(0); + if (type === 'year') { + selectedValue.month(0); + } + this.onSelectCalendarPanel( + selectedValue, + 'startValue' + ); + }} + value={state.startValue} + /> + { + return ( + state.startValue && + date.isBefore(state.startValue, type) + ); + }} + onSelect={value => { + const selectedValue = value + .clone() + .hour(23) + .minute(59) + .second(59); + if (type === 'year') { + selectedValue.month(11).date(31); + } else { + selectedValue.date(selectedValue.daysInMonth()); + } + this.onSelectCalendarPanel( + selectedValue, + 'endValue' + ); + }} + value={state.endValue} + /> +
    + ); + + let startTimeInput = null; + let endTimeInput = null; + let timePanel = null; + let panelFooter = footerRender(); + + if (showTime) { + const startTimeInputValue = + state.inputing === 'startTime' + ? state.startTimeInputStr + : (state.startValue && + state.startValue.format(this.timeFormat)) || + ''; + const endTimeInputValue = + state.inputing === 'endTime' + ? state.endTimeInputStr + : (state.endValue && + state.endValue.format(this.timeFormat)) || + ''; + + startTriggerValue = + (state.startValue && + state.startValue.format(this.dateTimeFormat)) || + ''; + endTriggerValue = + (state.endValue && + state.endValue.format(this.dateTimeFormat)) || + ''; + + const sharedTimeInputProps = { + size, + placeholder: this.timeFormat, + onFocus: this.onFocusTimeInput, + onBlur: this.onTimeInputBlur, + onPressEnter: this.onTimeInputBlur, + onChange: this.onTimeInputChange, + onKeyDown: this.onTimeInputKeyDown, + }; + + const startTimeInputCls = classnames({ + [`${prefix}range-picker-panel-input-start-time`]: true, + [`${prefix}focus`]: state.activeDateInput === 'startTime', + }); + + startTimeInput = ( + this.onFocusTimeInput('startTime')} + className={startTimeInputCls} + /> + ); + + const endTimeInputCls = classnames({ + [`${prefix}range-picker-panel-input-end-time`]: true, + [`${prefix}focus`]: state.activeDateInput === 'endTime', + }); + + endTimeInput = ( + this.onFocusTimeInput('endTime')} + className={endTimeInputCls} + /> + ); + + const showSecond = this.timeFormat.indexOf('s') > -1; + const showMinute = this.timeFormat.indexOf('m') > -1; + + const sharedTimePickerProps = { + ...showTime, + prefix, + locale, + disabled, + showSecond, + showMinute, + }; + + const disabledTime = this.getDisabledTime(state); + + timePanel = ( +
    + + +
    + ); + } + + panelFooter = panelFooter || ( + ({ + label: key, + value: ranges[key], + onChange: values => { + this.setState({ + startValue: values[0], + endValue: values[1], + }); + this.onValueChange(values); + }, + }))} + disabledOk={ + !state.startValue || + !state.endValue || + state.startValue.valueOf() > state.endValue.valueOf() + } + locale={locale} + panel={state.panel} + onPanelChange={showTime ? this.changePanel : null} + onOk={this.onOk} + /> + ); + + const panelBody = { + [PANEL.DATE]: datePanel, + [PANEL.TIME]: timePanel, + }[state.panel]; + + const allowClear = state.startValue && state.endValue && hasClear; + let [startPlaceholder, endPlaceholder] = placeholder || []; + + if (typeof placeholder === 'string') { + startPlaceholder = placeholder; + endPlaceholder = placeholder; + } + + const trigger = ( +
    + this.onFocusDateInput('startValue')} + /> + + - + + this.onFocusDateInput('endValue')} + hasClear={allowClear} + hint="calendar" + /> +
    + ); + + const PopupComponent = popupComponent ? popupComponent : Popup; + + return ( +
    + + {popupContent ? ( + popupContent + ) : ( +
    +
    +
    + {startDateInput} + {startTimeInput} + + - + + {endDateInput} + {endTimeInput} +
    +
    + {panelBody} + {panelFooter} +
    + )} +
    +
    + ); + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/rtl.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/rtl.scss new file mode 100644 index 000000000..6789618cb --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/rtl.scss @@ -0,0 +1,75 @@ +#{$date-picker-prefix}-body[dir="rtl"] { + #{$date-picker-prefix}-panel-footer { + text-align: left; + } + #{$date-picker-prefix}-panel-footer > #{$date-picker-btn-prefix}:not(:last-child) { + margin-right: 0; + margin-left: $s-4; + } +} + +#{$date-picker-prefix}-body[dir="rtl"]#{$date-picker-prefix}-body-show-time { + #{$date-picker-prefix}-panel-input#{$date-picker-input-prefix} { + &:first-child { + margin-left: 2%; + margin-right: 0; + } + } + #{$time-picker-prefix}-menu { + float: right; + &:not(:last-child) { + border-right: none; + border-left: $time-picker-menu-border-width $line-solid $time-picker-menu-border-color; + } + } +} + + +#{$range-picker-prefix}-body[dir="rtl"] { + #{$range-picker-prefix}-panel-input { + text-align: right; + } + #{$date-picker-prefix}-panel-footer { + text-align: left; + } + #{$date-picker-prefix}-panel-footer > #{$date-picker-btn-prefix}:not(:last-child) { + margin-right: 0; + margin-left: $s-4; + } +} + +#{$range-picker-prefix}-body[dir="rtl"]#{$range-picker-prefix}-body-show-time { + #{$range-picker-prefix}-panel { + &-input-start-date { + margin-right: 0; + margin-left: $s-2; + } + + &-input-end-time { + margin-left: 0; + margin-right: $s-2; + } + + &-time-start, &-time-end { + float: right; + } + &-time-start { + // Extend time-picker border + border-right: none; + border-left: $line-1 $line-solid $date-picker-panel-time-panel-separator-color; + } + + &-time-end { + // Extend time-picker border + border-left: none; + border-right: $line-1 $line-solid $date-picker-panel-time-panel-separator-color; + } + } + #{$time-picker-prefix}-menu { + float: right; + &:not(:last-child) { + border-right: none; + border-left: $time-picker-menu-border-width $line-solid $time-picker-menu-border-color; + } + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/scss/date-picker.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/scss/date-picker.scss new file mode 100644 index 000000000..8bd652b10 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/scss/date-picker.scss @@ -0,0 +1,33 @@ +// +// date-picker 样式 +// +#{$date-picker-prefix}, +#{$month-picker-prefix}, +#{$year-picker-prefix}, +#{$week-picker-prefix} { + display: inline-block; + width: $s-50; + + &-input { + width: 100%; + } + + &-body { + width: $s-18 * 4; + } + + &-panel-input#{$date-picker-input-prefix} { + width: 100%; + background: $color-transparent; + } +} + +#{$date-picker-prefix}-body#{$date-picker-prefix}-body-show-time { + #{$date-picker-prefix}-panel-input#{$date-picker-input-prefix} { + width: 49%; + + &:first-child { + margin-right: 2%; + } + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/scss/mixin.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/scss/mixin.scss new file mode 100755 index 000000000..254a60903 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/scss/mixin.scss @@ -0,0 +1,18 @@ + +%input-separator { + cursor: default; + display: inline-block; + text-align: center; + color: $color-text1-1; + width: $date-picker-input-separator-width; + font-size: $font-size-caption; + vertical-align: middle; +} + +@mixin range-picker-input-corner($corner) { + #{$range-picker-prefix} { + &-trigger, &-panel-input { + border-radius: $corner; + } + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/scss/range-picker.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/scss/range-picker.scss new file mode 100644 index 000000000..10b74dc07 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/scss/range-picker.scss @@ -0,0 +1,111 @@ +// +// date-picker 样式 +// +#{$range-picker-prefix} { + + display: inline-block; + width: $s-28 * 3; + + &-input { + width: 100%; + } + + &-trigger { + // Extend next-input + border: $input-border-width solid $input-border-color; + background-color: $input-bg-color; + + // Extend next-input + &:hover { + border-color: $input-hover-border-color; + background-color: $input-hover-bg-color; + } + + // Extend next-input + &.#{$css-prefix}error { + border-color: $input-feedback-error-border-color; + } + + &-separator { + @extend %input-separator; + } + + &-input#{$date-picker-input-prefix} { + height: auto; + width: calc((100% - #{$date-picker-input-separator-width}) / 2); + } + } + + &.#{$css-prefix}disabled { + #{$range-picker-prefix}-trigger { + cursor: not-allowed; + @include input-disabled(); + } + } + + &.#{$css-prefix}large { + @include range-picker-input-corner($form-element-large-corner); + } + + &.#{$css-prefix}medium { + @include range-picker-input-corner($form-element-medium-corner); + } + + &.#{$css-prefix}small { + @include range-picker-input-corner($form-element-small-corner); + } + + &-body { + width: $s-30 * 5; + } + + &-panel { + &-input-separator { + @extend %input-separator; + } + + &-input-start-date#{$date-picker-input-prefix}, + &-input-end-date#{$date-picker-input-prefix} { + width: calc((100% - #{$date-picker-input-separator-width}) / 2); + } + } +} + +#{$range-picker-prefix}-body#{$range-picker-prefix}-body-show-time { + #{$range-picker-prefix}-panel { + &-input-start-date, + &-input-end-date, + &-input-start-time, + &-input-end-time { + width: calc((100% - #{$date-picker-input-separator-width} - #{$s-4}) / 4); + } + + &-input-start-date { + margin-right: $s-2; + } + + &-input-end-time { + margin-left: $s-2; + } + + // time-panel + &-time { + @include clearfix; + } + + &-time-start, &-time-end { + width: 50%; + float: left; + } + + &-time-start { + // Extend time-picker border + border-right: $line-1 $line-solid $date-picker-panel-time-panel-separator-color; + } + + &-time-end { + // Extend time-picker border + border-left: $line-1 $line-solid $date-picker-panel-time-panel-separator-color; + } + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/scss/variable.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/scss/variable.scss new file mode 100644 index 000000000..77b3cfcae --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/scss/variable.scss @@ -0,0 +1,50 @@ +//// +/// @module date-picker: 日期选择 +/// @tag DatePicker +/// @category component +/// @family data-entry +/// @varPrefix $date-picker +/// @classPrefix {prefix}-date-picker +/// @order {"size/panel footer":10,"statement/normal":10,"statement/normal/panel":100} +//// + + +$date-picker-prefix: '.' + $css-prefix + 'date-picker'; + +$range-picker-prefix: '.' + $css-prefix + 'range-picker'; + +$month-picker-prefix: '.' + $css-prefix + 'month-picker'; + +$year-picker-prefix: '.' + $css-prefix + 'year-picker'; + +$week-picker-prefix: '.' + $css-prefix + 'week-picker'; + +$date-picker-btn-prefix: '.' + $css-prefix + 'btn'; + +$date-picker-input-prefix: '.' + $css-prefix + 'input'; + +$date-picker-time-prefix: '.' + $css-prefix + 'time-picker'; + +/// 日期输入框 +// -------------------------------------------------- + +$date-picker-input-separator-width: $s-4 !default; + +// 日期选择面板 +// -------------------------------------------------- + +/// padding (l, r) +/// @namespace size/panel footer +$date-picker-panel-footer-padding-lr: $s-5 !default; + +/// padding (t, b) +/// @namespace size/panel footer +$date-picker-panel-footer-padding-tb: $s-2 !default; + +/// background +/// @namespace statement/normal/panel +$date-picker-panel-background: $color-white !default; + +/// separator border +/// @namespace statement/normal/panel +$date-picker-panel-time-panel-separator-color: $color-line1-2 !default; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/style.js b/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/style.js new file mode 100644 index 000000000..6c3649c3d --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/style.js @@ -0,0 +1,6 @@ +import '../input/style.js'; +import '../overlay/style.js'; +import '../calendar/style.js'; +import '../time-picker/style.js'; +import '../button/style.js'; +import './main.scss'; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/util/index.js b/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/util/index.js new file mode 100644 index 000000000..bbd97ab3d --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/util/index.js @@ -0,0 +1,183 @@ +import moment from 'moment'; +import { KEYCODE } from '../../util'; + +export const PANEL = { + TIME: 'time-panel', + DATE: 'date-panel', +}; + +export const DEFAULT_TIME_FORMAT = 'HH:mm:ss'; + +export function isFunction(obj) { + return !!(obj && obj.constructor && obj.call && obj.apply); +} + +/** + * 将 source 的 time 替换为 target 的 time + * @param {Object} source 输入值 + * @param {Object} target 目标值 + */ +export function resetValueTime(source, target) { + if (!moment.isMoment(source) || !moment.isMoment(target)) { + return source; + } + return source + .clone() + .hour(target.hour()) + .minute(target.minute()) + .second(target.second()); +} + +export function formatDateValue(value, format) { + const val = + typeof value === 'string' ? moment(value, format, false) : value; + if (val && moment.isMoment(val) && val.isValid()) { + return val; + } + + return null; +} + +export function checkDateValue(props, propName, componentName) { + // 支持传入 moment 对象或字符串,字符串不检测是否为日期字符串 + if ( + props[propName] && + !moment.isMoment(props[propName]) && + typeof props[propName] !== 'string' + ) { + return new Error( + `Invalid prop ${propName} supplied to ${componentName}. Required a moment object or format date string!` + ); + } +} + +export function getDateTimeFormat(format, showTime, type) { + if (!format && type) { + format = { + date: 'YYYY-MM-DD', + month: 'YYYY-MM', + year: 'YYYY', + time: '', + }[type]; + } + const timeFormat = showTime ? showTime.format || DEFAULT_TIME_FORMAT : ''; + const dateTimeFormat = timeFormat ? `${format} ${timeFormat}` : format; + return { + format, + timeFormat, + dateTimeFormat, + }; +} + +export function extend(source, target) { + for (const key in source) { + if (source.hasOwnProperty(key)) { + target[key] = source[key]; + } + } + return target; +} + +/** + * 监听键盘事件,操作日期字符串 + * @param {KeyboardEvent} e 事件对象 + * @param {Object} param1 + * @param {String} type 类型 year month day + */ +export function onDateKeydown(e, { format, dateInputStr, value }, type) { + if ( + [KEYCODE.UP, KEYCODE.DOWN, KEYCODE.PAGE_UP, KEYCODE.PAGE_DOWN].indexOf( + e.keyCode + ) === -1 + ) { + return; + } + + if ( + (e.altKey && + [KEYCODE.PAGE_UP, KEYCODE.PAGE_DOWN].indexOf(e.keyCode) === -1) || + e.controlKey || + e.shiftKey + ) { + return; + } + + let date = moment(dateInputStr, format, true); + + if (date.isValid()) { + const stepUnit = e.altKey ? 'year' : 'month'; + switch (e.keyCode) { + case KEYCODE.UP: + date.subtract(1, type); + break; + case KEYCODE.DOWN: + date.add(1, type); + break; + case KEYCODE.PAGE_UP: + date.subtract(1, stepUnit); + break; + case KEYCODE.PAGE_DOWN: + date.add(1, stepUnit); + break; + } + } else if (value) { + date = value.clone(); + } else { + date = moment(); + } + + e.preventDefault(); + return date.format(format); +} + +/** + * 监听键盘事件,操作时间 + * @param {KeyboardEvent} e + * @param {Object} param1 + * @param {String} type second hour minute + */ +export function onTimeKeydown(e, { format, timeInputStr, steps, value }, type) { + if ( + [KEYCODE.UP, KEYCODE.DOWN, KEYCODE.PAGE_UP, KEYCODE.PAGE_DOWN].indexOf( + e.keyCode + ) === -1 + ) + return; + if ( + (e.altKey && + [KEYCODE.PAGE_UP, KEYCODE.PAGE_DOWN].indexOf(e.keyCode) === -1) || + e.controlKey || + e.shiftKey + ) + return; + + let time = moment(timeInputStr, format, true); + + if (time.isValid()) { + const stepUnit = e.altKey ? 'hour' : 'minute'; + switch (e.keyCode) { + case KEYCODE.UP: + time.subtract(steps[type], type); + break; + case KEYCODE.DOWN: + time.add(steps[type], type); + break; + case KEYCODE.PAGE_UP: + time.subtract(steps[stepUnit], stepUnit); + break; + case KEYCODE.PAGE_DOWN: + time.add(steps[stepUnit], stepUnit); + break; + } + } else if (value) { + time = value.clone(); + } else { + time = moment() + .hours(0) + .minutes(0) + .seconds(0); + } + + e.preventDefault(); + return time.format(format); +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/week-picker.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/week-picker.jsx new file mode 100644 index 000000000..bd398a5d1 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/week-picker.jsx @@ -0,0 +1,464 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import moment from 'moment'; +import { polyfill } from 'react-lifecycles-compat'; +import Overlay from '../overlay'; +import Input from '../input'; +import Calendar from '../calendar'; +import ConfigProvider from '../config-provider'; +import nextLocale from '../locale/zh-cn'; +import { func, obj, KEYCODE } from '../util'; +import { checkDateValue, formatDateValue } from './util'; + +const { Popup } = Overlay; + +/** + * DatePicker.WeekPicker + */ +class WeekPicker extends Component { + static propTypes = { + ...ConfigProvider.propTypes, + prefix: PropTypes.string, + rtl: PropTypes.bool, + /** + * 输入框内置标签 + */ + label: PropTypes.node, + /** + * 输入框状态 + */ + state: PropTypes.oneOf(['success', 'loading', 'error']), + /** + * 输入提示 + */ + placeholder: PropTypes.string, + /** + * 默认展现的月 + * @return {MomentObject} 返回包含指定月份的 moment 对象实例 + */ + defaultVisibleMonth: PropTypes.func, + onVisibleMonthChange: PropTypes.func, + /** + * 日期值(受控)moment 对象 + */ + value: checkDateValue, + /** + * 初始日期值,moment 对象 + */ + defaultValue: checkDateValue, + /** + * 日期值的格式(用于限定用户输入和展示) + */ + format: PropTypes.string, + /** + * 禁用日期函数 + * @param {MomentObject} 日期值 + * @param {String} view 当前视图类型,year: 年, month: 月, date: 日 + * @return {Boolean} 是否禁用 + */ + disabledDate: PropTypes.func, + /** + * 自定义面板页脚 + * @return {Node} 自定义的面板页脚组件 + */ + footerRender: PropTypes.func, + /** + * 日期值改变时的回调 + * @param {MomentObject|String} value 日期值 + */ + onChange: PropTypes.func, + /** + * 输入框尺寸 + */ + size: PropTypes.oneOf(['small', 'medium', 'large']), + /** + * 是否禁用 + */ + disabled: PropTypes.bool, + /** + * 是否显示清空按钮 + */ + hasClear: PropTypes.bool, + /** + * 弹层显示状态 + */ + visible: PropTypes.bool, + /** + * 弹层默认是否显示 + */ + defaultVisible: PropTypes.bool, + /** + * 弹层展示状态变化时的回调 + * @param {Boolean} visible 弹层是否显示 + * @param {String} type 触发弹层显示和隐藏的来源 calendarSelect 表示由日期表盘的选择触发; okBtnClick 表示由确认按钮触发; fromTrigger 表示由trigger的点击触发; docClick 表示由document的点击触发 + */ + onVisibleChange: PropTypes.func, + /** + * 弹层触发方式 + */ + popupTriggerType: PropTypes.oneOf(['click', 'hover']), + /** + * 弹层对齐方式,具体含义见 OverLay文档 + */ + popupAlign: PropTypes.string, + /** + * 弹层容器 + * @param {Element} target 目标元素 + * @return {Element} 弹层的容器元素 + */ + popupContainer: PropTypes.any, + /** + * 弹层自定义样式 + */ + popupStyle: PropTypes.object, + /** + * 弹层自定义样式类 + */ + popupClassName: PropTypes.string, + /** + * 弹层其他属性 + */ + popupProps: PropTypes.object, + /** + * 是否跟随滚动 + */ + followTrigger: PropTypes.bool, + /** + * 输入框其他属性 + */ + inputProps: PropTypes.object, + /** + * 自定义日期渲染函数 + * @param {Object} value 日期值(moment对象) + * @returns {ReactNode} + */ + dateCellRender: PropTypes.func, + /** + * 自定义月份渲染函数 + * @param {Object} calendarDate 对应 Calendar 返回的自定义日期对象 + * @returns {ReactNode} + */ + monthCellRender: PropTypes.func, + /** + * 是否为预览态 + */ + isPreview: PropTypes.bool, + /** + * 预览态模式下渲染的内容 + * @param {MomentObject} value 年份 + */ + renderPreview: PropTypes.func, + yearCellRender: PropTypes.func, // 兼容 0.x yearCellRender + locale: PropTypes.object, + className: PropTypes.string, + name: PropTypes.string, + popupComponent: PropTypes.elementType, + popupContent: PropTypes.node, + }; + + static defaultProps = { + prefix: 'next-', + rtl: false, + format: 'YYYY-wo', + size: 'medium', + disabledDate: () => false, + footerRender: () => null, + hasClear: true, + popupTriggerType: 'click', + popupAlign: 'tl tl', + locale: nextLocale.DatePicker, + defaultVisible: false, + onChange: func.noop, + onVisibleChange: func.noop, + }; + + constructor(props, context) { + super(props, context); + + const value = formatDateValue( + props.value || props.defaultValue, + props.format + ); + + this.state = { + value, + visible: props.visible || props.defaultVisible, + }; + } + + static getDerivedStateFromProps(props) { + const st = {}; + if ('value' in props) { + st.value = formatDateValue(props.value, props.format); + } + + if ('visible' in props) { + st.visible = props.visible; + } + + return st; + } + + handleChange = (newValue, prevValue) => { + if (!('value' in this.props)) { + this.setState({ + value: newValue, + }); + } + + const newValueOf = newValue ? newValue.valueOf() : null; + const preValueOf = prevValue ? prevValue.valueOf() : null; + + if (newValueOf !== preValueOf) { + this.props.onChange(newValue); + } + }; + + onDateInputChange = (value, e, eventType) => { + if (eventType === 'clear' || !value) { + e.stopPropagation(); + this.handleChange(null, this.state.value); + } + }; + + onKeyDown = e => { + if ( + [ + KEYCODE.UP, + KEYCODE.DOWN, + KEYCODE.PAGE_UP, + KEYCODE.PAGE_DOWN, + ].indexOf(e.keyCode) === -1 + ) { + return; + } + + if ( + (e.altKey && + [KEYCODE.PAGE_UP, KEYCODE.PAGE_DOWN].indexOf(e.keyCode) === + -1) || + e.controlKey || + e.shiftKey + ) { + return; + } + + let date = this.state.value; + + if (date && date.isValid()) { + const stepUnit = e.altKey ? 'year' : 'month'; + switch (e.keyCode) { + case KEYCODE.UP: + date.subtract(1, 'w'); + break; + case KEYCODE.DOWN: + date.add(1, 'w'); + break; + case KEYCODE.PAGE_UP: + date.subtract(1, stepUnit); + break; + case KEYCODE.PAGE_DOWN: + date.add(1, stepUnit); + break; + } + } else { + date = moment(); + } + + e.preventDefault(); + + this.handleChange(date, this.state.value); + }; + + onVisibleChange = (visible, type) => { + if (!('visible' in this.props)) { + this.setState({ + visible, + }); + } + this.props.onVisibleChange(visible, type); + }; + + onSelectCalendarPanel = value => { + this.handleChange(value, this.state.value); + this.onVisibleChange(false, 'calendarSelect'); + }; + + renderPreview(others) { + const { prefix, format, className, renderPreview } = this.props; + const { value } = this.state; + const previewCls = classnames(className, `${prefix}form-preview`); + + const label = value ? value.format(format) : ''; + + if (typeof renderPreview === 'function') { + return ( +
    + {renderPreview(value, this.props)} +
    + ); + } + + return ( +

    + {label} +

    + ); + } + + dateRender = value => { + const { prefix, dateCellRender } = this.props; + const selectedValue = this.state.value; + const content = + dateCellRender && typeof dateCellRender === 'function' + ? dateCellRender(value) + : value.dates(); + if ( + selectedValue && + selectedValue.years() === value.years() && + selectedValue.weeks() === value.weeks() + ) { + const firstDay = moment.localeData().firstDayOfWeek(); + const endDay = firstDay - 1 < 0 ? 6 : firstDay - 1; + return ( +
    + {content} +
    + ); + } + + return content; + }; + + render() { + const { + prefix, + rtl, + locale, + label, + state, + format, + defaultVisibleMonth, + onVisibleMonthChange, + disabledDate, + footerRender, + placeholder, + size, + disabled, + hasClear, + popupTriggerType, + popupAlign, + popupContainer, + popupStyle, + popupClassName, + popupProps, + popupComponent, + popupContent, + followTrigger, + className, + inputProps, + monthCellRender, + yearCellRender, + isPreview, + ...others + } = this.props; + const { visible, value } = this.state; + + const sharedInputProps = { + ...inputProps, + size, + disabled, + onChange: this.onDateInputChange, + onKeyDown: this.onKeyDown, + }; + + if (rtl) { + others.dir = 'rtl'; + } + + if (isPreview) { + return this.renderPreview( + obj.pickOthers(others, WeekPicker.PropTypes) + ); + } + + const trigger = ( +
    + +
    + ); + + const PopupComponent = popupComponent ? popupComponent : Popup; + + return ( +
    + + {popupContent ? ( + popupContent + ) : ( +
    + + {footerRender()} +
    + )} +
    +
    + ); + } +} + +export default polyfill(WeekPicker); diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/year-picker.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/year-picker.jsx new file mode 100644 index 000000000..b9954b818 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/date-picker/year-picker.jsx @@ -0,0 +1,488 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import moment from 'moment'; +import Overlay from '../overlay'; +import Input from '../input'; +import Calendar from '../calendar'; +import nextLocale from '../locale/zh-cn'; +import { func, obj } from '../util'; +import { checkDateValue, formatDateValue, onDateKeydown } from './util'; + +const { Popup } = Overlay; + +/** + * DatePicker.YearPicker + */ +class YearPicker extends Component { + static propTypes = { + prefix: PropTypes.string, + rtl: PropTypes.bool, + /** + * 输入框内置标签 + */ + label: PropTypes.node, + /** + * 输入框状态 + */ + state: PropTypes.oneOf(['success', 'loading', 'error']), + /** + * 输入提示 + */ + placeholder: PropTypes.string, + /** + * 日期值(受控)moment 对象 + */ + value: checkDateValue, + /** + * 初始日期值,moment 对象 + */ + defaultValue: checkDateValue, + /** + * 日期值的格式(用于限定用户输入和展示) + */ + format: PropTypes.string, + /** + * 禁用日期函数 + * @param {MomentObject} 日期值 + * @param {String} view 当前视图类型,year: 年, month: 月, date: 日 + * @return {Boolean} 是否禁用 + */ + disabledDate: PropTypes.func, + /** + * 自定义面板页脚 + * @return {Node} 自定义的面板页脚组件 + */ + footerRender: PropTypes.func, + /** + * 日期值改变时的回调 + * @param {MomentObject|String} value 日期值 + */ + onChange: PropTypes.func, + /** + * 输入框尺寸 + */ + size: PropTypes.oneOf(['small', 'medium', 'large']), + /** + * 是否禁用 + */ + disabled: PropTypes.bool, + /** + * 是否显示清空按钮 + */ + hasClear: PropTypes.bool, + /** + * 弹层显示状态 + */ + visible: PropTypes.bool, + /** + * 弹层默认是否显示 + */ + defaultVisible: PropTypes.bool, + /** + * 弹层展示状态变化时的回调 + * @param {Boolean} visible 弹层是否显示 + * @param {String} reason 触发弹层显示和隐藏的来源 calendarSelect 表示由日期表盘的选择触发; fromTrigger 表示由trigger的点击触发; docClick 表示由document的点击触发 + */ + onVisibleChange: PropTypes.func, + /** + * 弹层触发方式 + */ + popupTriggerType: PropTypes.oneOf(['click', 'hover']), + /** + * 弹层对齐方式, 具体含义见 OverLay文档 + */ + popupAlign: PropTypes.string, + /** + * 弹层容器 + * @param {Element} target 目标元素 + * @return {Element} 弹层的容器元素 + */ + popupContainer: PropTypes.any, + /** + * 弹层自定义样式 + */ + popupStyle: PropTypes.object, + /** + * 弹层自定义样式类 + */ + popupClassName: PropTypes.string, + /** + * 弹层其他属性 + */ + popupProps: PropTypes.object, + /** + * 是否跟随滚动 + */ + followTrigger: PropTypes.bool, + /** + * 输入框其他属性 + */ + inputProps: PropTypes.object, + yearCellRender: PropTypes.func, // 兼容 0.x yearCellRender + /** + * 日期输入框的 aria-label 属性 + */ + dateInputAriaLabel: PropTypes.string, + /** + * 是否为预览态 + */ + isPreview: PropTypes.bool, + /** + * 预览态模式下渲染的内容 + * @param {MomentObject} value 年份 + */ + renderPreview: PropTypes.func, + locale: PropTypes.object, + className: PropTypes.string, + name: PropTypes.string, + popupComponent: PropTypes.elementType, + popupContent: PropTypes.node, + }; + + static defaultProps = { + prefix: 'next-', + rtl: false, + format: 'YYYY', + size: 'medium', + disabledDate: () => false, + footerRender: () => null, + hasClear: true, + popupTriggerType: 'click', + popupAlign: 'tl tl', + locale: nextLocale.DatePicker, + onChange: func.noop, + onVisibleChange: func.noop, + }; + + constructor(props, context) { + super(props, context); + + const value = formatDateValue( + props.value || props.defaultValue, + props.format + ); + + this.inputAsString = + typeof (props.value || props.defaultValue) === 'string'; // 判断用户输入是否是字符串 + this.state = { + value, + dateInputStr: '', + inputing: false, + visible: props.visible || props.defaultVisible, + }; + } + + componentWillReceiveProps(nextProps) { + if ('value' in nextProps) { + const value = formatDateValue( + nextProps.value, + nextProps.format || this.props.format + ); + this.setState({ + value, + }); + this.inputAsString = typeof nextProps.value === 'string'; + } + + if ('visible' in nextProps) { + this.setState({ + visible: nextProps.visible, + }); + } + } + + onValueChange = newValue => { + const ret = + this.inputAsString && newValue + ? newValue.format(this.props.format) + : newValue; + this.props.onChange(ret); + }; + + onSelectCalendarPanel = value => { + // const { format } = this.props; + const prevSelectedMonth = this.state.value; + const selectedMonth = value + .clone() + .month(0) + .date(1) + .hour(0) + .minute(0) + .second(0); + + this.handleChange( + selectedMonth, + prevSelectedMonth, + { inputing: false }, + () => { + this.onVisibleChange(false, 'calendarSelect'); + } + ); + }; + + clearValue = () => { + this.setState({ + dateInputStr: '', + }); + + this.handleChange(null, this.state.value); + }; + + onDateInputChange = (inputStr, e, eventType) => { + if (eventType === 'clear' || !inputStr) { + e.stopPropagation(); + this.clearValue(); + } else { + this.setState({ + dateInputStr: inputStr, + inputing: true, + }); + } + }; + + onDateInputBlur = () => { + const { dateInputStr } = this.state; + if (dateInputStr) { + const { disabledDate, format } = this.props; + const parsed = moment(dateInputStr, format, true); + + this.setState({ + dateInputStr: '', + inputing: false, + }); + + if (parsed.isValid() && !disabledDate(parsed, 'year')) { + this.handleChange(parsed, this.state.value); + } + } + }; + + onKeyDown = e => { + const { format } = this.props; + const { dateInputStr, value } = this.state; + const dateStr = onDateKeydown( + e, + { format, dateInputStr, value }, + 'year' + ); + if (!dateStr) return; + this.onDateInputChange(dateStr); + }; + + handleChange = (newValue, prevValue, others = {}, callback) => { + if (!('value' in this.props)) { + this.setState({ + value: newValue, + ...others, + }); + } else { + this.setState({ + ...others, + }); + } + + const { format } = this.props; + + const newValueOf = newValue ? newValue.format(format) : null; + const preValueOf = prevValue ? prevValue.format(format) : null; + + if (newValueOf !== preValueOf) { + this.onValueChange(newValue); + if (typeof callback === 'function') { + return callback(); + } + } + }; + + onVisibleChange = (visible, reason) => { + if (!('visible' in this.props)) { + this.setState({ + visible, + }); + } + this.props.onVisibleChange(visible, reason); + }; + + renderPreview(others) { + const { prefix, format, className, renderPreview } = this.props; + const { value } = this.state; + const previewCls = classnames(className, `${prefix}form-preview`); + + const label = value ? value.format(format) : ''; + + if (typeof renderPreview === 'function') { + return ( +
    + {renderPreview(value, this.props)} +
    + ); + } + + return ( +

    + {label} +

    + ); + } + + render() { + const { + prefix, + rtl, + locale, + label, + state, + format, + disabledDate, + footerRender, + placeholder, + size, + disabled, + hasClear, + popupTriggerType, + popupAlign, + popupContainer, + popupStyle, + popupClassName, + popupProps, + popupComponent, + popupContent, + followTrigger, + className, + inputProps, + dateInputAriaLabel, + yearCellRender, + isPreview, + ...others + } = this.props; + + const { visible, value, dateInputStr, inputing } = this.state; + + const yearPickerCls = classnames( + { + [`${prefix}year-picker`]: true, + }, + className + ); + + const triggerInputCls = classnames({ + [`${prefix}year-picker-input`]: true, + [`${prefix}error`]: false, + }); + + const panelBodyClassName = classnames({ + [`${prefix}year-picker-body`]: true, + }); + + if (rtl) { + others.dir = 'rtl'; + } + + if (isPreview) { + return this.renderPreview( + obj.pickOthers(others, YearPicker.PropTypes) + ); + } + + const panelInputCls = `${prefix}year-picker-panel-input`; + + const sharedInputProps = { + ...inputProps, + size, + disabled, + onChange: this.onDateInputChange, + onBlur: this.onDateInputBlur, + onPressEnter: this.onDateInputBlur, + onKeyDown: this.onKeyDown, + }; + + const dateInputValue = inputing + ? dateInputStr + : (value && value.format(format)) || ''; + const triggerInputValue = dateInputValue; + + const dateInput = ( + + ); + + const datePanel = ( + + ); + + const panelBody = datePanel; + const panelFooter = footerRender(); + + const allowClear = value && hasClear; + const trigger = ( +
    + +
    + ); + + const PopupComponent = popupComponent ? popupComponent : Popup; + + return ( +
    + + {popupContent ? ( + popupContent + ) : ( +
    +
    + {dateInput} +
    + {panelBody} + {panelFooter} +
    + )} +
    +
    + ); + } +} + +export default YearPicker; diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/demo-helper/.stylelintrc b/packages/material-parser/test/fixtures/fusion-next-component/src/demo-helper/.stylelintrc new file mode 100644 index 000000000..78845e416 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/demo-helper/.stylelintrc @@ -0,0 +1,13 @@ +{ + "extends": [ + "@alifd/stylelint-config-next" + ], + "rules": { + "max-nesting-depth": null, + "max-empty-lines": 3, + "no-duplicate-selectors": null, + "no-descending-specificity": null, + "font-family-no-missing-generic-family-keyword": null, + "selector-max-class": null + } +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/demo-helper/icon.scss b/packages/material-parser/test/fixtures/fusion-next-component/src/demo-helper/icon.scss new file mode 100644 index 000000000..570f1d982 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/demo-helper/icon.scss @@ -0,0 +1,471 @@ +@font-face { + /* project id 272666 */ + font-family: 'iconfont'; + src: url('//at.alicdn.com/t/font_o8u52jwbfgm8to6r.eot'); + src: url('//at.alicdn.com/t/font_o8u52jwbfgm8to6r.eot?#iefix') format('embedded-opentype'), url('//at.alicdn.com/t/font_o8u52jwbfgm8to6r.woff') format('woff'), url('//at.alicdn.com/t/font_o8u52jwbfgm8to6r.ttf') format('truetype'), url('//at.alicdn.com/t/font_o8u52jwbfgm8to6r.svg#iconfont') format('svg'); +} + +.demo-icon { + font-family: 'iconfont' !important; + font-size: 12px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + cursor: pointer; +} + +.demo-icon-all:before { + content: "\e662"; +} + +.demo-icon-cart:before { + content: "\e618"; +} + +.demo-icon-comments:before { + content: "\e605"; +} + +.demo-icon-cry:before { + content: "\e61a"; +} + +.demo-icon-email:before { + content: "\e663"; +} + +.demo-icon-favorite:before { + content: "\e60a"; +} + +.demo-icon-folder:before { + content: "\e61b"; +} + +.demo-icon-form:before { + content: "\e61c"; +} + +.demo-icon-help:before { + content: "\e61f"; +} + +.demo-icon-refresh:before { + content: "\e621"; +} + +.demo-icon-set:before { + content: "\e623"; +} + +.demo-icon-training:before { + content: "\e624"; +} + +.demo-icon-account:before { + content: "\e664"; +} + +.demo-icon-atm:before { + content: "\e626"; +} + +.demo-icon-clock:before { + content: "\e615"; +} + +.demo-icon-attachment:before { + content: "\e627"; +} + +.demo-icon-3column:before { + content: "\e628"; +} + +.demo-icon-4column:before { + content: "\e629"; +} + +.demo-icon-discount:before { + content: "\e62a"; +} + +.demo-icon-service:before { + content: "\e62b"; +} + +.demo-icon-print:before { + content: "\e62c"; +} + +.demo-icon-box:before { + content: "\e62d"; +} + +.demo-icon-browse:before { + content: "\e634"; +} + +.demo-icon-atm-away:before { + content: "\e635"; +} + +.demo-icon-scanning:before { + content: "\e636"; +} + +.demo-icon-compare:before { + content: "\e637"; +} + +.demo-icon-filter:before { + content: "\e638"; +} + +.demo-icon-pin:before { + content: "\e639"; +} + +.demo-icon-history:before { + content: "\e63a"; +} + +.demo-icon-similar-product:before { + content: "\e63b"; +} + +.demo-icon-link:before { + content: "\e63c"; +} + +.demo-icon-cut:before { + content: "\e64a"; +} + +.demo-icon-table:before { + content: "\e63e"; +} + +.demo-icon-nav-list:before { + content: "\e63f"; +} + +.demo-icon-image-text:before { + content: "\e640"; +} + +.demo-icon-text:before { + content: "\e641"; +} + +.demo-icon-move:before { + content: "\e642"; +} + +.demo-icon-subtract:before { + content: "\e650"; +} + +.demo-icon-dollar:before { + content: "\e643"; +} + +.demo-icon-office:before { + content: "\e644"; +} + +.demo-icon-operation:before { + content: "\e645"; +} + +.demo-icon-download:before { + content: "\e646"; +} + +.demo-icon-map:before { + content: "\e647"; +} + +.demo-icon-bad:before { + content: "\e648"; +} + +.demo-icon-good:before { + content: "\e649"; +} + +.demo-icon-skip:before { + content: "\e64b"; +} + +.demo-icon-play:before { + content: "\e64c"; +} + +.demo-icon-stop:before { + content: "\e64d"; +} + +.demo-icon-compass:before { + content: "\e64e"; +} + +.demo-icon-security:before { + content: "\e64f"; +} + +.demo-icon-share:before { + content: "\e651"; +} + +.demo-icon-store:before { + content: "\e652"; +} + +.demo-icon-phone:before { + content: "\e653"; +} + +.demo-icon-ellipsis:before { + content: "\e654"; +} + +.demo-icon-email-filling:before { + content: "\e665"; +} + +.demo-icon-favorites-filling:before { + content: "\e666"; +} + +.demo-icon-account-filling:before { + content: "\e667"; +} + +.demo-icon-credit-level:before { + content: "\e65a"; +} + +.demo-icon-credit-level-filling:before { + content: "\e65c"; +} + +.demo-icon-mobile-phone:before { + content: "\e65d"; +} + +.demo-icon-smile:before { + content: "\e668"; +} + +.demo-icon-personal-center:before { + content: "\e669"; +} + +.demo-icon-arrow-up-filling:before { + content: "\e601"; +} + +.demo-icon-arrow-right:before { + content: "\e603"; +} + +.demo-icon-arrow-down:before { + content: "\e66b"; +} + +.demo-icon-arrow-up:before { + content: "\e66c"; +} + +.demo-icon-add:before { + content: "\e66f"; +} + +.demo-icon-minus:before { + content: "\e670"; +} + +.demo-icon-edit:before { + content: "\e613"; +} + +.demo-icon-error:before { + content: "\e672"; +} + +.demo-icon-select:before { + content: "\e673"; +} + +.demo-icon-ashbin:before { + content: "\e61e"; +} + +.demo-icon-calendar:before { + content: "\e620"; +} + +.demo-icon-time:before { + content: "\e622"; +} + +.demo-icon-success:before { + content: "\e674"; +} + +.demo-icon-warning:before { + content: "\e675"; +} + +.demo-icon-search:before { + content: "\e656"; +} + +.demo-icon-display:before { + content: "\e677"; +} + +.demo-icon-category:before { + content: "\e658"; +} + +.demo-icon-prompt:before { + content: "\e678"; +} + +.demo-icon-arrow-down-filling:before { + content: "\e65b"; +} + +.demo-icon-sorting:before { + content: "\e676"; +} + +.demo-icon-ascending:before { + content: "\e606"; +} + +.demo-icon-descending:before { + content: "\e608"; +} + +.demo-icon-success-filling:before { + content: "\e679"; +} + +.demo-icon-picture:before { + content: "\e60c"; +} + +.demo-icon-close:before { + content: "\e67a"; +} + +.demo-icon-semi-select:before { + content: "\e67b"; +} + +.demo-icon-tag-subscript:before { + content: "\e614"; +} + +.demo-icon-survey:before { + content: "\e65f"; +} + +.demo-icon-loading:before { + content: "\e67c"; +} + +.demo-icon-arrow-double-left:before { + content: "\e616"; +} + +.demo-icon-arrow-double-right:before { + content: "\e661"; +} + +.demo-icon-nav-more:before { + content: "\e67d"; +} + +.demo-icon-delete-filling:before { + content: "\e681"; +} + +.demo-icon-arrow-left:before { + content: "\e682"; +} + +.demo-icon-lights:before { + content: "\e66d"; +} + +.demo-icon-expand:before { + content: "\e66e"; +} + +.demo-icon-hide:before { + content: "\e671"; +} + +.demo-icon-fusion-logo:before { + content: "\e67f"; +} + +.demo-icon-arrow-right-filling:before { + content: "\e680"; +} + +.demo-icon-arrow-left-filling:before { + content: "\e683"; +} + +.demo-icon-superstar:before { + content: "\e684"; +} + +.demo-icon-qr-code:before { + content: "\e685"; +} + +.demo-icon-home:before { + content: "\e689"; +} + +.demo-icon-electronics:before { + content: "\e68a"; +} + +.demo-icon-import:before { + content: "\e67e"; +} + +.demo-icon-process:before { + content: "\e687"; +} + +.demo-icon-gifts:before { + content: "\e688"; +} + +.demo-icon-bags:before { + content: "\e68b"; +} + +.demo-icon-pointing-left:before { + content: "\e68c"; +} + +.demo-icon-pointing-right:before { + content: "\e68d"; +} + +.demo-icon-no-results:before { + content: "\e686"; +} + +.demo-icon-auto:before { + content: "\e68e"; +} diff --git a/packages/material-parser/test/fixtures/fusion-next-component/src/demo-helper/index.jsx b/packages/material-parser/test/fixtures/fusion-next-component/src/demo-helper/index.jsx new file mode 100644 index 000000000..71d892576 --- /dev/null +++ b/packages/material-parser/test/fixtures/fusion-next-component/src/demo-helper/index.jsx @@ -0,0 +1,768 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; +import md5 from 'md5'; + +const COL = '{Col}'; +const LABEL = '{Label}'; +const TITLE = '{Title}'; +const { showType = 'none', demoItems = {} } = window.DEMO_VARIABLE || {}; +const callback = []; +const COOL = {}; +const FUN = {}; +let demoCount = 0; + +// TODO: { functions, statements, sizes } + +function convertArrayToObject(demoFunction) { + const objDemoFunction = {}; + if (Array.isArray(demoFunction)) { + demoFunction.forEach(demo => { + objDemoFunction[demo.name] = { + label: demo.label, + value: demo.value, + enum: demo.enum.map(e => { + let label = e; + if (e === 'true') { + label = '是'; + } else if (e === 'false') { + label = '否'; + } + + return { + label: label, + value: e, + }; + }), + }; + }); + return objDemoFunction; + } + return demoFunction; +} + +function convertObjectToArray(demoFunction) { + const arrayDemo = []; + Object.keys(demoFunction).forEach(name => { + const demo = demoFunction[name]; + arrayDemo.push({ + name: name, + label: demo.label, + value: demo.value, + enum: demo.enum.map(e => { + return e.value; + }), + }); + }); + return arrayDemo; +} + +/** + * XyzAbc -> xyz-abc + * @param {String} str 驼峰字符串 + * @return {String} 输出规范化的字符串 + */ +function deCamelize(str) { + const matches = str.match(/([A-Z][a-z]{2,})/g); + if (matches === null) { + // return str.toLowerCase(); + return str; + } + return matches + .toString() + .replace(',', '-') + .toLowerCase(); +} + +/** + * 格式化词组 'AbcZex XyzYxx' -> 'abc-zex xyz-yxx' + * @param {String} str 驼峰词组 + * @return {String} 输出格式化的词组 + */ +function formatTitle(str) { + if (!str || typeof str !== 'string') { + return; + } + return str + .split(' ') + .map(deCamelize) + .join(' '); +} + +class Demo extends Component { + static displayName = 'Demo'; + + static propTypes = { + parentDisplayName: PropTypes.string, + defaultBackground: PropTypes.oneOf(['dark', 'light']), + title: PropTypes.string, + block: PropTypes.bool, + children: PropTypes.any, + className: PropTypes.string, + demoIndex: PropTypes.string, + demoItems: PropTypes.object, + demoScope: PropTypes.object, + demoTitle: PropTypes.string, + showType: PropTypes.string, + switchVisible: PropTypes.func, + switchBackground: PropTypes.bool, + demoFunction: PropTypes.object, + onFunctionChange: PropTypes.func, + style: PropTypes.object, + }; + + static defaultProps = { + defaultBackground: 'light', + block: false, + onFunctionChange: () => {}, + }; + + constructor(props) { + super(props); + + this.state = { + demoIndex: props.demoIndex || `${demoCount++}`, + demoItems: props.demoItems || demoItems, + showType: props.showType || showType, + background: props.defaultBackground, + initDate: new Date().getTime(), + }; + + if (!props.demoIndex) { + callback.push(this.setVisible.bind(this)); + } + } + + componentWillReceiveProps(nextProps) { + if ('defaultBackground' in nextProps) { + this.setState({ + background: nextProps.defaultBackground, + }); + } + } + + setVisible(data) { + delete data.demoIndex; + + this.setState(data); + } + + switchVisible(demoIndex) { + const demoItems = this.props.demoItems || this.state.demoItems; + + // TIP: 清理无效数据 + Object.keys(demoItems).forEach(key => { + if (demoItems[key].existed) { + delete demoItems[key].existed; + } else { + delete demoItems[key]; + } + }); + + if (!demoItems[demoIndex]) { + return; + } + + const { hidden = false } = demoItems[demoIndex]; + const childKeys = Object.keys(demoItems).filter(key => + new RegExp(`^${demoIndex.replace(/\*/, '(\\*|\\d+)')}`).test(key) + ); + + // TIP: 更新当前控制器 + demoItems[demoIndex].hidden = !hidden; + // TIP: 更新下级控制器 + childKeys.forEach(key => { + if (key.indexOf('*') > -1) { + demoItems[key].hidden = !hidden; + } + }); + // TIP: 更新 DEMO + childKeys.forEach(key => { + if (key.indexOf('*') < 0) { + demoItems[key].hidden = + (demoItems[key.replace(/\d+$/, '*')] || {}).hidden || + (demoItems[key.replace(/\d+-(\d+)$/, '*-$1')] || {}) + .hidden || + !hidden; + } + }); + // TIP: 同步上级控制器 + this.syncVisible(demoIndex, demoItems); + + sendMessage(window.compName, 'displayed', { + demoIndex, + demoItems, + }); + } + + syncVisible(demoIndex, demoItems) { + let index = demoIndex.replace(/(-(\*|\d+)){2}$/, '-\\d+-\\d+'); + + if (index !== demoIndex) { + const itemKeys = Object.keys(demoItems).filter( + key => new RegExp(`^${index}`).test(key) && key.indexOf('*') < 0 + ); + const hidden = demoItems[itemKeys[0] || demoIndex].hidden; + let sameValue = true; + + itemKeys.forEach(key => { + if (!!demoItems[key].hidden !== hidden) { + sameValue = false; + } + }); + + index = demoIndex.replace(/-(\*|\d+)-(\*|\d+)$/, '-*'); + + demoItems[index].hidden = (sameValue && hidden) || false; + + this.syncVisible(index, demoItems); + } + } + + switchBackground() { + const background = this.state.background === 'light' ? 'dark' : 'light'; + + this.setState({ + background: background, + }); + } + + onFunctionChange(name, e) { + e.stopPropagation(); + + const value = e.currentTarget.value; + const demoFunction = convertArrayToObject(this.props.demoFunction); + + let nextDemoFunction = {}; + Object.keys(demoFunction).forEach(funcName => { + const func = demoFunction[funcName]; + + if (funcName === name) { + func.value = value; + } + + nextDemoFunction[funcName] = func; + }); + + if (Array.isArray(this.props.demoFunction)) { + nextDemoFunction = convertObjectToArray(nextDemoFunction); + } + + this.props.onFunctionChange(nextDemoFunction); + return false; + } + + render() { + let isDemoShape = false; + let hasDemoLevel = false; + let children; + + const block = this.props.block ? 'block' : null; + const index = this.props.demoIndex || this.state.demoIndex; + const demoItems = this.props.demoItems || this.state.demoItems; + const demoScope = this.props.demoScope || this; + const demoTitle = this.props.demoTitle + ? `${this.props.demoTitle} -> ${this.props.title || TITLE}` + : this.props.title || TITLE; + const showType = this.props.showType || this.state.showType; + const switchVisible = this.props.switchVisible || this.switchVisible; + const { background, initDate } = this.state; + const { className, switchBackground, style } = this.props; + const demoFunction = convertArrayToObject(this.props.demoFunction); + + if (this.props.children) { + isDemoShape = this.props.parentDisplayName !== 'Demo'; + + let first; + if (Array.isArray(this.props.children)) { + first = this.props.children[0]; + } else { + first = this.props.children; + } + + hasDemoLevel = first.type.displayName === 'Demo'; + } + + // 注入 demoFunction 到 window.COOL + if (isDemoShape && this.props.title && demoFunction) { + FUN[this.props.title] = {}; + Object.keys(demoFunction).forEach(funcName => { + const func = demoFunction[funcName]; + func.name = funcName; + FUN[this.props.title][funcName] = func; + }); + } + + let demoShapeLevel; + if ((isDemoShape && !hasDemoLevel) || !isDemoShape) { + demoShapeLevel = demoTitle.split(' -> ').join('_'); + + const body = React.Children.map(this.props.children, (child, i) => { + return React.cloneElement(child, { + block: this.props.block, + demoIndex: `${index}-${i}`, + demoItems, + demoScope, + demoTitle, + demoShapeLevel, + showType, + switchVisible, + }); + }); + + children = ( + + {body} +
    + ); + } else { + children = React.Children.map(this.props.children, (child, i) => { + return React.cloneElement(child, { + parentDisplayName: 'Demo', + defaultBackground: background, + demoIndex: `${index}-${i}`, + demoItems, + demoScope, + demoTitle, + demoFunction, + showType, + switchVisible, + }); + }); + } + + const functionSelect = []; + if (isDemoShape && demoFunction) { + Object.keys(demoFunction).forEach((funcName, i) => { + const func = demoFunction[funcName]; + const tmpRadio = []; + const name = md5(`${funcName}-${initDate}`); + + func.enum.forEach((enumObj, j) => { + const checked = enumObj.value.toString() === func.value; + + tmpRadio.push( + + ); + }); + + functionSelect.push( +
  • + {func.label}: + {tmpRadio} +
  • + ); + }); + } + + const demoIndex = `${index}-*`; + const { hidden = false } = demoItems[demoIndex] || {}; + + if (showType === 'hidden' || !hidden) { + if (!demoItems[demoIndex]) { + demoItems[demoIndex] = { + hidden: false, + title: demoTitle, + }; + } else { + demoItems[demoIndex].title = demoTitle; + } + demoItems[demoIndex].existed = true; + + const wrapCls = classNames({ + 'demo pc': true, + [`demo-${background}`]: background, + [className]: className, + }); + const switchCls = classNames({ + 'demo-switch': true, + 'demo-switch-on': background === 'dark', + 'demo-switch-off': background === 'light', + }); + + const customProps = {}; + if (this.props.title) { + // 注入 demo 的标题,用于按需选取 + customProps.title = formatTitle(this.props.title); + } + + return ( +
    +
    + {this.props.title || TITLE} + {showType === 'hidden' && ( +
    + ); + } else { + return null; + } + } +} + +/* eslint-disable react/no-multi-comp */ +class DemoGroup extends Component { + static displayName = 'DemoGroup'; + + static propTypes = { + label: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]), + block: PropTypes.bool, + height: PropTypes.string, + children: PropTypes.any, + className: PropTypes.string, + demoIndex: PropTypes.string, + demoItems: PropTypes.object, + demoScope: PropTypes.object, + demoTitle: PropTypes.string, + demoShapeLevel: PropTypes.string, + showType: PropTypes.string, + switchVisible: PropTypes.func, + }; + + static defaultProps = { + block: false, + height: '', + }; + + render() { + const { + demoIndex: index, + demoItems = {}, + demoScope = this, + showType, + switchVisible = () => {}, + } = this.props; + const demoIndex = `${index}-*`; + const demoTitle = `${this.props.demoTitle} -> ${this.props.label || + LABEL}`; + const demoShapeLevel = this.props.demoShapeLevel; + const { hidden = false } = demoItems[demoIndex] || {}; + + // 解析 + if (demoShapeLevel) { + if (!COOL[demoShapeLevel]) { + COOL[demoShapeLevel] = []; + } + + if (this.props.label) { + let ret = false; + COOL[demoShapeLevel].forEach((item, index) => { + if (item.name === 'statement') { + ret = true; + COOL[demoShapeLevel][index].enum.push(this.props.label); + } + }); + if (!ret) { + COOL[demoShapeLevel].push({ + name: 'statement', + enum: [this.props.label], + }); + } + } + } + + // 获得默认值 + const defaultCool = {}; + defaultCool.title = this.props.demoTitle; + defaultCool.shape = demoShapeLevel; + defaultCool.statement = this.props.label; + COOL[demoShapeLevel].forEach(item => { + if (item.value) { + defaultCool[item.name] = item.value; + } + }); + + const children = React.Children.map(this.props.children, (child, i) => { + const { + demoIndex: index, + demoItems = {}, + showType, + block, + } = this.props; + const demoIndex = `${index}-${i}`; + const { hidden = false } = demoItems[demoIndex] || {}; + const classes = classNames({ + 'demo-item': !hidden, + 'demo-item-hidden': hidden, + block: block, + }); + + COOL[demoShapeLevel].forEach(item => { + if (item.name === 'size') { + defaultCool.size = item.enum[i]; + } + }); + + if (showType === 'hidden' || !hidden) { + if (!demoItems[demoIndex]) { + demoItems[demoIndex] = { + hidden: false, + }; + } + demoItems[demoIndex].existed = true; + + const cloneChild = React.cloneElement(child, { + 'data-cool': JSON.stringify(defaultCool), + }); + + return ( + +
    + {cloneChild} +
    + + ); + } else { + return null; + } + }); + + if (showType === 'hidden' || !hidden) { + if (!demoItems[demoIndex]) { + demoItems[demoIndex] = { + hidden: false, + title: demoTitle, + }; + } else { + demoItems[demoIndex].title = demoTitle; + } + demoItems[demoIndex].existed = true; + + return ( + + {this.props.label === false ? null : ( + + {this.props.label || LABEL} + {showType === 'hidden' && ( +