diff --git a/.changeset/weak-cups-promise.md b/.changeset/weak-cups-promise.md new file mode 100644 index 00000000..53eaa9d8 --- /dev/null +++ b/.changeset/weak-cups-promise.md @@ -0,0 +1,5 @@ +--- +'@watermark-design/vue': minor +--- + +add blind watermark component in vue diff --git a/.eslintrc.js b/.eslintrc.js index 0008bb64..67e2fa84 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -57,7 +57,7 @@ module.exports = { 'no-unused-vars': [ 'error', { - argsIgnorePattern: '^_', + argsIgnorePattern: '^_|this', varsIgnorePattern: '^_', }, ], diff --git a/packages/vue/README.md b/packages/vue/README.md index 65e9e6bf..299b52e0 100644 --- a/packages/vue/README.md +++ b/packages/vue/README.md @@ -9,7 +9,7 @@ npm bundle size npm download week GitHub - Join the chat + Join the chat

# `@watermark-design/vue` diff --git a/packages/vue/package.json b/packages/vue/package.json index 9fe0eb3e..bcbeaa1b 100644 --- a/packages/vue/package.json +++ b/packages/vue/package.json @@ -67,7 +67,7 @@ "@watermark-design/shared": "workspace:^", "lodash.debounce": "^4.0.8", "lodash.omit": "^4.5.0", - "nanoid": "^5.0.2", + "nanoid": "^5.0.3", "vue-demi": "^0.14.6" }, "peerDependencies": { diff --git a/packages/vue/src/blind/index.ts b/packages/vue/src/blind/index.ts new file mode 100644 index 00000000..01de98f8 --- /dev/null +++ b/packages/vue/src/blind/index.ts @@ -0,0 +1,3 @@ +import blind from './src/blind.vue'; + +export default blind; diff --git a/packages/vue/src/blind/src/blind.vue b/packages/vue/src/blind/src/blind.vue new file mode 100644 index 00000000..c59e9633 --- /dev/null +++ b/packages/vue/src/blind/src/blind.vue @@ -0,0 +1,62 @@ + + + diff --git a/packages/vue/src/main.ts b/packages/vue/src/main.ts index 6619543d..d8e9e2e0 100644 --- a/packages/vue/src/main.ts +++ b/packages/vue/src/main.ts @@ -1,10 +1,12 @@ import type { App } from 'vue-demi'; import watermark from './watermark'; +import blind from './blind'; import teleport from './teleport'; export default { install(app: App) { app.component(watermark.name, watermark); + app.component(blind.name, blind); app.component(teleport.name, teleport); }, }; diff --git a/packages/vue/src/mixins/watermark.mixin.ts b/packages/vue/src/mixins/watermark.mixin.ts index 827307f6..acd62038 100644 --- a/packages/vue/src/mixins/watermark.mixin.ts +++ b/packages/vue/src/mixins/watermark.mixin.ts @@ -1,4 +1,4 @@ -import { CSSProperties, PropType } from 'vue-demi'; +import { CSSProperties, PropType, ComponentOptions } from 'vue-demi'; import { nanoid } from 'nanoid'; import debounce from 'lodash.debounce'; import { @@ -8,156 +8,187 @@ import { renderLayout, WatermarkCanvas, } from '@watermark-design/core'; -import type { WatermarkOptions } from '@watermark-design/core'; +import type { + WatermarkOptions, + GridLayoutOptions, + CanvasShadowStyles, + AdvancedStyleType, +} from '@watermark-design/core'; + +type OmittedWatermarkOptions = Omit< + WatermarkOptions, + 'parent' | 'mutationObserve' | 'appendToBody' +>; + +export type WatermarkMixinType = ComponentOptions & + OmittedWatermarkOptions & { + key: string; + watermarkCanvas: WatermarkCanvas; + watermarkImage: string; + observer: MutationObserver; + parentObserve: MutationObserver; + observing: boolean; + options: Partial; + watermarkWrapperStyle: CSSProperties; + watermarkStyle: CSSProperties; + generateKey: () => string; + create: () => Promise; + update: () => Promise; + draw: () => Promise; + remove: () => void; + handleObserver: () => void; + addObserver: () => void; + removeObserver: () => void; + }; -export default { +const WatermarkMixin: ComponentOptions = { props: { width: { - type: Number as PropType, + type: Number, default: initialOptions.width, }, height: { - type: Number as PropType, + type: Number, default: initialOptions.height, }, rotate: { - type: Number as PropType, + type: Number, default: initialOptions.rotate, }, layout: { - type: String as PropType, + type: String, default: initialOptions.layout, }, gridLayoutOptions: { - type: Object as PropType, + type: Object as PropType, default: undefined, }, auxiliaryLine: { - type: Boolean as PropType, + type: Boolean, default: initialOptions.auxiliaryLine, }, globalAlpha: { - type: Number as PropType, + type: Number, default: initialOptions.globalAlpha, }, zIndex: { - type: Number as PropType, + type: Number, default: 10, }, - // mutationObserve: { - // type: Boolean as PropType, - // default: false, - // }, + mutationObserve: { + type: Boolean, + default: false, + }, movable: { - type: Boolean as PropType, + type: Boolean, default: initialOptions.movable, }, mode: { - type: String as PropType, + type: String, default: initialOptions.mode, }, backgroundPosition: { - type: String as PropType, + type: String, default: initialOptions.backgroundPosition, }, backgroundRepeat: { - type: String as PropType, + type: String, default: initialOptions.backgroundRepeat, }, translatePlacement: { - type: String as PropType, + type: String, default: undefined, }, translateX: { - type: Number as PropType, + type: Number, default: undefined, }, translateY: { - type: Number as PropType, + type: Number, default: undefined, }, contentType: { - type: String as PropType, + type: String, default: initialOptions.contentType, }, content: { - type: String as PropType, + type: String, default: initialOptions.content, }, textType: { - type: String as PropType, + type: String, default: initialOptions.textType, }, lineHeight: { - type: Number as PropType, + type: Number, default: initialOptions.lineHeight, }, fontSize: { - type: String as PropType, + type: String, default: initialOptions.fontSize, }, fontFamily: { - type: String as PropType, + type: String, default: initialOptions.fontFamily, }, fontStyle: { - type: String as PropType, + type: String, default: initialOptions.fontStyle, }, fontVariant: { - type: String as PropType, + type: String, default: initialOptions.fontVariant, }, fontColor: { - type: String as PropType, + type: String, default: initialOptions.fontColor, }, fontWeight: { - type: String as PropType, + type: String, default: initialOptions.fontWeight, }, textAlign: { - type: String as PropType, + type: String, default: undefined, }, textBaseline: { - type: String as PropType, + type: String, default: undefined, }, filter: { - type: String as PropType, + type: String, default: initialOptions.filter, }, textRowMaxWidth: { - type: Number as PropType, + type: Number, default: undefined, }, richTextWidth: { - type: Number as PropType, + type: Number, default: undefined, }, richTextHeight: { - type: Number as PropType, + type: Number, default: undefined, }, image: { - type: String as PropType, + type: String, default: undefined, }, imageWidth: { - type: Number as PropType, + type: Number, default: initialOptions.imageWidth, }, imageHeight: { - type: Number as PropType, + type: Number, default: initialOptions.imageHeight, }, shadowStyle: { - type: Object as PropType, + type: Object as PropType>, default: undefined, }, advancedStyle: { - type: Object as PropType, + type: Object as PropType, default: undefined, }, appendToBody: { @@ -168,11 +199,11 @@ export default { emits: ['success', 'error', 'beforeDestroy', 'destroyed', 'observeSuccess', 'observeError'], data() { return { - key: null as string, - watermarkCanvas: null as WatermarkCanvas, - watermarkImage: null as string, - observer: null as MutationObserver, - parentObserve: null as MutationObserver, + key: '' as string, + watermarkCanvas: null as unknown as WatermarkCanvas, + watermarkImage: '' as string, + observer: null as unknown as MutationObserver, + parentObserve: null as unknown as MutationObserver, observing: false, }; }, @@ -203,7 +234,7 @@ export default { width: this.width, height: this.height, gridLayoutOptions: this.gridLayoutOptions, - }); + } as WatermarkOptions); return { ...(this.mutationObserve && { visibility: `visible${important}`, @@ -244,10 +275,10 @@ export default { this.$emit('success'); }, methods: { - generateKey() { + generateKey(): string { return this.mutationObserve ? nanoid(6) : 'watermark'; }, - create: debounce(async function () { + create: debounce(async function (this: any) { this.watermarkCanvas = new WatermarkCanvas(this.$props, this.options); this.remove(); this.key = this.generateKey(); @@ -259,7 +290,7 @@ export default { this.$emit('error'); } }, 10), - update: debounce(async function () { + update: debounce(async function (this: any) { this.remove(); this.key = this.generateKey(); try { @@ -344,3 +375,5 @@ export default { }, }, }; + +export default WatermarkMixin; diff --git a/packages/vue/src/teleport/src/teleport.tsx b/packages/vue/src/teleport/src/teleport.tsx index ae764ab7..63d42733 100644 --- a/packages/vue/src/teleport/src/teleport.tsx +++ b/packages/vue/src/teleport/src/teleport.tsx @@ -1,150 +1,150 @@ -export default { - name: 'Teleport', - props: { - to: { - type: String, - required: true, - }, - where: { - type: String, - default: 'after', - }, - disabled: Boolean, - }, - data() { - return { - nodes: [] as Node[], - waiting: false, - observer: null as MutationObserver | null, - parent: null as Element | null, - }; - }, - computed: { - classes() { - if (this.disabled) { - return ['teleport']; - } - - return ['teleport', 'teleport-hidden']; - }, - }, - watch: { - to: 'maybeMove', - where: 'maybeMove', - disabled(value) { - if (value) { - this.disable(); - this.teardownObserver(); - } else { - this.bootObserver(); - this.move(); - } - }, - }, - mounted() { - // Store a reference to the nodes - this.nodes = Array.from(this.$el.childNodes); - - if (!this.disabled) { - this.bootObserver(); - } - - // Move slot content to target - this.maybeMove(); - }, - beforeUnmount() { - // Move back - this.disable(); - - // Stop observing - this.teardownObserver(); - }, - methods: { - maybeMove() { - if (!this.disabled) { - this.move(); - } else { - console.log(this.$el); - } - }, - move() { - this.waiting = false; - this.parent = document.querySelector(this.to); - if (!this.parent) { - this.disable(); - this.waiting = true; - return; - } - - if (this.where === 'before') { - this.parent.prepend(this.getFragment()); - } else { - this.parent.appendChild(this.getFragment()); - } - }, - disable() { - this.$el.appendChild(this.getFragment()); - this.parent = null; - }, - // Using a fragment is faster because it'll trigger only a single reflow - // See https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment - getFragment() { - const fragment = document.createDocumentFragment(); - - this.nodes.forEach((node) => fragment.appendChild(node)); - - return fragment; - }, - onMutations(mutations: MutationRecord[]) { - // Makes sure the move operation is only done once - let shouldMove = false; - - for (let i = 0; i < mutations.length; i++) { - const mutation = mutations[i]; - const filteredAddedNodes = Array.from(mutation.addedNodes).filter( - (node: Node) => !this.nodes.includes(node) - ); - - if (Array.from(mutation.removedNodes).includes(this.parent!)) { - this.disable(); - this.waiting = !this.disabled; - } else if (this.waiting && filteredAddedNodes.length > 0) { - shouldMove = true; - } - } - - if (shouldMove) { - this.move(); - } - }, - bootObserver() { - if (this.observer) { - return; - } - - this.observer = new MutationObserver((mutations) => this.onMutations(mutations)); - - this.observer.observe(document.body, { - childList: true, - subtree: true, - attributes: false, - characterData: false, - }); - }, - teardownObserver() { - if (this.observer) { - this.observer.disconnect(); - this.observer = null; - } - }, - }, - render(h) { - return h( - 'div', - { - class: this.classes, - }, - this.$slots.default - ); - }, -}; +// export default { +// name: 'Teleport', +// props: { +// to: { +// type: String, +// required: true, +// }, +// where: { +// type: String, +// default: 'after', +// }, +// disabled: Boolean, +// }, +// data() { +// return { +// nodes: [] as Node[], +// waiting: false, +// observer: null as MutationObserver | null, +// parent: null as Element | null, +// }; +// }, +// computed: { +// classes() { +// if (this.disabled) { +// return ['teleport']; +// } +// +// return ['teleport', 'teleport-hidden']; +// }, +// }, +// watch: { +// to: 'maybeMove', +// where: 'maybeMove', +// disabled(value) { +// if (value) { +// this.disable(); +// this.teardownObserver(); +// } else { +// this.bootObserver(); +// this.move(); +// } +// }, +// }, +// mounted() { +// // Store a reference to the nodes +// this.nodes = Array.from(this.$el.childNodes); +// +// if (!this.disabled) { +// this.bootObserver(); +// } +// +// // Move slot content to target +// this.maybeMove(); +// }, +// beforeUnmount() { +// // Move back +// this.disable(); +// +// // Stop observing +// this.teardownObserver(); +// }, +// methods: { +// maybeMove() { +// if (!this.disabled) { +// this.move(); +// } else { +// console.log(this.$el); +// } +// }, +// move() { +// this.waiting = false; +// this.parent = document.querySelector(this.to); +// if (!this.parent) { +// this.disable(); +// this.waiting = true; +// return; +// } +// +// if (this.where === 'before') { +// this.parent.prepend(this.getFragment()); +// } else { +// this.parent.appendChild(this.getFragment()); +// } +// }, +// disable() { +// this.$el.appendChild(this.getFragment()); +// this.parent = null; +// }, +// // Using a fragment is faster because it'll trigger only a single reflow +// // See https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment +// getFragment() { +// const fragment = document.createDocumentFragment(); +// +// this.nodes.forEach((node) => fragment.appendChild(node)); +// +// return fragment; +// }, +// onMutations(mutations: MutationRecord[]) { +// // Makes sure the move operation is only done once +// let shouldMove = false; +// +// for (let i = 0; i < mutations.length; i++) { +// const mutation = mutations[i]; +// const filteredAddedNodes = Array.from(mutation.addedNodes).filter( +// (node: Node) => !this.nodes.includes(node) +// ); +// +// if (Array.from(mutation.removedNodes).includes(this.parent!)) { +// this.disable(); +// this.waiting = !this.disabled; +// } else if (this.waiting && filteredAddedNodes.length > 0) { +// shouldMove = true; +// } +// } +// +// if (shouldMove) { +// this.move(); +// } +// }, +// bootObserver() { +// if (this.observer) { +// return; +// } +// +// this.observer = new MutationObserver((mutations) => this.onMutations(mutations)); +// +// this.observer.observe(document.body, { +// childList: true, +// subtree: true, +// attributes: false, +// characterData: false, +// }); +// }, +// teardownObserver() { +// if (this.observer) { +// this.observer.disconnect(); +// this.observer = null; +// } +// }, +// }, +// render(h) { +// return h( +// 'div', +// { +// class: this.classes, +// }, +// this.$slots.default +// ); +// }, +// }; diff --git a/packages/vue/src/watermark/src/watermark.vue b/packages/vue/src/watermark/src/watermark.vue index f8030979..d2a10366 100644 --- a/packages/vue/src/watermark/src/watermark.vue +++ b/packages/vue/src/watermark/src/watermark.vue @@ -10,12 +10,12 @@ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b3189180..51d7e72a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -308,8 +308,8 @@ importers: specifier: ^4.5.0 version: 4.5.0 nanoid: - specifier: ^5.0.2 - version: 5.0.2 + specifier: ^5.0.3 + version: 5.0.3 vue-demi: specifier: ^0.14.6 version: 0.14.6(@vue/composition-api@1.7.2)(vue@3.3.7) @@ -358,8 +358,8 @@ importers: specifier: workspace:^ version: link:../packages/vue element-plus: - specifier: ^2.4.1 - version: 2.4.1(@vue/composition-api@1.7.2)(vue@3.3.7) + specifier: ^2.4.2 + version: 2.4.2(@vue/composition-api@1.7.2)(vue@3.3.7) react: specifier: ^18.2.0 version: 18.2.0 @@ -8119,8 +8119,8 @@ packages: resolution: {integrity: sha512-iS7KhLYCSJbdo3rUSkhDTVuFNCV34RKs2UaB9Ecr7VlqzjjWW//0nfsFF5dtDmyXlZQaDYYtID5fjtC/6lpRug==} dev: true - /element-plus@2.4.1(@vue/composition-api@1.7.2)(vue@3.3.7): - resolution: {integrity: sha512-t7nl+vQlkBKVk1Ag6AufSDyFV8YIXxTFsaya4Nz/0tiRlcz65WPN4WMFeNURuFJleu1HLNtP4YyQKMuS7El8uA==} + /element-plus@2.4.2(@vue/composition-api@1.7.2)(vue@3.3.7): + resolution: {integrity: sha512-E/HwXX7JF1LPvQSjs0fZ8WblIoc0quoXsRXQZiL7QDq7xJdNGSUaXtdk7xiEv7axPmLfEFtxE5du9fFspDrmJw==} peerDependencies: vue: ^3.2.0 dependencies: @@ -12100,8 +12100,8 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - /nanoid@5.0.2: - resolution: {integrity: sha512-2ustYUX1R2rL/Br5B/FMhi8d5/QzvkJ912rBYxskcpu0myTHzSZfTr1LAS2Sm7jxRUObRrSBFoyzwAhL49aVSg==} + /nanoid@5.0.3: + resolution: {integrity: sha512-I7X2b22cxA4LIHXPSqbBCEQSL+1wv8TuoefejsX4HFWyC6jc5JG7CEaxOltiKjc1M+YCS2YkrZZcj4+dytw9GA==} engines: {node: ^18 || >=20} hasBin: true dev: false