View.tsx 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. import { css } from "@linaria/core";
  2. import { omit, upperFirst } from "lodash";
  3. import { defineComponent } from "vue";
  4. import { any, string } from "vue-types";
  5. import { useEditor } from "../../..";
  6. import { Background, Layout } from "../../../typings";
  7. export const View = defineComponent({
  8. props: {
  9. compId: string(),
  10. background: any<Background>(),
  11. layout: any<Layout>(),
  12. },
  13. setup(props, { slots }) {
  14. const { store, actions, helper } = useEditor();
  15. function createStyle(): any {
  16. const style: any = {};
  17. const { textAlign, offsetY, zIndex } = props.layout || {};
  18. if (textAlign) {
  19. style.textAlign = textAlign;
  20. }
  21. if (offsetY) {
  22. style[`margin` + ((offsetY as number) > 0 ? "Top" : "Bottom")] =
  23. helper.designToNaturalSize(Math.abs(offsetY as number) * -1);
  24. }
  25. if (zIndex) {
  26. style["zIndex"] = zIndex;
  27. }
  28. return style;
  29. }
  30. function createContentStyle() {
  31. const style: any = {};
  32. const { background, layout } = props;
  33. const [w, h] = (layout?.size as number[]) || [];
  34. if (background) {
  35. Object.entries(background).forEach(([key, value]) => {
  36. if (key === "image") {
  37. value = `url(${value})`;
  38. }
  39. style["background" + upperFirst(key)] = value;
  40. });
  41. console.log(style, background);
  42. }
  43. if (w) style["width"] = helper.designToNaturalSize(w);
  44. if (h) style["height"] = helper.designToNaturalSize(h);
  45. if (layout?.offsetX) {
  46. style["marginLeft"] = helper.designToNaturalSize(
  47. layout.offsetX as number
  48. );
  49. }
  50. return style;
  51. }
  52. return () => {
  53. const isComp = !!props.compId;
  54. const isSelected = isComp && store.currCompId === props.compId;
  55. const bgOpts = Object.values(omit(props.background, ["image", "color"]));
  56. const bgClasses = bgOpts.length ? `bg-${bgOpts.join(" bg-")}` : "";
  57. return isComp ? (
  58. <div
  59. class={[
  60. store.isEditMode && viewStyle,
  61. store.isEditMode && isSelected && "view_selected",
  62. bgClasses,
  63. ]}
  64. style={createStyle()}
  65. onClick={
  66. isComp && !isSelected
  67. ? () => actions.pickCurrComp(props.compId as string)
  68. : undefined
  69. }
  70. >
  71. <div class="view_content" style={createContentStyle()}>
  72. {slots.default?.()}
  73. </div>
  74. </div>
  75. ) : (
  76. <div class="view_inside">{slots.default?.()}</div>
  77. );
  78. };
  79. },
  80. });
  81. const viewStyle = css`
  82. position: relative;
  83. > * {
  84. pointer-events: none;
  85. }
  86. .view_content {
  87. display: inline-block;
  88. width: 100%;
  89. height: 100%;
  90. background: no-repeat center / cover;
  91. &:hover {
  92. outline: 1px dashed @inf-primary-color;
  93. }
  94. }
  95. &.view_selected {
  96. > * {
  97. pointer-events: auto;
  98. }
  99. &::after {
  100. display: none;
  101. }
  102. .view_content {
  103. outline: 1px solid @inf-primary-color;
  104. }
  105. .view_inside:hover {
  106. outline: 1px dashed @inf-primary-color;
  107. outline-offset: -1px;
  108. }
  109. }
  110. .view_inside {
  111. position: relative;
  112. }
  113. `;