View.tsx 3.3 KB

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