Skip to content

Commit

Permalink
refactor!: move scroll functionality into @smooth-scrollbar/core
Browse files Browse the repository at this point in the history
- remove dynamic style #235
- remove core-js polyfills #407
- expose only ScrollbarOptions type
  • Loading branch information
sadeghbarati committed Apr 9, 2023
1 parent ecc2c7c commit e3e6d66
Show file tree
Hide file tree
Showing 52 changed files with 1,751 additions and 1,682 deletions.
24 changes: 24 additions & 0 deletions packages/core/build.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { defineBuildConfig } from 'unbuild'
import pkg from './package.json'

export default defineBuildConfig({
entries: [
{
input: 'src/index',
},
{
input: 'src/style',
builder: 'mkdist',
},
],
declaration: true,
clean: true,
replace: {
__SCROLLBAR_VERSION__: JSON.stringify(pkg.version),
// eslint-disable-next-line @typescript-eslint/quotes
__DEV__: `(process.env.NODE_ENV !== 'production')`,
},
rollup: {
emitCJS: true,
},
})
44 changes: 44 additions & 0 deletions packages/core/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"name": "@smooth-scrollbar/core",
"version": "9.0.0",
"description": "Customize scrollbar in modern browsers with smooth scrolling experience.",
"author": "Dolphin Wood <dolphin.w.e@gmail.com>",
"license": "MIT",
"homepage": "https://github.com/idiotWu/smooth-scrollbar#readme",
"repository": {
"type": "git",
"url": "git+https://github.com/idiotWu/smooth-scrollbar.git"
},
"bugs": {
"url": "https://github.com/idiotWu/smooth-scrollbar/issues"
},
"keywords": [
"scrollbar",
"customize",
"acceleration",
"performance"
],
"exports": {
".": {
"types": "./dist/index.d.ts",
"require": "./dist/index.cjs",
"import": "./dist/index.mjs"
},
"./style.css": "./dist/style.css",
"./package.json": "./package.json"
},
"main": "./dist/index.cjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"style": "./dist/style.css",
"scripts": {
"build": "unbuild",
"dev": "unbuild --stub"
},
"dependencies": {
"@smooth-scrollbar/shared": "^9.0.0"
},
"devDependencies": {
"tslib": "^2.5.0"
}
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
export function boolean(proto: any, key: string) {
const alias = `_${key}`;
const alias = `_${key}`

Object.defineProperty(proto, key, {
get() {
return this[alias];
return this[alias]
},
set(val?: boolean) {
set(value?: boolean) {
Object.defineProperty(this, alias, {
value: !!val,
value: !!value,
enumerable: false,
writable: true,
configurable: true,
});
})
},
enumerable: true,
configurable: true,
});
})
}
20 changes: 20 additions & 0 deletions packages/core/src/decorators/debounce.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { debounce as $debounce } from '@smooth-scrollbar/shared'

export function debounce(...options: any[]) {
return (_proto: any, key: string, descriptor: PropertyDescriptor) => {
const fn = descriptor.value

return {
get(): any {
if (!Object.prototype.hasOwnProperty.call(this, key)) {
Object.defineProperty(this, key, {
value: $debounce(fn, ...options),
})
}

// @ts-expect-error ignore types
return this[key]
},
}
}
}
3 changes: 3 additions & 0 deletions packages/core/src/decorators/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './range'
export * from './boolean'
export * from './debounce'
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import { clamp } from '../utils';
import { clamp } from '@smooth-scrollbar/shared'

export function range(min = -Infinity, max = Infinity) {
export function range(min = Number.NEGATIVE_INFINITY, max = Number.POSITIVE_INFINITY) {
return (proto: any, key: string) => {
const alias = `_${key}`;
const alias = `_${key}`

Object.defineProperty(proto, key, {
get() {
return this[alias];
return this[alias]
},
set(val: number) {
set(value: number) {
Object.defineProperty(this, alias, {
value: clamp(val, min, max),
value: clamp(value, min, max),
enumerable: false,
writable: true,
configurable: true,
});
})
},
enumerable: true,
configurable: true,
});
};
})
}
}
6 changes: 6 additions & 0 deletions packages/core/src/events/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export * from './keyboard'
export * from './mouse'
export * from './resize'
export * from './select'
export * from './touch'
export * from './wheel'
101 changes: 101 additions & 0 deletions packages/core/src/events/keyboard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import type { Scrollbar } from '@smooth-scrollbar/shared'
import { eventScope } from '@smooth-scrollbar/shared'

enum KEY {
TAB = 'Tab',
SPACE = ' ',
PAGE_UP = 'PageUp',
PAGE_DOWN = 'PageDown',
END = 'End',
HOME = 'Home',
LEFT = 'ArrowLeft',
UP = 'ArrowUp',
RIGHT = 'ArrowRight',
DOWN = 'ArrowDown',
}

export function keyboardHandler(scrollbar: Scrollbar) {
const addEvent = eventScope(scrollbar)
const container = scrollbar.containerEl

addEvent(container, 'keydown', (event: KeyboardEvent) => {
const { activeElement } = document

if (activeElement !== container && !container.contains(activeElement))
return

if (isEditable(activeElement))
return

const delta = getKeyDelta(scrollbar, event.code)

if (!delta)
return

const [x, y] = delta

scrollbar.addTransformableMomentum(x, y, event, (willScroll) => {
if (willScroll) {
event.preventDefault()
}
else {
scrollbar.containerEl.blur()

if (scrollbar.parent)
scrollbar.parent.containerEl.focus()
}
})
})
}

function getKeyDelta(scrollbar: Scrollbar, key: string) {
const {
size,
limit,
offset,
} = scrollbar

switch (key) {
case KEY.TAB:
return handleTabKey(scrollbar)
case KEY.SPACE:
return [0, 200]
case KEY.PAGE_UP:
return [0, -size.container.height + 40]
case KEY.PAGE_DOWN:
return [0, size.container.height - 40]
case KEY.END:
return [0, limit.y - offset.y]
case KEY.HOME:
return [0, -offset.y]
case KEY.LEFT:
return [-40, 0]
case KEY.UP:
return [0, -40]
case KEY.RIGHT:
return [40, 0]
case KEY.DOWN:
return [0, 40]
}
}

function handleTabKey(scrollbar: Scrollbar) {
// handle in next frame
requestAnimationFrame(() => {
scrollbar.scrollIntoView(document.activeElement as HTMLElement, {
offsetTop: scrollbar.size.container.height / 2,
offsetLeft: scrollbar.size.container.width / 2,
onlyScrollIfNeeded: true,
})
})
}

function isEditable(element: any): boolean {
if (element.tagName === 'INPUT'
|| element.tagName === 'SELECT'
|| element.tagName === 'TEXTAREA'
|| element.isContentEditable)
return !element.disabled

return false
}
Loading

0 comments on commit e3e6d66

Please sign in to comment.