diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..679a1bd --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,19 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: 'npm' # See documentation for possible values + directory: '/' # Location of package manifests + target-branch: 'next' + schedule: + interval: 'weekly' + # Allow up to x open pull requests for npm dependencies + open-pull-requests-limit: 5 + commit-message: + # Prefix all commit messages with "npm" + prefix: 'npm' + labels: + - 'dependencies' diff --git a/README.md b/README.md index a580698..ce20194 100644 --- a/README.md +++ b/README.md @@ -36,24 +36,27 @@ yarn add @adamdehaven/vue-custom-tooltip@next It is recommended to initialize the plugin in your Vue project's entry file. For projects created with [`@vue/cli`](https://cli.vuejs.org/), this is likely your `main.{js|ts}` file where you are already importing `Vue`. -```js +```ts // main.{js|ts} (or your Vue entry file) +// =========================================================== +// VUE 2.x +// =========================================================== // Import Vue... you're probably already doing this import Vue from 'vue' -// Import the tooltip component before calling 'new Vue()' +// Import the tooltip component import VueCustomTooltip from '@adamdehaven/vue-custom-tooltip' -// Install the plugin using ONE of the options below: +// Initialize the plugin using ONE of the options below: // -------------------------------------------------- -// 1. Install with default options +// 1. Initialize with default options Vue.use(VueCustomTooltip) // ===== OR ===== -// 2. Install with custom options (defaults shown) +// 2. Initialize with custom options (defaults shown) Vue.use(VueCustomTooltip, { name: 'VueCustomTooltip', color: '#fff', @@ -61,6 +64,37 @@ Vue.use(VueCustomTooltip, { borderRadius: 100, fontWeight: 400, }) + +// =========================================================== +// VUE 3.x +// =========================================================== +import { createApp } from 'vue' +import App from './App.vue' + +// Import the tooltip component and option types +import VueCustomTooltip, { TooltipOptions } from '@adamdehaven/vue-custom-tooltip' + +const app = createApp(App) + +// Initialize the plugin using ONE of the options below: +// -------------------------------------------------- + +// 1. Initialize with default options +app.use(VueCustomTooltip) + +// ===== OR === + +// 2. Initialize with custom options (defaults shown) +const opt: TooltipOptions = { + name: 'VueCustomTooltip', + color: '#fff', + background: '#000', + borderRadius: 100, + fontWeight: 400, +} + +app.use(VueCustomTooltip, opt) +app.mount('#app') ``` ### In-Component (locally available) @@ -69,13 +103,13 @@ Alternatively, you may initialize the component directly within a single file in **Notes on in-component initialization**: -- Initializing within a component does not allow for customizing the [Plugin Options](#options); however, you may still utilize all [`props`](#props) on the `` element. +- Initializing within a component does not allow for customizing the [Plugin Options](#options); however, you may still utilize all [`props`](#props) on the `` element, or customize styles with [CSS Variables](#css-variables). ```html diff --git a/src/VueCustomTooltip.vue b/src/VueCustomTooltip.vue index 35d6b25..61d5ecb 100644 --- a/src/VueCustomTooltip.vue +++ b/src/VueCustomTooltip.vue @@ -23,7 +23,6 @@ export default defineComponent({ return ['is-top', 'is-bottom', 'is-left', 'is-right'].indexOf(value) > -1 }, }, - // Size of the tooltip - forces 'is-large' if multiline is true size: { type: String, default: 'is-medium', @@ -36,13 +35,31 @@ export default defineComponent({ const tooltipOptions: TooltipOptions = inject('vue-custom-tooltip', defaultTooltipOptions) const setCssVars = () => { + if (!tooltipOptions || !defaultTooltipOptions) { + return + } + const htmlRoot: HTMLElement | null = document && document.documentElement ? document.documentElement : null if (htmlRoot) { /* eslint-disable @typescript-eslint/no-non-null-assertion */ - htmlRoot.style.setProperty('--vue-custom-tooltip-color', tooltipOptions.color!) - htmlRoot.style.setProperty('--vue-custom-tooltip-background', tooltipOptions.background!) - htmlRoot.style.setProperty('--vue-custom-tooltip-border-radius', `${tooltipOptions.borderRadius!}px`) - htmlRoot.style.setProperty('--vue-custom-tooltip-font-weight', tooltipOptions.fontWeight!.toString()) + htmlRoot.style.setProperty( + '--vue-custom-tooltip-color', + tooltipOptions.color !== defaultTooltipOptions.color ? tooltipOptions.color! : null, + ) + htmlRoot.style.setProperty( + '--vue-custom-tooltip-background', + tooltipOptions.background !== defaultTooltipOptions.background ? tooltipOptions.background! : null, + ) + htmlRoot.style.setProperty( + '--vue-custom-tooltip-border-radius', + tooltipOptions.borderRadius !== defaultTooltipOptions.borderRadius + ? `${tooltipOptions.borderRadius!}px` + : null, + ) + htmlRoot.style.setProperty( + '--vue-custom-tooltip-font-weight', + tooltipOptions.fontWeight !== defaultTooltipOptions.fontWeight ? tooltipOptions.fontWeight!.toString() : null, + ) /* eslint-enable @typescript-eslint/no-non-null-assertion */ } } @@ -52,10 +69,12 @@ export default defineComponent({ return () => [ h( props.abbreviation ? 'abbr' : 'span', - Object.assign({}, attrs, { + { 'class': [ + attrs.class, props.position, - props.multiline ? 'is-large' : props.size, // force large size if multiline is true + // force at least medium size if multiline is true + props.multiline && props.size === 'is-small' ? 'is-medium' : props.size, { 'vue-custom-tooltip': props.active && props.label, 'is-sticky': props.sticky, @@ -66,11 +85,182 @@ export default defineComponent({ 'data-label': props.label, 'aria-label': props.label, 'role': 'tooltip', - 'style': [{ cursor: props.abbreviation ? 'help' : 'pointer' }], - }), + 'style': [{ cursor: props.abbreviation ? 'help' : 'pointer' }, attrs.style], + }, slots, ), ] }, }) + + diff --git a/src/index.ts b/src/index.ts index 182dc91..37972f2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,10 +1,16 @@ -import { App } from 'vue' +import { App, Plugin } from 'vue' import VueCustomTooltip from './VueCustomTooltip.vue' import { TooltipOptions, defaultTooltipOptions } from './types' -import './tooltip.scss' -export default { - install: (app: App, options?: TooltipOptions): void => { +// Define typescript interfaces for installable component +type InstallableComponent = typeof VueCustomTooltip & { + install: Exclude +} + +export default ((): InstallableComponent => { + const installable = VueCustomTooltip as unknown as InstallableComponent + + installable.install = (app: App, options?: TooltipOptions): void => { const userOptions = Object.assign({}, options) /** @@ -47,6 +53,10 @@ export default { // Register component, using options.name /* eslint-disable-next-line @typescript-eslint/no-non-null-assertion */ - app.component(pluginOptions.name!, VueCustomTooltip) - }, -} + app.component(pluginOptions.name!, installable) + } + + return installable +})() + +export { VueCustomTooltip, TooltipOptions } diff --git a/src/main.ts b/src/main.ts index 093b8ad..8f2cc6a 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,18 +1,17 @@ import { createApp } from 'vue' import App from './App.vue' -import VueCustomTooltipPlugin from './index' -import { TooltipOptions } from './types' +import VueCustomTooltip from './index' const app = createApp(App) -const tooltipOptions: TooltipOptions = { +const tooltipOptions = { // name: 'VueCustomTooltip', // color: '#fff', - background: '#007ac1', + background: '#ff0000', // borderRadius: 12, // fontWeight: 400, } -app.use(VueCustomTooltipPlugin, tooltipOptions) +app.use(VueCustomTooltip, tooltipOptions) app.mount('#app') diff --git a/src/tooltip.scss b/src/tooltip.scss deleted file mode 100644 index cd5723a..0000000 --- a/src/tooltip.scss +++ /dev/null @@ -1,167 +0,0 @@ -$tooltip-color: var(--vue-custom-tooltip-color, #fff); // default color -$tooltip-background: var(--vue-custom-tooltip-background, #000); // default background color -$tooltip-radius: var(--vue-custom-tooltip-border-radius, 100px); // default border radius -$weight-normal: var(--vue-custom-tooltip-font-weight, 400); // default font weight -$speed: 86ms; -$easing: ease-out; - -@mixin tooltip-arrow($direction, $color) { - @if $direction == "is-top" { - border-top: 5px solid #000; // default for IE - border-top: 5px solid $color; - border-right: 5px solid transparent; - border-left: 5px solid transparent; - bottom: calc(100% + 2px); - } @else if $direction == "is-bottom" { - border-right: 5px solid transparent; - border-bottom: 5px solid #000; // default for IE - border-bottom: 5px solid $color; - border-left: 5px solid transparent; - top: calc(100% + 2px); - } @else if $direction == "is-right" { - border-top: 5px solid transparent; - border-right: 5px solid #000; // default for IE - border-right: 5px solid $color; - border-bottom: 5px solid transparent; - left: calc(100% + 3px); - } @else if $direction == "is-left" { - border-top: 5px solid transparent; - border-bottom: 5px solid transparent; - border-left: 5px solid #000; // default for IE - border-left: 5px solid $color; - right: calc(100% + 3px); - } -} - -@mixin tooltip($direction) { - &.#{$direction} { - &:before, - &:after { - @if ($direction == "is-top") { - top: auto; - right: auto; - bottom: calc(100% + 5px + 2px); - left: 50%; - transform: translateX(-50%); - } @else if ($direction == "is-bottom") { - top: calc(100% + 5px + 2px); - right: auto; - bottom: auto; - left: 50%; - transform: translateX(-50%); - } @else if ($direction == "is-right") { - top: 50%; - right: auto; - bottom: auto; - left: calc(100% + 5px + 2px); - transform: translateY(-50%); - } @else if ($direction == "is-left") { - top: 50%; - right: calc(100% + 5px + 2px); - bottom: auto; - left: auto; - transform: translateY(-50%); - } - } - - &:before { - @include tooltip-arrow($direction, $tooltip-background); - } - - &.has-multiline { - &.is-small:after { - width: 140px; - } - - &.is-medium:after { - width: 210px; - } - - &.is-large:after { - width: 340px; - padding: 0.6rem 1rem 0.65rem; - } - } - } -} -// Base -.vue-custom-tooltip { - @include tooltip("is-top"); - @include tooltip("is-right"); - @include tooltip("is-bottom"); - @include tooltip("is-left"); - position: relative; - display: inline-block; - text-decoration-line: none !important; - - &.is-underlined { - border-bottom: 1px dotted #000; // default for IE - border-bottom: 1px dotted $tooltip-background; - line-height: 1.2; - } - - &:before, - &:after { - position: absolute; - content: ""; - opacity: 0; - visibility: hidden; - pointer-events: none; - transition: opacity $speed $easing, visibility $speed $easing; - } - - &:before { - z-index: 889; - } - - &:after { - content: attr(data-label); - color: #fff; // default for IE - color: $tooltip-color; - background: #000; // default for IE - background: $tooltip-background; - width: auto; - max-width: 100vw; - padding: 0.45rem 0.75rem 0.45rem; - border-radius: 100px; // default for IE - border-radius: $tooltip-radius; - font-size: 0.85rem !important; - font-weight: 400; // default for IE - font-weight: $weight-normal; - line-height: 1.3; - letter-spacing: normal !important; - text-transform: none; - box-shadow: 0px 1px 2px 1px rgba(0, 1, 0, 0.2); - z-index: 888; - white-space: nowrap; - } - - &:not([data-label=""]):hover:before, - &:not([data-label=""]):hover:after { - opacity: 1; - visibility: visible; - } - - // If parent is disabled - :disabled & { - pointer-events: none; - } - - &:not([data-label=""]).is-sticky { - &:before, - &:after { - opacity: 1; - visibility: visible; - } - } - - &.has-multiline { - &:after { - display: block; - padding: 0.5rem 0.75rem 0.65rem; - text-align: center; - line-height: 1.4; - white-space: pre-wrap; - } - } -}